mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 23:53:18 +02:00
commit bash-20060302 snapshot
This commit is contained in:
@@ -454,3 +454,5 @@ lib/sh/vprint.c Chet Ramey, Brian Fox
|
||||
lib/sh/xstrchr.c Chet Ramey, Mitsuru Chinen
|
||||
lib/sh/zread.c Chet Ramey
|
||||
lib/sh/zwrite.c Chet Ramey
|
||||
|
||||
tests/posix-ifs.sh Glenn Fowler
|
||||
|
||||
@@ -13111,3 +13111,42 @@ lib/readline/display.c
|
||||
----
|
||||
builtins/hash.def
|
||||
- don't print `hash table empty' message in posix mode
|
||||
|
||||
2/27
|
||||
----
|
||||
lib/glob/sm_loop.c
|
||||
- change extmatch() to turn off FNM_PERIOD in flags passed to recursive
|
||||
calls to gmatch() when calling it with a substring after the start
|
||||
of the string it receives. Changed `+', `*', `?, `@', and `!' cases
|
||||
to do the right thing. Fixes bug reported by Benoit Vila
|
||||
<bvila@free.fr>
|
||||
|
||||
braces.c
|
||||
- add QUIT; statements to mkseq to make large sequence generation
|
||||
interruptible
|
||||
|
||||
2/28
|
||||
----
|
||||
lib/glob/glob.c
|
||||
- initialize nalloca in glob_vector
|
||||
|
||||
3/1
|
||||
---
|
||||
lib/glob/glob.c
|
||||
- in glob_vector, when freeing up the linked list after some error,
|
||||
make sure to set `tmplink' to 0 if `firstlink' is set to 0, else we
|
||||
get multiple-free errors
|
||||
|
||||
3/5
|
||||
---
|
||||
trap.c
|
||||
- inheritance of the DEBUG, RETURN, and ERR traps is now dependent
|
||||
only on the `functrace' and `errtrace' shell options, as the
|
||||
documentation says, rather than on whether or not the shell is in
|
||||
debugging mode. Reported by Philip Susi <psusi@cfl.rr.com>
|
||||
|
||||
parse.y
|
||||
- in parse_matched_pair, don't recursively parse ${...} or other
|
||||
${...} constructs inside ``
|
||||
- in parse_matched_pair, remove special code that recursively parses
|
||||
quoted strings inside `` constructs. For Bourne shell compatibility
|
||||
|
||||
+48
-2
@@ -12958,7 +12958,7 @@ bashline.c
|
||||
and bash_directory_expansion
|
||||
|
||||
lib/readline/doc/rltech.texi
|
||||
- add note to description of rl_direcotory_completion_hook that it
|
||||
- add note to description of rl_directory_completion_hook that it
|
||||
needs to dequote the directory name even if no other expansions are
|
||||
performed
|
||||
|
||||
@@ -13082,7 +13082,8 @@ lib/readline/bind.c
|
||||
functions using the ANYOTHERKEY binding code.
|
||||
|
||||
variables.c
|
||||
- shells running in posix mode do not set $HOME, as POSIX requires
|
||||
- shells running in posix mode do not set $HOME, as POSIX apparently
|
||||
requires
|
||||
|
||||
2/15
|
||||
----
|
||||
@@ -13105,3 +13106,48 @@ lib/readline/readline.c
|
||||
lib/readline/display.c
|
||||
- further fixes to _rl_make_prompt_for_search from Eric Blake to deal
|
||||
with multiple calls to expand_prompt
|
||||
|
||||
2/21
|
||||
----
|
||||
builtins/hash.def
|
||||
- don't print `hash table empty' message in posix mode
|
||||
|
||||
2/27
|
||||
----
|
||||
lib/glob/sm_loop.c
|
||||
- change extmatch() to turn off FNM_PERIOD in flags passed to recursive
|
||||
calls to gmatch() when calling it with a substring after the start
|
||||
of the string it receives. Changed `+', `*', `?, `@', and `!' cases
|
||||
to do the right thing. Fixes bug reported by Benoit Vila
|
||||
<bvila@free.fr>
|
||||
|
||||
braces.c
|
||||
- add QUIT; statements to mkseq to make large sequence generation
|
||||
interruptible
|
||||
|
||||
2/28
|
||||
----
|
||||
lib/glob/glob.c
|
||||
- initialize nalloca in glob_vector
|
||||
|
||||
3/1
|
||||
---
|
||||
lib/glob/glob.c
|
||||
- in glob_vector, when freeing up the linked list after some error,
|
||||
make sure to set `tmplink' to 0 if `firstlink' is set to 0, else we
|
||||
get multiple-free errors
|
||||
|
||||
3/5
|
||||
---
|
||||
trap.c
|
||||
- change `||' to `&&' and make the DEBUG, ERR, and RETURN traps
|
||||
inherited when the appropriate shell options are set, not just when
|
||||
the shell is in debugging mode and the appropriate options are set.
|
||||
This matches the documentation.
|
||||
Reported by Philip Susi <psusi@cfl.rr.com>
|
||||
|
||||
parse.y
|
||||
- in parse_matched_pair, don't recursively parse ${...} or other
|
||||
${...} constructs inside ``
|
||||
- in parse_matched_pair, remove special code that recursively parses
|
||||
quoted strings inside `` constructs. For Bourne shell compatibility
|
||||
|
||||
@@ -742,6 +742,7 @@ tests/exp-tests f
|
||||
tests/exp.right f
|
||||
tests/extglob.tests f
|
||||
tests/extglob.right f
|
||||
tests/extglob1.sub f
|
||||
tests/extglob2.tests f
|
||||
tests/extglob2.right f
|
||||
tests/extglob3.tests f
|
||||
|
||||
@@ -313,6 +313,9 @@ mkseq (start, end, incr, type)
|
||||
n = start;
|
||||
do
|
||||
{
|
||||
#if defined (SHELL)
|
||||
QUIT; /* XXX - memory leak here */
|
||||
#endif
|
||||
if (type == ST_INT)
|
||||
result[i++] = itos (n);
|
||||
else
|
||||
|
||||
@@ -178,7 +178,7 @@ helpdoc: $(MKBUILTINS) $(DEFSRC)
|
||||
|
||||
install-help:
|
||||
@-if test -n "${HELPDIR}" && test -d helpfiles ; then \
|
||||
test -d ${HELPDIR} || ${SHELL} ${MKDIRS} $(DESTDIR)$(HELPDIR) ;\
|
||||
test -d $(DESTDIR)${HELPDIR} || ${SHELL} ${MKDIRS} $(DESTDIR)$(HELPDIR) ;\
|
||||
( for f in helpfiles/*; do \
|
||||
echo installing $$f; \
|
||||
${INSTALL_DATA} $$f $(DESTDIR)$(HELPDIR); \
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ USA @*
|
||||
@top Bash Features
|
||||
|
||||
This text is a brief description of the features that are present in
|
||||
the Bash shell (version @value{VERSION}, @value{UPDATED})..
|
||||
the Bash shell (version @value{VERSION}, @value{UPDATED}).
|
||||
|
||||
This is Edition @value{EDITION}, last updated @value{UPDATED},
|
||||
of @cite{The GNU Bash Reference Manual},
|
||||
|
||||
@@ -33,7 +33,7 @@ CC = @CC@
|
||||
RANLIB = @RANLIB@
|
||||
AR = @AR@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
RM = rm
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
MV = mv
|
||||
|
||||
@@ -59,6 +59,7 @@ CCFLAGS = $(PROFILE_FLAGS) $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) ${INCLUDES} \
|
||||
# Here is a rule for making .o files from .c files that doesn't force
|
||||
# the type of the machine (like -sun3) into the flags.
|
||||
.c.o:
|
||||
$(RM) $@
|
||||
$(CC) -c $(CCFLAGS) $<
|
||||
|
||||
# The name of the library target.
|
||||
|
||||
+8
-2
@@ -73,7 +73,7 @@
|
||||
#endif
|
||||
|
||||
extern void throw_to_top_level __P((void));
|
||||
extern int test_eaccess __P((char *, int));
|
||||
extern int sh_eaccess __P((char *, int));
|
||||
|
||||
extern int extended_glob;
|
||||
|
||||
@@ -293,7 +293,7 @@ dequote_pathname (pathname)
|
||||
# define GLOB_TESTNAME(name) (lstat (name, &finfo))
|
||||
#else /* !HAVE_LSTAT */
|
||||
# if !defined (AFS)
|
||||
# define GLOB_TESTNAME(name) (test_eaccess (nextname, F_OK))
|
||||
# define GLOB_TESTNAME(name) (sh_eaccess (nextname, F_OK))
|
||||
# else /* AFS */
|
||||
# define GLOB_TESTNAME(name) (access (nextname, F_OK))
|
||||
# endif /* AFS */
|
||||
@@ -360,6 +360,7 @@ glob_vector (pat, dir, flags)
|
||||
count = lose = skip = 0;
|
||||
|
||||
firstmalloc = 0;
|
||||
nalloca = 0;
|
||||
|
||||
/* If PAT is empty, skip the loop, but return one (empty) filename. */
|
||||
if (pat == 0 || *pat == '\0')
|
||||
@@ -540,12 +541,17 @@ glob_vector (pat, dir, flags)
|
||||
/* Here free the strings we have got. */
|
||||
while (lastlink)
|
||||
{
|
||||
/* Since we build the list in reverse order, the first N entries
|
||||
will be allocated with malloc, if firstmalloc is set, from
|
||||
lastlink to firstmalloc. */
|
||||
if (firstmalloc)
|
||||
{
|
||||
if (lastlink == firstmalloc)
|
||||
firstmalloc = 0;
|
||||
tmplink = lastlink;
|
||||
}
|
||||
else
|
||||
tmplink = 0;
|
||||
free (lastlink->name);
|
||||
lastlink = lastlink->next;
|
||||
FREE (tmplink);
|
||||
|
||||
@@ -0,0 +1,894 @@
|
||||
/* glob.c -- file-name wildcard pattern matching for Bash.
|
||||
|
||||
Copyright (C) 1985-2005 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 2, 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/* To whomever it may concern: I have never seen the code which most
|
||||
Unix programs use to perform this function. I wrote this from scratch
|
||||
based on specifications for the pattern matching. --RMS. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
|
||||
#pragma alloca
|
||||
#endif /* _AIX && RISC6000 && !__GNUC__ */
|
||||
|
||||
#include "bashtypes.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "posixdir.h"
|
||||
#include "posixstat.h"
|
||||
#include "shmbutil.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#include "filecntl.h"
|
||||
#if !defined (F_OK)
|
||||
# define F_OK 0
|
||||
#endif
|
||||
|
||||
#include "stdc.h"
|
||||
#include "memalloc.h"
|
||||
#include "quit.h"
|
||||
|
||||
#include "glob.h"
|
||||
#include "strmatch.h"
|
||||
|
||||
#if !defined (HAVE_BCOPY) && !defined (bcopy)
|
||||
# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
|
||||
#endif /* !HAVE_BCOPY && !bcopy */
|
||||
|
||||
#if !defined (NULL)
|
||||
# if defined (__STDC__)
|
||||
# define NULL ((void *) 0)
|
||||
# else
|
||||
# define NULL 0x0
|
||||
# endif /* __STDC__ */
|
||||
#endif /* !NULL */
|
||||
|
||||
#if !defined (FREE)
|
||||
# define FREE(x) if (x) free (x)
|
||||
#endif
|
||||
|
||||
/* Don't try to alloca() more than this much memory for `struct globval'
|
||||
in glob_vector() */
|
||||
#ifndef ALLOCA_MAX
|
||||
# define ALLOCA_MAX 100000
|
||||
#endif
|
||||
|
||||
extern void throw_to_top_level __P((void));
|
||||
extern int sh_eaccess __P((char *, int));
|
||||
|
||||
extern int extended_glob;
|
||||
|
||||
/* Global variable which controls whether or not * matches .*.
|
||||
Non-zero means don't match .*. */
|
||||
int noglob_dot_filenames = 1;
|
||||
|
||||
/* Global variable which controls whether or not filename globbing
|
||||
is done without regard to case. */
|
||||
int glob_ignore_case = 0;
|
||||
|
||||
/* Global variable to return to signify an error in globbing. */
|
||||
char *glob_error_return;
|
||||
|
||||
/* Some forward declarations. */
|
||||
static int skipname __P((char *, char *));
|
||||
#if HANDLE_MULTIBYTE
|
||||
static int mbskipname __P((char *, char *));
|
||||
#endif
|
||||
#if HANDLE_MULTIBYTE
|
||||
static void udequote_pathname __P((char *));
|
||||
static void wdequote_pathname __P((char *));
|
||||
#else
|
||||
# define dequote_pathname udequote_pathname
|
||||
#endif
|
||||
static void dequote_pathname __P((char *));
|
||||
static int glob_testdir __P((char *));
|
||||
static char **glob_dir_to_array __P((char *, char **, int));
|
||||
|
||||
/* Compile `glob_loop.c' for single-byte characters. */
|
||||
#define CHAR unsigned char
|
||||
#define INT int
|
||||
#define L(CS) CS
|
||||
#define INTERNAL_GLOB_PATTERN_P internal_glob_pattern_p
|
||||
#include "glob_loop.c"
|
||||
|
||||
/* Compile `glob_loop.c' again for multibyte characters. */
|
||||
#if HANDLE_MULTIBYTE
|
||||
|
||||
#define CHAR wchar_t
|
||||
#define INT wint_t
|
||||
#define L(CS) L##CS
|
||||
#define INTERNAL_GLOB_PATTERN_P internal_glob_wpattern_p
|
||||
#include "glob_loop.c"
|
||||
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
/* And now a function that calls either the single-byte or multibyte version
|
||||
of internal_glob_pattern_p. */
|
||||
int
|
||||
glob_pattern_p (pattern)
|
||||
const char *pattern;
|
||||
{
|
||||
#if HANDLE_MULTIBYTE
|
||||
size_t n;
|
||||
wchar_t *wpattern;
|
||||
int r;
|
||||
|
||||
if (MB_CUR_MAX == 1)
|
||||
return (internal_glob_pattern_p ((unsigned char *)pattern));
|
||||
|
||||
/* Convert strings to wide chars, and call the multibyte version. */
|
||||
n = xdupmbstowcs (&wpattern, NULL, pattern);
|
||||
if (n == (size_t)-1)
|
||||
/* Oops. Invalid multibyte sequence. Try it as single-byte sequence. */
|
||||
return (internal_glob_pattern_p ((unsigned char *)pattern));
|
||||
|
||||
r = internal_glob_wpattern_p (wpattern);
|
||||
free (wpattern);
|
||||
|
||||
return r;
|
||||
#else
|
||||
return (internal_glob_pattern_p (pattern));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return 1 if DNAME should be skipped according to PAT. Mostly concerned
|
||||
with matching leading `.'. */
|
||||
|
||||
static int
|
||||
skipname (pat, dname)
|
||||
char *pat;
|
||||
char *dname;
|
||||
{
|
||||
/* 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] != '.' &&
|
||||
(pat[0] != '\\' || pat[1] != '.') &&
|
||||
(dname[0] == '.' &&
|
||||
(dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
|
||||
return 1;
|
||||
|
||||
/* If a dot must be explicity matched, check to see if they do. */
|
||||
else if (noglob_dot_filenames && dname[0] == '.' && pat[0] != '.' &&
|
||||
(pat[0] != '\\' || pat[1] != '.'))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HANDLE_MULTIBYTE
|
||||
/* 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)
|
||||
char *pat, *dname;
|
||||
{
|
||||
int ret;
|
||||
wchar_t *pat_wc, *dn_wc;
|
||||
size_t pat_n, dn_n, n;
|
||||
|
||||
pat_n = xdupmbstowcs (&pat_wc, NULL, pat);
|
||||
dn_n = xdupmbstowcs (&dn_wc, NULL, dname);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
FREE (pat_wc);
|
||||
FREE (dn_wc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
|
||||
static void
|
||||
udequote_pathname (pathname)
|
||||
char *pathname;
|
||||
{
|
||||
register int i, j;
|
||||
|
||||
for (i = j = 0; pathname && pathname[i]; )
|
||||
{
|
||||
if (pathname[i] == '\\')
|
||||
i++;
|
||||
|
||||
pathname[j++] = pathname[i++];
|
||||
|
||||
if (pathname[i - 1] == 0)
|
||||
break;
|
||||
}
|
||||
pathname[j] = '\0';
|
||||
}
|
||||
|
||||
#if HANDLE_MULTIBYTE
|
||||
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
|
||||
static void
|
||||
wdequote_pathname (pathname)
|
||||
char *pathname;
|
||||
{
|
||||
mbstate_t ps;
|
||||
size_t len, n;
|
||||
wchar_t *wpathname;
|
||||
int i, j;
|
||||
wchar_t *orig_wpathname;
|
||||
|
||||
len = strlen (pathname);
|
||||
/* Convert the strings into wide characters. */
|
||||
n = xdupmbstowcs (&wpathname, NULL, pathname);
|
||||
if (n == (size_t) -1)
|
||||
/* Something wrong. */
|
||||
return;
|
||||
orig_wpathname = wpathname;
|
||||
|
||||
for (i = j = 0; wpathname && wpathname[i]; )
|
||||
{
|
||||
if (wpathname[i] == L'\\')
|
||||
i++;
|
||||
|
||||
wpathname[j++] = wpathname[i++];
|
||||
|
||||
if (wpathname[i - 1] == L'\0')
|
||||
break;
|
||||
}
|
||||
wpathname[j] = L'\0';
|
||||
|
||||
/* Convert the wide character string into unibyte character set. */
|
||||
memset (&ps, '\0', sizeof(mbstate_t));
|
||||
n = wcsrtombs(pathname, (const wchar_t **)&wpathname, len, &ps);
|
||||
pathname[len] = '\0';
|
||||
|
||||
/* Can't just free wpathname here; wcsrtombs changes it in many cases. */
|
||||
free (orig_wpathname);
|
||||
}
|
||||
|
||||
static void
|
||||
dequote_pathname (pathname)
|
||||
char *pathname;
|
||||
{
|
||||
if (MB_CUR_MAX > 1)
|
||||
wdequote_pathname (pathname);
|
||||
else
|
||||
udequote_pathname (pathname);
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
/* Test whether NAME exists. */
|
||||
|
||||
#if defined (HAVE_LSTAT)
|
||||
# define GLOB_TESTNAME(name) (lstat (name, &finfo))
|
||||
#else /* !HAVE_LSTAT */
|
||||
# if !defined (AFS)
|
||||
# define GLOB_TESTNAME(name) (sh_eaccess (nextname, F_OK))
|
||||
# else /* AFS */
|
||||
# define GLOB_TESTNAME(name) (access (nextname, F_OK))
|
||||
# endif /* AFS */
|
||||
#endif /* !HAVE_LSTAT */
|
||||
|
||||
/* Return 0 if DIR is a directory, -1 otherwise. */
|
||||
static int
|
||||
glob_testdir (dir)
|
||||
char *dir;
|
||||
{
|
||||
struct stat finfo;
|
||||
|
||||
if (stat (dir, &finfo) < 0)
|
||||
return (-1);
|
||||
|
||||
if (S_ISDIR (finfo.st_mode) == 0)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return a vector of names of files in directory DIR
|
||||
whose names match glob pattern PAT.
|
||||
The names are not in any particular order.
|
||||
Wildcards at the beginning of PAT do not match an initial period.
|
||||
|
||||
The vector is terminated by an element that is a null pointer.
|
||||
|
||||
To free the space allocated, first free the vector's elements,
|
||||
then free the vector.
|
||||
|
||||
Return 0 if cannot get enough memory to hold the pointer
|
||||
and the names.
|
||||
|
||||
Return -1 if cannot access directory DIR.
|
||||
Look in errno for more information. */
|
||||
|
||||
char **
|
||||
glob_vector (pat, dir, flags)
|
||||
char *pat;
|
||||
char *dir;
|
||||
int flags;
|
||||
{
|
||||
struct globval
|
||||
{
|
||||
struct globval *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
DIR *d;
|
||||
register struct dirent *dp;
|
||||
struct globval *lastlink;
|
||||
register struct globval *nextlink;
|
||||
register char *nextname, *npat;
|
||||
unsigned int count;
|
||||
int lose, skip;
|
||||
register char **name_vector;
|
||||
register unsigned int i;
|
||||
int mflags; /* Flags passed to strmatch (). */
|
||||
int nalloca;
|
||||
struct globval *firstmalloc, *tmplink;
|
||||
|
||||
lastlink = 0;
|
||||
count = lose = skip = 0;
|
||||
|
||||
firstmalloc = 0;
|
||||
nalloca = 0;
|
||||
|
||||
/* If PAT is empty, skip the loop, but return one (empty) filename. */
|
||||
if (pat == 0 || *pat == '\0')
|
||||
{
|
||||
if (glob_testdir (dir) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
nextlink = (struct globval *)alloca (sizeof (struct globval));
|
||||
if (nextlink == NULL)
|
||||
return ((char **) NULL);
|
||||
|
||||
nextlink->next = (struct globval *)0;
|
||||
nextname = (char *) malloc (1);
|
||||
if (nextname == 0)
|
||||
lose = 1;
|
||||
else
|
||||
{
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
nextname[0] = '\0';
|
||||
count = 1;
|
||||
}
|
||||
|
||||
skip = 1;
|
||||
}
|
||||
|
||||
/* If the filename pattern (PAT) does not contain any globbing characters,
|
||||
we can dispense with reading the directory, and just see if there is
|
||||
a filename `DIR/PAT'. If there is, and we can access it, just make the
|
||||
vector to return and bail immediately. */
|
||||
if (skip == 0 && glob_pattern_p (pat) == 0)
|
||||
{
|
||||
int dirlen;
|
||||
struct stat finfo;
|
||||
|
||||
if (glob_testdir (dir) < 0)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
dirlen = strlen (dir);
|
||||
nextname = (char *)malloc (dirlen + strlen (pat) + 2);
|
||||
npat = (char *)malloc (strlen (pat) + 1);
|
||||
if (nextname == 0 || npat == 0)
|
||||
lose = 1;
|
||||
else
|
||||
{
|
||||
strcpy (npat, pat);
|
||||
dequote_pathname (npat);
|
||||
|
||||
strcpy (nextname, dir);
|
||||
nextname[dirlen++] = '/';
|
||||
strcpy (nextname + dirlen, npat);
|
||||
|
||||
if (GLOB_TESTNAME (nextname) >= 0)
|
||||
{
|
||||
free (nextname);
|
||||
nextlink = (struct globval *)alloca (sizeof (struct globval));
|
||||
if (nextlink)
|
||||
{
|
||||
nextlink->next = (struct globval *)0;
|
||||
lastlink = nextlink;
|
||||
nextlink->name = npat;
|
||||
count = 1;
|
||||
}
|
||||
else
|
||||
lose = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
free (nextname);
|
||||
free (npat);
|
||||
}
|
||||
}
|
||||
|
||||
skip = 1;
|
||||
}
|
||||
|
||||
if (skip == 0)
|
||||
{
|
||||
/* Open the directory, punting immediately if we cannot. If opendir
|
||||
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)
|
||||
return ((char **) &glob_error_return);
|
||||
#endif
|
||||
|
||||
d = opendir (dir);
|
||||
if (d == NULL)
|
||||
return ((char **) &glob_error_return);
|
||||
|
||||
/* Compute the flags that will be passed to strmatch(). We don't
|
||||
need to do this every time through the loop. */
|
||||
mflags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
|
||||
|
||||
#ifdef FNM_CASEFOLD
|
||||
if (glob_ignore_case)
|
||||
mflags |= FNM_CASEFOLD;
|
||||
#endif
|
||||
|
||||
if (extended_glob)
|
||||
mflags |= FNM_EXTMATCH;
|
||||
|
||||
/* Scan the directory, finding all names that match.
|
||||
For each name that matches, allocate a struct globval
|
||||
on the stack and store the name in it.
|
||||
Chain those structs together; lastlink is the front of the chain. */
|
||||
while (1)
|
||||
{
|
||||
/* Make globbing interruptible in the shell. */
|
||||
if (interrupt_state)
|
||||
{
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
dp = readdir (d);
|
||||
if (dp == NULL)
|
||||
break;
|
||||
|
||||
/* If this directory entry is not to be used, try again. */
|
||||
if (REAL_DIR_ENTRY (dp) == 0)
|
||||
continue;
|
||||
|
||||
#if 0
|
||||
if (dp->d_name == 0 || *dp->d_name == 0)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
#if HANDLE_MULTIBYTE
|
||||
if (MB_CUR_MAX > 1 && mbskipname (pat, dp->d_name))
|
||||
continue;
|
||||
else
|
||||
#endif
|
||||
if (skipname (pat, dp->d_name))
|
||||
continue;
|
||||
|
||||
if (strmatch (pat, dp->d_name, mflags) != FNM_NOMATCH)
|
||||
{
|
||||
if (nalloca < ALLOCA_MAX)
|
||||
{
|
||||
nextlink = (struct globval *) alloca (sizeof (struct globval));
|
||||
nalloca += sizeof (struct globval);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextlink = (struct globval *) malloc (sizeof (struct globval));
|
||||
if (firstmalloc == 0)
|
||||
{
|
||||
firstmalloc = nextlink;
|
||||
itrace("glob_vector: switching from alloca to malloc for nextlink: count = %d", count);
|
||||
}
|
||||
}
|
||||
nextname = (char *) malloc (D_NAMLEN (dp) + 1);
|
||||
if (nextlink == 0 || nextname == 0)
|
||||
{
|
||||
lose = 1;
|
||||
break;
|
||||
}
|
||||
nextlink->next = lastlink;
|
||||
lastlink = nextlink;
|
||||
nextlink->name = nextname;
|
||||
bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
(void) closedir (d);
|
||||
}
|
||||
|
||||
if (lose == 0)
|
||||
{
|
||||
name_vector = (char **) malloc ((count + 1) * sizeof (char *));
|
||||
lose |= name_vector == NULL;
|
||||
}
|
||||
|
||||
/* Have we run out of memory? */
|
||||
if (lose)
|
||||
{
|
||||
tmplink = 0;
|
||||
|
||||
/* Here free the strings we have got. */
|
||||
while (lastlink)
|
||||
{
|
||||
/* Since we build the list in reverse order, the first N entries
|
||||
will be allocated with malloc, if firstmalloc is set, from
|
||||
lastlink to firstmalloc. */
|
||||
if (firstmalloc)
|
||||
{
|
||||
if (lastlink == firstmalloc)
|
||||
firstmalloc = 0;
|
||||
tmplink = lastlink;
|
||||
}
|
||||
else
|
||||
tmplink = 0;
|
||||
free (lastlink->name);
|
||||
lastlink = lastlink->next;
|
||||
FREE (tmplink);
|
||||
}
|
||||
|
||||
QUIT;
|
||||
|
||||
return ((char **)NULL);
|
||||
}
|
||||
|
||||
/* Copy the name pointers from the linked list into the vector. */
|
||||
for (tmplink = lastlink, i = 0; i < count; ++i)
|
||||
{
|
||||
name_vector[i] = tmplink->name;
|
||||
tmplink = tmplink->next;
|
||||
}
|
||||
|
||||
name_vector[count] = NULL;
|
||||
|
||||
/* If we allocated some of the struct globvals, free them now. */
|
||||
if (firstmalloc)
|
||||
{
|
||||
tmplink = 0;
|
||||
while (lastlink)
|
||||
{
|
||||
tmplink = lastlink;
|
||||
if (lastlink == firstmalloc)
|
||||
lastlink = firstmalloc = 0;
|
||||
else
|
||||
lastlink = lastlink->next;
|
||||
free (tmplink);
|
||||
}
|
||||
}
|
||||
|
||||
return (name_vector);
|
||||
}
|
||||
|
||||
/* Return a new array which is the concatenation of each string in ARRAY
|
||||
to DIR. This function expects you to pass in an allocated ARRAY, and
|
||||
it takes care of free()ing that array. Thus, you might think of this
|
||||
function as side-effecting ARRAY. This should handle GX_MARKDIRS. */
|
||||
static char **
|
||||
glob_dir_to_array (dir, array, flags)
|
||||
char *dir, **array;
|
||||
int flags;
|
||||
{
|
||||
register unsigned int i, l;
|
||||
int add_slash;
|
||||
char **result, *new;
|
||||
struct stat sb;
|
||||
|
||||
l = strlen (dir);
|
||||
if (l == 0)
|
||||
{
|
||||
if (flags & GX_MARKDIRS)
|
||||
for (i = 0; array[i]; i++)
|
||||
{
|
||||
if ((stat (array[i], &sb) == 0) && S_ISDIR (sb.st_mode))
|
||||
{
|
||||
l = strlen (array[i]);
|
||||
new = (char *)realloc (array[i], l + 2);
|
||||
if (new == 0)
|
||||
return NULL;
|
||||
new[l] = '/';
|
||||
new[l+1] = '\0';
|
||||
array[i] = new;
|
||||
}
|
||||
}
|
||||
return (array);
|
||||
}
|
||||
|
||||
add_slash = dir[l - 1] != '/';
|
||||
|
||||
i = 0;
|
||||
while (array[i] != NULL)
|
||||
++i;
|
||||
|
||||
result = (char **) malloc ((i + 1) * sizeof (char *));
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
|
||||
for (i = 0; array[i] != NULL; i++)
|
||||
{
|
||||
/* 3 == 1 for NUL, 1 for slash at end of DIR, 1 for GX_MARKDIRS */
|
||||
result[i] = (char *) malloc (l + strlen (array[i]) + 3);
|
||||
|
||||
if (result[i] == NULL)
|
||||
return (NULL);
|
||||
|
||||
strcpy (result[i], dir);
|
||||
if (add_slash)
|
||||
result[i][l] = '/';
|
||||
strcpy (result[i] + l + add_slash, array[i]);
|
||||
if (flags & GX_MARKDIRS)
|
||||
{
|
||||
if ((stat (result[i], &sb) == 0) && S_ISDIR (sb.st_mode))
|
||||
{
|
||||
size_t rlen;
|
||||
rlen = strlen (result[i]);
|
||||
result[i][rlen] = '/';
|
||||
result[i][rlen+1] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
result[i] = NULL;
|
||||
|
||||
/* Free the input array. */
|
||||
for (i = 0; array[i] != NULL; i++)
|
||||
free (array[i]);
|
||||
free ((char *) array);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Do globbing on PATHNAME. Return an array of pathnames that match,
|
||||
marking the end of the array with a null-pointer as an element.
|
||||
If no pathnames match, then the array is empty (first element is null).
|
||||
If there isn't enough memory, then return NULL.
|
||||
If a file system error occurs, return -1; `errno' has the error code. */
|
||||
char **
|
||||
glob_filename (pathname, flags)
|
||||
char *pathname;
|
||||
int flags;
|
||||
{
|
||||
char **result;
|
||||
unsigned int result_size;
|
||||
char *directory_name, *filename;
|
||||
unsigned int directory_len;
|
||||
int free_dirname; /* flag */
|
||||
|
||||
result = (char **) malloc (sizeof (char *));
|
||||
result_size = 1;
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
|
||||
result[0] = NULL;
|
||||
|
||||
directory_name = NULL;
|
||||
|
||||
/* Find the filename. */
|
||||
filename = strrchr (pathname, '/');
|
||||
if (filename == NULL)
|
||||
{
|
||||
filename = pathname;
|
||||
directory_name = "";
|
||||
directory_len = 0;
|
||||
free_dirname = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
directory_len = (filename - pathname) + 1;
|
||||
directory_name = (char *) malloc (directory_len + 1);
|
||||
|
||||
if (directory_name == 0) /* allocation failed? */
|
||||
return (NULL);
|
||||
|
||||
bcopy (pathname, directory_name, directory_len);
|
||||
directory_name[directory_len] = '\0';
|
||||
++filename;
|
||||
free_dirname = 1;
|
||||
}
|
||||
|
||||
/* If directory_name contains globbing characters, then we
|
||||
have to expand the previous levels. Just recurse. */
|
||||
if (glob_pattern_p (directory_name))
|
||||
{
|
||||
char **directories;
|
||||
register unsigned int i;
|
||||
|
||||
if (directory_name[directory_len - 1] == '/')
|
||||
directory_name[directory_len - 1] = '\0';
|
||||
|
||||
directories = glob_filename (directory_name, flags & ~GX_MARKDIRS);
|
||||
|
||||
if (free_dirname)
|
||||
{
|
||||
free (directory_name);
|
||||
directory_name = NULL;
|
||||
}
|
||||
|
||||
if (directories == NULL)
|
||||
goto memory_error;
|
||||
else if (directories == (char **)&glob_error_return)
|
||||
{
|
||||
free ((char *) result);
|
||||
return ((char **) &glob_error_return);
|
||||
}
|
||||
else if (*directories == NULL)
|
||||
{
|
||||
free ((char *) directories);
|
||||
free ((char *) result);
|
||||
return ((char **) &glob_error_return);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Scan directory even on a NULL pathname. That way, `*h/'
|
||||
returns only directories ending in `h', instead of all
|
||||
files ending in `h' with a `/' appended. */
|
||||
temp_results = glob_vector (filename, directories[i], flags & ~GX_MARKDIRS);
|
||||
|
||||
/* Handle error cases. */
|
||||
if (temp_results == NULL)
|
||||
goto memory_error;
|
||||
else if (temp_results == (char **)&glob_error_return)
|
||||
/* This filename is probably not a directory. Ignore it. */
|
||||
;
|
||||
else
|
||||
{
|
||||
char **array;
|
||||
register unsigned int l;
|
||||
|
||||
array = glob_dir_to_array (directories[i], temp_results, flags);
|
||||
l = 0;
|
||||
while (array[l] != NULL)
|
||||
++l;
|
||||
|
||||
result =
|
||||
(char **)realloc (result, (result_size + l) * sizeof (char *));
|
||||
|
||||
if (result == NULL)
|
||||
goto memory_error;
|
||||
|
||||
for (l = 0; array[l] != NULL; ++l)
|
||||
result[result_size++ - 1] = array[l];
|
||||
|
||||
result[result_size - 1] = NULL;
|
||||
|
||||
/* Note that the elements of ARRAY are not freed. */
|
||||
free ((char *) array);
|
||||
}
|
||||
}
|
||||
/* Free the directories. */
|
||||
for (i = 0; directories[i]; i++)
|
||||
free (directories[i]);
|
||||
|
||||
free ((char *) directories);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* If there is only a directory name, return it. */
|
||||
if (*filename == '\0')
|
||||
{
|
||||
result = (char **) realloc ((char *) result, 2 * sizeof (char *));
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
/* Handle GX_MARKDIRS here. */
|
||||
result[0] = (char *) malloc (directory_len + 1);
|
||||
if (result[0] == NULL)
|
||||
goto memory_error;
|
||||
bcopy (directory_name, result[0], directory_len + 1);
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
result[1] = NULL;
|
||||
return (result);
|
||||
}
|
||||
else
|
||||
{
|
||||
char **temp_results;
|
||||
|
||||
/* There are no unquoted globbing characters in DIRECTORY_NAME.
|
||||
Dequote it before we try to open the directory since there may
|
||||
be quoted globbing characters which should be treated verbatim. */
|
||||
if (directory_len > 0)
|
||||
dequote_pathname (directory_name);
|
||||
|
||||
/* We allocated a small array called RESULT, which we won't be using.
|
||||
Free that memory now. */
|
||||
free (result);
|
||||
|
||||
/* Just return what glob_vector () returns appended to the
|
||||
directory name. */
|
||||
temp_results = glob_vector (filename,
|
||||
(directory_len == 0 ? "." : directory_name),
|
||||
flags & ~GX_MARKDIRS);
|
||||
|
||||
if (temp_results == NULL || temp_results == (char **)&glob_error_return)
|
||||
{
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
return (temp_results);
|
||||
}
|
||||
|
||||
result = glob_dir_to_array (directory_name, temp_results, flags);
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* We get to memory_error if the program has run out of memory, or
|
||||
if this is the shell, and we have been interrupted. */
|
||||
memory_error:
|
||||
if (result != NULL)
|
||||
{
|
||||
register unsigned int i;
|
||||
for (i = 0; result[i] != NULL; ++i)
|
||||
free (result[i]);
|
||||
free ((char *) result);
|
||||
}
|
||||
|
||||
if (free_dirname && directory_name)
|
||||
free (directory_name);
|
||||
|
||||
QUIT;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#if defined (TEST)
|
||||
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < argc; ++i)
|
||||
{
|
||||
char **value = glob_filename (argv[i], 0);
|
||||
if (value == NULL)
|
||||
puts ("Out of memory.");
|
||||
else if (value == &glob_error_return)
|
||||
perror (argv[i]);
|
||||
else
|
||||
for (i = 0; value[i] != NULL; i++)
|
||||
puts (value[i]);
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
#endif /* TEST. */
|
||||
+16
-8
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991-2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
int FCT __P((CHAR *, CHAR *, int));
|
||||
|
||||
static int GMATCH __P((CHAR *, CHAR *, CHAR *, CHAR *, int));
|
||||
@@ -638,12 +637,13 @@ EXTMATCH (xc, s, se, p, pe, flags)
|
||||
CHAR *psub; /* pointer to sub-pattern */
|
||||
CHAR *pnext; /* pointer to next sub-pattern */
|
||||
CHAR *srest; /* pointer to rest of string */
|
||||
int m1, m2;
|
||||
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); /* ) */
|
||||
@@ -677,8 +677,12 @@ fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
|
||||
string matches the rest of the pattern. Also handle
|
||||
multiple matches of the pattern. */
|
||||
if (m1)
|
||||
m2 = (GMATCH (srest, se, prest, pe, flags) == 0) ||
|
||||
(s != srest && GMATCH (srest, se, p - 1, pe, flags) == 0);
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
@@ -688,7 +692,7 @@ fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
case L('?'): /* match zero or one of the patterns */
|
||||
case L('@'): /* match exactly 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. */
|
||||
@@ -704,8 +708,10 @@ fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
|
||||
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, flags) == 0)
|
||||
GMATCH (srest, se, prest, pe, xflags) == 0)
|
||||
return (0);
|
||||
}
|
||||
if (pnext == prest)
|
||||
@@ -726,7 +732,9 @@ fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
|
||||
if (pnext == prest)
|
||||
break;
|
||||
}
|
||||
if (m1 == 0 && GMATCH (srest, se, prest, pe, flags) == 0)
|
||||
/* 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);
|
||||
|
||||
@@ -2737,6 +2737,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
char *ret, *nestret, *ttrans;
|
||||
int retind, retsize, rflags;
|
||||
|
||||
/* itrace("parse_matched_pair: open = %c close = %c", open, close); */
|
||||
count = 1;
|
||||
pass_next_character = backq_backslash = was_dollar = in_comment = 0;
|
||||
check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
|
||||
@@ -2824,8 +2825,10 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
{
|
||||
if MBTEST((flags & P_ALLOWESC) && ch == '\\')
|
||||
pass_next_character++;
|
||||
#if 0
|
||||
else if MBTEST((flags & P_BACKQUOTE) && ch == '\\')
|
||||
backq_backslash++;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2908,6 +2911,7 @@ add_nestret:
|
||||
}
|
||||
FREE (nestret);
|
||||
}
|
||||
#if 0
|
||||
else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
|
||||
{
|
||||
/* Add P_BACKQUOTE so backslash quotes the next character and
|
||||
@@ -2917,7 +2921,8 @@ add_nestret:
|
||||
nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags|P_BACKQUOTE);
|
||||
goto add_nestret;
|
||||
}
|
||||
else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
|
||||
#endif
|
||||
else if MBTEST(open != '`' && was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
|
||||
/* check for $(), $[], or ${} inside quoted string. */
|
||||
{
|
||||
if (open == ch) /* undo previous increment */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Yacc grammar for bash. */
|
||||
|
||||
/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -118,7 +118,6 @@ extern int current_command_number;
|
||||
extern int sourcelevel;
|
||||
extern int posixly_correct;
|
||||
extern int last_command_exit_value;
|
||||
extern int interrupt_immediately;
|
||||
extern char *shell_name, *current_host_name;
|
||||
extern char *dist_version;
|
||||
extern int patch_level;
|
||||
@@ -1212,10 +1211,12 @@ yy_readline_get ()
|
||||
old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
|
||||
interrupt_immediately++;
|
||||
}
|
||||
terminate_immediately = 1;
|
||||
|
||||
current_readline_line = readline (current_readline_prompt ?
|
||||
current_readline_prompt : "");
|
||||
|
||||
terminate_immediately = 0;
|
||||
if (signal_is_ignored (SIGINT) == 0 && old_sigint)
|
||||
{
|
||||
interrupt_immediately--;
|
||||
@@ -1347,10 +1348,16 @@ yy_stream_get ()
|
||||
if (bash_input.location.file)
|
||||
{
|
||||
if (interactive)
|
||||
interrupt_immediately++;
|
||||
{
|
||||
interrupt_immediately++;
|
||||
terminate_immediately++;
|
||||
}
|
||||
result = getc_with_restart (bash_input.location.file);
|
||||
if (interactive)
|
||||
interrupt_immediately--;
|
||||
{
|
||||
interrupt_immediately--;
|
||||
terminate_immediately--;
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
@@ -2716,6 +2723,7 @@ read_token (command)
|
||||
#define P_ALLOWESC 0x02
|
||||
#define P_DQUOTE 0x04
|
||||
#define P_COMMAND 0x08 /* parsing a command, so look for comments */
|
||||
#define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
|
||||
|
||||
static char matched_pair_error;
|
||||
static char *
|
||||
@@ -2725,12 +2733,13 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
int *lenp, flags;
|
||||
{
|
||||
int count, ch, was_dollar, in_comment, check_comment;
|
||||
int pass_next_character, nestlen, ttranslen, start_lineno;
|
||||
int pass_next_character, backq_backslash, nestlen, ttranslen, start_lineno;
|
||||
char *ret, *nestret, *ttrans;
|
||||
int retind, retsize, rflags;
|
||||
|
||||
itrace("parse_matched_pair: open = %c close = %c", open, close);
|
||||
count = 1;
|
||||
pass_next_character = was_dollar = in_comment = 0;
|
||||
pass_next_character = backq_backslash = was_dollar = in_comment = 0;
|
||||
check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
|
||||
|
||||
/* RFLAGS is the set of flags we want to pass to recursive calls. */
|
||||
@@ -2742,11 +2751,8 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
start_lineno = line_number;
|
||||
while (count)
|
||||
{
|
||||
#if 0
|
||||
ch = shell_getc ((qc != '\'' || (flags & P_ALLOWESC)) && pass_next_character == 0);
|
||||
#else
|
||||
ch = shell_getc (qc != '\'' && pass_next_character == 0);
|
||||
#endif
|
||||
ch = shell_getc (qc != '\'' && pass_next_character == 0 && backq_backslash == 0);
|
||||
|
||||
if (ch == EOF)
|
||||
{
|
||||
free (ret);
|
||||
@@ -2771,9 +2777,16 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
continue;
|
||||
}
|
||||
/* Not exactly right yet */
|
||||
else if (check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind -1])))
|
||||
else if MBTEST(check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind - 1])))
|
||||
in_comment = 1;
|
||||
|
||||
/* last char was backslash inside backquoted command substitution */
|
||||
if (backq_backslash)
|
||||
{
|
||||
backq_backslash = 0;
|
||||
/* Placeholder for adding special characters */
|
||||
}
|
||||
|
||||
if (pass_next_character) /* last char was backslash */
|
||||
{
|
||||
pass_next_character = 0;
|
||||
@@ -2798,11 +2811,9 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
}
|
||||
else if MBTEST(ch == close) /* ending delimiter */
|
||||
count--;
|
||||
#if 1
|
||||
/* handle nested ${...} specially. */
|
||||
else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
|
||||
count++;
|
||||
#endif
|
||||
else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
|
||||
count++;
|
||||
|
||||
@@ -2814,6 +2825,10 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
{
|
||||
if MBTEST((flags & P_ALLOWESC) && ch == '\\')
|
||||
pass_next_character++;
|
||||
#if 0
|
||||
else if MBTEST((flags & P_BACKQUOTE) && ch == '\\')
|
||||
backq_backslash++;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2896,18 +2911,24 @@ add_nestret:
|
||||
}
|
||||
FREE (nestret);
|
||||
}
|
||||
#if 0
|
||||
else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
|
||||
{
|
||||
nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags);
|
||||
/* Add P_BACKQUOTE so backslash quotes the next character and
|
||||
shell_getc does the right thing with \<newline>. We do this for
|
||||
a measure of backwards compatibility -- it's not strictly the
|
||||
right POSIX thing. */
|
||||
nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags|P_BACKQUOTE);
|
||||
goto add_nestret;
|
||||
}
|
||||
else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
|
||||
#endif
|
||||
else if MBTEST(open != '`' && was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
|
||||
/* check for $(), $[], or ${} inside quoted string. */
|
||||
{
|
||||
if (open == ch) /* undo previous increment */
|
||||
count--;
|
||||
if (ch == '(') /* ) */
|
||||
nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags);
|
||||
nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE);
|
||||
else if (ch == '{') /* } */
|
||||
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
|
||||
else if (ch == '[') /* ] */
|
||||
@@ -2946,7 +2967,6 @@ parse_dparen (c)
|
||||
{
|
||||
wd = alloc_word_desc ();
|
||||
wd->word = wval;
|
||||
wd = make_word (wval);
|
||||
yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
|
||||
return (ARITH_FOR_EXPRS);
|
||||
}
|
||||
@@ -3496,7 +3516,7 @@ read_token_word (character)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to locale)-expand the converted string. */
|
||||
/* Try to locale-expand the converted string. */
|
||||
ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
|
||||
free (ttok);
|
||||
|
||||
@@ -3578,7 +3598,7 @@ read_token_word (character)
|
||||
FREE (ttok);
|
||||
all_digit_token = 0;
|
||||
compound_assignment = 1;
|
||||
#if 0
|
||||
#if 1
|
||||
goto next_character;
|
||||
#else
|
||||
goto got_token; /* ksh93 seems to do this */
|
||||
@@ -4745,11 +4765,8 @@ parse_compound_assignment (retlenp)
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
|
||||
#if 0
|
||||
last_read_token = orig_last_token; /* XXX - was WORD? */
|
||||
#else
|
||||
last_read_token = WORD;
|
||||
#endif
|
||||
|
||||
if (wl)
|
||||
{
|
||||
rl = REVERSE_LIST (wl, WORD_LIST *);
|
||||
|
||||
+8103
File diff suppressed because it is too large
Load Diff
@@ -82,6 +82,7 @@ extern int errno;
|
||||
#define EX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define EX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define EX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define EX_BACKQ 0x08 /* experimental */
|
||||
|
||||
/* Flags for the `pflags' argument to param_expand() */
|
||||
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
|
||||
@@ -554,7 +555,7 @@ string_extract (string, sindex, charlist, flags)
|
||||
char *charlist;
|
||||
int flags;
|
||||
{
|
||||
register int c, i;
|
||||
register int c, i, si;
|
||||
int found;
|
||||
size_t slen;
|
||||
char *temp;
|
||||
@@ -582,6 +583,13 @@ string_extract (string, sindex, charlist, flags)
|
||||
i = ni;
|
||||
}
|
||||
#endif
|
||||
else if ((flags & EX_BACKQ) && (c == '\'' || c == '"'))
|
||||
{
|
||||
si = i + 1;
|
||||
i = (c == '\'') ? skip_single_quoted (string, slen, si)
|
||||
: skip_double_quoted (string, slen, si);
|
||||
continue;
|
||||
}
|
||||
else if (MEMBER (c, charlist))
|
||||
{
|
||||
found = 1;
|
||||
@@ -5837,7 +5845,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
|
||||
sindex = *indexp;
|
||||
t_index = ++sindex;
|
||||
/* ${#var} doesn't have any of the other parameter expansions on it. */
|
||||
if (string[t_index] == '#' && legal_variable_starter (string[sindex])) /* {{ */
|
||||
if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
|
||||
name = string_extract (string, &t_index, "}", EX_VARNAME);
|
||||
else
|
||||
name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
@@ -78,3 +78,12 @@ a b a,b a-b a.b a:b a;b a_b
|
||||
a b a,b a-b a.b a:b a;b a_b
|
||||
a b a,b a-b a.b a:b a;b a_b
|
||||
argv[1] = <ef>
|
||||
a.c
|
||||
a.c
|
||||
a.c
|
||||
a.c
|
||||
a.c
|
||||
a.c
|
||||
ok 1
|
||||
ok 2
|
||||
ok 3
|
||||
|
||||
+3
-1
@@ -193,7 +193,7 @@ esac
|
||||
|
||||
MYDIR=$PWD # save where we are
|
||||
|
||||
TESTDIR=/tmp/eglob-test
|
||||
TESTDIR=/tmp/eglob-test-$$
|
||||
mkdir $TESTDIR
|
||||
builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; }
|
||||
rm -rf *
|
||||
@@ -360,4 +360,6 @@ recho "${x#*(a|b)cd}"
|
||||
# in the right place
|
||||
builtin cd $MYDIR
|
||||
|
||||
${THIS_SH} ./extglob1.sub
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
MYDIR=$PWD
|
||||
|
||||
: ${TMPDIR:=/tmp}
|
||||
GDIR=$TMPDIR/gtest-$$
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
mkdir $GDIR || exit 1
|
||||
cd $GDIR || exit 1
|
||||
|
||||
touch a.c
|
||||
|
||||
echo +([[:alpha:].])
|
||||
echo +([[:alpha:].])+([[:alpha:].])
|
||||
echo *([[:alpha:].])
|
||||
echo *([[:alpha:].])*([[:alpha:].])
|
||||
|
||||
echo ?([[:alpha:].])?([[:alpha:].])?([[:alpha:].])
|
||||
echo @([[:alpha:].])@([[:alpha:].])@([[:alpha:].])
|
||||
|
||||
case . in
|
||||
!([[:alpha:].]) ) echo bad 1;;
|
||||
*) echo ok 1;;
|
||||
esac
|
||||
|
||||
case . in
|
||||
?([[:alpha:].]) ) echo ok 2;;
|
||||
*) echo bad 2;;
|
||||
esac
|
||||
|
||||
case . in
|
||||
@([[:alpha:].]) ) echo ok 3;;
|
||||
*) echo bad 3;;
|
||||
esac
|
||||
|
||||
cd $MYDIR
|
||||
rm -rf $GDIR
|
||||
@@ -30,5 +30,8 @@ argv[1] = <hello, $"world">
|
||||
argv[1] = <hello, \$"world">
|
||||
argv[1] = <hello, $"world">
|
||||
argv[1] = <hello, $world>
|
||||
1
|
||||
1
|
||||
;foo
|
||||
argv[1] = <^I>
|
||||
argv[1] = <'A^IB'>
|
||||
|
||||
+6
-1
@@ -102,7 +102,12 @@ recho $'hello, $\"world"'
|
||||
recho "hello, $"world""
|
||||
|
||||
# ansi quoting inside double-quoted command subst - bash-3.1 bug
|
||||
function args
|
||||
echo $(set -- $'a b'; echo $#)
|
||||
echo "$(set -- $'a b'; echo $#)"
|
||||
|
||||
echo "$(echo $';foo')"
|
||||
|
||||
args ()
|
||||
{
|
||||
for a in "$@";do echo "'$a'";done
|
||||
}
|
||||
|
||||
@@ -47,3 +47,22 @@ argv[1] = <sed> argv[2] = <-e> argv[3] = <s/[^I:]//g>
|
||||
argv[1] = <foo\^Jbar>
|
||||
argv[1] = <foobar>
|
||||
argv[1] = <foo\^Jbar>
|
||||
b
|
||||
a
|
||||
b
|
||||
c
|
||||
argv[1] = <a\>
|
||||
argv[2] = <b>
|
||||
argv[1] = <$>
|
||||
argv[2] = <bab>
|
||||
argv[1] = <$foo>
|
||||
argv[2] = <bab>
|
||||
argv[1] = <$foo>
|
||||
argv[2] = <bab>
|
||||
argv[1] = <`>
|
||||
argv[2] = <ab>
|
||||
argv[1] = <\>
|
||||
argv[2] = <ab>
|
||||
${
|
||||
argv[1] = <(")>
|
||||
argv[1] = <(")>
|
||||
|
||||
@@ -83,3 +83,29 @@ bar'`
|
||||
|
||||
echo $(recho 'foo\
|
||||
bar')
|
||||
|
||||
a=`echo 'a b c' | sed 's/ /\\
|
||||
/g' | grep 'b'`
|
||||
echo $a
|
||||
a=`echo 'a b c' | sed 's/ /\\
|
||||
/g'`
|
||||
echo "$a"
|
||||
|
||||
recho `echo 'a\' b`
|
||||
|
||||
recho `echo '\$' bab`
|
||||
recho `echo '\$foo' bab`
|
||||
recho `echo '$foo' bab`
|
||||
|
||||
recho `echo '\`' ab`
|
||||
|
||||
recho `echo '\\' ab`
|
||||
|
||||
echo `echo '${'`
|
||||
|
||||
recho `echo "(\\")"`
|
||||
# produces no output
|
||||
: `: "\\""`
|
||||
# ultimate workaround
|
||||
recho `echo "(\")"`
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
echo "Single Quote"
|
||||
echo 'foo
|
||||
bar'
|
||||
echo 'foo
|
||||
bar'
|
||||
echo 'foo\
|
||||
bar'
|
||||
|
||||
echo "Double Quote"
|
||||
echo "foo
|
||||
bar"
|
||||
echo "foo
|
||||
bar"
|
||||
echo "foo\
|
||||
bar"
|
||||
|
||||
echo "Backslash Single Quote"
|
||||
echo `echo 'foo
|
||||
bar'`
|
||||
echo `echo 'foo
|
||||
bar'`
|
||||
echo `echo 'foo\
|
||||
bar'`
|
||||
|
||||
echo "Backslash Double Quote"
|
||||
echo `echo "foo
|
||||
bar"`
|
||||
echo `echo "foo
|
||||
bar"`
|
||||
echo `echo "foo\
|
||||
bar"`
|
||||
|
||||
echo "Double Quote Backslash Single Quote"
|
||||
echo "`echo 'foo
|
||||
bar'`"
|
||||
echo "`echo 'foo
|
||||
bar'`"
|
||||
echo "`echo 'foo\
|
||||
bar'`"
|
||||
|
||||
echo "Dollar Paren Single Quote"
|
||||
echo $(echo 'foo
|
||||
bar')
|
||||
echo $(echo 'foo
|
||||
bar')
|
||||
echo $(echo 'foo\
|
||||
bar')
|
||||
|
||||
echo "Dollar Paren Double Quote"
|
||||
echo $(echo "foo
|
||||
bar")
|
||||
echo $(echo "foo
|
||||
bar")
|
||||
echo $(echo "foo\
|
||||
bar")
|
||||
|
||||
echo "Double Quote Dollar Paren Single Quote"
|
||||
echo "$(echo 'foo
|
||||
bar')"
|
||||
echo "$(echo 'foo
|
||||
bar')"
|
||||
echo "$(echo 'foo\
|
||||
bar')"
|
||||
|
||||
# old-style command substitution parsing compatibility tests -- post bash-3.1
|
||||
recho 'foo \\
|
||||
bar'
|
||||
|
||||
recho 'foo \
|
||||
bar'
|
||||
|
||||
echo `recho sed -e 's/[ :]/\\
|
||||
/g'`
|
||||
|
||||
echo `recho sed -e 's/[ :]/\
|
||||
/g'`
|
||||
|
||||
echo `recho 'foo\\
|
||||
bar'`
|
||||
|
||||
echo `recho 'foo\
|
||||
bar'`
|
||||
|
||||
echo $(recho 'foo\
|
||||
bar')
|
||||
|
||||
a=`echo 'a b c' | sed 's/ /\\
|
||||
/g' | grep 'b'`
|
||||
echo $a
|
||||
a=`echo 'a b c' | sed 's/ /\\
|
||||
/g'`
|
||||
echo "$a"
|
||||
|
||||
recho `echo 'a\' b`
|
||||
|
||||
recho `echo '\$' bab`
|
||||
recho `echo '\$foo' bab`
|
||||
|
||||
recho `echo '\`' ab`
|
||||
|
||||
recho `echo '\\' ab`
|
||||
@@ -888,18 +888,13 @@ reset_or_restore_signal_handlers (reset)
|
||||
`functrace' or `errtrace' options have been set, then let command
|
||||
substitutions inherit them. Let command substitution inherit the
|
||||
RETURN trap if we're in the debugger and tracing functions. */
|
||||
#if defined (DEBUGGER)
|
||||
if (debugging_mode == 0 || function_trace_mode == 0)
|
||||
#endif
|
||||
sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
|
||||
#if defined (DEBUGGER)
|
||||
if (debugging_mode == 0 || error_trace_mode == 0)
|
||||
#endif
|
||||
if (function_trace_mode == 0)
|
||||
{
|
||||
sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
|
||||
sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
|
||||
}
|
||||
if (error_trace_mode == 0)
|
||||
sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
|
||||
#if defined (DEBUGGER)
|
||||
if (debugging_mode == 0 || function_trace_mode == 0)
|
||||
#endif
|
||||
sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
|
||||
}
|
||||
|
||||
/* Reset trapped signals to their original values, but don't free the
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* trap.c -- Not the trap command, but useful functions for manipulating
|
||||
those objects. The trap command is in builtins/trap.def. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -452,7 +452,7 @@ set_sigint_handler ()
|
||||
else if (interactive) /* XXX - was interactive_shell */
|
||||
return (set_signal_handler (SIGINT, sigint_sighandler));
|
||||
else
|
||||
return (set_signal_handler (SIGINT, termination_unwind_protect));
|
||||
return (set_signal_handler (SIGINT, termsig_sighandler));
|
||||
}
|
||||
|
||||
/* Return the correct handler for signal SIG according to the values in
|
||||
@@ -494,17 +494,9 @@ set_signal (sig, string)
|
||||
{
|
||||
/* If we aren't sure of the original value, check it. */
|
||||
if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
|
||||
{
|
||||
original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
|
||||
set_signal_handler (sig, original_signals[sig]);
|
||||
}
|
||||
|
||||
/* Signals ignored on entry to the shell cannot be trapped or reset. */
|
||||
GETORIGSIG (sig);
|
||||
if (original_signals[sig] == SIG_IGN)
|
||||
{
|
||||
sigmodes[sig] |= SIG_HARD_IGNORE;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only change the system signal handler if SIG_NO_TRAP is not set.
|
||||
@@ -897,15 +889,15 @@ reset_or_restore_signal_handlers (reset)
|
||||
substitutions inherit them. Let command substitution inherit the
|
||||
RETURN trap if we're in the debugger and tracing functions. */
|
||||
#if defined (DEBUGGER)
|
||||
if (debugging_mode == 0 || function_trace_mode == 0)
|
||||
if (debugging_mode == 0 && function_trace_mode == 0)
|
||||
#endif
|
||||
sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
|
||||
#if defined (DEBUGGER)
|
||||
if (debugging_mode == 0 || error_trace_mode == 0)
|
||||
if (debugging_mode == 0 && error_trace_mode == 0)
|
||||
#endif
|
||||
sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
|
||||
#if defined (DEBUGGER)
|
||||
if (debugging_mode == 0 || function_trace_mode == 0)
|
||||
if (debugging_mode == 0 && function_trace_mode == 0)
|
||||
#endif
|
||||
sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user