diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | Doc/Zsh/expn.yo | 14 | ||||
-rw-r--r-- | Src/subst.c | 62 | ||||
-rw-r--r-- | Test/D04parameter.ztst | 24 |
4 files changed, 84 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog index 84a034b2a..145420cc0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2008-09-27 Peter Stephenson <p.w.stephenson@ntlworld.com> + * 25760: Doc/Zsh/expn.yo, Src/subst.c, Test/D04parameter.ztst: + (~) tokenizes arguments to further parameter flags, but not + the rest of the parameter expansion. + * Jörg Sommer: 25755, with tweak from 25756: Completion/Linux/Command/_modutils (args): improved handling of module arguments. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index b16ec4b5b..e2434431a 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -910,7 +910,19 @@ argument, a matched pair of delimiters must surround each argument. startitem() item(tt(p))( Recognize the same escape sequences as the tt(print) builtin -in string arguments to any of the flags described below. +in string arguments to any of the flags described below that +follow this argument. +) +item(tt(~))( +Force string arguments to any of the flags below that follow within +the parentheses to be treated as patterns. Compare with a tt(~) +outside parentheses, which forces the entire substituted string to +be treated as a pattern. Hence, for example, +example([[ "?" = ${(~j.|.)array} ]]) +with the tt(EXTENDED_GLOB) option set succeeds if and only if tt($array) +contains the string `tt(?)' as an element. The argument may be +repeated to toggle the behaviour; its effect only lasts to the +end of the parenthesised group. ) item(tt(j:)var(string)tt(:))( Join the words of arrays together using var(string) as a separator. diff --git a/Src/subst.c b/Src/subst.c index 95369fdf6..df60a27ab 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1232,6 +1232,27 @@ substevalchar(char *ptr) return metafy(ptr, len, META_USEHEAP); } +/* + * Helper function for arguments to parameter flags which + * handles the (p) and (~) flags as escapes and tok_arg respectively. + */ + +static char * +untok_and_escape(char *s, int escapes, int tok_arg) +{ + int klen; + char *dst; + + untokenize(dst = dupstring(s)); + if (escapes) { + dst = getkeystring(dst, &klen, GETKEYS_SEP, NULL); + dst = metafy(dst, klen, META_HREALLOC); + } + if (tok_arg) + shtokenize(dst); + return dst; +} + /* parameter substitution */ #define isstring(c) ((c) == '$' || (char)(c) == String || (char)(c) == Qstring) @@ -1501,23 +1522,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) int tt = 0; zlong num; /* - * The (p) flag is (uniquely) only remembered within + * The (p) flag is only remembered within * this block. It says we do print-style handling * on the values for flags, but only on those. - * This explains the ghastly macro, but why can't it - * be a function? UNTOK_AND_ESCAPE is defined - * so that the argument must be an lvalue. */ int escapes = 0; - int klen; -#define UNTOK(C) (itok(C) ? ztokens[(C) - Pound] : (C)) -#define UNTOK_AND_ESCAPE(X, S) {\ - untokenize(X = dupstring(S));\ - if (escapes) {\ - X = getkeystring(X, &klen, GETKEYS_SEP, NULL);\ - X = metafy(X, klen, META_HREALLOC);\ - }\ - } + /* + * '~' in parentheses caused tokenization of string arg: + * similar to (p). + */ + int tok_arg = 0; for (s++; (c = *s) != ')' && c != Outpar; s++, tt = 0) { int arglen; /* length of modifier argument */ @@ -1528,6 +1542,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) case ')': case Outpar: break; + case '~': + case Tilde: + tok_arg = !tok_arg; + break; case 'A': ++arrasg; break; @@ -1642,9 +1660,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) sav = *t; *t = '\0'; if (tt) - UNTOK_AND_ESCAPE(spsep, s + arglen) + spsep = untok_and_escape(s + arglen, + escapes, tok_arg); else - UNTOK_AND_ESCAPE(sep, s + arglen) + sep = untok_and_escape(s + arglen, + escapes, tok_arg); *t = sav; s = t + arglen - 1; } else @@ -1677,9 +1697,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) sav = *t; *t = '\0'; if (tt) - UNTOK_AND_ESCAPE(premul, s + arglen) + premul = untok_and_escape(s + arglen, escapes, + tok_arg); else - UNTOK_AND_ESCAPE(postmul, s + arglen) + postmul = untok_and_escape(s + arglen, escapes, + tok_arg); *t = sav; sav = *s; s = t + arglen; @@ -1695,9 +1717,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) sav = *t; *t = '\0'; if (tt) - UNTOK_AND_ESCAPE(preone, s + arglen) + preone = untok_and_escape(s + arglen, + escapes, tok_arg); else - UNTOK_AND_ESCAPE(postone, s + arglen) + postone = untok_and_escape(s + arglen, + escapes, tok_arg); *t = sav; /* -1 since loop will increment */ s = t + arglen - 1; diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 721396e73..376932b34 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1,4 +1,5 @@ # Test parameter expansion. Phew. +# (By the way, did I say "phew"?) %prep @@ -1062,3 +1063,26 @@ >1 >1 >1 + + foo=("|" "?") + [[ "|" = ${(j.|.)foo} ]] && print yes || print no + [[ "|" = ${(j.|.)~foo} ]] && print yes || print no + [[ "|" = ${(~j.|.)foo} ]] && print yes || print no + [[ "|" = ${(~~j.|.)foo} ]] && print yes || print no + [[ "|" = ${(j.|.~)foo} ]] && print yes || print no + [[ "x" = ${(j.|.)foo} ]] && print yes || print no + [[ "x" = ${(j.|.)~foo} ]] && print yes || print no + [[ "x" = ${(~j.|.)foo} ]] && print yes || print no + [[ "x" = ${(~~j.|.)foo} ]] && print yes || print no + [[ "x" = ${(j.|.~)foo} ]] && print yes || print no +0:GLOBSUBST only on parameter substitution arguments +>no +>yes +>yes +>no +>no +>no +>yes +>no +>no +>no |