Fixed variable expansion errors
This commit is contained in:
9656
docs/mstest_m_failed_tests_report.txt
Normal file
9656
docs/mstest_m_failed_tests_report.txt
Normal file
File diff suppressed because it is too large
Load Diff
9178
docs/mstest_m_failed_tests_report_filtered.txt
Normal file
9178
docs/mstest_m_failed_tests_report_filtered.txt
Normal file
File diff suppressed because it is too large
Load Diff
8656
docs/mstest_m_failed_tests_report_mandatory_only.txt
Normal file
8656
docs/mstest_m_failed_tests_report_mandatory_only.txt
Normal file
File diff suppressed because it is too large
Load Diff
26
docs/mstest_m_removed_extra_tests.txt
Normal file
26
docs/mstest_m_removed_extra_tests.txt
Normal 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
|
||||||
59
docs/mstest_m_removed_extra_tests_mandatory_only.txt
Normal file
59
docs/mstest_m_removed_extra_tests_mandatory_only.txt
Normal 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
|
||||||
@@ -12,25 +12,81 @@
|
|||||||
|
|
||||||
#include "parser_expand_internal.h"
|
#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(
|
static bool expand_argv(
|
||||||
t_command *command,
|
t_command *command,
|
||||||
t_minishell *minishell
|
t_minishell *minishell
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *expanded;
|
t_list *expanded_args;
|
||||||
|
t_list *fields;
|
||||||
|
t_list *last;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
expanded_args = NULL;
|
||||||
while (i < command->argc)
|
while (i < command->argc)
|
||||||
{
|
{
|
||||||
expanded = parser_expand_word(command->argv[i], minishell, true);
|
fields = NULL;
|
||||||
if (expanded == NULL)
|
if (!parser_expand_word_fields(command->argv[i], minishell,
|
||||||
return (false);
|
true, &fields))
|
||||||
free(command->argv[i]);
|
return (ft_lstclear(&expanded_args, free), false);
|
||||||
command->argv[i] = expanded;
|
if (expanded_args == NULL)
|
||||||
|
expanded_args = fields;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last = ft_lstlast(expanded_args);
|
||||||
|
if (last != NULL)
|
||||||
|
last->next = fields;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return (true);
|
return (command_set_expanded_argv(command, expanded_args, minishell));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool expand_redirections(
|
static bool expand_redirections(
|
||||||
|
|||||||
90
src/parser/parser_expand_fields.c
Normal file
90
src/parser/parser_expand_fields.c
Normal 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, ¤t, &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));
|
||||||
|
}
|
||||||
105
src/parser/parser_expand_fields_step.c
Normal file
105
src/parser/parser_expand_fields_step.c
Normal 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);
|
||||||
|
}
|
||||||
100
src/parser/parser_expand_fields_utils.c
Normal file
100
src/parser/parser_expand_fields_utils.c
Normal 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);
|
||||||
|
}
|
||||||
@@ -17,11 +17,21 @@
|
|||||||
# include "errors.h"
|
# include "errors.h"
|
||||||
# include "variables.h"
|
# include "variables.h"
|
||||||
|
|
||||||
|
typedef struct s_fields_ctx t_fields_ctx;
|
||||||
|
|
||||||
void parser_expand_malloc_error(t_minishell *minishell);
|
void parser_expand_malloc_error(t_minishell *minishell);
|
||||||
char *parser_expand_variable(const char *word, size_t *i,
|
char *parser_expand_variable(const char *word, size_t *i,
|
||||||
t_minishell *minishell);
|
t_minishell *minishell);
|
||||||
char *parser_expand_word(const char *word, t_minishell *minishell,
|
char *parser_expand_word(const char *word, t_minishell *minishell,
|
||||||
bool expand_vars);
|
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
|
typedef struct s_word_ctx
|
||||||
{
|
{
|
||||||
@@ -32,4 +42,22 @@ typedef struct s_word_ctx
|
|||||||
bool expand_vars;
|
bool expand_vars;
|
||||||
} t_word_ctx;
|
} 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
|
#endif
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ static bool word_step(
|
|||||||
|
|
||||||
if (word_toggle_quotes(word[*i], ctx.in_single_quote, ctx.in_double_quote))
|
if (word_toggle_quotes(word[*i], ctx.in_single_quote, ctx.in_double_quote))
|
||||||
return ((*i)++, true);
|
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)
|
if (word[*i] == '$' && !*ctx.in_single_quote && ctx.expand_vars)
|
||||||
{
|
{
|
||||||
expanded = parser_expand_variable(word, i, ctx.minishell);
|
expanded = parser_expand_variable(word, i, ctx.minishell);
|
||||||
|
|||||||
Reference in New Issue
Block a user