ash: eval: Replace with listsetvar with mklocal/setvareq

Upstream commit:

    Date: Sat, 19 May 2018 02:39:55 +0800
    eval: Replace with listsetvar with mklocal/setvareq

    This patch replaces listsetvar with mklocal/setvareq.  As we now
    determine special built-in status prior to variable assignment, we
    no longer have to do a second pass listsetvar.  Instead we will
    call setvareq directly instead of mklocal when necessary.

    In order to do this mklocal can now take a flag in order to mark
    a variable for export.

    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2020-02-19 17:33:44 +01:00
parent 54bef2a8ef
commit 3e729102a8

View File

@ -2476,24 +2476,6 @@ unsetvar(const char *s)
setvar(s, NULL, 0); setvar(s, NULL, 0);
} }
/*
* Process a linked list of variable assignments.
*/
static void
listsetvar(struct strlist *list_set_var, int flags)
{
struct strlist *lp = list_set_var;
if (!lp)
return;
INT_OFF;
do {
setvareq(lp->text, flags);
lp = lp->next;
} while (lp);
INT_ON;
}
/* /*
* Generate a list of variables satisfying the given conditions. * Generate a list of variables satisfying the given conditions.
*/ */
@ -9810,7 +9792,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
* (options will be restored on return from the function). * (options will be restored on return from the function).
*/ */
static void static void
mklocal(char *name) mklocal(char *name, int flags)
{ {
struct localvar *lvp; struct localvar *lvp;
struct var **vpp; struct var **vpp;
@ -9847,9 +9829,9 @@ mklocal(char *name)
if (vp == NULL) { if (vp == NULL) {
/* variable did not exist yet */ /* variable did not exist yet */
if (eq) if (eq)
vp = setvareq(name, VSTRFIXED); vp = setvareq(name, VSTRFIXED | flags);
else else
vp = setvar(name, NULL, VSTRFIXED); vp = setvar(name, NULL, VSTRFIXED | flags);
lvp->flags = VUNSET; lvp->flags = VUNSET;
} else { } else {
lvp->text = vp->var_text; lvp->text = vp->var_text;
@ -9859,7 +9841,7 @@ mklocal(char *name)
*/ */
vp->flags |= VSTRFIXED|VTEXTFIXED; vp->flags |= VSTRFIXED|VTEXTFIXED;
if (eq) if (eq)
setvareq(name, 0); setvareq(name, flags);
else else
/* "local VAR" unsets VAR: */ /* "local VAR" unsets VAR: */
setvar0(name, NULL); setvar0(name, NULL);
@ -9885,7 +9867,7 @@ localcmd(int argc UNUSED_PARAM, char **argv)
argv = argptr; argv = argptr;
while ((name = *argv++) != NULL) { while ((name = *argv++) != NULL) {
mklocal(name); mklocal(name, 0);
} }
return 0; return 0;
} }
@ -10166,6 +10148,8 @@ evalcommand(union node *cmd, int flags)
int status; int status;
char **nargv; char **nargv;
smallint cmd_is_exec; smallint cmd_is_exec;
int vflags;
int vlocal;
errlinno = lineno = cmd->ncmd.linno; errlinno = lineno = cmd->ncmd.linno;
if (funcline) if (funcline)
@ -10173,7 +10157,6 @@ evalcommand(union node *cmd, int flags)
/* First expand the arguments. */ /* First expand the arguments. */
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
localvar_stop = pushlocalvars();
file_stop = g_parsefile; file_stop = g_parsefile;
back_exitstatus = 0; back_exitstatus = 0;
@ -10187,6 +10170,8 @@ evalcommand(union node *cmd, int flags)
cmd_flag = 0; cmd_flag = 0;
cmd_is_exec = 0; cmd_is_exec = 0;
spclbltin = -1; spclbltin = -1;
vflags = 0;
vlocal = 0;
path = NULL; path = NULL;
argc = 0; argc = 0;
@ -10199,6 +10184,8 @@ evalcommand(union node *cmd, int flags)
find_command(arglist.list->text, &cmdentry, find_command(arglist.list->text, &cmdentry,
cmd_flag | DO_REGBLTIN, pathval()); cmd_flag | DO_REGBLTIN, pathval());
vlocal++;
/* implement bltin and command here */ /* implement bltin and command here */
if (cmdentry.cmdtype != CMDBUILTIN) if (cmdentry.cmdtype != CMDBUILTIN)
break; break;
@ -10206,6 +10193,7 @@ evalcommand(union node *cmd, int flags)
pseudovarflag = IS_BUILTIN_ASSIGN(cmdentry.u.cmd); pseudovarflag = IS_BUILTIN_ASSIGN(cmdentry.u.cmd);
if (spclbltin < 0) { if (spclbltin < 0) {
spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd); spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
vlocal = !spclbltin;
} }
cmd_is_exec = cmdentry.u.cmd == EXECCMD; cmd_is_exec = cmdentry.u.cmd == EXECCMD;
if (cmdentry.u.cmd != COMMANDCMD) if (cmdentry.u.cmd != COMMANDCMD)
@ -10224,6 +10212,9 @@ evalcommand(union node *cmd, int flags)
for (sp = arglist.list; sp; sp = sp->next) for (sp = arglist.list; sp; sp = sp->next)
argc++; argc++;
if (cmd_is_exec && argc > 1)
vflags = VEXPORT;
} }
/* Reserve one extra spot at the front for shellexec. */ /* Reserve one extra spot at the front for shellexec. */
@ -10254,6 +10245,7 @@ evalcommand(union node *cmd, int flags)
status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2); status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
if (status) { if (status) {
vlocal = 0;
bail: bail:
exitstatus = status; exitstatus = status;
@ -10264,13 +10256,20 @@ evalcommand(union node *cmd, int flags)
goto out; goto out;
} }
localvar_stop = NULL;
if (vlocal)
localvar_stop = pushlocalvars();
for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
struct strlist **spp; struct strlist **spp;
spp = varlist.lastp; spp = varlist.lastp;
expandarg(argp, &varlist, EXP_VARTILDE); expandarg(argp, &varlist, EXP_VARTILDE);
mklocal((*spp)->text); if (vlocal)
mklocal((*spp)->text, VEXPORT);
else
setvareq((*spp)->text, vflags);
} }
/* Print the command if xflag is set. */ /* Print the command if xflag is set. */
@ -10313,8 +10312,8 @@ evalcommand(union node *cmd, int flags)
if (cmdentry.cmdtype != CMDBUILTIN if (cmdentry.cmdtype != CMDBUILTIN
|| !(IS_BUILTIN_REGULAR(cmdentry.u.cmd)) || !(IS_BUILTIN_REGULAR(cmdentry.u.cmd))
) { ) {
find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path = path ? path : pathval();
path ? path : pathval()); find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path);
} }
jp = NULL; jp = NULL;
@ -10385,17 +10384,10 @@ evalcommand(union node *cmd, int flags)
FORCE_INT_ON; FORCE_INT_ON;
/* fall through to exec'ing external program */ /* fall through to exec'ing external program */
} }
listsetvar(varlist.list, VEXPORT|VSTACK);
path = path ? path : pathval();
shellexec(argv[0], argv, path, cmdentry.u.index); shellexec(argv[0], argv, path, cmdentry.u.index);
/* NOTREACHED */ /* NOTREACHED */
} /* default */ } /* default */
case CMDBUILTIN: case CMDBUILTIN:
if (spclbltin > 0 || argc == 0) {
poplocalvars(1);
if (cmd_is_exec && argc > 1)
listsetvar(varlist.list, VEXPORT);
}
if (evalbltin(cmdentry.u.cmd, argc, argv, flags) if (evalbltin(cmdentry.u.cmd, argc, argv, flags)
&& !(exception_type == EXERROR && spclbltin <= 0) && !(exception_type == EXERROR && spclbltin <= 0)
) { ) {
@ -10418,6 +10410,7 @@ evalcommand(union node *cmd, int flags)
popredir(/*drop:*/ cmd_is_exec); popredir(/*drop:*/ cmd_is_exec);
unwindredir(redir_stop); unwindredir(redir_stop);
unwindfiles(file_stop); unwindfiles(file_stop);
if (vlocal)
unwindlocalvars(localvar_stop); unwindlocalvars(localvar_stop);
if (lastarg) { if (lastarg) {
/* dsl: I think this is intended to be used to support /* dsl: I think this is intended to be used to support