mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-06 03:40:50 +02:00
more changes for bracket expressions in patterns
This commit is contained in:
+6
-6
@@ -127,8 +127,8 @@ static int glob_testdir PARAMS((char *, int));
|
||||
static char **glob_dir_to_array PARAMS((char *, char **, int));
|
||||
|
||||
/* Make sure these names continue to agree with what's in smatch.c */
|
||||
extern char *glob_patscan PARAMS((char *, char *, int));
|
||||
extern wchar_t *glob_patscan_wc PARAMS((wchar_t *, wchar_t *, int));
|
||||
extern char *glob_patscan PARAMS((char *, char *, int, int));
|
||||
extern wchar_t *glob_patscan_wc PARAMS((wchar_t *, wchar_t *, wint_t, int));
|
||||
|
||||
/* And this from gmisc.c/gm_loop.c */
|
||||
extern int wextglob_pattern_p PARAMS((wchar_t *));
|
||||
@@ -207,7 +207,7 @@ extglob_skipname (pat, dname, flags)
|
||||
wild = *pat == '*' || *pat == '?';
|
||||
pp = pat + 2;
|
||||
se = pp + strlen (pp); /* end of pattern string */
|
||||
pe = glob_patscan (pp, se, 0); /* end of extglob pattern */
|
||||
pe = glob_patscan (pp, se, 0, 0); /* end of extglob pattern */
|
||||
|
||||
/* if pe == 0, this is an invalid extglob pattern */
|
||||
if (pe == 0)
|
||||
@@ -234,7 +234,7 @@ extglob_skipname (pat, dname, flags)
|
||||
nullpat = pe >= (pat + 2) && pe[-2] == '(' && pe[-1] == ')';
|
||||
|
||||
/* check every subpattern */
|
||||
while (t = glob_patscan (pp, pe, '|'))
|
||||
while (t = glob_patscan (pp, pe, '|', 0))
|
||||
{
|
||||
/* If T == PE and *T == 0 (&& PE[-1] == RPAREN), we have hit the end
|
||||
of a pattern with no trailing characters. */
|
||||
@@ -358,7 +358,7 @@ wextglob_skipname (pat, dname, flags)
|
||||
wild = *pat == L'*' || *pat == L'?';
|
||||
pp = pat + 2;
|
||||
se = pp + wcslen (pp);
|
||||
pe = glob_patscan_wc (pp, se, 0);
|
||||
pe = glob_patscan_wc (pp, se, 0, 0);
|
||||
|
||||
/* if pe == 0, this is an invalid extglob pattern */
|
||||
if (pe == 0)
|
||||
@@ -382,7 +382,7 @@ wextglob_skipname (pat, dname, flags)
|
||||
nullpat = pe >= (pat + 2) && pe[-2] == L'(' && pe[-1] == L')';
|
||||
|
||||
/* check every subpattern */
|
||||
while (t = glob_patscan_wc (pp, pe, '|'))
|
||||
while (t = glob_patscan_wc (pp, pe, '|', 0))
|
||||
{
|
||||
n = t[-1]; /* ( */
|
||||
if (wextglob_pattern_p (pp) && n == L')') /* nested extglob? */
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@
|
||||
#include "glob.h"
|
||||
|
||||
/* Make sure these names continue to agree with what's in smatch.c */
|
||||
extern char *glob_patscan PARAMS((char *, char *, int));
|
||||
extern char *glob_patscan PARAMS((char *, char *, int, int));
|
||||
|
||||
/* Compile `gm_loop.c' for single-byte characters. */
|
||||
#define CHAR char
|
||||
@@ -92,7 +92,7 @@ glob_dirscan (pat, dirsep)
|
||||
{
|
||||
if (se == 0)
|
||||
se = p + strlen (p) - 1;
|
||||
pe = glob_patscan (p + 2, se, 0);
|
||||
pe = glob_patscan (p + 2, se, 0, 0);
|
||||
if (pe == 0)
|
||||
continue;
|
||||
else if (*pe == 0)
|
||||
|
||||
+79
-122
@@ -27,13 +27,13 @@ struct STRUCT
|
||||
int FCT PARAMS((CHAR *, CHAR *, int));
|
||||
|
||||
static int GMATCH PARAMS((CHAR *, CHAR *, CHAR *, CHAR *, struct STRUCT *, int));
|
||||
static CHAR *PARSE_COLLSYM PARAMS((CHAR *, INT *));
|
||||
static inline CHAR *PARSE_SUBBRACKET PARAMS((CHAR *, int));
|
||||
static CHAR *BRACKMATCH PARAMS((CHAR *, U_CHAR, int));
|
||||
static int EXTMATCH PARAMS((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
|
||||
|
||||
extern void DEQUOTE_PATHNAME PARAMS((CHAR *));
|
||||
|
||||
/*static*/ CHAR *PATSCAN PARAMS((CHAR *, CHAR *, INT));
|
||||
/*static*/ CHAR *PATSCAN PARAMS((CHAR *, CHAR *, INT, int));
|
||||
|
||||
int
|
||||
FCT (pattern, string, flags)
|
||||
@@ -192,7 +192,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
|
||||
that's OK, since we can match 0 or 1 occurrences.
|
||||
We need to skip the glob pattern and see if we
|
||||
match the rest of the string. */
|
||||
newn = PATSCAN (p + 1, pe, 0);
|
||||
newn = PATSCAN (p + 1, pe, 0, flags);
|
||||
/* If NEWN is 0, we have an ill-formed pattern. */
|
||||
p = newn ? newn : pe;
|
||||
}
|
||||
@@ -225,7 +225,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
|
||||
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);
|
||||
newn = PATSCAN (p + 1, pe, 0, flags);
|
||||
/* If NEWN is 0, we have an ill-formed pattern. */
|
||||
p = newn ? newn : pe;
|
||||
}
|
||||
@@ -380,36 +380,28 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
|
||||
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;
|
||||
if (p[pc] == 0)
|
||||
{
|
||||
if (vp)
|
||||
*vp = INVALID;
|
||||
return (p + pc);
|
||||
}
|
||||
val = COLLSYM (p, pc);
|
||||
if (vp)
|
||||
*vp = val;
|
||||
return (p + pc + 2);
|
||||
}
|
||||
|
||||
#define SLASH_PATHNAME(c) (c == L('/') && (flags & FNM_PATHNAME))
|
||||
|
||||
/* Parse a special bracket expression symbol ([.sym.], [=char=], [:cclass:]),
|
||||
starting at P, and return the position of the terminating .], =], or :].
|
||||
P points to the character after the opening bracket. Returns NULL if the
|
||||
symbol isn't correctly terminated. */
|
||||
static inline CHAR *
|
||||
PARSE_SUBBRACKET (p, flags)
|
||||
CHAR *p;
|
||||
int flags;
|
||||
{
|
||||
CHAR type; /* the type of special bracket expression symbol */
|
||||
|
||||
type = *p;
|
||||
|
||||
/* POSIX allows a right bracket to appear in a collating symbol. */
|
||||
while (*++p != L('\0') && SLASH_PATHNAME (*p) == 0 && (type != L('.') && *p == L(']')) == 0)
|
||||
if (*p == type && p[1] == L(']'))
|
||||
return p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Use prototype definition here because of type promotion. */
|
||||
static CHAR *
|
||||
#if defined (PROTOTYPES)
|
||||
@@ -423,10 +415,10 @@ 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, isrange;
|
||||
int forcecoll, isrange;
|
||||
INT pc;
|
||||
CHAR *savep;
|
||||
CHAR *brchrp;
|
||||
CHAR *close;
|
||||
U_CHAR orig_test;
|
||||
|
||||
orig_test = test;
|
||||
@@ -451,18 +443,13 @@ BRACKMATCH (p, test, flags)
|
||||
|
||||
/* 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(']'))
|
||||
it, and check for equivalence. */
|
||||
if (c == L('[') && *p == L('=') && (close = PARSE_SUBBRACKET (p, flags)) != NULL)
|
||||
{
|
||||
pc = FOLD (p[1]);
|
||||
p += 4;
|
||||
|
||||
/* Finding a slash in a bracket expression means you have to
|
||||
match the bracket as an ordinary character (see below). */
|
||||
if (pc == L('/') && (flags & FNM_PATHNAME))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
|
||||
p++;
|
||||
pc = COLLSYM (p, close - p);
|
||||
pc = FOLD (pc);
|
||||
p = close + 2;
|
||||
|
||||
if (COLLEQUIV (test, pc))
|
||||
{
|
||||
@@ -486,30 +473,21 @@ BRACKMATCH (p, test, flags)
|
||||
}
|
||||
|
||||
/* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */
|
||||
if (c == L('[') && *p == L(':'))
|
||||
if (c == L('[') && *p == L(':') && (close = PARSE_SUBBRACKET (p, flags)) != NULL)
|
||||
{
|
||||
CHAR *close, *ccname;
|
||||
CHAR *ccname;
|
||||
|
||||
pc = 0; /* make sure invalid char classes don't match. */
|
||||
/* Find end of character class name */
|
||||
for (close = p + 1; *close != '\0' && SLASH_PATHNAME(*close) == 0; close++)
|
||||
if (*close == L(':') && *(close+1) == L(']'))
|
||||
break;
|
||||
|
||||
if (*close != L('\0') && SLASH_PATHNAME(*close) == 0)
|
||||
ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR));
|
||||
if (ccname)
|
||||
{
|
||||
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');
|
||||
/* As a result of a POSIX discussion, char class names are
|
||||
allowed to be quoted (?) */
|
||||
DEQUOTE_PATHNAME (ccname);
|
||||
pc = IS_CCLASS (orig_test, (XCHAR *)ccname);
|
||||
}
|
||||
bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR));
|
||||
*(ccname + (close - p - 1)) = L('\0');
|
||||
/* As a result of a POSIX discussion, char class names are
|
||||
allowed to be quoted (?) */
|
||||
DEQUOTE_PATHNAME (ccname);
|
||||
pc = IS_CCLASS (orig_test, (XCHAR *)ccname);
|
||||
if (pc == -1)
|
||||
{
|
||||
/* CCNAME is not a valid character class in the current
|
||||
@@ -521,14 +499,12 @@ BRACKMATCH (p, test, flags)
|
||||
string. If we don't want to do that, take out the update
|
||||
of P. */
|
||||
pc = 0;
|
||||
p = close + 2;
|
||||
}
|
||||
else
|
||||
p = close + 2; /* move past the closing `]' */
|
||||
|
||||
free (ccname);
|
||||
}
|
||||
|
||||
free (ccname);
|
||||
|
||||
p = close + 2;
|
||||
|
||||
if (pc)
|
||||
{
|
||||
/*[*/ /* Move past the closing `]', since the first thing we do at
|
||||
@@ -556,13 +532,11 @@ BRACKMATCH (p, test, flags)
|
||||
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('.'))
|
||||
if (c == L('[') && *p == L('.') && (close = PARSE_SUBBRACKET (p, flags)) != NULL)
|
||||
{
|
||||
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;
|
||||
p++;
|
||||
cstart = COLLSYM (p, close - p);
|
||||
p = close + 2;
|
||||
forcecoll = 1;
|
||||
}
|
||||
|
||||
@@ -616,13 +590,11 @@ BRACKMATCH (p, test, flags)
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
else if (cend == L('/') && (flags & FNM_PATHNAME))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
if (cend == L('[') && *p == L('.'))
|
||||
if (cend == L('[') && *p == L('.') && (close = PARSE_SUBBRACKET (p, flags)) != NULL)
|
||||
{
|
||||
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;
|
||||
p++;
|
||||
cend = COLLSYM (p, close - p);
|
||||
p = close + 2;
|
||||
forcecoll = 1;
|
||||
}
|
||||
cend = FOLD (cend);
|
||||
@@ -658,46 +630,29 @@ BRACKMATCH (p, test, flags)
|
||||
matched:
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
c = *--p;
|
||||
brcnt = 1;
|
||||
brchrp = 0;
|
||||
while (brcnt > 0)
|
||||
while (1)
|
||||
{
|
||||
int oc;
|
||||
|
||||
/* A `[' without a matching `]' is just another character to match. */
|
||||
if (c == L('\0'))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
else if (c == L('/') && (flags & FNM_PATHNAME))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
|
||||
oc = c;
|
||||
c = *p++;
|
||||
if (c == L('[') && (*p == L('=') || *p == L(':') || *p == L('.')))
|
||||
{
|
||||
brcnt++;
|
||||
brchrp = p++; /* skip over the char after the left bracket */
|
||||
c = *p;
|
||||
if (c == L('\0'))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
else if (c == L('/') && (flags & FNM_PATHNAME))
|
||||
return ((test == L('[')) ? savep : (CHAR *)0);
|
||||
/* If *brchrp == ':' we should check that the rest of the characters
|
||||
form a valid character class name. We don't do that yet, but we
|
||||
keep BRCHRP in case we want to. */
|
||||
}
|
||||
/* We only want to check brchrp if we set it above. */
|
||||
else if (c == L(']') && brcnt > 1 && brchrp != 0 && oc == *brchrp)
|
||||
{
|
||||
brcnt--;
|
||||
brchrp = 0; /* just in case */
|
||||
if ((close = PARSE_SUBBRACKET (p, flags)) != NULL)
|
||||
p = close + 2;
|
||||
}
|
||||
/* Left bracket loses its special meaning inside a bracket expression.
|
||||
It is only valid when followed by a `.', `=', or `:', which we check
|
||||
for above. Technically the right bracket can appear in a collating
|
||||
symbol, so we check for that here. Otherwise, it terminates the
|
||||
bracket expression. */
|
||||
else if (c == L(']') && (brchrp == 0 || *brchrp != L('.')) && brcnt >= 1)
|
||||
brcnt = 0;
|
||||
symbol, so we check for that as well. The right brackets terminating
|
||||
collating symbols, equivalence classes, or character classes are
|
||||
processed by PARSE_SUBBRACKET. Otherwise, a right bracket terminates
|
||||
the bracket expression. */
|
||||
else if (c == L(']'))
|
||||
break;
|
||||
else if (!(flags & FNM_NOESCAPE) && c == L('\\'))
|
||||
{
|
||||
if (*p == '\0')
|
||||
@@ -734,16 +689,15 @@ matched:
|
||||
first character after the matching DELIM or NULL if the pattern is
|
||||
empty or invalid. */
|
||||
/*static*/ CHAR *
|
||||
PATSCAN (string, end, delim)
|
||||
PATSCAN (string, end, delim, flags)
|
||||
CHAR *string, *end;
|
||||
INT delim;
|
||||
int flags;
|
||||
{
|
||||
int pnest, bnest, skip;
|
||||
INT cchar;
|
||||
CHAR *s, c, *bfirst;
|
||||
CHAR *s, c, *bfirst, *t;
|
||||
|
||||
pnest = bnest = skip = 0;
|
||||
cchar = 0;
|
||||
bfirst = NULL;
|
||||
|
||||
if (string == end)
|
||||
@@ -761,7 +715,8 @@ PATSCAN (string, end, delim)
|
||||
switch (c)
|
||||
{
|
||||
case L('\\'):
|
||||
skip = 1;
|
||||
if ((flags & FNM_NOESCAPE) == 0)
|
||||
skip = 1;
|
||||
break;
|
||||
|
||||
case L('\0'):
|
||||
@@ -779,7 +734,11 @@ PATSCAN (string, end, delim)
|
||||
bnest++;
|
||||
}
|
||||
else if (s[1] == L(':') || s[1] == L('.') || s[1] == L('='))
|
||||
cchar = s[1];
|
||||
{
|
||||
t = PARSE_SUBBRACKET (s + 1, flags);
|
||||
if (t)
|
||||
s = t + 2 - 1; /* -1 to cancel s++ in loop above */
|
||||
}
|
||||
break;
|
||||
|
||||
/* `]' is not special if it's the first char (after a leading `!'
|
||||
@@ -788,9 +747,7 @@ PATSCAN (string, end, delim)
|
||||
case L(']'):
|
||||
if (bnest)
|
||||
{
|
||||
if (cchar && s[-1] == cchar)
|
||||
cchar = 0;
|
||||
else if (s != bfirst)
|
||||
if (s != bfirst)
|
||||
{
|
||||
bnest--;
|
||||
bfirst = 0;
|
||||
@@ -879,7 +836,7 @@ 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); /* ) */
|
||||
prest = PATSCAN (p + (*p == L('(')), pe, 0, flags); /* ) */
|
||||
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. */
|
||||
@@ -902,7 +859,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
|
||||
string. */
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = PATSCAN (psub, pe, L('|'));
|
||||
pnext = PATSCAN (psub, pe, L('|'), flags);
|
||||
for (srest = s; srest <= se; srest++)
|
||||
{
|
||||
/* Match this substring (S -> SREST) against this
|
||||
@@ -939,7 +896,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
|
||||
rest of the string. */
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = PATSCAN (psub, pe, L('|'));
|
||||
pnext = PATSCAN (psub, pe, L('|'), flags);
|
||||
srest = (prest == pe) ? se : s;
|
||||
for ( ; srest <= se; srest++)
|
||||
{
|
||||
@@ -960,7 +917,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
|
||||
m1 = 0;
|
||||
for (psub = p + 1; ; psub = pnext)
|
||||
{
|
||||
pnext = PATSCAN (psub, pe, L('|'));
|
||||
pnext = PATSCAN (psub, pe, L('|'), flags);
|
||||
/* If one of the patterns matches, just bail immediately. */
|
||||
if (m1 = (GMATCH (s, srest, psub, pnext - 1, NULL, flags) == 0))
|
||||
break;
|
||||
@@ -1001,7 +958,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
|
||||
#undef FCT
|
||||
#undef GMATCH
|
||||
#undef COLLSYM
|
||||
#undef PARSE_COLLSYM
|
||||
#undef PARSE_SUBBRACKET
|
||||
#undef PATSCAN
|
||||
#undef STRCOMPARE
|
||||
#undef EXTMATCH
|
||||
|
||||
+2
-2
@@ -322,7 +322,7 @@ is_cclass (c, name)
|
||||
#define FCT internal_strmatch
|
||||
#define GMATCH gmatch
|
||||
#define COLLSYM collsym
|
||||
#define PARSE_COLLSYM parse_collsym
|
||||
#define PARSE_SUBBRACKET parse_subbracket
|
||||
#define BRACKMATCH brackmatch
|
||||
#define PATSCAN glob_patscan
|
||||
#define STRCOMPARE strcompare
|
||||
@@ -578,7 +578,7 @@ posix_cclass_only (pattern)
|
||||
#define FCT internal_wstrmatch
|
||||
#define GMATCH gmatch_wc
|
||||
#define COLLSYM collwcsym
|
||||
#define PARSE_COLLSYM parse_collwcsym
|
||||
#define PARSE_SUBBRACKET parse_subbracket_wc
|
||||
#define BRACKMATCH brackmatch_wc
|
||||
#define PATSCAN glob_patscan_wc
|
||||
#define STRCOMPARE wscompare
|
||||
|
||||
@@ -3394,9 +3394,9 @@ _rl_update_final (void)
|
||||
puts_face (&last_line[_rl_screenwidth - 1 + woff],
|
||||
&last_face[_rl_screenwidth - 1 + woff], 1);
|
||||
}
|
||||
_rl_vis_botlin = 0;
|
||||
if (botline_length > 0 || _rl_last_c_pos > 0)
|
||||
if ((_rl_vis_botlin == 0 && botline_length == 0) || botline_length > 0 || _rl_last_c_pos > 0)
|
||||
rl_crlf ();
|
||||
_rl_vis_botlin = 0;
|
||||
fflush (rl_outstream);
|
||||
rl_display_fixed++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user