mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 23:53:18 +02:00
commit bash-20120914 snapshot
This commit is contained in:
@@ -3537,3 +3537,43 @@ expr.c
|
||||
short-circuiting evaluation completely. readtok will leave curtok
|
||||
set correctly without re-entering the evaluator at all. Rest of
|
||||
fix for bug reported by Dan Douglas <ormaaj@gmail.com>
|
||||
|
||||
9/11
|
||||
----
|
||||
|
||||
parse.y
|
||||
- parse_comsub: make sure the `reserved word ok in this context' flag
|
||||
is preserved after we read `do' followed by whitespace. Fixes bug
|
||||
reported by Benoit Vaugon <benoit.vaugon@gmail.com>
|
||||
|
||||
9/13
|
||||
----
|
||||
configure.ac,config.h.in
|
||||
- enable-direxpand-default: new configure option, turns the `direxpand'
|
||||
shell option on by default
|
||||
|
||||
bashline.c
|
||||
- dircomplete_expand, dircomplete_expand_relpath: initialize to 1 if
|
||||
DIRCOMPLETE_EXPAND_DEFAULT is defined and non-zero
|
||||
|
||||
doc/bashref.texi
|
||||
- enable-direxpand-default: document new configure option
|
||||
|
||||
9/14
|
||||
----
|
||||
shell.c
|
||||
- --protected: make option valid only when wordexp is compiled into
|
||||
the shell. Fix from Roman Rakus <rrakus@redhat.com>
|
||||
|
||||
configure.ac
|
||||
- HP NonStop (*-nsk*): compile --without-bash-malloc. Change from
|
||||
Joachim Schmitz <jojo@schmitz-digital.de>
|
||||
|
||||
9/16
|
||||
----
|
||||
subst.c,execute_cmd.c,lib/glob/sm_loop.c,lib/sh/shquote.c
|
||||
- minor code cleanups from Joachim Schmitz <jojo@schmitz-digital.de>
|
||||
|
||||
lib/readline/colors.h
|
||||
- workaround for HP NonStop compiler issue with <stdbool.h> from
|
||||
Joachim Schmitz <jojo@schmitz-digital.de>
|
||||
|
||||
+42
-4
@@ -3508,10 +3508,6 @@ redir.c
|
||||
9/8
|
||||
---
|
||||
expr.c
|
||||
- expr_streval: save and restore the value of `noeval' around any call
|
||||
to get_array_value, since that can end up recursively calling
|
||||
evalexp to perform array subscript evaluation. Fixes bug reported
|
||||
by Dan Douglas <ormaaj@gmail.com>
|
||||
- readtok: invalidate previous contents of `curlval' before freeing
|
||||
and reallocating tokstr (which, chances are, will get the same
|
||||
pointer as before and render curlval inconsistent). Fixes other
|
||||
@@ -3535,3 +3531,45 @@ lib/readline/display.c
|
||||
lib/readline/{terminal.c,rlprivate.h}
|
||||
- move CUSTOM_REDISPLAY_FUNC and CUSTOM_INPUT_FUNC defines from
|
||||
terminal.c to rlprivate.h so other files can use them
|
||||
|
||||
expr.c
|
||||
- expr_streval: if noeval is non-zero, just return 0 right away,
|
||||
short-circuiting evaluation completely. readtok will leave curtok
|
||||
set correctly without re-entering the evaluator at all. Rest of
|
||||
fix for bug reported by Dan Douglas <ormaaj@gmail.com>
|
||||
|
||||
9/11
|
||||
----
|
||||
|
||||
parse.y
|
||||
- parse_comsub: make sure the `reserved word ok in this context' flag
|
||||
is preserved after we read `do' followed by whitespace. Fixes bug
|
||||
reported by Benoit Vaugon <benoit.vaugon@gmail.com>
|
||||
|
||||
9/13
|
||||
----
|
||||
configure.ac,config.h.in
|
||||
- enable-direxpand-default: new configure option, turns the `direxpand'
|
||||
shell option on by default
|
||||
|
||||
bashline.c
|
||||
- dircomplete_expand, dircomplete_expand_relpath: initialize to 1 if
|
||||
DIRCOMPLETE_EXPAND_DEFAULT is defined and non-zero
|
||||
|
||||
doc/bashref.texi
|
||||
- enable-direxpand-default: document new configure option
|
||||
|
||||
9/14
|
||||
----
|
||||
shell.c
|
||||
- --protected: make option valid only when wordexp is compiled into
|
||||
the shell. Fix from Roman Rakus <rrakus@redhat.com>
|
||||
|
||||
configure.ac
|
||||
- HP NonStop (*-nsk*): compile --without-bash-malloc. Change from
|
||||
Joachim Schmitz <jojo@schmitz-digital.de>
|
||||
|
||||
9/16
|
||||
----
|
||||
subst.c,execute_cmd.c,lib/glob/sm_loop.c,lib/sh/shquote.c
|
||||
- minor code cleanups from Joachim Schmitz <jojo@schmitz-digital.de>
|
||||
|
||||
+15
-1
@@ -1,5 +1,5 @@
|
||||
@%:@! /bin/sh
|
||||
@%:@ From configure.ac for Bash 4.2, version 4.050.
|
||||
@%:@ From configure.ac for Bash 4.2, version 4.052.
|
||||
@%:@ Guess values for system-dependent variables and create Makefiles.
|
||||
@%:@ Generated by GNU Autoconf 2.68 for bash 4.2-maint.
|
||||
@%:@
|
||||
@@ -783,6 +783,7 @@ enable_cond_command
|
||||
enable_cond_regexp
|
||||
enable_coprocesses
|
||||
enable_debugger
|
||||
enable_direxpand_default
|
||||
enable_directory_stack
|
||||
enable_disabled_builtins
|
||||
enable_dparen_arithmetic
|
||||
@@ -1466,6 +1467,8 @@ Optional Features:
|
||||
--enable-coprocesses enable coprocess support and the coproc reserved
|
||||
word
|
||||
--enable-debugger enable support for bash debugger
|
||||
--enable-direxpand-default
|
||||
enable the direxpand shell option by default
|
||||
--enable-directory-stack
|
||||
enable builtins pushd/popd/dirs
|
||||
--enable-disabled-builtins
|
||||
@@ -2837,6 +2840,7 @@ sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF
|
||||
*-beos*) opt_bash_malloc=no ;; # they say it's suitable
|
||||
*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment
|
||||
*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft
|
||||
*-nsk*) opt_bash_malloc=no ;; # HP NonStop
|
||||
esac
|
||||
|
||||
# memory scrambling on free()
|
||||
@@ -2967,6 +2971,7 @@ opt_single_longdoc_strings=yes
|
||||
opt_casemod_attrs=yes
|
||||
opt_casemod_expansions=yes
|
||||
opt_extglob_default=no
|
||||
opt_dircomplete_expand_default=no
|
||||
|
||||
opt_static_link=no
|
||||
opt_profiling=no
|
||||
@@ -3049,6 +3054,11 @@ if test "${enable_debugger+set}" = set; then :
|
||||
enableval=$enable_debugger; opt_debugger=$enableval
|
||||
fi
|
||||
|
||||
@%:@ Check whether --enable-direxpand-default was given.
|
||||
if test "${enable_direxpand_default+set}" = set; then :
|
||||
enableval=$enable_direxpand_default; opt_dircomplete_expand_default=$enableval
|
||||
fi
|
||||
|
||||
@%:@ Check whether --enable-directory-stack was given.
|
||||
if test "${enable_directory_stack+set}" = set; then :
|
||||
enableval=$enable_directory_stack; opt_dirstack=$enableval
|
||||
@@ -3284,6 +3294,10 @@ fi
|
||||
if test $opt_casemod_expansions = yes; then
|
||||
$as_echo "@%:@define CASEMOD_EXPANSIONS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
if test $opt_dircomplete_expand_default = yes; then
|
||||
$as_echo "@%:@define DIRCOMPLETE_EXPAND_DEFAULT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
if test $opt_memscramble = yes; then
|
||||
|
||||
+1706
-1701
File diff suppressed because it is too large
Load Diff
@@ -255,8 +255,13 @@ int force_fignore = 1;
|
||||
int dircomplete_spelling = 0;
|
||||
|
||||
/* Expand directory names during word/filename completion. */
|
||||
#if DIRCOMPLETE_EXPAND_DEFAULT
|
||||
int dircomplete_expand = 1;
|
||||
int dircomplete_expand_relpath = 1;
|
||||
#else
|
||||
int dircomplete_expand = 0;
|
||||
int dircomplete_expand_relpath = 0;
|
||||
#endif
|
||||
|
||||
/* When non-zero, perform `normal' shell quoting on completed filenames
|
||||
even when the completed name contains a directory name with a shell
|
||||
|
||||
+6
-3
@@ -160,9 +160,6 @@
|
||||
memory contents on malloc() and free(). */
|
||||
#undef MEMSCRAMBLE
|
||||
|
||||
/* Define AFS if you are using Transarc's AFS. */
|
||||
#undef AFS
|
||||
|
||||
/* Define for case-modifying variable attributes; variables modified on
|
||||
assignment */
|
||||
#undef CASEMOD_ATTRS
|
||||
@@ -170,6 +167,12 @@
|
||||
/* Define for case-modifying word expansions */
|
||||
#undef CASEMOD_EXPANSIONS
|
||||
|
||||
/* Define to make the `direxpand' shopt option enabled by default. */
|
||||
#undef DIRCOMPLETE_EXPAND_DEFAULT
|
||||
|
||||
/* Define AFS if you are using Transarc's AFS. */
|
||||
#undef AFS
|
||||
|
||||
#undef ENABLE_NLS
|
||||
|
||||
/* End of configuration settings controllable by autoconf. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#! /bin/sh
|
||||
# From configure.ac for Bash 4.2, version 4.050.
|
||||
# From configure.ac for Bash 4.2, version 4.052.
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.68 for bash 4.2-maint.
|
||||
#
|
||||
@@ -783,6 +783,7 @@ enable_cond_command
|
||||
enable_cond_regexp
|
||||
enable_coprocesses
|
||||
enable_debugger
|
||||
enable_direxpand_default
|
||||
enable_directory_stack
|
||||
enable_disabled_builtins
|
||||
enable_dparen_arithmetic
|
||||
@@ -1466,6 +1467,8 @@ Optional Features:
|
||||
--enable-coprocesses enable coprocess support and the coproc reserved
|
||||
word
|
||||
--enable-debugger enable support for bash debugger
|
||||
--enable-direxpand-default
|
||||
enable the direxpand shell option by default
|
||||
--enable-directory-stack
|
||||
enable builtins pushd/popd/dirs
|
||||
--enable-disabled-builtins
|
||||
@@ -2837,6 +2840,7 @@ sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF
|
||||
*-beos*) opt_bash_malloc=no ;; # they say it's suitable
|
||||
*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment
|
||||
*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft
|
||||
*-nsk*) opt_bash_malloc=no ;; # HP NonStop
|
||||
esac
|
||||
|
||||
# memory scrambling on free()
|
||||
@@ -2967,6 +2971,7 @@ opt_single_longdoc_strings=yes
|
||||
opt_casemod_attrs=yes
|
||||
opt_casemod_expansions=yes
|
||||
opt_extglob_default=no
|
||||
opt_dircomplete_expand_default=no
|
||||
|
||||
opt_static_link=no
|
||||
opt_profiling=no
|
||||
@@ -3049,6 +3054,11 @@ if test "${enable_debugger+set}" = set; then :
|
||||
enableval=$enable_debugger; opt_debugger=$enableval
|
||||
fi
|
||||
|
||||
# Check whether --enable-direxpand-default was given.
|
||||
if test "${enable_direxpand_default+set}" = set; then :
|
||||
enableval=$enable_direxpand_default; opt_dircomplete_expand_default=$enableval
|
||||
fi
|
||||
|
||||
# Check whether --enable-directory-stack was given.
|
||||
if test "${enable_directory_stack+set}" = set; then :
|
||||
enableval=$enable_directory_stack; opt_dirstack=$enableval
|
||||
@@ -3284,6 +3294,10 @@ fi
|
||||
if test $opt_casemod_expansions = yes; then
|
||||
$as_echo "#define CASEMOD_EXPANSIONS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
if test $opt_dircomplete_expand_default = yes; then
|
||||
$as_echo "#define DIRCOMPLETE_EXPAND_DEFAULT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
if test $opt_memscramble = yes; then
|
||||
|
||||
+7
-1
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AC_REVISION([for Bash 4.2, version 4.050])dnl
|
||||
AC_REVISION([for Bash 4.2, version 4.052])dnl
|
||||
|
||||
define(bashvers, 4.2)
|
||||
define(relstatus, maint)
|
||||
@@ -89,6 +89,7 @@ sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF
|
||||
*-beos*) opt_bash_malloc=no ;; # they say it's suitable
|
||||
*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment
|
||||
*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft
|
||||
*-nsk*) opt_bash_malloc=no ;; # HP NonStop
|
||||
esac
|
||||
|
||||
# memory scrambling on free()
|
||||
@@ -188,6 +189,7 @@ opt_single_longdoc_strings=yes
|
||||
opt_casemod_attrs=yes
|
||||
opt_casemod_expansions=yes
|
||||
opt_extglob_default=no
|
||||
opt_dircomplete_expand_default=no
|
||||
|
||||
dnl options that affect how bash is compiled and linked
|
||||
opt_static_link=no
|
||||
@@ -222,6 +224,7 @@ AC_ARG_ENABLE(cond-command, AC_HELP_STRING([--enable-cond-command], [enable the
|
||||
AC_ARG_ENABLE(cond-regexp, AC_HELP_STRING([--enable-cond-regexp], [enable extended regular expression matching in conditional commands]), opt_cond_regexp=$enableval)
|
||||
AC_ARG_ENABLE(coprocesses, AC_HELP_STRING([--enable-coprocesses], [enable coprocess support and the coproc reserved word]), opt_coproc=$enableval)
|
||||
AC_ARG_ENABLE(debugger, AC_HELP_STRING([--enable-debugger], [enable support for bash debugger]), opt_debugger=$enableval)
|
||||
AC_ARG_ENABLE(direxpand-default, AC_HELP_STRING([--enable-direxpand-default], [enable the direxpand shell option by default]), opt_dircomplete_expand_default=$enableval)
|
||||
AC_ARG_ENABLE(directory-stack, AC_HELP_STRING([--enable-directory-stack], [enable builtins pushd/popd/dirs]), opt_dirstack=$enableval)
|
||||
AC_ARG_ENABLE(disabled-builtins, AC_HELP_STRING([--enable-disabled-builtins], [allow disabled builtins to still be invoked]), opt_disabled_builtins=$enableval)
|
||||
AC_ARG_ENABLE(dparen-arithmetic, AC_HELP_STRING([--enable-dparen-arithmetic], [include ((...)) command]), opt_dparen_arith=$enableval)
|
||||
@@ -341,6 +344,9 @@ fi
|
||||
if test $opt_casemod_expansions = yes; then
|
||||
AC_DEFINE(CASEMOD_EXPANSIONS)
|
||||
fi
|
||||
if test $opt_dircomplete_expand_default = yes; then
|
||||
AC_DEFINE(DIRCOMPLETE_EXPAND_DEFAULT)
|
||||
fi
|
||||
|
||||
if test $opt_memscramble = yes; then
|
||||
AC_DEFINE(MEMSCRAMBLE)
|
||||
|
||||
@@ -7955,6 +7955,11 @@ Include support for coprocesses and the @code{coproc} reserved word
|
||||
@item --enable-debugger
|
||||
Include support for the bash debugger (distributed separately).
|
||||
|
||||
@item --enable-direxpand-default
|
||||
Cause the @code{direxpand} shell option (@pxref{The Shopt Builtin})
|
||||
to be enabled by default when the shell starts.
|
||||
It is normally disabled by default.
|
||||
|
||||
@item --enable-directory-stack
|
||||
Include support for a @code{csh}-like directory stack and the
|
||||
@code{pushd}, @code{popd}, and @code{dirs} builtins
|
||||
|
||||
+3
-9
@@ -2,15 +2,9 @@
|
||||
Copyright (C) 1988-2012 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Tue Aug 28 17:19:20 EDT 2012
|
||||
@set LASTCHANGE Thu Sep 13 17:12:28 EDT 2012
|
||||
|
||||
@set EDITION 4.2
|
||||
@set VERSION 4.2
|
||||
@set UPDATED 28 August 2012
|
||||
@set UPDATED-MONTH August 2012
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@set UPDATED 13 September 2012
|
||||
@set UPDATED-MONTH September 2012
|
||||
|
||||
+2
-2
@@ -698,7 +698,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
if (variable_context != 0)
|
||||
{
|
||||
ofifo = num_fifos ();
|
||||
ofifo_list = copy_fifo_list (&osize);
|
||||
ofifo_list = copy_fifo_list ((int *)&osize);
|
||||
saved_fifo = 1;
|
||||
}
|
||||
else
|
||||
@@ -1017,7 +1017,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
{
|
||||
nfifo = num_fifos ();
|
||||
if (nfifo > ofifo)
|
||||
close_new_fifos (ofifo_list, osize);
|
||||
close_new_fifos ((char *)ofifo_list, osize);
|
||||
free (ofifo_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
+5363
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -291,7 +291,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, forcecoll;;
|
||||
int brcnt, forcecoll;
|
||||
INT pc;
|
||||
CHAR *savep;
|
||||
|
||||
|
||||
@@ -0,0 +1,773 @@
|
||||
/* Copyright (C) 1991-2011 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/>.
|
||||
*/
|
||||
|
||||
int FCT __P((CHAR *, CHAR *, int));
|
||||
|
||||
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));
|
||||
|
||||
int
|
||||
FCT (pattern, string, flags)
|
||||
CHAR *pattern;
|
||||
CHAR *string;
|
||||
int flags;
|
||||
{
|
||||
CHAR *se, *pe;
|
||||
|
||||
if (string == 0 || pattern == 0)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
se = string + STRLEN ((XCHAR *)string);
|
||||
pe = pattern + STRLEN ((XCHAR *)pattern);
|
||||
|
||||
return (GMATCH (string, se, pattern, pe, flags));
|
||||
}
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, FNM_NOMATCH if not. */
|
||||
static int
|
||||
GMATCH (string, se, pattern, pe, flags)
|
||||
CHAR *string, *se;
|
||||
CHAR *pattern, *pe;
|
||||
int flags;
|
||||
{
|
||||
CHAR *p, *n; /* pattern, string */
|
||||
INT c; /* current pattern character - XXX U_CHAR? */
|
||||
INT sc; /* current string character - XXX U_CHAR? */
|
||||
|
||||
p = pattern;
|
||||
n = string;
|
||||
|
||||
if (string == 0 || pattern == 0)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
#if DEBUG_MATCHING
|
||||
fprintf(stderr, "gmatch: string = %s; se = %s\n", string, se);
|
||||
fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
|
||||
#endif
|
||||
|
||||
while (p < pe)
|
||||
{
|
||||
c = *p++;
|
||||
c = FOLD (c);
|
||||
|
||||
sc = n < se ? *n : '\0';
|
||||
|
||||
#ifdef EXTENDED_GLOB
|
||||
/* EXTMATCH () will handle recursively calling GMATCH, so we can
|
||||
just return what EXTMATCH() returns. */
|
||||
if ((flags & FNM_EXTMATCH) && *p == L('(') &&
|
||||
(c == L('+') || c == L('*') || c == L('?') || c == L('@') || c == L('!'))) /* ) */
|
||||
{
|
||||
int lflags;
|
||||
/* If we're not matching the start of the string, we're not
|
||||
concerned about the special cases for matching `.' */
|
||||
lflags = (n == string) ? flags : (flags & ~FNM_PERIOD);
|
||||
return (EXTMATCH (c, n, se, p, pe, lflags));
|
||||
}
|
||||
#endif /* EXTENDED_GLOB */
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case L('?'): /* Match single character */
|
||||
if (sc == '\0')
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_PATHNAME) && sc == L('/'))
|
||||
/* If we are matching a pathname, `?' can never match a `/'. */
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_PERIOD) && sc == L('.') &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
|
||||
/* `?' cannot match a `.' 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. */
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case L('\\'): /* backslash escape removes special meaning */
|
||||
if (p == pe)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if ((flags & FNM_NOESCAPE) == 0)
|
||||
{
|
||||
c = *p++;
|
||||
/* A trailing `\' cannot match. */
|
||||
if (p > pe)
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD (c);
|
||||
}
|
||||
if (FOLD (sc) != (U_CHAR)c)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '*': /* Match zero or more characters */
|
||||
if (p == pe)
|
||||
return 0;
|
||||
|
||||
if ((flags & FNM_PERIOD) && sc == L('.') &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
|
||||
/* `*' cannot match a `.' 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. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
/* Collapse multiple consecutive `*' and `?', but make sure that
|
||||
one character of the string is consumed for each `?'. */
|
||||
for (c = *p++; (c == L('?') || c == L('*')); c = *p++)
|
||||
{
|
||||
if ((flags & FNM_PATHNAME) && sc == L('/'))
|
||||
/* A slash does not match a wildcard under FNM_PATHNAME. */
|
||||
return FNM_NOMATCH;
|
||||
#ifdef EXTENDED_GLOB
|
||||
else if ((flags & FNM_EXTMATCH) && c == L('?') && *p == L('(')) /* ) */
|
||||
{
|
||||
CHAR *newn;
|
||||
for (newn = n; newn < se; ++newn)
|
||||
{
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
else if (c == L('?'))
|
||||
{
|
||||
if (sc == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
/* One character of the string is consumed in matching
|
||||
this ? wildcard, so *??? won't match if there are
|
||||
fewer than three characters. */
|
||||
n++;
|
||||
sc = n < se ? *n : '\0';
|
||||
}
|
||||
|
||||
#ifdef EXTENDED_GLOB
|
||||
/* Handle ******(patlist) */
|
||||
if ((flags & FNM_EXTMATCH) && c == L('*') && *p == L('(')) /*)*/
|
||||
{
|
||||
CHAR *newn;
|
||||
/* We need to check whether or not the extended glob
|
||||
pattern matches the remainder of the string.
|
||||
If it does, we match the entire pattern. */
|
||||
for (newn = n; newn < se; ++newn)
|
||||
{
|
||||
if (EXTMATCH (c, newn, se, p, pe, flags) == 0)
|
||||
return (0);
|
||||
}
|
||||
/* We didn't match the extended glob pattern, but
|
||||
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);
|
||||
/* If NEWN is 0, we have an ill-formed pattern. */
|
||||
p = newn ? newn : pe;
|
||||
}
|
||||
#endif
|
||||
if (p == pe)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we've hit the end of the pattern and the last character of
|
||||
the pattern was handled by the loop above, we've succeeded.
|
||||
Otherwise, we need to match that last character. */
|
||||
if (p == pe && (c == L('?') || c == L('*')))
|
||||
return (0);
|
||||
|
||||
/* General case, use recursion. */
|
||||
{
|
||||
U_CHAR c1;
|
||||
|
||||
c1 = ((flags & FNM_NOESCAPE) == 0 && c == L('\\')) ? *p : c;
|
||||
c1 = FOLD (c1);
|
||||
for (--p; n < se; ++n)
|
||||
{
|
||||
/* Only call strmatch if the first character indicates a
|
||||
possible match. We can check the first character if
|
||||
we're not doing an extended glob match. */
|
||||
if ((flags & FNM_EXTMATCH) == 0 && c != L('[') && FOLD (*n) != c1) /*]*/
|
||||
continue;
|
||||
|
||||
/* If we're doing an extended glob match and the pattern is not
|
||||
one of the extended glob patterns, we can check the first
|
||||
character. */
|
||||
if ((flags & FNM_EXTMATCH) && p[1] != L('(') && /*)*/
|
||||
STRCHR (L("?*+@!"), *p) == 0 && c != L('[') && FOLD (*n) != c1) /*]*/
|
||||
continue;
|
||||
|
||||
/* Otherwise, we just recurse. */
|
||||
if (GMATCH (n, se, p, pe, flags & ~FNM_PERIOD) == 0)
|
||||
return (0);
|
||||
}
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
case L('['):
|
||||
{
|
||||
if (sc == L('\0') || n == se)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
/* A character class cannot match a `.' 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_PERIOD) && sc == L('.') &&
|
||||
(n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
p = BRACKMATCH (p, sc, flags);
|
||||
if (p == 0)
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((U_CHAR)c != FOLD (sc))
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
if (n == se)
|
||||
return (0);
|
||||
|
||||
if ((flags & FNM_LEADING_DIR) && *n == L('/'))
|
||||
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
|
||||
return 0;
|
||||
|
||||
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;
|
||||
|
||||
p++; /* move past the `.' */
|
||||
|
||||
for (pc = 0; p[pc]; pc++)
|
||||
if (p[pc] == L('.') && p[pc+1] == L(']'))
|
||||
break;
|
||||
val = COLLSYM (p, pc);
|
||||
if (vp)
|
||||
*vp = val;
|
||||
return (p + pc + 2);
|
||||
}
|
||||
|
||||
/* 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;;
|
||||
INT pc;
|
||||
CHAR *savep;
|
||||
|
||||
test = FOLD (test);
|
||||
|
||||
savep = p;
|
||||
|
||||
/* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the
|
||||
circumflex (`^') in its role in a `nonmatching list'. A bracket
|
||||
expression starting with an unquoted circumflex character produces
|
||||
unspecified results. This implementation treats the two identically. */
|
||||
if (not = (*p == L('!') || *p == L('^')))
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
/* 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
|
||||
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(']'))
|
||||
{
|
||||
pc = FOLD (p[1]);
|
||||
p += 4;
|
||||
if (COLLEQUIV (test, pc))
|
||||
{
|
||||
/*[*/ /* Move past the closing `]', since the first thing we do at
|
||||
the `matched:' label is back p up one. */
|
||||
p++;
|
||||
goto matched;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = *p++;
|
||||
if (c == L('\0'))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
|
||||
c = FOLD (c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */
|
||||
if (c == L('[') && *p == L(':'))
|
||||
{
|
||||
CHAR *close, *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 == 0)
|
||||
pc = 0;
|
||||
else
|
||||
{
|
||||
bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR));
|
||||
*(ccname + (close - p - 1)) = L('\0');
|
||||
pc = IS_CCLASS (test, (XCHAR *)ccname);
|
||||
}
|
||||
if (pc == -1)
|
||||
pc = 0;
|
||||
else
|
||||
p = close + 2;
|
||||
|
||||
free (ccname);
|
||||
}
|
||||
|
||||
if (pc)
|
||||
{
|
||||
/*[*/ /* Move past the closing `]', since the first thing we do at
|
||||
the `matched:' label is back p up one. */
|
||||
p++;
|
||||
goto matched;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* continue the loop here, since this expression can't be
|
||||
the first part of a range expression. */
|
||||
c = *p++;
|
||||
if (c == L('\0'))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
else if (c == L(']'))
|
||||
break;
|
||||
c = FOLD (c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* POSIX.2 collating symbols. See POSIX.2 2.8.3.2. Find the end of
|
||||
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('.'))
|
||||
{
|
||||
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;
|
||||
forcecoll = 1;
|
||||
}
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
|
||||
{
|
||||
if (*p == '\0')
|
||||
return (CHAR *)0;
|
||||
cstart = cend = *p++;
|
||||
}
|
||||
|
||||
cstart = cend = FOLD (cstart);
|
||||
|
||||
/* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
|
||||
is not preceded by a backslash and is not part of a bracket
|
||||
expression produces undefined results.' This implementation
|
||||
treats the `[' as just a character to be matched if there is
|
||||
not a closing `]'. */
|
||||
if (c == L('\0'))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
|
||||
c = *p++;
|
||||
c = FOLD (c);
|
||||
|
||||
if ((flags & FNM_PATHNAME) && c == L('/'))
|
||||
/* [/] can never match when matching a pathname. */
|
||||
return (CHAR *)0;
|
||||
|
||||
/* This introduces a range, unless the `-' is the last
|
||||
character of the class. Find the end of the range
|
||||
and move past it. */
|
||||
if (c == L('-') && *p != L(']'))
|
||||
{
|
||||
cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
|
||||
cend = *p++;
|
||||
if (cend == L('\0'))
|
||||
return (CHAR *)0;
|
||||
if (cend == L('[') && *p == L('.'))
|
||||
{
|
||||
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;
|
||||
forcecoll = 1;
|
||||
}
|
||||
cend = FOLD (cend);
|
||||
|
||||
c = *p++;
|
||||
|
||||
/* POSIX.2 2.8.3.2: ``The ending range point shall collate
|
||||
equal to or higher than the starting range point; otherwise
|
||||
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, forcecoll) > 0)
|
||||
{
|
||||
if (c == L(']'))
|
||||
break;
|
||||
c = FOLD (c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
|
||||
goto matched;
|
||||
|
||||
if (c == L(']'))
|
||||
break;
|
||||
}
|
||||
/* No match. */
|
||||
return (!not ? (CHAR *)0 : p);
|
||||
|
||||
matched:
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
c = *--p;
|
||||
brcnt = 1;
|
||||
while (brcnt > 0)
|
||||
{
|
||||
/* A `[' without a matching `]' is just another character to match. */
|
||||
if (c == L('\0'))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
|
||||
c = *p++;
|
||||
if (c == L('[') && (*p == L('=') || *p == L(':') || *p == L('.')))
|
||||
brcnt++;
|
||||
else if (c == L(']'))
|
||||
brcnt--;
|
||||
else if (!(flags & FNM_NOESCAPE) && c == L('\\'))
|
||||
{
|
||||
if (*p == '\0')
|
||||
return (CHAR *)0;
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
}
|
||||
}
|
||||
return (not ? (CHAR *)0 : p);
|
||||
}
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
/* ksh-like extended pattern matching:
|
||||
|
||||
[?*+@!](pat-list)
|
||||
|
||||
where pat-list is a list of one or patterns separated by `|'. Operation
|
||||
is as follows:
|
||||
|
||||
?(patlist) match zero or one of the given patterns
|
||||
*(patlist) match zero or more of the given patterns
|
||||
+(patlist) match one or more of the given patterns
|
||||
@(patlist) match exactly one of the given patterns
|
||||
!(patlist) match anything except one of the given patterns
|
||||
*/
|
||||
|
||||
/* Scan a pattern starting at STRING and ending at END, keeping track of
|
||||
embedded () and []. If DELIM is 0, we scan until a matching `)'
|
||||
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 *
|
||||
PATSCAN (string, end, delim)
|
||||
CHAR *string, *end;
|
||||
INT delim;
|
||||
{
|
||||
int pnest, bnest, skip;
|
||||
INT cchar;
|
||||
CHAR *s, c, *bfirst;
|
||||
|
||||
pnest = bnest = skip = 0;
|
||||
cchar = 0;
|
||||
bfirst = NULL;
|
||||
|
||||
for (s = string; c = *s; s++)
|
||||
{
|
||||
if (s >= end)
|
||||
return (s);
|
||||
if (skip)
|
||||
{
|
||||
skip = 0;
|
||||
continue;
|
||||
}
|
||||
switch (c)
|
||||
{
|
||||
case L('\\'):
|
||||
skip = 1;
|
||||
break;
|
||||
|
||||
case L('\0'):
|
||||
return ((CHAR *)NULL);
|
||||
|
||||
/* `[' is not special inside a bracket expression, but it may
|
||||
introduce one of the special POSIX bracket expressions
|
||||
([.SYM.], [=c=], [: ... :]) that needs special handling. */
|
||||
case L('['):
|
||||
if (bnest == 0)
|
||||
{
|
||||
bfirst = s + 1;
|
||||
if (*bfirst == L('!') || *bfirst == L('^'))
|
||||
bfirst++;
|
||||
bnest++;
|
||||
}
|
||||
else if (s[1] == L(':') || s[1] == L('.') || s[1] == L('='))
|
||||
cchar = s[1];
|
||||
break;
|
||||
|
||||
/* `]' is not special if it's the first char (after a leading `!'
|
||||
or `^') in a bracket expression or if it's part of one of the
|
||||
special POSIX bracket expressions ([.SYM.], [=c=], [: ... :]) */
|
||||
case L(']'):
|
||||
if (bnest)
|
||||
{
|
||||
if (cchar && s[-1] == cchar)
|
||||
cchar = 0;
|
||||
else if (s != bfirst)
|
||||
{
|
||||
bnest--;
|
||||
bfirst = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case L('('):
|
||||
if (bnest == 0)
|
||||
pnest++;
|
||||
break;
|
||||
|
||||
case L(')'):
|
||||
if (bnest == 0 && pnest-- <= 0)
|
||||
return ++s;
|
||||
break;
|
||||
|
||||
case L('|'):
|
||||
if (bnest == 0 && pnest == 0 && delim == L('|'))
|
||||
return ++s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Return 0 if dequoted pattern matches S in the current locale. */
|
||||
static int
|
||||
STRCOMPARE (p, pe, s, se)
|
||||
CHAR *p, *pe, *s, *se;
|
||||
{
|
||||
int ret;
|
||||
CHAR c1, c2;
|
||||
|
||||
c1 = *pe;
|
||||
c2 = *se;
|
||||
|
||||
*pe = *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;
|
||||
|
||||
return (ret == 0 ? ret : FNM_NOMATCH);
|
||||
}
|
||||
|
||||
/* Match a ksh extended pattern specifier. Return FNM_NOMATCH on failure or
|
||||
0 on success. This is handed the entire rest of the pattern and string
|
||||
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;
|
||||
{
|
||||
CHAR *prest; /* pointer to rest of pattern */
|
||||
CHAR *psub; /* pointer to sub-pattern */
|
||||
CHAR *pnext; /* pointer to next sub-pattern */
|
||||
CHAR *srest; /* pointer to rest of string */
|
||||
int m1, m2, xflags; /* xflags = flags passed to recursive matches */
|
||||
|
||||
#if DEBUG_MATCHING
|
||||
fprintf(stderr, "extmatch: xc = %c\n", xc);
|
||||
fprintf(stderr, "extmatch: s = %s; se = %s\n", s, se);
|
||||
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); /* ) */
|
||||
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));
|
||||
|
||||
switch (xc)
|
||||
{
|
||||
case L('+'): /* match one or more occurrences */
|
||||
case L('*'): /* match zero or more occurrences */
|
||||
/* If we can get away with no matches, don't even bother. Just
|
||||
call GMATCH on the rest of the pattern and return success if
|
||||
it succeeds. */
|
||||
if (xc == L('*') && (GMATCH (s, se, prest, pe, flags) == 0))
|
||||
return 0;
|
||||
|
||||
/* OK, we have to do this the hard way. First, we make sure one of
|
||||
the subpatterns matches, then we try to match the rest of the
|
||||
string. */
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = PATSCAN (psub, pe, L('|'));
|
||||
for (srest = s; srest <= se; srest++)
|
||||
{
|
||||
/* Match this substring (S -> SREST) against this
|
||||
subpattern (psub -> pnext - 1) */
|
||||
m1 = GMATCH (s, srest, psub, pnext - 1, flags) == 0;
|
||||
/* OK, we matched a subpattern, so make sure the rest of the
|
||||
string matches the rest of the pattern. Also handle
|
||||
multiple matches of the pattern. */
|
||||
if (m1)
|
||||
{
|
||||
/* if srest > s, we are not at start of string */
|
||||
xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
|
||||
m2 = (GMATCH (srest, se, prest, pe, xflags) == 0) ||
|
||||
(s != srest && GMATCH (srest, se, p - 1, pe, xflags) == 0);
|
||||
}
|
||||
if (m1 && m2)
|
||||
return (0);
|
||||
}
|
||||
if (pnext == prest)
|
||||
break;
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
case L('?'): /* match zero or one of the patterns */
|
||||
case L('@'): /* match one (or more) of the patterns */
|
||||
/* If we can get away with no matches, don't even bother. Just
|
||||
call gmatch on the rest of the pattern and return success if
|
||||
it succeeds. */
|
||||
if (xc == L('?') && (GMATCH (s, se, prest, pe, flags) == 0))
|
||||
return 0;
|
||||
|
||||
/* OK, we have to do this the hard way. First, we see if one of
|
||||
the subpatterns matches, then, if it does, we try to match the
|
||||
rest of the string. */
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = PATSCAN (psub, pe, L('|'));
|
||||
srest = (prest == pe) ? se : s;
|
||||
for ( ; srest <= se; srest++)
|
||||
{
|
||||
/* if srest > s, we are not at start of string */
|
||||
xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
|
||||
if (GMATCH (s, srest, psub, pnext - 1, flags) == 0 &&
|
||||
GMATCH (srest, se, prest, pe, xflags) == 0)
|
||||
return (0);
|
||||
}
|
||||
if (pnext == prest)
|
||||
break;
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
case '!': /* match anything *except* one of the patterns */
|
||||
for (srest = s; srest <= se; srest++)
|
||||
{
|
||||
m1 = 0;
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = PATSCAN (psub, pe, L('|'));
|
||||
/* If one of the patterns matches, just bail immediately. */
|
||||
if (m1 = (GMATCH (s, srest, psub, pnext - 1, flags) == 0))
|
||||
break;
|
||||
if (pnext == prest)
|
||||
break;
|
||||
}
|
||||
/* if srest > s, we are not at start of string */
|
||||
xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
|
||||
if (m1 == 0 && GMATCH (srest, se, prest, pe, xflags) == 0)
|
||||
return (0);
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
#endif /* EXTENDED_GLOB */
|
||||
|
||||
#undef IS_CCLASS
|
||||
#undef FOLD
|
||||
#undef CHAR
|
||||
#undef U_CHAR
|
||||
#undef XCHAR
|
||||
#undef INT
|
||||
#undef INVALID
|
||||
#undef FCT
|
||||
#undef GMATCH
|
||||
#undef COLLSYM
|
||||
#undef PARSE_COLLSYM
|
||||
#undef PATSCAN
|
||||
#undef STRCOMPARE
|
||||
#undef EXTMATCH
|
||||
#undef BRACKMATCH
|
||||
#undef STRCHR
|
||||
#undef STRCOLL
|
||||
#undef STRLEN
|
||||
#undef STRCMP
|
||||
#undef COLLEQUIV
|
||||
#undef RANGECMP
|
||||
#undef L
|
||||
@@ -29,6 +29,10 @@
|
||||
|
||||
#include <stdio.h> // size_t
|
||||
|
||||
#if defined(__TANDEM) && defined(HAVE_STDBOOL_H) && (__STDC_VERSION__ < 199901L)
|
||||
typedef int _Bool;
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STDBOOL_H)
|
||||
# include <stdbool.h> // bool
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/* `dir', `vdir' and `ls' directory listing programs for GNU.
|
||||
|
||||
Modified by Chet Ramey for Readline.
|
||||
|
||||
Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Richard Stallman and David MacKenzie. */
|
||||
|
||||
/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
|
||||
Flaherty <dennisf@denix.elk.miles.com> based on original patches by
|
||||
Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
|
||||
|
||||
#ifndef _COLORS_H_
|
||||
#define _COLORS_H_
|
||||
|
||||
#include <stdio.h> // size_t
|
||||
|
||||
#if defined (HAVE_STDBOOL_H)
|
||||
# include <stdbool.h> // bool
|
||||
#else
|
||||
typedef int _rl_bool_t;
|
||||
|
||||
#ifdef bool
|
||||
# undef bool
|
||||
#endif
|
||||
#define bool _rl_bool_t
|
||||
|
||||
#ifndef true
|
||||
# define true 1
|
||||
# define false 0
|
||||
#endif
|
||||
|
||||
#endif /* !HAVE_STDBOOL_H */
|
||||
|
||||
/* Null is a valid character in a color indicator (think about Epson
|
||||
printers, for example) so we have to use a length/buffer string
|
||||
type. */
|
||||
struct bin_str
|
||||
{
|
||||
size_t len;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
/* file type indicators (dir, sock, fifo, ...)
|
||||
Default value is initialized in parse-colors.c.
|
||||
It is then modified from the values of $LS_COLORS. */
|
||||
extern struct bin_str _rl_color_indicator[];
|
||||
|
||||
/* The LS_COLORS variable is in a termcap-like format. */
|
||||
typedef struct _color_ext_type
|
||||
{
|
||||
struct bin_str ext; /* The extension we're looking for */
|
||||
struct bin_str seq; /* The sequence to output when we do */
|
||||
struct _color_ext_type *next; /* Next in list */
|
||||
} COLOR_EXT_TYPE;
|
||||
|
||||
/* file extensions indicators (.txt, .log, .jpg, ...)
|
||||
Values are taken from $LS_COLORS in rl_parse_colors(). */
|
||||
extern COLOR_EXT_TYPE *_rl_color_ext_list;
|
||||
|
||||
#define FILETYPE_INDICATORS \
|
||||
{ \
|
||||
C_ORPHAN, C_FIFO, C_CHR, C_DIR, C_BLK, C_FILE, \
|
||||
C_LINK, C_SOCK, C_FILE, C_DIR \
|
||||
}
|
||||
|
||||
/* Whether we used any colors in the output so far. If so, we will
|
||||
need to restore the default color later. If not, we will need to
|
||||
call prep_non_filename_text before using color for the first time. */
|
||||
|
||||
enum indicator_no
|
||||
{
|
||||
C_LEFT, C_RIGHT, C_END, C_RESET, C_NORM, C_FILE, C_DIR, C_LINK,
|
||||
C_FIFO, C_SOCK,
|
||||
C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR, C_SETUID, C_SETGID,
|
||||
C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE, C_CAP, C_MULTIHARDLINK,
|
||||
C_CLR_TO_EOL
|
||||
};
|
||||
|
||||
|
||||
#if !S_IXUGO
|
||||
# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
|
||||
#endif
|
||||
|
||||
enum filetype
|
||||
{
|
||||
unknown,
|
||||
fifo,
|
||||
chardev,
|
||||
directory,
|
||||
blockdev,
|
||||
normal,
|
||||
symbolic_link,
|
||||
sock,
|
||||
whiteout,
|
||||
arg_directory
|
||||
};
|
||||
|
||||
extern void _rl_put_indicator (const struct bin_str *ind);
|
||||
extern void _rl_set_normal_color (void);
|
||||
extern bool _rl_print_color_indicator (char *f);
|
||||
extern void _rl_prep_non_filename_text (void);
|
||||
|
||||
#endif /* !_COLORS_H_ */
|
||||
+1
-1
@@ -222,7 +222,7 @@ sh_backslash_quote (string, table, flags)
|
||||
|
||||
result = (char *)xmalloc (2 * strlen (string) + 1);
|
||||
|
||||
backslash_table = table ? table : bstab;
|
||||
backslash_table = table ? table : (char *)bstab;
|
||||
for (r = result, s = string; s && (c = *s); s++)
|
||||
{
|
||||
if (backslash_table[c] == 1)
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
/* shquote - functions to quote and dequote strings */
|
||||
|
||||
/* Copyright (C) 1999 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/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "syntax.h"
|
||||
#include <xmalloc.h>
|
||||
|
||||
/* Default set of characters that should be backslash-quoted in strings */
|
||||
static const char bstab[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, /* TAB, NL */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
1, 1, 1, 0, 1, 0, 1, 1, /* SPACE, !, DQUOTE, DOL, AMP, SQUOTE */
|
||||
1, 1, 1, 0, 1, 0, 0, 0, /* LPAR, RPAR, STAR, COMMA */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 0, 1, 1, /* SEMI, LESSTHAN, GREATERTHAN, QUEST */
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 1, 0, /* LBRACK, BS, RBRACK, CARAT */
|
||||
|
||||
1, 0, 0, 0, 0, 0, 0, 0, /* BACKQ */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 0, 0, /* LBRACE, BAR, RBRACE */
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions for quoting strings to be re-read as input */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Return a new string which is the single-quoted version of STRING.
|
||||
Used by alias and trap, among others. */
|
||||
char *
|
||||
sh_single_quote (string)
|
||||
const char *string;
|
||||
{
|
||||
register int c;
|
||||
char *result, *r;
|
||||
const char *s;
|
||||
|
||||
result = (char *)xmalloc (3 + (4 * strlen (string)));
|
||||
r = result;
|
||||
*r++ = '\'';
|
||||
|
||||
for (s = string; s && (c = *s); s++)
|
||||
{
|
||||
*r++ = c;
|
||||
|
||||
if (c == '\'')
|
||||
{
|
||||
*r++ = '\\'; /* insert escaped single quote */
|
||||
*r++ = '\'';
|
||||
*r++ = '\''; /* start new quoted string */
|
||||
}
|
||||
}
|
||||
|
||||
*r++ = '\'';
|
||||
*r = '\0';
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Quote STRING using double quotes. Return a new string. */
|
||||
char *
|
||||
sh_double_quote (string)
|
||||
const char *string;
|
||||
{
|
||||
register unsigned char c;
|
||||
char *result, *r;
|
||||
const char *s;
|
||||
|
||||
result = (char *)xmalloc (3 + (2 * strlen (string)));
|
||||
r = result;
|
||||
*r++ = '"';
|
||||
|
||||
for (s = string; s && (c = *s); s++)
|
||||
{
|
||||
/* Backslash-newline disappears within double quotes, so don't add one. */
|
||||
if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
|
||||
*r++ = '\\';
|
||||
else if (c == CTLESC || c == CTLNUL)
|
||||
*r++ = CTLESC; /* could be '\\'? */
|
||||
|
||||
*r++ = c;
|
||||
}
|
||||
|
||||
*r++ = '"';
|
||||
*r = '\0';
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Turn S into a simple double-quoted string. If FLAGS is non-zero, quote
|
||||
double quote characters in S with backslashes. */
|
||||
char *
|
||||
sh_mkdoublequoted (s, slen, flags)
|
||||
const char *s;
|
||||
int slen, flags;
|
||||
{
|
||||
char *r, *ret;
|
||||
int rlen;
|
||||
|
||||
rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
|
||||
ret = r = (char *)xmalloc (rlen);
|
||||
|
||||
*r++ = '"';
|
||||
while (*s)
|
||||
{
|
||||
if (flags && *s == '"')
|
||||
*r++ = '\\';
|
||||
*r++ = *s++;
|
||||
}
|
||||
*r++ = '"';
|
||||
*r = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Remove backslashes that are quoting characters that are special between
|
||||
double quotes. Return a new string. XXX - should this handle CTLESC
|
||||
and CTLNUL? */
|
||||
char *
|
||||
sh_un_double_quote (string)
|
||||
char *string;
|
||||
{
|
||||
register int c, pass_next;
|
||||
char *result, *r, *s;
|
||||
|
||||
r = result = (char *)xmalloc (strlen (string) + 1);
|
||||
|
||||
for (pass_next = 0, s = string; s && (c = *s); s++)
|
||||
{
|
||||
if (pass_next)
|
||||
{
|
||||
*r++ = c;
|
||||
pass_next = 0;
|
||||
continue;
|
||||
}
|
||||
if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
|
||||
{
|
||||
pass_next = 1;
|
||||
continue;
|
||||
}
|
||||
*r++ = c;
|
||||
}
|
||||
|
||||
*r = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Quote special characters in STRING using backslashes. Return a new
|
||||
string. NOTE: if the string is to be further expanded, we need a
|
||||
way to protect the CTLESC and CTLNUL characters. As I write this,
|
||||
the current callers will never cause the string to be expanded without
|
||||
going through the shell parser, which will protect the internal
|
||||
quoting characters. TABLE, if set, points to a map of the ascii code
|
||||
set with char needing to be backslash-quoted if table[char]==1. FLAGS,
|
||||
if 1, causes tildes to be quoted as well. */
|
||||
|
||||
char *
|
||||
sh_backslash_quote (string, table, flags)
|
||||
char *string;
|
||||
char *table;
|
||||
int flags;
|
||||
{
|
||||
int c;
|
||||
char *result, *r, *s, *backslash_table;
|
||||
|
||||
result = (char *)xmalloc (2 * strlen (string) + 1);
|
||||
|
||||
backslash_table = table ? table : bstab;
|
||||
for (r = result, s = string; s && (c = *s); s++)
|
||||
{
|
||||
if (backslash_table[c] == 1)
|
||||
*r++ = '\\';
|
||||
else if (c == '#' && s == string) /* comment char */
|
||||
*r++ = '\\';
|
||||
else if ((flags&1) && c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
|
||||
/* Tildes are special at the start of a word or after a `:' or `='
|
||||
(technically unquoted, but it doesn't make a difference in practice) */
|
||||
*r++ = '\\';
|
||||
*r++ = c;
|
||||
}
|
||||
|
||||
*r = '\0';
|
||||
return (result);
|
||||
}
|
||||
|
||||
#if defined (PROMPT_STRING_DECODE)
|
||||
/* Quote characters that get special treatment when in double quotes in STRING
|
||||
using backslashes. Return a new string. */
|
||||
char *
|
||||
sh_backslash_quote_for_double_quotes (string)
|
||||
char *string;
|
||||
{
|
||||
unsigned char c;
|
||||
char *result, *r, *s;
|
||||
|
||||
result = (char *)xmalloc (2 * strlen (string) + 1);
|
||||
|
||||
for (r = result, s = string; s && (c = *s); s++)
|
||||
{
|
||||
if (sh_syntaxtab[c] & CBSDQUOTE)
|
||||
*r++ = '\\';
|
||||
/* I should probably add flags for these to sh_syntaxtab[] */
|
||||
else if (c == CTLESC || c == CTLNUL)
|
||||
*r++ = CTLESC; /* could be '\\'? */
|
||||
|
||||
*r++ = c;
|
||||
}
|
||||
|
||||
*r = '\0';
|
||||
return (result);
|
||||
}
|
||||
#endif /* PROMPT_STRING_DECODE */
|
||||
|
||||
int
|
||||
sh_contains_shell_metas (string)
|
||||
char *string;
|
||||
{
|
||||
char *s;
|
||||
|
||||
for (s = string; s && *s; s++)
|
||||
{
|
||||
switch (*s)
|
||||
{
|
||||
case ' ': case '\t': case '\n': /* IFS white space */
|
||||
case '\'': case '"': case '\\': /* quoting chars */
|
||||
case '|': case '&': case ';': /* shell metacharacters */
|
||||
case '(': case ')': case '<': case '>':
|
||||
case '!': case '{': case '}': /* reserved words */
|
||||
case '*': case '[': case '?': case ']': /* globbing chars */
|
||||
case '^':
|
||||
case '$': case '`': /* expansion chars */
|
||||
return (1);
|
||||
case '~': /* tilde expansion */
|
||||
if (s == string || s[-1] == '=' || s[-1] == ':')
|
||||
return (1);
|
||||
break;
|
||||
case '#':
|
||||
if (s == string) /* comment char */
|
||||
return (1);
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -3675,6 +3675,17 @@ eof_error:
|
||||
}
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
|
||||
; /* don't modify LEX_RESWDOK if we're starting a comment */
|
||||
/* Allow `do' followed by space, tab, or newline to preserve the
|
||||
RESWDOK flag, but reset the reserved word length counter so we
|
||||
can read another one. */
|
||||
else if MBTEST(((tflags & LEX_INCASE) == 0) &&
|
||||
(isblank(ch) || ch == '\n') &&
|
||||
lex_rwlen == 2 &&
|
||||
STREQN (ret + retind - 2, "do", 2))
|
||||
{
|
||||
/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', found \"do\"", line_number, ch);*/
|
||||
lex_rwlen = 0;
|
||||
}
|
||||
else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
|
||||
/* If we can read a reserved word and we're in case, we're at the
|
||||
point where we can read a new pattern list or an esac. We
|
||||
@@ -3690,6 +3701,15 @@ eof_error:
|
||||
tflags &= ~LEX_RESWDOK;
|
||||
/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
|
||||
}
|
||||
#if 0
|
||||
/* If we find a space or tab but have read something and it's not
|
||||
`do', turn off the reserved-word-ok flag */
|
||||
else if MBTEST(isblank (ch) && lex_rwlen > 0)
|
||||
{
|
||||
tflags &= ~LEX_RESWDOK;
|
||||
/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Might be the start of a here-doc delimiter */
|
||||
|
||||
@@ -252,7 +252,9 @@ static const struct {
|
||||
{ "noprofile", Int, &no_profile, (char **)0x0 },
|
||||
{ "norc", Int, &no_rc, (char **)0x0 },
|
||||
{ "posix", Int, &posixly_correct, (char **)0x0 },
|
||||
#if defined (WORDEXP_OPTION)
|
||||
{ "protected", Int, &protected_mode, (char **)0x0 },
|
||||
#endif
|
||||
{ "rcfile", Charp, (int *)0x0, &bashrc_file },
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
{ "restricted", Int, &restricted, (char **)0x0 },
|
||||
|
||||
@@ -7875,7 +7875,7 @@ comsub:
|
||||
temp = nameref_cell (var);
|
||||
if (temp && *temp && valid_array_reference (temp))
|
||||
{
|
||||
tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (int *)NULL);
|
||||
tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (arrayind_t *)NULL);
|
||||
if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
|
||||
return (tdesc);
|
||||
ret = tdesc;
|
||||
|
||||
Reference in New Issue
Block a user