From 675d24aeaff29dbce6dc116a4b7c9f6026ed5069 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 27 Jan 2018 22:02:05 +0100 Subject: ash: add LINENO support 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 function old new delta parse_command 1604 1677 +73 calcsize 156 223 +67 copynode 196 258 +62 evalcommand 1546 1606 +60 ash_main 1046 1103 +57 lookupvar 51 106 +55 evalcase 269 317 +48 evaltree 501 547 +46 evalfor 156 200 +44 evalsubshell 156 195 +39 raise_error_syntax 11 29 +18 varinit_data 120 132 +12 evalfun 270 280 +10 funcline - 4 +4 cmdtxt 569 572 +3 trapcmd 306 304 -2 ash_vmsg 153 150 -3 startlinno 4 - -4 funcnest 4 - -4 xxreadtoken 263 250 -13 readtoken1 2645 2602 -43 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 14/4 up/down: 598/-69) Total: 529 bytes text data bss dec hex filename 932834 481 6864 940179 e5893 busybox_old 933375 481 6856 940712 e5aa8 busybox_unstripped Signed-off-by: Denys Vlasenko --- shell/ash_LINENO.patch | 498 ------------------------------------------------- 1 file changed, 498 deletions(-) delete mode 100644 shell/ash_LINENO.patch (limited to 'shell/ash_LINENO.patch') diff --git a/shell/ash_LINENO.patch b/shell/ash_LINENO.patch deleted file mode 100644 index a71549d6a..000000000 --- a/shell/ash_LINENO.patch +++ /dev/null @@ -1,498 +0,0 @@ -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) { -- cgit v1.2.3