123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- This patch is a backport from dash of the combination of:
- [SHELL] Add preliminary LINENO support
- [VAR] Fix varinit ordering that broke fc
- [SHELL] Improve LINENO support
- Applies cleanly on top of:
- commit 9832bbaba966f0e52e183f10cd93fad7f8f643fe
- Date: Tue Aug 15 15:44:41 2017 +0200
- Testsuite needs some tweaks (line numbers in some messages change).
- Unfortunately, it is somewhat big:
- function old new delta
- parse_command 1581 1658 +77
- calcsize 203 272 +69
- copynode 195 257 +62
- lookupvar 59 108 +49
- evaltree 494 534 +40
- evalfor 152 187 +35
- evalcase 278 313 +35
- evalcommand 1547 1581 +34
- evalsubshell 169 199 +30
- linenovar - 22 +22
- raise_error_syntax 11 29 +18
- evalfun 266 280 +14
- varinit_data 96 108 +12
- cmdtxt 626 631 +5
- lineno - 4 +4
- funcline - 4 +4
- ash_vmsg 144 141 -3
- startlinno 4 - -4
- funcnest 4 - -4
- xxreadtoken 272 259 -13
- readtoken1 2635 2594 -41
- ------------------------------------------------------------------------------
- (add/remove: 3/2 grow/shrink: 13/3 up/down: 510/-65) Total: 445 bytes
- text data bss dec hex filename
- 912030 563 5844 918437 e03a5 busybox_old
- 912473 587 5844 918904 e0578 busybox_unstripped
- diff --git a/shell/ash.c b/shell/ash.c
- index 703802f..93a3814 100644
- --- a/shell/ash.c
- +++ b/shell/ash.c
- @@ -312,6 +312,8 @@ struct globals_misc {
- /* shell level: 0 for the main shell, 1 for its children, and so on */
- int shlvl;
- #define rootshell (!shlvl)
- + int errlinno;
- +
- char *minusc; /* argument to -c option */
-
- char *curdir; // = nullstr; /* current working directory */
- @@ -389,6 +391,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc;
- #define job_warning (G_misc.job_warning)
- #define rootpid (G_misc.rootpid )
- #define shlvl (G_misc.shlvl )
- +#define errlinno (G_misc.errlinno )
- #define minusc (G_misc.minusc )
- #define curdir (G_misc.curdir )
- #define physdir (G_misc.physdir )
- @@ -723,6 +726,7 @@ union node;
-
- struct ncmd {
- smallint type; /* Nxxxx */
- + int linno;
- union node *assign;
- union node *args;
- union node *redirect;
- @@ -736,6 +740,7 @@ struct npipe {
-
- struct nredir {
- smallint type;
- + int linno;
- union node *n;
- union node *redirect;
- };
- @@ -755,6 +760,7 @@ struct nif {
-
- struct nfor {
- smallint type;
- + int linno;
- union node *args;
- union node *body;
- char *var;
- @@ -762,6 +768,7 @@ struct nfor {
-
- struct ncase {
- smallint type;
- + int linno;
- union node *expr;
- union node *cases;
- };
- @@ -773,6 +780,13 @@ struct nclist {
- union node *body;
- };
-
- +struct ndefun {
- + smallint type;
- + int linno;
- + char *text;
- + union node *body;
- +};
- +
- struct narg {
- smallint type;
- union node *next;
- @@ -824,6 +838,7 @@ union node {
- struct nfor nfor;
- struct ncase ncase;
- struct nclist nclist;
- + struct ndefun ndefun;
- struct narg narg;
- struct nfile nfile;
- struct ndup ndup;
- @@ -1253,7 +1268,6 @@ struct parsefile {
-
- static struct parsefile basepf; /* top level input file */
- static struct parsefile *g_parsefile = &basepf; /* current input file */
- -static int startlinno; /* line # where last token started */
- static char *commandname; /* currently executing command */
-
-
- @@ -1267,7 +1281,7 @@ ash_vmsg(const char *msg, va_list ap)
- if (strcmp(arg0, commandname))
- fprintf(stderr, "%s: ", commandname);
- if (!iflag || g_parsefile->pf_fd > 0)
- - fprintf(stderr, "line %d: ", startlinno);
- + fprintf(stderr, "line %d: ", errlinno);
- }
- vfprintf(stderr, msg, ap);
- newline_and_flush(stderr);
- @@ -1327,6 +1341,7 @@ static void raise_error_syntax(const char *) NORETURN;
- static void
- raise_error_syntax(const char *msg)
- {
- + errlinno = g_parsefile->linno;
- ash_msg_and_raise_error("syntax error: %s", msg);
- /* NOTREACHED */
- }
- @@ -1993,6 +2008,9 @@ static void changepath(const char *) FAST_FUNC;
- static void change_random(const char *) FAST_FUNC;
- #endif
-
- +static int lineno;
- +static char linenovar[sizeof("LINENO=%d") + sizeof(int)*3] = "LINENO=";
- +
- static const struct {
- int flags;
- const char *var_text;
- @@ -2014,6 +2032,7 @@ static const struct {
- #if ENABLE_ASH_GETOPTS
- { VSTRFIXED|VTEXTFIXED , defoptindvar, getoptsreset },
- #endif
- + { VSTRFIXED|VTEXTFIXED , linenovar , NULL },
- #if ENABLE_ASH_RANDOM_SUPPORT
- { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
- #endif
- @@ -2066,12 +2085,14 @@ extern struct globals_var *const ash_ptr_to_globals_var;
- #define vps4 (&vps2)[1]
- #if ENABLE_ASH_GETOPTS
- # define voptind (&vps4)[1]
- +# define vlineno (&voptind)[1]
- # if ENABLE_ASH_RANDOM_SUPPORT
- -# define vrandom (&voptind)[1]
- +# define vrandom (&vlineno)[1]
- # endif
- #else
- +# define vlineno (&vps4)[1]
- # if ENABLE_ASH_RANDOM_SUPPORT
- -# define vrandom (&vps4)[1]
- +# define vrandom (&vlineno)[1]
- # endif
- #endif
-
- @@ -2209,8 +2230,12 @@ lookupvar(const char *name)
- if (v->flags & VDYNAMIC)
- v->var_func(NULL);
- #endif
- - if (!(v->flags & VUNSET))
- + if (!(v->flags & VUNSET)) {
- + if (v == &vlineno && v->var_text == linenovar) {
- + fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
- + }
- return var_end(v->var_text);
- + }
- }
- return NULL;
- }
- @@ -4783,7 +4808,7 @@ cmdtxt(union node *n)
- p = "; done";
- goto dodo;
- case NDEFUN:
- - cmdputs(n->narg.text);
- + cmdputs(n->ndefun.text);
- p = "() { ... }";
- goto dotail2;
- case NCMD:
- @@ -8551,6 +8576,9 @@ calcsize(int funcblocksize, union node *n)
- funcblocksize = calcsize(funcblocksize, n->nclist.next);
- break;
- case NDEFUN:
- + funcblocksize = calcsize(funcblocksize, n->ndefun.body);
- + funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
- + break;
- case NARG:
- funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
- funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
- @@ -8626,6 +8654,7 @@ copynode(union node *n)
- new->ncmd.redirect = copynode(n->ncmd.redirect);
- new->ncmd.args = copynode(n->ncmd.args);
- new->ncmd.assign = copynode(n->ncmd.assign);
- + new->ncmd.linno = n->ncmd.linno;
- break;
- case NPIPE:
- new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
- @@ -8636,6 +8665,7 @@ copynode(union node *n)
- case NSUBSHELL:
- new->nredir.redirect = copynode(n->nredir.redirect);
- new->nredir.n = copynode(n->nredir.n);
- + new->nredir.linno = n->nredir.linno;
- break;
- case NAND:
- case NOR:
- @@ -8654,10 +8684,12 @@ copynode(union node *n)
- new->nfor.var = nodeckstrdup(n->nfor.var);
- new->nfor.body = copynode(n->nfor.body);
- new->nfor.args = copynode(n->nfor.args);
- + new->nfor.linno = n->nfor.linno;
- break;
- case NCASE:
- new->ncase.cases = copynode(n->ncase.cases);
- new->ncase.expr = copynode(n->ncase.expr);
- + new->ncase.linno = n->ncase.linno;
- break;
- case NCLIST:
- new->nclist.body = copynode(n->nclist.body);
- @@ -8665,6 +8697,10 @@ copynode(union node *n)
- new->nclist.next = copynode(n->nclist.next);
- break;
- case NDEFUN:
- + new->ndefun.body = copynode(n->ndefun.body);
- + new->ndefun.text = nodeckstrdup(n->ndefun.text);
- + new->ndefun.linno = n->ndefun.linno;
- + break;
- case NARG:
- new->narg.backquote = copynodelist(n->narg.backquote);
- new->narg.text = nodeckstrdup(n->narg.text);
- @@ -8733,7 +8769,7 @@ defun(union node *func)
- INT_OFF;
- entry.cmdtype = CMDFUNCTION;
- entry.u.func = copyfunc(func);
- - addcmdentry(func->narg.text, &entry);
- + addcmdentry(func->ndefun.text, &entry);
- INT_ON;
- }
-
- @@ -8743,8 +8779,8 @@ defun(union node *func)
- #define SKIPFUNC (1 << 2)
- static smallint evalskip; /* set to SKIPxxx if we are skipping commands */
- static int skipcount; /* number of levels to skip */
- -static int funcnest; /* depth of function calls */
- static int loopnest; /* current loop nesting level */
- +static int funcline; /* starting line number of current function, or 0 if not in a function */
-
- /* Forward decl way out to parsing code - dotrap needs it */
- static int evalstring(char *s, int flags);
- @@ -8839,6 +8875,9 @@ evaltree(union node *n, int flags)
- status = !evaltree(n->nnot.com, EV_TESTED);
- goto setstatus;
- case NREDIR:
- + errlinno = lineno = n->nredir.linno;
- + if (funcline)
- + lineno -= funcline - 1;
- expredir(n->nredir.redirect);
- pushredir(n->nredir.redirect);
- status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
- @@ -8993,6 +9032,10 @@ evalfor(union node *n, int flags)
- struct stackmark smark;
- int status = 0;
-
- + errlinno = lineno = n->ncase.linno;
- + if (funcline)
- + lineno -= funcline - 1;
- +
- setstackmark(&smark);
- arglist.list = NULL;
- arglist.lastp = &arglist.list;
- @@ -9024,6 +9067,10 @@ evalcase(union node *n, int flags)
- struct stackmark smark;
- int status = 0;
-
- + errlinno = lineno = n->ncase.linno;
- + if (funcline)
- + lineno -= funcline - 1;
- +
- setstackmark(&smark);
- arglist.list = NULL;
- arglist.lastp = &arglist.list;
- @@ -9058,6 +9105,10 @@ evalsubshell(union node *n, int flags)
- int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
- int status;
-
- + errlinno = lineno = n->nredir.linno;
- + if (funcline)
- + lineno -= funcline - 1;
- +
- expredir(n->nredir.redirect);
- if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
- goto nofork;
- @@ -9365,8 +9416,10 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
- struct jmploc *volatile savehandler;
- struct jmploc jmploc;
- int e;
- + int savefuncline;
-
- saveparam = shellparam;
- + savefuncline = funcline;
- savehandler = exception_handler;
- e = setjmp(jmploc.loc);
- if (e) {
- @@ -9376,7 +9429,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
- exception_handler = &jmploc;
- shellparam.malloced = 0;
- func->count++;
- - funcnest++;
- + funcline = func->n.ndefun.linno;
- INT_ON;
- shellparam.nparam = argc - 1;
- shellparam.p = argv + 1;
- @@ -9385,11 +9438,11 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
- shellparam.optoff = -1;
- #endif
- pushlocalvars();
- - evaltree(func->n.narg.next, flags & EV_TESTED);
- + evaltree(func->n.ndefun.body, flags & EV_TESTED);
- poplocalvars(0);
- funcdone:
- INT_OFF;
- - funcnest--;
- + funcline = savefuncline;
- freefunc(func);
- freeparam(&shellparam);
- shellparam = saveparam;
- @@ -9753,6 +9806,10 @@ evalcommand(union node *cmd, int flags)
- char **nargv;
- smallint cmd_is_exec;
-
- + errlinno = lineno = cmd->ncmd.linno;
- + if (funcline)
- + lineno -= funcline - 1;
- +
- /* First expand the arguments. */
- TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
- setstackmark(&smark);
- @@ -9798,7 +9855,7 @@ evalcommand(union node *cmd, int flags)
- *nargv = NULL;
-
- lastarg = NULL;
- - if (iflag && funcnest == 0 && argc > 0)
- + if (iflag && funcline == 0 && argc > 0)
- lastarg = nargv[-1];
-
- expredir(cmd->ncmd.redirect);
- @@ -11317,6 +11374,7 @@ simplecmd(void)
- union node *vars, **vpp;
- union node **rpp, *redir;
- int savecheckkwd;
- + int savelinno;
- #if BASH_TEST2
- smallint double_brackets_flag = 0;
- #endif
- @@ -11330,6 +11388,7 @@ simplecmd(void)
- rpp = &redir;
-
- savecheckkwd = CHKALIAS;
- + savelinno = g_parsefile->linno;
- for (;;) {
- int t;
- checkkwd = savecheckkwd;
- @@ -11419,7 +11478,9 @@ simplecmd(void)
- }
- n->type = NDEFUN;
- checkkwd = CHKNL | CHKKWD | CHKALIAS;
- - n->narg.next = parse_command();
- + n->ndefun.text = n->narg.text;
- + n->ndefun.linno = g_parsefile->linno;
- + n->ndefun.body = parse_command();
- return n;
- }
- IF_BASH_FUNCTION(function_flag = 0;)
- @@ -11435,6 +11496,7 @@ simplecmd(void)
- *rpp = NULL;
- n = stzalloc(sizeof(struct ncmd));
- n->type = NCMD;
- + n->ncmd.linno = savelinno;
- n->ncmd.args = args;
- n->ncmd.assign = vars;
- n->ncmd.redirect = redir;
- @@ -11450,10 +11512,13 @@ parse_command(void)
- union node *redir, **rpp;
- union node **rpp2;
- int t;
- + int savelinno;
-
- redir = NULL;
- rpp2 = &redir;
-
- + savelinno = g_parsefile->linno;
- +
- switch (readtoken()) {
- default:
- raise_error_unexpected_syntax(-1);
- @@ -11504,6 +11569,7 @@ parse_command(void)
- raise_error_syntax("bad for loop variable");
- n1 = stzalloc(sizeof(struct nfor));
- n1->type = NFOR;
- + n1->nfor.linno = savelinno;
- n1->nfor.var = wordtext;
- checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (readtoken() == TIN) {
- @@ -11544,6 +11610,7 @@ parse_command(void)
- case TCASE:
- n1 = stzalloc(sizeof(struct ncase));
- n1->type = NCASE;
- + n1->ncase.linno = savelinno;
- if (readtoken() != TWORD)
- raise_error_unexpected_syntax(TWORD);
- n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
- @@ -11595,6 +11662,7 @@ parse_command(void)
- case TLP:
- n1 = stzalloc(sizeof(struct nredir));
- n1->type = NSUBSHELL;
- + n1->nredir.linno = savelinno;
- n1->nredir.n = list(0);
- /*n1->nredir.redirect = NULL; - stzalloc did it */
- t = TRP;
- @@ -11628,6 +11696,7 @@ parse_command(void)
- if (n1->type != NSUBSHELL) {
- n2 = stzalloc(sizeof(struct nredir));
- n2->type = NREDIR;
- + n2->nredir.linno = savelinno;
- n2->nredir.n = n1;
- n1 = n2;
- }
- @@ -11726,10 +11795,8 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
- IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */
- IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
- int dqvarnest; /* levels of variables expansion within double quotes */
- -
- IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
-
- - startlinno = g_parsefile->linno;
- bqlist = NULL;
- quotef = 0;
- IF_FEATURE_SH_MATH(prevsyntax = 0;)
- @@ -11906,7 +11973,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
- if (syntax != BASESYNTAX && eofmark == NULL)
- raise_error_syntax("unterminated quoted string");
- if (varnest != 0) {
- - startlinno = g_parsefile->linno;
- /* { */
- raise_error_syntax("missing '}'");
- }
- @@ -12298,7 +12364,6 @@ parsebackq: {
-
- case PEOF:
- IF_ASH_ALIAS(case PEOA:)
- - startlinno = g_parsefile->linno;
- raise_error_syntax("EOF in backquote substitution");
-
- case '\n':
- @@ -12380,8 +12445,6 @@ parsearith: {
- * quoted.
- * If the token is TREDIR, then we set redirnode to a structure containing
- * the redirection.
- - * In all cases, the variable startlinno is set to the number of the line
- - * on which the token starts.
- *
- * [Change comment: here documents and internal procedures]
- * [Readtoken shouldn't have any arguments. Perhaps we should make the
- @@ -12419,7 +12482,6 @@ xxreadtoken(void)
- return lasttoken;
- }
- setprompt_if(needprompt, 2);
- - startlinno = g_parsefile->linno;
- for (;;) { /* until token or start of word found */
- c = pgetc();
- if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
- @@ -12480,7 +12542,6 @@ xxreadtoken(void)
- return lasttoken;
- }
- setprompt_if(needprompt, 2);
- - startlinno = g_parsefile->linno;
- for (;;) { /* until token or start of word found */
- c = pgetc();
- switch (c) {
|