diff options
author | Bart Schaefer <schaefer@zsh.org> | 2023-11-15 20:16:04 -0800 |
---|---|---|
committer | Bart Schaefer <schaefer@zsh.org> | 2023-11-15 20:16:04 -0800 |
commit | e6ad117ccb548c8411610571c92fa4094f275460 (patch) | |
tree | 81ea94a83fd4d1dfdc20d19da322ccd767eaf709 | |
parent | be223aedee772fc31e12ec8c5277f50aae25b0fe (diff) | |
download | zsh-e6ad117ccb548c8411610571c92fa4094f275460.tar.gz zsh-e6ad117ccb548c8411610571c92fa4094f275460.tar.xz zsh-e6ad117ccb548c8411610571c92fa4094f275460.zip |
52202: improve handling of quoting in ${var/pattern/replacement}
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Src/lex.c | 53 | ||||
-rw-r--r-- | Src/subst.c | 7 | ||||
-rw-r--r-- | Test/D04parameter.ztst | 8 |
4 files changed, 49 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog index 4f5c6b024..6baa171dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2023-11-15 Bart Schaefer <schaefer@zsh.org> + + * 52202: Src/lex.c, Src/subst.c, Test/D04parameter.ztst: improve + handling of quoting in ${var/pattern/replacement}. Still not + perfect, e.g., deeply nested expansions in the pattern may fail. + 2023-11-14 Oliver Kiddle <opk@zsh.org> * github #106: Matt Koscica: Completion/Unix/Command/_tmux, diff --git a/Src/lex.c b/Src/lex.c index 33b17cc95..31b130b07 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -938,7 +938,7 @@ gettokstr(int c, int sub) { int bct = 0, pct = 0, brct = 0, seen_brct = 0, fdpar = 0; int intpos = 1, in_brace_param = 0, cmdsubst = 0; - int inquote, unmatched = 0; + int inquote, unmatched = 0, in_pattern = 0; enum lextok peek; #ifdef DEBUG int ocmdsp = cmdsp; @@ -1160,7 +1160,7 @@ gettokstr(int c, int sub) if (bct-- == in_brace_param) { if (cmdsubst) cmdpop(); - in_brace_param = cmdsubst = 0; + in_brace_param = cmdsubst = in_pattern = 0; } c = Outbrace; break; @@ -1309,7 +1309,8 @@ gettokstr(int c, int sub) lexbuf.ptr--, lexbuf.len--; else break; - } + } else if (in_pattern && c == '/') + add(Bnull); add(c); } ALLOWHIST @@ -1397,26 +1398,36 @@ gettokstr(int c, int sub) */ c = Dash; break; - case LX2_BANG: - /* - * Same logic as Dash, for ! to perform negation in range. - */ - if (seen_brct) - c = Bang; - else - c = '!'; - } - add(c); - c = hgetc(); - if (intpos) + case LX2_BANG: + /* + * Same logic as Dash, for ! to perform negation in range. + */ + if (seen_brct) + c = Bang; + else + c = '!'; + case LX2_OTHER: + if (in_brace_param) { + if (c == '/') { + if (in_pattern == 0) + in_pattern = 2; + else + --in_pattern; + } + } + } + add(c); + c = hgetc(); + if (intpos) intpos--; - if (lexstop) + if (lexstop) break; - if (!cmdsubst && in_brace_param && act == LX2_STRING && - (c == '|' || c == Bar || inblank(c))) { - cmdsubst = in_brace_param; - cmdpush(CS_CURSH); - } + if (!cmdsubst && in_brace_param && act == LX2_STRING && + (c == '|' || c == Bar || inblank(c))) { + cmdsubst = in_brace_param; + cmdpush(CS_CURSH); + } else if (in_pattern == 2 && c != '/') + in_pattern = 1; } brk: if (errflag) { diff --git a/Src/subst.c b/Src/subst.c index 60d850feb..4ef1d1269 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -3088,6 +3088,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, chuck(ptr); else ptr++; + } else if (c == Dnull) { + chuck(ptr); + while (*ptr && *ptr != c) + ptr++; + if (*ptr == Dnull) + chuck(ptr); + ptr--; /* Outer loop is about to increment */ } } replstr = (*ptr && ptr[1]) ? ptr+1 : ""; diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index c2008582c..69a4fd3ec 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -2762,13 +2762,13 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888 slash='/' print -r -- x${slash/'/'}y --Df:(users/28784) substituting a single-quoted backslash, part #1: slash +0:(users/28784) substituting a single-quoted backslash, part #1: slash >xy single_quote="'" - print -r -- x${single_quote/'/'}y --Df:(users/28784) substituting a single-quoted backslash, part #2: single quote ->x/y + print -r -- x${single_quote/$'/'}y +0:(users/28784) substituting a single-quoted backslash, part #2: single quote +>x'y control="foobar" print -r -- x${control/'bar'}y |