diff options
author | Harald van Dijk <harald@gigawatt.nl> | 2011-03-15 15:52:05 +0800 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2011-03-15 15:52:05 +0800 |
commit | 5bb39bb1995cb12d8da76b1d482df9be1acc2eb4 (patch) | |
tree | 09c088a97971babd2e0dd593d7601e282ed5fc69 /src/eval.c | |
parent | [EVAL] Let funcnode refer to a function definition, not its first command (diff) | |
download | dash-5bb39bb1995cb12d8da76b1d482df9be1acc2eb4.tar.gz dash-5bb39bb1995cb12d8da76b1d482df9be1acc2eb4.zip |
[SHELL] Improve LINENO support
This patch improves LINENO support by storing line numbers in the parse tree, for commands as well as for function definitions. It makes LINENO behaves properly when calling functions, and has the added benefit of improved line numbers in error messages when the last-parsed command is not the last-executed one. It removes the earlier LINENO support, and instead sets LINENO from evaltree when a command is executed Signed-off-by: Harald van Dijk <harald@gigawatt.nl> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/src/eval.c b/src/eval.c index 9f4388a..426c03a 100644 --- a/src/eval.c +++ b/src/eval.c @@ -73,7 +73,7 @@ int evalskip; /* set if we are skipping commands */ STATIC int skipcount; /* number of levels to skip */ MKINIT int loopnest; /* current loop nesting level */ -static int funcnest; /* depth of function calls */ +static int funcline; /* starting line number of current function, or 0 if not in a function */ char *commandname; @@ -218,6 +218,9 @@ evaltree(union node *n, int flags) status = !exitstatus; 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); @@ -376,6 +379,10 @@ evalfor(union node *n, int flags) struct strlist *sp; struct stackmark smark; + errlinno = lineno = n->nfor.linno; + if (funcline) + lineno -= funcline - 1; + setstackmark(&smark); arglist.lastp = &arglist.list; for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { @@ -417,6 +424,10 @@ evalcase(union node *n, int flags) struct arglist arglist; struct stackmark smark; + errlinno = lineno = n->ncase.linno; + if (funcline) + lineno -= funcline - 1; + setstackmark(&smark); arglist.lastp = &arglist.list; expandarg(n->ncase.expr, &arglist, EXP_TILDE); @@ -448,6 +459,10 @@ evalsubshell(union node *n, int flags) int backgnd = (n->type == NBACKGND); int status; + errlinno = lineno = n->nredir.linno; + if (funcline) + lineno -= funcline - 1; + expredir(n->nredir.redirect); if (!backgnd && flags & EV_EXIT && !have_traps()) goto nofork; @@ -704,6 +719,10 @@ evalcommand(union node *cmd, int flags) int status; char **nargv; + 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); @@ -737,7 +756,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]; preverrout.fd = 2; @@ -937,8 +956,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; if ((e = setjmp(jmploc.loc))) { goto funcdone; } @@ -947,18 +968,18 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) handler = &jmploc; shellparam.malloc = 0; func->count++; - funcnest++; + funcline = func->n.ndefun.linno; INTON; shellparam.nparam = argc - 1; shellparam.p = argv + 1; shellparam.optind = 1; shellparam.optoff = -1; pushlocalvars(); - evaltree(func->n.narg.next, flags & EV_TESTED); + evaltree(func->n.ndefun.body, flags & EV_TESTED); poplocalvars(0); funcdone: INTOFF; - funcnest--; + funcline = savefuncline; freefunc(func); freeparam(&shellparam); shellparam = saveparam; @@ -1048,7 +1069,7 @@ returncmd(int argc, char **argv) * If called outside a function, do what ksh does; * skip the rest of the file. */ - evalskip = funcnest ? SKIPFUNC : SKIPFILE; + evalskip = funcline ? SKIPFUNC : SKIPFILE; return argv[1] ? number(argv[1]) : exitstatus; } |