Merge pull request #1 from Savapitech/history_T_A

add builtins history
This commit is contained in:
savalet
2025-04-16 18:36:38 +02:00
committed by GitHub
21 changed files with 709 additions and 35 deletions

View File

@@ -13,6 +13,7 @@ LIB_NAME := libu.a
SRC := $(wildcard src/*.c)
SRC += $(wildcard src/builtins/*.c)
SRC += $(wildcard src/utils/*.c)
LIB_SRC := $(wildcard ulib/*.c)
LIB_SRC += $(wildcard ulib/write/printf/*.c)

View File

@@ -9,9 +9,8 @@
#define AST_H
#include <stddef.h>
#include <stdint.h>
#include "shell.h"
#include "env.h"
#include "builtins_handler.h"
#define DEFAULT_AST_CAP 128
#define T_ALL 0xff
@@ -96,7 +95,7 @@ extern const tokens_list_t TOKENS_LIST[];
ast_t *parse_expression(ast_ctx_t *ctx);
void print_ast(ast_ctx_t *ctx, ast_t *ast, size_t depth);
token_t get_next_token(ast_ctx_t *ctx);
int visitor(char *buffer, env_t *env, history_t *history);
int visitor(char *buffer, exec_ctx_t *exec_ctx);
ast_t *create_node(ast_ctx_t *ctx);
bool ensure_node_cap(ast_t *node);
bool ensure_list_cap(ast_t *node);

View File

@@ -13,9 +13,9 @@
typedef struct {
char const *name;
int (*ptr)(ef_t *ef, char **args);
} builtins_t;
} builtins_funcs_t;
extern const builtins_t BUILTINS[];
extern const builtins_funcs_t BUILTINS[];
extern const size_t BUILTINS_SZ;
int builtins_exit(ef_t *ef, char **args);
@@ -25,4 +25,5 @@ int builtins_unsetenv(ef_t *ef, char **args);
int builtins_cd(ef_t *ef, char **args);
int builtins_builtins(ef_t *ef, char **args);
int builtins_funny_double_dot(ef_t *ef, char **args);
int builtins_history(ef_t *ef, char **args);
#endif /* BUILTIND_H */

View File

@@ -0,0 +1,176 @@
/*
** EPITECH PROJECT, 2025
** history_42sh
** File description:
** builtin_history
*/
#include <stdlib.h>
#include <stdio.h>
#include "history.h"
/*
**Il faut deux \0 parce que dans le gettokeniser
** y un truc qui regarde
**après le premier \0
*/
/*
**cat in str prend un
** his_variable_t en
** parametre pour
** connaitre la coord
** d' ou commencer a concaténer
** mais aussi le nombre de charactère a retiré
** il vas free le buffer
*/
#include <string.h>
#include "utils.h"
#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
static char *concat_cmd_arg(char *dest, char *src)
{
int l;
int i;
char *r_value = NULL;
if (!src) {
r_value = u_strdup(dest);
return r_value;
} else {
l = strlen(dest);
i = strlen(src);
r_value = malloc(sizeof(char)* (i + l + 2));
if (r_value != NULL) {
strcpy(r_value, dest);
r_value[l] = ' ';
r_value[l +1] = '\0';
strcat(r_value, src);
}
}
return r_value;
}
char *his_last_command(char *line,
his_variable_t *his_variable, his_command_t *his_command)
{
char *new_line = NULL;
char *new_str = NULL;
if (his_command->sz == 0){
printf("%d: Event not found\n", his_command->sz);
return NULL;
}
new_line = concat_cmd_arg(his_command[his_command->sz - 1].command,
his_command[his_command->sz - 1].arg);
new_str = cat_in_str(his_variable, line, new_line);
printf("%s\n", new_line);
free(new_line);
free(line);
return new_str;
}
char *his_last_same_command(char *line,
his_variable_t *his_variable, his_command_t *his_command)
{
char *new_line = &line[his_variable->coord_variable + 1];
char *new_str = NULL;
for (int i = his_command->sz - 1; i > 0; i--) {
if (his_command[i].command == NULL) {
printf("%s: Event not found\n", new_line);
return new_str;
}
if (strncmp(his_command[i].command, new_line, strlen(new_line)) == 0) {
new_line = concat_cmd_arg(his_command[i].command,
his_command[i].arg);
new_str = cat_in_str(his_variable, line, new_line);
free(line);
return new_str;
}
}
printf("%s: Event not found\n", new_line);
return new_str;
}
char *his_id_command(char *line,
his_variable_t *his_variable, his_command_t *his_command)
{
int id = -1 + atoi(&line[his_variable->coord_variable + 1]);
char *new_line;
char *new_str = NULL;
if (id < 0 || id > 100 || his_command[id].command == NULL){
printf("%d: Event not found\n", id + 1);
return new_str;
}
new_line = concat_cmd_arg(his_command[id].command, his_command[id].arg);
new_str = cat_in_str(his_variable, line, new_line);
printf("%s\n", new_str);
free(new_line);
free(line);
return new_str;
}
static char *get_last_word(char *str)
{
char *last_word = NULL;
int last_space = 0;
int x = 0;
if (!str)
return NULL;
while (str[x] != '\0') {
if (isblank(str[x]))
last_space = x + 1;
x++;
}
last_word = malloc(sizeof(char) * (x - last_space) + 1);
if (last_word != NULL) {
last_word = strncpy(last_word, &str[last_space], x - last_space);
last_word[x - last_space] = '\0';
}
return last_word;
}
char *his_last_word(char *line,
his_variable_t *his_variable, his_command_t *his_command)
{
char *new_line = NULL;
char *new_str = NULL;
if (his_command[his_command->sz - 1].arg == NULL){
new_line = get_last_word(his_command[his_command->sz - 1].command);
} else
new_line = get_last_word(his_command[his_command->sz - 1].arg);
if (!new_line)
return NULL;
new_str = cat_in_str(his_variable, line, new_line);
printf("%s\n", new_str);
free(new_line);
free(line);
return new_str;
}
char *his_last_arg(char *line,
his_variable_t *his_variable, his_command_t *his_command)
{
int id = his_command->sz - 1;
char *new_line = NULL;
char *new_str = NULL;
if (!his_command[id].arg)
new_line = " ";
else
new_line = u_strdup(his_command[id].arg);
new_str = cat_in_str(his_variable, line, new_line);
printf("%s\n", new_line);
if (his_command[id].arg)
free(new_line);
free(line);
return new_str;
}

View File

@@ -62,17 +62,17 @@ int builtins_cd_chdir(ef_t *ef, char **args, char *path)
{
char *act_pwd;
if (ef->history->last_chdir != NULL && args[1] != NULL
if (ef->exec_ctx->history->last_chdir != NULL && args[1] != NULL
&& u_strcmp(args[1], "-") == 0)
path = ef->history->last_chdir;
path = ef->exec_ctx->history->last_chdir;
act_pwd = get_current_dir();
if (chdir(path) < 0) {
write(STDERR_FILENO, path, u_strlen(path));
cd_print_error();
return RETURN_FAILURE;
}
free(ef->history->last_chdir);
ef->history->last_chdir = act_pwd;
free(ef->exec_ctx->history->last_chdir);
ef->exec_ctx->history->last_chdir = act_pwd;
return RETURN_SUCCESS;
}

View File

@@ -23,5 +23,5 @@ int builtins_exit(ef_t *ef, char **args __attribute__((unused)))
}
free_env(ef->env);
free(ef->buffer);
exit(ef->history->last_exit_code);
exit(ef->exec_ctx->history->last_exit_code);
}

