Files
minishell/src/parser/parser.c
2026-02-09 20:47:43 +01:00

301 lines
6.9 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/22 18:37:38 by sede-san #+# #+# */
/* Updated: 2026/02/09 18:50:43 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser.h"
// parse exclusive
static char *extract_next_command(char *line, size_t *index);
static char *trim_whitespaces(char *line, size_t *start, size_t *end);
// static void set_pipes(t_list *commands);
// common
static void find_boundary(char *line, size_t *index, char bound_char);
// 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);
static void set_path(t_command *command, t_minishell *minishell);
static u_int8_t path_is_solved(char *cmd_name, t_minishell *msh);
static char *solve_path(char *command_name, t_minishell *minishell);
t_list *parse(
char *line,
t_minishell *minishell
) {
t_list *commands;
t_list *tokens;
t_command *command;
char *command_str;
size_t i;
if (line == NULL)
return (NULL);
commands = NULL;
i = 0;
while (line[i] != '\0')
{
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);
}
// static void set_pipes(
// t_list *commands
// ) {
// t_list *current_command;
// t_list *previous_command;
// t_list *next_command;
// t_command *command;
// previous_command = NULL;
// current_command = commands;
// while (current_command != NULL)
// {
// command = (t_command *)current_command->content;
// 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;
command = (t_command *)ft_calloc(1, sizeof(t_command));
if (!command)
return (NULL);
// resolve_heredoc
set_argv(command, line, minishell);
if (!command->argv)
{
free(command);
return (NULL);
}
set_argc(command);
set_infile(command);
set_outfile(command);
set_path(command, minishell);
return (command);
}
static void set_argv(
t_command *command,
char *line,
t_minishell *minishell
) {
t_list *argv_list;
char *arg;
size_t i;
size_t start;
size_t end;
if (line == NULL)
return ;
i = 0;
argv_list = NULL;
while (line[i] != '\0')
{
start = i;
find_boundary(line, &i, ' ');
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);
ft_lstclear(&argv_list, free);
}
static void expand_envs(
char *arg,
t_minishell *minishell
) {
// TODO
(void)arg;
(void)minishell;
}
static char **lst_to_argv(
t_list *argv_list
) {
char **argv;
t_list *current_arg;
size_t i;
argv = (char **)ft_calloc(ft_lstsize(argv_list) + 1, sizeof(char *));
if (!argv)
return (NULL);
i = 0;
current_arg = argv_list;
while (current_arg != NULL)
{
argv[i] = ft_strdup((char *)current_arg->content);
i++;
current_arg = current_arg->next;
}
return (argv);
}
static void set_argc(
t_command *command
) {
int argc;
argc = 0;
while (command->argv[argc] != NULL)
argc++;
command->argc = argc;
}
static void set_infile(
t_command *command
) {
// test_infile
command->infile = -1;
}
static void set_outfile(
t_command *command
) {
// test_outfile
command->outfile = STDOUT_FILENO;
}
static void set_path(
t_command *command,
t_minishell *minishell
) {
char *command_path;
char *command_name;
command_name = command->argv[0];
if (!path_is_solved(command_name, minishell))
command_path = solve_path(command_name, minishell);
else
command_path = ft_strdup(command_name);
command->path = command_path;
}
static char *solve_path(
char *command_name,
t_minishell *minishell
){
char *command_path;
char **path_env;
size_t i;
path_env = ft_split(get_env("PATH", minishell), ':');
if (!path_env)
return (NULL);
command_path = NULL;
i = -1;
while (!command_path && path_env[++i])
{
command_path = ft_strnjoin(3, path_env[i], "/", command_name);
if (command_path != NULL && access(command_path, F_OK) != EXIT_SUCCESS)
{
free(command_path);
command_path = NULL;
}
}
ft_free_split(path_env);
return (command_path);
}
static u_int8_t path_is_solved(
char *command_name,
t_minishell *minishell
){
return (ft_strncmp(command_name, "/", 1) == 0
|| (command_name[1] && ft_strncmp(command_name, "./", 2) == 0)
|| (command_name[2] && ft_strncmp(command_name, "../", 3) == 0)
|| is_builtin(command_name, minishell)
);
}