Commit 6269db88 authored by Peter Stephenson's avatar Peter Stephenson

35067: Add (b) parameter flag for pattern char backslashing.

Doc tweak from Daniel in 35071.

Includes test.
parent bb2362e2
2015-05-10 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 35067 (doc tweak from Daniel, 35071): Doc/Zsh/expn.yo,
Src/subst.c, Src/utils.c, Src/zsh.h, Src/ztype.h,
Test/D04parameter.ztst: add ${(b)foo} for backslash
quoting of patterns.
2015-05-10 Mikael Magnusson <mikachu@gmail.com>
* 35065: Src/zsh.h: Don't treat NUL as a combining character
......
......@@ -1014,6 +1014,25 @@ form of single quoting is used that only quotes the string if needed to
protect special characters. Typically this form gives the most readable
output.
)
item(tt(b))(
Quote with backslashes only characters that are special to pattern
matching. This is useful when the contents of the variable are to be
tested using tt(GLOB_SUBST), including the tt(${~)var(...)tt(}) switch.
Quoting using one of the tt(q) family of flags does not work
for this purpose since quotes are not stripped from non-pattern
characters by tt(GLOB_SUBST). In other words,
example(pattern=${(q)str}
[[ $str = ${~pattern} ]])
works if tt($str) is tt('a*b') but not if it is tt('a b'), whereas
example(pattern=${(b)str}
[[ $str = ${~pattern} ]])
is always true for any possible value of tt($str).
)
item(tt(Q))(
Remove one level of quotes from the resulting words.
)
......
......@@ -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:
......
......@@ -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) {
......
......@@ -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 ''.
*/
......
......@@ -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
......
......@@ -1699,3 +1699,7 @@
>
>
>Four
funnychars='The qu*nk br!wan f@x j/mps o[]r the la~# ^"&;'
[[ $funnychars = ${~${(b)funnychars}} ]]
0:${(b)...} quoting protects from GLOB_SUBST
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment