Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat<execute>: begin adding loop #75

Merged
merged 2 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/execute/ast_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ char *handle_word(struct ast_node *node);

int redir_manager(struct ast_node *ast, int *save_fd, int *fd_dup);

/**
* \brief Set variable
* \param key The key of the variable.
* \param value The value of the variable.
*/

void set_variable(char *key, char *value);

/**
* \brief Use for Free Hash Map Variables at the end of the program
*
Expand Down
11 changes: 8 additions & 3 deletions src/execute/hash_map/hash_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct hash_map *hash_map_init(size_t size)
return new;
}

bool hash_map_insert(struct hash_map *hash_map, const char *key, char *value,
bool hash_map_insert(struct hash_map *hash_map, char *key, char *value,
bool *updated)
{
if (hash_map == NULL || hash_map->size == 0)
Expand All @@ -45,6 +45,8 @@ bool hash_map_insert(struct hash_map *hash_map, const char *key, char *value,
struct pair_list *ind = hash_map->data[index];
if (strcmp(ind->key, key) == 0)
{
free(key);
free(ind->value);
ind->value = value;
*updated = true;
return true;
Expand Down Expand Up @@ -84,6 +86,9 @@ void hash_map_free(struct hash_map *hash_map)
{
struct pair_list *to_free = index;
index = index->next;
free(to_free->key);
//printf("free %s\n", to_free->value);
free(to_free->value);
free(to_free);
}
}
Expand All @@ -110,7 +115,7 @@ void hash_map_dump(struct hash_map *hash_map)
}
}

char *hash_map_get(const struct hash_map *hash_map, const char *key)
char *hash_map_get(const struct hash_map *hash_map, char *key)
{
if (hash_map == NULL || hash_map->size == 0)
{
Expand All @@ -129,7 +134,7 @@ char *hash_map_get(const struct hash_map *hash_map, const char *key)
return NULL;
}

bool hash_map_remove(struct hash_map *hash_map, const char *key)
bool hash_map_remove(struct hash_map *hash_map, char *key)
{
if (hash_map == NULL || hash_map->size == 0)
{
Expand Down
8 changes: 4 additions & 4 deletions src/execute/hash_map/hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
struct pair_list
{
const char *key;
char *key;
char *value;
struct pair_list *next;
};
Expand Down Expand Up @@ -56,7 +56,7 @@ struct hash_map *hash_map_init(size_t size);
* was updated.
* \return True if the pair was inserted, false otherwise.
*/
bool hash_map_insert(struct hash_map *hash_map, const char *key, char *value,
bool hash_map_insert(struct hash_map *hash_map, char *key, char *value,
bool *updated);

/**
Expand All @@ -77,14 +77,14 @@ void hash_map_dump(struct hash_map *hash_map);
* \param key The key of the pair.
* \return The value of the pair.
*/
char *hash_map_get(const struct hash_map *hash_map, const char *key);
char *hash_map_get(const struct hash_map *hash_map, char *key);

/**
* \brief Remove a pair from a hash map.
* \param hash_map The hash map.
* \param key The key of the pair.
* \return True if the pair was removed, false otherwise.
*/
bool hash_map_remove(struct hash_map *hash_map, const char *key);
bool hash_map_remove(struct hash_map *hash_map, char *key);

#endif /* ! HASH_MAP_H */
145 changes: 142 additions & 3 deletions src/execute/utils/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@

#include "ast/ast.h"
#include "ast_eval.h"
#include <string.h>
#include "options/options.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

int while_loop(struct ast_node *node)
{
Expand All @@ -29,11 +36,143 @@ int until_loop(struct ast_node *node)
return status;
}

int for_loop(struct ast_node *node)
int build_num(char *str, int *start)
{
if (node == NULL)
int build_num = 0;
while ((size_t)*start < strlen(str) && str[*start] - '0' >= 0 && str[*start] - '0' < 10)
{
return -1;
build_num = build_num * 10 + (str[*start] - '0');
(*start)++; // Utilisez l'opérateur ++ sur le pointeur lui-même
}
return build_num;
}

int isValidPattern(const char *input) {
if (input[0] == '{' && input[strlen(input) - 1] == '}') {
char *cleanedString = malloc(sizeof(char) * strlen(input));
strncpy(cleanedString, input + 1, strlen(input) - 2);
cleanedString[strlen(input) - 2] = '\0';
char *startStr = strtok(cleanedString, "..");
char *endStr = strtok(NULL, "..");

if (startStr != NULL && endStr != NULL
&& is_number(startStr) && is_number(endStr))
{
free(cleanedString);
return 1;
}
free(cleanedString);
}
return 0;
}

int case_number(struct ast_node *node, int index)
{
int status = 0;
char *var = node->children[0]->value;
int length = 0;
int *numbers = malloc(sizeof(int) * length);
int start = 1;
int first = build_num(node->children[index]->value, &start);
start+=2;
int c = 0;
int last = build_num(node->children[index]->value, &start);
//printf("last : %d\n", last);
for (int j = first; j <= last; j++)
{
numbers = realloc(numbers, sizeof(int) * (++length));
numbers[c] = j;
c++;
}
for (int i = 0; i < length; i++)
{
char *str = malloc(sizeof(char) * 10);
sprintf(str, "%d", numbers[i]);
set_variable(var, str);
status = match_ast(node->children[node->children_count - 1]);
free(str);
}
free(numbers);
return status;
}

int isDirectory(const char *path) {
if (path[strlen(path) - 1] != '*') {
// Le chemin pointe vers un répertoire
return 0;
}
char *cleanedString = malloc(sizeof(char) * strlen(path));
strncpy(cleanedString, path, strlen(path) - 1);
cleanedString[strlen(path) - 1] = '\0';
struct stat pathStat;
if (stat(cleanedString, &pathStat) != 0)
{
return 0;
}
return S_ISDIR(pathStat.st_mode); // Vérifiez si le chemin pointe vers un répertoire
}

int case_directory(struct ast_node *node, int i)
{
int status = 0;
char *var = node->children[i]->value;
var[strlen(var) - 1] = '\0';
DIR *dir;
struct dirent *entry;
struct stat fileStat;

dir = opendir(var);

if (dir == NULL)
{
perror("Erreur lors de l'ouverture du dossier");
return 0;
}
while ((entry = readdir(dir)) != NULL)
{
char filePath[1024];
snprintf(filePath, sizeof(filePath), "%s/%s", var, entry->d_name);

if (stat(filePath, &fileStat) == 0)
{
if (S_ISREG(fileStat.st_mode))
{
printf("%s\n", entry->d_name);
}
}
}

closedir(dir);
return status;
}

int for_loop(struct ast_node *node)
{
int status = 0;
char *var = node->children[0]->value;
if (node->children_count == 2)
{
//HANDLE CASE OF $@
return 0;
}
else
{
for (int i = 1; i < node->children_count - 1; i++)
{
if (isValidPattern(node->children[i]->value))
{
status = case_number(node, i);
}
else if (isDirectory(node->children[i]->value))
{
status = case_directory(node, i);
}
else
{
set_variable(var, node->children[i]->value);
status = match_ast(node->children[node->children_count - 1]);
}
}
}
return status;
}
2 changes: 1 addition & 1 deletion src/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ int parser_loop(struct lexer *lexer, bool pretty_print_enabled)
{
return 2;
}

// print_ast(ast, 0);
if (pretty_print_enabled)
{
print_ast(ast, 0);
Expand Down
45 changes: 44 additions & 1 deletion src/parser/parser_condition.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ struct ast_node *rule_until(struct lexer *lexer)
struct ast_node *rule_for(struct lexer *lexer)
{
struct ast_node *current = ast_node_new(AST_FOR);

if (parser_peek(lexer) == TOKEN_WORD)
{
char *value = lexer_peek(lexer).data;
Expand All @@ -223,17 +224,58 @@ struct ast_node *rule_for(struct lexer *lexer)
free(value);
parser_pop(lexer);
if (parser_peek(lexer) != TOKEN_WORD)
{
goto ERROR;
}
value = lexer_peek(lexer).data;
struct ast_node *var = ast_node_new(AST_WORD);
var->value = value;
ast_append(current, var);
parser_pop(lexer);
if (parser_peek(lexer) == TOKEN_SEMICOLON)
{
goto END;
}

while (parser_peek(lexer) == TOKEN_EOL)
{
parser_pop(lexer);
}

value = lexer_peek(lexer).data;
if (strcmp(value, "in") == 0)
{
free(value);
parser_pop(lexer);
value = lexer_peek(lexer).data;
while ((parser_peek(lexer) == TOKEN_WORD
|| parser_peek(lexer) == TOKEN_VARIABLE)
&& strcmp(value, "do") != 0)
{
struct ast_node *condition = ast_node_new(AST_WORD);
condition->value = value;
ast_append(current, condition);
parser_pop(lexer);
value = lexer_peek(lexer).data;
}
free(value);
if (parser_peek(lexer) != TOKEN_SEMICOLON && parser_peek(lexer) != TOKEN_EOL)
{
goto ERROR;
}
parser_pop(lexer);
}
else
{
goto ERROR;
}

END:
while (parser_peek(lexer) == TOKEN_EOL)
{
parser_pop(lexer);
}

value = lexer_peek(lexer).data;
if (strcmp(value, "do") == 0)
{
Expand All @@ -244,6 +286,7 @@ struct ast_node *rule_for(struct lexer *lexer)
goto ERROR;
ast_append(current, response);
value = lexer_peek(lexer).data;

if (strcmp(value, "done") == 0)
{
free(value);
Expand All @@ -252,7 +295,7 @@ struct ast_node *rule_for(struct lexer *lexer)
}
}
}
free(value);
//free(value);
}
ERROR:
ast_free(current);
Expand Down
3 changes: 3 additions & 0 deletions tests/loop/loop/loop1.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
for i in {1..5}; do
echo $i
done
3 changes: 3 additions & 0 deletions tests/loop/loop/loop2.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
for file in ../loop/*; do
echo $file
done
1 change: 1 addition & 0 deletions tests/loop/loop/loop3.test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
for i in Monday Tuesday Wednesday; do echo $i ;done
3 changes: 3 additions & 0 deletions tests/loop/loop/loop4.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
for arg in $@; do
echo $arg
done
3 changes: 3 additions & 0 deletions tests/loop/loop/loop5.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
for i in {1,5}; do
echo $i
done
5 changes: 5 additions & 0 deletions tests/loop/loop/loop6.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
start=1
end=5
for i in {$start..$end}; do
echo $i
done
5 changes: 5 additions & 0 deletions tests/loop/loop/testsuite.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
run_test loop1.test
run_test loop2.test
run_test loop3.test
run_test loop4.test
run_test loop5.test
2 changes: 2 additions & 0 deletions tests/loop/loop_error/error1.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
for i in {1..5}
echo $i
1 change: 1 addition & 0 deletions tests/loop/loop_error/testsuite.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
run_test error1.test
Loading