From 0383d0751d180215bdb2268fa235e97741d740c2 Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 4 Jun 2011 11:28:42 +0000 Subject: sh: Honour -n while processing -c string. --- bin/sh/eval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bin/sh/eval.c') diff --git a/bin/sh/eval.c b/bin/sh/eval.c index a50c53f..404de33 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -165,7 +165,7 @@ evalstring(char *s, int flags) setstackmark(&smark); setinputstring(s, 1); while ((n = parsecmd(0)) != NEOF) { - if (n != NULL) { + if (n != NULL && !nflag) { if (flags_exit && preadateof()) evaltree(n, flags | EV_EXIT); else -- cgit v1.1 From fba76e8544240faef25943d9886fc3bc31161eb9 Mon Sep 17 00:00:00 2001 From: jilles Date: Sun, 5 Jun 2011 14:13:15 +0000 Subject: sh: Fix $? in heredocs on simple commands. PR: bin/41410 --- bin/sh/eval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bin/sh/eval.c') diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 404de33..585f91e 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -409,6 +409,7 @@ evalsubshell(union node *n, int flags) struct job *jp; int backgnd = (n->type == NBACKGND); + oexitstatus = exitstatus; expredir(n->nredir.redirect); if ((!backgnd && flags & EV_EXIT && !have_traps()) || forkshell(jp = makejob(n, 1), n, backgnd) == 0) { @@ -436,6 +437,7 @@ evalredir(union node *n, int flags) struct jmploc *savehandler; volatile int in_redirect = 1; + oexitstatus = exitstatus; expredir(n->nredir.redirect); savehandler = handler; if (setjmp(jmploc.loc)) { @@ -478,7 +480,6 @@ expredir(union node *n) for (redir = n ; redir ; redir = redir->nfile.next) { struct arglist fn; fn.lastp = &fn.list; - oexitstatus = exitstatus; switch (redir->type) { case NFROM: case NTO: -- cgit v1.1 From bd55770c9432e60436b620cca0048948daf2445b Mon Sep 17 00:00:00 2001 From: jilles Date: Thu, 9 Jun 2011 23:12:23 +0000 Subject: sh: Do parameter expansion before printing PS4 (set -x). The function name expandstr() and the general idea of doing this kind of expansion by treating the text as a here document without end marker is from dash. All variants of parameter expansion and arithmetic expansion also work (the latter is not required by POSIX but it does not take extra code and many other shells also allow it). Command substitution is prevented because I think it causes too much code to be re-entered (for example creating an unbounded recursion of trace lines). Unfortunately, our LINENO is somewhat crude, otherwise PS4='$LINENO+ ' would be quite useful. --- bin/sh/eval.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'bin/sh/eval.c') diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 585f91e..92a18e4 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -745,8 +745,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) /* Print the command if xflag is set. */ if (xflag) { char sep = 0; - const char *p; - out2str(ps4val()); + const char *p, *ps4; + ps4 = expandstr(ps4val()); + out2str(ps4 != NULL ? ps4 : ps4val()); for (sp = varlist.list ; sp ; sp = sp->next) { if (sep != 0) out2c(' '); -- cgit v1.1 From 91789615b49a87147298eee12c9b111d8c1b64c9 Mon Sep 17 00:00:00 2001 From: jilles Date: Sun, 12 Jun 2011 23:06:04 +0000 Subject: sh: Save/restore changed variables in optimized command substitution. In optimized command substitution, save and restore any variables changed by expansions (${var=value} and $((var=assigned))), instead of trying to determine if an expansion may cause such changes. If $! is referenced in optimized command substitution, do not cause jobs to be remembered longer. This fixes $(jobs $!) again, simplifies the man page and shortens the code. --- bin/sh/eval.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'bin/sh/eval.c') diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 92a18e4..9d67b9e 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -571,14 +571,8 @@ evalpipe(union node *n) static int is_valid_fast_cmdsubst(union node *n) { - union node *argp; - if (n->type != NCMD) - return 0; - for (argp = n->ncmd.args ; argp ; argp = argp->narg.next) - if (expandhassideeffects(argp->narg.text)) - return 0; - return 1; + return (n->type == NCMD); } /* @@ -596,6 +590,7 @@ evalbackcmd(union node *n, struct backcmd *result) struct stackmark smark; /* unnecessary */ struct jmploc jmploc; struct jmploc *savehandler; + struct localvar *savelocalvars; setstackmark(&smark); result->fd = -1; @@ -608,12 +603,18 @@ evalbackcmd(union node *n, struct backcmd *result) } if (is_valid_fast_cmdsubst(n)) { exitstatus = oexitstatus; + savelocalvars = localvars; + localvars = NULL; + forcelocal++; savehandler = handler; if (setjmp(jmploc.loc)) { if (exception == EXERROR || exception == EXEXEC) exitstatus = 2; else if (exception != 0) { handler = savehandler; + forcelocal--; + poplocalvars(); + localvars = savelocalvars; longjmp(handler->loc, 1); } } else { @@ -621,6 +622,9 @@ evalbackcmd(union node *n, struct backcmd *result) evalcommand(n, EV_BACKCMD, result); } handler = savehandler; + forcelocal--; + poplocalvars(); + localvars = savelocalvars; } else { exitstatus = 0; if (pipe(pip) < 0) -- cgit v1.1 From 00d33feb9db18288f251841bbebdf3b74f4d875e Mon Sep 17 00:00:00 2001 From: jilles Date: Thu, 16 Jun 2011 21:50:28 +0000 Subject: sh: Reduce unnecessary forks with eval. The eval special builtin now runs the code with EV_EXIT if it was run with EV_EXIT itself. In particular, this eliminates one fork when a command substitution contains an eval command that ends with an external program or a subshell. This is similar to what r220978 did for functions. --- bin/sh/eval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bin/sh/eval.c') diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 9d67b9e..25793c1 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -140,7 +140,7 @@ evalcmd(int argc, char **argv) STPUTC('\0', concat); p = grabstackstr(concat); } - evalstring(p, builtin_flags & EV_TESTED); + evalstring(p, builtin_flags); } else exitstatus = 0; return exitstatus; @@ -908,6 +908,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) dup2(pip[1], 1); close(pip[1]); } + flags &= ~EV_BACKCMD; } flags |= EV_EXIT; } -- cgit v1.1 From c7a72567a8474dcecd93215073976b04171d1144 Mon Sep 17 00:00:00 2001 From: jilles Date: Fri, 17 Jun 2011 13:03:49 +0000 Subject: sh: Add case statement fallthrough (with ';&' instead of ';;'). Replacing ;; with the new control operator ;& will cause the next list to be executed as well without checking its pattern, continuing until a list ends with ;; or until the end of the case statement. This is like omitting "break" in a C "switch" statement. The sequence ;& was formerly invalid. This feature is proposed for the next POSIX issue in Austin Group issue #449. --- bin/sh/eval.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'bin/sh/eval.c') diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 25793c1..a22d4b1 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -386,6 +386,14 @@ evalcase(union node *n, int flags) for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { if (casematch(patp, arglist.list->text)) { + while (cp->nclist.next && + cp->type == NCLISTFALLTHRU) { + if (evalskip != 0) + break; + evaltree(cp->nclist.body, + flags & ~EV_EXIT); + cp = cp->nclist.next; + } if (evalskip == 0) { evaltree(cp->nclist.body, flags); } -- cgit v1.1 From f78ebc168ba76cc9de70590c71fceac20b9d63b8 Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 18 Jun 2011 23:58:59 +0000 Subject: sh: Remove special support for background simple commands. It expands the arguments in the parent shell process, which is incorrect. --- bin/sh/eval.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'bin/sh/eval.c') diff --git a/bin/sh/eval.c b/bin/sh/eval.c index a22d4b1..d5da7d3 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -894,14 +894,13 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) } /* Fork off a child process if necessary. */ - if (cmd->ncmd.backgnd - || ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) + if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) && ((flags & EV_EXIT) == 0 || have_traps())) || ((flags & EV_BACKCMD) != 0 && (cmdentry.cmdtype != CMDBUILTIN || !safe_builtin(cmdentry.u.index, argc, argv)))) { jp = makejob(cmd, 1); - mode = cmd->ncmd.backgnd; + mode = FORK_FG; if (flags & EV_BACKCMD) { mode = FORK_NOJOB; if (pipe(pip) < 0) @@ -1068,8 +1067,7 @@ parent: /* parent process gets here (if we forked) */ backcmd->fd = pip[0]; close(pip[1]); backcmd->jp = jp; - } else - exitstatus = 0; + } out: if (lastarg) -- cgit v1.1