aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/minishell.h14
-rw-r--r--include/ms_glob.h32
-rw-r--r--include/utils.h31
m---------libft0
-rw-r--r--src/env.c9
-rw-r--r--src/glob.c162
-rw-r--r--src/main.c5
-rw-r--r--src/path.c3
-rw-r--r--src/preprocess.c191
-rw-r--r--src/utils.c26
10 files changed, 299 insertions, 174 deletions
diff --git a/include/minishell.h b/include/minishell.h
index ed332c4..9551c1f 100644
--- a/include/minishell.h
+++ b/include/minishell.h
@@ -6,7 +6,7 @@
/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2020/02/26 15:33:51 by cacharle #+# #+# */
-/* Updated: 2020/04/04 14:50:21 by charles ### ########.fr */
+/* Updated: 2020/04/05 14:52:20 by charles ### ########.fr */
/* */
/* ************************************************************************** */
@@ -71,6 +71,7 @@ t_path path_update(t_path path, char *path_var);
t_env env_from_array(char **envp);
char *env_search(t_env env, char *key);
+char *env_search_first_match(t_env env, const char *haystack);
/*
** builtin*.c - directory with all builtin commands
@@ -108,17 +109,6 @@ int builtin_exit(char **argv, t_env env);
** preprocess.c
*/
-char *ms_glob(char *pattern);
char *preprocess(char *input, t_env env);
-/*
-** util.c - various utilitary functions
-*/
-
-int utils_directory_iter(
- char *dirname,
- void *param,
- int (*f)(char*, struct dirent*, void*)
- );
-
#endif
diff --git a/include/ms_glob.h b/include/ms_glob.h
new file mode 100644
index 0000000..774d3be
--- /dev/null
+++ b/include/ms_glob.h
@@ -0,0 +1,32 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ms_glob.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2020/04/05 11:45:11 by charles #+# #+# */
+/* Updated: 2020/04/05 13:05:10 by charles ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#ifndef MS_GLOB_H
+# define MS_GLOB_H
+
+# include <dirent.h>
+# include <unistd.h>
+# include <stddef.h>
+# include "libft_str.h"
+# include "libft_vec.h"
+# include "utils.h"
+
+struct s_glob_param
+{
+ char *pattern;
+ t_ftvec *matches;
+};
+
+t_ftvec *glob_matches(char *pattern);
+char *ms_glob(char *pattern);
+
+#endif
diff --git a/include/utils.h b/include/utils.h
new file mode 100644
index 0000000..6f2fbc9
--- /dev/null
+++ b/include/utils.h
@@ -0,0 +1,31 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* utils.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2020/04/05 12:05:49 by charles #+# #+# */
+/* Updated: 2020/04/05 14:51:38 by charles ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#ifndef UTILS_H
+# define UTILS_H
+
+/*
+** \file utils.h
+** \brief Various utilitary functions
+*/
+
+typedef int (*t_directory_iter_func)(char*, struct dirent*, void*);
+
+int utils_directory_iter(
+ char *dirname,
+ void *param,
+ t_directory_iter_func f
+);
+
+size_t utils_var_end(char *name);
+
+#endif
diff --git a/libft b/libft
-Subproject 51b845a6a202b50966f50e166cfb11bcbdccbe3
+Subproject 3a2d19df9e509d0b015c786eb02f8315ff0ad91
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 <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <charles.cabergs@gmail.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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, &param,
+ (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 <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <charles.cabergs@gmail.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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, &param, 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 <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
+}