25
src/builtins/history.c Normal file
View File

@@ -0,0 +1,25 @@
/*
** EPITECH PROJECT, 2025
** 42sh
** File description:
** history
*/
#include <stdio.h>
#include "common.h"
#include "env.h"
#include "exec.h"
int builtins_history(ef_t *ef, char **args __attribute__((unused)))
{
his_command_t *cmd_history = ef->exec_ctx->history_command;
for (int i = 0; i < cmd_history->sz; i++){
if (cmd_history[i].arg) {
printf("%d %s %s\n", i + 1, cmd_history[i].command,
cmd_history[i].arg);
} else
printf("%d %s\n", i + 1, cmd_history[i].command);
}
return RETURN_SUCCESS;
}

23
src/builtins_handler.h Normal file
View File

@@ -0,0 +1,23 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#ifndef BUILTINS_HANDLER_H
#define BUILTINS_HANDLER_H
#include "env.h"
#include "history.h"
#include "shell.h"
typedef struct {
env_t *env;
history_t *history;
his_command_t *history_command;
} exec_ctx_t;
size_t update_command(char **buffer,
size_t *buffer_sz, exec_ctx_t *exec_ctx);
#endif /* BUILTINS_HANDLER_H */

View File

@@ -23,7 +23,7 @@
#include "u_mem.h"
#include "u_str.h"
const builtins_t BUILTINS[] = {
const builtins_funcs_t BUILTINS[] = {
{ "builtins", &builtins_builtins },
{ "cd", &builtins_cd },
{ "chdir", &builtins_cd },
@@ -32,7 +32,8 @@ const builtins_t BUILTINS[] = {
{ "setenv", &builtins_setenv },
{ "unsetenv", &builtins_unsetenv },
{ ":", &builtins_funny_double_dot },
{ "exit", &builtins_exit }
{ "exit", &builtins_exit },
{ "history", &builtins_history}
};
const size_t BUILTINS_SZ = sizeof BUILTINS / sizeof *BUILTINS;
@@ -137,8 +138,8 @@ int launch_bin(char *full_bin_path, char **args, ef_t *ef)
else
waitpid(pid, &status, WNOHANG);
if (WIFEXITED(status))
ef->history->last_exit_code =
ef->history->last_exit_code ?: WEXITSTATUS(status);
ef->exec_ctx->history->last_exit_code =
ef->exec_ctx->history->last_exit_code ?: WEXITSTATUS(status);
return status;
}
@@ -171,7 +172,7 @@ bool builtins_launcher(ef_t *ef, char **args)
if (u_strlen(BUILTINS[i].name) != bin_l)
continue;
if (u_strcmp(BUILTINS[i].name, args[0]) == 0) {
ef->history->last_exit_code =
ef->exec_ctx->history->last_exit_code =
BUILTINS[i].ptr(ef, args);
return true;
}
@@ -199,5 +200,6 @@ int execute(ef_t *ef)
U_DEBUG("Exit code [%d]\n", ef->history->last_exit_code);
free(full_bin_path);
free((void *)args);
return ef->history->last_exit_code != 0 ? RETURN_FAILURE : RETURN_SUCCESS;
return ef->exec_ctx->history->last_exit_code
!= 0 ? RETURN_FAILURE : RETURN_SUCCESS;
}

