mirror of
https://codeberg.org/la-chouette/minishell.git
synced 2025-12-06 07:28:09 +01:00
150 lines
4.7 KiB
C
150 lines
4.7 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* wildcard_exp_utils.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2025/03/07 17:10:01 by jguelen #+# #+# */
|
|
/* Updated: 2025/03/10 17:22:00 by jguelen ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include "subst.h"
|
|
|
|
/*
|
|
** Cleanly disposes of a pattern checker two dimensionnal array.
|
|
*/
|
|
static void destroy_pattern_check(char **pattern_check, size_t len)
|
|
{
|
|
size_t i;
|
|
|
|
i = 0;
|
|
while (i < len)
|
|
{
|
|
free(pattern_check[i]);
|
|
i++;
|
|
}
|
|
free(pattern_check);
|
|
}
|
|
|
|
/*
|
|
** Returns 1 if the currently examined characters in str and pattern can match
|
|
** allowing to preserve the validity of previous matches one "character" behind
|
|
** in both strings.
|
|
** i.e. serves to detect when the currently examined character of str in index i
|
|
** and the current character of pattern match exactly or the character in
|
|
** pattern under scrutiny is an unquoted '?'. There is one exception to wit
|
|
** the character '.' can only be matched exactly if it is the first character of
|
|
** both str and pattern and explicitly given. That is in this case ? cannot
|
|
** match it even if it can under all other circumstance.
|
|
*/
|
|
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] == '.')));
|
|
}
|
|
|
|
/*
|
|
** Fills the table which contains in its most low and right cell 0 if
|
|
** str does not match the pattern and 1 otherwise.
|
|
** This construction is only done for the current diectory so no special
|
|
** treatment is to be considered for '/' characters which otherwise have
|
|
** to be matched explicitely. We do however consider the case where the '.'
|
|
** character cannot be matched unless explicitely when in first position
|
|
** in str.
|
|
*/
|
|
void build_pattern_checks(char *str, t_worddesc *pattern,
|
|
char **pattern_check)
|
|
{
|
|
size_t i;
|
|
size_t j;
|
|
size_t str_len;
|
|
size_t pattern_len;
|
|
|
|
i = 1;
|
|
str_len = ft_strlen(str);
|
|
pattern_len = ft_strlen(pattern->word);
|
|
pattern_check[0][0] = 1;
|
|
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]);
|
|
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);
|
|
}
|