mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-13 07:00:49 +02:00
Bash-5.3-alpha release
This commit is contained in:
+1
-5
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user