mirror of
https://codeberg.org/la-chouette/minishell.git
synced 2025-12-06 07:28:09 +01:00
Expansion: fix: algo was wrong for wildcard
Hopefully, this is a proper fix. This commit serves mainly to save advancement.
This commit is contained in:
parent
1766e8d1ba
commit
fc12d8e057
5 changed files with 129 additions and 81 deletions
|
|
@ -6,7 +6,7 @@
|
|||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
|||
38
src/subst/wildcard_exp_utils2.c
Normal file
38
src/subst/wildcard_exp_utils2.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* wildcard_exp_utils2.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: jguelen <marvin@42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue