From 501f2003a89673cebc956ec5aa5f4f401b3a8f5f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 1 Jun 2014 20:55:39 +0100 Subject: 32640: (#q) in [[ ... ]] forces globbing --- Src/cond.c | 34 +++++++++++---------- Src/glob.c | 100 +++++++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 84 insertions(+), 50 deletions(-) (limited to 'Src') diff --git a/Src/cond.c b/Src/cond.c index c67354297..6e9b55806 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -37,6 +37,21 @@ static char *condstr[COND_MOD] = { "-ne", "-lt", "-gt", "-le", "-ge", "=~" }; +static void cond_subst(char **strp, int glob_ok) +{ + if (glob_ok && + checkglobqual(*strp, strlen(*strp), 1, NULL)) { + LinkList args = newlinklist(); + addlinknode(args, *strp); + prefork(args, 0); + while (!errflag && args && nonempty(args) && + has_token((char *)peekfirst(args))) + zglob(args, firstnode(args), 0); + *strp = sepjoin(hlinklist2array(args, 0), NULL, 1); + } else + singsub(strp); +} + /* * Evaluate a conditional expression given the arguments. * If fromtest is set, the caller is the test or [ builtin; @@ -177,13 +192,13 @@ evalcond(Estate state, char *fromtest) } left = ecgetstr(state, EC_DUPTOK, &htok); if (htok) { - singsub(&left); + cond_subst(&left, !fromtest); untokenize(left); } if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRNEQ) { right = ecgetstr(state, EC_DUPTOK, &htok); if (htok) { - singsub(&right); + cond_subst(&right, !fromtest); untokenize(right); } } @@ -194,7 +209,7 @@ evalcond(Estate state, char *fromtest) fprintf(xtrerr, " %s ", condstr[ctype]); if (ctype == COND_STREQ || ctype == COND_STRNEQ) { char *rt = dupstring(ecrawstr(state->prog, state->pc, NULL)); - singsub(&rt); + cond_subst(&rt, !fromtest); quote_tokenized_output(rt, xtrerr); } else @@ -283,7 +298,7 @@ evalcond(Estate state, char *fromtest) right = dupstring(opat = ecrawstr(state->prog, state->pc, &htok)); if (htok) - singsub(&right); + cond_subst(&right, !fromtest); save = (!(state->prog->flags & EF_HEAP) && !strcmp(opat, right) && pprog != dummy_patprog2); @@ -516,17 +531,6 @@ cond_val(char **args, int num) return mathevali(s); } -/**/ -mod_export int -cond_match(char **args, int num, char *str) -{ - char *s = args[num]; - - singsub(&s); - - return matchpat(str, s); -} - /**/ static void tracemodcond(char *name, char **args, int inf) diff --git a/Src/glob.c b/Src/glob.c index 07dd7c2d4..278c147f9 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -1061,6 +1061,67 @@ insert_glob_match(LinkList list, LinkNode next, char *data) insertlinknode(list, next, data); } +/* + * Return + * 1 if str ends in bare glob qualifiers + * 2 if str ends in non-bare glob qualifiers (#q) + * 0 otherwise. + * + * str is the string to check. + * sl is its length (to avoid recalculation). + * nobareglob is 1 if bare glob qualifiers are not allowed. + * *sp, if sp is not null, will be a pointer to the opening parenthesis. + */ + +/**/ +int +checkglobqual(char *str, int sl, int nobareglob, char **sp) +{ + char *s; + int paren, ret = 1; + + if (str[sl - 1] != Outpar) + return 0; + + /* Check these are really qualifiers, not a set of * + * alternatives or exclusions. We can be more * + * lenient with an explicit (#q) than with a bare * + * set of qualifiers. */ + paren = 0; + for (s = str + sl - 2; *s && (*s != Inpar || paren); s--) { + switch (*s) { + case Outpar: + paren++; /*FALLTHROUGH*/ + case Bar: + if (!zpc_disables[ZPC_BAR]) + nobareglob = 1; + break; + case Tilde: + if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_TILDE]) + nobareglob = 1; + break; + case Inpar: + paren--; + break; + } + if (s == str) + break; + } + if (*s != Inpar) + return 0; + if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH] && s[1] == Pound) { + if (s[2] != 'q') + return 0; + ret = 2; + } else if (nobareglob) + return 0; + + if (sp) + *sp = s; + + return ret; +} + /* Main entry point to the globbing code for filename globbing. * * np points to a node in the list list which will be expanded * * into a series of nodes. */ @@ -1118,7 +1179,7 @@ zglob(LinkList list, LinkNode np, int nountok) (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH])) { struct qual *newquals; char *s; - int sense, paren; + int sense, qualsfound; off_t data; char *sdata, *newcolonmod; int (*func) _((char *, Statptr, off_t, char *)); @@ -1148,40 +1209,7 @@ zglob(LinkList list, LinkNode np, int nountok) newquals = qo = qn = ql = NULL; sl = strlen(str); - if (str[sl - 1] != Outpar) - break; - - /* Check these are really qualifiers, not a set of * - * alternatives or exclusions. We can be more * - * lenient with an explicit (#q) than with a bare * - * set of qualifiers. */ - paren = 0; - for (s = str + sl - 2; *s && (*s != Inpar || paren); s--) { - switch (*s) { - case Outpar: - paren++; /*FALLTHROUGH*/ - case Bar: - if (!zpc_disables[ZPC_BAR]) - nobareglob = 1; - break; - case Tilde: - if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_TILDE]) - nobareglob = 1; - break; - case Inpar: - paren--; - break; - } - } - if (*s != Inpar) - break; - if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH] && s[1] == Pound) { - if (s[2] == 'q') { - *s = 0; - s += 2; - } else - break; - } else if (nobareglob) + if (!(qualsfound = checkglobqual(str, sl, nobareglob, &s))) break; /* Real qualifiers found. */ @@ -1194,6 +1222,8 @@ zglob(LinkList list, LinkNode np, int nountok) str[sl-1] = 0; *s++ = 0; + if (qualsfound == 2) + s += 2; while (*s && !newcolonmod) { func = (int (*) _((char *, Statptr, off_t, char *)))0; if (idigit(*s)) { -- cgit 1.4.1