Merge branch 'solo' into feature/executor-gl
# Conflicts: # src/parser/parser.c
This commit is contained in:
@@ -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/09 18:45:41 by sede-san ### ########.fr */
|
/* Updated: 2026/02/10 23:21:35 by sede-san ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -19,9 +19,37 @@
|
|||||||
/* Structures & Data Types */
|
/* Structures & Data Types */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
typedef struct s_minishell t_minishell;
|
# define TOKENS_COUNT 5
|
||||||
typedef struct s_variables t_variables;
|
|
||||||
typedef struct s_command t_command;
|
typedef enum e_token_type
|
||||||
|
{
|
||||||
|
TOKEN_WORD,
|
||||||
|
TOKEN_PIPE,
|
||||||
|
TOKEN_REDIRECT_IN,
|
||||||
|
TOKEN_REDIRECT_OUT,
|
||||||
|
TOKEN_APPEND,
|
||||||
|
TOKEN_HEREDOC
|
||||||
|
} t_token_type;
|
||||||
|
|
||||||
|
typedef struct s_token
|
||||||
|
{
|
||||||
|
t_token_type type;
|
||||||
|
char *value;
|
||||||
|
} t_token;
|
||||||
|
|
||||||
|
typedef enum e_redirection_type
|
||||||
|
{
|
||||||
|
REDIRECT_IN,
|
||||||
|
REDIRECT_OUT,
|
||||||
|
APPEND,
|
||||||
|
HEREDOC
|
||||||
|
} t_redirection_type;
|
||||||
|
|
||||||
|
typedef struct s_redirection
|
||||||
|
{
|
||||||
|
t_token_type type;
|
||||||
|
char *target;
|
||||||
|
} t_redirection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure that holds both environment and internal variables
|
* @brief Structure that holds both environment and internal variables
|
||||||
@@ -70,6 +98,7 @@ typedef struct s_command
|
|||||||
char **argv;
|
char **argv;
|
||||||
char *path;
|
char *path;
|
||||||
t_list *redirections;
|
t_list *redirections;
|
||||||
|
t_list *heredocs;
|
||||||
} t_command;
|
} t_command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
23
include/errors.h
Normal file
23
include/errors.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* errors.h :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2026/02/10 22:28:01 by sede-san #+# #+# */
|
||||||
|
/* Updated: 2026/02/10 23:24:16 by sede-san ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#ifndef ERRORS_H
|
||||||
|
# define ERRORS_H
|
||||||
|
|
||||||
|
# include "minishell.h"
|
||||||
|
# include "core.h"
|
||||||
|
# include "parser.h"
|
||||||
|
|
||||||
|
extern void syntax_error_unexpected_token(t_token *token);
|
||||||
|
extern void malloc_error(void);
|
||||||
|
|
||||||
|
#endif /* ERRORS_H */
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2025/10/20 16:35:10 by sede-san #+# #+# */
|
/* Created: 2025/10/20 16:35:10 by sede-san #+# #+# */
|
||||||
/* Updated: 2026/02/09 18:38:16 by sede-san ### ########.fr */
|
/* Updated: 2026/02/10 22:12:58 by sede-san ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
# include "chardefs.h"
|
# include "chardefs.h"
|
||||||
# include <stdbool.h>
|
# include <stdbool.h>
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
|
# include <errno.h>
|
||||||
# include <readline/readline.h> // readline(3), rl_clear_history(),
|
# include <readline/readline.h> // readline(3), rl_clear_history(),
|
||||||
// rl_on_new_line(), rl_replace_line(),
|
// rl_on_new_line(), rl_replace_line(),
|
||||||
// rl_redisplay()
|
// rl_redisplay()
|
||||||
|
|||||||
@@ -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/09 21:19:02 by sede-san ### ########.fr */
|
/* Updated: 2026/02/12 03:06:43 by sede-san ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -17,38 +17,6 @@
|
|||||||
# include "core.h"
|
# include "core.h"
|
||||||
# include "builtins.h"
|
# include "builtins.h"
|
||||||
|
|
||||||
# define TOKENS_COUNT 5
|
|
||||||
|
|
||||||
typedef enum e_token_type
|
|
||||||
{
|
|
||||||
TOKEN_WORD,
|
|
||||||
TOKEN_PIPE,
|
|
||||||
TOKEN_REDIRECT_IN,
|
|
||||||
TOKEN_REDIRECT_OUT,
|
|
||||||
TOKEN_APPEND,
|
|
||||||
TOKEN_HEREDOC
|
|
||||||
} t_token_type;
|
|
||||||
|
|
||||||
typedef struct s_token
|
|
||||||
{
|
|
||||||
t_token_type type;
|
|
||||||
char *value;
|
|
||||||
} t_token;
|
|
||||||
|
|
||||||
typedef enum e_redirection_type
|
|
||||||
{
|
|
||||||
REDIRECT_IN,
|
|
||||||
REDIRECT_OUT,
|
|
||||||
APPEND,
|
|
||||||
HEREDOC
|
|
||||||
} t_redirection_type;
|
|
||||||
|
|
||||||
typedef struct s_redirection
|
|
||||||
{
|
|
||||||
t_redirection_type type;
|
|
||||||
char *target;
|
|
||||||
} t_redirection;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Functions */
|
/* Functions */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@@ -57,4 +25,16 @@ typedef struct s_redirection
|
|||||||
|
|
||||||
extern t_list *parse(char *line, t_minishell *minishell);
|
extern t_list *parse(char *line, t_minishell *minishell);
|
||||||
|
|
||||||
|
// lexer.c
|
||||||
|
|
||||||
|
extern t_list *lex(const char *line);
|
||||||
|
|
||||||
|
extern void token_clear(t_token *token);
|
||||||
|
extern t_command *command_new(t_list **tokens);
|
||||||
|
extern void command_clear(t_command *command);
|
||||||
|
extern void command_add_tokens(t_command **command, t_list **tokens);
|
||||||
|
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 */
|
#endif /* PARSER_H */
|
||||||
|
|||||||
31
src/errors/errors.c
Normal file
31
src/errors/errors.c
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* errors.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2026/02/10 22:22:06 by sede-san #+# #+# */
|
||||||
|
/* Updated: 2026/02/12 02:55:36 by sede-san ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "errors.h"
|
||||||
|
|
||||||
|
void syntax_error_unexpected_token(
|
||||||
|
t_token *token
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char *cause;
|
||||||
|
|
||||||
|
if (token == NULL)
|
||||||
|
cause = "newline";
|
||||||
|
else
|
||||||
|
cause = token->value;
|
||||||
|
ft_eprintf("minishell: syntax error near unexpected token `%s'\n", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
void malloc_error(void)
|
||||||
|
{
|
||||||
|
ft_eprintf("minishell: %s\n", strerror(ENOMEM));
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2026/02/09 18:56:41 by sede-san #+# #+# */
|
/* Created: 2026/02/09 18:56:41 by sede-san #+# #+# */
|
||||||
/* Updated: 2026/02/10 12:33:55 by sede-san ### ########.fr */
|
/* Updated: 2026/02/11 02:06:36 by sede-san ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
static t_token *tokenize(const char *line, size_t *start);
|
static t_token *tokenize(const char *line, size_t *start);
|
||||||
static t_token_type get_token_type(const char *str);
|
static t_token_type get_token_type(const char *str);
|
||||||
static t_token *token_new(t_token_type type, char *text);
|
static t_token *token_new(t_token_type type, char *text);
|
||||||
static void token_clear(t_token *token);
|
void token_clear(t_token *token);
|
||||||
static t_token *read_token(t_token_type type, const char *line, size_t *i);
|
static t_token *read_token(t_token_type type, const char *line, size_t *i);
|
||||||
static t_token *read_word(const char *line, size_t *i);
|
static t_token *read_word(const char *line, size_t *i);
|
||||||
static inline bool is_meta(char c);
|
static inline bool is_meta(char c);
|
||||||
@@ -41,7 +41,7 @@ t_list *lex(
|
|||||||
while (ft_isspace(line[i]))
|
while (ft_isspace(line[i]))
|
||||||
i++;
|
i++;
|
||||||
if (line[i] == '\0')
|
if (line[i] == '\0')
|
||||||
break;
|
break ;
|
||||||
token = tokenize(line, &i);
|
token = tokenize(line, &i);
|
||||||
ft_lstadd_back(&tokens, ft_lstnew(token));
|
ft_lstadd_back(&tokens, ft_lstnew(token));
|
||||||
if (token == NULL)
|
if (token == NULL)
|
||||||
@@ -117,7 +117,7 @@ static t_token *token_new(
|
|||||||
return (token);
|
return (token);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void token_clear(
|
void token_clear(
|
||||||
t_token *token
|
t_token *token
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -158,8 +158,6 @@ static t_token *read_word(
|
|||||||
in_double_quote = false;
|
in_double_quote = false;
|
||||||
while (line[*i] != '\0')
|
while (line[*i] != '\0')
|
||||||
{
|
{
|
||||||
char c = line[*i];
|
|
||||||
(void)c;
|
|
||||||
if (line[*i] == '\'' && !in_double_quote)
|
if (line[*i] == '\'' && !in_double_quote)
|
||||||
in_single_quote = !in_single_quote;
|
in_single_quote = !in_single_quote;
|
||||||
else if (line[*i] == '"' && !in_single_quote)
|
else if (line[*i] == '"' && !in_single_quote)
|
||||||
|
|||||||
@@ -6,241 +6,370 @@
|
|||||||
/* 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/09 18:50:43 by sede-san ### ########.fr */
|
/* Updated: 2026/02/12 03:06:20 by sede-san ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "errors.h"
|
||||||
|
|
||||||
// parse exclusive
|
static t_list *parse_tokens(
|
||||||
static char *extract_next_command(char *line, size_t *index);
|
t_list *tokens
|
||||||
static char *trim_whitespaces(char *line, size_t *start, size_t *end);
|
);
|
||||||
// static void set_pipes(t_list *commands);
|
|
||||||
|
|
||||||
// common
|
static t_list *ft_lstfind(
|
||||||
static void find_boundary(char *line, size_t *index, char bound_char);
|
t_list *lst,
|
||||||
|
bool (*pre)(void *)
|
||||||
// command exclusive
|
);
|
||||||
static t_command *cmdnew(char *line, t_minishell *minishell);
|
|
||||||
static void set_argv(t_command *command, char *line, t_minishell *minishell);
|
|
||||||
static void expand_envs(char *arg, t_minishell *minishell);
|
|
||||||
static char **lst_to_argv(t_list *argv_list);
|
|
||||||
static void set_argc(t_command *command);
|
|
||||||
static void set_infile(t_command *command);
|
|
||||||
static void set_outfile(t_command *command);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts a command line string into a list of commands.
|
||||||
|
*
|
||||||
|
* @param line The command line string to parse.
|
||||||
|
* @param minishell The minishell instance.
|
||||||
|
*
|
||||||
|
* @return A list of commands or `NULL` on error.
|
||||||
|
*/
|
||||||
t_list *parse(
|
t_list *parse(
|
||||||
char *line,
|
char *line,
|
||||||
t_minishell *minishell
|
t_minishell *minishell
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
t_list *commands;
|
t_list *commands;
|
||||||
t_command *command;
|
t_list *tokens;
|
||||||
char *command_str;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
commands = NULL;
|
tokens = lex(line);
|
||||||
i = 0;
|
commands = parse_tokens(tokens);
|
||||||
while (line[i] != '\0')
|
(void)minishell;
|
||||||
{
|
// expand_variables(commands, minishell);
|
||||||
/* TODO: re-enable when parser consumes lexer tokens */
|
ft_lstclear(&tokens, (void (*)(void *))token_clear);
|
||||||
/* tokens = tokenize(); */
|
|
||||||
command_str = extract_next_command(line, &i);
|
|
||||||
if (command_str != NULL)
|
|
||||||
{
|
|
||||||
command = cmdnew(command_str, minishell);
|
|
||||||
free(command_str);
|
|
||||||
if (command != NULL)
|
|
||||||
ft_lstadd_back(&commands, ft_lstnew(command));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// set_pipes(commands);
|
|
||||||
return (commands);
|
return (commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static void set_pipes(
|
/**
|
||||||
// t_list *commands
|
* @brief Converts a list of tokens into a list of commands.
|
||||||
// ) {
|
*
|
||||||
// t_list *current_command;
|
* @param tokens The list of tokens to parse.
|
||||||
// t_list *previous_command;
|
* @param minishell The minishell instance.
|
||||||
// t_list *next_command;
|
*
|
||||||
// t_command *command;
|
* @return A list of commands or `NULL` on error.
|
||||||
|
*/
|
||||||
// previous_command = NULL;
|
static t_list *parse_tokens(
|
||||||
// current_command = commands;
|
t_list *tokens
|
||||||
// while (current_command != NULL)
|
)
|
||||||
// {
|
{
|
||||||
// command = (t_command *)current_command->content;
|
t_list *commands;
|
||||||
// if (previous_command != NULL)
|
|
||||||
// command->piped_from = (t_command *)previous_command->content;
|
|
||||||
// next_command = current_command->next;
|
|
||||||
// if (next_command != NULL)
|
|
||||||
// command->piped_to = (t_command *)next_command->content;
|
|
||||||
// previous_command = current_command;
|
|
||||||
// current_command = current_command->next;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
static char *extract_next_command(
|
|
||||||
char *line,
|
|
||||||
size_t *index
|
|
||||||
) {
|
|
||||||
char *command_str;
|
|
||||||
size_t start;
|
|
||||||
size_t end;
|
|
||||||
|
|
||||||
start = *index;
|
|
||||||
find_boundary(line, index, '|');
|
|
||||||
end = *index;
|
|
||||||
command_str = trim_whitespaces(line, &start, &end);
|
|
||||||
while (line[*index] == '|' || ft_isspace(line[*index]))
|
|
||||||
(*index)++;
|
|
||||||
return (command_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void find_boundary(
|
|
||||||
char *line,
|
|
||||||
size_t *index,
|
|
||||||
char bound_char
|
|
||||||
) {
|
|
||||||
bool in_single_quote;
|
|
||||||
bool in_double_quote;
|
|
||||||
|
|
||||||
in_single_quote = false;
|
|
||||||
in_double_quote = false;
|
|
||||||
while (line[*index] != '\0')
|
|
||||||
{
|
|
||||||
if (line[*index] == '\'' && !in_double_quote)
|
|
||||||
in_single_quote = !in_single_quote;
|
|
||||||
else if (line[*index] == '"' && !in_single_quote)
|
|
||||||
in_double_quote = !in_double_quote;
|
|
||||||
if (line[*index] == bound_char && !in_single_quote && !in_double_quote)
|
|
||||||
break ;
|
|
||||||
(*index)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *trim_whitespaces(
|
|
||||||
char *line,
|
|
||||||
size_t *start,
|
|
||||||
size_t *end
|
|
||||||
) {
|
|
||||||
while (*start < *end && ft_isspace(line[*start]))
|
|
||||||
(*start)++;
|
|
||||||
while (*end > *start && ft_isspace(line[*end - 1]))
|
|
||||||
(*end)--;
|
|
||||||
if (*end > *start)
|
|
||||||
return (ft_substr(line, *start, *end - *start));
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static t_command *cmdnew(
|
|
||||||
char *line,
|
|
||||||
t_minishell *minishell
|
|
||||||
) {
|
|
||||||
t_command *command;
|
t_command *command;
|
||||||
|
t_list *current_token;
|
||||||
|
t_list *new_command;
|
||||||
|
|
||||||
|
if (tokens == NULL)
|
||||||
|
return (NULL);
|
||||||
|
commands = NULL;
|
||||||
|
current_token = tokens;
|
||||||
|
while (current_token != NULL)
|
||||||
|
{
|
||||||
|
command = command_new(¤t_token);
|
||||||
|
if (command == NULL)
|
||||||
|
{
|
||||||
|
ft_lstclear(&commands, (void (*)(void *))command_clear);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
new_command = ft_lstnew(command);
|
||||||
|
if (new_command == NULL)
|
||||||
|
{
|
||||||
|
command_clear(command);
|
||||||
|
ft_lstclear(&commands, (void (*)(void *))command_clear);
|
||||||
|
return (malloc_error(), NULL);
|
||||||
|
}
|
||||||
|
ft_lstadd_back(&commands, new_command);
|
||||||
|
if (current_token != NULL)
|
||||||
|
{
|
||||||
|
if (current_token->next == NULL)
|
||||||
|
syntax_error_unexpected_token((t_token *)current_token->content);
|
||||||
|
current_token = current_token->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new command from a list of tokens.
|
||||||
|
*
|
||||||
|
* @param tokens The list of tokens to create the command from.
|
||||||
|
*
|
||||||
|
* @return A new command or NULL on error.
|
||||||
|
*
|
||||||
|
* @note The `tokens` pointer is moved to the next command's tokens.
|
||||||
|
*/
|
||||||
|
t_command *command_new(
|
||||||
|
t_list **tokens
|
||||||
|
)
|
||||||
|
{
|
||||||
|
t_command *command;
|
||||||
|
t_list *current_token;
|
||||||
|
t_list *delimiter_token;
|
||||||
|
|
||||||
command = (t_command *)ft_calloc(1, sizeof(t_command));
|
command = (t_command *)ft_calloc(1, sizeof(t_command));
|
||||||
if (!command)
|
if (command == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
// resolve_heredoc
|
current_token = *tokens;
|
||||||
set_argv(command, line, minishell);
|
delimiter_token = ft_lstfind(current_token, (bool (*)(void *))is_pipe);
|
||||||
if (!command->argv)
|
while (command != NULL && current_token != delimiter_token)
|
||||||
{
|
{
|
||||||
free(command);
|
command_add_tokens(&command, ¤t_token);
|
||||||
return (NULL);
|
|
||||||
}
|
}
|
||||||
set_argc(command);
|
*tokens = current_token;
|
||||||
set_infile(command);
|
|
||||||
set_outfile(command);
|
|
||||||
return (command);
|
return (command);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_argv(
|
/**
|
||||||
t_command *command,
|
* @brief Creates a new redirection from a list of tokens.
|
||||||
char *line,
|
*
|
||||||
t_minishell *minishell
|
* @param tokens The list of tokens to create the redirection from.
|
||||||
) {
|
*
|
||||||
t_list *argv_list;
|
* @return A new redirection or `NULL` on error.
|
||||||
char *arg;
|
*/
|
||||||
size_t i;
|
t_redirection *redirection_new(
|
||||||
size_t start;
|
t_list **tokens
|
||||||
size_t end;
|
)
|
||||||
|
{
|
||||||
|
t_redirection *redirection;
|
||||||
|
t_token *token;
|
||||||
|
|
||||||
if (line == NULL)
|
redirection = (t_redirection *)malloc(sizeof(t_redirection));
|
||||||
return ;
|
if (redirection == NULL)
|
||||||
i = 0;
|
return (malloc_error(), NULL);
|
||||||
argv_list = NULL;
|
token = (t_token *)(*tokens)->content;
|
||||||
while (line[i] != '\0')
|
redirection->type = token->type;
|
||||||
|
*tokens = (*tokens)->next;
|
||||||
|
if (*tokens == NULL)
|
||||||
{
|
{
|
||||||
start = i;
|
free(redirection);
|
||||||
find_boundary(line, &i, ' ');
|
return (syntax_error_unexpected_token(NULL), NULL);
|
||||||
end = i;
|
|
||||||
arg = trim_whitespaces(line, &start, &end);
|
|
||||||
expand_envs(arg, minishell);
|
|
||||||
if (arg != NULL)
|
|
||||||
ft_lstadd_back(&argv_list, ft_lstnew(arg));
|
|
||||||
while (ft_isspace(line[i]))
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
command->argv = lst_to_argv(argv_list);
|
token = (t_token *)(*tokens)->content;
|
||||||
ft_lstclear(&argv_list, free);
|
if (token->type != TOKEN_WORD)
|
||||||
|
{
|
||||||
|
free(redirection);
|
||||||
|
while (*tokens != NULL)
|
||||||
|
*tokens = (*tokens)->next;
|
||||||
|
return (syntax_error_unexpected_token(token), NULL);
|
||||||
|
}
|
||||||
|
redirection->target = ft_strdup(token->value);
|
||||||
|
if (redirection->target == NULL)
|
||||||
|
{
|
||||||
|
free(redirection);
|
||||||
|
return (malloc_error(), NULL);
|
||||||
|
}
|
||||||
|
*tokens = (*tokens)->next;
|
||||||
|
return (redirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void expand_envs(
|
void redirection_clear(
|
||||||
char *arg,
|
t_redirection *redirection
|
||||||
t_minishell *minishell
|
)
|
||||||
) {
|
{
|
||||||
// TODO
|
if (redirection != NULL)
|
||||||
(void)arg;
|
{
|
||||||
(void)minishell;
|
free(redirection->target);
|
||||||
|
free(redirection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **lst_to_argv(
|
/**
|
||||||
t_list *argv_list
|
* @brief Adds a token to a command, updating the command's arguments and
|
||||||
) {
|
* redirections as necessary.
|
||||||
|
*
|
||||||
|
* @param command The command to add the token to.
|
||||||
|
* @param tokens The list of tokens to add to the command.
|
||||||
|
*
|
||||||
|
* @note The `command` pointer can be free'd if there is an error while adding
|
||||||
|
* the token.
|
||||||
|
*/
|
||||||
|
void command_add_tokens(
|
||||||
|
t_command **command,
|
||||||
|
t_list **tokens
|
||||||
|
)
|
||||||
|
{
|
||||||
|
t_token *token;
|
||||||
|
|
||||||
|
token = (t_token *)(*tokens)->content;
|
||||||
|
if (is_redirection(token))
|
||||||
|
redirection_add(tokens, token, command);
|
||||||
|
else
|
||||||
|
words_add(tokens, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
char **args_to_array(
|
||||||
|
t_list *args,
|
||||||
|
size_t argc
|
||||||
|
)
|
||||||
|
{
|
||||||
char **argv;
|
char **argv;
|
||||||
t_list *current_arg;
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
argv = (char **)ft_calloc(ft_lstsize(argv_list) + 1, sizeof(char *));
|
argv = (char **)malloc(sizeof(char *) * (argc + 1));
|
||||||
if (!argv)
|
if (argv == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
i = 0;
|
i = 0;
|
||||||
current_arg = argv_list;
|
while (args != NULL)
|
||||||
while (current_arg != NULL)
|
|
||||||
{
|
{
|
||||||
argv[i] = ft_strdup((char *)current_arg->content);
|
argv[i] = (char *)args->content;
|
||||||
|
args = args->next;
|
||||||
i++;
|
i++;
|
||||||
current_arg = current_arg->next;
|
|
||||||
}
|
}
|
||||||
|
argv[i] = NULL;
|
||||||
return (argv);
|
return (argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_argc(
|
/**
|
||||||
t_command *command
|
* @brief Adds all consecutive word tokens to a command's argv and updates its
|
||||||
) {
|
* argc accordingly.
|
||||||
int argc;
|
*
|
||||||
|
* @param command The command to add the word tokens to.
|
||||||
|
* @param tokens The list of tokens to add to the command.
|
||||||
|
*/
|
||||||
|
void words_add(
|
||||||
|
t_list **tokens,
|
||||||
|
t_command **command
|
||||||
|
)
|
||||||
|
{
|
||||||
|
t_list *args;
|
||||||
|
t_list *arg;
|
||||||
|
t_token *token;
|
||||||
|
|
||||||
argc = 0;
|
args = NULL;
|
||||||
while (command->argv[argc] != NULL)
|
arg = *tokens;
|
||||||
argc++;
|
token = (t_token *)arg->content;
|
||||||
command->argc = argc;
|
while (arg != NULL && token->type == TOKEN_WORD)
|
||||||
|
{
|
||||||
|
ft_lstadd_back(&args, ft_lstnew(ft_strdup(token->value)));
|
||||||
|
(*command)->argc++;
|
||||||
|
arg = arg->next;
|
||||||
|
if (arg != NULL)
|
||||||
|
token = (t_token *)arg->content;
|
||||||
|
}
|
||||||
|
*tokens = arg;
|
||||||
|
(*command)->argv = args_to_array(args, (*command)->argc);
|
||||||
|
ft_lstclear_nodes(&args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_infile(
|
void redirection_add(
|
||||||
t_command *command
|
t_list **tokens,
|
||||||
) {
|
t_token *token,
|
||||||
// test_infile
|
t_command **command
|
||||||
/* command->infile = -1; */
|
)
|
||||||
(void)command;
|
{
|
||||||
|
t_redirection *redirection;
|
||||||
|
t_list *redirection_tokens;
|
||||||
|
|
||||||
|
redirection = redirection_new(tokens);
|
||||||
|
if (redirection == NULL)
|
||||||
|
{
|
||||||
|
command_clear(*command);
|
||||||
|
*command = NULL;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
redirection_tokens = ft_lstnew(redirection);
|
||||||
|
if (redirection_tokens == NULL)
|
||||||
|
{
|
||||||
|
free(redirection);
|
||||||
|
return (malloc_error());
|
||||||
|
}
|
||||||
|
if (token->type == TOKEN_HEREDOC)
|
||||||
|
ft_lstadd_back(&(*command)->heredocs, redirection_tokens);
|
||||||
|
else
|
||||||
|
ft_lstadd_back(&(*command)->redirections, redirection_tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_outfile(
|
/**
|
||||||
t_command *command
|
* @brief Checks if a token is a redirection token.
|
||||||
) {
|
*
|
||||||
// test_outfile
|
* @param token The token to check.
|
||||||
/* command->outfile = STDOUT_FILENO; */
|
*
|
||||||
(void)command;
|
* @return `true` if the token is a redirection token, `false` otherwise.
|
||||||
|
*/
|
||||||
|
bool is_redirection(
|
||||||
|
t_token *token
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (token->type == TOKEN_REDIRECT_IN
|
||||||
|
|| token->type == TOKEN_REDIRECT_OUT
|
||||||
|
|| token->type == TOKEN_APPEND
|
||||||
|
|| token->type == TOKEN_HEREDOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_clear_argv(
|
||||||
|
t_command *command
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (command->argv != NULL)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
while (i < command->argc)
|
||||||
|
{
|
||||||
|
free(command->argv[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
free(command->argv);
|
||||||
|
command->argv = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears a command, freeing all associated memory.
|
||||||
|
*
|
||||||
|
* @param command The command to clear.
|
||||||
|
*/
|
||||||
|
void command_clear(
|
||||||
|
t_command *command
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (command != NULL)
|
||||||
|
{
|
||||||
|
command_clear_argv(command);
|
||||||
|
ft_lstclear(&command->redirections, (void (*)(void *))redirection_clear);
|
||||||
|
ft_lstclear(&command->heredocs, (void (*)(void *))redirection_clear);
|
||||||
|
free(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if a token is a pipe token.
|
||||||
|
*
|
||||||
|
* @param token The token to check.
|
||||||
|
*
|
||||||
|
* @return `true` if the token is a pipe token, `false` otherwise.
|
||||||
|
*/
|
||||||
|
bool is_pipe(
|
||||||
|
t_token *token)
|
||||||
|
{
|
||||||
|
return (token->type == TOKEN_PIPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finds a node in a linked list that satisfies a given predicate.
|
||||||
|
*
|
||||||
|
* @param lst The linked list to search through.
|
||||||
|
* @param pre The predicate function to apply to each node's content.
|
||||||
|
*
|
||||||
|
* @returns The first node that satisfies the predicate or `NULL` if no such
|
||||||
|
* node exists or if the list is `NULL`.
|
||||||
|
*/
|
||||||
|
t_list *ft_lstfind(
|
||||||
|
t_list *lst,
|
||||||
|
bool (*pre)(void *))
|
||||||
|
{
|
||||||
|
while (lst != NULL)
|
||||||
|
{
|
||||||
|
if (pre(lst->content))
|
||||||
|
return (lst);
|
||||||
|
lst = lst->next;
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user