summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2017-01-17 14:20:55 -0500
committerChet Ramey <chet.ramey@case.edu>2017-01-17 14:20:55 -0500
commit3e8a02a68917250f088a500b09543255364f6f2b (patch)
treedccc69fc7b986d8dcf092fb0354b3751c6cacc5f
parentee88838cf9421e2e40a7b7969cdf78a0010b075c (diff)
downloadbash-3e8a02a68917250f088a500b09543255364f6f2b.tar.gz
commit bash-20170113 snapshot
-rw-r--r--CWRU/CWRU.chlog24
-rw-r--r--lib/glob/glob.c51
-rw-r--r--lib/glob/glob_loop.c31
-rw-r--r--lib/glob/gmisc.c19
-rwxr-xr-xtests/RUN-ONE-TEST2
-rw-r--r--tests/extglob.right8
-rw-r--r--tests/extglob3.sub4
-rw-r--r--tests/extglob4.sub7
8 files changed, 107 insertions, 39 deletions
diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog
index e1826ba..2d2f7fc 100644
--- a/CWRU/CWRU.chlog
+++ b/CWRU/CWRU.chlog
@@ -12973,3 +12973,27 @@ execute_cmd.c
the only time QUIT gets called is when the path is actually
searched. It doesn't happen for an absolute pathname. Fix for
bug reported by Russell King <rmk@armlinux.org.uk>
+
+ 1/16
+ ----
+lib/glob/glob.c
+ - extglob_skipname,wextglob_skipname: if we don't find a reason to
+ not skip the name in any subpattern (r returns 0 for any subpattern),
+ return 1 because we should skip the name
+ - extglob_skipname,wextglob_skipname: if we don't find a reason to
+ not skip the name in any subpattern, but the first part of the extglob
+ pattern is a wildcard (`*(pat)'), check the rest of the pattern, if
+ any, to decide whether or not to skip the name. Fixes bug reported
+ by Grisha Levit <grishalevit@gmail.com>
+
+lib/glob/glob_loop.c
+ - CHAR -> GCHAR (unsigned char); change uses of CHAR to GCHAR
+ - extglob_skipname: move here from gmisc.c, generalize for regular
+ and wide-char versions
+
+lib/glob/glob.c
+ - wchkname -> wskipname
+ - wskipname: now takes a third `flags' argument, like the other variants
+ of skipname
+
+
diff --git a/lib/glob/glob.c b/lib/glob/glob.c
index 796ee9d..1451afa 100644
--- a/lib/glob/glob.c
+++ b/lib/glob/glob.c
@@ -126,19 +126,23 @@ extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int));
extern char *glob_dirscan __P((char *, int));
/* Compile `glob_loop.c' for single-byte characters. */
-#define CHAR unsigned char
+#define GCHAR unsigned char
+#define CHAR char
#define INT int
#define L(CS) CS
#define INTERNAL_GLOB_PATTERN_P internal_glob_pattern_p
+#define EXTGLOB_PATTERN_P extglob_pattern_p
#include "glob_loop.c"
/* Compile `glob_loop.c' again for multibyte characters. */
#if HANDLE_MULTIBYTE
+#define GCHAR wchar_t
#define CHAR wchar_t
#define INT wint_t
#define L(CS) L##CS
#define INTERNAL_GLOB_PATTERN_P internal_glob_wpattern_p
+#define EXTGLOB_PATTERN_P wextglob_pattern_p
#include "glob_loop.c"
#endif /* HANDLE_MULTIBYTE */
@@ -182,9 +186,10 @@ extglob_skipname (pat, dname, flags)
int flags;
{
char *pp, *pe, *t, *se;
- int n, r, negate;
+ int n, r, negate, wild;
negate = *pat == '!';
+ wild = *pat == '*' || *pat == '?';
pp = pat + 2;
se = pp + strlen (pp) - 1; /* end of string */
pe = glob_patscan (pp, se, 0); /* end of extglob pattern (( */
@@ -203,14 +208,19 @@ extglob_skipname (pat, dname, flags)
r = skipname (pp, dname, flags); /*(*/
#endif
*pe = ')';
+ if (wild && pe[1]) /* if we can match zero instances, check further */
+ return (skipname (pe+1, dname, flags));
return r;
}
/* check every subpattern */
while (t = glob_patscan (pp, pe, '|'))
{
- n = t[-1];
- t[-1] = '\0';
+ n = t[-1]; /* ( */
+ if (extglob_pattern_p (pp) && n == ')')
+ t[-1] = n; /* no-op for now */
+ else
+ t[-1] = '\0';
#if defined (HANDLE_MULTIBYTE)
r = mbskipname (pp, dname, flags);
#else
@@ -222,12 +232,14 @@ extglob_skipname (pat, dname, flags)
pp = t;
} /*(*/
- /* glob_patscan might find end of pattern */
+ /* glob_patscan might find end of string */
if (pp == se)
return r;
/* but if it doesn't then we didn't match a leading dot */
- return 0;
+ if (wild && *pe) /* if we can match zero instances, check further */
+ return (skipname (pe, dname, flags));
+ return 1;
}
#endif
@@ -263,8 +275,9 @@ skipname (pat, dname, flags)
#if HANDLE_MULTIBYTE
static int
-wchkname (pat_wc, dn_wc)
+wskipname (pat_wc, dn_wc, flags)
wchar_t *pat_wc, *dn_wc;
+ int flags;
{
/* If a leading dot need not be explicitly matched, and the
pattern doesn't start with a `.', don't match `.' or `..' */
@@ -291,9 +304,10 @@ wextglob_skipname (pat, dname, flags)
{
#if EXTENDED_GLOB
wchar_t *pp, *pe, *t, n, *se;
- int r, negate;
+ int r, negate, wild;
negate = *pat == L'!';
+ wild = *pat == L'*' || *pat == L'?';
pp = pat + 2;
se = pp + wcslen (pp) - 1; /*(*/
pe = glob_patscan_wc (pp, se, 0);
@@ -301,17 +315,22 @@ wextglob_skipname (pat, dname, flags)
if (pe == se && *pe == ')' && (t = wcschr (pp, L'|')) == 0)
{
*pe = L'\0';
- r = wchkname (pp, dname); /*(*/
+ r = wskipname (pp, dname, flags); /*(*/
*pe = L')';
+ if (wild && pe[1] != L'\0')
+ return (wskipname (pe+1, dname, flags));
return r;
}
/* check every subpattern */
while (t = glob_patscan_wc (pp, pe, '|'))
{
- n = t[-1];
- t[-1] = L'\0';
- r = wchkname (pp, dname);
+ n = t[-1]; /* ( */
+ if (wextglob_pattern_p (pp) && n == L')')
+ t[-1] = n; /* no-op for now */
+ else
+ t[-1] = L'\0';
+ r = wskipname (pp, dname, flags);
t[-1] = n;
if (r == 0)
return 0;
@@ -322,9 +341,11 @@ wextglob_skipname (pat, dname, flags)
return r;
/* but if it doesn't then we didn't match a leading dot */
- return 0;
+ if (wild && *pe != L'\0')
+ return (wskipname (pe, dname, flags));
+ return 1;
#else
- return (wchkname (pat, dname));
+ return (wskipname (pat, dname, flags));
#endif
}
@@ -355,7 +376,7 @@ mbskipname (pat, dname, flags)
ret = 0;
if (pat_n != (size_t)-1 && dn_n !=(size_t)-1)
- ret = ext ? wextglob_skipname (pat_wc, dn_wc, flags) : wchkname (pat_wc, dn_wc);
+ ret = ext ? wextglob_skipname (pat_wc, dn_wc, flags) : wskipname (pat_wc, dn_wc, flags);
else
ret = skipname (pat, dname, flags);
diff --git a/lib/glob/glob_loop.c b/lib/glob/glob_loop.c
index 89e86af..9529ccb 100644
--- a/lib/glob/glob_loop.c
+++ b/lib/glob/glob_loop.c
@@ -16,16 +16,16 @@
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
-static int INTERNAL_GLOB_PATTERN_P __P((const CHAR *));
+static int INTERNAL_GLOB_PATTERN_P __P((const GCHAR *));
/* Return nonzero if PATTERN has any special globbing chars in it.
Compiled twice, once each for single-byte and multibyte characters. */
static int
INTERNAL_GLOB_PATTERN_P (pattern)
- const CHAR *pattern;
+ const GCHAR *pattern;
{
- register const CHAR *p;
- register CHAR c;
+ register const GCHAR *p;
+ register GCHAR c;
int bopen;
p = pattern;
@@ -61,7 +61,30 @@ INTERNAL_GLOB_PATTERN_P (pattern)
return 0;
}
+#if EXTENDED_GLOB
+int
+EXTGLOB_PATTERN_P (pat)
+ const CHAR *pat;
+{
+ switch (pat[0])
+ {
+ case L('*'):
+ case L('+'):
+ case L('!'):
+ case L('@'):
+ case L('?'):
+ return (pat[1] == L('(')); /* ) */
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+#endif
+
+#undef EXTGLOB_PATTERN_P
#undef INTERNAL_GLOB_PATTERN_P
#undef L
#undef INT
#undef CHAR
+#undef GCHAR
diff --git a/lib/glob/gmisc.c b/lib/glob/gmisc.c
index 31906a4..19065fb 100644
--- a/lib/glob/gmisc.c
+++ b/lib/glob/gmisc.c
@@ -213,25 +213,6 @@ bad_bracket:
}
#endif
-int
-extglob_pattern_p (pat)
- char *pat;
-{
- switch (pat[0])
- {
- case '*':
- case '+':
- case '!':
- case '@':
- case '?':
- return (pat[1] == LPAREN);
- default:
- return 0;
- }
-
- return 0;
-}
-
#undef FOLD
#define FOLD(c) ((flags & FNM_CASEFOLD) \
? TOLOWER ((unsigned char)c) \
diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST
index 58c375b..554f3d6 100755
--- a/tests/RUN-ONE-TEST
+++ b/tests/RUN-ONE-TEST
@@ -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
diff --git a/tests/extglob.right b/tests/extglob.right
index efb7e5f..8c50059 100644
--- a/tests/extglob.right
+++ b/tests/extglob.right
@@ -94,14 +94,22 @@ a ab
a
. ..
. .. a.log
+*(foo)
+*(foo|bar)
a.log
?(foo)
a.log
a.log
. ..
+. ..
+a.log
a.log
.x .y .z
a b c
.x .y .z a b c
a b c
a b c
+a b c
+a b c
+.x .y .z a b c
+.x .y .z a b c
diff --git a/tests/extglob3.sub b/tests/extglob3.sub
index 8511b67..3f51c40 100644
--- a/tests/extglob3.sub
+++ b/tests/extglob3.sub
@@ -7,14 +7,18 @@ touch a.log
echo *(.)
echo *(.)*
+echo *(foo)
+echo *(foo|bar)
echo ?(foo)*
echo ?(foo)
echo *(foo)*
echo @(|foo)*
echo *(foo).*
+echo *(foo|bar).*
echo !(foo)*
+echo !(foo|bar)*
cd $OLDPWD
rm -rf $DIR
diff --git a/tests/extglob4.sub b/tests/extglob4.sub
index ccf74ef..2b4c53c 100644
--- a/tests/extglob4.sub
+++ b/tests/extglob4.sub
@@ -19,6 +19,13 @@ echo @(*|.!(|.)) # wrong, adds . and ..
echo @(*|@(f)) # ??
echo @(*|@(ff))
+echo !(f)
+echo !(f)!(f)
+
+shopt -s dotglob
+echo @(*|@(f))
+echo @(*|@(ff))
+
cd $OLDPWD
rm -rf $GTDIR