From abeb5eaf19728543897153b6122fa59e85bfadc5 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Fri, 23 Aug 2024 04:26:44 +0100 Subject: [PATCH] Fix certain syntax errors not being recorded in history For the following types of syntax error, the command line is not recorded in the shell history for retrieval and correction: $ a[]=12 -ksh: syntax error at line 1: `[]' empty subscript $ function foo $bad { :; } -ksh: syntax error at line 1: invalid reference list $ echo $(( 1 << 8 ) ) -ksh: syntax error at line 1: `<<8' here-document not contained within command substitution Up-arrow will not work to get the above command lines back. It's also odd that these report a line number (1) though we're working on the interactive command line and other syntax errors do not report a line number, e.g.: $ ) -ksh: syntax error: `)' unexpected Analysis: Syntax errors are normally thrown via a call to sh_syntax(), which does the I/O stream flushing and closing necessary to ensure that the command line gets added to the history before calling errormsg(). But the above three problematic errors call errormsg() directly. The fix is to refactor sh_syntax() to handle these errors properly and call sh_syntax() when these occur. src/cmd/ksh93/sh/lex.c, src/cmd/ksh93/sh/parse.c: - Add 'special' argument to sh_syntax() to handle the three cases above. A value of zero is a regular syntax error and 1-3 are the special messages above. - Construct the error message in parts using the sh.strbuf Sfio string buffer. This fixes the cosmetic 'at line 1' problem on interactive shells. src/cmd/ksh93/data/{keywords,lexstates}.c, src/cmd/ksh93/include/{shlex,lexstates}.h: - Refactor and rename the syntax error-related messages to make the above changes possible. - Group them all together in lexstates.{c,h} for clarity. Resolves: https://github.com/ksh93/ksh/issues/775 --- NEWS | 5 ++ src/cmd/ksh93/data/keywords.c | 8 +-- src/cmd/ksh93/data/lexstates.c | 20 ++++--- src/cmd/ksh93/include/lexstates.h | 16 ++++-- src/cmd/ksh93/include/shlex.h | 7 +-- src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh/lex.c | 68 ++++++++++++------------ src/cmd/ksh93/sh/parse.c | 86 ++++++++++++++----------------- 8 files changed, 108 insertions(+), 104 deletions(-) diff --git a/NEWS b/NEWS index 3ad23f527b21..1c398a10e135 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ This documents significant changes in the 1.0 branch of ksh 93u+m. For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0 Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library. +2024-08-22: + +- Fixed: command lines containing certain specific kinds of syntax error + were not entered into the shell's history for retrieval and correction. + 2024-08-21: - Fixed a corner-case crashing bug in shell discipline functions. diff --git a/src/cmd/ksh93/data/keywords.c b/src/cmd/ksh93/data/keywords.c index 8843a9b9f90a..b39dba368375 100644 --- a/src/cmd/ksh93/data/keywords.c +++ b/src/cmd/ksh93/data/keywords.c @@ -2,7 +2,7 @@ * * * This software is part of the ast package * * Copyright (c) 1982-2012 AT&T Intellectual Property * -* Copyright (c) 2020-2023 Contributors to ksh 93u+m * +* Copyright (c) 2020-2024 Contributors to ksh 93u+m * * and is licensed under the * * Eclipse Public License, Version 2.0 * * * @@ -51,9 +51,3 @@ const Shtable_t shtab_reserved[] = "}", RBRACE, "", 0, }; - -const char e_unexpected[] = "unexpected"; -const char e_unmatched[] = "unmatched"; -const char e_endoffile[] = "end of file"; -const char e_newline[] = "newline"; - diff --git a/src/cmd/ksh93/data/lexstates.c b/src/cmd/ksh93/data/lexstates.c index 4c0c2acf8191..132867ccb0c9 100644 --- a/src/cmd/ksh93/data/lexstates.c +++ b/src/cmd/ksh93/data/lexstates.c @@ -2,7 +2,7 @@ * * * This software is part of the ast package * * Copyright (c) 1982-2011 AT&T Intellectual Property * -* Copyright (c) 2020-2023 Contributors to ksh 93u+m * +* Copyright (c) 2020-2024 Contributors to ksh 93u+m * * and is licensed under the * * Eclipse Public License, Version 2.0 * * * @@ -729,11 +729,19 @@ const char *sh_lexrstates[ST_NONE] = const char e_lexversion[] = "%d: invalid binary script version"; const char e_lexspace[] = "line %d: use space or tab to separate operators %c and %c"; const char e_lexslash[] = "line %d: $ not preceded by \\"; -const char e_lexsyntax1[] = "syntax error at line %d: `%s' %s"; -const char e_lexsyntax2[] = "syntax error: `%s' %s"; -const char e_lexsyntax3[] = "syntax error at line %d: duplicate label %s"; -const char e_lexsyntax4[] = "syntax error at line %d: invalid reference list"; -const char e_lexsyntax5[] = "syntax error at line %d: `<<%s' here-document not contained within command substitution"; + +/* syntax error messages */ +const char e_syntaxerror[] = "syntax error: "; +const char e_syntaxerror_at[] = "syntax error at line %d: "; +const char e_unexpected[] = "`%s' unexpected"; +const char e_unmatched[] = "`%s' unmatched"; +const char e_emptysubscr[] = "[]: empty subscript"; +const char e_badreflist[] = "invalid reference list"; +const char e_heredoccomsub[] = "`<<%s' here-document not contained within command substitution"; +const char e_endoffile[] = "end of file"; +const char e_newline[] = "newline"; + +/* noexec linter warning messages */ const char e_lexwarnvar[] = "line %d: in '((%s))', using '$' as in '$%.*s' is slower and can introduce rounding errors"; const char e_lexarithwarn[] = "line %d: %s is slower than ((%.*s%s"; const char e_lexobsolete1[] = "line %d: `...` obsolete, use $(...)"; diff --git a/src/cmd/ksh93/include/lexstates.h b/src/cmd/ksh93/include/lexstates.h index a4cb0ce9b55c..225dc9449c45 100644 --- a/src/cmd/ksh93/include/lexstates.h +++ b/src/cmd/ksh93/include/lexstates.h @@ -129,11 +129,17 @@ extern const char *sh_lexrstates[ST_NONE]; extern const char e_lexversion[]; extern const char e_lexspace[]; extern const char e_lexslash[]; -extern const char e_lexsyntax1[]; -extern const char e_lexsyntax2[]; -extern const char e_lexsyntax3[]; -extern const char e_lexsyntax4[]; -extern const char e_lexsyntax5[]; + +extern const char e_syntaxerror[]; +extern const char e_syntaxerror_at[]; +extern const char e_unexpected[]; +extern const char e_unmatched[]; +extern const char e_emptysubscr[]; +extern const char e_badreflist[]; +extern const char e_heredoccomsub[]; +extern const char e_endoffile[]; +extern const char e_newline[]; + extern const char e_lexwarnvar[]; extern const char e_lexarithwarn[]; extern const char e_lexobsolete1[]; diff --git a/src/cmd/ksh93/include/shlex.h b/src/cmd/ksh93/include/shlex.h index 5312275eb9cb..2a46d0de1f9f 100644 --- a/src/cmd/ksh93/include/shlex.h +++ b/src/cmd/ksh93/include/shlex.h @@ -168,11 +168,6 @@ typedef struct _shlex_ #define SH_COMPASSIGN 010 /* allow compound assignments only */ -extern const char e_unexpected[]; -extern const char e_unmatched[]; -extern const char e_endoffile[]; -extern const char e_newline[]; - /* odd chars */ #define LBRACE '{' #define RBRACE '}' @@ -185,7 +180,7 @@ extern int sh_lex(Lex_t*); extern Shnode_t *sh_dolparen(Lex_t*); extern Lex_t *sh_lexopen(Lex_t*, int); extern void sh_lexskip(Lex_t*,int,int,int); -extern noreturn void sh_syntax(Lex_t*); +extern noreturn void sh_syntax(Lex_t*, int); #if SHOPT_KIA extern int kiaclose(Lex_t *); extern unsigned long kiaentity(Lex_t*, const char*,int,int,int,int,unsigned long,int,int,const char*); diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 8006f4a733bb..468e12b057a0 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -18,7 +18,7 @@ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_SVER "1.0.11-beta" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2024-08-21" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2024-08-22" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2024 Contributors to ksh " SH_RELEASE_FORK /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c index 354bc20213c5..8e2bd3077c86 100644 --- a/src/cmd/ksh93/sh/lex.c +++ b/src/cmd/ksh93/sh/lex.c @@ -340,7 +340,7 @@ int sh_lex(Lex_t* lp) else { lp->token = -1; - sh_syntax(lp); + sh_syntax(lp,0); } } /* end-of-file */ @@ -374,7 +374,7 @@ int sh_lex(Lex_t* lp) } lp->lasttok = c; lp->token = EOFSYM; - sh_syntax(lp); + sh_syntax(lp,0); } goto breakloop; case S_COM: @@ -414,7 +414,7 @@ int sh_lex(Lex_t* lp) lp->lasttok = IODOCSYM; lp->token = EOFSYM; lp->lastline = c; - sh_syntax(lp); + sh_syntax(lp,0); } if(!lp->lexd.dolparen) lp->lexd.nocopy--; @@ -501,7 +501,7 @@ int sh_lex(Lex_t* lp) { /* throw "`(' unmatched" error */ lp->lasttok = LPAREN; lp->token = EOFSYM; - sh_syntax(lp); + sh_syntax(lp,0); } return r; } @@ -547,7 +547,7 @@ int sh_lex(Lex_t* lp) { lp->token = c = IORDWRSYMT; if(lp->inexec) - sh_syntax(lp); + sh_syntax(lp,0); } else if(n>0) fcseek(-LEN); @@ -561,7 +561,7 @@ int sh_lex(Lex_t* lp) if(lp->inexec) { lp->token = c; - sh_syntax(lp); + sh_syntax(lp,0); } } else @@ -972,7 +972,7 @@ int sh_lex(Lex_t* lp) if(c!='%') { lp->token = n; - sh_syntax(lp); + sh_syntax(lp,0); } else if(lp->lexd.warn) errormsg(SH_DICT,ERROR_warn(0),e_lexquote,sh.inlineno,'%'); @@ -1005,7 +1005,7 @@ int sh_lex(Lex_t* lp) if(n!='$') { lp->token = c; - sh_syntax(lp); + sh_syntax(lp,0); } else { @@ -1110,7 +1110,7 @@ int sh_lex(Lex_t* lp) if(c!=n && lp->lex.incasetoken = c; - sh_syntax(lp); + sh_syntax(lp,0); } if(c==RBRACE && (mode==ST_NAME||mode==ST_NORM)) goto epat; @@ -1148,10 +1148,7 @@ int sh_lex(Lex_t* lp) if(n>0 && n==']') { if(mode==ST_NAME) - { - errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1, sh.inlineno, "[]", "empty subscript"); - UNREACHABLE(); - } + sh_syntax(lp,1); if(!epatchar || epatchar=='%') continue; } @@ -1655,7 +1652,7 @@ static int comsub(Lex_t *lp, int endtok) case EOFSYM: lp->lastline = line; lp->lasttok = endtok; - sh_syntax(lp); + sh_syntax(lp,0); /* UNREACHABLE */ case IOSEEKSYM: if(fcgetc(c)!='#' && c>0) @@ -1692,11 +1689,8 @@ static int comsub(Lex_t *lp, int endtok) lp->lex = save; lp->assignok = (endchar(lp)==RBRACT?assignok:0); if(lp->heredoc && !inheredoc) - { /* here-document isn't fully contained in command substitution */ - errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax5,sh.inlineno,lp->heredoc->ioname); - UNREACHABLE(); - } + sh_syntax(lp,3); return messages; } @@ -2110,20 +2104,10 @@ static char *fmttoken(Lex_t *lp, int sym) /* * print a bad syntax message */ -noreturn void sh_syntax(Lex_t *lp) +noreturn void sh_syntax(Lex_t *lp, int special) { - const char *cp = sh_translate(e_unexpected); - char *tokstr; - int tok = lp->token; + const int eof = lp->token==EOFSYM && lp->lasttok; Sfio_t *sp; - if((tok==EOFSYM) && lp->lasttok) - { - tok = lp->lasttok; - cp = sh_translate(e_unmatched); - } - else - lp->lastline = sh.inlineno; - tokstr = fmttoken(lp,tok); if((sp=fcfile()) || (sh.infd>=0 && (sp=sh.sftable[sh.infd]))) { /* clear out any pending input */ @@ -2139,10 +2123,28 @@ noreturn void sh_syntax(Lex_t *lp) sh.st.firstline = lp->firstline; /* reset lexer state */ sh_lexopen(lp, 0); - if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE)) - errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,lp->lastline,tokstr,cp); + /* construct error message */ + if (sh_isstate(SH_INTERACTIVE) || sh_isstate(SH_PROFILE)) + sfprintf(sh.strbuf, sh_translate(e_syntaxerror)); + else + sfprintf(sh.strbuf, sh_translate(e_syntaxerror_at), eof ? sh.inlineno : lp->lastline); + if (special==1) + sfprintf(sh.strbuf, sh_translate(e_emptysubscr)); + else if (special==2) + sfprintf(sh.strbuf, sh_translate(e_badreflist)); + else if (special==3) + sfprintf(sh.strbuf, sh_translate(e_heredoccomsub), lp->heredoc->ioname); else - errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp); + { + const char *msg; + int tok; + if (eof) + tok = lp->lasttok, msg = sh_translate(e_unmatched); + else + tok = lp->token, msg = sh_translate(e_unexpected); + sfprintf(sh.strbuf, msg, fmttoken(lp, tok)); + } + errormsg(SH_DICT, ERROR_exit(SYNBAD), "%s", sfstruse(sh.strbuf)); UNREACHABLE(); } diff --git a/src/cmd/ksh93/sh/parse.c b/src/cmd/ksh93/sh/parse.c index 32ebc22e63ff..a4b9faa10b0a 100644 --- a/src/cmd/ksh93/sh/parse.c +++ b/src/cmd/ksh93/sh/parse.c @@ -372,7 +372,7 @@ static Shnode_t *makelist(Lex_t *lexp, int type, Shnode_t *l, Shnode_t *r) { Shnode_t *t = NULL; if(!l || !r) - sh_syntax(lexp); + sh_syntax(lexp,0); else { if((type&COMMSK) == TTST) @@ -579,7 +579,7 @@ static Shnode_t *sh_cmd(Lex_t *lexp, int sym, int flag) lexp->token=';'; } else if(!left && !(flag&SH_EMPTY)) - sh_syntax(lexp); + sh_syntax(lexp,0); switch(lexp->token) { case COOPSYM: /* set up a cooperating process */ @@ -596,7 +596,7 @@ static Shnode_t *sh_cmd(Lex_t *lexp, int sym, int flag) /* FALLTHROUGH */ case ';': if(!left) - sh_syntax(lexp); + sh_syntax(lexp,0); if(right=sh_cmd(lexp,sym,flag|SH_EMPTY)) left=makelist(lexp,TLST, left, right); break; @@ -608,7 +608,7 @@ static Shnode_t *sh_cmd(Lex_t *lexp, int sym, int flag) if(sym && sym!=lexp->token) { if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM)) - sh_syntax(lexp); + sh_syntax(lexp,0); } } dcl_dehacktivate(); @@ -675,7 +675,7 @@ static Shnode_t *term(Lex_t *lexp,int flag) t->tre.tretyp |= showme; } else if(lexp->token) - sh_syntax(lexp); + sh_syntax(lexp,0); } return t; } @@ -697,7 +697,7 @@ static struct regnod* syncase(Lex_t *lexp,int esym) while(1) { if(!lexp->arg) - sh_syntax(lexp); + sh_syntax(lexp,0); lexp->arg->argnxt.ap=r->regptr; r->regptr = lexp->arg; if((tok=sh_lex(lexp))==RPAREN) @@ -705,7 +705,7 @@ static struct regnod* syncase(Lex_t *lexp,int esym) else if(tok=='|') sh_lex(lexp); else - sh_syntax(lexp); + sh_syntax(lexp,0); } r->regcom=sh_cmd(lexp,0,SH_NL|SH_EMPTY|SH_SEMI); if((tok=lexp->token)==BREAKCASESYM) @@ -718,7 +718,7 @@ static struct regnod* syncase(Lex_t *lexp,int esym) else { if(tok!=esym && tok!=EOFSYM) - sh_syntax(lexp); + sh_syntax(lexp,0); r->regnxt=0; } if(lexp->token==EOFSYM) @@ -784,7 +784,7 @@ static Shnode_t *arithfor(Lex_t *lexp,Shnode_t *tf) if(n<2) { lexp->token = RPAREN|SYMREP; - sh_syntax(lexp); + sh_syntax(lexp,0); } /* check whether the increment is present */ if(*argp->argval) @@ -800,7 +800,7 @@ static Shnode_t *arithfor(Lex_t *lexp,Shnode_t *tf) else if(n==';') n = sh_lex(lexp); if(n!=DOSYM && n!=LBRACE) - sh_syntax(lexp); + sh_syntax(lexp,0); tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI); tw->wh.whtyp = TWH; return tf; @@ -831,7 +831,7 @@ static Shnode_t *funct(Lex_t *lexp) if(!(flag = (lexp->token==FUNCTSYM))) t->funct.functtyp |= FPOSIX; else if(sh_lex(lexp)) - sh_syntax(lexp); + sh_syntax(lexp,0); if(!(iop=fcfile())) { iop = sfopen(NULL,fcseek(0),"s"); @@ -875,10 +875,7 @@ static Shnode_t *funct(Lex_t *lexp) int c=-1; t->funct.functargs = ac = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NULL); if(ac->comset || (ac->comtyp&COMSCAN)) - { - errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,sh.inlineno); - UNREACHABLE(); - } + sh_syntax(lexp,2); argv0 = argv = ac->comarg.dp->dolval + ARG_SPARE; while(cp= *argv++) { @@ -887,10 +884,7 @@ static Shnode_t *funct(Lex_t *lexp) while(c=mbchar(cp), isaname(c)); } if(c) - { - errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,sh.inlineno); - UNREACHABLE(); - } + sh_syntax(lexp,2); nargs = argv-argv0; size += sizeof(struct dolnod)+(nargs+ARG_SPARE)*sizeof(char*); if(sh.shcomp && strncmp(".sh.math.",t->funct.functnam,9)==0) @@ -905,7 +899,7 @@ static Shnode_t *funct(Lex_t *lexp) lexp->token = sh_lex(lexp); } if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM) - sh_syntax(lexp); + sh_syntax(lexp,0); sh_pushcontext(&buff,1); jmpval = sigsetjmp(buff.buff,0); if(jmpval == 0) @@ -1035,7 +1029,7 @@ static struct argnod *assign(Lex_t *lexp, struct argnod *ap, int type) lexp->assignlevel++; n = strlen(ap->argval)-1; if(ap->argval[n]!='=') - sh_syntax(lexp); + sh_syntax(lexp,0); if(ap->argval[n-1]=='+') { ap->argval[n--]=0; @@ -1108,7 +1102,7 @@ static struct argnod *assign(Lex_t *lexp, struct argnod *ap, int type) } } else if(n && n!=FUNCTSYM) - sh_syntax(lexp); + sh_syntax(lexp,0); else if(type!=NV_ARRAY && n!=FUNCTSYM && !(lexp->arg->argflag&ARG_ASSIGN) && @@ -1151,7 +1145,7 @@ static struct argnod *assign(Lex_t *lexp, struct argnod *ap, int type) array = 0; } else - sh_syntax(lexp); + sh_syntax(lexp,0); } } lexp->noreserv = 0; @@ -1169,7 +1163,7 @@ static struct argnod *assign(Lex_t *lexp, struct argnod *ap, int type) { if(array && n==LPAREN) goto comarray; - sh_syntax(lexp); + sh_syntax(lexp,0); } lexp->assignok = SH_ASSIGN; if((n=skipnl(lexp,0)) || array) @@ -1177,7 +1171,7 @@ static struct argnod *assign(Lex_t *lexp, struct argnod *ap, int type) if(n==RPAREN) break; if(array || n!=FUNCTSYM) - sh_syntax(lexp); + sh_syntax(lexp,0); } if((n!=FUNCTSYM) && !(lexp->arg->argflag&ARG_ASSIGN) && @@ -1186,13 +1180,13 @@ static struct argnod *assign(Lex_t *lexp, struct argnod *ap, int type) { struct argnod *arg = lexp->arg; if(n!=0) - sh_syntax(lexp); + sh_syntax(lexp,0); /* check for SysV style function */ if(sh_lex(lexp)!=LPAREN || sh_lex(lexp)!=RPAREN) { lexp->arg = arg; lexp->token = 0; - sh_syntax(lexp); + sh_syntax(lexp,0); } lexp->arg = arg; lexp->token = SYMRES; @@ -1254,19 +1248,19 @@ static Shnode_t *item(Lex_t *lexp,int flag) int saveline = lexp->lastline; t = getnode(swnod); if(sh_lex(lexp)) - sh_syntax(lexp); + sh_syntax(lexp,0); t->sw.swarg=lexp->arg; t->sw.swtyp=TSW; t->sw.swio = 0; t->sw.swtyp |= FLINENO; t->sw.swline = sh.inlineno; if((tok=skipnl(lexp,0))!=INSYM && tok!=LBRACE) - sh_syntax(lexp); + sh_syntax(lexp,0); if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM) { lexp->lasttok = savetok; lexp->lastline = saveline; - sh_syntax(lexp); + sh_syntax(lexp,0); } break; } @@ -1305,7 +1299,7 @@ static Shnode_t *item(Lex_t *lexp,int flag) if(sh_lex(lexp)) { if(lexp->token!=EXPRSYM || t->for_.fortyp!=TFOR) - sh_syntax(lexp); + sh_syntax(lexp,0); /* arithmetic for */ t = arithfor(lexp,t); break; @@ -1322,7 +1316,7 @@ static Shnode_t *item(Lex_t *lexp,int flag) if(sh_lex(lexp)) { if(lexp->token != NL && lexp->token !=';') - sh_syntax(lexp); + sh_syntax(lexp,0); /* some Linux scripts assume this */ if(sh_isoption(SH_NOEXEC)) errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,sh.inlineno-(lexp->token=='\n')); @@ -1331,14 +1325,14 @@ static Shnode_t *item(Lex_t *lexp,int flag) else t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NULL); if(lexp->token != NL && lexp->token !=';') - sh_syntax(lexp); + sh_syntax(lexp,0); tok = skipnl(lexp,0); } /* 'for i;do cmd' is valid syntax */ else if(tok==';') while((tok=sh_lex(lexp))==NL); if(tok!=DOSYM && tok!=LBRACE) - sh_syntax(lexp); + sh_syntax(lexp,0); t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI); break; } @@ -1354,11 +1348,11 @@ static Shnode_t *item(Lex_t *lexp,int flag) t->funct.functargs = 0; t->funct.functloc = 0; if(sh_lex(lexp)) - sh_syntax(lexp); + sh_syntax(lexp,0); t->funct.functnam=(char*) lexp->arg->argval; while((tok=sh_lex(lexp))==NL); if(tok!=LBRACE) - sh_syntax(lexp); + sh_syntax(lexp,0); t->funct.functtre = sh_cmd(lexp,RBRACE,SH_NL); break; #endif /* SHOPT_NAMESPACE */ @@ -1397,7 +1391,7 @@ static Shnode_t *item(Lex_t *lexp,int flag) if(!(flag&SH_SEMI)) return NULL; if(sh_lex(lexp)==';') - sh_syntax(lexp); + sh_syntax(lexp,0); showme = FSHOWME; } /* FALLTHROUGH */ @@ -1478,7 +1472,7 @@ static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io) break; } if(associative && (!(argp->argflag&ARG_ASSIGN) || argp->argval[0]!='[')) - sh_syntax(lexp); + sh_syntax(lexp,0); /* check for assignment argument */ if((argp->argflag&ARG_ASSIGN) && assignment!=2) { @@ -1535,7 +1529,7 @@ static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io) } } if((flag&NV_COMVAR) && !assignment) - sh_syntax(lexp); + sh_syntax(lexp,0); *argtail = argp; argtail = &(argp->argnxt.ap); if(!(lexp->assignok=key_on) && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC)) @@ -1675,7 +1669,7 @@ static int skipnl(Lex_t *lexp,int flag) int token; while((token=sh_lex(lexp))==NL); if(token==';' && !(flag&SH_SEMI)) - sh_syntax(lexp); + sh_syntax(lexp,0); return token; } @@ -1764,7 +1758,7 @@ static struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag) iof |= IOPROCSUB; } else - sh_syntax(lexp); + sh_syntax(lexp,0); } if( (iof&IOPROCSUB) && !(iof&IOLSEEK)) iop->ioname= (char*)lexp->arg->argchn.ap; @@ -1908,7 +1902,7 @@ static Shnode_t *test_expr(Lex_t *lp,int sym) { Shnode_t *t = test_or(lp); if(lp->token!=sym) - sh_syntax(lp); + sh_syntax(lp,0); return t; } @@ -1960,12 +1954,12 @@ static Shnode_t *test_primary(Lex_t *lexp) break; case '!': if(!(t = test_primary(lexp))) - sh_syntax(lexp); + sh_syntax(lexp,0); t->tre.tretyp ^= TNEGATE; /* xor it, so that a '!' negates another '!' */ return t; case TESTUNOP: if(sh_lex(lexp)) - sh_syntax(lexp); + sh_syntax(lexp,0); #if SHOPT_KIA if(lexp->kiafile && !strchr("sntzoOG",num)) { @@ -2003,7 +1997,7 @@ static Shnode_t *test_primary(Lex_t *lexp) return t; } else - sh_syntax(lexp); + sh_syntax(lexp,0); #if SHOPT_KIA if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT)) { @@ -2014,7 +2008,7 @@ static Shnode_t *test_primary(Lex_t *lexp) } #endif /* SHOPT_KIA */ if(sh_lex(lexp)) - sh_syntax(lexp); + sh_syntax(lexp,0); if(num&TEST_STRCMP) { /* If the argument is unquoted, enable pattern matching */