Fixed variable expansion errors

This commit is contained in:
marcnava-42cursus
2026-02-14 13:33:44 +01:00
parent dd6101edec
commit ba40670ace
11 changed files with 27965 additions and 7 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
Tests eliminados del reporte por ser extras (\ y/o ~):
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:52 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:54 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:56 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:58 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:60 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:62 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:64 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:7 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:59 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:61 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:63 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:65 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:67 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:69 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:71 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:314 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:328 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:337 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:606 | motivo: \, ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_redirs.sh:208 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_path_check.sh:30 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/8_syntax_errors.sh:19 | motivo: ~
Total casos eliminados (extras): 22

View File

@@ -0,0 +1,59 @@
Tests eliminados del reporte por estar fuera del obligatorio:
- \ (barra invertida no especificada)
- ~ (tilde expansion no obligatoria)
- $"..." (extension bash, no requerida)
- ; (separador no obligatorio segun subject)
- && / || (bonus)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:26 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:28 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:32 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:34 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:52 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:54 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:56 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:58 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:60 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:62 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:64 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/10_parsing_hell.sh:301 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:7 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:31 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:33 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:37 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:39 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:59 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:61 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:63 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:65 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:67 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:69 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:71 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:314 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:328 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:337 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:536 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:538 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:552 | motivo: ; (no obligatorio)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:606 | motivo: \, ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_redirs.sh:208 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:40 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:42 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:44 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:48 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:60 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:62 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:129 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:139 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:141 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:143 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:147 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:159 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:161 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_path_check.sh:30 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/8_syntax_errors.sh:19 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/8_syntax_errors.sh:68 | motivo: &&/|| (bonus)
Total casos evaluados en reporte original: 195
Total casos eliminados (extras): 48
Total casos restantes (mandatory): 147

View File

