From 4aeba6d2f03706fa21281709a138a7d3ea9797dc Mon Sep 17 00:00:00 2001 From: Charles Date: Sun, 5 Apr 2020 15:04:23 +0200 Subject: Preprocessing (glob and iterpolation) draft (not tested) --- src/env.c | 9 ++- src/glob.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 5 +- src/path.c | 3 +- src/preprocess.c | 191 +++++++++++-------------------------------------------- src/utils.c | 26 +++++++- 6 files changed, 234 insertions(+), 162 deletions(-) create mode 100644 src/glob.c (limited to 'src') diff --git a/src/env.c b/src/env.c index f00d046..41aca6d 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/04/04 13:33:42 by charles ### ########.fr */ +/* Updated: 2020/04/05 14:42:38 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -50,6 +50,7 @@ t_env env_from_array(char **envp) ** \return Value after '=' in environment variable array or NULL if not found */ +// could be a wrapper around ft_lfind char *env_search(t_env env, char *key) { size_t i; @@ -64,12 +65,14 @@ char *env_search(t_env env, char *key) return (NULL); } -char *env_match_first(t_env env, const char *haystack) +char *env_search_first_match(t_env env, const char *haystack) { int len; size_t i; - len = -1; + if (ft_isdigit(*haystack)) + return (NULL); + len = 0; while (ft_isalnum(haystack[len]) || haystack[len] == '_') len++; while (i < env->size) diff --git a/src/glob.c b/src/glob.c new file mode 100644 index 0000000..2d544da --- /dev/null +++ b/src/glob.c @@ -0,0 +1,162 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* 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/main.c b/src/main.c index f897faa..d9302ad 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/04 18:37:03 by charles ### ########.fr */ +/* Updated: 2020/04/05 12:15:57 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,6 +18,7 @@ #include "minishell.h" #include "ast.h" #include "eval.h" +#include "ms_glob.h" /* ** \brief Program entrypoint @@ -87,7 +88,7 @@ int main(int argc, char **argv, char **envp) /* free(line); */ /* ft_htdestroy(path, free); */ /* ms_glob("src#<{(|"); */ - char *j = ms_glob("*/"); + char *j = ms_glob("*/*.c"); printf("%s\n", j); free(j); ft_vecdestroy(env, free); diff --git a/src/path.c b/src/path.c index c9f184c..d768d07 100644 --- a/src/path.c +++ b/src/path.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/27 15:51:01 by cacharle #+# #+# */ -/* Updated: 2020/04/03 13:53:01 by charles ### ########.fr */ +/* Updated: 2020/04/05 12:09:05 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,7 @@ */ #include "minishell.h" +#include "utils.h" /* ** \brief Number of buckets of a path hash table diff --git a/src/preprocess.c b/src/preprocess.c index 6dbc386..1151bca 100644 --- a/src/preprocess.c +++ b/src/preprocess.c @@ -6,179 +6,64 @@ /* By: charles +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/03 08:58:49 by charles #+# #+# */ -/* Updated: 2020/04/04 18:30:10 by charles ### ########.fr */ +/* Updated: 2020/04/05 14:58:00 by charles ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" +#include "ms_glob.h" -// 8 en moyenne -#define MATCHES_VEC_DEFAULT_SIZE 32 - -struct s_glob_param -{ - char *pattern; - t_ftvec *matches; -}; - -t_ftvec *glob_matches(char *pattern); - - -int glob_iter(char *dirname, struct dirent *entry, void *void_param) +static char *iterpolate(char *str, t_env env) { - struct s_glob_param *param; - char *subdir_pattern; - char *subdir_name; - t_ftvec *subdir_matches; + size_t i; + t_ftdstr *dstr; + char *match; - param = void_param; - /* printf("DIR: %15s %d\n", entry->d_name, entry->d_type == DT_DIR); */ - if (param->pattern[0] != '.' && entry->d_name[0] == '.') - return (0); - if ((subdir_pattern = ft_strchr(param->pattern, '/')) != NULL) - { - *subdir_pattern = '\0'; - subdir_pattern++; - } - if (!ft_fnmatch(param->pattern, entry->d_name)) - { - if (subdir_pattern != NULL) - subdir_pattern[-1] = '/'; - return (0); - } - if (subdir_pattern != NULL) + if ((dstr = ft_dstrnew(str)) == NULL) + return (NULL); + free(str); + i = 0; + while (i < dstr->length) { - if (entry->d_type != DT_DIR) - { - if (ft_vecpush_safe(param->matches, ft_strdup(entry->d_name)) == NULL) - return (-1); - subdir_pattern[-1] = '/'; - return (0); - } - - if ((subdir_name = ft_strjoin3(dirname, "/", entry->d_name)) == NULL) - return (-1); - chdir(subdir_name); - free(subdir_name); - subdir_matches = glob_matches(subdir_pattern); - chdir(dirname); - if (subdir_matches == NULL) - return (-1); - for (size_t i = 0; i < subdir_matches->size; i++) + if (dstr->str[i] == '$') { - if (ft_vecpush_safe(param->matches, - ft_strjoin3(entry->d_name, "/", subdir_matches->data[i])) == NULL) + if ((match = env_search_first_match(env, dstr->str + i + 1)) == NULL) + ft_dstrerase(dstr, i, utils_var_end(dstr->str + i + 1)); + else { - ft_vecdestroy(subdir_matches, free); - return (-1); + if (ft_dstrsubstitute(dstr, match, i, utils_var_end(dstr->str + i + 1)) == NULL) + return (NULL); } } - ft_vecdestroy(subdir_matches, free); - subdir_pattern[-1] = '/'; - } - else - { - if (ft_vecpush_safe(param->matches, ft_strdup(entry->d_name)) == NULL) - return (-1); + i++; } - return (0); + return (ft_dstrunwrap(dstr)); } -t_ftvec *glob_matches(char *pattern) +static char *preprocess_arg(char *arg, t_env env) { - 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_DEFAULT_SIZE)) == NULL) - { - free(param.pattern); - return (NULL); - } - if (utils_directory_iter(dirname, ¶m, glob_iter) == -1) + if (*arg == '\'') + return (ft_strsubf(arg, 1, ft_strlen(arg) - 1)); + if (*arg == '"') { - free(param.pattern); - ft_vecdestroy(param.matches, free); - return (NULL); + if (ft_strchr(arg, '$') != NULL) + arg = iterpolate(arg, env); + return (ft_strsubf(arg, 1, ft_strlen(arg) - 1)); } - free(param.pattern); - return (param.matches); + if (ft_strchr(arg, '$') != NULL) + return (iterpolate(arg, env)); + if (ft_strchr(arg, '*') != NULL) + return (ms_glob(arg)); + return (arg); } -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); - return (join); -} - -/* void iterpolate_iter_f(char **curr) */ -/* { */ -/* if (*curr != '$') */ -/* return (i + 1); */ -/* } */ - - -char *preprocess(char *input, t_env env) +char **preprocess_argv(char **argv, t_env env) { - /* int i; */ - /* t_ftdstr *input_dstr; */ - /* char *glob_str; */ - /* char *tmp; */ + int i; - (void)input; - (void)env; - /* glob_str = NULL; */ - /* if ((input_dstr = ft_dstrnew(input)) == NULL) */ - /* return (NULL); */ - /* i = 0; */ - /* while (input_dstr->str[i] != '\0') */ - /* { */ - /* if (input_dstr->str[i] == '*') */ - /* { */ - /* free(glob_str); */ - /* if ((glob_str = ms_glob()) = NULL) */ - /* { */ - /* ft_dstrdestroy(input_str); */ - /* return (NULL); */ - /* } */ - /* if (ft_dstrinsert(input_dstr, glob_str, 0) == NULL) */ - /* { */ - /* free(glob_str); */ - /* ft_dstrdestroy(input_dstr); */ - /* return (NULL); */ - /* } */ - /* i += strlen(glob_str); */ - /* } */ - /* else if (input_dstr->str[i] == '$') */ - /* { */ - /* if ((tmp = env_match_first(env, input_dstr->str + i + 1)) == NULL) */ - /* tmp = ""; */ - /* if (ft_dstrreplace(input_dstr, tmp, i, i + ft_strlen(tmp)) == NULL) */ - /* { */ - /* free(glob_str); */ - /* ft_dstrdestroy(input_dstr); */ - /* return (NULL); */ - /* } */ - /* i += ft_strlen(tmp); */ - /* } */ - /* else */ - /* i++; */ - /* } */ - /* printf("%d %d %s\n", input_dstr->length, input_dstr->capacity, input_dstr->str); */ - /* return (ft_dstrunwrap(input_dstr)); */ - return NULL; + i = -1; + while (argv[++i] != NULL) + if ((argv[i] = preprocess_arg(argv[i], env)) == NULL) + return (NULL); + return (argv); } diff --git a/src/utils.c b/src/utils.c index 9ef99a6..dd89457 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/03 14:58:17 by charles ### ########.fr */ +/* Updated: 2020/04/05 14:51:52 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -37,7 +37,27 @@ int utils_directory_iter( if (closedir(dir) == -1) return (-1); return (0); - } -/* int utils_not_alnum */ +/* bool utils_is_var_name(char *name) */ +/* { */ +/* if (!(ft_isalpha(*name) || *name == '_')) */ +/* return (false); */ +/* name++; */ +/* while (*name != '\0) */ +/* if (!(ft_isalnum(*name) || *name == '_')) */ +/* return (false); */ +/* return (true); */ +/* } */ + +size_t utils_var_end(char *name) +{ + size_t i; + + if (ft_isdigit(*name)) + return (0); + i = 0; + while (ft_isalnum(name[i]) || name[i] == '_') + i++; + return (i); +} -- cgit