Bash-4.3 distribution sources and documentation

This commit is contained in:
Chet Ramey 2014-02-26 09:36:43 -05:00
commit ac50fbac37
497 changed files with 129395 additions and 87598 deletions

View file

@ -48,6 +48,8 @@
#include "stdc.h"
#include "memalloc.h"
#include <signal.h>
#include "shell.h"
#include "glob.h"
@ -84,6 +86,8 @@ struct globval
extern void throw_to_top_level __P((void));
extern int sh_eaccess __P((char *, int));
extern char *sh_makepath __P((const char *, const char *, int));
extern int signal_is_pending __P((int));
extern void run_pending_traps __P((void));
extern int extended_glob;
@ -112,9 +116,13 @@ static void wdequote_pathname __P((char *));
# define dequote_pathname udequote_pathname
#endif
static void dequote_pathname __P((char *));
static int glob_testdir __P((char *));
static int glob_testdir __P((char *, int));
static char **glob_dir_to_array __P((char *, char **, int));
/* Make sure these names continue to agree with what's in smatch.c */
extern char *glob_patscan __P((char *, char *, int));
extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int));
/* Compile `glob_loop.c' for single-byte characters. */
#define CHAR unsigned char
#define INT int
@ -162,15 +170,67 @@ glob_pattern_p (pattern)
#endif
}
#if EXTENDED_GLOB
/* Return 1 if all subpatterns in the extended globbing pattern PAT indicate
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;
{
char *pp, *pe, *t;
int n, r;
pp = pat + 2;
pe = pp + strlen (pp) - 1; /*(*/
if (*pe != ')')
return 0;
if ((t = strchr (pp, '|')) == 0) /* easy case first */
{
*pe = '\0';
r = skipname (pp, dname, flags); /*(*/
*pe = ')';
return r;
}
while (t = glob_patscan (pp, pe, '|'))
{
n = t[-1];
t[-1] = '\0';
r = skipname (pp, dname, flags);
t[-1] = n;
if (r == 0) /* if any pattern says not skip, we don't skip */
return r;
pp = t;
} /*(*/
if (pp == pe) /* glob_patscan might find end of pattern */
return r;
*pe = '\0';
# if defined (HANDLE_MULTIBYTE)
r = mbskipname (pp, dname, flags); /*(*/
# else
r = skipname (pp, dname, flags); /*(*/
# endif
*pe = ')';
return r;
}
#endif
/* 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;
{
#if EXTENDED_GLOB
if (extglob_pattern_p (pat)) /* XXX */
return (extglob_skipname (pat, dname, flags));
#endif
/* If a leading dot need not be explicitly matched, and the pattern
doesn't start with a `.', don't match `.' or `..' */
if (noglob_dot_filenames == 0 && pat[0] != '.' &&
@ -179,7 +239,7 @@ skipname (pat, dname, flags)
(dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
return 1;
/* If a dot must be explicity matched, check to see if they do. */
/* If a dot must be explicitly matched, check to see if they do. */
else if (noglob_dot_filenames && dname[0] == '.' && pat[0] != '.' &&
(pat[0] != '\\' || pat[1] != '.'))
return 1;
@ -188,18 +248,91 @@ skipname (pat, dname, flags)
}
#if HANDLE_MULTIBYTE
static int
wchkname (pat_wc, dn_wc)
wchar_t *pat_wc, *dn_wc;
{
/* If a leading dot need not be explicitly matched, and the
pattern doesn't start with a `.', don't match `.' or `..' */
if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' &&
(pat_wc[0] != L'\\' || pat_wc[1] != L'.') &&
(dn_wc[0] == L'.' &&
(dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0'))))
return 1;
/* If a leading dot must be explicitly matched, check to see if the
pattern and dirname both have one. */
else if (noglob_dot_filenames && dn_wc[0] == L'.' &&
pat_wc[0] != L'.' &&
(pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
return 1;
return 0;
}
static int
wextglob_skipname (pat, dname, flags)
wchar_t *pat, *dname;
int flags;
{
#if EXTENDED_GLOB
wchar_t *pp, *pe, *t, n;
int r;
pp = pat + 2;
pe = pp + wcslen (pp) - 1; /*(*/
if (*pe != L')')
return 0;
if ((t = wcschr (pp, L'|')) == 0)
{
*pe = L'\0';
r = wchkname (pp, dname); /*(*/
*pe = L')';
return r;
}
while (t = glob_patscan_wc (pp, pe, '|'))
{
n = t[-1];
t[-1] = L'\0';
r = wchkname (pp, dname);
t[-1] = n;
if (r == 0)
return 0;
pp = t;
}
if (pp == pe) /* glob_patscan_wc might find end of pattern */
return r;
*pe = L'\0';
r = wchkname (pp, dname); /*(*/
*pe = L')';
return r;
#else
return (wchkname (pat, dname));
#endif
}
/* 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;
{
int ret;
int ret, ext;
wchar_t *pat_wc, *dn_wc;
size_t pat_n, dn_n;
if (mbsmbchar (dname) == 0 && mbsmbchar (pat) == 0)
return (skipname (pat, dname, flags));
ext = 0;
#if EXTENDED_GLOB
ext = extglob_pattern_p (pat);
#endif
pat_wc = dn_wc = (wchar_t *)NULL;
pat_n = xdupmbstowcs (&pat_wc, NULL, pat);
@ -208,22 +341,7 @@ mbskipname (pat, dname, flags)
ret = 0;
if (pat_n != (size_t)-1 && dn_n !=(size_t)-1)
{
/* If a leading dot need not be explicitly matched, and the
pattern doesn't start with a `.', don't match `.' or `..' */
if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' &&
(pat_wc[0] != L'\\' || pat_wc[1] != L'.') &&
(dn_wc[0] == L'.' &&
(dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0'))))
ret = 1;
/* If a leading dot must be explicity matched, check to see if the
pattern and dirname both have one. */
else if (noglob_dot_filenames && dn_wc[0] == L'.' &&
pat_wc[0] != L'.' &&
(pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
ret = 1;
}
ret = ext ? wextglob_skipname (pat_wc, dn_wc, flags) : wchkname (pat_wc, dn_wc);
else
ret = skipname (pat, dname, flags);
@ -325,13 +443,20 @@ dequote_pathname (pathname)
/* Return 0 if DIR is a directory, -1 otherwise. */
static int
glob_testdir (dir)
glob_testdir (dir, flags)
char *dir;
int flags;
{
struct stat finfo;
int r;
/*itrace("glob_testdir: testing %s", dir);*/
if (stat (dir, &finfo) < 0)
/*itrace("glob_testdir: testing %s" flags = %d, dir, flags);*/
#if defined (HAVE_LSTAT)
r = (flags & GX_ALLDIRS) ? lstat (dir, &finfo) : stat (dir, &finfo);
#else
r = stat (dir, &finfo);
#endif
if (r < 0)
return (-1);
if (S_ISDIR (finfo.st_mode) == 0)
@ -407,7 +532,6 @@ finddirs (pat, sdir, flags, ep, np)
return ret;
}
/* Return a vector of names of files in directory DIR
whose names match glob pattern PAT.
@ -456,7 +580,7 @@ glob_vector (pat, dir, flags)
/* If PAT is empty, skip the loop, but return one (empty) filename. */
if (pat == 0 || *pat == '\0')
{
if (glob_testdir (dir) < 0)
if (glob_testdir (dir, 0) < 0)
return ((char **) &glob_error_return);
nextlink = (struct globval *)alloca (sizeof (struct globval));
@ -478,7 +602,7 @@ glob_vector (pat, dir, flags)
skip = 1;
}
patlen = strlen (pat);
patlen = (pat && *pat) ? strlen (pat) : 0;
/* If the filename pattern (PAT) does not contain any globbing characters,
we can dispense with reading the directory, and just see if there is
@ -489,14 +613,18 @@ glob_vector (pat, dir, flags)
int dirlen;
struct stat finfo;
if (glob_testdir (dir) < 0)
if (glob_testdir (dir, 0) < 0)
return ((char **) &glob_error_return);
dirlen = strlen (dir);
nextname = (char *)malloc (dirlen + patlen + 2);
npat = (char *)malloc (patlen + 1);
if (nextname == 0 || npat == 0)
lose = 1;
{
FREE (nextname);
FREE (npat);
lose = 1;
}
else
{
strcpy (npat, pat);
@ -518,7 +646,10 @@ glob_vector (pat, dir, flags)
count = 1;
}
else
lose = 1;
{
free (npat);
lose = 1;
}
}
else
{
@ -536,7 +667,7 @@ glob_vector (pat, dir, flags)
is not robust (i.e., it opens non-directories successfully), test
that DIR is a directory and punt if it's not. */
#if defined (OPENDIR_NOT_ROBUST)
if (glob_testdir (dir) < 0)
if (glob_testdir (dir, 0) < 0)
return ((char **) &glob_error_return);
#endif
@ -570,7 +701,12 @@ glob_vector (pat, dir, flags)
lose = 1;
break;
}
else if (signal_is_pending (SIGINT)) /* XXX - make SIGINT traps responsive */
{
lose = 1;
break;
}
dp = readdir (d);
if (dp == NULL)
break;
@ -599,7 +735,7 @@ glob_vector (pat, dir, flags)
if (flags & GX_NULLDIR)
pflags |= MP_IGNDOT;
subdir = sh_makepath (dir, dp->d_name, pflags);
isdir = glob_testdir (subdir);
isdir = glob_testdir (subdir, flags);
if (isdir < 0 && (flags & GX_MATCHDIRS))
{
free (subdir);
@ -635,6 +771,8 @@ glob_vector (pat, dir, flags)
nextname = (char *) malloc (sdlen + 1);
if (nextlink == 0 || nextname == 0)
{
FREE (nextlink);
FREE (nextname);
free (subdir);
lose = 1;
break;
@ -647,6 +785,8 @@ glob_vector (pat, dir, flags)
++count;
continue;
}
else if (flags & GX_MATCHDIRS)
free (subdir);
convfn = fnx_fromfs (dp->d_name, D_NAMLEN (dp));
if (strmatch (pat, convfn, mflags) != FNM_NOMATCH)
@ -666,6 +806,8 @@ glob_vector (pat, dir, flags)
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
if (nextlink == 0 || nextname == 0)
{
FREE (nextlink);
FREE (nextname);
lose = 1;
break;
}
@ -689,7 +831,11 @@ glob_vector (pat, dir, flags)
nextname = (char *)malloc (sdlen + 1);
nextlink = (struct globval *) malloc (sizeof (struct globval));
if (nextlink == 0 || nextname == 0)
lose = 1;
{
FREE (nextlink);
FREE (nextname);
lose = 1;
}
else
{
nextlink->name = nextname;
@ -733,7 +879,7 @@ glob_vector (pat, dir, flags)
FREE (tmplink);
}
QUIT;
/* Don't call QUIT; here; let higher layers deal with it. */
return ((char **)NULL);
}
@ -815,7 +961,13 @@ glob_dir_to_array (dir, array, flags)
result[i] = (char *) malloc (l + strlen (array[i]) + 3);
if (result[i] == NULL)
return (NULL);
{
int ind;
for (ind = 0; ind < i; ind++)
free (result[ind]);
free (result);
return (NULL);
}
strcpy (result[i], dir);
if (add_slash)
@ -893,19 +1045,70 @@ glob_filename (pathname, flags)
/* If directory_name contains globbing characters, then we
have to expand the previous levels. Just recurse. */
if (glob_pattern_p (directory_name))
if (directory_len > 0 && glob_pattern_p (directory_name))
{
char **directories;
char **directories, *d, *p;
register unsigned int i;
int all_starstar, last_starstar;
all_starstar = last_starstar = 0;
d = directory_name;
dflags = flags & ~GX_MARKDIRS;
if ((flags & GX_GLOBSTAR) && directory_name[0] == '*' && directory_name[1] == '*' && (directory_name[2] == '/' || directory_name[2] == '\0'))
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
/* Collapse a sequence of ** patterns separated by one or more slashes
to a single ** terminated by a slash or NUL */
if ((flags & GX_GLOBSTAR) && d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0'))
{
p = d;
while (d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0'))
{
p = d;
if (d[2])
{
d += 3;
while (*d == '/')
d++;
if (*d == 0)
break;
}
}
if (*d == 0)
all_starstar = 1;
d = p;
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
directory_len = strlen (d);
}
if (directory_name[directory_len - 1] == '/')
directory_name[directory_len - 1] = '\0';
/* If there is a non [star][star]/ component in directory_name, we
still need to collapse trailing sequences of [star][star]/ into
a single one and note that the directory name ends with [star][star],
so we can compensate if filename is [star][star] */
if ((flags & GX_GLOBSTAR) && all_starstar == 0)
{
int dl, prev;
prev = dl = directory_len;
while (dl >= 4 && d[dl - 1] == '/' &&
d[dl - 2] == '*' &&
d[dl - 3] == '*' &&
d[dl - 4] == '/')
prev = dl, dl -= 3;
if (dl != directory_len)
last_starstar = 1;
directory_len = prev;
}
directories = glob_filename (directory_name, dflags);
/* If the directory name ends in [star][star]/ but the filename is
[star][star], just remove the final [star][star] from the directory
so we don't have to scan everything twice. */
if (last_starstar && directory_len > 4 &&
filename[0] == '*' && filename[1] == '*' && filename[2] == 0)
{
directory_len -= 3;
}
if (d[directory_len - 1] == '/')
d[directory_len - 1] = '\0';
directories = glob_filename (d, dflags);
if (free_dirname)
{
@ -927,13 +1130,26 @@ glob_filename (pathname, flags)
return ((char **) &glob_error_return);
}
/* If we have something like [star][star]/[star][star], it's no use to
glob **, then do it again, and throw half the results away. */
if (all_starstar && filename[0] == '*' && filename[1] == '*' && filename[2] == 0)
{
free ((char *) directories);
free (directory_name);
directory_name = NULL;
directory_len = 0;
goto only_filename;
}
/* We have successfully globbed the preceding directory name.
For each name in DIRECTORIES, call glob_vector on it and
FILENAME. Concatenate the results together. */
for (i = 0; directories[i] != NULL; ++i)
{
char **temp_results;
int shouldbreak;
shouldbreak = 0;
/* XXX -- we've recursively scanned any directories resulting from
a `**', so turn off the flag. We turn it on again below if
filename is `**' */
@ -964,8 +1180,39 @@ glob_filename (pathname, flags)
/* If we're expanding **, we don't need to glue the directory
name to the results; we've already done it in glob_vector */
if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
array = temp_results;
if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && (filename[2] == '\0' || filename[2] == '/'))
{
/* When do we remove null elements from temp_results? And
how to avoid duplicate elements in the final result? */
/* If (dflags & GX_NULLDIR) glob_filename potentially left a
NULL placeholder in the temp results just in case
glob_vector/glob_dir_to_array did something with it, but
if it didn't, and we're not supposed to be passing them
through for some reason ((flags & GX_NULLDIR) == 0) we
need to remove all the NULL elements from the beginning
of TEMP_RESULTS. */
/* If we have a null directory name and ** as the filename,
we have just searched for everything from the current
directory on down. Break now (shouldbreak = 1) to avoid
duplicate entries in the final result. */
#define NULL_PLACEHOLDER(x) ((x) && *(x) && **(x) == 0)
if ((dflags & GX_NULLDIR) && (flags & GX_NULLDIR) == 0 &&
NULL_PLACEHOLDER (temp_results))
#undef NULL_PLACEHOLDER
{
register int i, n;
for (n = 0; temp_results[n] && *temp_results[n] == 0; n++)
;
i = n;
do
temp_results[i - n] = temp_results[i];
while (temp_results[i++] != 0);
array = temp_results;
shouldbreak = 1;
}
else
array = temp_results;
}
else
array = glob_dir_to_array (directories[i], temp_results, flags);
l = 0;
@ -986,6 +1233,11 @@ glob_filename (pathname, flags)
/* Note that the elements of ARRAY are not freed. */
if (array != temp_results)
free ((char *) array);
else if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
free (temp_results); /* expanding ** case above */
if (shouldbreak)
break;
}
}
/* Free the directories. */
@ -997,6 +1249,7 @@ glob_filename (pathname, flags)
return (result);
}
only_filename:
/* If there is only a directory name, return it. */
if (*filename == '\0')
{
@ -1055,10 +1308,13 @@ glob_filename (pathname, flags)
{
if (free_dirname)
free (directory_name);
QUIT; /* XXX - shell */
run_pending_traps ();
return (temp_results);
}
result = glob_dir_to_array ((dflags & GX_ALLDIRS) ? "" : directory_name, temp_results, flags);
if (free_dirname)
free (directory_name);
return (result);
@ -1079,6 +1335,7 @@ glob_filename (pathname, flags)
free (directory_name);
QUIT;
run_pending_traps ();
return (NULL);
}

View file

@ -35,6 +35,8 @@ extern int glob_pattern_p __P((const char *));
extern char **glob_vector __P((char *, char *, int));
extern char **glob_filename __P((char *, int));
extern int extglob_pattern_p __P((const char *));
extern char *glob_error_return;
extern int noglob_dot_filenames;
extern int glob_ignore_case;

View file

@ -200,6 +200,24 @@ bad_bracket:
}
#endif
int
extglob_pattern_p (pat)
char *pat;
{
switch (pat[0])
{
case '*':
case '+':
case '!':
case '@':
return (pat[1] == LPAREN);
default:
return 0;
}
return 0;
}
/* Return 1 of the first character of STRING could match the first
character of pattern PAT. Used to avoid n2 calls to strmatch(). */
int

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1991-2006 Free Software Foundation, Inc.
/* Copyright (C) 1991-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -22,7 +22,8 @@ static int GMATCH __P((CHAR *, CHAR *, CHAR *, CHAR *, int));
static CHAR *PARSE_COLLSYM __P((CHAR *, INT *));
static CHAR *BRACKMATCH __P((CHAR *, U_CHAR, int));
static int EXTMATCH __P((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
static CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
/*static*/ CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
int
FCT (pattern, string, flags)
@ -144,8 +145,9 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
if (EXTMATCH (c, newn, se, p, pe, flags) == 0)
return (0);
}
/* We didn't match. If we have a `?(...)', that's failure. */
return FNM_NOMATCH;
/* We didn't match. If we have a `?(...)', we can match 0
or 1 times. */
return 0;
}
#endif
else if (c == L('?'))
@ -191,6 +193,18 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
if (p == pe && (c == L('?') || c == L('*')))
return (0);
/* If we've hit the end of the string and the rest of the pattern
is something that matches the empty string, we can succeed. */
#if defined (EXTENDED_GLOB)
if (n == se && ((flags & FNM_EXTMATCH) && (c == L('!') || c == L('?')) && *p == L('(')))
{
--p;
if (EXTMATCH (c, n, se, p, pe, flags) == 0)
return (c == L('!') ? FNM_NOMATCH : 0);
return (c == L('!') ? 0 : FNM_NOMATCH);
}
#endif
/* General case, use recursion. */
{
U_CHAR c1;
@ -290,7 +304,7 @@ BRACKMATCH (p, test, flags)
{
register CHAR cstart, cend, c;
register int not; /* Nonzero if the sense of the character class is inverted. */
int brcnt;
int brcnt, forcecoll;
INT pc;
CHAR *savep;
@ -311,6 +325,7 @@ BRACKMATCH (p, test, flags)
/* Initialize cstart and cend in case `-' is the last
character of the pattern. */
cstart = cend = c;
forcecoll = 0;
/* POSIX.2 equivalence class: [=c=]. See POSIX.2 2.8.3.2. Find
the end of the equivalence class, move the pattern pointer past
@ -400,6 +415,7 @@ BRACKMATCH (p, test, flags)
range. If it is, we set cstart to one greater than `test',
so any comparisons later will fail. */
cstart = (pc == INVALID) ? test + 1 : pc;
forcecoll = 1;
}
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
@ -443,6 +459,7 @@ BRACKMATCH (p, test, flags)
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;
forcecoll = 1;
}
cend = FOLD (cend);
@ -453,7 +470,7 @@ BRACKMATCH (p, test, flags)
the expression shall be treated as invalid.'' Note that this
applies to only the range expression; the rest of the bracket
expression is still checked for matches. */
if (RANGECMP (cstart, cend) > 0)
if (RANGECMP (cstart, cend, forcecoll) > 0)
{
if (c == L(']'))
break;
@ -462,7 +479,7 @@ BRACKMATCH (p, test, flags)
}
}
if (RANGECMP (test, cstart) >= 0 && RANGECMP (test, cend) <= 0)
if (RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
goto matched;
if (c == L(']'))
@ -517,7 +534,7 @@ matched:
because we're scanning a `patlist'. Otherwise, we scan until we see
DELIM. In all cases, we never scan past END. The return value is the
first character after the matching DELIM. */
static CHAR *
/*static*/ CHAR *
PATSCAN (string, end, delim)
CHAR *string, *end;
INT delim;
@ -530,6 +547,9 @@ PATSCAN (string, end, delim)
cchar = 0;
bfirst = NULL;
if (string == end)
return (NULL);
for (s = string; c = *s; s++)
{
if (s >= end)
@ -606,19 +626,32 @@ STRCOMPARE (p, pe, s, se)
{
int ret;
CHAR c1, c2;
int l1, l2;
l1 = pe - p;
l2 = se - s;
if (l1 != l2)
return (FNM_NOMATCH); /* unequal lengths, can't be identical */
c1 = *pe;
c2 = *se;
*pe = *se = '\0';
if (c1 != 0)
*pe = '\0';
if (c2 != 0)
*se = '\0';
#if HAVE_MULTIBYTE || defined (HAVE_STRCOLL)
ret = STRCOLL ((XCHAR *)p, (XCHAR *)s);
#else
ret = STRCMP ((XCHAR *)p, (XCHAR *)s);
#endif
*pe = c1;
*se = c2;
if (c1 != 0)
*pe = c1;
if (c2 != 0)
*se = c2;
return (ret == 0 ? ret : FNM_NOMATCH);
}

View file

@ -43,15 +43,25 @@
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
#ifndef GLOBASCII_DEFAULT
# define GLOBASCII_DEFAULT 0
#endif
int glob_asciirange = GLOBASCII_DEFAULT;
/* We use strcoll(3) for range comparisons in bracket expressions,
even though it can have unwanted side effects in locales
other than POSIX or US. For instance, in the de locale, [A-Z] matches
all characters. */
all characters. If GLOB_ASCIIRANGE is non-zero, and we're not forcing
the use of strcoll (e.g., for explicit collating symbols), we use
straight ordering as if in the C locale. */
#if defined (HAVE_STRCOLL)
/* Helper function for collating symbol equivalence. */
static int rangecmp (c1, c2)
static int
rangecmp (c1, c2, forcecoll)
int c1, c2;
int forcecoll;
{
static char s1[2] = { ' ', '\0' };
static char s2[2] = { ' ', '\0' };
@ -64,6 +74,9 @@ static int rangecmp (c1, c2)
if (c1 == c2)
return (0);
if (forcecoll == 0 && glob_asciirange)
return (c1 - c2);
s1[0] = c1;
s2[0] = c2;
@ -72,7 +85,7 @@ static int rangecmp (c1, c2)
return (c1 - c2);
}
#else /* !HAVE_STRCOLL */
# define rangecmp(c1, c2) ((int)(c1) - (int)(c2))
# define rangecmp(c1, c2, f) ((int)(c1) - (int)(c2))
#endif /* !HAVE_STRCOLL */
#if defined (HAVE_STRCOLL)
@ -80,7 +93,7 @@ static int
collequiv (c1, c2)
int c1, c2;
{
return (rangecmp (c1, c2) == 0);
return (rangecmp (c1, c2, 1) == 0);
}
#else
# define collequiv(c1, c2) ((c1) == (c2))
@ -214,14 +227,14 @@ is_cclass (c, name)
#define COLLSYM collsym
#define PARSE_COLLSYM parse_collsym
#define BRACKMATCH brackmatch
#define PATSCAN patscan
#define PATSCAN glob_patscan
#define STRCOMPARE strcompare
#define EXTMATCH extmatch
#define STRCHR(S, C) strchr((S), (C))
#define STRCOLL(S1, S2) strcoll((S1), (S2))
#define STRLEN(S) strlen(S)
#define STRCMP(S1, S2) strcmp((S1), (S2))
#define RANGECMP(C1, C2) rangecmp((C1), (C2))
#define RANGECMP(C1, C2, F) rangecmp((C1), (C2), (F))
#define COLLEQUIV(C1, C2) collequiv((C1), (C2))
#define CTYPE_T enum char_class
#define IS_CCLASS(C, S) is_cclass((C), (S))
@ -244,8 +257,9 @@ is_cclass (c, name)
extern char *mbsmbchar __P((const char *));
static int
rangecmp_wc (c1, c2)
rangecmp_wc (c1, c2, forcecoll)
wint_t c1, c2;
int forcecoll;
{
static wchar_t s1[2] = { L' ', L'\0' };
static wchar_t s2[2] = { L' ', L'\0' };
@ -253,6 +267,9 @@ rangecmp_wc (c1, c2)
if (c1 == c2)
return 0;
if (forcecoll == 0 && glob_asciirange && c1 <= UCHAR_MAX && c2 <= UCHAR_MAX)
return ((int)(c1 - c2));
s1[0] = c1;
s2[0] = c2;
@ -263,7 +280,7 @@ static int
collequiv_wc (c, equiv)
wint_t c, equiv;
{
return (!(c - equiv));
return (c == equiv);
}
/* Helper function for collating symbol. */
@ -342,14 +359,14 @@ is_wcclass (wc, name)
#define COLLSYM collwcsym
#define PARSE_COLLSYM parse_collwcsym
#define BRACKMATCH brackmatch_wc
#define PATSCAN patscan_wc
#define PATSCAN glob_patscan_wc
#define STRCOMPARE wscompare
#define EXTMATCH extmatch_wc
#define STRCHR(S, C) wcschr((S), (C))
#define STRCOLL(S1, S2) wcscoll((S1), (S2))
#define STRLEN(S) wcslen(S)
#define STRCMP(S1, S2) wcscmp((S1), (S2))
#define RANGECMP(C1, C2) rangecmp_wc((C1), (C2))
#define RANGECMP(C1, C2, F) rangecmp_wc((C1), (C2), (F))
#define COLLEQUIV(C1, C2) collequiv_wc((C1), (C2))
#define CTYPE_T enum char_class
#define IS_CCLASS(C, S) is_wcclass((C), (S))
@ -369,13 +386,7 @@ xstrmatch (pattern, string, flags)
wchar_t *wpattern, *wstring;
size_t plen, slen, mplen, mslen;
#if 0
plen = strlen (pattern);
mplen = mbstrlen (pattern);
if (plen == mplen && strlen (string) == mbstrlen (string))
#else
if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
#endif
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
if (MB_CUR_MAX == 1)

View file

@ -1,6 +1,6 @@
/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
/* Copyright (C) 2002-2010 Free Software Foundation, Inc.
/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -166,7 +166,7 @@ xdupmbstowcs2 (destp, src)
do
{
end_or_backslash = strchrnul(p, '\\');
nms = (end_or_backslash - p);
nms = end_or_backslash - p;
if (*end_or_backslash == '\0')
nms++;
@ -283,6 +283,8 @@ xdupmbstowcs (destp, indicesp, src)
{
if (destp)
*destp = NULL;
if (indicesp)
*indicesp = NULL;
return (size_t)-1;
}
@ -298,6 +300,8 @@ xdupmbstowcs (destp, indicesp, src)
if (wsbuf == NULL)
{
*destp = NULL;
if (indicesp)
*indicesp = NULL;
return (size_t)-1;
}
@ -309,6 +313,7 @@ xdupmbstowcs (destp, indicesp, src)
{
free (wsbuf);
*destp = NULL;
*indicesp = NULL;
return (size_t)-1;
}
}
@ -343,6 +348,8 @@ xdupmbstowcs (destp, indicesp, src)
free (wsbuf);
FREE (indices);
*destp = NULL;
if (indicesp)
*indicesp = NULL;
return (size_t)-1;
}
@ -362,18 +369,22 @@ xdupmbstowcs (destp, indicesp, src)
free (wsbuf);
FREE (indices);
*destp = NULL;
if (indicesp)
*indicesp = NULL;
return (size_t)-1;
}
wsbuf = wstmp;
if (indicesp)
{
idxtmp = (char **) realloc (indices, wsbuf_size * sizeof (char **));
idxtmp = (char **) realloc (indices, wsbuf_size * sizeof (char *));
if (idxtmp == NULL)
{
free (wsbuf);
free (indices);
*destp = NULL;
if (indicesp)
*indicesp = NULL;
return (size_t)-1;
}
indices = idxtmp;