diff --git a/ecsls.toml b/ecsls.toml index 8d1c8b6..04134d1 100644 --- a/ecsls.toml +++ b/ecsls.toml @@ -1 +1,2 @@ - +[reports] +merge = "multiplier" diff --git a/src/readline.c b/src/readline.c new file mode 100644 index 0000000..63afc39 --- /dev/null +++ b/src/readline.c @@ -0,0 +1,132 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "debug.h" +#include "readline.h" +#include "u_str.h" + +static +size_t strcpy_printable(char *dest, char const *src, size_t n) +{ + size_t count = 0; + + for (size_t i = 0; i < n; i++) { + if (isprint(src[i])) { + *dest = src[i]; + count++; + dest++; + } + } + return count; +} + +static +bool str_printable(char const *str, size_t size) +{ + for (size_t i = 0; i < size; i++) + if (!isprint(str[i])) + return false; + return true; +} + +static +bool ensure_buff_av_capacity(buff_t *buff, size_t requested) +{ + char *new_str; + size_t endsize = BUFF_INIT_SZ; + + if ((buff->sz + requested) < buff->cap) + return true; + for (; endsize < buff->sz + requested; endsize <<= 1); + if (endsize > buff->cap) { + new_str = realloc(buff->str, (sizeof *buff->str) * endsize); + if (new_str == NULL) + return false; + buff->str = new_str; + buff->cap = endsize; + } + return true; +} + +static +bool ensure_buff_capacity(buff_t *buff) +{ + char *new_str; + + if (buff->str == NULL) { + new_str = malloc((sizeof *buff->str) * BUFF_INIT_SZ); + if (new_str == NULL) + return false; + buff->str = new_str; + buff->cap = BUFF_INIT_SZ; + } + if (buff->sz == buff->cap) { + new_str = realloc(buff->str, (sizeof *buff->str) * buff->cap << 1); + if (new_str == NULL) + return false; + buff->str = new_str; + buff->cap <<= 1; + } + return true; +} + +static +bool append_null_terminator(buff_t *buff) +{ + if (!ensure_buff_av_capacity(buff, 1)) + return false; + buff->str[buff->sz] = '\0'; + buff->sz++; + return true; +} + +static +int8_t handle_line_buff(buff_t *buff, char *read_buff, ssize_t read_size) +{ + if (*read_buff == CTRL('d')) { + buff->sz = 0; + return WRITE_CONST(STDOUT_FILENO, "exit\n"), RETURN_SUCCESS; + } + if (str_printable(read_buff, read_size)) + write(STDOUT_FILENO, read_buff, read_size); + if (!ensure_buff_av_capacity(buff, read_size)) + return RETURN_FAILURE; + buff->sz += strcpy_printable(buff->str + buff->sz, + read_buff, read_size); + return -1; +} + +bool readline(buff_t *buff) +{ + char read_buff[32] = ""; + ssize_t read_size = 0; + + if (!ensure_buff_capacity(buff)) + return false; + while (*read_buff != '\n' && *read_buff != '\r') { + memset(read_buff, '\0', sizeof read_buff); + read_size = read(STDIN_FILENO, &read_buff, sizeof read_buff - 1); + if (read_size < 0) + return false; + if (read_size == 0) { + buff->sz = 0; + return true; + } + if (handle_line_buff(buff, read_buff, read_size) > -1) + return true; + } + U_DEBUG("buff count: %zu\n", buff->sz); + return append_null_terminator(buff); +} diff --git a/src/readline.h b/src/readline.h new file mode 100644 index 0000000..cd382d3 --- /dev/null +++ b/src/readline.h @@ -0,0 +1,17 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + +#ifndef READLINE + #define READLINE + #define CTRL(x) (x & 0xf) + #define BUFF_INIT_SZ 128 + #include + + #include "u_str.h" + +bool readline(buff_t *buff); +#endif /* READLINE */ diff --git a/src/shell.c b/src/shell.c index d64ffff..13bf4f2 100644 --- a/src/shell.c +++ b/src/shell.c @@ -16,6 +16,7 @@ #include "debug.h" #include "env.h" #include "history.h" +#include "readline.h" #include "shell.h" #include "u_str.h" @@ -56,22 +57,20 @@ void write_prompt(int is_a_tty) } static -bool change_shell_command(char **buffer, exec_ctx_t *exec_ctx, - size_t buffer_sz) +bool change_shell_command(buff_t *buff, exec_ctx_t *exec_ctx) { - size_t buffer_len = 0; char *tmp_buff = NULL; - if (getline(buffer, &buffer_sz, stdin) == -1) + if (!readline(buff)) return true; - tmp_buff = (*buffer); - buffer_len = update_command(&tmp_buff, &buffer_sz, exec_ctx); - if (buffer_len < 1 || !u_str_is_alnum(tmp_buff)) { + tmp_buff = buff->str; + buff->sz = update_command(&tmp_buff, &buff->sz, exec_ctx); + if (buff->sz < 1 || !u_str_is_alnum(tmp_buff)) { check_basic_error(tmp_buff); free(tmp_buff); return false; } - U_DEBUG("Buffer [%lu] [%s]\n", buffer_len, buffer); + U_DEBUG("Buffer [%lu] [%s]\n", buff->sz, buff->str); visitor(tmp_buff, exec_ctx); free(tmp_buff); return false; @@ -80,16 +79,15 @@ bool change_shell_command(char **buffer, exec_ctx_t *exec_ctx, static int shell_loop(int is_a_tty, exec_ctx_t *exec_ctx) { - char *buffer = NULL; - size_t buffer_sz = 0; + buff_t buff = { .str = NULL, 0 }; while (true) { write_prompt(is_a_tty); - if (change_shell_command(&buffer, exec_ctx, buffer_sz) == true) + if (change_shell_command(&buff, exec_ctx)) return exec_ctx->history->last_exit_code; } free(exec_ctx->history_command); - return (free(buffer), exec_ctx->history->last_exit_code); + return free(buff.str), exec_ctx->history->last_exit_code; } his_command_t *init_cmd_history(void)