View File

@@ -43,6 +43,7 @@ typedef struct {
int pout_fd;
int in_fd;
int out_fd;
exec_ctx_t *exec_ctx;
} ef_t;
__attribute__((nonnull))

54
src/history.h Normal file
View File

@@ -0,0 +1,54 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#ifndef HISTORY_H
#define HISTORY_H
#define CHAR_HIST '!'
#define TWO_CHAR_CMD 3
#include <stddef.h>
typedef struct history_variable_s {
int coord_variable;
int size_variable;
int type;
char *str;
int id;
} his_variable_t;
typedef struct history_command_s {
int id;
char *command;
char *arg;
int sz;
} his_command_t;
typedef struct parsing_history_s {
char *name;
char *(*funct)(char *, his_variable_t *, his_command_t *);
} parsing_history_t;
extern const parsing_history_t tab_fnct[];
int parse_history(char **pointer_line,
size_t *buffer_len, size_t *buffer_sz, his_command_t **cmd_history);
char *his_last_command(char *line,
his_variable_t *his_variable, his_command_t *his_command);
char *his_last_same_command(char *line,
his_variable_t *his_variable, his_command_t *his_command);
char *his_id_command(char *line,
his_variable_t *his_variable, his_command_t *his_command);
char *his_last_word(char *line,
his_variable_t *his_variable, his_command_t *his_command);
char *his_last_arg(char *line,
his_variable_t *his_variable, his_command_t *his_command);
his_command_t *fill_cmd_history(his_command_t *cmd_history);
int save_cmd_history(his_command_t *cmd_history);
his_command_t set_cmd(char *line, his_command_t cmd_struct);
#endif /* HISTORY_H */

46
src/init_history.c Normal file
View File

