From 0c226a628297057e2ef5a8e06755e1c37b260304 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Tue, 19 Mar 2013 15:05:35 +0000 Subject: 31158: following a wildcard with a repetition produces a bad pattern error --- Src/pattern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Src/pattern.c') diff --git a/Src/pattern.c b/Src/pattern.c index 53ada0f8d..3b6edb850 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -1474,7 +1474,7 @@ patcomppiece(int *flagp) } /* too much at once doesn't currently work */ - if (kshchar && pound) + if (kshchar && (pound || count)) return 0; if (kshchar == '*') { -- cgit v1.2.3 From 68d0d76db55c0b8778f0b68d3eda54060b576c41 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 1 Jun 2013 20:39:09 +0100 Subject: 31441: use array to decide which forms of pattern are enabled --- ChangeLog | 5 ++ Src/glob.c | 20 +++--- Src/pattern.c | 208 +++++++++++++++++++++++++++++++++++----------------------- Src/zsh.h | 40 ++++++++++- 4 files changed, 182 insertions(+), 91 deletions(-) (limited to 'Src/pattern.c') diff --git a/ChangeLog b/ChangeLog index 3ea29b6b3..87a64b835 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-06-01 Peter Stephenson + + * 31441: Src/glob.c, Src/pattern.c, Src/zsh.h: use an array + based on ZPC_* enum to decide which forms of pattern are enabled. + 2013-05-30 Peter Stephenson * 31436: Doc/Zsh/expn.yo: KSH_GLOB syntax does not diff --git a/Src/glob.c b/Src/glob.c index ca2ffaf51..db86d2468 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -708,8 +708,9 @@ parsecomplist(char *instr) } /* Parse repeated directories such as (dir/)# and (dir/)## */ - if (*(str = instr) == Inpar && !skipparens(Inpar, Outpar, (char **)&str) && - *str == Pound && isset(EXTENDEDGLOB) && str[-2] == '/') { + if (*(str = instr) == zpc_special[ZPC_INPAR] && + !skipparens(Inpar, Outpar, (char **)&str) && + *str == zpc_special[ZPC_HASH] && str[-2] == '/') { instr++; if (!(p1 = patcompile(instr, compflags, &instr))) return NULL; @@ -761,9 +762,9 @@ parsepat(char *str) * Check for initial globbing flags, so that they don't form * a bogus path component. */ - if ((*str == Inpar && str[1] == Pound && isset(EXTENDEDGLOB)) || - (isset(KSHGLOB) && *str == '@' && str[1] == Inpar && - str[2] == Pound)) { + if ((*str == zpc_special[ZPC_INPAR] && str[1] == zpc_special[ZPC_HASH]) || + (*str == zpc_special[ZPC_KSH_AT] && str[1] == Inpar && + str[2] == zpc_special[ZPC_HASH])) { str += (*str == Inpar) ? 2 : 3; if (!patgetglobflags(&str, &assert, &ignore)) return NULL; @@ -1146,7 +1147,7 @@ zglob(LinkList list, LinkNode np, int nountok) gf_pre_words = NULL; /* Check for qualifiers */ - while (!nobareglob || isset(EXTENDEDGLOB)) { + while (!nobareglob || zpc_special[ZPC_HASH] != Marker) { struct qual *newquals; char *s; int sense, paren; @@ -1192,10 +1193,11 @@ zglob(LinkList list, LinkNode np, int nountok) case Outpar: paren++; /*FALLTHROUGH*/ case Bar: - nobareglob = 1; + if (zpc_special[ZPC_BAR] != Marker) + nobareglob = 1; break; case Tilde: - if (isset(EXTENDEDGLOB)) + if (zpc_special[ZPC_TILDE] != Marker) nobareglob = 1; break; case Inpar: @@ -1205,7 +1207,7 @@ zglob(LinkList list, LinkNode np, int nountok) } if (*s != Inpar) break; - if (isset(EXTENDEDGLOB) && s[1] == Pound) { + if (s[1] == zpc_special[ZPC_HASH]) { if (s[2] == 'q') { *s = 0; s += 2; diff --git a/Src/pattern.c b/Src/pattern.c index 3b6edb850..54d6e7cb3 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -225,34 +225,27 @@ typedef unsigned long zrange_t; #endif /* - * Characters which terminate a pattern segment. We actually use - * a pointer patendseg which skips the first character if we are not - * parsing a file pattern. - * Note that the size of this and the next array are hard-wired - * via the definitions. + * Array of characters corresponding to zpc_chars enum, which it must match. */ - -static char endseg[] = { - '/', /* file only */ - '\0', Bar, Outpar, /* all patterns */ - Tilde /* extended glob only */ +static const char zpc_chars[ZPC_COUNT] = { + '/', '\0', Bar, Outpar, Tilde, Inpar, Quest, Star, Inbrack, Inang, + Hat, Pound, Bnullkeep, Quest, Star, '+', '!', '@' }; -#define PATENDSEGLEN_NORM 4 -#define PATENDSEGLEN_EXT 5 - -/* Characters which terminate a simple string */ - -static char endstr[] = { - '/', /* file only */ - '\0', Bar, Outpar, Quest, Star, Inbrack, Inpar, Inang, Bnullkeep, - /* all patterns */ - Tilde, Hat, Pound /* extended glob only */ -}; - -#define PATENDSTRLEN_NORM 10 -#define PATENDSTRLEN_EXT 13 +/* + * Characters which terminate a simple string (ZPC_COUNT) or + * an entire pattern segment (the first ZPC_SEG_COUNT). + * Each entry is either the corresponding character in zpc_chars + * or Marker which is guaranteed not to match a character in a + * pattern we are compiling. + * + * The complete list indicates characters that are special, so e.g. + * (testchar == special[ZPC_TILDE]) succeeds only if testchar is a Tilde + * *and* Tilde is currently special. + */ +/**/ +char zpc_special[ZPC_COUNT]; /* Default size for pattern buffer */ #define P_DEF_ALLOC 256 @@ -264,10 +257,6 @@ static char *patcode; /* point of code emission */ static long patsize; /* size of code */ static char *patout; /* start of code emission string */ static long patalloc; /* size allocated for same */ -static char *patendseg; /* characters ending segment */ -static int patendseglen; /* length of same */ -static char *patendstr; /* characters ending plain string */ -static int patendstrlen; /* length of sameo */ /* Flags used in both compilation and execution */ static int patflags; /* flags passed down to patcompile */ @@ -417,12 +406,56 @@ static long rn_offs; (P_OP(p) == P_BACK) ? \ ((p)-rn_offs) : ((p)+rn_offs) : NULL) +/* + * Set up zpc_special with characters that end a string segment. + * "Marker" cannot occur in the pattern we are compiling so + * is used to mark "invalid". + */ +static void +patcompcharsset(void) +{ + memcpy(zpc_special, zpc_chars, ZPC_COUNT); + if (!isset(EXTENDEDGLOB)) { + /* Extended glob characters are not active */ + zpc_special[ZPC_TILDE] = zpc_special[ZPC_HAT] = + zpc_special[ZPC_HASH] = Marker; + } + if (!isset(KSHGLOB)) { + /* + * Ksh glob characters are not active. + * * and ? are shared with normal globbing, but for their + * use here we are looking for a following Inpar. + */ + zpc_special[ZPC_KSH_QUEST] = zpc_special[ZPC_KSH_STAR] = + zpc_special[ZPC_KSH_PLUS] = zpc_special[ZPC_KSH_BANG] = + zpc_special[ZPC_KSH_AT] = Marker; + } + /* + * Note that if we are using KSHGLOB, then we test for a following + * Inpar, not zpc_special[ZPC_INPAR]: the latter makes an Inpar on + * its own active. The zpc_special[ZPC_KSH_*] followed by any old Inpar + * discriminate ksh globbing. + */ + if (isset(SHGLOB)) { + /* + * Grouping and numeric ranges are not valid. + * We do allow alternation, however; it's needed for + * "case". This may not be entirely consistent. + * + * Don't disable Outpar: we may need to match the end of KSHGLOB + * parentheses and it would be difficult to tell them apart. + */ + zpc_special[ZPC_INPAR] = zpc_special[ZPC_INANG] = Marker; + } +} + /* Called before parsing a set of file matchs to initialize flags */ /**/ void patcompstart(void) { + patcompcharsset(); if (isset(CASEGLOB)) patglobflags = 0; else @@ -469,16 +502,9 @@ patcompile(char *exp, int inflags, char **endexp) patnpar = 1; patflags = inflags & ~(PAT_PURES|PAT_HAS_EXCLUDP); - patendseg = endseg; - patendseglen = isset(EXTENDEDGLOB) ? PATENDSEGLEN_EXT : PATENDSEGLEN_NORM; - patendstr = endstr; - patendstrlen = isset(EXTENDEDGLOB) ? PATENDSTRLEN_EXT : PATENDSTRLEN_NORM; - if (!(patflags & PAT_FILE)) { - patendseg++; - patendstr++; - patendseglen--; - patendstrlen--; + patcompcharsset(); + zpc_special[ZPC_SLASH] = Marker; remnulargs(patparse); if (isset(MULTIBYTE)) patglobflags = GF_MULTIBYTE; @@ -698,11 +724,11 @@ patcompswitch(int paren, int *flagp) *flagp |= flags & (P_HSTART|P_PURESTR); - while (*patparse == Bar || - (isset(EXTENDEDGLOB) && *patparse == Tilde && + while (*patparse == zpc_chars[ZPC_BAR] || + (*patparse == zpc_special[ZPC_TILDE] && (patparse[1] == '/' || - !memchr(patendseg, patparse[1], patendseglen)))) { - int tilde = *patparse++ == Tilde; + !memchr(zpc_special, patparse[1], ZPC_SEG_COUNT)))) { + int tilde = *patparse++ == zpc_special[ZPC_TILDE]; long gfnode = 0, newbr; *flagp &= ~P_PURESTR; @@ -739,12 +765,9 @@ patcompswitch(int paren, int *flagp) up.p = NULL; patadd((char *)&up, 0, sizeof(up), 0); /* / is not treated as special if we are at top level */ - if (!paren && *patendseg == '/') { + if (!paren && zpc_special[ZPC_SLASH] == '/') { tilde++; - patendseg++; - patendseglen--; - patendstr++; - patendstrlen--; + zpc_special[ZPC_SLASH] = Marker; } } else { excsync = 0; @@ -784,10 +807,7 @@ patcompswitch(int paren, int *flagp) newbr = patcompbranch(&flags); if (tilde == 2) { /* restore special treatment of / */ - patendseg--; - patendseglen++; - patendstr--; - patendstrlen++; + zpc_special[ZPC_SLASH] = '/'; } if (!newbr) return 0; @@ -855,14 +875,13 @@ patcompbranch(int *flagp) *flagp = P_PURESTR; starter = chain = 0; - while (!memchr(patendseg, *patparse, patendseglen) || - (*patparse == Tilde && patparse[1] != '/' && - memchr(patendseg, patparse[1], patendseglen))) { - if (isset(EXTENDEDGLOB) && - ((!isset(SHGLOB) && - (*patparse == Inpar && patparse[1] == Pound)) || - (isset(KSHGLOB) && *patparse == '@' && patparse[1] == Inpar && - patparse[2] == Pound))) { + while (!memchr(zpc_special, *patparse, ZPC_SEG_COUNT) || + (*patparse == zpc_special[ZPC_TILDE] && patparse[1] != '/' && + memchr(zpc_special, patparse[1], ZPC_SEG_COUNT))) { + if ((*patparse == zpc_special[ZPC_INPAR] && + patparse[1] == zpc_special[ZPC_HASH]) || + (*patparse == zpc_special[ZPC_KSH_AT] && patparse[1] == Inpar && + patparse[2] == zpc_special[ZPC_HASH])) { /* Globbing flags. */ char *pp1 = patparse; int oldglobflags = patglobflags, ignore; @@ -910,7 +929,7 @@ patcompbranch(int *flagp) break; else continue; - } else if (isset(EXTENDEDGLOB) && *patparse == Hat) { + } else if (*patparse == zpc_special[ZPC_HAT]) { /* * ^pat: anything but pat. For proper backtracking, * etc., we turn this into (*~pat), except without the @@ -1171,7 +1190,7 @@ patcomppiece(int *flagp) { long starter = 0, next, op, opnd; int flags, flags2, kshchar, len, ch, patch, nmeta; - int pound, count; + int hash, count; union upat up; char *nptr, *str0, *ptr, *patprev; zrange_t from, to; @@ -1185,11 +1204,17 @@ patcomppiece(int *flagp) * the string doesn't introduce a ksh-like parenthesized expression. */ kshchar = '\0'; - if (isset(KSHGLOB) && *patparse && patparse[1] == Inpar) { - if (strchr("?*+!@", *patparse)) - kshchar = STOUC(*patparse); - else if (*patparse == Star || *patparse == Quest) - kshchar = STOUC(ztokens[*patparse - Pound]); + if (*patparse && patparse[1] == Inpar) { + if (*patparse == zpc_special[ZPC_KSH_PLUS]) + kshchar = STOUC('+'); + else if (*patparse == zpc_special[ZPC_KSH_BANG]) + kshchar = STOUC('!'); + else if (*patparse == zpc_special[ZPC_KSH_AT]) + kshchar = STOUC('@'); + else if (*patparse == zpc_special[ZPC_KSH_STAR]) + kshchar = STOUC('*'); + else if (*patparse == zpc_special[ZPC_KSH_QUEST]) + kshchar = STOUC('?'); } /* @@ -1199,10 +1224,10 @@ patcomppiece(int *flagp) * tildes are not special if there is nothing following to * be excluded. */ - if (kshchar || (memchr(patendstr, *patparse, patendstrlen) && - (*patparse != Tilde || + if (kshchar || (memchr(zpc_special, *patparse, ZPC_COUNT) && + (*patparse != zpc_special[ZPC_TILDE] || patparse[1] == '/' || - !memchr(patendseg, patparse[1], patendseglen)))) + !memchr(zpc_special, patparse[1], ZPC_SEG_COUNT)))) break; /* Remember the previous character for backtracking */ @@ -1227,10 +1252,14 @@ patcomppiece(int *flagp) * If we have more than one character, a following hash * or (#c...) only applies to the last, so backtrack one character. */ - if (isset(EXTENDEDGLOB) && - (*patparse == Pound || - (*patparse == Inpar && patparse[1] == Pound && - patparse[2] == 'c')) && morelen) + if ((*patparse == zpc_special[ZPC_HASH] || + (*patparse == zpc_special[ZPC_INPAR] && + patparse[1] == zpc_special[ZPC_HASH] && + patparse[2] == 'c') || + (*patparse == zpc_special[ZPC_KSH_AT] && + patparse[1] == Inpar && + patparse[2] == zpc_special[ZPC_HASH] && + patparse[3] == 'c')) && morelen) patparse = patprev; /* * If len is 1, we can't have an active # following, so doesn't @@ -1306,15 +1335,21 @@ patcomppiece(int *flagp) METACHARINC(patparse); switch(patch) { case Quest: + DPUTS(zpc_special[ZPC_QUEST] == Marker, + "Treating '?' as pattern character although disabled"); flags |= P_SIMPLE; starter = patnode(P_ANY); break; case Star: + DPUTS(zpc_special[ZPC_STAR] == Marker, + "Treating '*' as pattern character although disabled"); /* kshchar is used as a sign that we can't have #'s. */ kshchar = -1; starter = patnode(P_STAR); break; case Inbrack: + DPUTS(zpc_special[ZPC_INBRACK] == Marker, + "Treating '[' as pattern character although disabled"); flags |= P_SIMPLE; if (*patparse == Hat || *patparse == '^' || *patparse == '!') { patparse++; @@ -1368,9 +1403,10 @@ patcomppiece(int *flagp) patadd(NULL, 0, 1, 0); break; case Inpar: - /* is this how to treat parentheses in SHGLOB? */ - if (isset(SHGLOB) && !kshchar) - return 0; + DPUTS(zpc_special[ZPC_INPAR] == Marker, + "Treating '(' as pattern character although disabled"); + DPUTS(isset(SHGLOB) && !kshchar, + "Treating bare '(' as pattern character with SHGLOB"); if (kshchar == '!') { /* This is nasty, we should really either handle all * kshglobbing below or here. But most of the @@ -1393,6 +1429,9 @@ patcomppiece(int *flagp) break; case Inang: /* Numeric glob */ + DPUTS(zpc_special[ZPC_INANG] == Marker, + "Treating '<' as pattern character although disabled"); + DPUTS(isset(SHGLOB), "Treating <..> as numeric range with SHGLOB"); len = 0; /* beginning present 1, end present 2 */ if (idigit(*patparse)) { from = (zrange_t) zstrtol((char *)patparse, @@ -1435,6 +1474,8 @@ patcomppiece(int *flagp) */ break; case Pound: + DPUTS(zpc_special[ZPC_HASH] == Marker, + "Treating '#' as pattern character although disabled"); DPUTS(!isset(EXTENDEDGLOB), "BUG: # not treated as string"); /* * A hash here is an error; it should follow something @@ -1465,16 +1506,21 @@ patcomppiece(int *flagp) } count = 0; - if (!(pound = (*patparse == Pound && isset(EXTENDEDGLOB))) && - !(count = (isset(EXTENDEDGLOB) && *patparse == Inpar && - patparse[1] == Pound && patparse[2] == 'c')) && + if (!(hash = (*patparse == zpc_special[ZPC_HASH])) && + !(count = ((*patparse == zpc_special[ZPC_INPAR] && + patparse[1] == zpc_special[ZPC_HASH] && + patparse[2] == 'c') || + (*patparse == zpc_special[ZPC_KSH_AT] && + patparse[1] == Inpar && + patparse[2] == zpc_special[ZPC_HASH] && + patparse[3] == 'c'))) && (kshchar <= 0 || kshchar == '@' || kshchar == '!')) { *flagp = flags; return starter; } /* too much at once doesn't currently work */ - if (kshchar && (pound || count)) + if (kshchar && (hash || count)) return 0; if (kshchar == '*') { @@ -1490,7 +1536,7 @@ patcomppiece(int *flagp) op = P_COUNT; patparse += 3; *flagp = P_HSTART; - } else if (*++patparse == Pound) { + } else if (*++patparse == zpc_special[ZPC_HASH]) { op = P_TWOHASH; patparse++; *flagp = P_HSTART; @@ -1600,7 +1646,7 @@ patcomppiece(int *flagp) pattail(starter, next); patoptail(starter, next); } - if (*patparse == Pound) + if (*patparse == zpc_special[ZPC_HASH]) return 0; return starter; diff --git a/Src/zsh.h b/Src/zsh.h index f247563d4..639c2b746 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -179,7 +179,11 @@ struct mathfunc { * Take care to update the use of IMETA appropriately when adding * tokens here. */ -/* Marker used in paramsubst for rc_expand_param */ +/* + * Marker used in paramsubst for rc_expand_param. + * Also used in pattern character arrays as guaranteed not to + * mark a character in a string. + */ #define Marker ((char) 0xa0) /* chars that need to be quoted if meant literally */ @@ -1375,6 +1379,40 @@ struct patprog { #define PAT_HAS_EXCLUDP 0x0800 /* (internal): top-level path1~path2. */ #define PAT_LCMATCHUC 0x1000 /* equivalent to setting (#l) */ +/** + * Indexes into the array of active pattern characters. + * This must match the array zpc_chars in pattern.c. + */ +enum zpc_chars { + /* + * These characters both terminate a pattern segment and + * a pure string segment. + */ + ZPC_SLASH, /* / active as file separator */ + ZPC_NULL, /* \0 as string terminator */ + ZPC_BAR, /* | for "or" */ + ZPC_OUTPAR, /* ) for grouping */ + ZPC_TILDE, /* ~ for exclusion (extended glob) */ + ZPC_SEG_COUNT, /* No. of the above characters */ + /* + * These characters terminate a pure string segment. + */ + ZPC_INPAR = ZPC_SEG_COUNT, /* ( for grouping */ + ZPC_QUEST, /* ? as wildcard */ + ZPC_STAR, /* * as wildcard */ + ZPC_INBRACK, /* [ for character class */ + ZPC_INANG, /* < for numeric glob */ + ZPC_HAT, /* ^ for exclusion (extended glob) */ + ZPC_HASH, /* # for repetition (extended glob) */ + ZPC_BNULLKEEP, /* Special backslashed null not removed */ + ZPC_KSH_QUEST, /* ? for ?(...) in KSH_GLOB */ + ZPC_KSH_STAR, /* * for *(...) in KSH_GLOB */ + ZPC_KSH_PLUS, /* + for +(...) in KSH_GLOB */ + ZPC_KSH_BANG, /* ! for !(...) in KSH_GLOB */ + ZPC_KSH_AT, /* @ for @(...) in KSH_GLOB */ + ZPC_COUNT /* Number of special chararacters */ +}; + /* * Special match types used in character classes. These * are represented as tokens, with Meta added. The character -- cgit v1.2.3 From fdf2867e5f08809ff3fccc78fb6df13a196e3efc Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 13 Jun 2013 18:38:33 +0100 Subject: 31444: Basic code for enable/disable -p --- Doc/Zsh/builtins.yo | 102 +++++++++++++++++++++++++++++--- Doc/Zsh/options.yo | 13 ++++ Doc/zmacros.yo | 1 + Src/builtin.c | 20 +++++-- Src/exec.c | 5 ++ Src/options.c | 1 + Src/pattern.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Src/zsh.h | 16 +++++ 8 files changed, 313 insertions(+), 12 deletions(-) (limited to 'Src/pattern.c') diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index f3a7f6a97..3623f9bb9 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -291,8 +291,8 @@ enditem() findex(disable) cindex(disabling commands) cindex(commands, disabling) -item(tt(disable) [ tt(-afmrs) ] var(name) ...)( -Temporarily disable the var(name)d hash table elements. The default +item(tt(disable) [ tt(-afmprs) ] var(name) ...)( +Temporarily disable the var(name)d hash table elements or patterns. The default is to disable builtin commands. This allows you to use an external command with the same name as a builtin command. The tt(-a) option causes tt(disable) to act on regular or global aliases. The tt(-s) @@ -305,6 +305,80 @@ quoted to prevent them from undergoing filename expansion), and all hash table elements from the corresponding hash table matching these patterns are disabled. Disabled objects can be enabled with the tt(enable) command. + +With the option tt(-p), var(name) ... refer to elements of the +shell's pattern syntax as described in noderef(Filename Generation). +Certain elements can be disabled separately, as given below. + +Note that patterns +not allowed by the current settings for the options tt(EXTENDED_GLOB), +tt(KSH_GLOB) and tt(SH_GLOB) are never enabled, regardless of the +setting here. For example, if tt(EXTENDED_GLOB) is not active, +the pattern tt(^) is ineffective even if `tt(disable -p "^")' has +not been issued. The list below indicates any option settings +that restrict the use of the pattern. It should be noted that +setting tt(SH_GLOB) has a wider effect then merely disabling patterns +as certain expressions, in particular those involving parentheses, +are parsed differently. + +The following patterns may be disabled; all +the strings need quoting on the command line to prevent them from +being interpreted immediately as patterns and the patterns are +shown below in single quotes as a reminder. +startitem() +item(tt('?'))( +The pattern character tt(?) wherever it occurs, including when preceding +a parenthesis with tt(KSH_GLOB). +) +item(tt('*'))( +The pattern character tt(*) wherever it occurs, including recursive +globbing and when preceding a parenthesis with tt(KSH_GLOB). +) +item('LSQUARE()')( +Character classes. +) +item(tt('<') (tt(NO_SH_GLOB)))( +Numeric ranges. +) +item(tt('|') (tt(NO_SH_GLOB)))( +Alternation in grouped patterns, case statements, or KSH_GLOB +parenthesised expressions. +) +item(tt('LPAR()') (tt(NO_SH_GLOB)))( +Grouping using single parentheses. Disabling this does not disable the +use of parentheses for tt(KSH_GLOB) where they are introduced by a +special character, nor for glob qualifiers (use `tt(setopt +NO_BARE_GLOB_QUAL)' to disable glob qualifiers that use parentheses +only). +) +item(tt('~') (tt(EXTENDED_GLOB)))( +Exclusion in the form var(A)tt(~)var(B). +) +item(tt('^') (tt(EXTENDED_GLOB)))( +Exclusion in the form var(A)tt(^)var(B). +) +item(tt('#') (tt(EXTENDED_GLOB)))( +The pattern character tt(#) wherever it occurs, both for +repetition of a previous pattern and for indicating globbing flags. +) +item(tt('?LPAR()') (tt(KSH_GLOB)))( +The grouping form tt(?LPAR())var(...)tt(RPAR()). Note this is also +disabled if tt('?') is disabled. +) +item(tt('*LPAR()') (tt(KSH_GLOB)))( +The grouping form tt(*LPAR())var(...)tt(RPAR()). Note this is also +disabled if tt('*') is disabled. +) +item(tt('PLUS()LPAR()') (tt(KSH_GLOB)))( +The grouping form tt(PLUS()LPAR())var(...)tt(RPAR()). +) +item(tt('!LPAR()') (tt(KSH_GLOB)))( +The grouping form tt(!LPAR())var(...)tt(RPAR()). +) +item(tt('@LPAR()') (tt(KSH_GLOB)))( +The grouping form tt(@LPAR())var(...)tt(RPAR()). +) +enditem() ) findex(disown) cindex(jobs, disowning) @@ -376,7 +450,9 @@ the section COMPATIBILITY in zmanref(zsh) ifnzman(\ noderef(Compatibility) )\ -. +. In addition to setting shell options, the command also restores +the pristine state of pattern enables, as if all patterns had been +enabled using tt(enable -p). If the tt(emulate) command occurs inside a function that has been marked for execution tracing with tt(functions -t) then the tt(xtrace) @@ -390,9 +466,11 @@ are reset to their default value corresponding to the specified emulation mode, except for certain options describing the interactive environment; otherwise, only those options likely to cause portability problems in scripts and functions are altered. If the tt(-L) switch is given, -the options tt(LOCAL_OPTIONS) and tt(LOCAL_TRAPS) will be set as -well, causing the effects of the tt(emulate) command and any tt(setopt) and -tt(trap) commands to be local to the immediately surrounding shell +the options tt(LOCAL_OPTIONS), tt(LOCAL_PATTERNS) and tt(LOCAL_TRAPS) +will be set as +well, causing the effects of the tt(emulate) command and any tt(setopt), +tt(disable -p) or tt(enable -b), and tt(trap) commands to be local to +the immediately surrounding shell function, if any; normally these options are turned off in all emulation modes except tt(ksh). The tt(-L) switch is mutually exclusive with the use of tt(-c) in var(flags). @@ -414,7 +492,8 @@ Use of tt(-c) enables `sticky' emulation mode for functions defined within the evaluated expression: the emulation mode is associated thereafter with the function so that whenever the function is executed the emulation (respecting the tt(-R) switch, if present) and all -options are set before entry to the function, and restored after exit. +options are set (and pattern disables cleared) +before entry to the function, and the state is restored after exit. If the function is called when the sticky emulation is already in effect, either within an `tt(emulate) var(shell) tt(-c)' expression or within another function with the same sticky emulation, entry and exit @@ -471,7 +550,7 @@ endsitem() findex(enable) cindex(enabling commands) cindex(commands, enabling) -item(tt(enable) [ tt(-afmrs) ] var(name) ...)( +item(tt(enable) [ tt(-afmprs) ] var(name) ...)( Enable the var(name)d hash table elements, presumably disabled earlier with tt(disable). The default is to enable builtin commands. The tt(-a) option causes tt(enable) to act on regular or global aliases. @@ -483,6 +562,13 @@ printed. With the tt(-m) flag the arguments are taken as patterns (should be quoted) and all hash table elements from the corresponding hash table matching these patterns are enabled. Enabled objects can be disabled with the tt(disable) builtin command. + +tt(enable -p) reenables patterns disabled with tt(disable -p). Note +that it does not override globbing options; for example, `tt(enable -p +"~")' does not cause the pattern character tt(~) to be active unless +the tt(EXTENDED_GLOB) option is also set. To enable all possible +patterns (so that they may be invidually disabled with tt(disable -p)), +use `tt(setopt EXTENDED_GLOB KSH_GLOB NO_SH_GLOB)'. ) findex(eval) cindex(evaluating arguments as commands) diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 60892dd8b..ec862321e 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1618,6 +1618,19 @@ A shell function can also guarantee itself a known shell configuration with a formulation like `tt(emulate -L zsh)'; the tt(-L) activates tt(LOCAL_OPTIONS). ) +pindex(LOCAL_PATTERNS) +pindex(NO_LOCAL_PATTERNS) +pindex(LOCALPATTERNS) +pindex(NOLOCALPATTERNS) +item(tt(LOCAL_PATTERNS))( +If this option is set at the point of return from a shell function, +the state of pattern disables, as set with the builtin command +`tt(disable -p)', is restored to what it was when the function was +entered. The behaviour of this option is similar to the effect +of tt(LOCAL_OPTIONS) on options; hence `tt(emulate -L sh)' (or +indeed any other emulation with the tt(-L) option) activates +tt(LOCAL_PATTERNS). +) pindex(LOCAL_TRAPS) pindex(NO_LOCAL_TRAPS) pindex(LOCALTRAPS) diff --git a/Doc/zmacros.yo b/Doc/zmacros.yo index 19506d222..aed5bd8a7 100644 --- a/Doc/zmacros.yo +++ b/Doc/zmacros.yo @@ -33,6 +33,7 @@ DEFINEMACRO(RQUOTE)(0)(CHAR(39)) DEFINEMACRO(LPAR)(0)(CHAR(40)) DEFINEMACRO(RPAR)(0)(CHAR(41)) DEFINEMACRO(PLUS)(0)(CHAR(43)) +DEFINEMACRO(LSQUARE)(0)(CHAR(91)) DEFINEMACRO(DASH)(0)(ifztexi(--)ifnztexi(-)) diff --git a/Src/builtin.c b/Src/builtin.c index bc91578b3..8516acd81 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -55,11 +55,11 @@ static struct builtin builtins[] = BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL), BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klmprtuxz", NULL), BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL), - BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmrs", NULL), + BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmprs", NULL), BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL), BUILTIN("echo", BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"), BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "LR", NULL), - BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmrs", NULL), + BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmprs", NULL), BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL), BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL), BUILTIN("export", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "E:%F:%HL:%R:%TUZ:%afhi:%lprtu", "xg"), @@ -467,7 +467,9 @@ bin_enable(char *name, char **argv, Options ops, int func) int match = 0, returnval = 0; /* Find out which hash table we are working with. */ - if (OPT_ISSET(ops,'f')) + if (OPT_ISSET(ops,'p')) { + return pat_enables(name, argv, func == BIN_ENABLE); + } else if (OPT_ISSET(ops,'f')) ht = shfunctab; else if (OPT_ISSET(ops,'r')) ht = reswdtab; @@ -5020,6 +5022,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) int opt_R = OPT_ISSET(ops, 'R'); int saveemulation, savehackchar; int ret = 1, new_emulation; + unsigned int savepatterns; char saveopts[OPT_SIZE], new_opts[OPT_SIZE]; char *cmd = 0; const char *shname = *argv; @@ -5061,7 +5064,8 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) if (!argv[1]) { emulate(shname, OPT_ISSET(ops,'R'), &emulation, opts); if (OPT_ISSET(ops,'L')) - opts[LOCALOPTIONS] = opts[LOCALTRAPS] = 1; + opts[LOCALOPTIONS] = opts[LOCALTRAPS] = opts[LOCALPATTERNS] = 1; + clearpatterndisables(); return 0; } @@ -5082,6 +5086,13 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) goto restore; } + savepatterns = savepatterndisables(); + /* + * All emulations start with an empty set of pattern disables, + * hence no special "sticky" behaviour is required. + */ + clearpatterndisables(); + saveemulation = emulation; emulation = new_emulation; memcpy(opts, new_opts, sizeof(opts)); @@ -5131,6 +5142,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) sticky = save_sticky; emulation = saveemulation; memcpy(opts, saveopts, sizeof(opts)); + restorepatterndisables(savepatterns); restore: keyboardhackchar = savehackchar; inittyptab(); /* restore banghist */ diff --git a/Src/exec.c b/Src/exec.c index 14c2ba003..75805d3f5 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4627,6 +4627,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) } starttrapscope(); + startpatternscope(); pptab = pparams; if (!(flags & PM_UNDEFINED)) @@ -4674,6 +4675,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) offptr++) opts[*offptr] = 0; } + /* All emulations start with pattern disables clear */ + clearpatterndisables(); } else restore_sticky = 0; @@ -4774,6 +4777,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) scriptname = oldscriptname; oflags = ooflags; + endpatternscope(); /* before restoring old LOCALPATTERNS */ + if (restore_sticky) { /* * If we switched to an emulation environment just for diff --git a/Src/options.c b/Src/options.c index 480fccd57..ad869b253 100644 --- a/Src/options.c +++ b/Src/options.c @@ -179,6 +179,7 @@ static struct optname optns[] = { {{NULL, "listrowsfirst", 0}, LISTROWSFIRST}, {{NULL, "listtypes", OPT_ALL}, LISTTYPES}, {{NULL, "localoptions", OPT_EMULATE|OPT_KSH}, LOCALOPTIONS}, +{{NULL, "localpatterns", OPT_EMULATE}, LOCALPATTERNS}, {{NULL, "localtraps", OPT_EMULATE|OPT_KSH}, LOCALTRAPS}, {{NULL, "login", OPT_SPECIAL}, LOGINSHELL}, {{NULL, "longlistjobs", 0}, LONGLISTJOBS}, diff --git a/Src/pattern.c b/Src/pattern.c index 54d6e7cb3..a90d3cddc 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -232,6 +232,27 @@ static const char zpc_chars[ZPC_COUNT] = { Hat, Pound, Bnullkeep, Quest, Star, '+', '!', '@' }; +/* + * Corresponding strings used in enable/disable -p. + * NULL means no way of turning this on or off. + */ +static const char *zpc_strings[ZPC_COUNT] = { + NULL, NULL, "|", NULL, "~", "(", "?", "*", "[", "<", + "^", "#", NULL, "?(", "*(", "+(", "!(", "@(" +}; + +/* + * Corresponding array of pattern disables as set by the user + * using "disable -p". + */ +static char zpc_disables[ZPC_COUNT]; + +/* + * Stack of saved (compressed) zpc_disables for function scope. + */ + +static struct zpc_disables_save *zpc_disables_stack; + /* * Characters which terminate a simple string (ZPC_COUNT) or * an entire pattern segment (the first ZPC_SEG_COUNT). @@ -414,7 +435,19 @@ static long rn_offs; static void patcompcharsset(void) { + char *spp, *disp; + int i; + + /* Initialise enabled special characters */ memcpy(zpc_special, zpc_chars, ZPC_COUNT); + /* Apply user disables from disable -p */ + for (i = 0, spp = zpc_special, disp = zpc_disables; + i < ZPC_COUNT; + i++, spp++, disp++) { + if (*disp) + *spp = Marker; + } + if (!isset(EXTENDEDGLOB)) { /* Extended glob characters are not active */ zpc_special[ZPC_TILDE] = zpc_special[ZPC_HAT] = @@ -3799,3 +3832,137 @@ freepatprog(Patprog prog) if (prog && prog != dummy_patprog1 && prog != dummy_patprog2) zfree(prog, prog->size); } + +/* Disable or reenable a pattern character */ + +/**/ +int +pat_enables(const char *cmd, char **patp, int enable) +{ + int ret = 0; + const char **stringp; + char *disp; + + if (!*patp) { + int done = 0; + for (stringp = zpc_strings, disp = zpc_disables; + stringp < zpc_strings + ZPC_COUNT; + stringp++, disp++) { + if (!*stringp) + continue; + if (enable ? *disp : !*disp) + continue; + if (done) + putc(' ', stdout); + printf("'%s'", *stringp); + done = 1; + } + if (done) + putc('\n', stdout); + return 0; + } + + for (; *patp; patp++) { + for (stringp = zpc_strings, disp = zpc_disables; + stringp < zpc_strings + ZPC_COUNT; + stringp++, disp++) { + if (*stringp && !strcmp(*stringp, *patp)) { + *disp = (char)!enable; + break; + } + } + if (stringp == zpc_strings + ZPC_COUNT) { + zerrnam(cmd, "invalid pattern: %s", *patp); + ret = 1; + } + } + + return ret; +} + +/* + * Save the current state of pattern disables, returning the saved value. + */ + +/**/ +unsigned int +savepatterndisables(void) +{ + unsigned int disables, bit; + char *disp; + + disables = 0; + for (bit = 1, disp = zpc_disables; + disp < zpc_disables + ZPC_COUNT; + bit <<= 1, disp++) { + if (*disp) + disables |= bit; + } + return disables; +} + +/* + * Function scope saving pattern enables. + */ + +/**/ +void +startpatternscope(void) +{ + Zpc_disables_save newdis; + + newdis = (Zpc_disables_save)zalloc(sizeof(*newdis)); + newdis->next = zpc_disables_stack; + newdis->disables = savepatterndisables(); + + zpc_disables_stack = newdis; +} + +/* + * Restore completely the state of pattern disables. + */ + +/**/ +void +restorepatterndisables(unsigned int disables) +{ + char *disp; + unsigned int bit; + + for (bit = 1, disp = zpc_disables; + disp < zpc_disables + ZPC_COUNT; + bit <<= 1, disp++) { + if (disables & bit) + *disp = 1; + else + *disp = 0; + } +} + +/* + * Function scope to restore pattern enables if localpatterns is turned on. + */ + +/**/ +void +endpatternscope(void) +{ + Zpc_disables_save olddis; + + olddis = zpc_disables_stack; + zpc_disables_stack = olddis->next; + + if (isset(LOCALPATTERNS)) + restorepatterndisables(olddis->disables); + + zfree(olddis, sizeof(*olddis)); +} + +/* Reinitialise pattern disables */ + +/**/ +void +clearpatterndisables(void) +{ + memset(zpc_disables, 0, ZPC_COUNT); +} diff --git a/Src/zsh.h b/Src/zsh.h index 639c2b746..299357de8 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1413,6 +1413,21 @@ enum zpc_chars { ZPC_COUNT /* Number of special chararacters */ }; +/* + * Structure to save disables special characters for function scope. + */ +struct zpc_disables_save { + struct zpc_disables_save *next; + /* + * Bit vector of ZPC_COUNT disabled characters. + * We'll live dangerously and assumed ZPC_COUNT is no greater + * than the number of bits an an unsigned int. + */ + unsigned int disables; +}; + +typedef struct zpc_disables_save *Zpc_disables_save; + /* * Special match types used in character classes. These * are represented as tokens, with Meta added. The character @@ -2074,6 +2089,7 @@ enum { LISTROWSFIRST, LISTTYPES, LOCALOPTIONS, + LOCALPATTERNS, LOCALTRAPS, LOGINSHELL, LONGLISTJOBS, -- cgit v1.2.3 From 347a63da0cf1c681ac97c21a107b4722abf449b2 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 13 Jun 2013 18:40:36 +0100 Subject: 31465: fix basic completion and globbing uses of disabled patterns --- ChangeLog | 10 +++++++ Completion/compinit | 3 ++- Src/glob.c | 35 ------------------------- Src/pattern.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 36 deletions(-) (limited to 'Src/pattern.c') diff --git a/ChangeLog b/ChangeLog index f85626314..c495ede95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2013-06-13 Peter Stephenson + + * 31465: Completion/compinit, Src/glob.c, Src/pattern.c: fix + basic completion and globbing use of pattern disables. + + * 31444: Doc/Zsh/builtins.yo, Doc/Zsh/options.yo, + Doc/zmacros.yo, Src/builtin.c, Src/exec.c, Src/options.c, + Src/pattern.c, Src/zsh.h: Basic (not fully functional) code for + enable/disable -p. + 2013-06-13 Barton E. Schaefer * 31474: Makefile.in, Src/zsh.mdd: create patchlevel.h correctly diff --git a/Completion/compinit b/Completion/compinit index 7b8a34619..f9d2c574c 100644 --- a/Completion/compinit +++ b/Completion/compinit @@ -163,8 +163,9 @@ _comp_options=( typeset -g _comp_setup='local -A _comp_caller_options; _comp_caller_options=(${(kv)options[@]}); - setopt localoptions localtraps ${_comp_options[@]}; + setopt localoptions localtraps localpatterns ${_comp_options[@]}; local IFS=$'\'\ \\t\\r\\n\\0\'' + enable -p \| \~ \( \? \* \[ \< \^ \# exec start && isset(KSHGLOB) && + ((str[-1] == Quest && !zpc_disables[ZPC_KSH_QUEST]) || + (str[-1] == Star && !zpc_disables[ZPC_KSH_STAR]) || + (str[-1] == '+' && !zpc_disables[ZPC_KSH_PLUS]) || + (str[-1] == '!' && !zpc_disables[ZPC_KSH_BANG]) || + (str[-1] == '@' && !zpc_disables[ZPC_KSH_AT])))) + return 1; + break; + + case Bar: + if (!zpc_disables[ZPC_BAR]) + return 1; + break; + + case Star: + if (!zpc_disables[ZPC_STAR]) + return 1; + break; + + case Inbrack: + if (!zpc_disables[ZPC_INBRACK]) + return 1; + break; + + case Inang: + if (!zpc_disables[ZPC_INANG]) + return 1; + break; + + case Quest: + if (!zpc_disables[ZPC_QUEST]) + return 1; + break; + + case Pound: + if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH]) + return 1; + break; + + case Hat: + if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HAT]) + return 1; + break; + } + } + return 0; +} -- cgit v1.2.3 From 60debf388f65849fc31b92982274cc984da74052 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 23 Sep 2013 21:02:31 +0100 Subject: 31764: Dewreakify havoc caused by pattern disables on glob qualifiers. Don't use the zpc_specials array before it's defined, it's rude. --- ChangeLog | 6 ++++++ Src/glob.c | 9 +++++---- Src/pattern.c | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'Src/pattern.c') diff --git a/ChangeLog b/ChangeLog index 3220b6291..88dad0284 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-09-23 Peter Stephenson + + * 31764 (with correction of sense of a test): Src/glob.c, + Src/pattern.c: use of array before initialisation wreaked havoc + in detecting glob qualifiers. + 2013-09-22 m0viefreak * 31754: Completion/Unix/Command/_git: _git: git rm: make git rm diff --git a/Src/glob.c b/Src/glob.c index 9299b95ea..e0d0cf68e 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -1112,7 +1112,8 @@ zglob(LinkList list, LinkNode np, int nountok) gf_pre_words = NULL; /* Check for qualifiers */ - while (!nobareglob || zpc_special[ZPC_HASH] != Marker) { + while (!nobareglob || + (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH])) { struct qual *newquals; char *s; int sense, paren; @@ -1158,11 +1159,11 @@ zglob(LinkList list, LinkNode np, int nountok) case Outpar: paren++; /*FALLTHROUGH*/ case Bar: - if (zpc_special[ZPC_BAR] != Marker) + if (!zpc_disables[ZPC_BAR]) nobareglob = 1; break; case Tilde: - if (zpc_special[ZPC_TILDE] != Marker) + if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_TILDE]) nobareglob = 1; break; case Inpar: @@ -1172,7 +1173,7 @@ zglob(LinkList list, LinkNode np, int nountok) } if (*s != Inpar) break; - if (s[1] == zpc_special[ZPC_HASH]) { + if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH] && s[1] == Pound) { if (s[2] == 'q') { *s = 0; s += 2; diff --git a/Src/pattern.c b/Src/pattern.c index b7897e75c..4f0166bfa 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -245,7 +245,8 @@ static const char *zpc_strings[ZPC_COUNT] = { * Corresponding array of pattern disables as set by the user * using "disable -p". */ -static char zpc_disables[ZPC_COUNT]; +/**/ +char zpc_disables[ZPC_COUNT]; /* * Stack of saved (compressed) zpc_disables for function scope. -- cgit v1.2.3 From fa033326357218652310c4510898be622b871c4f Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Wed, 9 Oct 2013 17:57:03 +0200 Subject: 31805: Add $patchars and $dis_patchars to zsh/parameter module --- Doc/Zsh/mod_parameter.yo | 8 ++++++++ Src/Modules/parameter.c | 40 ++++++++++++++++++++++++++++++++++++++++ Src/Modules/parameter.mdd | 2 +- Src/pattern.c | 3 ++- Test/V01zmodload.ztst | 2 ++ 5 files changed, 53 insertions(+), 2 deletions(-) (limited to 'Src/pattern.c') diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo index 5948d74f2..32d4796f7 100644 --- a/Doc/Zsh/mod_parameter.yo +++ b/Doc/Zsh/mod_parameter.yo @@ -57,6 +57,14 @@ vindex(dis_reswords) item(tt(dis_reswords))( Like tt(reswords) but for disabled reserved words. ) +vindex(patchars) +item(tt(patchars))( +This array contains the enabled pattern characters. +) +vindex(dis_patchars) +item(tt(dis_patchars))( +Like tt(patchars) but for disabled pattern characters. +) vindex(aliases) item(tt(aliases))( This maps the names of the regular aliases currently enabled to their diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index a029c9cb4..22148f991 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -759,6 +759,38 @@ disreswordsgetfn(UNUSED(Param pm)) return getreswords(DISABLED); } +/* Functions for the patchars special parameter. */ + +/**/ +static char ** +getpatchars(int dis) +{ + int i; + char **ret, **p; + + p = ret = (char **) zhalloc(ZPC_COUNT * sizeof(char *)); + + for (i = 0; i < ZPC_COUNT; i++) + if (zpc_strings[i] && !dis == !zpc_disables[i]) + *p++ = dupstring(zpc_strings[i]); + + *p = NULL; + + return ret; +} + +static char ** +patcharsgetfn(UNUSED(Param pm)) +{ + return getpatchars(0); +} + +static char ** +dispatcharsgetfn(UNUSED(Param pm)) +{ + return getpatchars(1); +} + /* Functions for the options special parameter. */ /**/ @@ -2018,6 +2050,10 @@ static const struct gsu_array reswords_gsu = { reswordsgetfn, arrsetfn, stdunsetfn }; static const struct gsu_array disreswords_gsu = { disreswordsgetfn, arrsetfn, stdunsetfn }; +static const struct gsu_array patchars_gsu = +{ patcharsgetfn, arrsetfn, stdunsetfn }; +static const struct gsu_array dispatchars_gsu = +{ dispatcharsgetfn, arrsetfn, stdunsetfn }; static const struct gsu_array dirs_gsu = { dirsgetfn, dirssetfn, stdunsetfn }; static const struct gsu_array historywords_gsu = @@ -2038,6 +2074,8 @@ static struct paramdef partab[] = { &pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions), SPECIALPMDEF("dis_galiases", 0, &pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases), + SPECIALPMDEF("dis_patchars", PM_ARRAY|PM_READONLY, + &dispatchars_gsu, NULL, NULL), SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY, &disreswords_gsu, NULL, NULL), SPECIALPMDEF("dis_saliases", 0, @@ -2072,6 +2110,8 @@ static struct paramdef partab[] = { &pmoptions_gsu, getpmoption, scanpmoptions), SPECIALPMDEF("parameters", PM_READONLY, NULL, getpmparameter, scanpmparameters), + SPECIALPMDEF("patchars", PM_ARRAY|PM_READONLY, + &patchars_gsu, NULL, NULL), SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY, &reswords_gsu, NULL, NULL), SPECIALPMDEF("saliases", 0, diff --git a/Src/Modules/parameter.mdd b/Src/Modules/parameter.mdd index eb48d5f2a..a91a5dc09 100644 --- a/Src/Modules/parameter.mdd +++ b/Src/Modules/parameter.mdd @@ -2,6 +2,6 @@ name=zsh/parameter link=either load=yes -autofeatures="p:parameters p:commands p:functions p:dis_functions p:funcfiletrace p:funcsourcetrace p:funcstack p:functrace p:builtins p:dis_builtins p:reswords p:dis_reswords p:options p:modules p:dirstack p:history p:historywords p:jobtexts p:jobdirs p:jobstates p:nameddirs p:userdirs p:aliases p:dis_aliases p:galiases p:dis_galiases p:saliases p:dis_saliases" +autofeatures="p:parameters p:commands p:functions p:dis_functions p:funcfiletrace p:funcsourcetrace p:funcstack p:functrace p:builtins p:dis_builtins p:reswords p:dis_reswords p:patchars p:dis_patchars p:options p:modules p:dirstack p:history p:historywords p:jobtexts p:jobdirs p:jobstates p:nameddirs p:userdirs p:aliases p:dis_aliases p:galiases p:dis_galiases p:saliases p:dis_saliases" objects="parameter.o" diff --git a/Src/pattern.c b/Src/pattern.c index 4f0166bfa..609a9e372 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -236,7 +236,8 @@ static const char zpc_chars[ZPC_COUNT] = { * Corresponding strings used in enable/disable -p. * NULL means no way of turning this on or off. */ -static const char *zpc_strings[ZPC_COUNT] = { +/**/ +const char *zpc_strings[ZPC_COUNT] = { NULL, NULL, "|", NULL, "~", "(", "?", "*", "[", "<", "^", "#", NULL, "?(", "*(", "+(", "!(", "@(" }; diff --git a/Test/V01zmodload.ztst b/Test/V01zmodload.ztst index ea908e952..3580bacea 100644 --- a/Test/V01zmodload.ztst +++ b/Test/V01zmodload.ztst @@ -183,6 +183,7 @@ >p:dis_builtins >p:dis_functions >p:dis_galiases +>p:dis_patchars >p:dis_reswords >p:dis_saliases >p:funcfiletrace @@ -200,6 +201,7 @@ >p:nameddirs >p:options >p:parameters +>p:patchars >p:reswords >p:saliases >p:userdirs -- cgit v1.2.3 From 1c172cb080800ff2a6cedb63574c376faf42510a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 24 Oct 2013 18:45:50 +0100 Subject: 31877: fix behaviour of disable -p with parentheses --- ChangeLog | 5 +++++ Src/pattern.c | 44 ++++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 18 deletions(-) (limited to 'Src/pattern.c') diff --git a/ChangeLog b/ChangeLog index 416e8de76..9d0572073 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-10-24 Peter Stephenson + + * 31877: Src/pattern.c: fix behaviour of disable -p for + entities with parentheses. + 2013-10-24 Peter Stephenson * 31888: Test/A05execution.ztst: add test of pipestatus diff --git a/Src/pattern.c b/Src/pattern.c index 609a9e372..c86f86d69 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -748,7 +748,7 @@ patcompswitch(int paren, int *flagp) starter = 0; br = patnode(P_BRANCH); - if (!patcompbranch(&flags)) + if (!patcompbranch(&flags, paren)) return 0; if (patglobflags != (int)savglobflags) gfchanged++; @@ -839,7 +839,7 @@ patcompswitch(int paren, int *flagp) patglobflags = (int)savglobflags; } } - newbr = patcompbranch(&flags); + newbr = patcompbranch(&flags, paren); if (tilde == 2) { /* restore special treatment of / */ zpc_special[ZPC_SLASH] = '/'; @@ -902,7 +902,7 @@ patcompswitch(int paren, int *flagp) /**/ static long -patcompbranch(int *flagp) +patcompbranch(int *flagp, int paren) { long chain, latest = 0, starter; int flags = 0; @@ -973,7 +973,7 @@ patcompbranch(int *flagp) patparse++; latest = patcompnot(0, &flags); } else - latest = patcomppiece(&flags); + latest = patcomppiece(&flags, paren); if (!latest) return 0; if (!starter) @@ -1221,7 +1221,7 @@ pattern_range_to_string(char *rangestr, char *outstr) /**/ static long -patcomppiece(int *flagp) +patcomppiece(int *flagp, int paren) { long starter = 0, next, op, opnd; int flags, flags2, kshchar, len, ch, patch, nmeta; @@ -1253,17 +1253,25 @@ patcomppiece(int *flagp) } /* - * End of string (or no string at all) if ksh-type parentheses, - * or special character, unless that character is a tilde and - * the character following is an end-of-segment character. Thus - * tildes are not special if there is nothing following to - * be excluded. + * If '(' is disabled as a pattern char, allow ')' as + * an ordinary string character if there are no parentheses to + * close. Don't allow it otherwise, it changes the syntax. */ - if (kshchar || (memchr(zpc_special, *patparse, ZPC_COUNT) && - (*patparse != zpc_special[ZPC_TILDE] || - patparse[1] == '/' || - !memchr(zpc_special, patparse[1], ZPC_SEG_COUNT)))) - break; + if (zpc_special[ZPC_INPAR] != Marker || *patparse != Outpar || + paren) { + /* + * End of string (or no string at all) if ksh-type parentheses, + * or special character, unless that character is a tilde and + * the character following is an end-of-segment character. Thus + * tildes are not special if there is nothing following to + * be excluded. + */ + if (kshchar || (memchr(zpc_special, *patparse, ZPC_COUNT) && + (*patparse != zpc_special[ZPC_TILDE] || + patparse[1] == '/' || + !memchr(zpc_special, patparse[1], ZPC_SEG_COUNT)))) + break; + } /* Remember the previous character for backtracking */ patprev = patparse; @@ -1438,7 +1446,7 @@ patcomppiece(int *flagp) patadd(NULL, 0, 1, 0); break; case Inpar: - DPUTS(zpc_special[ZPC_INPAR] == Marker, + DPUTS(!kshchar && zpc_special[ZPC_INPAR] == Marker, "Treating '(' as pattern character although disabled"); DPUTS(isset(SHGLOB) && !kshchar, "Treating bare '(' as pattern character with SHGLOB"); @@ -1523,7 +1531,7 @@ patcomppiece(int *flagp) * Marker for restoring a backslash in output: * does not match a character. */ - next = patcomppiece(flagp); + next = patcomppiece(flagp, paren); /* * Can't match a pure string since we need to do this * as multiple chunks. @@ -1710,7 +1718,7 @@ patcompnot(int paren, int *flagsp) pattail(starter, excl = patnode(P_EXCLUDE)); up.p = NULL; patadd((char *)&up, 0, sizeof(up), 0); - if (!(br = (paren ? patcompswitch(1, &dummy) : patcompbranch(&dummy)))) + if (!(br = (paren ? patcompswitch(1, &dummy) : patcompbranch(&dummy, 0)))) return 0; pattail(br, patnode(P_EXCEND)); n = patnode(P_NOTHING); /* just so much easier */ -- cgit v1.2.3 From 375115c7dfd6dff576915d25fe2ecdd381dd9d81 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 6 Nov 2013 19:25:07 +0000 Subject: unposted: updates for 4.0.2-test-1. Update references to 4.0.2 to 4.0.3. Additional mod_export declarations. Additions to .distfiles. --- ChangeLog | 8 ++++++++ Completion/Debian/Command/.distfiles | 1 + Completion/Unix/Type/.distfiles | 1 + Config/version.mk | 4 ++-- Etc/FAQ.yo | 2 +- README | 5 ++--- Src/pattern.c | 4 ++-- Src/signals.c | 8 +++++--- Test/.distfiles | 1 + 9 files changed, 23 insertions(+), 11 deletions(-) (limited to 'Src/pattern.c') diff --git a/ChangeLog b/ChangeLog index 06abd2415..5f5dc719c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2013-11-06 Peter Stephenson + + * unposted: Completion/Debian/Command/.distfiles, + Completion/Unix/Type/.distfiles, Config/version.mk, Etc/FAQ.yo, + README, Src/pattern.c, Src/signals.c, Test/.distfiles: updates + for 4.0.2-test-1 in preparation for 4.0.3. Updated files + in .distfiles and add mod_export declarations. + 2013-11-03 Peter Stephenson * Stefan Neudorf: 31936: Doc/Zsh/builtins.yo, diff --git a/Completion/Debian/Command/.distfiles b/Completion/Debian/Command/.distfiles index a7f2205de..ed1575091 100644 --- a/Completion/Debian/Command/.distfiles +++ b/Completion/Debian/Command/.distfiles @@ -14,6 +14,7 @@ _cdbs-edit-patch _dak _dchroot _dchroot-dsa +_dcut _debchange _debdiff _debfoster diff --git a/Completion/Unix/Type/.distfiles b/Completion/Unix/Type/.distfiles index 42ecce56e..ea0baa7c7 100644 --- a/Completion/Unix/Type/.distfiles +++ b/Completion/Unix/Type/.distfiles @@ -34,6 +34,7 @@ _perl_basepods _perl_modules _pids _ports +_postscript _printers _ps1234 _pspdf diff --git a/Config/version.mk b/Config/version.mk index b755d739c..351a29602 100644 --- a/Config/version.mk +++ b/Config/version.mk @@ -27,5 +27,5 @@ # This must also serve as a shell script, so do not add spaces around the # `=' signs. -VERSION=5.0.2-dev-0 -VERSION_DATE='January 3, 2013' +VERSION=5.0.2-test-1 +VERSION_DATE='November 6, 2013' diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo index ed46571d0..4e04e73ea 100644 --- a/Etc/FAQ.yo +++ b/Etc/FAQ.yo @@ -301,7 +301,7 @@ sect(On what machines will it run?) sect(What's the latest version?) - Zsh 5.0.2 is the latest production version. For details of all the + Zsh 5.0.3 is the latest production version. For details of all the changes, see the NEWS file in the source distribution. A beta of the next version is sometimes available. Development of zsh is diff --git a/README b/README index 8ddad6e4e..c2fbf746d 100644 --- a/README +++ b/README @@ -5,9 +5,8 @@ THE Z SHELL (ZSH) Version ------- -This is version 5.0.2 of the shell. This is a stable release. -There are minor new features as well as bug fixes since 5.0.0 and -one bug fix since the short-lived 5.0.1. +This is version 5.0.3 of the shell. This is a stable release. +There are minor new features as well as bug fixes since 5.0.2. Installing Zsh -------------- diff --git a/Src/pattern.c b/Src/pattern.c index c86f86d69..a7ef12573 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -237,7 +237,7 @@ static const char zpc_chars[ZPC_COUNT] = { * NULL means no way of turning this on or off. */ /**/ -const char *zpc_strings[ZPC_COUNT] = { +mod_export const char *zpc_strings[ZPC_COUNT] = { NULL, NULL, "|", NULL, "~", "(", "?", "*", "[", "<", "^", "#", NULL, "?(", "*(", "+(", "!(", "@(" }; @@ -247,7 +247,7 @@ const char *zpc_strings[ZPC_COUNT] = { * using "disable -p". */ /**/ -char zpc_disables[ZPC_COUNT]; +mod_export char zpc_disables[ZPC_COUNT]; /* * Stack of saved (compressed) zpc_disables for function scope. diff --git a/Src/signals.c b/Src/signals.c index 046ee6a4a..c8f5fbcca 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -185,7 +185,7 @@ noholdintr(void) * only the given signal */ /**/ -sigset_t +mod_export sigset_t signal_mask(int sig) { sigset_t set; @@ -202,7 +202,8 @@ signal_mask(int sig) /**/ #ifndef BSD_SIGNALS -sigset_t +/**/ +mod_export sigset_t signal_block(sigset_t set) { sigset_t oset; @@ -245,7 +246,8 @@ signal_block(sigset_t set) /* Unblock the signals in the given signal * * set. Return the old signal set. */ -sigset_t +/**/ +mod_export sigset_t signal_unblock(sigset_t set) { sigset_t oset; diff --git a/Test/.distfiles b/Test/.distfiles index ab92153b0..1c0102818 100644 --- a/Test/.distfiles +++ b/Test/.distfiles @@ -41,6 +41,7 @@ V05styles.ztst V06parameter.ztst V07pcre.ztst V08zpty.ztst +X02zlevi.ztst Y01completion.ztst Y02compmatch.ztst Y03arguments.ztst -- cgit v1.2.3