diff --git a/Makefile b/Makefile index 931d191..6f7a094 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,8 @@ srcs = \ src/parser/wordlist/wordlist_copy.c \ src/parser/wordlist/wordlist_debug.c \ src/parser/wordlist/wordlist_idx.c \ + src/parser/wordlist/wordlist_quicksort.c \ + src/parser/wordlist/wordlist_utils.c \ src/parser/wordsplit/rule_utils.c \ src/parser/wordsplit/tokenizing_1_5.c \ src/parser/wordsplit/tokenizing_6_10.c \ @@ -59,10 +61,14 @@ srcs = \ src/postprocess/redirections/redirection_list.c \ src/postprocess/redirections/redirection_parsing.c \ src/postprocess/redirections/redirection_type.c \ + src/subst/path_split.c \ src/subst/replace_substr.c \ + src/subst/simple_filename_exp.c \ src/subst/variable_subst.c \ src/subst/variable_subst_utils.c \ src/subst/wildcard_exp.c \ + src/subst/wildcard_exp_utils.c \ + src/subst/wildcard_exp_utils2.c \ objs = $(srcs:.c=.o) export objs diff --git a/src/subst/simple_filename_exp.c b/src/subst/simple_filename_exp.c index 05cd92a..2a4db7a 100644 --- a/src/subst/simple_filename_exp.c +++ b/src/subst/simple_filename_exp.c @@ -6,7 +6,7 @@ /* By: jguelen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/02 13:40:10 by jguelen #+# #+# */ -/* Updated: 2025/03/14 18:46:41 by jguelen ### ########.fr */ +/* Updated: 2025/03/15 11:30:56 by jguelen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -83,7 +83,7 @@ char *filepath_from_env(char *filename, t_minishell *app) while (path[i]) { if (!path[i][0]) - alloc_path(".", filename); + filepath = alloc_path(".", filename); else filepath = alloc_path(path[i], filename); ret = stat(filepath, &file_stat); // Deal with possible failure of stat diff --git a/src/subst/wildcard_exp.c b/src/subst/wildcard_exp.c index 496dc13..50ca165 100644 --- a/src/subst/wildcard_exp.c +++ b/src/subst/wildcard_exp.c @@ -6,7 +6,7 @@ /* By: jguelen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/23 15:02:59 by jguelen #+# #+# */ -/* Updated: 2025/03/14 14:30:30 by jguelen ### ########.fr */ +/* Updated: 2025/03/15 14:45:11 by jguelen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -128,6 +128,41 @@ static t_wordlist *expand_star_core(t_worddesc *file_pattern) return (wordlist_quicksort_full(file_wordlist)); } +/* +** Returns 1 if and only if filename is recognized by pattern, 0 +** otherwise or -1 in case of error. +** Takes only into account the * wildcard or ?, those characters +** NOTE: for a pattern to accept '.' as the first character of a filename +** it must be explicitly matched (only for the first character though). +** Similarly, '/' is never to be matched except if given explicitly. +*/ +char fits_pattern(char *str, t_worddesc *pattern) +{ + char **pattern_check; + size_t str_len; + size_t pattern_len; + size_t i; + char ret; + + pattern_len = ft_strlen(pattern->word); + str_len = ft_strlen(str); + pattern_check = ft_calloc(str_len + 1, sizeof(char *)); + if (!pattern_check) + return (-1); + i = 0; + while (i <= str_len) + { + pattern_check[i] = ft_calloc(pattern_len + 1, sizeof(char)); + if (!pattern_check[i]) + return (destroy_pattern_check(pattern_check, str_len + 1), NULL); + i++; + } + build_pattern_checks(str, pattern, pattern_check); + ret = pattern_check[str_len][pattern_len]; + destroy_pattern_check(pattern_check, str_len + 1); + return (ret); +} + /* ** TODO ** Pre-processes file_pattern to give it a proper marker chain and remove diff --git a/src/subst/wildcard_exp_utils.c b/src/subst/wildcard_exp_utils.c index ce4fded..fa03dea 100644 --- a/src/subst/wildcard_exp_utils.c +++ b/src/subst/wildcard_exp_utils.c @@ -6,7 +6,7 @@ /* By: jguelen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/07 17:10:01 by jguelen #+# #+# */ -/* Updated: 2025/03/14 15:09:36 by jguelen ### ########.fr */ +/* Updated: 2025/03/15 15:33:07 by jguelen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -42,12 +42,45 @@ static void destroy_pattern_check(char **pattern_check, size_t len) static int same_character_or_one_char_wild(char *str, t_worddesc *pattern, size_t i, size_t j) { - return (str[i] == pattern->word[j] - || (pattern->word[j] == '?' - && pattern->marker[j] != '\'' - && pattern->marker != '"' - && pattern->marker != '&' - && !(i == 1 && pattern->word[i] == '.'))); + return (str[i - 1] == pattern->word[j - 1] + || (pattern->word[j - 1] == '?' + && pattern->marker[j - 1] != '\'' + && pattern->marker[j - 1] != '"' + && pattern->marker[j - 1] != '&' + && !(i == 1 && str[i - 1] == '.'))); +} + +/* +** Condition to know if the wildcard '*' can catch something. +*/ +static int at_star_in_pattern(char *str, t_worddesc *pattern, + size_t i, size_t j) +{ + return (pattern->word[j - 1] == '*' + && pattern->marker[j - 1] != '\'' + && pattern->marker[j - 1] != '"' + && pattern->marker[j - 1] != '&' + && !(i == 1 && str[i - 1] == '.')); +} + +/* +** Sets true where the pattern would match an empty string (the most basic +** prefix of str). +*/ +static void init_pattern_checker(t_worddesc *pattern, char **checker) +{ + size_t i; + + checker[0][0] = 1; + i = 0; + while (pattern->word[i] == '*' + && pattern->marker[i] != '\'' + && pattern->marker[i] != '"' + && pattern->marker[i] != '&') + { + checker[0][i + 1] = 1; + i++; + } } /* @@ -58,11 +91,9 @@ static int same_character_or_one_char_wild(char *str, t_worddesc *pattern, ** to be matched explicitely. We do however consider the case where the '.' ** character cannot be matched unless explicitely when in first position ** in str. -** The algorithm is extremely similar to the one presented here: -** https://www.youtube.com/watch?v=3ZDZ-N0EPV0 */ void build_pattern_checks(char *str, t_worddesc *pattern, - char **pattern_check) + char **checker) { size_t i; size_t j; @@ -72,81 +103,19 @@ void build_pattern_checks(char *str, t_worddesc *pattern, i = 1; str_len = ft_strlen(str); pattern_len = ft_strlen(pattern->word); - pattern_check[0][0] = 1; + init_pattern_checker(pattern, checker); while (i <= str_len) { j = 1; while (j <= pattern_len) { - if (same_character_or_one_char_wild(str, pattern->word, i, j)) - pattern_check[i][j] = pattern_check[i - 1][j - 1]; - else if (pattern->word[j] == '*' && pattern->marker[j] != '\'' - && pattern->marker[j] != '"' && pattern->marker[j] != '&' - && !(i == 1 && pattern->word[i] == '.')) - pattern_check[i][j] = !!(pattern_check[i - 1][j] - + pattern_check[i][j - 1]); + if (same_character_or_one_char_wild(str, pattern, i, j)) + checker[i][j] = checker[i - 1][j - 1]; + else if (at_star_in_pattern(str, pattern, i, j)) + checker[i][j] = !!(checker[i - 1][j] + checker[i][j - 1] + + checker[i - 1][j - 1]); j++; } i++; } } - -/* -** Returns 1 if and only if filename is recognized by pattern, 0 -** otherwise or -1 in case of error. -** Takes only into account the * wildcard or ?, those characters -** NOTE: for a pattern to accept '.' as the first character of a filename -** it must be explicitly matched (only for the first character though). -** Similarly, '/' is never to be matched except if given explicitly. -*/ -char fits_pattern(char *str, t_worddesc *pattern) -{ - char **pattern_check; - size_t str_len; - size_t pattern_len; - size_t i; - char ret; - - pattern_len = ft_strlen(pattern->word); - str_len = ft_strlen(str); - pattern_check = ft_calloc(str_len + 1, sizeof(char *)); - if (!pattern_check) - return (-1); - i = 0; - while (i <= str_len) - { - pattern_check[i] = ft_calloc(pattern_len + 1, sizeof(char)); - if (!pattern_check[i]) - return (destroy_pattern_check(pattern_check, str_len + 1), NULL); - i++; - } - build_pattern_checks(str, pattern, pattern_check); - ret = pattern_check[str_len][pattern_len]; - destroy_pattern_check(pattern_check, str_len + 1); - return (ret); -} - -/* -** Checks if a worddesc is to be considered a pattern as bash would in a -** reduced capacity, to wit if it contains at least one unquoted '?' or '*' -** character. -** Returns 1 if the worddesc pointed to by desc is to be considered a pattern, -** 0 otherwise. -*/ -int ispattern(t_worddesc *desc) -{ - size_t i; - - if (!desc) - return (0); - i = 0; - while (desc->word[i]) - { - if ((desc->word[i] == '*' || desc->word[i] == '?') - && (desc->marker[i] != '\'' && desc->marker[i] != '"' - && desc->marker[i] != '&')) - return (1); - i++; - } - return (0); -} diff --git a/src/subst/wildcard_exp_utils2.c b/src/subst/wildcard_exp_utils2.c new file mode 100644 index 0000000..7eeffad --- /dev/null +++ b/src/subst/wildcard_exp_utils2.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* wildcard_exp_utils2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jguelen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/15 15:09:56 by jguelen #+# #+# */ +/* Updated: 2025/03/15 15:10:30 by jguelen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "subst.h" + +/* +** Checks if a worddesc is to be considered a pattern as bash would in a +** reduced capacity, to wit if it contains at least one unquoted '?' or '*' +** character. +** Returns 1 if the worddesc pointed to by desc is to be considered a pattern, +** 0 otherwise. +*/ +int ispattern(t_worddesc *desc) +{ + size_t i; + + if (!desc) + return (0); + i = 0; + while (desc->word[i]) + { + if ((desc->word[i] == '*' || desc->word[i] == '?') + && (desc->marker[i] != '\'' && desc->marker[i] != '"' + && desc->marker[i] != '&')) + return (1); + i++; + } + return (0); +}