@@ -0,0 +1,46 @@
/*
** EPITECH PROJECT, 2025
** 42sh
** File description:
** init_history
*/
#include <fcntl.h>
#include <unistd.h>
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "history.h"
#include "ctype.h"
static char *get_arg(char *line, int x, int end_cmd)
{
char *tmp = malloc(sizeof(char) * (x - end_cmd) + 1);
if (tmp != NULL) {
tmp = strncpy(tmp, &line[end_cmd], x - end_cmd);
tmp[x - end_cmd] = '\0';
}
return tmp;
}
his_command_t set_cmd(char *line, his_command_t cmd_struct)
{
int x = 0;
int end_cmd;
while (line[x] != '\0' && !isblank(line[x]))
x++;
cmd_struct.command = malloc(sizeof(char) * x + 1);
if (cmd_struct.command != NULL) {
cmd_struct.command = strncpy(cmd_struct.command, line, x);
cmd_struct.command[x] = '\0';
}
end_cmd = x + 1;
while (line[x] != '\0')
x++;
if (x <= end_cmd)
return cmd_struct;
cmd_struct.arg = get_arg(line, x, end_cmd);
return cmd_struct;
}

131
src/parse_history.c Normal file
View File

@@ -0,0 +1,131 @@
/*
** EPITECH PROJECT, 2025
** history_42sh
** File description:
** his for history
*/
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "utils.h"
#include "common.h"
#include "env.h"
#include "exec.h"
#include "u_mem.h"
#include "u_str.h"
#include "history.h"
const parsing_history_t tab_fnct[] = {
{"!!", &his_last_command},
{"!$", &his_last_word},
{"!*", &his_last_arg},
{"![command]", &his_last_same_command},
{"![number]", &his_id_command},
};
static
int cmd_history_is_in(char *line)
{
for (int i = 0; line[i] != 0; i++)
if (line[i] == CHAR_HIST &&
(line[i + 1] != ' ' && line[i + 1] != '\t'
&& line[i + 1] != '\0'))
return 0;
return 1;
}
static
int is_two_char_cmd(char *line, int coord_x)
{
if (line[coord_x] != CHAR_HIST)
return -1;
coord_x++;
switch (line[coord_x]){
case '!':
return 0;
case '$':
return 1;
case '*':
return 2;
}
return -1;
}
static
int choose_id_or_last(his_variable_t *his_variable, int index_str, char *str)
{
int mode = 0;
const int cpy_index = index_str;
if (str[index_str] != CHAR_HIST && is_a_token(str, index_str + 1) == false)
return -1;
index_str++;
for (; str[index_str] != 0; index_str++){
if (is_a_token(str, index_str) == true || isblank(str[index_str]))
break;
if (!isdigit(str[index_str]))
mode = 1;
}
his_variable->coord_variable = cpy_index;
his_variable->size_variable = index_str - cpy_index;
his_variable->str = strn_to_ndup(cpy_index, (index_str - cpy_index), str);
if (his_variable->str == NULL)
return 3;
his_variable->id = atoi(his_variable->str + 1);
return (mode == 1) ? 3 : 4;
}
static
int which_his_cmd(his_variable_t *his_variable, char const *line)
{
for (int i = 0; line[i] != '\0'; i++){
his_variable->type = is_two_char_cmd(line, i);
if (his_variable->type != -1){
his_variable->coord_variable = i;
his_variable->size_variable = 2;
return 0;
}
his_variable->type = choose_id_or_last(his_variable, i, line);
if (his_variable->type != -1)
return 0;
}
return 0;
}
static
char *replace_history(char *line, his_command_t *cmd_history)
{
his_variable_t his_variable = {.coord_variable = 0,
.id = 0, .size_variable = 0, .str = NULL, .type = -1};
which_his_cmd(&his_variable, line);
while (his_variable.type != -1){
line = tab_fnct[his_variable.type].funct(line, &his_variable,
cmd_history);
if (line == NULL)
return NULL;
which_his_cmd(&his_variable, line);
}
return line;
}
int parse_history(char **pointer_line,
size_t *buffer_len, size_t *buffer_sz, his_command_t **cmd_history)
{
char *line = *pointer_line;
*buffer_sz = 0;
if (cmd_history_is_in(line) == 0){
line = replace_history(line, *cmd_history);
if (line == NULL)
return 84;
*buffer_len = u_strlen(line) + 1;
*pointer_line = line;
return 0;
}
return 0;
}

View File

