A POR TODAAS

This commit is contained in:
marcnava-42cursus
2026-02-14 06:14:59 +01:00
parent e2b734cf0c
commit dd6101edec
5 changed files with 269 additions and 167 deletions

View File

@@ -6,170 +6,54 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/13 21:24:45 by sede-san #+# #+# */ /* Created: 2026/02/13 21:24:45 by sede-san #+# #+# */
/* Updated: 2026/02/14 05:45:59 by sede-san ### ########.fr */ /* Updated: 2026/02/14 06:56:00 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "parser.h" #include "parser_expand_internal.h"
#include "errors.h"
#include "variables.h"
static char *replace_value(char *original, char *value, int start, int end); static bool expand_argv(
static void expand_variable(char **argument, int *i, t_minishell *minishell); t_command *command,
static void expand_argument(char **argument, t_minishell *minishell);
static char *replace_value(
char *original,
char *value,
int start,
int end
)
{
const char *before = ft_substr(original, 0, start);
const char *after = ft_substr(original, end, ft_strlen(original) - end);
const char *expanded = ft_strnjoin(3, before, value, after);
free((char *)before);
free((char *)after);
return ((char *)expanded);
}
static void expand_variable(
char **argument,
int *i,
t_minishell *minishell t_minishell *minishell
) )
{ {
char *expanded;
char *variable_name;
char *variable_value;
const int start = *i + 1;
int end;
end = start;
while (ft_isalnum((*argument)[end]) || (*argument)[end] == '_'
|| (*argument)[end] == '?')
end++;
variable_name = ft_substr(*argument, start, end - start);
if (variable_name == NULL)
return (minishell->exit = true, malloc_error());
variable_value = get_var(variable_name, minishell);
free(variable_name);
if (variable_value == NULL)
variable_value = "";
expanded = replace_value(*argument, variable_value, start - 1, end);
if (expanded == NULL)
return (minishell->exit = true, malloc_error());
*i += ft_strlen(variable_value);
free(*argument);
*argument = expanded;
}
static void toggle_quotes(
char quote,
bool *in_single_quote,
bool *in_double_quote
)
{
if (quote == '\'' && !*in_double_quote)
*in_single_quote = !*in_single_quote;
else if (quote == '\"' && !*in_single_quote)
*in_double_quote = !*in_double_quote;
}
static void remove_quotes(
char **argument,
int start,
int end,
int length
)
{
char *before;
char *quoted;
char *after;
if ((*argument)[start] != '\'' && (*argument)[start] != '\"')
return ;
before = ft_substr(*argument, 0, start);
quoted = ft_substr(*argument, start + 1, end - start - 1);
after = ft_substr(*argument, end + 1, ft_strlen(*argument) - end - 1);
free(*argument);
*argument = ft_strnjoin(3, before, quoted, after);
free((char *)before);
free((char *)after);
free((char *)quoted);
}
static void check_boundaries(
bool in_single_quote,
bool in_double_quote,
int *quote_boundaries,
int i
)
{
if ((in_single_quote || in_double_quote) && quote_boundaries[0] == -1)
quote_boundaries[0] = i;
else if (!in_single_quote && !in_double_quote
&& quote_boundaries[0] != -1 && quote_boundaries[1] == -1)
quote_boundaries[1] = i;
}
static void handle_quotes(
char **argument,
int *i,
bool *in_single_quote,
t_minishell *minishell
)
{
bool in_double_quote;
int quote_boundaries[2];
quote_boundaries[0] = -1;
quote_boundaries[1] = -1;
in_double_quote = false;
while ((*argument)[*i] != '\0')
{
if ((*argument)[*i] == '$' && !*in_single_quote)
{
expand_variable(argument, i, minishell);
if (*argument == NULL)
return (minishell->exit = true, malloc_error());
}
else
{
toggle_quotes((*argument)[*i], in_single_quote, &in_double_quote);
check_boundaries(
*in_single_quote, in_double_quote, quote_boundaries, *i);
(*i)++;
}
}
if (*in_single_quote || in_double_quote)
return (syntax_error_unexpected_token(NULL));
return (remove_quotes(
argument, quote_boundaries[0], quote_boundaries[1], *i));
}
static void expand_argument(
char **argument,
t_minishell *minishell
)
{
bool in_single_quote;
int i; int i;
char *expanded;
in_single_quote = false;
i = 0; i = 0;
while ((*argument)[i] != '\0') while (i < command->argc)
{ {
if ((*argument)[i] == '$' && !in_single_quote) expanded = parser_expand_word(command->argv[i], minishell, true);
{ if (expanded == NULL)
expand_variable(argument, &i, minishell); return (false);
if (*argument == NULL) free(command->argv[i]);
return (minishell->exit = true, malloc_error()); command->argv[i] = expanded;
} i++;
else
handle_quotes(argument, &i, &in_single_quote, minishell);
} }
return (true);
}
static bool expand_redirections(
t_list *redirections,
t_minishell *minishell,
bool expand_vars
)
{
t_redirection *redirection;
char *expanded;
while (redirections != NULL)
{
redirection = (t_redirection *)redirections->content;
expanded = parser_expand_word(redirection->target, minishell,
expand_vars);
if (expanded == NULL)
return (false);
free(redirection->target);
redirection->target = expanded;
redirections = redirections->next;
}
return (true);
} }
void expand( void expand(
@@ -177,24 +61,23 @@ void expand(
t_minishell *minishell t_minishell *minishell
) )
{ {
t_list *current_command; t_list *current;
t_command *command; t_command *command;
int i;
current_command = *commands; if (commands == NULL || *commands == NULL)
while (current_command != NULL) return ;
current = *commands;
while (current != NULL)
{ {
command = (t_command *)current_command->content; command = (t_command *)current->content;
i = 0; if (!expand_argv(command, minishell)
while (i < command->argc) || !expand_redirections(command->redirections, minishell, true)
|| !expand_redirections(command->heredocs, minishell, false))
{ {
expand_argument(&command->argv[i], minishell); ft_lstclear(commands, (void (*)(void *))command_clear);
if (command->argv[i] == NULL) *commands = NULL;
ft_lstclear(commands, (void (*)(void *))command_clear); return ;
i++;
} }
if (command == NULL) current = current->next;
return (ft_lstclear(commands, (void (*)(void *))command_clear));
current_command = current_command->next;
} }
} }

View File

@@ -0,0 +1,35 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_internal.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 06:56:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 06:56:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PARSER_EXPAND_INTERNAL_H
# define PARSER_EXPAND_INTERNAL_H
# include "parser.h"
# include "errors.h"
# include "variables.h"
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);
typedef struct s_word_ctx
{
char **result;
bool *in_single_quote;
bool *in_double_quote;
t_minishell *minishell;
bool expand_vars;
} t_word_ctx;
#endif

View File

@@ -0,0 +1,82 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_variable.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 06:56:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 06:56:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
void parser_expand_malloc_error(
t_minishell *minishell
)
{
minishell->exit = true;
malloc_error();
}
static bool is_var_char(
char c
)
{
return (ft_isalnum(c) || c == '_');
}
static char *dup_or_error(
const char *value,
t_minishell *minishell
)
{
char *dup;
dup = ft_strdup(value);
if (dup == NULL)
return (parser_expand_malloc_error(minishell), NULL);
return (dup);
}
static char *expand_named_variable(
const char *word,
size_t *i,
t_minishell *minishell
)
{
char *name;
char *value;
size_t start;
start = *i;
while (word[*i] != '\0' && is_var_char(word[*i]))
(*i)++;
name = ft_substr(word, start, *i - start);
if (name == NULL)
return (parser_expand_malloc_error(minishell), NULL);
value = get_var(name, minishell);
free(name);
if (value == NULL)
value = "";
return (dup_or_error(value, minishell));
}
char *parser_expand_variable(const char *word, size_t *i,
t_minishell *minishell)
{
char *expanded;
(*i)++;
if (word[*i] == '?')
{
expanded = ft_itoa(minishell->exit_status);
if (expanded == NULL)
return (parser_expand_malloc_error(minishell), NULL);
return ((*i)++, expanded);
}
if (word[*i] == '\0' || !is_var_char(word[*i]))
return (dup_or_error("$", minishell));
return (expand_named_variable(word, i, minishell));
}

View File

@@ -0,0 +1,100 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_word.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 06:56:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 06:56:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
static bool word_toggle_quotes(
char c,
bool *in_single_quote,
bool *in_double_quote
)
{
if (c == '\'' && !*in_double_quote)
return (*in_single_quote = !*in_single_quote, true);
if (c == '\"' && !*in_single_quote)
return (*in_double_quote = !*in_double_quote, true);
return (false);
}
static bool word_append(
char **result,
const char *value,
t_minishell *minishell
)
{
char *joined;
joined = ft_strnjoin(2, *result, (char *)value);
if (joined == NULL)
{
free(*result);
*result = NULL;
return (parser_expand_malloc_error(minishell), false);
}
free(*result);
*result = joined;
return (true);
}
static bool word_step(
const char *word,
size_t *i,
t_word_ctx ctx
)
{
char *expanded;
char value[2];
if (word_toggle_quotes(word[*i], ctx.in_single_quote, ctx.in_double_quote))
return ((*i)++, true);
if (word[*i] == '$' && !*ctx.in_single_quote && ctx.expand_vars)
{
expanded = parser_expand_variable(word, i, ctx.minishell);
if (expanded == NULL || !word_append(ctx.result, expanded,
ctx.minishell))
return (free(expanded), false);
return (free(expanded), true);
}
value[0] = word[*i];
value[1] = '\0';
(*i)++;
return (word_append(ctx.result, value, ctx.minishell));
}
char *parser_expand_word(
const char *word,
t_minishell *minishell,
bool expand_vars
)
{
char *result;
size_t i;
bool in_single_quote;
bool in_double_quote;
result = ft_strdup("");
if (result == NULL)
return (parser_expand_malloc_error(minishell), NULL);
i = 0;
in_single_quote = false;
in_double_quote = false;
while (word[i] != '\0')
{
if (!word_step(word, &i, (t_word_ctx){&result, &in_single_quote,
&in_double_quote, minishell, expand_vars}))
return (NULL);
}
if (in_single_quote || in_double_quote)
return (free(result), syntax_error_unexpected_token(NULL),
minishell->exit_status = 2, NULL);
return (result);
}

View File

@@ -71,7 +71,9 @@ void set_env(
} }
} }
val = value; val = value;
if (val != NULL) if (val == NULL)
val = ft_strdup("");
else
val = ft_strdup(value); val = ft_strdup(value);
if (val == NULL) if (val == NULL)
{ {