commit bash-20170120 snapshot

This commit is contained in:
Chet Ramey
2017-01-30 15:48:59 -05:00
parent 3e8a02a689
commit 571ba52b71
15 changed files with 324 additions and 383 deletions
+1
View File
@@ -164,4 +164,5 @@ xmbsrtowcs.o: xmbsrtowcs.c
# dependencies for C files that include other C files
glob.o: glob_loop.c
gmisc.o: gm_loop.c
smatch.o: sm_loop.c
+13 -12
View File
@@ -1,6 +1,6 @@
/* glob.c -- file-name wildcard pattern matching for Bash.
Copyright (C) 1985-2009 Free Software Foundation, Inc.
Copyright (C) 1985-2017 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -123,6 +123,9 @@ static char **glob_dir_to_array __P((char *, char **, int));
extern char *glob_patscan __P((char *, char *, int));
extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int));
/* And this from gmisc.c/gm_loop.c */
extern int wextglob_pattern_p __P((wchar_t *));
extern char *glob_dirscan __P((char *, int));
/* Compile `glob_loop.c' for single-byte characters. */
@@ -131,7 +134,6 @@ extern char *glob_dirscan __P((char *, int));
#define INT int
#define L(CS) CS
#define INTERNAL_GLOB_PATTERN_P internal_glob_pattern_p
#define EXTGLOB_PATTERN_P extglob_pattern_p
#include "glob_loop.c"
/* Compile `glob_loop.c' again for multibyte characters. */
@@ -142,7 +144,6 @@ extern char *glob_dirscan __P((char *, int));
#define INT wint_t
#define L(CS) L##CS
#define INTERNAL_GLOB_PATTERN_P internal_glob_wpattern_p
#define EXTGLOB_PATTERN_P wextglob_pattern_p
#include "glob_loop.c"
#endif /* HANDLE_MULTIBYTE */
@@ -275,23 +276,23 @@ skipname (pat, dname, flags)
#if HANDLE_MULTIBYTE
static int
wskipname (pat_wc, dn_wc, flags)
wchar_t *pat_wc, *dn_wc;
wskipname (pat, dname, flags)
wchar_t *pat, *dname;
int flags;
{
/* 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'))))
if (noglob_dot_filenames == 0 && pat[0] != L'.' &&
(pat[0] != L'\\' || pat[1] != L'.') &&
(dname[0] == L'.' &&
(dname[1] == L'\0' || (dname[1] == L'.' && dname[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'.'))
else if (noglob_dot_filenames && dname[0] == L'.' &&
pat[0] != L'.' &&
(pat[0] != L'\\' || pat[1] != L'.'))
return 1;
return 0;
+1 -23
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1991-2005 Free Software Foundation, Inc.
/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -61,28 +61,6 @@ INTERNAL_GLOB_PATTERN_P (pattern)
return 0;
}
#if EXTENDED_GLOB
int
EXTGLOB_PATTERN_P (pat)
const CHAR *pat;
{
switch (pat[0])
{
case L('*'):
case L('+'):
case L('!'):
case L('@'):
case L('?'):
return (pat[1] == L('(')); /* ) */
default:
return 0;
}
return 0;
}
#endif
#undef EXTGLOB_PATTERN_P
#undef INTERNAL_GLOB_PATTERN_P
#undef L
#undef INT
+208
View File
@@ -0,0 +1,208 @@
/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if EXTENDED_GLOB
int
EXTGLOB_PATTERN_P (pat)
const CHAR *pat;
{
switch (pat[0])
{
case L('*'):
case L('+'):
case L('!'):
case L('@'):
case L('?'):
return (pat[1] == L('(')); /* ) */
default:
return 0;
}
return 0;
}
#endif
/* Return 1 of the first character of STRING could match the first
character of pattern PAT. Compiled to both single and wiide character
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;
{
CHAR c;
if (*string == 0)
return (*pat == L('*')); /* XXX - allow only * to match empty string */
switch (c = *pat++)
{
default:
return (FOLD(*string) == FOLD(c));
case L('\\'):
return (FOLD(*string) == FOLD(*pat));
case L('?'):
return (*pat == L('(') ? 1 : (*string != L'\0'));
case L('*'):
return (1);
case L('+'):
case L('!'):
case L('@'):
return (*pat == L('(') ? 1 : (FOLD(*string) == FOLD(c)));
case L('['):
return (*string != L('\0'));
}
}
int
MATCHLEN (pat, max)
CHAR *pat;
size_t max;
{
CHAR c;
int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
if (*pat == 0)
return (0);
matlen = in_cclass = in_collsym = in_equiv = 0;
while (c = *pat++)
{
switch (c)
{
default:
matlen++;
break;
case L('\\'):
if (*pat == 0)
return ++matlen;
else
{
matlen++;
pat++;
}
break;
case L('?'):
if (*pat == LPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case L('*'):
return (matlen = -1);
case L('+'):
case L('!'):
case L('@'):
if (*pat == LPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case L('['):
/* scan for ending `]', skipping over embedded [:...:] */
bracklen = 1;
c = *pat++;
do
{
if (c == 0)
{
pat--; /* back up to NUL */
matlen += bracklen;
goto bad_bracket;
}
else if (c == L('\\'))
{
/* *pat == backslash-escaped character */
bracklen++;
/* If the backslash or backslash-escape ends the string,
bail. The ++pat skips over the backslash escape */
if (*pat == 0 || *++pat == 0)
{
matlen += bracklen;
goto bad_bracket;
}
}
else if (c == L('[') && *pat == L(':')) /* character class */
{
pat++;
bracklen++;
in_cclass = 1;
}
else if (in_cclass && c == L(':') && *pat == L(']'))
{
pat++;
bracklen++;
in_cclass = 0;
}
else if (c == L('[') && *pat == L('.')) /* collating symbol */
{
pat++;
bracklen++;
if (*pat == L(']')) /* right bracket can appear as collating symbol */
{
pat++;
bracklen++;
}
in_collsym = 1;
}
else if (in_collsym && c == L('.') && *pat == L(']'))
{
pat++;
bracklen++;
in_collsym = 0;
}
else if (c == L('[') && *pat == L('=')) /* equivalence class */
{
pat++;
bracklen++;
if (*pat == L(']')) /* right bracket can appear as equivalence class */
{
pat++;
bracklen++;
}
in_equiv = 1;
}
else if (in_equiv && c == L('=') && *pat == L(']'))
{
pat++;
bracklen++;
in_equiv = 0;
}
else
bracklen++;
}
while ((c = *pat++) != L(']'));
matlen++; /* bracket expression can only match one char */
bad_bracket:
break;
}
}
return matlen;
}
#undef EXTGLOB_PATTERN_P
#undef MATCH_PATTERN_CHAR
#undef MATCHLEN
#undef FOLD
#undef L
#undef LPAREN
#undef RPAREN
#undef INT
#undef CHAR
+27 -331
View File
@@ -1,6 +1,6 @@
/* gmisc.c -- miscellaneous pattern matching utility functions for Bash.
Copyright (C) 2010 Free Software Foundation, Inc.
Copyright (C) 2010-2017 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -35,348 +35,44 @@
#ifndef FNM_CASEFOLD
# include "strmatch.h"
#endif
#ifndef LPAREN
# define LPAREN '('
#endif
#ifndef RPAREN
# define RPAREN ')'
#endif
#if defined (HANDLE_MULTIBYTE)
#define WLPAREN L'('
#define WRPAREN L')'
#include "glob.h"
/* 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));
#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c))
/* Return 1 of the first character of WSTRING could match the first
character of pattern WPAT. Wide character version. FLAGS is a
subset of strmatch flags; used to do case-insensitive matching for now. */
int
match_pattern_wchar (wpat, wstring, flags)
wchar_t *wpat, *wstring;
int flags;
{
wchar_t wc;
if (*wstring == 0)
return (*wpat == L'*'); /* XXX - allow only * to match empty string */
switch (wc = *wpat++)
{
default:
return (FOLD(*wstring) == FOLD(wc));
case L'\\':
return (FOLD(*wstring) == FOLD(*wpat));
case L'?':
return (*wpat == WLPAREN ? 1 : (*wstring != L'\0'));
case L'*':
return (1);
case L'+':
case L'!':
case L'@':
return (*wpat == WLPAREN ? 1 : (FOLD(*wstring) == FOLD(wc)));
case L'[':
return (*wstring != L'\0');
}
}
int
wmatchlen (wpat, wmax)
wchar_t *wpat;
size_t wmax;
{
wchar_t wc;
int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
if (*wpat == 0)
return (0);
matlen = in_cclass = in_collsym = in_equiv = 0;
while (wc = *wpat++)
{
switch (wc)
{
default:
matlen++;
break;
case L'\\':
if (*wpat == 0)
return ++matlen;
else
{
matlen++;
wpat++;
}
break;
case L'?':
if (*wpat == WLPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case L'*':
return (matlen = -1);
case L'+':
case L'!':
case L'@':
if (*wpat == WLPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case L'[':
/* scan for ending `]', skipping over embedded [:...:] */
bracklen = 1;
wc = *wpat++;
do
{
if (wc == 0)
{
wpat--; /* back up to NUL */
matlen += bracklen;
goto bad_bracket;
}
else if (wc == L'\\')
{
/* *wpat == backslash-escaped character */
bracklen++;
/* If the backslash or backslash-escape ends the string,
bail. The ++wpat skips over the backslash escape */
if (*wpat == 0 || *++wpat == 0)
{
matlen += bracklen;
goto bad_bracket;
}
}
else if (wc == L'[' && *wpat == L':') /* character class */
{
wpat++;
bracklen++;
in_cclass = 1;
}
else if (in_cclass && wc == L':' && *wpat == L']')
{
wpat++;
bracklen++;
in_cclass = 0;
}
else if (wc == L'[' && *wpat == L'.') /* collating symbol */
{
wpat++;
bracklen++;
if (*wpat == L']') /* right bracket can appear as collating symbol */
{
wpat++;
bracklen++;
}
in_collsym = 1;
}
else if (in_collsym && wc == L'.' && *wpat == L']')
{
wpat++;
bracklen++;
in_collsym = 0;
}
else if (wc == L'[' && *wpat == L'=') /* equivalence class */
{
wpat++;
bracklen++;
if (*wpat == L']') /* right bracket can appear as equivalence class */
{
wpat++;
bracklen++;
}
in_equiv = 1;
}
else if (in_equiv && wc == L'=' && *wpat == L']')
{
wpat++;
bracklen++;
in_equiv = 0;
}
else
bracklen++;
}
while ((wc = *wpat++) != L']');
matlen++; /* bracket expression can only match one char */
bad_bracket:
break;
}
}
return matlen;
}
#endif
#undef FOLD
/* Compile `gm_loop.c' for single-byte characters. */
#define CHAR char
#define INT int
#define L(CS) CS
#define EXTGLOB_PATTERN_P extglob_pattern_p
#define MATCH_PATTERN_CHAR match_pattern_char
#define MATCHLEN umatchlen
#define FOLD(c) ((flags & FNM_CASEFOLD) \
? TOLOWER ((unsigned char)c) \
: ((unsigned char)c))
#ifndef LPAREN
#define LPAREN '('
#define RPAREN ')'
#endif
#include "gm_loop.c"
/* Return 1 of the first character of STRING could match the first
character of pattern PAT. Used to avoid n2 calls to strmatch().
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;
{
char c;
/* Compile `gm_loop.c' again for multibyte characters. */
#if HANDLE_MULTIBYTE
if (*string == 0)
return (*pat == '*'); /* XXX - allow only * to match empty string */
#define CHAR wchar_t
#define INT wint_t
#define L(CS) L##CS
#define EXTGLOB_PATTERN_P wextglob_pattern_p
#define MATCH_PATTERN_CHAR match_pattern_wchar
#define MATCHLEN wmatchlen
switch (c = *pat++)
{
default:
return (FOLD(*string) == FOLD(c));
case '\\':
return (FOLD(*string) == FOLD(*pat));
case '?':
return (*pat == LPAREN ? 1 : (*string != '\0'));
case '*':
return (1);
case '+':
case '!':
case '@':
return (*pat == LPAREN ? 1 : (FOLD(*string) == FOLD(c)));
case '[':
return (*string != '\0');
}
}
#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c))
#define LPAREN L'('
#define RPAREN L')'
#include "gm_loop.c"
int
umatchlen (pat, max)
char *pat;
size_t max;
{
char c;
int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
#endif /* HANDLE_MULTIBYTE */
if (*pat == 0)
return (0);
matlen = in_cclass = in_collsym = in_equiv = 0;
while (c = *pat++)
{
switch (c)
{
default:
matlen++;
break;
case '\\':
if (*pat == 0)
return ++matlen;
else
{
matlen++;
pat++;
}
break;
case '?':
if (*pat == LPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case '*':
return (matlen = -1);
case '+':
case '!':
case '@':
if (*pat == LPAREN)
return (matlen = -1); /* XXX for now */
else
matlen++;
break;
case '[':
/* scan for ending `]', skipping over embedded [:...:] */
bracklen = 1;
c = *pat++;
do
{
if (c == 0)
{
pat--; /* back up to NUL */
matlen += bracklen;
goto bad_bracket;
}
else if (c == '\\')
{
/* *pat == backslash-escaped character */
bracklen++;
/* If the backslash or backslash-escape ends the string,
bail. The ++pat skips over the backslash escape */
if (*pat == 0 || *++pat == 0)
{
matlen += bracklen;
goto bad_bracket;
}
}
else if (c == '[' && *pat == ':') /* character class */
{
pat++;
bracklen++;
in_cclass = 1;
}
else if (in_cclass && c == ':' && *pat == ']')
{
pat++;
bracklen++;
in_cclass = 0;
}
else if (c == '[' && *pat == '.') /* collating symbol */
{
pat++;
bracklen++;
if (*pat == ']') /* right bracket can appear as collating symbol */
{
pat++;
bracklen++;
}
in_collsym = 1;
}
else if (in_collsym && c == '.' && *pat == ']')
{
pat++;
bracklen++;
in_collsym = 0;
}
else if (c == '[' && *pat == '=') /* equivalence class */
{
pat++;
bracklen++;
if (*pat == ']') /* right bracket can appear as equivalence class */
{
pat++;
bracklen++;
}
in_equiv = 1;
}
else if (in_equiv && c == '=' && *pat == ']')
{
pat++;
bracklen++;
in_equiv = 0;
}
else
bracklen++;
}
while ((c = *pat++) != ']');
matlen++; /* bracket expression can only match one char */
bad_bracket:
break;
}
}
return matlen;
}
#if defined (EXTENDED_GLOB)
/* Skip characters in PAT and return the final occurrence of DIRSEP. This
+4 -1
View File
@@ -625,7 +625,10 @@ stat_char (filename)
#endif
if (r == -1)
return (0);
{
xfree (f);
return (0);
}
character = 0;
if (S_ISDIR (finfo.st_mode))