summaryrefslogtreecommitdiffstats
path: root/bin/sh
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2011-11-26 23:28:31 +0000
committerjilles <jilles@FreeBSD.org>2011-11-26 23:28:31 +0000
commit49f86abcab96df05c0f8a4d10bcaf2b55e15c850 (patch)
tree4adc84a5a8f01e241ebd7c5e58e96a75000d60bb /bin/sh
parenta634fb6b1ecfd62eb2230ac4a8f6d371acd16f70 (diff)
downloadFreeBSD-src-49f86abcab96df05c0f8a4d10bcaf2b55e15c850.zip
FreeBSD-src-49f86abcab96df05c0f8a4d10bcaf2b55e15c850.tar.gz
sh: Reduce one level of evaltree() recursion when executing 'case'.
Free expanded case text before executing commands. Remove impossible evalskip checks (expanding an argument cannot set evalskip anymore since $(break) and the like are properly executed in a subshell environment).
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/eval.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index d5da7d3..c0ab4e4 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -89,7 +89,7 @@ int oexitstatus; /* saved exit status */
static void evalloop(union node *, int);
static void evalfor(union node *, int);
-static void evalcase(union node *, int);
+static union node *evalcase(union node *, int);
static void evalsubshell(union node *, int);
static void evalredir(union node *, int);
static void expredir(union node *);
@@ -256,7 +256,7 @@ evaltree(union node *n, int flags)
evalfor(n, flags & ~EV_EXIT);
break;
case NCASE:
- evalcase(n, flags);
+ next = evalcase(n, flags);
break;
case NDEFUN:
defun(n->narg.text, n->narg.next);
@@ -370,7 +370,7 @@ out:
-static void
+static union node *
evalcase(union node *n, int flags)
{
union node *cp;
@@ -383,26 +383,24 @@ evalcase(union node *n, int flags)
oexitstatus = exitstatus;
exitstatus = 0;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
- for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
+ for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
+ popstackmark(&smark);
while (cp->nclist.next &&
cp->type == NCLISTFALLTHRU) {
- if (evalskip != 0)
- break;
evaltree(cp->nclist.body,
flags & ~EV_EXIT);
+ if (evalskip != 0)
+ return (NULL);
cp = cp->nclist.next;
}
- if (evalskip == 0) {
- evaltree(cp->nclist.body, flags);
- }
- goto out;
+ return (cp->nclist.body);
}
}
}
-out:
popstackmark(&smark);
+ return (NULL);
}
OpenPOWER on IntegriCloud