1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-01 05:16:05 +01:00

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

Doc tweak from Daniel in 35071.

Includes test.
This commit is contained in:
Peter Stephenson 2015-05-10 19:19:34 +01:00
parent bb2362e2c0
commit 6269db883a
7 changed files with 72 additions and 6 deletions

View file

@ -1,3 +1,10 @@
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> 2015-05-10 Mikael Magnusson <mikachu@gmail.com>
* 35065: Src/zsh.h: Don't treat NUL as a combining character * 35065: Src/zsh.h: Don't treat NUL as a combining character

View file

@ -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 protect special characters. Typically this form gives the most readable
output. 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))( item(tt(Q))(
Remove one level of quotes from the resulting words. Remove one level of quotes from the resulting words.
) )

View file

@ -1592,7 +1592,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
/* combination of (L), (U) and (C) flags. */ /* combination of (L), (U) and (C) flags. */
int casmod = CASMOD_NONE; 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. * or not (0). quotetype counts the q's for the first case.
* quoterr is simply (X) but gets passed around a lot because the * quoterr is simply (X) but gets passed around a lot because the
* combination (eX) needs it. * combination (eX) needs it.
@ -1861,6 +1861,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
quotemod++, quotetype++; quotemod++, quotetype++;
} }
break; break;
case 'b':
if (quotemod || quotetype != QT_NONE)
goto flagerr;
quotemod = 1;
quotetype = QT_BACKSLASH_PATTERN;
break;
case 'Q': case 'Q':
quotemod--; quotemod--;
break; break;
@ -3460,7 +3466,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
if (quotemod) { if (quotemod) {
int pre = 0, post = 0; int pre = 0, post = 0;
if (quotemod > 0 && quotetype > QT_BACKSLASH) { if (quotemod > 0) {
switch (quotetype) switch (quotetype)
{ {
case QT_DOLLARS: case QT_DOLLARS:
@ -3471,6 +3477,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
case QT_SINGLE_OPTIONAL: case QT_SINGLE_OPTIONAL:
/* quotes will be added for us */ /* quotes will be added for us */
case QT_BACKSLASH:
case QT_BACKSLASH_PATTERN:
/* no quotes */
break; break;
default: default:

View file

@ -3694,6 +3694,8 @@ inittyptab(void)
typtab[bangchar] |= ISPECIAL; typtab[bangchar] |= ISPECIAL;
} else } else
typtab_flags &= ~ZTF_BANGCHAR; typtab_flags &= ~ZTF_BANGCHAR;
for (s = PATCHARS; *s; s++)
typtab[STOUC(*s)] |= IPATTERN;
unqueue_signals(); unqueue_signals();
} }
@ -5075,6 +5077,10 @@ quotestring(const char *s, char **e, int instring)
alloclen = slen * 7 + 1; alloclen = slen * 7 + 1;
break; break;
case QT_BACKSLASH_PATTERN:
alloclen = slen * 2 + 1;
break;
case QT_SINGLE_OPTIONAL: case QT_SINGLE_OPTIONAL:
/* /*
* Here, we may need to add single quotes. * 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); quotestart = v = buf = zshcalloc(alloclen);
DPUTS(instring < QT_BACKSLASH || instring == QT_BACKTICK || DPUTS(instring < QT_BACKSLASH || instring == QT_BACKTICK ||
instring > QT_SINGLE_OPTIONAL, instring > QT_BACKSLASH_PATTERN,
"BUG: bad quote type in quotestring"); "BUG: bad quote type in quotestring");
u = s; u = s;
if (instring == QT_DOLLARS) { if (instring == QT_DOLLARS) {
@ -5134,9 +5140,18 @@ quotestring(const char *s, char **e, int instring)
u = uend; u = uend;
} }
} }
} } else if (instring == QT_BACKSLASH_PATTERN) {
else while (*u) {
{ if (e && !sf && *e == u) {
*e = v;
sf = 1;
}
if (ipattern(*u))
*v++ = '\\';
*v++ = *u++;
}
} else {
if (shownull) { if (shownull) {
/* We can't show an empty string with just backslash quoting. */ /* We can't show an empty string with just backslash quoting. */
if (!*u) { if (!*u) {

View file

@ -215,6 +215,10 @@ struct mathfunc {
#define SPECCHARS "#$^*()=|{}[]`<>?~;&\n\t \\\'\"" #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 * Types of quote. This is used in various places, so care needs
* to be taken when changing them. (Oooh, don't you look surprised.) * 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(). * This is only useful as an argument to quotestring().
*/ */
QT_SINGLE_OPTIONAL, 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 ''. * As QT_BACKSLASH, but a NULL string is shown as ''.
*/ */

View file

@ -42,6 +42,7 @@
#define IMETA (1 << 12) #define IMETA (1 << 12)
#define IWSEP (1 << 13) #define IWSEP (1 << 13)
#define INULL (1 << 14) #define INULL (1 << 14)
#define IPATTERN (1 << 15)
#define zistype(X,Y) (typtab[STOUC(X)] & Y) #define zistype(X,Y) (typtab[STOUC(X)] & Y)
#define idigit(X) zistype(X,IDIGIT) #define idigit(X) zistype(X,IDIGIT)
#define ialnum(X) zistype(X,IALNUM) #define ialnum(X) zistype(X,IALNUM)
@ -58,6 +59,7 @@
#define imeta(X) zistype(X,IMETA) #define imeta(X) zistype(X,IMETA)
#define iwsep(X) zistype(X,IWSEP) #define iwsep(X) zistype(X,IWSEP)
#define inull(X) zistype(X,INULL) #define inull(X) zistype(X,INULL)
#define ipattern(X) zistype(X,IPATTERN)
/* /*
* Bit flags for typtab_flags --- preserved after * Bit flags for typtab_flags --- preserved after

View file

@ -1699,3 +1699,7 @@
> >
> >
>Four >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