@@ -15,6 +15,7 @@
#include "common.h"
#include "debug.h"
#include "env.h"
#include "history.h"
#include "shell.h"
#include "u_str.h"
@@ -32,6 +33,8 @@ void debug_env_entries(env_t *env)
static
void check_basic_error(char const *buffer)
{
if (buffer == NULL)
return;
if (*buffer == '|')
WRITE_CONST(STDERR_FILENO, "Invalid null command.\n");
if (*buffer == '>' || *buffer == '<')
@@ -46,40 +49,83 @@ void ignore_sigint(int sig __attribute__((unused)))
}
static
int shell_loop(env_t *env, int is_a_tty, history_t *history)
void write_prompt(int is_a_tty)
{
if (is_a_tty)
WRITE_CONST(STDOUT_FILENO, SHELL_PROMPT);
}
/*
** Noeud de fonction
** Pour changer la commande
** passer en parametre
** si besoin
*/
static
int shell_loop(int is_a_tty, exec_ctx_t *exec_ctx)
{
char *buffer = NULL;
size_t buffer_sz;
size_t buffer_len;
size_t buffer_sz = 0;
size_t buffer_len = 0;
while (true) {
if (is_a_tty)
WRITE_CONST(STDOUT_FILENO, SHELL_PROMPT);
write_prompt(is_a_tty);
if (getline(&buffer, &buffer_sz, stdin) == -1)
break;
buffer_len = u_strlen(buffer);
if (buffer_len < 2 || !u_str_is_alnum(buffer)) {
buffer_len = update_command(&buffer, &buffer_sz, exec_ctx);
if (buffer_len < 1 || !u_str_is_alnum(buffer)) {
check_basic_error(buffer);
continue;
}
buffer[buffer_len - 1] = '\0';
U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, buffer);
visitor(buffer, env, history);
visitor(buffer, exec_ctx);
free(buffer);
}
return (free(buffer), history->last_exit_code);
free(exec_ctx->history_command);
return (free(buffer), exec_ctx->history->last_exit_code);
}
his_command_t *init_cmd_history(void)
{
his_command_t *cmd_history = malloc(sizeof(his_command_t) * 100);
if (cmd_history == NULL)
return NULL;
for (int i = 0; i != 100; i++){
cmd_history[i].arg = NULL;
cmd_history[i].command = NULL;
cmd_history[i].id = i;
}
cmd_history->sz = 0;
return cmd_history;
}
static
bool error_in_init(exec_ctx_t *exec_ctx)
{
if (!exec_ctx->history_command || !exec_ctx->env->env) {
free(exec_ctx->history_command);
free(exec_ctx->env->env);
return true;
}
return false;
}
int shell(char **env_ptr)
{
env_t env = parse_env(env_ptr);
history_t history = { .cmd_history = NULL, 0, .last_chdir = NULL };
history_t history = { .cmd_history = NULL, 0, .last_chdir = NULL};
his_command_t *cmd_history = init_cmd_history();
exec_ctx_t exec_ctx = {.env = &env,
.history = &history, .history_command = cmd_history };
int shell_result;
if (!env.env)
if (error_in_init(&exec_ctx) == true){
return RETURN_FAILURE;
}
U_DEBUG_CALL(debug_env_entries, &env);
signal(SIGINT, ignore_sigint);
shell_result = shell_loop(&env, isatty(STDIN_FILENO), &history);
free_env(&env);
shell_result = shell_loop(isatty(STDIN_FILENO), &exec_ctx);
free_env(exec_ctx.env);
return shell_result;
}

48
src/update_command.c Normal file
View File

@@ -0,0 +1,48 @@
/*
** EPITECH PROJECT, 2025
** 42sh
** File description:
** update_command
*/
#include "history.h"
#include "builtins_handler.h"
#include "u_str.h"
static int check_cmd(char *cmd)
{
if (!cmd)
return 84;
for (int i = 0; cmd[i] != 0; i++)
if (cmd[i] == CHAR_HIST &&
(cmd[i + 1] != ' ' && cmd[i + 1] != '\t'
&& cmd[i + 1] != '\0'))
return 84;
return 0;
}
his_command_t *save_command(char *cmd, his_command_t *cmd_history)
{
if (check_cmd(cmd) == 84)
return cmd_history;
if (cmd_history->sz < 100) {
cmd_history[cmd_history->sz] = set_cmd(cmd,
cmd_history[cmd_history->sz]);
}
cmd_history->sz++;
return cmd_history;
}
size_t update_command(char **buffer,
size_t *buffer_sz, exec_ctx_t *exec_ctx)
{
size_t buffer_len = 0;
buffer_len = u_strlen(*buffer);
(*buffer)[buffer_len - 1] = '\0';
if (parse_history(buffer, &buffer_len,
buffer_sz, &exec_ctx->history_command) == 84)
return -1;
exec_ctx->history_command = save_command(*buffer,
exec_ctx->history_command);
return buffer_len;
}

