diff --git a/src/execute/ast_eval.h b/src/execute/ast_eval.h index f93c9a72..3798b99f 100644 --- a/src/execute/ast_eval.h +++ b/src/execute/ast_eval.h @@ -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 * diff --git a/src/execute/hash_map/hash_map.c b/src/execute/hash_map/hash_map.c index 5e9d136c..9f20360a 100644 --- a/src/execute/hash_map/hash_map.c +++ b/src/execute/hash_map/hash_map.c @@ -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) @@ -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; @@ -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); } } @@ -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) { @@ -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) { diff --git a/src/execute/hash_map/hash_map.h b/src/execute/hash_map/hash_map.h index d02bb3c0..32c2ae32 100644 --- a/src/execute/hash_map/hash_map.h +++ b/src/execute/hash_map/hash_map.h @@ -18,7 +18,7 @@ */ struct pair_list { - const char *key; + char *key; char *value; struct pair_list *next; }; @@ -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); /** @@ -77,7 +77,7 @@ 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. @@ -85,6 +85,6 @@ char *hash_map_get(const struct hash_map *hash_map, const char *key); * \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 */ diff --git a/src/execute/utils/loop.c b/src/execute/utils/loop.c index b659c2f8..3e7694c1 100644 --- a/src/execute/utils/loop.c +++ b/src/execute/utils/loop.c @@ -8,6 +8,13 @@ #include "ast/ast.h" #include "ast_eval.h" +#include +#include "options/options.h" +#include +#include +#include +#include +#include int while_loop(struct ast_node *node) { @@ -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; +} diff --git a/src/parser/parser.c b/src/parser/parser.c index 09e2a9e7..ea70c3e8 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -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); diff --git a/src/parser/parser_condition.c b/src/parser/parser_condition.c index 211bc9ca..a68a6cd5 100644 --- a/src/parser/parser_condition.c +++ b/src/parser/parser_condition.c @@ -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; @@ -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) { @@ -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); @@ -252,7 +295,7 @@ struct ast_node *rule_for(struct lexer *lexer) } } } - free(value); + //free(value); } ERROR: ast_free(current); diff --git a/tests/loop/loop/loop1.test b/tests/loop/loop/loop1.test new file mode 100644 index 00000000..1c96a230 --- /dev/null +++ b/tests/loop/loop/loop1.test @@ -0,0 +1,3 @@ +for i in {1..5}; do + echo $i +done diff --git a/tests/loop/loop/loop2.test b/tests/loop/loop/loop2.test new file mode 100644 index 00000000..31f06088 --- /dev/null +++ b/tests/loop/loop/loop2.test @@ -0,0 +1,3 @@ +for file in ../loop/*; do + echo $file +done diff --git a/tests/loop/loop/loop3.test b/tests/loop/loop/loop3.test new file mode 100644 index 00000000..6553f19e --- /dev/null +++ b/tests/loop/loop/loop3.test @@ -0,0 +1 @@ +for i in Monday Tuesday Wednesday; do echo $i ;done \ No newline at end of file diff --git a/tests/loop/loop/loop4.test b/tests/loop/loop/loop4.test new file mode 100644 index 00000000..53bb7a47 --- /dev/null +++ b/tests/loop/loop/loop4.test @@ -0,0 +1,3 @@ +for arg in $@; do + echo $arg +done diff --git a/tests/loop/loop/loop5.test b/tests/loop/loop/loop5.test new file mode 100644 index 00000000..de669124 --- /dev/null +++ b/tests/loop/loop/loop5.test @@ -0,0 +1,3 @@ +for i in {1,5}; do + echo $i +done diff --git a/tests/loop/loop/loop6.test b/tests/loop/loop/loop6.test new file mode 100644 index 00000000..e0a7b59d --- /dev/null +++ b/tests/loop/loop/loop6.test @@ -0,0 +1,5 @@ +start=1 +end=5 +for i in {$start..$end}; do + echo $i +done \ No newline at end of file diff --git a/tests/loop/loop/testsuite.sh b/tests/loop/loop/testsuite.sh new file mode 100644 index 00000000..92085ef0 --- /dev/null +++ b/tests/loop/loop/testsuite.sh @@ -0,0 +1,5 @@ +run_test loop1.test +run_test loop2.test +run_test loop3.test +run_test loop4.test +run_test loop5.test \ No newline at end of file diff --git a/tests/loop/loop_error/error1.test b/tests/loop/loop_error/error1.test new file mode 100644 index 00000000..e05ba288 --- /dev/null +++ b/tests/loop/loop_error/error1.test @@ -0,0 +1,2 @@ +for i in {1..5} +echo $i diff --git a/tests/loop/loop_error/testsuite.sh b/tests/loop/loop_error/testsuite.sh new file mode 100644 index 00000000..69a2054d --- /dev/null +++ b/tests/loop/loop_error/testsuite.sh @@ -0,0 +1 @@ +run_test error1.test \ No newline at end of file