From 5ade92701836ce5ee1d39fc8d486b7709547058e Mon Sep 17 00:00:00 2001 From: Charles Date: Tue, 9 Jun 2020 17:09:55 +0200 Subject: Added iterpolation like bash according to lexer output (2 leaks) --- .gitignore | 2 + include/ast.h | 8 +- include/lexer.h | 19 +++- include/minishell.h | 3 +- libft | 2 +- print_argv_env_main.c | 12 +++ src/.DS_Store | Bin 6148 -> 0 bytes src/env.c | 6 +- src/glob.c | 162 --------------------------------- src/lexer/lexer_len_element_and_mall.c | 1 + src/lexer/token.c | 29 ++++++ src/main.c | 24 ++++- src/ms_glob.c | 162 +++++++++++++++++++++++++++++++++ src/parse/parse.c | 12 ++- src/preprocess.c | 96 +++++++++++++++---- src/utils.c | 4 +- 16 files changed, 341 insertions(+), 201 deletions(-) create mode 100644 print_argv_env_main.c delete mode 100644 src/.DS_Store delete mode 100644 src/glob.c create mode 100644 src/lexer/token.c create mode 100644 src/ms_glob.c diff --git a/.gitignore b/.gitignore index a4a5b81..8fa34d8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ minishell tags doc/* tmp/* +.DS_Store +a.out diff --git a/include/ast.h b/include/ast.h index 1dd28a1..e63ab22 100644 --- a/include/ast.h +++ b/include/ast.h @@ -6,7 +6,7 @@ /* By: charles +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:05:38 by charles #+# #+# */ -/* Updated: 2020/05/14 23:54:46 by charles ### ########.fr */ +/* Updated: 2020/06/09 11:44:45 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -66,9 +66,9 @@ typedef struct s_line typedef struct s_cmd { - char **argv; - char *in; - char *out; + char **argv; // change to t_ftvec of t_token + char *in; // change to t_token + char *out; // change to t_token bool is_append; } t_cmd; diff --git a/include/lexer.h b/include/lexer.h index e7a6cdf..e20e0e7 100644 --- a/include/lexer.h +++ b/include/lexer.h @@ -1,6 +1,23 @@ - #include "minishell.h" +// just to make iterpolation compile +////////////////////////////////////// +enum e_token_tag +{ + LTAG_STR, + LTAG_STR_SINGLE, + LTAG_STR_DOUBLE, +}; + +typedef struct +{ + enum e_token_tag tag; + char *content; +} t_token; + +t_token *token_new(enum e_token_tag tag, char *content); +////////////////////////////////////// + char **lexer(char *input); int lexer_sep(char input); int lexer_verif_entre_cote(char *input, int i); diff --git a/include/minishell.h b/include/minishell.h index 9551c1f..76e4f7a 100644 --- a/include/minishell.h +++ b/include/minishell.h @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/26 15:33:51 by cacharle #+# #+# */ -/* Updated: 2020/04/05 14:52:20 by charles ### ########.fr */ +/* Updated: 2020/06/09 14:05:36 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -110,5 +110,6 @@ int builtin_exit(char **argv, t_env env); */ char *preprocess(char *input, t_env env); +char **preprocess_argv(t_ftvec *argv, t_env env); #endif diff --git a/libft b/libft index 8b8b8b8..f1babc3 160000 --- a/libft +++ b/libft @@ -1 +1 @@ -Subproject commit 8b8b8b8a35524f0ee73ac74c947a325ea54b2880 +Subproject commit f1babc364b2507cb8999d3132941b056feac37cd diff --git a/print_argv_env_main.c b/print_argv_env_main.c new file mode 100644 index 0000000..dcc6e0e --- /dev/null +++ b/print_argv_env_main.c @@ -0,0 +1,12 @@ +#include + +int main(int argc, char **argv, char **envp) +{ + printf("ARGV:\n"); + for (int i = 0; i < argc; i++) + printf("[%d] %s\n", i, argv[i]); + printf("\nENV:\n"); + for (int i = 0; envp[i] != NULL && i < 10; i++) + printf("[%d] %s\n", i, envp[i]); + return 0; +} diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index cd95961..0000000 Binary files a/src/.DS_Store and /dev/null differ diff --git a/src/env.c b/src/env.c index fcee163..326caa9 100644 --- a/src/env.c +++ b/src/env.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/28 09:21:24 by cacharle #+# #+# */ -/* Updated: 2020/05/08 13:48:40 by charles ### ########.fr */ +/* Updated: 2020/06/09 16:15:47 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -75,8 +75,10 @@ char *env_search_first_match(t_env env, const char *haystack) len = 0; while (ft_isalnum(haystack[len]) || haystack[len] == '_') len++; + if (len == 0) + return ("$"); i = 0; - while (i < env->size) + while (i < env->size - 1) { if (ft_strncmp((char*)env->data[i], haystack, len) == 0) return (ft_strchr((char*)env->data[i], '=') + 1); diff --git a/src/glob.c b/src/glob.c deleted file mode 100644 index 2d544da..0000000 --- a/src/glob.c +++ /dev/null @@ -1,162 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* glob.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: charles +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2020/04/05 11:44:07 by charles #+# #+# */ -/* Updated: 2020/04/05 13:21:25 by charles ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "ms_glob.h" - -/* -** \brief Match vector start size -** \note From ~: average file in directory is 8 -** From /: average file in directory is 15 -*/ - -#define MATCHES_VEC_START_SIZE 16 - -/* -** \brief Glob directory iteration function -** for subdirectory matches -** \param dirname Current directory name -** \param entry Current directory entry -** \param param Contain matches vector and pattern to match -** \param subdir_pattern Pattern left after '/' in parrent pattern -** \return 0 on success, -1 on error -*/ - -static int glob_iter_subdir( - char *dirname, - struct dirent *entry, - struct s_glob_param *param, - char *subdir_pattern -) -{ - char subdir_name[PATH_MAX]; - t_ftvec *subdir_matches; - size_t i; - - ft_strcat3(ft_strcpy(subdir_name, dirname), "/", entry->d_name); - chdir(subdir_name); - subdir_matches = glob_matches(subdir_pattern); - chdir(dirname); - if (subdir_matches == NULL) - return (-1); - i = 0; - while (i < subdir_matches->size) - if (ft_vecpush_safe(param->matches, ft_strjoin3(entry->d_name, - "/", subdir_matches->data[i++])) == NULL) - { - ft_vecdestroy(subdir_matches, free); - return (-1); - } - ft_vecdestroy(subdir_matches, free); - subdir_pattern[-1] = '/'; - return (0); -} - -/* -** \brief Glob directory iteration function -** \param dirname Current directory name -** \param entry Current directory entry -** \param param Contain matches vector and pattern to match -** \return 0 on success or -1 on error -*/ - -static int glob_iter( - char *dirname, - struct dirent *entry, - struct s_glob_param *param -) -{ - char *subdir_pattern; - - if (param->pattern[0] != '.' && entry->d_name[0] == '.') - return (0); - if ((subdir_pattern = ft_strchr(param->pattern, '/')) != NULL) - *subdir_pattern++ = '\0'; - if (!ft_fnmatch(param->pattern, entry->d_name)) - { - if (subdir_pattern != NULL) - subdir_pattern[-1] = '/'; - return (0); - } - if (subdir_pattern != NULL) - { - if (entry->d_type != DT_DIR) - { - subdir_pattern[-1] = '/'; - return (0); - } - return (glob_iter_subdir(dirname, entry, param, subdir_pattern)); - } - if (ft_vecpush_safe(param->matches, ft_strdup(entry->d_name)) == NULL) - return (-1); - return (0); -} - -/* -** \brief Fill a vector with all match -** \param pattern Pattern to match -** \return Matches vector or NULL on error -*/ - -t_ftvec *glob_matches(char *pattern) -{ - char dirname[PATH_MAX]; - struct s_glob_param param; - - if (getcwd(dirname, PATH_MAX) == NULL) - return (NULL); - if ((param.pattern = ft_strdup(pattern)) == NULL || - (param.matches = ft_vecnew(MATCHES_VEC_START_SIZE)) == NULL) - { - free(param.pattern); - return (NULL); - } - if (utils_directory_iter(dirname, ¶m, - (t_directory_iter_func)glob_iter) == -1) - { - free(param.pattern); - ft_vecdestroy(param.matches, free); - return (NULL); - } - free(param.pattern); - return (param.matches); -} - -/* -** \brief Search files which match a pattern in the current directory -** \param pattern Pattern to match -** \return Space separated list of match, -** pattern if no match found, -** NULL on error -*/ - -char *ms_glob(char *pattern) -{ - char *join; - t_ftvec *matches; - - if ((matches = glob_matches(pattern)) == NULL) - return (NULL); - ft_vecsort(matches, ft_compar_str); - if (ft_vecpush(matches, NULL) == NULL || - (join = ft_strsjoin((char**)matches->data, "\n")) == NULL) - { - ft_vecdestroy(matches, free); - return (NULL); - } - ft_vecdestroy(matches, free); - if (*join == '\0') - { - free(join); - return (ft_strdup(pattern)); - } - return (join); -} diff --git a/src/lexer/lexer_len_element_and_mall.c b/src/lexer/lexer_len_element_and_mall.c index 30ebc7b..e0e1132 100644 --- a/src/lexer/lexer_len_element_and_mall.c +++ b/src/lexer/lexer_len_element_and_mall.c @@ -38,6 +38,7 @@ char **lexer_malloc_len_elem(char *input, int i, char **out) int k = 0; int temp = 0; + (void)i; j += lexer_count_len_element(&input[j], 0); k = j; out[temp] = malloc(sizeof(char) * k); diff --git a/src/lexer/token.c b/src/lexer/token.c new file mode 100644 index 0000000..bf534a4 --- /dev/null +++ b/src/lexer/token.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* token.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: charles +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/06/09 13:38:08 by charles #+# #+# */ +/* Updated: 2020/06/09 13:39:27 by charles ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "lexer.h" + +t_token *token_new(enum e_token_tag tag, char *content) +{ + t_token *token; + + if (content == NULL + || (token = malloc(sizeof(t_token))) == NULL) + return (NULL); + if ((token->content = ft_strdup(content)) == NULL) + { + free(token); + return (NULL); + } + token->tag = tag; + return token; +} diff --git a/src/main.c b/src/main.c index d9302ad..802d3d2 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/28 11:45:44 by cacharle #+# #+# */ -/* Updated: 2020/04/05 12:15:57 by charles ### ########.fr */ +/* Updated: 2020/06/09 16:53:45 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,6 +19,7 @@ #include "ast.h" #include "eval.h" #include "ms_glob.h" +#include "lexer.h" /* ** \brief Program entrypoint @@ -88,9 +89,24 @@ int main(int argc, char **argv, char **envp) /* free(line); */ /* ft_htdestroy(path, free); */ /* ms_glob("src#<{(|"); */ - char *j = ms_glob("*/*.c"); - printf("%s\n", j); - free(j); + + /* char *j = ms_glob("|)}>#*.c"); */ + /* printf("%s\n", j); */ + /* free(j); */ + + t_ftvec *v = ft_vecnew(32); + /* ft_vecpush(v, token_new(LTAG_STR, "$TERM$LFS$TERM$TERM.")); */ + /* ft_vecpush(v, token_new(LTAG_STR, "$$LFS$TERM$TERM.")); */ + ft_vecpush(v, token_new(LTAG_STR, "*/*.c$TERM")); + /* ft_vecpush(v, token_new(LTAG_STR, "src#<{(|.c include#<{(|.h")); */ + /* ft_vecpush(v, token_new(LTAG_STR, "$A$B")); */ + char **as = preprocess_argv(v, env); + char **tmp = as; + + while (*as != NULL) + puts(*as++); + + ft_split_destroy(tmp); ft_vecdestroy(env, free); return (0); } diff --git a/src/ms_glob.c b/src/ms_glob.c new file mode 100644 index 0000000..2ab62a3 --- /dev/null +++ b/src/ms_glob.c @@ -0,0 +1,162 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ms_glob.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: charles +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/04/05 11:44:07 by charles #+# #+# */ +/* Updated: 2020/06/09 16:20:22 by charles ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ms_glob.h" + +/* +** \brief Match vector start size +** \note From ~: average file in directory is 8 +** From /: average file in directory is 15 +*/ + +#define MATCHES_VEC_START_SIZE 16 + +/* +** \brief Glob directory iteration function +** for subdirectory matches +** \param dirname Current directory name +** \param entry Current directory entry +** \param param Contain matches vector and pattern to match +** \param subdir_pattern Pattern left after '/' in parrent pattern +** \return 0 on success, -1 on error +*/ + +static int glob_iter_subdir( + char *dirname, + struct dirent *entry, + struct s_glob_param *param, + char *subdir_pattern +) +{ + char subdir_name[PATH_MAX]; + t_ftvec *subdir_matches; + size_t i; + + ft_strcat3(ft_strcpy(subdir_name, dirname), "/", entry->d_name); + chdir(subdir_name); + subdir_matches = glob_matches(subdir_pattern); + chdir(dirname); + if (subdir_matches == NULL) + return (-1); + i = 0; + while (i < subdir_matches->size) + if (ft_vecpush_safe(param->matches, ft_strjoin3(entry->d_name, + "/", subdir_matches->data[i++])) == NULL) + { + ft_vecdestroy(subdir_matches, free); + return (-1); + } + ft_vecdestroy(subdir_matches, free); + subdir_pattern[-1] = '/'; + return (0); +} + +/* +** \brief Glob directory iteration function +** \param dirname Current directory name +** \param entry Current directory entry +** \param param Contain matches vector and pattern to match +** \return 0 on success or -1 on error +*/ + +static int glob_iter( + char *dirname, + struct dirent *entry, + struct s_glob_param *param +) +{ + char *subdir_pattern; + + if (param->pattern[0] != '.' && entry->d_name[0] == '.') + return (0); + if ((subdir_pattern = ft_strchr(param->pattern, '/')) != NULL) + *subdir_pattern++ = '\0'; + if (!ft_fnmatch(param->pattern, entry->d_name)) + { + if (subdir_pattern != NULL) + subdir_pattern[-1] = '/'; + return (0); + } + if (subdir_pattern != NULL) + { + if (entry->d_type != DT_DIR) + { + subdir_pattern[-1] = '/'; + return (0); + } + return (glob_iter_subdir(dirname, entry, param, subdir_pattern)); + } + if (ft_vecpush_safe(param->matches, ft_strdup(entry->d_name)) == NULL) + return (-1); + return (0); +} + +/* +** \brief Fill a vector with all match +** \param pattern Pattern to match +** \return Matches vector or NULL on error +*/ + +t_ftvec *glob_matches(char *pattern) +{ + char dirname[PATH_MAX]; + struct s_glob_param param; + + if (getcwd(dirname, PATH_MAX) == NULL) + return (NULL); + if ((param.pattern = ft_strdup(pattern)) == NULL || + (param.matches = ft_vecnew(MATCHES_VEC_START_SIZE)) == NULL) + { + free(param.pattern); + return (NULL); + } + if (utils_directory_iter(dirname, ¶m, + (t_directory_iter_func)glob_iter) == -1) + { + free(param.pattern); + ft_vecdestroy(param.matches, free); + return (NULL); + } + free(param.pattern); + return (param.matches); +} + +/* +** \brief Search files which match a pattern in the current directory +** \param pattern Pattern to match +** \return Space separated list of match, +** pattern if no match found, +** NULL on error +*/ + +char *ms_glob(char *pattern) +{ + char *join; + t_ftvec *matches; + + if ((matches = glob_matches(pattern)) == NULL) + return (NULL); + ft_vecsort(matches, ft_compar_str); + if (ft_vecpush(matches, NULL) == NULL || + (join = ft_strsjoin((char**)matches->data, " ")) == NULL) + { + ft_vecdestroy(matches, free); + return (NULL); + } + ft_vecdestroy(matches, free); + if (*join == '\0') + { + free(join); + return (ft_strdup(pattern)); + } + return (join); +} diff --git a/src/parse/parse.c b/src/parse/parse.c index 4c8d279..a0da5d9 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -7,10 +7,12 @@ t_ast *parse(char **input) { - int i = 0; + /* int i = 0; */ - while (input[i] != '\0') - { - - } + (void)input; + /* while (input[i] != '\0') */ + /* { */ + /* */ + /* } */ + return NULL; } diff --git a/src/preprocess.c b/src/preprocess.c index c30bb70..0d72a2c 100644 --- a/src/preprocess.c +++ b/src/preprocess.c @@ -6,12 +6,13 @@ /* By: charles +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/03 08:58:49 by charles #+# #+# */ -/* Updated: 2020/04/05 15:04:06 by charles ### ########.fr */ +/* Updated: 2020/06/09 17:03:37 by charles ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" #include "ms_glob.h" +#include "lexer.h" static char *iterpolate(char *str, t_env env) { @@ -28,11 +29,18 @@ static char *iterpolate(char *str, t_env env) if (dstr->str[i] == '$') { if ((match = env_search_first_match(env, dstr->str + i + 1)) == NULL) + { ft_dstrerase(dstr, i, utils_var_end(dstr->str + i + 1)); + i--; + } else { if (ft_dstrsubstitute(dstr, match, i, utils_var_end(dstr->str + i + 1)) == NULL) + { + ft_dstrdestroy(dstr); return (NULL); + } + i += ft_strlen(match) - 1; } } i++; @@ -40,30 +48,80 @@ static char *iterpolate(char *str, t_env env) return (ft_dstrunwrap(dstr)); } -static char *preprocess_arg(char *arg, t_env env) +static char *iterpolate_globs(char *str) +{ + char **strs; + int i; + + if ((strs = ft_split(str, ' ')) == NULL) + return (NULL); + i = 0; + while (strs[i] != NULL) + { + if (ft_strchr(strs[i], '*') != NULL + && (strs[i] = ms_glob(strs[i])) == NULL) + { + ft_split_destroy(strs); + return (NULL); + } + i++; + } + return (ft_strsjoinf(strs, " ")); +} + +static int splat_arg(t_ftvec *argv, int i) { - if (*arg == '\'') - return (ft_strsubf(arg, 1, ft_strlen(arg) - 1)); - if (*arg == '"') + t_token *splated; + char **strs; + int j; + + if ((splated = ft_vectake(argv, i)) == NULL + || (strs = ft_split(splated->content, ' ')) == NULL) + return (-1); + j = 0; + while (strs[j] != NULL) { - if (ft_strchr(arg, '$') != NULL) - arg = iterpolate(arg, env); - return (ft_strsubf(arg, 1, ft_strlen(arg) - 1)); + if (ft_vecinsert_safe(argv, i + j, token_new(LTAG_STR, strs[j])) == NULL) + { + ft_split_destroy(strs); + return (-1); + } + j++; } - if (ft_strchr(arg, '$') != NULL) - return (iterpolate(arg, env)); - if (ft_strchr(arg, '*') != NULL) - return (ms_glob(arg)); - return (arg); + ft_split_destroy(strs); + return i + j - 1; } -char **preprocess_argv(char **argv, t_env env) +void iter_func_unwrap_token(void **addr) { - int i; + char *content; + + content = (*(t_token**)addr)->content; + free(*(t_token**)addr); + *(char**)addr = content; +} + +char **preprocess_argv(t_ftvec *argv, t_env env) +{ + size_t i; + t_token *token; i = -1; - while (argv[++i] != NULL) - if ((argv[i] = preprocess_arg(argv[i], env)) == NULL) - return (NULL); - return (argv); + while (++i < argv->size) + { + token = argv->data[i]; + if (token->tag == LTAG_STR_SINGLE) + continue ; + token->content = iterpolate(token->content, env); + if (token->tag == LTAG_STR) + { + if (ft_strchr(token->content, '*') != NULL) + token->content = iterpolate_globs(token->content); + if ((i = splat_arg(argv, i)) == (size_t)-1) + return (NULL); + } + } + ft_veciter_addr(argv, iter_func_unwrap_token); + ft_vecpush(argv, NULL); + return ((char**)ft_vecunwrap(argv)); } diff --git a/src/utils.c b/src/utils.c index dd89457..3449c25 100644 --- a/src/utils.c +++ b/src/utils.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/28 11:56:31 by cacharle #+# #+# */ -/* Updated: 2020/04/05 14:51:52 by charles ### ########.fr */ +/* Updated: 2020/06/09 15:49:39 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -59,5 +59,5 @@ size_t utils_var_end(char *name) i = 0; while (ft_isalnum(name[i]) || name[i] == '_') i++; - return (i); + return (i + 1); } -- cgit