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).
This commit is contained in:
Jilles Tjoelker 2011-11-26 23:28:31 +00:00
parent cdb7ebe38c
commit a157dc4d90
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=228013

View File

@ -89,7 +89,7 @@ int oexitstatus; /* saved exit status */
static void evalloop(union node *, int); static void evalloop(union node *, int);
static void evalfor(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 evalsubshell(union node *, int);
static void evalredir(union node *, int); static void evalredir(union node *, int);
static void expredir(union node *); static void expredir(union node *);
@ -256,7 +256,7 @@ evaltree(union node *n, int flags)
evalfor(n, flags & ~EV_EXIT); evalfor(n, flags & ~EV_EXIT);
break; break;
case NCASE: case NCASE:
evalcase(n, flags); next = evalcase(n, flags);
break; break;
case NDEFUN: case NDEFUN:
defun(n->narg.text, n->narg.next); defun(n->narg.text, n->narg.next);
@ -370,7 +370,7 @@ evalfor(union node *n, int flags)
static void static union node *
evalcase(union node *n, int flags) evalcase(union node *n, int flags)
{ {
union node *cp; union node *cp;
@ -383,26 +383,24 @@ evalcase(union node *n, int flags)
oexitstatus = exitstatus; oexitstatus = exitstatus;
exitstatus = 0; exitstatus = 0;
expandarg(n->ncase.expr, &arglist, EXP_TILDE); 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) { for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) { if (casematch(patp, arglist.list->text)) {
popstackmark(&smark);
while (cp->nclist.next && while (cp->nclist.next &&
cp->type == NCLISTFALLTHRU) { cp->type == NCLISTFALLTHRU) {
if (evalskip != 0)
break;
evaltree(cp->nclist.body, evaltree(cp->nclist.body,
flags & ~EV_EXIT); flags & ~EV_EXIT);
if (evalskip != 0)
return (NULL);
cp = cp->nclist.next; cp = cp->nclist.next;
} }
if (evalskip == 0) { return (cp->nclist.body);
evaltree(cp->nclist.body, flags);
}
goto out;
} }
} }
} }
out:
popstackmark(&smark); popstackmark(&smark);
return (NULL);
} }