18
src/utils.h Normal file
View File

@@ -0,0 +1,18 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#ifndef UTILS_H
#define UTILS_H
#include "history.h"
#include "u_str.h"
char *strn_to_ndup(int start, int size, char *str);
bool is_a_token(char *str, int index_str);
char *cat_in_str(his_variable_t *his_variable, char *str, char *cpy);
int len_array(char **array);
#endif /* UTILS_H */

43
src/utils/cat_in_str.c Normal file
View File

@@ -0,0 +1,43 @@
/*
** EPITECH PROJECT, 2025
** 42sh
** File description:
** cat_in_str
*/
#include "history.h"
#include <string.h>
#include <stdlib.h>
static
int insert_in_str(char *dest, char *cpy, int start)
{
for (int j = 0; cpy[j] != 0; j++){
dest[start] = cpy[j];
start++;
}
return start;
}
char *cat_in_str(his_variable_t *his_variable, char *str, char *cpy)
{
int i = 0;
int len_str = strlen(str);
int size_right = len_str -
his_variable->coord_variable - his_variable->size_variable;
int size_left = (len_str - size_right) - his_variable->size_variable;
char *new_str = malloc(sizeof(char) *
(size_right + size_left + strlen(cpy) + 2));
if (new_str == NULL)
return NULL;
for (; i < size_left; i++)
new_str[i] = str[i];
i += insert_in_str(new_str, cpy, i);
for (int k = 0; k < size_right; k++){
new_str[i] = str[k + size_left + his_variable->size_variable];
i++;
}
new_str[i] = '\0';
new_str[i + 1] = '\0';
return new_str;
}

20
src/utils/is_a_token.c Normal file
View File

@@ -0,0 +1,20 @@
/*
** EPITECH PROJECT, 2025
** 42sh
** File description:
** is_a_token
*/
#include "string.h"
#include "u_str.h"
#include "ast.h"
bool is_a_token(char *str, int index_str)
{
str += index_str;
for (size_t i = 0; i < 16; i++) {
if (strncmp(str, TOKENS_LIST[i].str, 2) == 0){
return true;
}
}
return false;
}

17
src/utils/len_array.c Normal file
View File

@@ -0,0 +1,17 @@
/*
** EPITECH PROJECT, 2025
** 42sh
** File description:
** len_array
*/
#include <stdlib.h>
int len_array(char **array)
{
int i = 0;
while (array[i] != NULL)
i++;
return i;
}

22
src/utils/strn_to_ndup.c Normal file
View File

@@ -0,0 +1,22 @@
/*
** EPITECH PROJECT, 2025
** 42sh
** File description:
** strn_to_ndup
*/
#include <stdlib.h>
char *strn_to_ndup(int start, int size, char *str)
{
char *new_str = malloc(sizeof(char) * (size + 1));
int count = 0;
if (new_str == NULL)
return NULL;
new_str[size] = '\0';
for (int i = start; i != start + size; i++){
new_str[count] = str[i];
count++;
}
return new_str;
}

View File

@@ -146,18 +146,19 @@ void remove_trailing_semi(char *str)
}
}
int visitor(char *buffer, env_t *env, history_t *history)
int visitor(char *buffer, exec_ctx_t *exec_ctx)
{
ast_ctx_t ctx = { 0, .str = buffer, .cap = u_strlen(buffer) + 10,
.ast = malloc(sizeof *ctx.ast * (u_strlen(buffer) + 10)) };
ef_t ef = { .buffer = buffer, .env = env,
.history = history, .ctx = &ctx, .pout_fd = STDOUT_FILENO,
.flags = 0, 0 };
ef_t ef = { .buffer = buffer, .env = exec_ctx->env,
.history = exec_ctx->history, .ctx
= &ctx, .pout_fd = STDOUT_FILENO, .flags = 0,
.exec_ctx = exec_ctx};
int result = RETURN_FAILURE;
ctx.first_node = ctx.ast;
remove_trailing_semi(ctx.str);
history->last_exit_code = 0;
exec_ctx->history->last_exit_code = 0;
if (ctx.ast == NULL)
return RETURN_FAILURE;
result = visitor_launcher(&ef);