diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Src/glob.c | 40 | ||||
-rw-r--r-- | Src/lex.c | 2 | ||||
-rw-r--r-- | Src/pattern.c | 13 | ||||
-rw-r--r-- | Src/subst.c | 6 | ||||
-rw-r--r-- | Src/zsh.h | 29 | ||||
-rw-r--r-- | Test/D04parameter.ztst | 14 | ||||
-rwxr-xr-x | Test/ztst.zsh | 2 |
8 files changed, 92 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog index b082f2c0f..3806ac2cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-10-11 Peter Stephenson <pws@csr.com> + + * 21862/21863: Src/glob.c, Src/lex.c, Src/pattern.c, Src/subst.c, + Src/zsh.h, Test/D04parameter.ztst, Test/ztst.zsh: Ensure that + backslashes in parameters substituted by GLOB_SUBST are not + swallowed up if there is no pattern match. + 2005-10-07 Peter Stephenson <pws@csr.com> * Stephen RĂ¼ger: 21846: Completion/Unix/Command/_chmod: too 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 */ diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 3ad19368d..6abba0ab3 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -196,6 +196,20 @@ >* boringfile evenmoreboringfile boringfile evenmoreboringfile >boringfile evenmoreboringfile +# The following tests a bug where globsubst didn't preserve +# backslashes when printing out the original string. + str1='\\*\\' + ( + setopt globsubst nonomatch + [[ \\\\ = $str1 ]] && print -r '\\ matched by' $str1 + [[ \\foo\\ = $str1 ]] && print -r '\\foo matched by' $str1 + [[ a\\b\\ = $str1 ]] || print -r 'a\\b not matched by' $str1 + ) +0:globsubst with backslashes +>\\ matched by \\*\\ +>\\foo matched by \\*\\ +>a\\b not matched by \\*\\ + print -l "${$(print one word)}" "${=$(print two words)}" 0:splitting of $(...) inside ${...} >one word diff --git a/Test/ztst.zsh b/Test/ztst.zsh index 0f0c704c7..c0fbc179f 100755 --- a/Test/ztst.zsh +++ b/Test/ztst.zsh @@ -280,7 +280,7 @@ ZTST_diff() { diff_out=$(diff "$@") diff_ret="$?" if [[ "$diff_ret" != "0" ]]; then - echo "$diff_out" + print -r "$diff_out" fi return "$diff_ret" |