From cca66ab341ffa330908aa6ea8da03e991aa6903c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 11 Oct 2005 16:48:05 +0000 Subject: 21862/21863: GLOB_SUBST shouldn't swallow up backslashes in parameter substitutions that don't match anything. --- Src/glob.c | 40 +++++++++++++++++++++++++++++++--------- Src/lex.c | 2 +- Src/pattern.c | 13 ++++++++++--- Src/subst.c | 6 +++--- Src/zsh.h | 29 +++++++++++++++++++++++++---- 5 files changed, 70 insertions(+), 20 deletions(-) (limited to 'Src') diff --git a/Src/glob.c b/Src/glob.c index 93d5e3312..be2dcd5ec 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2487,19 +2487,29 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr) mod_export void tokenize(char *s) { - zshtokenize(s, 0); + zshtokenize(s, 0, 0); } +/* + * shtokenize is used when we tokenize a string with GLOB_SUBST set. + * In that case we need to retain backslashes when we turn the + * pattern back into a string, so that the string is not + * modified if it failed to match a pattern. + * + * It may be modified by the effect of SH_GLOB which turns off + * various zsh-specific options. + */ + /**/ mod_export void shtokenize(char *s) { - zshtokenize(s, isset(SHGLOB)); + zshtokenize(s, 1, isset(SHGLOB)); } /**/ static void -zshtokenize(char *s, int shglob) +zshtokenize(char *s, int glbsbst, int shglob) { char *t; int bslash = 0; @@ -2508,9 +2518,10 @@ zshtokenize(char *s, int shglob) cont: switch (*s) { case Bnull: + case Bnullkeep: case '\\': if (bslash) { - s[-1] = Bnull; + s[-1] = glbsbst ? Bnullkeep : Bnull; break; } bslash = 1; @@ -2519,7 +2530,7 @@ zshtokenize(char *s, int shglob) if (shglob) break; if (bslash) { - s[-1] = Bnull; + s[-1] = glbsbst ? Bnullkeep : Bnull; break; } t = s; @@ -2549,7 +2560,7 @@ zshtokenize(char *s, int shglob) for (t = ztokens; *t; t++) if (*t == *s) { if (bslash) - s[-1] = Bnull; + s[-1] = glbsbst ? Bnullkeep : Bnull; else *s = (t - ztokens) + Pound; break; @@ -2569,12 +2580,23 @@ remnulargs(char *s) char *o = s, c; while ((c = *s++)) - if (INULL(c)) { + if (c == Bnullkeep) { + /* + * An active backslash that needs to be turned back into + * a real backslash for output. However, we don't + * do that yet since we need to ignore it during + * pattern matching. + */ + continue; + } else if (INULL(c)) { char *t = s - 1; - while ((c = *s++)) - if (!INULL(c)) + while ((c = *s++)) { + if (c == Bnullkeep) + *t++ = '\\'; + else if (!INULL(c)) *t++ = c; + } *t = '\0'; if (!*o) { o[0] = Nularg; diff --git a/Src/lex.c b/Src/lex.c index bf2adb1dc..3ab099daf 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -33,7 +33,7 @@ /* tokens */ /**/ -mod_export char ztokens[] = "#$^*()$=|{}[]`<>?~`,'\"\\"; +mod_export char ztokens[] = "#$^*()$=|{}[]`<>?~`,'\"\\\\"; /* parts of the current token */ diff --git a/Src/pattern.c b/Src/pattern.c index 36578226c..aa95a46bd 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -260,13 +260,13 @@ static char endseg[] = { static char endstr[] = { '/', /* file only */ - '\0', Bar, Outpar, Quest, Star, Inbrack, Inpar, Inang, + '\0', Bar, Outpar, Quest, Star, Inbrack, Inpar, Inang, Bnullkeep, /* all patterns */ Tilde, Hat, Pound /* extended glob only */ }; -#define PATENDSTRLEN_NORM 9 -#define PATENDSTRLEN_EXT 12 +#define PATENDSTRLEN_NORM 10 +#define PATENDSTRLEN_EXT 13 /* Default size for pattern buffer */ @@ -1240,6 +1240,13 @@ patcomppiece(int *flagp) */ return 0; break; + case Bnullkeep: + /* + * Marker for restoring a backslash in output: + * does not match a character. + */ + return patcomppiece(flagp); + break; #ifdef DEBUG default: dputs("BUG: character not handled in patcomppiece"); diff --git a/Src/subst.c b/Src/subst.c index defb53bd9..67de61418 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1945,7 +1945,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) */ for (ptr = s; (c = *ptr) && c != '/'; ptr++) { - if ((c == Bnull || c == '\\') && ptr[1]) + if ((c == Bnull || c == Bnullkeep || c == '\\') && ptr[1]) { if (ptr[1] == '/') chuck(ptr); @@ -2846,11 +2846,11 @@ modify(char **str, char **ptr) } zsfree(hsubr); for (tt = hsubl; *tt; tt++) - if (INULL(*tt)) + if (INULL(*tt) && *tt != Bnullkeep) chuck(tt--); untokenize(hsubl); for (tt = hsubr = ztrdup(ptr2); *tt; tt++) - if (INULL(*tt)) + if (INULL(*tt) && *tt != Bnullkeep) chuck(tt--); ptr2[-1] = del; if (sav) diff --git a/Src/zsh.h b/Src/zsh.h index b10f0bea2..19cfe216d 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -120,7 +120,10 @@ struct mathfunc { #define DEFAULT_IFS " \t\n\203 " -/* Character tokens */ +/* + * Character tokens. + * These should match the characters in ztokens, defined in lex.c + */ #define Pound ((char) 0x84) #define String ((char) 0x85) #define Hat ((char) 0x86) @@ -141,15 +144,33 @@ struct mathfunc { #define Tilde ((char) 0x95) #define Qtick ((char) 0x96) #define Comma ((char) 0x97) +/* + * Null arguments: placeholders for single and double quotes + * and backslashes. + */ #define Snull ((char) 0x98) #define Dnull ((char) 0x99) #define Bnull ((char) 0x9a) -#define Nularg ((char) 0x9b) +/* + * Backslash which will be returned to "\" instead of being stripped + * when we turn the string into a printable format. + */ +#define Bnullkeep ((char) 0x9b) +/* + * Null argument that does not correspond to any character. + * This should be last as it does not appear in ztokens and + * is used to initialise the IMETA type in inittyptab(). + */ +#define Nularg ((char) 0x9c) -#define INULL(x) (((x) & 0xfc) == 0x98) +#define INULL(x) (((x) & 0xf8) == 0x98) +/* + * Take care to update the use of IMETA appropriately when adding + * tokens here. + */ /* Marker used in paramsubst for rc_expand_param */ -#define Marker ((char) 0x9c) +#define Marker ((char) 0xa0) /* chars that need to be quoted if meant literally */ -- cgit 1.4.1