save commit
This commit is contained in:
@@ -6,73 +6,295 @@
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/10/22 18:37:38 by sede-san #+# #+# */
|
||||
/* Updated: 2025/10/23 22:53:35 by sede-san ### ########.fr */
|
||||
/* Updated: 2026/02/09 18:50:43 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
#include "parser.h"
|
||||
|
||||
static char **expand_envs(char **argv);
|
||||
static int count_argv(char **argv);
|
||||
// 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);
|
||||
|
||||
char *parse(
|
||||
// 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_command command;
|
||||
) {
|
||||
t_list *commands;
|
||||
t_list *tokens;
|
||||
t_command *command;
|
||||
char *command_str;
|
||||
size_t i;
|
||||
|
||||
if (!line || !*line)
|
||||
if (line == NULL)
|
||||
return (NULL);
|
||||
(void)minishell;
|
||||
command.argv = expand_envs(ft_split(line, SPACE));
|
||||
command.argc = count_argv(command.argv);
|
||||
if (!command.argc)
|
||||
return (NULL);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//* DEBUG
|
||||
// int i = -1;
|
||||
// while (command.argv[++i])
|
||||
// printf("argv[%i]: %s\n", i, command.argv[i]);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
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 char **expand_envs(
|
||||
char **argv
|
||||
){
|
||||
int i;
|
||||
char *env;
|
||||
static t_command *cmdnew(
|
||||
char *line,
|
||||
t_minishell *minishell
|
||||
) {
|
||||
t_command *command;
|
||||
|
||||
if (!argv)
|
||||
command = (t_command *)ft_calloc(1, sizeof(t_command));
|
||||
if (!command)
|
||||
return (NULL);
|
||||
else if (!*argv) // check if ft_split returned and empty matrix
|
||||
// resolve_heredoc
|
||||
set_argv(command, line, minishell);
|
||||
if (!command->argv)
|
||||
{
|
||||
ft_free_split(argv);
|
||||
free(command);
|
||||
return (NULL);
|
||||
}
|
||||
i = -1;
|
||||
while (argv[++i])
|
||||
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')
|
||||
{
|
||||
if (!ft_strchr(argv[i], DOLLAR)
|
||||
|| (ft_strchr(argv[i], DOLLAR) && ft_strchr(argv[i], SINGLE_QUOTE) && ft_strchr(argv[i] + (ft_strchr(argv[i], SINGLE_QUOTE) + 1 - argv[i]), SINGLE_QUOTE))) // env is surrounded by single quote
|
||||
continue ;
|
||||
env = getenv(ft_strchr(argv[i], DOLLAR) + 1);
|
||||
free(argv[i]);
|
||||
if (env)
|
||||
argv[i] = ft_strdup(env);
|
||||
else
|
||||
argv[i] = ft_strdup("");
|
||||
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 int count_argv(
|
||||
char **argv
|
||||
){
|
||||
int i;
|
||||
static void set_argc(
|
||||
t_command *command
|
||||
) {
|
||||
int argc;
|
||||
|
||||
i = 0;
|
||||
while (argv[i])
|
||||
i++;
|
||||
return (i);
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user