Bash-5.3-alpha release

This commit is contained in:
Chet Ramey
2024-04-22 10:33:38 -04:00
parent f3b6bd1945
commit 622d318652
700 changed files with 136534 additions and 96420 deletions
+1 -5
View File
@@ -1,7 +1,7 @@
/* collsyms.h -- collating symbol names and their corresponding characters
(in ascii) as given by POSIX.2 in table 2.8. */
/* Copyright (C) 1997-2002 Free Software Foundation, Inc.
/* Copyright (C) 1997-2002,2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -38,11 +38,7 @@ static __COLLSYM POSIXCOLL [] =
{ L("EOT"), L('\004') },
{ L("ENQ"), L('\005') },
{ L("ACK"), L('\006') },
#ifdef __STDC__
{ L("alert"), L('\a') },
#else
{ L("alert"), L('\007') },
#endif
{ L("BS"), L('\010') },
{ L("backspace"), L('\b') },
{ L("HT"), L('\011') },
+71 -101
View File
@@ -1,6 +1,6 @@
/* glob.c -- file-name wildcard pattern matching for Bash.
Copyright (C) 1985-2021 Free Software Foundation, Inc.
Copyright (C) 1985-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -60,14 +60,6 @@
# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
#endif /* !HAVE_BCOPY && !bcopy */
#if !defined (NULL)
# if defined (__STDC__)
# define NULL ((void *) 0)
# else
# define NULL 0x0
# endif /* __STDC__ */
#endif /* !NULL */
#if !defined (FREE)
# define FREE(x) if (x) free (x)
#endif
@@ -84,11 +76,11 @@ struct globval
char *name;
};
extern void throw_to_top_level PARAMS((void));
extern int sh_eaccess PARAMS((const char *, int));
extern char *sh_makepath PARAMS((const char *, const char *, int));
extern int signal_is_pending PARAMS((int));
extern void run_pending_traps PARAMS((void));
extern void throw_to_top_level (void);
extern int sh_eaccess (const char *, int);
extern char *sh_makepath (const char *, const char *, int);
extern int signal_is_pending (int);
extern void run_pending_traps (void);
extern int extended_glob;
@@ -111,29 +103,29 @@ char *glob_error_return;
static struct globval finddirs_error_return;
/* Some forward declarations. */
static int skipname PARAMS((char *, char *, int));
static int skipname (char *, char *, int);
#if HANDLE_MULTIBYTE
static int mbskipname PARAMS((char *, char *, int));
static int mbskipname (char *, char *, int);
#endif
void udequote_pathname PARAMS((char *));
void udequote_pathname (char *);
#if HANDLE_MULTIBYTE
void wcdequote_pathname PARAMS((wchar_t *));
static void wdequote_pathname PARAMS((char *));
static void dequote_pathname PARAMS((char *));
void wcdequote_pathname (wchar_t *);
static void wdequote_pathname (char *);
static void dequote_pathname (char *);
#else
# define dequote_pathname(p) udequote_pathname(p)
#endif
static int glob_testdir PARAMS((char *, int));
static char **glob_dir_to_array PARAMS((char *, char **, int));
static int glob_testdir (char *, int);
static char **glob_dir_to_array (char *, char **, int);
/* Make sure these names continue to agree with what's in smatch.c */
extern char *glob_patscan PARAMS((char *, char *, int));
extern wchar_t *glob_patscan_wc PARAMS((wchar_t *, wchar_t *, int));
extern char *glob_patscan (char *, char *, int, int);
extern wchar_t *glob_patscan_wc (wchar_t *, wchar_t *, wint_t, int);
/* And this from gmisc.c/gm_loop.c */
extern int wextglob_pattern_p PARAMS((wchar_t *));
extern int wextglob_pattern_p (wchar_t *);
extern char *glob_dirscan PARAMS((char *, int));
extern char *glob_dirscan (char *, int);
/* Compile `glob_loop.c' for single-byte characters. */
#define GCHAR unsigned char
@@ -158,8 +150,7 @@ extern char *glob_dirscan PARAMS((char *, int));
/* And now a function that calls either the single-byte or multibyte version
of internal_glob_pattern_p. */
int
glob_pattern_p (pattern)
const char *pattern;
glob_pattern_p (const char *pattern)
{
#if HANDLE_MULTIBYTE
size_t n;
@@ -196,9 +187,7 @@ glob_pattern_p (pattern)
that the name should be skipped. XXX - doesn't handle pattern negation,
not sure if it should */
static int
extglob_skipname (pat, dname, flags)
char *pat, *dname;
int flags;
extglob_skipname (char *pat, char *dname, int flags)
{
char *pp, *pe, *t, *se;
int n, r, negate, wild, nullpat, xflags;
@@ -207,7 +196,7 @@ extglob_skipname (pat, dname, flags)
wild = *pat == '*' || *pat == '?';
pp = pat + 2;
se = pp + strlen (pp); /* end of pattern string */
pe = glob_patscan (pp, se, 0); /* end of extglob pattern */
pe = glob_patscan (pp, se, 0, 0); /* end of extglob pattern */
/* if pe == 0, this is an invalid extglob pattern */
if (pe == 0)
@@ -234,7 +223,7 @@ extglob_skipname (pat, dname, flags)
nullpat = pe >= (pat + 2) && pe[-2] == '(' && pe[-1] == ')';
/* check every subpattern */
while (t = glob_patscan (pp, pe, '|'))
while (t = glob_patscan (pp, pe, '|', 0))
{
/* If T == PE and *T == 0 (&& PE[-1] == RPAREN), we have hit the end
of a pattern with no trailing characters. */
@@ -267,13 +256,8 @@ extglob_skipname (pat, dname, flags)
/* Return 1 if DNAME should be skipped according to PAT. Mostly concerned
with matching leading `.'. */
static int
skipname (pat, dname, flags)
char *pat;
char *dname;
int flags;
skipname (char *pat, char *dname, int flags)
{
int i;
#if EXTENDED_GLOB
if (extglob_pattern_p (pat)) /* XXX */
return (extglob_skipname (pat, dname, flags));
@@ -310,12 +294,8 @@ skipname (pat, dname, flags)
#if HANDLE_MULTIBYTE
static int
wskipname (pat, dname, flags)
wchar_t *pat, *dname;
int flags;
wskipname (wchar_t *pat, wchar_t *dname, int flags)
{
int i;
if (glob_always_skip_dot_and_dotdot && WDOT_OR_DOTDOT (dname))
return 1;
@@ -346,9 +326,7 @@ wskipname (pat, dname, flags)
}
static int
wextglob_skipname (pat, dname, flags)
wchar_t *pat, *dname;
int flags;
wextglob_skipname (wchar_t *pat, wchar_t *dname, int flags)
{
#if EXTENDED_GLOB
wchar_t *pp, *pe, *t, *se, n;
@@ -358,7 +336,7 @@ wextglob_skipname (pat, dname, flags)
wild = *pat == L'*' || *pat == L'?';
pp = pat + 2;
se = pp + wcslen (pp);
pe = glob_patscan_wc (pp, se, 0);
pe = glob_patscan_wc (pp, se, 0, 0);
/* if pe == 0, this is an invalid extglob pattern */
if (pe == 0)
@@ -382,7 +360,7 @@ wextglob_skipname (pat, dname, flags)
nullpat = pe >= (pat + 2) && pe[-2] == L'(' && pe[-1] == L')';
/* check every subpattern */
while (t = glob_patscan_wc (pp, pe, '|'))
while (t = glob_patscan_wc (pp, pe, '|', 0))
{
n = t[-1]; /* ( */
if (wextglob_pattern_p (pp) && n == L')') /* nested extglob? */
@@ -415,9 +393,7 @@ wextglob_skipname (pat, dname, flags)
/* Return 1 if DNAME should be skipped according to PAT. Handles multibyte
characters in PAT and DNAME. Mostly concerned with matching leading `.'. */
static int
mbskipname (pat, dname, flags)
char *pat, *dname;
int flags;
mbskipname (char *pat, char *dname, int flags)
{
int ret, ext;
wchar_t *pat_wc, *dn_wc;
@@ -452,8 +428,7 @@ mbskipname (pat, dname, flags)
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
void
udequote_pathname (pathname)
char *pathname;
udequote_pathname (char *pathname)
{
register int i, j;
@@ -474,8 +449,7 @@ udequote_pathname (pathname)
#if HANDLE_MULTIBYTE
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
void
wcdequote_pathname (wpathname)
wchar_t *wpathname;
wcdequote_pathname (wchar_t *wpathname)
{
int i, j;
@@ -494,13 +468,11 @@ wcdequote_pathname (wpathname)
}
static void
wdequote_pathname (pathname)
char *pathname;
wdequote_pathname (char *pathname)
{
mbstate_t ps;
size_t len, n;
wchar_t *wpathname;
int i, j;
wchar_t *orig_wpathname;
if (mbsmbchar (pathname) == 0)
@@ -538,8 +510,7 @@ wdequote_pathname (pathname)
}
static void
dequote_pathname (pathname)
char *pathname;
dequote_pathname (char *pathname)
{
if (MB_CUR_MAX > 1)
wdequote_pathname (pathname);
@@ -562,9 +533,7 @@ dequote_pathname (pathname)
/* Return 0 if DIR is a directory, -2 if DIR is a symlink, -1 otherwise. */
static int
glob_testdir (dir, flags)
char *dir;
int flags;
glob_testdir (char *dir, int flags)
{
struct stat finfo;
int r;
@@ -596,14 +565,9 @@ glob_testdir (dir, flags)
directories in the returned list. These two variables exist for the
convenience of the caller (always glob_vector). */
static struct globval *
finddirs (pat, sdir, flags, ep, np)
char *pat;
char *sdir;
int flags;
struct globval **ep;
int *np;
finddirs (char *pat, char *sdir, int flags, struct globval **ep, int *np)
{
char **r, *n;
char **r;
int ndirs;
struct globval *ret, *e, *g;
@@ -674,29 +638,26 @@ finddirs (pat, sdir, flags, ep, np)
Look in errno for more information. */
char **
glob_vector (pat, dir, flags)
char *pat;
char *dir;
int flags;
glob_vector (char *pat, char *dir, int flags)
{
DIR *d;
register struct dirent *dp;
struct globval *lastlink, *e, *dirlist;
register struct globval *nextlink;
register char *nextname, *npat, *subdir;
unsigned int count;
int lose, skip, ndirs, isdir, sdlen, add_current, patlen;
register char **name_vector;
register unsigned int i;
struct dirent *dp;
struct globval *nextlink, *lastlink, *e, *dirlist;
char *nextname, *npat, *subdir;
unsigned int count, i;
int lose, skip, ndirs, isdir, add_current;
size_t patlen, sdlen;
char **name_vector;
int mflags; /* Flags passed to strmatch (). */
int pflags; /* flags passed to sh_makepath () */
int hasglob; /* return value from glob_pattern_p */
int nalloca;
struct globval *firstmalloc, *tmplink;
char *convfn;
char *convfn, *convpat;
lastlink = 0;
count = lose = skip = add_current = 0;
count = 0;
lose = skip = add_current = 0;
firstmalloc = 0;
nalloca = 0;
@@ -739,7 +700,7 @@ glob_vector (pat, dir, flags)
hasglob = 0;
if (skip == 0 && ((hasglob = glob_pattern_p (pat)) == 0 || hasglob == 2))
{
int dirlen;
size_t dirlen;
struct stat finfo;
if (glob_testdir (dir, 0) < 0)
@@ -804,6 +765,10 @@ glob_vector (pat, dir, flags)
if (d == NULL)
return ((char **) &glob_error_return);
convpat = fnx_fromfs (pat, patlen);
if (convpat != pat)
convpat = savestring (convpat);
/* Compute the flags that will be passed to strmatch(). We don't
need to do this every time through the loop. */
mflags = (noglob_dot_filenames ? FNM_PERIOD : FNM_DOTDOT) | FNM_PATHNAME;
@@ -921,7 +886,7 @@ glob_vector (pat, dir, flags)
free (subdir);
convfn = fnx_fromfs (dp->d_name, D_NAMLEN (dp));
if (strmatch (pat, convfn, mflags) != FNM_NOMATCH)
if (strmatch (convpat, convfn, mflags) != FNM_NOMATCH)
{
if (nalloca < ALLOCA_MAX)
{
@@ -963,6 +928,9 @@ glob_vector (pat, dir, flags)
}
(void) closedir (d);
if (convpat != pat)
free (convpat);
}
/* compat: if GX_ADDCURDIR, add the passed directory also. Add an empty
@@ -1059,11 +1027,10 @@ glob_vector (pat, dir, flags)
it takes care of free()ing that array. Thus, you might think of this
function as side-effecting ARRAY. This should handle GX_MARKDIRS. */
static char **
glob_dir_to_array (dir, array, flags)
char *dir, **array;
int flags;
glob_dir_to_array (char *dir, char **array, int flags)
{
register unsigned int i, l;
unsigned int i;
size_t l;
int add_slash;
char **result, *new;
struct stat sb;
@@ -1148,14 +1115,12 @@ glob_dir_to_array (dir, array, flags)
If there isn't enough memory, then return NULL.
If a file system error occurs, return -1; `errno' has the error code. */
char **
glob_filename (pathname, flags)
char *pathname;
int flags;
glob_filename (char *pathname, int flags)
{
char **result, **new_result;
unsigned int result_size;
char *directory_name, *filename, *dname, *fn;
unsigned int directory_len;
size_t directory_len;
int free_dirname; /* flag */
int dflags, hasglob;
@@ -1214,7 +1179,7 @@ glob_filename (pathname, flags)
if (directory_len > 0 && (hasglob = glob_pattern_p (directory_name)) == 1)
{
char **directories, *d, *p;
register unsigned int i;
unsigned int i;
int all_starstar, last_starstar;
all_starstar = last_starstar = 0;
@@ -1250,7 +1215,7 @@ glob_filename (pathname, flags)
so we can compensate if filename is [star][star] */
if ((flags & GX_GLOBSTAR) && all_starstar == 0)
{
int dl, prev;
size_t dl, prev;
prev = dl = directory_len;
while (dl >= 4 && d[dl - 1] == '/' &&
d[dl - 2] == '*' &&
@@ -1336,8 +1301,6 @@ glob_filename (pathname, flags)
/* Special handling for symlinks to directories with globstar on */
if (all_starstar && (dflags & GX_NULLDIR) == 0)
{
int dlen;
/* If we have a directory name that is not null (GX_NULLDIR above)
and is a symlink to a directory, we return the symlink if
we're not `descending' into it (filename[0] == 0) and return
@@ -1380,7 +1343,7 @@ glob_filename (pathname, flags)
else
{
char **array;
register unsigned int l;
unsigned int l;
/* If we're expanding **, we don't need to glue the directory
name to the results; we've already done it in glob_vector */
@@ -1404,7 +1367,7 @@ glob_filename (pathname, flags)
NULL_PLACEHOLDER (temp_results))
#undef NULL_PLACEHOLDER
{
register int i, n;
int i, n;
for (n = 0; temp_results[n] && *temp_results[n] == 0; n++)
;
i = n;
@@ -1446,6 +1409,12 @@ glob_filename (pathname, flags)
free ((char *) array);
else if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
free (temp_results); /* expanding ** case above */
else if (array == temp_results)
/* If array == temp_results, either we assigned it above or
glob_dir_to_array returned temp_results because the dirname
was the empty string. In any case, we assume temp_results
has not been freed, and free it here. */
free (temp_results);
if (shouldbreak)
break;
@@ -1561,6 +1530,7 @@ only_filename:
if (free_dirname)
free (directory_name);
return (result);
}
+5 -5
View File
@@ -1,5 +1,5 @@
/* File-name wildcard pattern matching for GNU.
Copyright (C) 1985-2021 Free Software Foundation, Inc.
Copyright (C) 1985-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -34,11 +34,11 @@
#define GX_SYMLINK 0x1000 /* internal -- symlink to a directory */
#define GX_NEGATE 0x2000 /* internal -- extglob pattern being negated */
extern int glob_pattern_p PARAMS((const char *));
extern char **glob_vector PARAMS((char *, char *, int));
extern char **glob_filename PARAMS((char *, int));
extern int glob_pattern_p (const char *);
extern char **glob_vector (char *, char *, int);
extern char **glob_filename (char *, int);
extern int extglob_pattern_p PARAMS((const char *));
extern int extglob_pattern_p (const char *);
extern char *glob_error_return;
extern int noglob_dot_filenames;
+3 -4
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
/* Copyright (C) 1991-2020,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -16,13 +16,12 @@
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
static int INTERNAL_GLOB_PATTERN_P PARAMS((const GCHAR *));
static int INTERNAL_GLOB_PATTERN_P (const GCHAR *);
/* Return nonzero if PATTERN has any special globbing chars in it.
Compiled twice, once each for single-byte and multibyte characters. */
static int
INTERNAL_GLOB_PATTERN_P (pattern)
const GCHAR *pattern;
INTERNAL_GLOB_PATTERN_P (const GCHAR *pattern)
{
register const GCHAR *p;
register GCHAR c;
+5 -10
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
/* Copyright (C) 1991-2017,2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -18,8 +18,7 @@
#if EXTENDED_GLOB
int
EXTGLOB_PATTERN_P (pat)
const CHAR *pat;
EXTGLOB_PATTERN_P (const CHAR *pat)
{
switch (pat[0])
{
@@ -42,9 +41,7 @@ EXTGLOB_PATTERN_P (pat)
versions. FLAGS is a subset of strmatch flags; used to do case-insensitive
matching for now. */
int
MATCH_PATTERN_CHAR (pat, string, flags)
CHAR *pat, *string;
int flags;
MATCH_PATTERN_CHAR (CHAR *pat, CHAR *string, int flags)
{
CHAR c;
@@ -71,12 +68,10 @@ MATCH_PATTERN_CHAR (pat, string, flags)
}
int
MATCHLEN (pat, max)
CHAR *pat;
size_t max;
MATCHLEN (CHAR *pat, size_t max)
{
CHAR c;
int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
int matlen, bracklen, in_cclass, in_collsym, in_equiv;
if (*pat == 0)
return (0);
+4 -6
View File
@@ -1,6 +1,6 @@
/* gmisc.c -- miscellaneous pattern matching utility functions for Bash.
Copyright (C) 2010-2020 Free Software Foundation, Inc.
Copyright (C) 2010-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -38,7 +38,7 @@
#include "glob.h"
/* Make sure these names continue to agree with what's in smatch.c */
extern char *glob_patscan PARAMS((char *, char *, int));
extern char *glob_patscan (char *, char *, int, int);
/* Compile `gm_loop.c' for single-byte characters. */
#define CHAR char
@@ -79,9 +79,7 @@ extern char *glob_patscan PARAMS((char *, char *, int));
is only called when extended_glob is set, so we have to skip over extglob
patterns x(...) */
char *
glob_dirscan (pat, dirsep)
char *pat;
int dirsep;
glob_dirscan (char *pat, int dirsep)
{
char *p, *d, *pe, *se;
@@ -92,7 +90,7 @@ glob_dirscan (pat, dirsep)
{
if (se == 0)
se = p + strlen (p) - 1;
pe = glob_patscan (p + 2, se, 0);
pe = glob_patscan (p + 2, se, 0, 0);
if (pe == 0)
continue;
else if (*pe == 0)
+128 -156
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
/* Copyright (C) 1991-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -24,22 +24,19 @@ struct STRUCT
CHAR *string;
};
int FCT PARAMS((CHAR *, CHAR *, int));
int FCT (CHAR *, CHAR *, int);
static int GMATCH PARAMS((CHAR *, CHAR *, CHAR *, CHAR *, struct STRUCT *, int));
static CHAR *PARSE_COLLSYM PARAMS((CHAR *, INT *));
static CHAR *BRACKMATCH PARAMS((CHAR *, U_CHAR, int));
static int EXTMATCH PARAMS((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
static int GMATCH (CHAR *, CHAR *, CHAR *, CHAR *, struct STRUCT *, int);
static inline CHAR *PARSE_SUBBRACKET (CHAR *, int);
static CHAR *BRACKMATCH (CHAR *, U_CHAR, int);
static int EXTMATCH (INT, CHAR *, CHAR *, CHAR *, CHAR *, int);
extern void DEQUOTE_PATHNAME PARAMS((CHAR *));
extern void DEQUOTE_PATHNAME (CHAR *);
/*static*/ CHAR *PATSCAN PARAMS((CHAR *, CHAR *, INT));
/*static*/ CHAR *PATSCAN (CHAR *, CHAR *, INT, int);
int
FCT (pattern, string, flags)
CHAR *pattern;
CHAR *string;
int flags;
FCT (CHAR *pattern, CHAR *string, int flags)
{
CHAR *se, *pe;
@@ -55,11 +52,7 @@ FCT (pattern, string, flags)
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, FNM_NOMATCH if not. */
static int
GMATCH (string, se, pattern, pe, ends, flags)
CHAR *string, *se;
CHAR *pattern, *pe;
struct STRUCT *ends;
int flags;
GMATCH (CHAR *string, CHAR *se, CHAR *pattern, CHAR *pe, struct STRUCT *ends, int flags)
{
CHAR *p, *n; /* pattern, string */
INT c; /* current pattern character - XXX U_CHAR? */
@@ -120,7 +113,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
we are matching a pathname. */
if ((flags & FNM_DOTDOT) &&
((n == string && SDOT_OR_DOTDOT(n)) ||
((flags & FNM_PATHNAME) && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
((flags & FNM_PATHNAME) && n > string && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
return FNM_NOMATCH;
break;
@@ -166,7 +159,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
we are matching a pathname. */
if ((flags & FNM_DOTDOT) &&
((n == string && SDOT_OR_DOTDOT(n)) ||
((flags & FNM_PATHNAME) && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
((flags & FNM_PATHNAME) && n > string && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
return FNM_NOMATCH;
if (p == pe)
@@ -192,7 +185,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
that's OK, since we can match 0 or 1 occurrences.
We need to skip the glob pattern and see if we
match the rest of the string. */
newn = PATSCAN (p + 1, pe, 0);
newn = PATSCAN (p + 1, pe, 0, flags);
/* If NEWN is 0, we have an ill-formed pattern. */
p = newn ? newn : pe;
}
@@ -225,7 +218,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
that's OK, since we can match 0 or more occurrences.
We need to skip the glob pattern and see if we
match the rest of the string. */
newn = PATSCAN (p + 1, pe, 0);
newn = PATSCAN (p + 1, pe, 0, flags);
/* If NEWN is 0, we have an ill-formed pattern. */
p = newn ? newn : pe;
}
@@ -343,12 +336,17 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
(n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
return (FNM_NOMATCH);
/* If we are matching pathnames, we can't match a slash with a
bracket expression. */
if (sc == L('/') && (flags & FNM_PATHNAME))
return (FNM_NOMATCH);
/* `?' cannot match `.' or `..' if it is the first character of the
string or if it is the first character following a slash and
we are matching a pathname. */
if ((flags & FNM_DOTDOT) &&
((n == string && SDOT_OR_DOTDOT(n)) ||
((flags & FNM_PATHNAME) && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
((flags & FNM_PATHNAME) && n > string && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
return FNM_NOMATCH;
p = BRACKMATCH (p, sc, flags);
@@ -375,51 +373,36 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
return (FNM_NOMATCH);
}
/* Parse a bracket expression collating symbol ([.sym.]) starting at P, find
the value of the symbol, and move P past the collating symbol expression.
The value is returned in *VP, if VP is not null. */
static CHAR *
PARSE_COLLSYM (p, vp)
CHAR *p;
INT *vp;
{
register int pc;
INT val;
#define SLASH_PATHNAME(c) (c == L('/') && (flags & FNM_PATHNAME))
p++; /* move past the `.' */
for (pc = 0; p[pc]; pc++)
if (p[pc] == L('.') && p[pc+1] == L(']'))
break;
if (p[pc] == 0)
{
if (vp)
*vp = INVALID;
return (p + pc);
}
val = COLLSYM (p, pc);
if (vp)
*vp = val;
return (p + pc + 2);
/* Parse a special bracket expression symbol ([.sym.], [=char=], [:cclass:]),
starting at P, and return the position of the terminating .], =], or :].
P points to the character after the opening bracket. Returns NULL if the
symbol isn't correctly terminated. */
static inline CHAR *
PARSE_SUBBRACKET (CHAR *p, int flags)
{
CHAR type; /* the type of special bracket expression symbol */
type = *p;
/* POSIX allows a right bracket to appear in a collating symbol. */
while (*++p != L('\0') && SLASH_PATHNAME (*p) == 0 && (type != L('.') && *p == L(']')) == 0)
if (*p == type && p[1] == L(']'))
return p;
return NULL;
}
/* Use prototype definition here because of type promotion. */
static CHAR *
#if defined (PROTOTYPES)
BRACKMATCH (CHAR *p, U_CHAR test, int flags)
#else
BRACKMATCH (p, test, flags)
CHAR *p;
U_CHAR test;
int flags;
#endif
{
register CHAR cstart, cend, c;
register int not; /* Nonzero if the sense of the character class is inverted. */
int brcnt, forcecoll, isrange;
int forcecoll, isrange;
INT pc;
CHAR *savep;
CHAR *brchrp;
CHAR *close;
U_CHAR orig_test;
orig_test = test;
@@ -444,13 +427,14 @@ BRACKMATCH (p, test, flags)
/* POSIX.2 equivalence class: [=c=]. See POSIX.2 2.8.3.2. Find
the end of the equivalence class, move the pattern pointer past
it, and check for equivalence. XXX - this handles only
single-character equivalence classes, which is wrong, or at
least incomplete. */
if (c == L('[') && *p == L('=') && p[2] == L('=') && p[3] == L(']'))
it, and check for equivalence. */
if (c == L('[') && *p == L('=') && (close = PARSE_SUBBRACKET (p, flags)) != NULL)
{
pc = FOLD (p[1]);
p += 4;
p++;
pc = COLLSYM (p, close - p);
pc = FOLD (pc);
p = close + 2;
if (COLLEQUIV (test, pc))
{
/*[*/ /* Move past the closing `]', since the first thing we do at
@@ -463,36 +447,31 @@ BRACKMATCH (p, test, flags)
c = *p++;
if (c == L('\0'))
return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
else if (c == L('/') && (flags & FNM_PATHNAME))
return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
else if (c == L(']'))
break;
c = FOLD (c);
continue;
}
}
/* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */
if (c == L('[') && *p == L(':'))
if (c == L('[') && *p == L(':') && (close = PARSE_SUBBRACKET (p, flags)) != NULL)
{
CHAR *close, *ccname;
CHAR *ccname;
pc = 0; /* make sure invalid char classes don't match. */
/* Find end of character class name */
for (close = p + 1; *close != '\0'; close++)
if (*close == L(':') && *(close+1) == L(']'))
break;
if (*close != L('\0'))
ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR));
if (ccname)
{
ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR));
if (ccname == 0)
pc = 0;
else
{
bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR));
*(ccname + (close - p - 1)) = L('\0');
/* As a result of a POSIX discussion, char class names are
allowed to be quoted (?) */
DEQUOTE_PATHNAME (ccname);
pc = IS_CCLASS (orig_test, (XCHAR *)ccname);
}
bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR));
*(ccname + (close - p - 1)) = L('\0');
/* As a result of a POSIX discussion, char class names are
allowed to be quoted (?) */
DEQUOTE_PATHNAME (ccname);
pc = IS_CCLASS (orig_test, (XCHAR *)ccname);
if (pc == -1)
{
/* CCNAME is not a valid character class in the current
@@ -504,14 +483,12 @@ BRACKMATCH (p, test, flags)
string. If we don't want to do that, take out the update
of P. */
pc = 0;
p = close + 2;
}
else
p = close + 2; /* move past the closing `]' */
free (ccname);
}
free (ccname);
p = close + 2;
if (pc)
{
/*[*/ /* Move past the closing `]', since the first thing we do at
@@ -526,6 +503,8 @@ BRACKMATCH (p, test, flags)
c = *p++;
if (c == L('\0'))
return ((test == L('[')) ? savep : (CHAR *)0);
else if (c == L('/') && (flags & FNM_PATHNAME))
return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
else if (c == L(']'))
break;
c = FOLD (c);
@@ -537,20 +516,20 @@ BRACKMATCH (p, test, flags)
the symbol name, make sure it is terminated by `.]', translate
the name to a character using the external table, and do the
comparison. */
if (c == L('[') && *p == L('.'))
if (c == L('[') && *p == L('.') && (close = PARSE_SUBBRACKET (p, flags)) != NULL)
{
p = PARSE_COLLSYM (p, &pc);
/* An invalid collating symbol cannot be the first point of a
range. If it is, we set cstart to one greater than `test',
so any comparisons later will fail. */
cstart = (pc == INVALID) ? test + 1 : pc;
p++;
cstart = COLLSYM (p, close - p);
p = close + 2;
forcecoll = 1;
}
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
{
if (*p == '\0')
return (CHAR *)0;
return ((test == L('[')) ? savep : (CHAR *)0);
else if (*p == L('/') && (flags & FNM_PATHNAME))
return ((test == L('[')) ? savep : (CHAR *)0);
cstart = cend = *p++;
}
@@ -565,15 +544,23 @@ BRACKMATCH (p, test, flags)
if (c == L('\0'))
return ((test == L('[')) ? savep : (CHAR *)0);
/* POSIX.2 2.13.3 says: `If a <slash> character is found following an
unescaped <left-square-bracket> character before a corresponding
<right-square-bracket> is found, the open bracket shall be treated
as an ordinary character.' If we find a slash in a bracket
expression and the flags indicate we're supposed to be treating the
string like a pathname, we have to treat the `[' as just a character
to be matched. */
if (c == L('/') && (flags & FNM_PATHNAME))
return ((test == L('[')) ? savep : (CHAR *)0);
c = *p++;
c = FOLD (c);
if (c == L('\0'))
return ((test == L('[')) ? savep : (CHAR *)0);
if ((flags & FNM_PATHNAME) && c == L('/'))
/* [/] can never match when matching a pathname. */
return (CHAR *)0;
else if (c == L('/') && (flags & FNM_PATHNAME))
return ((test == L('[')) ? savep : (CHAR *)0);
/* This introduces a range, unless the `-' is the last
character of the class. Find the end of the range
@@ -584,14 +571,14 @@ BRACKMATCH (p, test, flags)
if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
cend = *p++;
if (cend == L('\0'))
return (CHAR *)0;
if (cend == L('[') && *p == L('.'))
return ((test == L('[')) ? savep : (CHAR *)0);
else if (cend == L('/') && (flags & FNM_PATHNAME))
return ((test == L('[')) ? savep : (CHAR *)0);
if (cend == L('[') && *p == L('.') && (close = PARSE_SUBBRACKET (p, flags)) != NULL)
{
p = PARSE_COLLSYM (p, &pc);
/* An invalid collating symbol cannot be the second part of a
range expression. If we get one, we set cend to one fewer
than the test character to make sure the range test fails. */
cend = (pc == INVALID) ? test - 1 : pc;
p++;
cend = COLLSYM (p, close - p);
p = close + 2;
forcecoll = 1;
}
cend = FOLD (cend);
@@ -627,46 +614,37 @@ BRACKMATCH (p, test, flags)
matched:
/* Skip the rest of the [...] that already matched. */
c = *--p;
brcnt = 1;
brchrp = 0;
while (brcnt > 0)
while (1)
{
int oc;
/* A `[' without a matching `]' is just another character to match. */
if (c == L('\0'))
return ((test == L('[')) ? savep : (CHAR *)0);
else if (c == L('/') && (flags & FNM_PATHNAME))
return ((test == L('[')) ? savep : (CHAR *)0);
oc = c;
c = *p++;
if (c == L('[') && (*p == L('=') || *p == L(':') || *p == L('.')))
{
brcnt++;
brchrp = p++; /* skip over the char after the left bracket */
if ((c = *p) == L('\0'))
return ((test == L('[')) ? savep : (CHAR *)0);
/* If *brchrp == ':' we should check that the rest of the characters
form a valid character class name. We don't do that yet, but we
keep BRCHRP in case we want to. */
}
/* We only want to check brchrp if we set it above. */
else if (c == L(']') && brcnt > 1 && brchrp != 0 && oc == *brchrp)
{
brcnt--;
brchrp = 0; /* just in case */
if ((close = PARSE_SUBBRACKET (p, flags)) != NULL)
p = close + 2;
}
/* Left bracket loses its special meaning inside a bracket expression.
It is only valid when followed by a `.', `=', or `:', which we check
for above. Technically the right bracket can appear in a collating
symbol, so we check for that here. Otherwise, it terminates the
bracket expression. */
else if (c == L(']') && (brchrp == 0 || *brchrp != L('.')) && brcnt >= 1)
brcnt = 0;
symbol, so we check for that as well. The right brackets terminating
collating symbols, equivalence classes, or character classes are
processed by PARSE_SUBBRACKET. Otherwise, a right bracket terminates
the bracket expression. */
else if (c == L(']'))
break;
else if (!(flags & FNM_NOESCAPE) && c == L('\\'))
{
if (*p == '\0')
return (CHAR *)0;
/* XXX 1003.2d11 is unclear if this is right. */
return ((test == L('[')) ? savep : (CHAR *)0);
/* We don't allow backslash to quote slash if we're matching pathnames */
else if (*p == L('/') && (flags & FNM_PATHNAME))
return ((test == L('[')) ? savep : (CHAR *)0);
/* Posix issue 8 leaves this unspecified for the shell. */
++p;
}
}
@@ -695,16 +673,12 @@ matched:
first character after the matching DELIM or NULL if the pattern is
empty or invalid. */
/*static*/ CHAR *
PATSCAN (string, end, delim)
CHAR *string, *end;
INT delim;
PATSCAN (CHAR *string, CHAR *end, INT delim, int flags)
{
int pnest, bnest, skip;
INT cchar;
CHAR *s, c, *bfirst;
CHAR *s, c, *bfirst, *t;
pnest = bnest = skip = 0;
cchar = 0;
bfirst = NULL;
if (string == end)
@@ -722,7 +696,8 @@ PATSCAN (string, end, delim)
switch (c)
{
case L('\\'):
skip = 1;
if ((flags & FNM_NOESCAPE) == 0)
skip = 1;
break;
case L('\0'):
@@ -740,7 +715,11 @@ PATSCAN (string, end, delim)
bnest++;
}
else if (s[1] == L(':') || s[1] == L('.') || s[1] == L('='))
cchar = s[1];
{
t = PARSE_SUBBRACKET (s + 1, flags);
if (t)
s = t + 2 - 1; /* -1 to cancel s++ in loop above */
}
break;
/* `]' is not special if it's the first char (after a leading `!'
@@ -749,9 +728,7 @@ PATSCAN (string, end, delim)
case L(']'):
if (bnest)
{
if (cchar && s[-1] == cchar)
cchar = 0;
else if (s != bfirst)
if (s != bfirst)
{
bnest--;
bfirst = 0;
@@ -781,8 +758,7 @@ PATSCAN (string, end, delim)
/* Return 0 if dequoted pattern matches S in the current locale. */
static int
STRCOMPARE (p, pe, s, se)
CHAR *p, *pe, *s, *se;
STRCOMPARE (CHAR *p, CHAR *pe, CHAR *s, CHAR *se)
{
int ret;
CHAR c1, c2;
@@ -821,11 +797,7 @@ STRCOMPARE (p, pe, s, se)
the first time an extended pattern specifier is encountered, so it calls
gmatch recursively. */
static int
EXTMATCH (xc, s, se, p, pe, flags)
INT xc; /* select which operation */
CHAR *s, *se;
CHAR *p, *pe;
int flags;
EXTMATCH (INT xc, CHAR *s, CHAR *se, CHAR *p, CHAR *pe, int flags)
{
CHAR *prest; /* pointer to rest of pattern */
CHAR *psub; /* pointer to sub-pattern */
@@ -840,12 +812,14 @@ fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
fprintf(stderr, "extmatch: flags = %d\n", flags);
#endif
prest = PATSCAN (p + (*p == L('(')), pe, 0); /* ) */
prest = PATSCAN (p + (*p == L('(')), pe, 0, flags); /* ) */
if (prest == 0)
/* If PREST is 0, we failed to scan a valid pattern. In this
case, we just want to compare the two as strings. */
return (STRCOMPARE (p - 1, pe, s, se));
glob_recursion_depth++;
switch (xc)
{
case L('+'): /* match one or more occurrences */
@@ -861,7 +835,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
string. */
for (psub = p + 1; ; psub = pnext)
{
pnext = PATSCAN (psub, pe, L('|'));
pnext = PATSCAN (psub, pe, L('|'), flags);
for (srest = s; srest <= se; srest++)
{
/* Match this substring (S -> SREST) against this
@@ -898,7 +872,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
rest of the string. */
for (psub = p + 1; ; psub = pnext)
{
pnext = PATSCAN (psub, pe, L('|'));
pnext = PATSCAN (psub, pe, L('|'), flags);
srest = (prest == pe) ? se : s;
for ( ; srest <= se; srest++)
{
@@ -919,7 +893,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
m1 = 0;
for (psub = p + 1; ; psub = pnext)
{
pnext = PATSCAN (psub, pe, L('|'));
pnext = PATSCAN (psub, pe, L('|'), flags);
/* If one of the patterns matches, just bail immediately. */
if (m1 = (GMATCH (s, srest, psub, pnext - 1, NULL, flags) == 0))
break;
@@ -933,9 +907,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
if (m1 == 0 && (flags & FNM_PERIOD) && *s == '.')
return (FNM_NOMATCH);
if (m1 == 0 && (flags & FNM_DOTDOT) &&
(SDOT_OR_DOTDOT (s) ||
((flags & FNM_PATHNAME) && s[-1] == L('/') && PDOT_OR_DOTDOT(s))))
if (m1 == 0 && (flags & FNM_DOTDOT) && (SDOT_OR_DOTDOT (s)))
return (FNM_NOMATCH);
/* if srest > s, we are not at start of string */
@@ -960,7 +932,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
#undef FCT
#undef GMATCH
#undef COLLSYM
#undef PARSE_COLLSYM
#undef PARSE_SUBBRACKET
#undef PATSCAN
#undef STRCOMPARE
#undef EXTMATCH
+41 -57
View File
@@ -1,7 +1,7 @@
/* strmatch.c -- ksh-like extended pattern matching for the shell and filename
globbing. */
/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
/* Copyright (C) 1991-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -60,14 +60,14 @@ extern int fnmatch (const char *, const char *, int);
#endif
int glob_asciirange = GLOBASCII_DEFAULT;
int glob_recursion_depth;
#if FNMATCH_EQUIV_FALLBACK
/* Construct a string w1 = "c1" and a pattern w2 = "[[=c2=]]" and pass them
to fnmatch to see if wide characters c1 and c2 collate as members of the
same equivalence class. We can't really do this portably any other way */
static int
_fnmatch_fallback (s, p)
int s, p; /* string char, patchar */
_fnmatch_fallback (int s, int p)
{
char s1[2]; /* string */
char s2[8]; /* constructed pattern */
@@ -99,13 +99,10 @@ _fnmatch_fallback (s, p)
/* Return 0 if C1 == C2 or collates equally if FORCECOLL is non-zero. */
static int
charcmp (c1, c2, forcecoll)
int c1, c2;
int forcecoll;
charcmp (int c1, int c2, int forcecoll)
{
static char s1[2] = { ' ', '\0' };
static char s2[2] = { ' ', '\0' };
int ret;
/* Eight bits only. Period. */
c1 &= 0xFF;
@@ -124,9 +121,7 @@ charcmp (c1, c2, forcecoll)
}
static int
rangecmp (c1, c2, forcecoll)
int c1, c2;
int forcecoll;
rangecmp (int c1, int c2, int forcecoll)
{
int r;
@@ -144,9 +139,12 @@ rangecmp (c1, c2, forcecoll)
#if defined (HAVE_STRCOLL)
/* Returns 1 if chars C and EQUIV collate equally in the current locale. */
static int
collequiv (c, equiv)
int c, equiv;
collseqcmp (int c, int equiv)
{
/* Make sure characters >= 0x80 are compared as bytes in a UTF-8 locale. */
if (locale_utf8locale && (UTF8_SINGLEBYTE (c) == 0 || UTF8_SINGLEBYTE (equiv) == 0))
return (c == equiv);
if (charcmp (c, equiv, 1) == 0)
return 1;
@@ -158,7 +156,7 @@ collequiv (c, equiv)
}
#else
# define collequiv(c, equiv) ((c) == (equiv))
# define collseqcmp(c, equiv) ((c) == (equiv))
#endif
#define _COLLSYM _collsym
@@ -167,9 +165,7 @@ collequiv (c, equiv)
#include "collsyms.h"
static int
collsym (s, len)
CHAR *s;
int len;
collsym (CHAR *s, int len)
{
register struct _collsym *csp;
char *x;
@@ -207,8 +203,7 @@ static char const *const cclass_name[] =
#define N_CHAR_CLASS (sizeof(cclass_name) / sizeof (cclass_name[0]))
static enum char_class
is_valid_cclass (name)
const char *name;
is_valid_cclass (const char *name)
{
enum char_class ret;
int i;
@@ -228,9 +223,7 @@ is_valid_cclass (name)
}
static int
cclass_test (c, char_class)
int c;
enum char_class char_class;
cclass_test (int c, enum char_class char_class)
{
int result;
@@ -287,13 +280,14 @@ cclass_test (c, char_class)
}
static int
is_cclass (c, name)
int c;
const char *name;
is_cclass (int c, const char *name)
{
enum char_class char_class;
int result;
if (locale_utf8locale && UTF8_SINGLEBYTE (c) == 0)
return -1;
char_class = is_valid_cclass (name);
if (char_class == CC_NO_CLASS)
return -1;
@@ -304,9 +298,10 @@ is_cclass (c, name)
/* Now include `sm_loop.c' for single-byte characters. */
/* The result of FOLD is an `unsigned char' */
# define FOLD(c) ((flags & FNM_CASEFOLD) \
? TOLOWER ((unsigned char)c) \
: ((unsigned char)c))
# define FOLD(c) \
(((flags & FNM_CASEFOLD) && (locale_utf8locale == 0 || UTF8_SINGLEBYTE (c))) \
? TOLOWER ((unsigned char)c) \
: ((unsigned char)c))
#if !defined (__CYGWIN__)
# define ISDIRSEP(c) ((c) == '/')
@@ -321,7 +316,7 @@ is_cclass (c, name)
#define FCT internal_strmatch
#define GMATCH gmatch
#define COLLSYM collsym
#define PARSE_COLLSYM parse_collsym
#define PARSE_SUBBRACKET parse_subbracket
#define BRACKMATCH brackmatch
#define PATSCAN glob_patscan
#define STRCOMPARE strcompare
@@ -334,7 +329,7 @@ is_cclass (c, name)
#define STRLEN(S) strlen(S)
#define STRCMP(S1, S2) strcmp((S1), (S2))
#define RANGECMP(C1, C2, F) rangecmp((C1), (C2), (F))
#define COLLEQUIV(C1, C2) collequiv((C1), (C2))
#define COLLEQUIV(C1, C2) collseqcmp((C1), (C2))
#define CTYPE_T enum char_class
#define IS_CCLASS(C, S) is_cclass((C), (S))
#include "sm_loop.c"
@@ -353,15 +348,15 @@ is_cclass (c, name)
# define STREQ(s1, s2) ((wcscmp (s1, s2) == 0))
# define STREQN(a, b, n) ((a)[0] == (b)[0] && wcsncmp(a, b, n) == 0)
extern char *mbsmbchar PARAMS((const char *));
extern char *mbsmbchar (const char *);
#if FNMATCH_EQUIV_FALLBACK
/* Construct a string w1 = "c1" and a pattern w2 = "[[=c2=]]" and pass them
to fnmatch to see if wide characters c1 and c2 collate as members of the
same equivalence class. We can't really do this portably any other way */
same equivalence class. We can't really do this portably any other way
c1 == string char, c2 == patchar */
static int
_fnmatch_fallback_wc (c1, c2)
wchar_t c1, c2; /* string char, patchar */
_fnmatch_fallback_wc (wchar_t c1, wchar_t c2)
{
char w1[MB_LEN_MAX+1]; /* string */
char w2[MB_LEN_MAX+8]; /* constructed pattern */
@@ -387,13 +382,10 @@ _fnmatch_fallback_wc (c1, c2)
#endif
static int
charcmp_wc (c1, c2, forcecoll)
wint_t c1, c2;
int forcecoll;
charcmp_wc (wint_t c1, wint_t c2, int forcecoll)
{
static wchar_t s1[2] = { L' ', L'\0' };
static wchar_t s2[2] = { L' ', L'\0' };
int r;
if (c1 == c2)
return 0;
@@ -408,9 +400,7 @@ charcmp_wc (c1, c2, forcecoll)
}
static int
rangecmp_wc (c1, c2, forcecoll)
wint_t c1, c2;
int forcecoll;
rangecmp_wc (wint_t c1, wint_t c2, int forcecoll)
{
int r;
@@ -425,8 +415,7 @@ rangecmp_wc (c1, c2, forcecoll)
/* Returns 1 if wide chars C and EQUIV collate equally in the current locale. */
static int
collequiv_wc (c, equiv)
wint_t c, equiv;
collseqcmp_wc (wint_t c, wint_t equiv)
{
wchar_t s, p;
@@ -453,9 +442,7 @@ collequiv_wc (c, equiv)
# include "collsyms.h"
static wint_t
collwcsym (s, len)
wchar_t *s;
int len;
collwcsym (wchar_t *s, int len)
{
register struct _collwcsym *csp;
@@ -470,9 +457,7 @@ collwcsym (s, len)
}
static int
is_wcclass (wc, name)
wint_t wc;
wchar_t *name;
is_wcclass (wint_t wc, wchar_t *name)
{
char *mbs;
mbstate_t state;
@@ -524,8 +509,7 @@ is_wcclass (wc, name)
This only uses single-byte code, but is only needed to support multibyte
locales. */
static int
posix_cclass_only (pattern)
char *pattern;
posix_cclass_only (char *pattern)
{
char *p, *p1;
char cc[16]; /* sufficient for all valid posix char class names */
@@ -577,7 +561,7 @@ posix_cclass_only (pattern)
#define FCT internal_wstrmatch
#define GMATCH gmatch_wc
#define COLLSYM collwcsym
#define PARSE_COLLSYM parse_collwcsym
#define PARSE_SUBBRACKET parse_subbracket_wc
#define BRACKMATCH brackmatch_wc
#define PATSCAN glob_patscan_wc
#define STRCOMPARE wscompare
@@ -590,7 +574,7 @@ posix_cclass_only (pattern)
#define STRLEN(S) wcslen(S)
#define STRCMP(S1, S2) wcscmp((S1), (S2))
#define RANGECMP(C1, C2, F) rangecmp_wc((C1), (C2), (F))
#define COLLEQUIV(C1, C2) collequiv_wc((C1), (C2))
#define COLLEQUIV(C1, C2) collseqcmp_wc((C1), (C2))
#define CTYPE_T enum char_class
#define IS_CCLASS(C, S) is_wcclass((C), (S))
#include "sm_loop.c"
@@ -598,16 +582,14 @@ posix_cclass_only (pattern)
#endif /* HAVE_MULTIBYTE */
int
xstrmatch (pattern, string, flags)
char *pattern;
char *string;
int flags;
xstrmatch (char *pattern, char *string, int flags)
{
#if HANDLE_MULTIBYTE
int ret;
size_t n;
wchar_t *wpattern, *wstring;
size_t plen, slen, mplen, mslen;
glob_recursion_depth = 0;
if (MB_CUR_MAX == 1)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
@@ -633,6 +615,8 @@ xstrmatch (pattern, string, flags)
return ret;
#else
glob_recursion_depth = 0;
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
#endif /* !HANDLE_MULTIBYTE */
}
+5 -11
View File
@@ -1,7 +1,7 @@
/* strmatch.c -- ksh-like extended pattern matching for the shell and filename
globbing. */
/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
/* Copyright (C) 1991-2020,2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -24,16 +24,13 @@
#include "stdc.h"
#include "strmatch.h"
extern int xstrmatch PARAMS((char *, char *, int));
extern int xstrmatch (char *, char *, int);
#if defined (HANDLE_MULTIBYTE)
extern int internal_wstrmatch PARAMS((wchar_t *, wchar_t *, int));
extern int internal_wstrmatch (wchar_t *, wchar_t *, int);
#endif
int
strmatch (pattern, string, flags)
char *pattern;
char *string;
int flags;
strmatch (char *pattern, char *string, int flags)
{
if (string == 0 || pattern == 0)
return FNM_NOMATCH;
@@ -43,10 +40,7 @@ strmatch (pattern, string, flags)
#if defined (HANDLE_MULTIBYTE)
int
wcsmatch (wpattern, wstring, flags)
wchar_t *wpattern;
wchar_t *wstring;
int flags;
wcsmatch (wchar_t *wpattern, wchar_t *wstring, int flags)
{
if (wstring == 0 || wpattern == 0)
return (FNM_NOMATCH);
+3 -3
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
/* Copyright (C) 1991-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -56,10 +56,10 @@
/* Match STRING against the filename pattern PATTERN,
returning zero if it matches, FNM_NOMATCH if not. */
extern int strmatch PARAMS((char *, char *, int));
extern int strmatch (char *, char *, int);
#if HANDLE_MULTIBYTE
extern int wcsmatch PARAMS((wchar_t *, wchar_t *, int));
extern int wcsmatch (wchar_t *, wchar_t *, int);
#endif
#endif /* _STRMATCH_H */
+12 -20
View File
@@ -1,6 +1,6 @@
/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
/* Copyright (C) 2002-2022 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -47,7 +47,7 @@ extern int errno;
#endif
#if ! HAVE_STRCHRNUL
extern char *strchrnul PARAMS((const char *, int));
extern char *strchrnul (const char *, int);
#endif
/* On some locales (ex. ja_JP.sjis), mbsrtowc doesn't convert 0x5c to U<0x5c>.
@@ -57,11 +57,7 @@ static mbstate_t local_state;
static int local_state_use = 0;
size_t
xmbsrtowcs (dest, src, len, pstate)
wchar_t *dest;
const char **src;
size_t len;
mbstate_t *pstate;
xmbsrtowcs (wchar_t *dest, const char **src, size_t len, mbstate_t *pstate)
{
mbstate_t *ps;
size_t mblength, wclength, n;
@@ -139,16 +135,15 @@ xmbsrtowcs (dest, src, len, pstate)
}
#if HAVE_MBSNRTOWCS
/* Convert a multibyte string to a wide character string. Memory for the
new wide character string is obtained with malloc.
/* Convert a multibyte string SRC to a wide character string and store the
result in *DESTP. Memory for the new wide character string is obtained
with malloc.
Fast multiple-character version of xdupmbstowcs used when the indices are
not required and mbsnrtowcs is available. */
static size_t
xdupmbstowcs2 (destp, src)
wchar_t **destp; /* Store the pointer to the wide character string */
const char *src; /* Multibyte character string */
xdupmbstowcs2 (wchar_t **destp, const char *src)
{
const char *p; /* Conversion start position of src */
wchar_t *wsbuf; /* Buffer for wide characters. */
@@ -258,11 +253,12 @@ xdupmbstowcs2 (destp, src)
}
#endif /* HAVE_MBSNRTOWCS */
/* Convert a multibyte string to a wide character string. Memory for the
new wide character string is obtained with malloc.
/* Convert a multibyte string SRC to a wide character string and store the
result in *DESTP. Memory for the new wide character string is obtained
with malloc.
The return value is the length of the wide character string. Returns a
pointer to the wide character string in DESTP. If INDICESP is not NULL,
pointer to the wide character string in *DESTP. If INDICESP is not NULL,
INDICESP stores the pointer to the pointer array. Each pointer is to
the first byte of each multibyte character. Memory for the pointer array
is obtained with malloc, too.
@@ -270,10 +266,7 @@ xdupmbstowcs2 (destp, src)
of DESTP and INDICESP are NULL. */
size_t
xdupmbstowcs (destp, indicesp, src)
wchar_t **destp; /* Store the pointer to the wide character string */
char ***indicesp; /* Store the pointer to the pointer array. */
const char *src; /* Multibyte character string */
xdupmbstowcs (wchar_t **destp, char ***indicesp, const char *src)
{
const char *p; /* Conversion start position of src */
wchar_t wc; /* Created wide character by conversion */
@@ -426,7 +419,6 @@ xwcsrtombs (char *dest, const wchar_t **srcp, size_t len, mbstate_t *ps)
size_t cur_max; /* XXX - locale_cur_max */
char buf[64], *destptr, *tmp_dest;
unsigned char uc;
mbstate_t prev_state;
cur_max = MB_CUR_MAX;
if (cur_max > sizeof (buf)) /* Holy cow. */