feat: added variable expansion

quote removal is not implemented yet in this commit
This commit is contained in:
2026-02-12 21:10:09 +01:00
parent 8882929423
commit 83553a57d5
3 changed files with 181 additions and 61 deletions

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/22 19:10:13 by sede-san #+# #+# */ /* Created: 2025/10/22 19:10:13 by sede-san #+# #+# */
/* Updated: 2026/02/10 23:21:35 by sede-san ### ########.fr */ /* Updated: 2026/02/12 20:19:23 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -123,9 +123,9 @@ typedef struct s_command
/* minishell.c */ /* minishell.c */
extern int minishell_init(t_minishell *minishell, char **envp); extern void minishell_init(t_minishell *minishell, char **envp);
extern uint8_t minishell_run(t_minishell *minishell); extern void minishell_run(t_minishell *minishell);
extern void minishell_clear(t_minishell *minishell); extern void minishell_clear(t_minishell *minishell);

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/22 19:03:51 by sede-san #+# #+# */ /* Created: 2025/10/22 19:03:51 by sede-san #+# #+# */
/* Updated: 2026/02/12 03:06:43 by sede-san ### ########.fr */ /* Updated: 2026/02/12 18:34:11 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -37,4 +37,5 @@ extern bool is_pipe(t_token *token);
extern bool is_redirection(t_token *token); extern bool is_redirection(t_token *token);
void redirection_add(t_list **tokens, t_token *token, t_command **command); void redirection_add(t_list **tokens, t_token *token, t_command **command);
void words_add(t_list **tokens, t_command **command); void words_add(t_list **tokens, t_command **command);
#endif /* PARSER_H */ #endif /* PARSER_H */

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/22 18:37:38 by sede-san #+# #+# */ /* Created: 2025/10/22 18:37:38 by sede-san #+# #+# */
/* Updated: 2026/02/12 03:06:20 by sede-san ### ########.fr */ /* Updated: 2026/02/12 20:55:49 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -22,6 +22,18 @@ static t_list *ft_lstfind(
bool (*pre)(void *) bool (*pre)(void *)
); );
static void expand_variable(
char **argument,
int *i,
t_minishell *minishell
);
static void expand(
t_list **commands,
t_minishell *minishell
);
/** /**
* @brief Converts a command line string into a list of commands. * @brief Converts a command line string into a list of commands.
* *
@@ -42,9 +54,8 @@ t_list *parse(
return (NULL); return (NULL);
tokens = lex(line); tokens = lex(line);
commands = parse_tokens(tokens); commands = parse_tokens(tokens);
(void)minishell;
// expand_variables(commands, minishell);
ft_lstclear(&tokens, (void (*)(void *))token_clear); ft_lstclear(&tokens, (void (*)(void *))token_clear);
expand(&commands, minishell);
return (commands); return (commands);
} }
@@ -95,6 +106,97 @@ static t_list *parse_tokens(
return (commands); return (commands);
} }
static void expand_variable(
char **argument,
int *i,
t_minishell *minishell
)
{
char *expanded;
char *variable;
char *variable_name;
const int start = *i + 1;
int end;
end = start;
while (ft_isalnum((*argument)[end]))
end++;
variable_name = ft_substr(*argument, start, end - start);
if (variable_name == NULL)
return (minishell->exit = true, malloc_error());
variable = get_env(variable_name, minishell);
free(variable_name);
if (variable == NULL)
variable = "";
expanded = ft_strnjoin(3,
ft_substr(*argument, 0, *i),
variable,
ft_substr(*argument,end, ft_strlen(*argument) - end));
if (expanded == NULL)
return (minishell->exit = true, malloc_error());
*i += ft_strlen(variable) - 1;
free(*argument);
*argument = expanded;
}
static void expand_argument(
char **argument,
t_minishell *minishell
)
{
bool in_single_quote;
bool in_double_quote;
int i;
in_single_quote = false;
in_double_quote = false;
i = 0;
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
{
if ((*argument)[i] == '\'' && !in_double_quote)
in_single_quote = !in_single_quote;
else if ((*argument)[i] == '"' && !in_single_quote)
in_double_quote = !in_double_quote;
i++;
}
}
}
static void expand(
t_list **commands,
t_minishell *minishell
)
{
t_list *current_command;
t_command *command;
int i;
current_command = *commands;
while (current_command != NULL)
{
command = (t_command *)current_command->content;
i = 0;
while (i < command->argc)
{
expand_argument(&command->argv[i], minishell);
if (command->argv[i] == NULL)
ft_lstclear(commands, (void (*)(void *))command_clear);
i++;
}
if (command == NULL)
return (ft_lstclear(commands, (void (*)(void *))command_clear));
current_command = current_command->next;
}
}
/** /**
* @brief Creates a new command from a list of tokens. * @brief Creates a new command from a list of tokens.
* *
@@ -203,25 +305,38 @@ void command_add_tokens(
words_add(tokens, command); words_add(tokens, command);
} }
/**
* @brief Converts a list of arguments into an array.
*
* @param args The list of arguments to convert.
* @param argc The number of arguments in the list.
*
* @return An array of arguments or `NULL` on error.
*
* @note The `args` list is cleared after the conversion and set to NULL.
*/
char **args_to_array( char **args_to_array(
t_list *args, t_list **args,
size_t argc size_t argc
) )
{ {
char **argv; char **argv;
t_list *arg;
size_t i; size_t i;
argv = (char **)malloc(sizeof(char *) * (argc + 1)); argv = (char **)malloc(sizeof(char *) * (argc + 1));
if (argv == NULL) if (argv == NULL)
return (NULL); return (NULL);
i = 0; i = 0;
while (args != NULL) arg = *args;
while (arg != NULL)
{ {
argv[i] = (char *)args->content; argv[i] = (char *)arg->content;
args = args->next; arg = arg->next;
i++; i++;
} }
argv[i] = NULL; argv[i] = NULL;
ft_lstclear_nodes(args);
return (argv); return (argv);
} }
@@ -253,7 +368,7 @@ void words_add(
token = (t_token *)arg->content; token = (t_token *)arg->content;
} }
*tokens = arg; *tokens = arg;
(*command)->argv = args_to_array(args, (*command)->argc); (*command)->argv = args_to_array(&args, (*command)->argc);
ft_lstclear_nodes(&args); ft_lstclear_nodes(&args);
} }
@@ -374,52 +489,56 @@ t_list *ft_lstfind(
return (NULL); return (NULL);
} }
void print_command_info( // void print_command_info(
t_command *command // t_command *command
) // )
{ // {
printf("Command:\n"); // printf("Command:\n");
printf(" argc: %d\n", command->argc); // printf(" argc: %d\n", command->argc);
printf(" argv: ["); // printf(" argv: [");
for (int i = 0; i < command->argc; i++) // for (int i = 0; i < command->argc; i++)
{ // {
printf("%s", command->argv[i]); // printf("%s", command->argv[i]);
if (i < command->argc - 1) // if (i < command->argc - 1)
printf(", "); // printf(", ");
} // }
printf("]\n"); // printf("]\n");
printf(" path: %s\n", command->path); // printf(" path: %s\n", command->path);
printf(" redirections:\n"); // printf(" redirections:\n");
t_list *redirection_node = command->redirections; // t_list *redirection_node = command->redirections;
while (redirection_node != NULL) // while (redirection_node != NULL)
{ // {
t_redirection *redirection = (t_redirection *)redirection_node->content; // t_redirection *redirection = (t_redirection *)redirection_node->content;
printf(" type: %d, target: %s\n", redirection->type, redirection->target); // printf(" type: %d, target: %s\n", redirection->type, redirection->target);
redirection_node = redirection_node->next; // redirection_node = redirection_node->next;
} // }
printf(" heredocs:\n"); // printf(" heredocs:\n");
t_list *heredoc_node = command->heredocs; // t_list *heredoc_node = command->heredocs;
while (heredoc_node != NULL) // while (heredoc_node != NULL)
{ // {
t_redirection *heredoc = (t_redirection *)heredoc_node->content; // t_redirection *heredoc = (t_redirection *)heredoc_node->content;
printf(" type: %d, target: %s\n", heredoc->type, heredoc->target); // printf(" type: %d, target: %s\n", heredoc->type, heredoc->target);
heredoc_node = heredoc_node->next; // heredoc_node = heredoc_node->next;
} // }
} // }
int main(int argc, char const *argv[]) // int main(int argc, char const *argv[], char **envp)
{ // {
t_list *commands; // t_minishell minishell;
char *line; // t_list *commands;
// char *line;
if (argc != 2) // if (argc != 2)
return (EXIT_FAILURE); // return (EXIT_FAILURE);
line = ft_strdup(argv[1]);
commands = parse(line, NULL); // minishell_init(&minishell, envp);
ft_lstiter(commands, (void (*)(void *))print_command_info);
if (line != NULL) // line = ft_strdup(argv[1]);
free(line); // commands = parse(line, NULL);
if (commands != NULL) // ft_lstiter(commands, (void (*)(void *))print_command_info);
ft_lstclear(&commands, (void (*)(void *))command_clear); // if (line != NULL)
return 0; // free(line);
} // if (commands != NULL)
// ft_lstclear(&commands, (void (*)(void *))command_clear);
// return 0;
// }