From 6269db883ad6989a578bac299deab9c4285bb1df Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 10 May 2015 19:19:34 +0100 Subject: 35067: Add (b) parameter flag for pattern char backslashing. Doc tweak from Daniel in 35071. Includes test. --- Src/subst.c | 13 +++++++++++-- Src/utils.c | 23 +++++++++++++++++++---- Src/zsh.h | 10 ++++++++++ Src/ztype.h | 2 ++ 4 files changed, 42 insertions(+), 6 deletions(-) (limited to 'Src') diff --git a/Src/subst.c b/Src/subst.c index f52bcdfc8..bf80495bd 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1592,7 +1592,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) /* combination of (L), (U) and (C) flags. */ int casmod = CASMOD_NONE; /* - * quotemod says we are doing either (q) (positive), (Q) (negative) + * quotemod says we are doing either (q/b) (positive), (Q) (negative) * or not (0). quotetype counts the q's for the first case. * quoterr is simply (X) but gets passed around a lot because the * combination (eX) needs it. @@ -1861,6 +1861,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) quotemod++, quotetype++; } break; + case 'b': + if (quotemod || quotetype != QT_NONE) + goto flagerr; + quotemod = 1; + quotetype = QT_BACKSLASH_PATTERN; + break; case 'Q': quotemod--; break; @@ -3460,7 +3466,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) if (quotemod) { int pre = 0, post = 0; - if (quotemod > 0 && quotetype > QT_BACKSLASH) { + if (quotemod > 0) { switch (quotetype) { case QT_DOLLARS: @@ -3471,6 +3477,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) case QT_SINGLE_OPTIONAL: /* quotes will be added for us */ + case QT_BACKSLASH: + case QT_BACKSLASH_PATTERN: + /* no quotes */ break; default: diff --git a/Src/utils.c b/Src/utils.c index 13d4b83d4..271c800fd 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -3694,6 +3694,8 @@ inittyptab(void) typtab[bangchar] |= ISPECIAL; } else typtab_flags &= ~ZTF_BANGCHAR; + for (s = PATCHARS; *s; s++) + typtab[STOUC(*s)] |= IPATTERN; unqueue_signals(); } @@ -5075,6 +5077,10 @@ quotestring(const char *s, char **e, int instring) alloclen = slen * 7 + 1; break; + case QT_BACKSLASH_PATTERN: + alloclen = slen * 2 + 1; + break; + case QT_SINGLE_OPTIONAL: /* * Here, we may need to add single quotes. @@ -5094,7 +5100,7 @@ quotestring(const char *s, char **e, int instring) quotestart = v = buf = zshcalloc(alloclen); DPUTS(instring < QT_BACKSLASH || instring == QT_BACKTICK || - instring > QT_SINGLE_OPTIONAL, + instring > QT_BACKSLASH_PATTERN, "BUG: bad quote type in quotestring"); u = s; if (instring == QT_DOLLARS) { @@ -5134,9 +5140,18 @@ quotestring(const char *s, char **e, int instring) u = uend; } } - } - else - { + } else if (instring == QT_BACKSLASH_PATTERN) { + while (*u) { + if (e && !sf && *e == u) { + *e = v; + sf = 1; + } + + if (ipattern(*u)) + *v++ = '\\'; + *v++ = *u++; + } + } else { if (shownull) { /* We can't show an empty string with just backslash quoting. */ if (!*u) { diff --git a/Src/zsh.h b/Src/zsh.h index bb52e106d..b2ab1dfae 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -215,6 +215,10 @@ struct mathfunc { #define SPECCHARS "#$^*()=|{}[]`<>?~;&\n\t \\\'\"" +/* chars that need to be quoted for pattern matching */ + +#define PATCHARS "#^*()|[]<>?~" + /* * Types of quote. This is used in various places, so care needs * to be taken when changing them. (Oooh, don't you look surprised.) @@ -248,6 +252,12 @@ enum { * This is only useful as an argument to quotestring(). */ QT_SINGLE_OPTIONAL, + /* + * Only quote pattern characters. + * ${(b)foo} guarantees that ${~foo} matches the string + * contained in foo. + */ + QT_BACKSLASH_PATTERN, /* * As QT_BACKSLASH, but a NULL string is shown as ''. */ diff --git a/Src/ztype.h b/Src/ztype.h index b73e3f840..76589b152 100644 --- a/Src/ztype.h +++ b/Src/ztype.h @@ -42,6 +42,7 @@ #define IMETA (1 << 12) #define IWSEP (1 << 13) #define INULL (1 << 14) +#define IPATTERN (1 << 15) #define zistype(X,Y) (typtab[STOUC(X)] & Y) #define idigit(X) zistype(X,IDIGIT) #define ialnum(X) zistype(X,IALNUM) @@ -58,6 +59,7 @@ #define imeta(X) zistype(X,IMETA) #define iwsep(X) zistype(X,IWSEP) #define inull(X) zistype(X,INULL) +#define ipattern(X) zistype(X,IPATTERN) /* * Bit flags for typtab_flags --- preserved after -- cgit 1.4.1