norma arreglada

This commit is contained in:
marcnava-42cursus
2026-02-14 15:12:25 +01:00
parent 39e5719183
commit 77a704a09a
9 changed files with 315 additions and 255 deletions

View File

@@ -14,6 +14,8 @@
#include "errors.h" #include "errors.h"
static t_list *parse_tokens(t_list *tokens); 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. * @brief Converts a command line string into a list of commands.
@@ -52,9 +54,7 @@ static t_list *parse_tokens(
) )
{ {
t_list *commands; t_list *commands;
t_command *command;
t_list *current_token; t_list *current_token;
t_list *new_command;
if (tokens == NULL) if (tokens == NULL)
return (NULL); return (NULL);
@@ -63,32 +63,49 @@ static t_list *parse_tokens(
if (((t_token *)current_token->content)->type == TOKEN_PIPE) if (((t_token *)current_token->content)->type == TOKEN_PIPE)
return (syntax_error_unexpected_token( return (syntax_error_unexpected_token(
(t_token *)current_token->content), NULL); (t_token *)current_token->content), NULL);
while (current_token != NULL) while (current_token != NULL && parse_add_command(&commands, &current_token)
{ && parse_advance_token(&commands, &current_token))
command = command_new(&current_token); continue ;
if (command == NULL) if (current_token != NULL)
{
ft_lstclear(&commands, (void (*)(void *))command_clear);
return (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); new_command = ft_lstnew(command);
if (new_command == NULL) if (new_command == NULL)
{ {
command_clear(command); command_clear(command);
ft_lstclear(&commands, (void (*)(void *))command_clear); return (ft_lstclear(commands, (void (*)(void *))command_clear),
return (malloc_error(), NULL); malloc_error(), false);
} }
ft_lstadd_back(&commands, new_command); ft_lstadd_back(commands, new_command);
if (current_token != NULL) return (true);
}
static bool parse_advance_token(
t_list **commands,
t_list **current_token
)
{ {
if (current_token->next == NULL) if (*current_token == NULL)
return (true);
if ((*current_token)->next == NULL)
{ {
ft_lstclear(&commands, (void (*)(void *))command_clear); ft_lstclear(commands, (void (*)(void *))command_clear);
return (syntax_error_unexpected_token( return (syntax_error_unexpected_token(
(t_token *)current_token->content), NULL); (t_token *)(*current_token)->content), false);
} }
current_token = current_token->next; *current_token = (*current_token)->next;
} return (true);
}
return (commands);
} }

46
src/parser/parser_clear.c Normal file
View File

@@ -0,0 +1,46 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_clear.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 16:10:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 16:10:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser.h"
static 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;
}
}
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);
}
}

View File

@@ -12,8 +12,6 @@
#include "parser.h" #include "parser.h"
void command_clear_argv(t_command *command);
static bool args_add_word( static bool args_add_word(
t_list **args, t_list **args,
const char *value const char *value
@@ -32,6 +30,31 @@ static bool args_add_word(
return (true); 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( static bool command_append_words(
t_command *command, t_command *command,
t_list **args, t_list **args,
@@ -78,79 +101,12 @@ void words_add(
) )
{ {
t_list *args; t_list *args;
t_list *arg;
t_token *token;
t_token *next_token;
int new_argc; int new_argc;
size_t i;
bool is_fd_prefix;
args = NULL; args = NULL;
new_argc = 0; new_argc = 0;
arg = *tokens; if (!words_collect(*tokens, &args, &new_argc, tokens)
token = (t_token *)arg->content; || !command_append_words(*command, &args, new_argc))
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))
return (ft_lstclear(&args, free), command_clear(*command), return (ft_lstclear(&args, free), command_clear(*command),
*command = NULL, (void)0); *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);
}
}

View File

@@ -15,6 +15,17 @@
#include "variables.h" #include "variables.h"
#include "errors.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 * @brief Retrieves the value of an environment variable from the shell's
* environment hashmap. * environment hashmap.
@@ -60,24 +71,15 @@ void set_env(
bool owns_key; bool owns_key;
environment = minishell->variables.environment; environment = minishell->variables.environment;
owns_key = false; key = resolve_key(name, environment, minishell, &owns_key);
key = (char *)name;
if (name != NULL && !ft_hashmap_contains_key(environment, name))
{
key = ft_strdup(name);
if (key == NULL) if (key == NULL)
return (minishell->exit = true, malloc_error()); return ;
owns_key = true; val = resolve_value(value, minishell);
}
if (value == NULL)
val = ft_strdup("");
else
val = ft_strdup(value);
if (val == NULL) if (val == NULL)
{ {
if (owns_key) if (owns_key)
free(key); free(key);
return (minishell->exit = true, malloc_error()); return ;
} }
old_value = ft_hashmap_put(environment, key, val); old_value = ft_hashmap_put(environment, key, val);
if (old_value != NULL) if (old_value != NULL)
@@ -107,123 +109,41 @@ void unset_env(
free(val); free(val);
} }
/** static char *resolve_key(
* @brief Converts the environment variables hashmap to an envp array format. const char *name,
* t_hashmap *environment,
* This function extracts all environment variables from the minishell's t_minishell *minishell,
* environment hashmap and converts them into a NULL-terminated array of bool *owns_key
* 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(
t_minishell *minishell
) )
{ {
char **envp;
t_list *env_list;
t_list *env;
t_map_entry *entry;
size_t i;
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 *key;
char *value;
char *new_shlvl;
int shlvl;
size_t key_len;
if (minishell == NULL || envp == NULL) key = (char *)name;
return ; *owns_key = false;
environment = &minishell->variables.environment; if (name == NULL)
*environment = ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp); return (NULL);
if (*environment == NULL) if (!ft_hashmap_contains_key(environment, name))
return ;
while (*envp != NULL)
{ {
equal = ft_strchr(*envp, '='); key = ft_strdup(name);
if (equal == NULL) if (key == NULL)
return (minishell->exit = true, malloc_error(), NULL);
*owns_key = true;
}
return (key);
}
static char *resolve_value(
char *value,
t_minishell *minishell
)
{ {
envp++; char *val;
continue ;
} if (value == NULL)
key_len = (size_t)(equal - *envp); val = ft_strdup("");
key = ft_substr(*envp, 0, key_len); else
value = ft_strdup(equal + 1); val = ft_strdup(value);
if (key == NULL || value == NULL) if (val == NULL)
{ return (minishell->exit = true, malloc_error(), NULL);
free(key); return (val);
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);
} }

View File

@@ -0,0 +1,121 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* environment_envp.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 16:10:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 16:10:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#include "core.h"
#include "variables.h"
#include "errors.h"
static void fill_envp(
char **envp,
t_list *env_list
)
{
t_list *env;
t_map_entry *entry;
size_t i;
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;
}
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);
}