301 lines
6.9 KiB
C
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)
|
|
);
|
|
}
|