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 +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
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);

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
void redirection_add(t_list **tokens, t_token *token, t_command **command);
void words_add(t_list **tokens, t_command **command);
#endif /* PARSER_H */

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 *)
);
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.
*
@@ -42,9 +54,8 @@ t_list *parse(
return (NULL);
tokens = lex(line);
commands = parse_tokens(tokens);
(void)minishell;
// expand_variables(commands, minishell);
ft_lstclear(&tokens, (void (*)(void *))token_clear);
expand(&commands, minishell);
return (commands);
}
@@ -95,6 +106,97 @@ static t_list *parse_tokens(
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.
*
@@ -203,25 +305,38 @@ void command_add_tokens(
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(
t_list *args,
t_list **args,
size_t argc
)
{
char **argv;
size_t i;
char **argv;
t_list *arg;
size_t i;
argv = (char **)malloc(sizeof(char *) * (argc + 1));
if (argv == NULL)
return (NULL);
i = 0;
while (args != NULL)
arg = *args;
while (arg != NULL)
{
argv[i] = (char *)args->content;
args = args->next;
argv[i] = (char *)arg->content;
arg = arg->next;
i++;
}
argv[i] = NULL;
ft_lstclear_nodes(args);
return (argv);
}
@@ -253,7 +368,7 @@ void words_add(
token = (t_token *)arg->content;
}
*tokens = arg;
(*command)->argv = args_to_array(args, (*command)->argc);
(*command)->argv = args_to_array(&args, (*command)->argc);
ft_lstclear_nodes(&args);
}
@@ -374,52 +489,56 @@ t_list *ft_lstfind(
return (NULL);
}
void print_command_info(
t_command *command
)
{
printf("Command:\n");
printf(" argc: %d\n", command->argc);
printf(" argv: [");
for (int i = 0; i < command->argc; i++)
{
printf("%s", command->argv[i]);
if (i < command->argc - 1)
printf(", ");
}
printf("]\n");
printf(" path: %s\n", command->path);
printf(" redirections:\n");
t_list *redirection_node = command->redirections;
while (redirection_node != NULL)
{
t_redirection *redirection = (t_redirection *)redirection_node->content;
printf(" type: %d, target: %s\n", redirection->type, redirection->target);
redirection_node = redirection_node->next;
}
printf(" heredocs:\n");
t_list *heredoc_node = command->heredocs;
while (heredoc_node != NULL)
{
t_redirection *heredoc = (t_redirection *)heredoc_node->content;
printf(" type: %d, target: %s\n", heredoc->type, heredoc->target);
heredoc_node = heredoc_node->next;
}
}
// void print_command_info(
// t_command *command
// )
// {
// printf("Command:\n");
// printf(" argc: %d\n", command->argc);
// printf(" argv: [");
// for (int i = 0; i < command->argc; i++)
// {
// printf("%s", command->argv[i]);
// if (i < command->argc - 1)
// printf(", ");
// }
// printf("]\n");
// printf(" path: %s\n", command->path);
// printf(" redirections:\n");
// t_list *redirection_node = command->redirections;
// while (redirection_node != NULL)
// {
// t_redirection *redirection = (t_redirection *)redirection_node->content;
// printf(" type: %d, target: %s\n", redirection->type, redirection->target);
// redirection_node = redirection_node->next;
// }
// printf(" heredocs:\n");
// t_list *heredoc_node = command->heredocs;
// while (heredoc_node != NULL)
// {
// t_redirection *heredoc = (t_redirection *)heredoc_node->content;
// printf(" type: %d, target: %s\n", heredoc->type, heredoc->target);
// heredoc_node = heredoc_node->next;
// }
// }
int main(int argc, char const *argv[])
{
t_list *commands;
char *line;
// int main(int argc, char const *argv[], char **envp)
// {
// t_minishell minishell;
// t_list *commands;
// char *line;
if (argc != 2)
return (EXIT_FAILURE);
line = ft_strdup(argv[1]);
commands = parse(line, NULL);
ft_lstiter(commands, (void (*)(void *))print_command_info);
if (line != NULL)
free(line);
if (commands != NULL)
ft_lstclear(&commands, (void (*)(void *))command_clear);
return 0;
}
// if (argc != 2)
// return (EXIT_FAILURE);
// minishell_init(&minishell, envp);
// line = ft_strdup(argv[1]);
// commands = parse(line, NULL);
// ft_lstiter(commands, (void (*)(void *))print_command_info);
// if (line != NULL)
// free(line);
// if (commands != NULL)
// ft_lstclear(&commands, (void (*)(void *))command_clear);
// return 0;
// }