From 77a704a09aab2e8ddbb8d43304ce606b54ee8a14 Mon Sep 17 00:00:00 2001 From: marcnava-42cursus Date: Sat, 14 Feb 2026 15:12:25 +0100 Subject: [PATCH] norma arreglada --- include/variables.h | 28 +-- src/errors/errors.c | 2 +- src/parser/parser.c | 79 +++++--- src/parser/parser_clear.c | 46 +++++ src/parser/parser_words.c | 98 +++------- src/variables/environment/environment.c | 190 ++++++------------- src/variables/environment/environment_envp.c | 121 ++++++++++++ src/variables/internal/internal.c | 2 +- src/variables/variables.c | 4 +- 9 files changed, 315 insertions(+), 255 deletions(-) create mode 100644 src/parser/parser_clear.c create mode 100644 src/variables/environment/environment_envp.c diff --git a/include/variables.h b/include/variables.h index 8b4b944..b79ec6f 100644 --- a/include/variables.h +++ b/include/variables.h @@ -13,31 +13,31 @@ #ifndef VARIABLES_H # define VARIABLES_H -# include "minishell.h" +# include "minishell.h" # include "core.h" // variables.c -extern char *get_var(const char *name, t_minishell *minishell); -extern void set_var(const char *name, char *value, t_minishell *minishell); -extern void unset_var(const char *name, t_minishell *minishell); +extern char *get_var(const char *name, t_minishell *minishell); +extern void set_var(const char *name, char *value, t_minishell *minishell); +extern void unset_var(const char *name, t_minishell *minishell); // environment.c -extern char *get_env(const char *name, t_minishell *minishell); -extern void set_env(const char *name, char *value, t_minishell *minishell); -extern void unset_env(const char *name, t_minishell *minishell); +extern char *get_env(const char *name, t_minishell *minishell); +extern void set_env(const char *name, char *value, t_minishell *minishell); +extern void unset_env(const char *name, t_minishell *minishell); -extern void set_envp(char **envp, t_minishell *minishell); -extern char **get_envp(t_minishell *minishell); -extern void free_envp(char **envp); +extern void set_envp(char **envp, t_minishell *minishell); +extern char **get_envp(t_minishell *minishell); +extern void free_envp(char **envp); // internal.c -extern char *get_int(const char *name, t_minishell *minishell); -extern void set_int(const char *name, char *value, t_minishell *minishell); -extern void unset_int(const char *name, t_minishell *minishell); +extern char *get_int(const char *name, t_minishell *minishell); +extern void set_int(const char *name, char *value, t_minishell *minishell); +extern void unset_int(const char *name, t_minishell *minishell); -extern void set_intp(t_minishell *minishell); +extern void set_intp(t_minishell *minishell); #endif /* VARIABLES_H */ diff --git a/src/errors/errors.c b/src/errors/errors.c index c22a1af..45996d3 100644 --- a/src/errors/errors.c +++ b/src/errors/errors.c @@ -35,4 +35,4 @@ void command_not_found_error( ) { ft_eprintf("minishell: %s: command not found\n", command); -} \ No newline at end of file +} diff --git a/src/parser/parser.c b/src/parser/parser.c index b338e28..94c7622 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -14,6 +14,8 @@ #include "errors.h" static t_list *parse_tokens(t_list *tokens); +static bool parse_add_command(t_list **commands, t_list **current_token); +static bool parse_advance_token(t_list **commands, t_list **current_token); /** * @brief Converts a command line string into a list of commands. @@ -51,10 +53,8 @@ static t_list *parse_tokens( t_list *tokens ) { - t_list *commands; - t_command *command; - t_list *current_token; - t_list *new_command; + t_list *commands; + t_list *current_token; if (tokens == NULL) return (NULL); @@ -63,32 +63,49 @@ static t_list *parse_tokens( if (((t_token *)current_token->content)->type == TOKEN_PIPE) return (syntax_error_unexpected_token( (t_token *)current_token->content), NULL); - while (current_token != NULL) - { - command = command_new(¤t_token); - if (command == NULL) - { - ft_lstclear(&commands, (void (*)(void *))command_clear); - return (NULL); - } - new_command = ft_lstnew(command); - if (new_command == NULL) - { - command_clear(command); - ft_lstclear(&commands, (void (*)(void *))command_clear); - return (malloc_error(), NULL); - } - ft_lstadd_back(&commands, new_command); - if (current_token != NULL) - { - if (current_token->next == NULL) - { - ft_lstclear(&commands, (void (*)(void *))command_clear); - return (syntax_error_unexpected_token( - (t_token *)current_token->content), NULL); - } - current_token = current_token->next; - } - } + while (current_token != NULL && parse_add_command(&commands, ¤t_token) + && parse_advance_token(&commands, ¤t_token)) + continue ; + if (current_token != NULL) + return (NULL); return (commands); } + +static bool parse_add_command( + t_list **commands, + t_list **current_token +) +{ + t_command *command; + t_list *new_command; + + command = command_new(current_token); + if (command == NULL) + return (ft_lstclear(commands, (void (*)(void *))command_clear), false); + new_command = ft_lstnew(command); + if (new_command == NULL) + { + command_clear(command); + return (ft_lstclear(commands, (void (*)(void *))command_clear), + malloc_error(), false); + } + ft_lstadd_back(commands, new_command); + return (true); +} + +static bool parse_advance_token( + t_list **commands, + t_list **current_token +) +{ + if (*current_token == NULL) + return (true); + if ((*current_token)->next == NULL) + { + ft_lstclear(commands, (void (*)(void *))command_clear); + return (syntax_error_unexpected_token( + (t_token *)(*current_token)->content), false); + } + *current_token = (*current_token)->next; + return (true); +} diff --git a/src/parser/parser_clear.c b/src/parser/parser_clear.c new file mode 100644 index 0000000..928f03a --- /dev/null +++ b/src/parser/parser_clear.c @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser_clear.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: sede-san argv != NULL) + { + i = 0; + while (i < command->argc) + { + free(command->argv[i]); + i++; + } + free(command->argv); + command->argv = NULL; + } +} + +void command_clear( + t_command *command +) +{ + if (command != NULL) + { + command_clear_argv(command); + ft_lstclear(&command->redirections, + (void (*)(void *))redirection_clear); + ft_lstclear(&command->heredocs, (void (*)(void *))redirection_clear); + free(command); + } +} diff --git a/src/parser/parser_words.c b/src/parser/parser_words.c index 1e23b03..ad1229f 100644 --- a/src/parser/parser_words.c +++ b/src/parser/parser_words.c @@ -12,8 +12,6 @@ #include "parser.h" -void command_clear_argv(t_command *command); - static bool args_add_word( t_list **args, const char *value @@ -32,6 +30,31 @@ static bool args_add_word( return (true); } +static bool words_collect( + t_list *arg, + t_list **args, + int *new_argc, + t_list **end +) +{ + t_token *token; + int io_number; + + while (arg != NULL) + { + token = (t_token *)arg->content; + if (token->type != TOKEN_WORD || parser_token_is_fd_prefix(arg, + &io_number)) + break ; + if (!args_add_word(args, token->value)) + return (false); + (*new_argc)++; + arg = arg->next; + } + *end = arg; + return (true); +} + static bool command_append_words( t_command *command, t_list **args, @@ -78,79 +101,12 @@ void words_add( ) { t_list *args; - t_list *arg; - t_token *token; - t_token *next_token; int new_argc; - size_t i; - bool is_fd_prefix; args = NULL; new_argc = 0; - arg = *tokens; - token = (t_token *)arg->content; - while (arg != NULL && token->type == TOKEN_WORD) - { - is_fd_prefix = false; - if (arg->next != NULL && token->value != NULL - && token->value[0] != '\0') - { - next_token = (t_token *)arg->next->content; - i = 0; - while (token->value[i] != '\0' && ft_isdigit(token->value[i])) - i++; - is_fd_prefix = (token->value[i] == '\0' && is_redirection(next_token)); - } - if (is_fd_prefix) - break ; - if (!args_add_word(&args, token->value)) - return (ft_lstclear(&args, free), command_clear(*command), - *command = NULL, (void)0); - new_argc++; - arg = arg->next; - if (arg != NULL) - token = (t_token *)arg->content; - } - *tokens = arg; - if (!command_append_words(*command, &args, new_argc)) + if (!words_collect(*tokens, &args, &new_argc, tokens) + || !command_append_words(*command, &args, new_argc)) return (ft_lstclear(&args, free), command_clear(*command), *command = NULL, (void)0); } - -void command_clear_argv( - t_command *command -) -{ - int i; - - if (command->argv != NULL) - { - i = 0; - while (i < command->argc) - { - free(command->argv[i]); - i++; - } - free(command->argv); - command->argv = NULL; - } -} - -/** - * @brief Clears a command, freeing all associated memory. - * - * @param command The command to clear. - */ -void command_clear( - t_command *command -) -{ - if (command != NULL) - { - command_clear_argv(command); - ft_lstclear(&command->redirections, - (void (*)(void *))redirection_clear); - ft_lstclear(&command->heredocs, (void (*)(void *))redirection_clear); - free(command); - } -} diff --git a/src/variables/environment/environment.c b/src/variables/environment/environment.c index e030c6c..4d4de96 100644 --- a/src/variables/environment/environment.c +++ b/src/variables/environment/environment.c @@ -15,6 +15,17 @@ #include "variables.h" #include "errors.h" +static char *resolve_key( + const char *name, + t_hashmap *environment, + t_minishell *minishell, + bool *owns_key + ); +static char *resolve_value( + char *value, + t_minishell *minishell + ); + /** * @brief Retrieves the value of an environment variable from the shell's * environment hashmap. @@ -53,31 +64,22 @@ void set_env( t_minishell *minishell ) { - t_hashmap *environment; - char *key; - char *val; - char *old_value; - bool owns_key; + t_hashmap *environment; + char *key; + char *val; + char *old_value; + bool owns_key; environment = minishell->variables.environment; - owns_key = false; - key = (char *)name; - if (name != NULL && !ft_hashmap_contains_key(environment, name)) - { - key = ft_strdup(name); - if (key == NULL) - return (minishell->exit = true, malloc_error()); - owns_key = true; - } - if (value == NULL) - val = ft_strdup(""); - else - val = ft_strdup(value); + key = resolve_key(name, environment, minishell, &owns_key); + if (key == NULL) + return ; + val = resolve_value(value, minishell); if (val == NULL) { if (owns_key) free(key); - return (minishell->exit = true, malloc_error()); + return ; } old_value = ft_hashmap_put(environment, key, val); if (old_value != NULL) @@ -100,130 +102,48 @@ void unset_env( { t_hashmap *environment; char *val; - + environment = minishell->variables.environment; val = ft_hashmap_remove(environment, (void *)name); if (val != NULL) free(val); } -/** - * @brief Converts the environment variables hashmap to an envp array format. - * - * This function extracts all environment variables from the minishell's - * environment hashmap and converts them into a NULL-terminated array of - * strings in the format "KEY=VALUE". - * - * @param minishell Pointer to the minishell structure containing the environment - * variables hashmap. - * - * @return A dynamically allocated array of strings representing environment - * variables in "KEY=VALUE" format, terminated by NULL. Returns NULL - * if memory allocation fails. The caller is responsible for freeing - * the returned array and its individual string elements using - * the `free_envp()` function. - * - * @note The function allocates memory for both the array and individual - * strings using malloc and ft_strnjoin respectively. - * @note The returned array size is environment->size + 1 to accommodate - * the NULL terminator. - */ -char **get_envp( +static char *resolve_key( + const char *name, + t_hashmap *environment, + t_minishell *minishell, + bool *owns_key +) +{ + char *key; + + key = (char *)name; + *owns_key = false; + if (name == NULL) + return (NULL); + if (!ft_hashmap_contains_key(environment, name)) + { + key = ft_strdup(name); + if (key == NULL) + return (minishell->exit = true, malloc_error(), NULL); + *owns_key = true; + } + return (key); +} + +static char *resolve_value( + char *value, t_minishell *minishell ) { - char **envp; - t_list *env_list; - t_list *env; - t_map_entry *entry; - size_t i; + char *val; - env_list = ft_hashmap_entries(minishell->variables.environment); - envp = (char **)malloc( - (minishell->variables.environment->size + 1) * sizeof(char *) - ); - if (envp != NULL) - { - i = 0; - env = env_list; - while (env != NULL) - { - entry = env->content; - envp[i++] = ft_strnjoin(3, entry->key, "=", entry->value); - env = env->next; - } - envp[i] = NULL; - } - ft_lstclear_nodes(&env_list); - return (envp); -} - -/** - * @brief Parses and stores environment variables from envp array into a hashmap - * - * This function iterates through the environment variables array (envp) and - * splits each variable string on the '=' delimiter to separate the variable - * name from its value. Each name-value pair is then stored in the minishell's - * environment hashmap for later retrieval. - * - * @param envp Array of environment variable strings in "NAME=value" format - * @param minishell Pointer to the minishell structure containing the environment - * hashmap - * - * @note The function assumes envp strings are in the standard format - * "NAME=value" - */ -void set_envp( - char **envp, - t_minishell *minishell -) -{ - t_hashmap **environment; - char *equal; - char *key; - char *value; - char *new_shlvl; - int shlvl; - size_t key_len; - - if (minishell == NULL || envp == NULL) - return ; - environment = &minishell->variables.environment; - *environment = ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp); - if (*environment == NULL) - return ; - while (*envp != NULL) - { - equal = ft_strchr(*envp, '='); - if (equal == NULL) - { - envp++; - continue ; - } - key_len = (size_t)(equal - *envp); - key = ft_substr(*envp, 0, key_len); - value = ft_strdup(equal + 1); - if (key == NULL || value == NULL) - { - free(key); - free(value); - minishell->exit = true; - return (malloc_error()); - } - set_env(key, value, minishell); - free(key); - free(value); - envp++; - } - value = get_env("SHLVL", minishell); - shlvl = 0; - if (value != NULL) - shlvl = ft_atoi(value); - if (shlvl < 0) - shlvl = 0; - new_shlvl = ft_itoa(shlvl + 1); - if (new_shlvl == NULL) - return (minishell->exit = true, malloc_error()); - set_env("SHLVL", new_shlvl, minishell); - free(new_shlvl); + if (value == NULL) + val = ft_strdup(""); + else + val = ft_strdup(value); + if (val == NULL) + return (minishell->exit = true, malloc_error(), NULL); + return (val); } diff --git a/src/variables/environment/environment_envp.c b/src/variables/environment/environment_envp.c new file mode 100644 index 0000000..5c4a234 --- /dev/null +++ b/src/variables/environment/environment_envp.c @@ -0,0 +1,121 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* environment_envp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: sede-san content; + envp[i++] = ft_strnjoin(3, entry->key, "=", entry->value); + env = env->next; + } + envp[i] = NULL; +} + +char **get_envp( + t_minishell *minishell +) +{ + char **envp; + t_list *env_list; + + env_list = ft_hashmap_entries(minishell->variables.environment); + envp = (char **)malloc( + (minishell->variables.environment->size + 1) * sizeof(char *) + ); + if (envp != NULL) + fill_envp(envp, env_list); + ft_lstclear_nodes(&env_list); + return (envp); +} + +static bool import_env_entry( + char *entry_text, + t_minishell *minishell +) +{ + char *equal; + char *key; + char *value; + size_t key_len; + + equal = ft_strchr(entry_text, '='); + if (equal == NULL) + return (true); + key_len = (size_t)(equal - entry_text); + key = ft_substr(entry_text, 0, key_len); + value = ft_strdup(equal + 1); + if (key == NULL || value == NULL) + return (free(key), free(value), minishell->exit = true, + malloc_error(), false); + set_env(key, value, minishell); + free(key); + free(value); + return (!minishell->exit); +} + +static void update_shlvl( + t_minishell *minishell +) +{ + char *value; + char *new_shlvl; + int shlvl; + + value = get_env("SHLVL", minishell); + shlvl = 0; + if (value != NULL) + shlvl = ft_atoi(value); + if (shlvl < 0) + shlvl = 0; + new_shlvl = ft_itoa(shlvl + 1); + if (new_shlvl == NULL) + return ((void)(minishell->exit = true), malloc_error()); + set_env("SHLVL", new_shlvl, minishell); + free(new_shlvl); +} + +void set_envp( + char **envp, + t_minishell *minishell +) +{ + t_hashmap *environment; + + if (minishell == NULL || envp == NULL) + return ; + environment = ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp); + if (environment == NULL) + return ; + minishell->variables.environment = environment; + while (*envp != NULL) + { + if (!import_env_entry(*envp, minishell)) + return ; + envp++; + } + update_shlvl(minishell); +} diff --git a/src/variables/internal/internal.c b/src/variables/internal/internal.c index 006a9d7..5b252fe 100644 --- a/src/variables/internal/internal.c +++ b/src/variables/internal/internal.c @@ -89,7 +89,7 @@ void unset_int( ) { char *value; - + value = ft_hashmap_remove(minishell->variables.internal, (void *)name); if (value != NULL) free(value); diff --git a/src/variables/variables.c b/src/variables/variables.c index 60f8e72..a8ef504 100644 --- a/src/variables/variables.c +++ b/src/variables/variables.c @@ -26,7 +26,7 @@ char *get_var( ) { char *value; - + value = get_int(name, minishell); if (value == NULL) value = get_env(name, minishell); @@ -37,7 +37,7 @@ void set_var(const char *name, char *value, t_minishell *minishell) { if (ft_hashmap_contains_key(minishell->variables.internal, name)) set_int(name, value, minishell); - set_env(name, value, minishell); + set_env(name, value, minishell); } void unset_var(