@@ -12,25 +12,81 @@
#include "parser_expand_internal.h"
static void command_clear_argv_expand(
t_command *command
)
{
int i;
i = 0;
while (i < command->argc)
{
free(command->argv[i]);
i++;
}
free(command->argv);
}
static bool command_set_expanded_argv(
t_command *command,
t_list *expanded_args,
t_minishell *minishell
)
{
char **argv;
t_list *current;
int argc;
int i;
argc = ft_lstsize(expanded_args);
argv = (char **)malloc(sizeof(char *) * (argc + 1));
if (argv == NULL)
return (ft_lstclear(&expanded_args, free),
parser_expand_malloc_error(minishell), false);
i = 0;
current = expanded_args;
while (current != NULL)
{
argv[i++] = (char *)current->content;
current = current->next;
}
argv[i] = NULL;
ft_lstclear_nodes(&expanded_args);
command_clear_argv_expand(command);
command->argc = argc;
command->argv = argv;
return (true);
}
static bool expand_argv(
t_command *command,
t_minishell *minishell
)
{
int i;
char *expanded;
t_list *expanded_args;
t_list *fields;
t_list *last;
i = 0;
expanded_args = NULL;
while (i < command->argc)
{
expanded = parser_expand_word(command->argv[i], minishell, true);
if (expanded == NULL)
return (false);
free(command->argv[i]);
command->argv[i] = expanded;
fields = NULL;
if (!parser_expand_word_fields(command->argv[i], minishell,
true, &fields))
return (ft_lstclear(&expanded_args, free), false);
if (expanded_args == NULL)
expanded_args = fields;
else
{
last = ft_lstlast(expanded_args);
if (last != NULL)
last->next = fields;
}
i++;
}
return (true);
return (command_set_expanded_argv(command, expanded_args, minishell));
}
static bool expand_redirections(

View File

@@ -0,0 +1,90 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_fields.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 13:15:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 13:15:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
static t_fields_ctx init_fields_ctx(
t_list **fields,
char **current,
t_field_state *state
)
{
t_fields_ctx ctx;
ctx.fields = fields;
ctx.current = current;
ctx.touched = &state->touched;
ctx.in_single_quote = &state->in_single_quote;
ctx.in_double_quote = &state->in_double_quote;
return (ctx);
}
static bool finish_word_fields(
t_fields_ctx ctx
)
{
if (*ctx.in_single_quote || *ctx.in_double_quote)
{
ft_lstclear(ctx.fields, free);
free(*ctx.current);
syntax_error_unexpected_token(NULL);
ctx.minishell->exit_status = 2;
return (false);
}
if ((*ctx.touched || (*ctx.current)[0] != '\0')
&& !parser_fields_push_field(ctx))
return (false);
free(*ctx.current);
return (true);
}
static bool process_word_fields(
const char *word,
t_fields_ctx ctx
)
{
size_t i;
i = 0;
while (word[i] != '\0')
{
if (!parser_fields_step(word, &i, ctx))
return (false);
}
return (true);
}
bool parser_expand_word_fields(
const char *word,
t_minishell *minishell,
bool expand_vars,
t_list **fields
)
{
char *current;
t_field_state state;
t_fields_ctx ctx;
*fields = NULL;
current = ft_strdup("");
if (current == NULL)
return (parser_expand_malloc_error(minishell), false);
state.touched = false;
state.in_single_quote = false;
state.in_double_quote = false;
ctx = init_fields_ctx(fields, &current, &state);
ctx.minishell = minishell;
ctx.expand_vars = expand_vars;
if (!process_word_fields(word, ctx))
return (ft_lstclear(fields, free), free(current), false);
return (finish_word_fields(ctx));
}

View File

@@ -0,0 +1,105 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_fields_step.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 14:12:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 14:12:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
static bool handle_quote_char(
const char *word,
size_t *i,
t_fields_ctx ctx
)
{
if (word[*i] == '\'' && !*ctx.in_double_quote)
{
*ctx.in_single_quote = !*ctx.in_single_quote;
*ctx.touched = true;
(*i)++;
return (true);
}
if (word[*i] == '\"' && !*ctx.in_single_quote)
{
*ctx.in_double_quote = !*ctx.in_double_quote;
*ctx.touched = true;
(*i)++;
return (true);
}
return (false);
}
static bool skip_dollar_quote_prefix(
const char *word,
size_t *i,
t_fields_ctx ctx
)
{
if (word[*i] == '$' && !*ctx.in_single_quote && !*ctx.in_double_quote
&& word[*i + 1] != '\0'
&& (word[*i + 1] == '\'' || word[*i + 1] == '\"'))
{
(*i)++;
return (true);
}
return (false);
}
static bool expand_dollar_token(
const char *word,
size_t *i,
t_fields_ctx ctx,
bool *handled
)
{
char *expanded;
*handled = false;
if (word[*i] != '$' || *ctx.in_single_quote || !ctx.expand_vars)
return (true);
*handled = true;
expanded = parser_expand_variable(word, i, ctx.minishell);
if (expanded == NULL)
return (false);
if (!*ctx.in_double_quote
&& !parser_fields_expand_unquoted_value(ctx, expanded))
return (free(expanded), false);
if (*ctx.in_double_quote && !parser_fields_append_text(ctx.current,
expanded, ctx.minishell))
return (free(expanded), false);
if (*ctx.in_double_quote && expanded[0] != '\0')
*ctx.touched = true;
free(expanded);
return (true);
}
bool parser_fields_step(
const char *word,
size_t *i,
t_fields_ctx ctx
)
{
char value[2];
bool handled;
if (handle_quote_char(word, i, ctx))
return (true);
if (skip_dollar_quote_prefix(word, i, ctx))
return (true);
if (!expand_dollar_token(word, i, ctx, &handled))
return (false);
if (handled)
return (true);
value[0] = word[(*i)++];
value[1] = '\0';
if (!parser_fields_append_text(ctx.current, value, ctx.minishell))
return (false);
*ctx.touched = true;
return (true);
}

View File

@@ -0,0 +1,100 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_fields_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 14:12:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 14:12:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
bool parser_fields_append_text(
char **current,
const char *value,
t_minishell *minishell
)
{
char *joined;
joined = ft_strnjoin(2, *current, (char *)value);
if (joined == NULL)
{
free(*current);
*current = NULL;
return (parser_expand_malloc_error(minishell), false);
}
free(*current);
*current = joined;
return (true);
}
static bool is_ifs_char(
char c
)
{
return (c == ' ' || c == '\t' || c == '\n');
}
bool parser_fields_push_field(
t_fields_ctx ctx
)
{
t_list *node;
node = ft_lstnew(*ctx.current);
if (node == NULL)
{
free(*ctx.current);
*ctx.current = NULL;
return (parser_expand_malloc_error(ctx.minishell), false);
}
ft_lstadd_back(ctx.fields, node);
*ctx.current = ft_strdup("");
if (*ctx.current == NULL)
return (ft_lstclear(ctx.fields, free),
parser_expand_malloc_error(ctx.minishell), false);
*ctx.touched = false;
return (true);
}
static void skip_ifs(
const char *expanded,
size_t *i
)
{
while (expanded[*i] != '\0' && is_ifs_char(expanded[*i]))
(*i)++;
}
bool parser_fields_expand_unquoted_value(
t_fields_ctx ctx,
const char *expanded
)
{
size_t i;
char value[2];
i = 0;
while (expanded[i] != '\0')
{
if (is_ifs_char(expanded[i]))
{
if ((*ctx.touched || (*ctx.current)[0] != '\0')
&& !parser_fields_push_field(ctx))
return (false);
skip_ifs(expanded, &i);
continue ;
}
value[0] = expanded[i];
value[1] = '\0';
if (!parser_fields_append_text(ctx.current, value, ctx.minishell))
return (false);
*ctx.touched = true;
i++;
}
return (true);
}

View File

@@ -17,11 +17,21 @@
# include "errors.h"
# include "variables.h"
typedef struct s_fields_ctx t_fields_ctx;
void parser_expand_malloc_error(t_minishell *minishell);
char *parser_expand_variable(const char *word, size_t *i,
t_minishell *minishell);
char *parser_expand_word(const char *word, t_minishell *minishell,
bool expand_vars);
bool parser_expand_word_fields(const char *word, t_minishell *minishell,
bool expand_vars, t_list **fields);
bool parser_fields_append_text(char **current, const char *value,
t_minishell *minishell);
bool parser_fields_push_field(t_fields_ctx ctx);
bool parser_fields_expand_unquoted_value(t_fields_ctx ctx,
const char *expanded);
bool parser_fields_step(const char *word, size_t *i, t_fields_ctx ctx);
typedef struct s_word_ctx
{
@@ -32,4 +42,22 @@ typedef struct s_word_ctx
bool expand_vars;
} t_word_ctx;
typedef struct s_fields_ctx
{
t_list **fields;
char **current;
bool *touched;
bool *in_single_quote;
bool *in_double_quote;
t_minishell *minishell;
bool expand_vars;
} t_fields_ctx;
typedef struct s_field_state
{
bool touched;
bool in_single_quote;
bool in_double_quote;
} t_field_state;
#endif

View File

@@ -56,6 +56,10 @@ static bool word_step(
if (word_toggle_quotes(word[*i], ctx.in_single_quote, ctx.in_double_quote))
return ((*i)++, true);
if (word[*i] == '$' && word[*i + 1] != '\0'
&& !*ctx.in_single_quote && !*ctx.in_double_quote
&& (word[*i + 1] == '\'' || word[*i + 1] == '\"'))
return ((*i)++, true);
if (word[*i] == '$' && !*ctx.in_single_quote && ctx.expand_vars)
{
expanded = parser_expand_variable(word, i, ctx.minishell);