From cfd34c75ac10e05a9573f6b26d3cb2d08b269f6a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 9 Aug 2017 19:57:47 +0100 Subject: 41504: make empty strings work in case patterns with no leading parenthesis --- ChangeLog | 6 ++++++ Src/lex.c | 6 +++--- Src/parse.c | 48 ++++++++++++++++++++++++++++++++++++++---------- Test/A01grammar.ztst | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 784a2b523..4e8ae5834 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2017-08-09 Peter Stephenson + + * 41504: Src/lex.c, Src/parse.c, Test/A01grammar.ztst: make + empty strings work in case patterns with no opening + parenthesis. + 2017-08-08 Peter Stephenson * unposted: Config/version.mk: update to 5.4.1-dev-0. diff --git a/Src/lex.c b/Src/lex.c index b2d9b3f42..8493d4737 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -760,7 +760,7 @@ gettok(void) return AMPER; case LX1_BAR: d = hgetc(); - if (d == '|') + if (d == '|' && !incasepat) return DBAR; else if (d == '&') return BARAMP; @@ -1058,7 +1058,7 @@ gettokstr(int c, int sub) if (isset(SHGLOB)) { if (sub || in_brace_param) break; - if (incasepat && !lexbuf.len) + if (incasepat > 0 && !lexbuf.len) return INPAR; if (!isset(KSHGLOB) && lexbuf.len) goto brk; @@ -1859,7 +1859,7 @@ exalias(void) Reswd rw; hwend(); - if (interact && isset(SHINSTDIN) && !strin && !incasepat && + if (interact && isset(SHINSTDIN) && !strin && incasepat <= 0 && tok == STRING && !nocorrect && !(inbufflags & INP_ALIAS) && (isset(CORRECTALL) || (isset(CORRECT) && incmdpos))) spckword(&tokstr, 1, incmdpos, 1); diff --git a/Src/parse.c b/Src/parse.c index ba9cd61eb..27052527d 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -48,7 +48,11 @@ mod_export int incond; /**/ mod_export int inredir; -/* != 0 if we are about to read a case pattern */ +/* + * 1 if we are about to read a case pattern + * -1 if we are not quite sure + * 0 otherwise + */ /**/ int incasepat; @@ -1194,6 +1198,7 @@ par_case(int *cmplx) for (;;) { char *str; + int skip_zshlex; while (tok == SEPER) zshlex(); @@ -1201,11 +1206,17 @@ par_case(int *cmplx) break; if (tok == INPAR) zshlex(); - if (tok != STRING) - YYERRORV(oecused); - if (!strcmp(tokstr, "esac")) - break; - str = dupstring(tokstr); + if (tok == BAR) { + str = dupstring(""); + skip_zshlex = 1; + } else { + if (tok != STRING) + YYERRORV(oecused); + if (!strcmp(tokstr, "esac")) + break; + str = dupstring(tokstr); + skip_zshlex = 0; + } type = WC_CASE_OR; pp = ecadd(0); palts = ecadd(0); @@ -1243,10 +1254,11 @@ par_case(int *cmplx) * this doesn't affect our ability to match a | or ) as * these are valid on command lines. */ - incasepat = 0; + incasepat = -1; incmdpos = 1; - for (;;) { + if (!skip_zshlex) zshlex(); + for (;;) { if (tok == OUTPAR) { ecstr(str); ecadd(ecnpats++); @@ -1302,10 +1314,26 @@ par_case(int *cmplx) } zshlex(); - if (tok != STRING) + switch (tok) { + case STRING: + /* Normal case */ + str = dupstring(tokstr); + zshlex(); + break; + + case OUTPAR: + case BAR: + /* Empty string */ + str = dupstring(""); + break; + + default: + /* Oops. */ YYERRORV(oecused); - str = dupstring(tokstr); + break; + } } + incasepat = 0; par_save_list(cmplx); if (tok == SEMIAMP) type = WC_CASE_AND; diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst index 9625a15bc..0302c9624 100644 --- a/Test/A01grammar.ztst +++ b/Test/A01grammar.ztst @@ -820,6 +820,43 @@ 0:case keeps exit status of last command executed in compound-list >37 + case '' in + burble) print No. + ;; + spurble|) print Yes! + ;; + |burble) print Not quite. + ;; + esac + case '' in + burble) print No. + ;; + |burble) print Wow! + ;; + spurble|) print Sorry. + ;; + esac + case '' in + gurgle) print No. + ;; + wurgle||jurgle) print Yikes! + ;; + durgle|) print Hmm. + ;; + |zurgle) print Hah. + ;; + esac + case '' in + # Useless doubled empty string to check special case. + ||jurgle) print Ok. + ;; + esac +0: case with no opening parentheses and empty string +>Yes! +>Wow! +>Yikes! +>Ok. + x=1 x=2 | echo $x echo $x -- cgit 1.4.1