aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2018-05-19 02:39:55 +0800
committerBen Hutchings <ben@decadent.org.uk>2020-03-28 21:42:55 +0000
commitcbf6b9e61bc7e49b8863901ef0bf85483af5861f (patch)
treee8d1fbf6fb9112a7323f22915fda9997bf2d24e8
parente9dcd440e4ba1812181839ba803dc0fe2909c43e (diff)
downloadklibc-cbf6b9e61bc7e49b8863901ef0bf85483af5861f.tar.gz
[klibc] dash: eval: Replace with listsetvar with mklocal/setvareq
[ dash commit 811a36120aef848cd308d56e06bf62e721be853c ] 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: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--usr/dash/eval.c36
-rw-r--r--usr/dash/var.c32
-rw-r--r--usr/dash/var.h3
3 files changed, 29 insertions, 42 deletions
diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index fc5a594a94517..77a8bdedb928b 100644
--- a/usr/dash/eval.c
+++ b/usr/dash/eval.c
@@ -737,6 +737,8 @@ evalcommand(union node *cmd, int flags)
int execcmd;
int status;
char **nargv;
+ int vflags;
+ int vlocal;
errlinno = lineno = cmd->ncmd.linno;
if (funcline)
@@ -745,7 +747,6 @@ evalcommand(union node *cmd, int flags)
/* First expand the arguments. */
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
setstackmark(&smark);
- localvar_stop = pushlocalvars();
file_stop = parsefile;
back_exitstatus = 0;
@@ -759,6 +760,8 @@ evalcommand(union node *cmd, int flags)
cmd_flag = 0;
execcmd = 0;
spclbltin = -1;
+ vflags = 0;
+ vlocal = 0;
path = NULL;
argc = 0;
@@ -770,6 +773,8 @@ evalcommand(union node *cmd, int flags)
find_command(arglist.list->text, &cmdentry,
cmd_flag | DO_REGBLTIN, pathval());
+ vlocal++;
+
/* implement bltin and command here */
if (cmdentry.cmdtype != CMDBUILTIN)
break;
@@ -780,6 +785,7 @@ evalcommand(union node *cmd, int flags)
cmdentry.u.cmd->flags &
BUILTIN_SPECIAL
;
+ vlocal = spclbltin ^ BUILTIN_SPECIAL;
}
execcmd = cmdentry.u.cmd == EXECCMD;
if (likely(cmdentry.u.cmd != COMMANDCMD))
@@ -798,6 +804,9 @@ evalcommand(union node *cmd, int flags)
for (sp = arglist.list; sp; sp = sp->next)
argc++;
+
+ if (execcmd && argc > 1)
+ vflags = VEXPORT;
}
/* Reserve one extra spot at the front for shellexec. */
@@ -818,7 +827,8 @@ evalcommand(union node *cmd, int flags)
redir_stop = pushredir(cmd->ncmd.redirect);
status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
- if (status) {
+ if (unlikely(status)) {
+ vlocal = 0;
bail:
exitstatus = status;
@@ -829,13 +839,19 @@ bail:
goto out;
}
+ if (likely(vlocal))
+ localvar_stop = pushlocalvars();
+
for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
struct strlist **spp;
spp = varlist.lastp;
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. */
@@ -857,8 +873,8 @@ bail:
/* Now locate the command. */
if (cmdentry.cmdtype != CMDBUILTIN ||
!(cmdentry.u.cmd->flags & BUILTIN_REGULAR)) {
- find_command(argv[0], &cmdentry, cmd_flag | DO_ERR,
- unlikely(path) ? path : pathval());
+ path = unlikely(path) ? path : pathval();
+ find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path);
}
jp = NULL;
@@ -881,17 +897,10 @@ bail:
break;
FORCEINTON;
}
- listsetvar(varlist.list, VEXPORT|VSTACK);
- path = unlikely(path) ? path : pathval();
shellexec(argv, path, cmdentry.u.index);
/* NOTREACHED */
case CMDBUILTIN:
- if (spclbltin > 0 || argc == 0) {
- poplocalvars(1);
- if (execcmd && argc > 1)
- listsetvar(varlist.list, VEXPORT);
- }
if (evalbltin(cmdentry.u.cmd, argc, argv, flags) &&
!(exception == EXERROR && spclbltin <= 0)) {
raise:
@@ -913,7 +922,8 @@ out:
popredir(execcmd);
unwindredir(redir_stop);
unwindfiles(file_stop);
- unwindlocalvars(localvar_stop);
+ if (likely(vlocal))
+ unwindlocalvars(localvar_stop);
if (lastarg)
/* dsl: I think this is intended to be used to support
* '_' in 'vi' command mode during line editing...
diff --git a/usr/dash/var.c b/usr/dash/var.c
index 604ab1f7327d2..40743e5d019cb 100644
--- a/usr/dash/var.c
+++ b/usr/dash/var.c
@@ -302,28 +302,6 @@ out:
return vp;
}
-
-
-/*
- * Process a linked list of variable assignments.
- */
-
-void
-listsetvar(struct strlist *list, int flags)
-{
- struct strlist *lp;
-
- lp = list;
- if (!lp)
- return;
- INTOFF;
- do {
- setvareq(lp->text, flags);
- } while ((lp = lp->next));
- INTON;
-}
-
-
/*
* Find the value of a variable. Returns NULL if not set.
*/
@@ -468,7 +446,7 @@ localcmd(int argc, char **argv)
argv = argptr;
while ((name = *argv++) != NULL) {
- mklocal(name);
+ mklocal(name, 0);
}
return 0;
}
@@ -481,7 +459,7 @@ localcmd(int argc, char **argv)
* "-" as a special case.
*/
-void mklocal(char *name)
+void mklocal(char *name, int flags)
{
struct localvar *lvp;
struct var **vpp;
@@ -502,16 +480,16 @@ void mklocal(char *name)
eq = strchr(name, '=');
if (vp == NULL) {
if (eq)
- vp = setvareq(name, VSTRFIXED);
+ vp = setvareq(name, VSTRFIXED | flags);
else
- vp = setvar(name, NULL, VSTRFIXED);
+ vp = setvar(name, NULL, VSTRFIXED | flags);
lvp->flags = VUNSET;
} else {
lvp->text = vp->text;
lvp->flags = vp->flags;
vp->flags |= VSTRFIXED|VTEXTFIXED;
if (eq)
- setvareq(name, 0);
+ setvareq(name, flags);
}
}
lvp->vp = vp;
diff --git a/usr/dash/var.h b/usr/dash/var.h
index 52f559d1e2b9e..8759be46267b1 100644
--- a/usr/dash/var.h
+++ b/usr/dash/var.h
@@ -139,7 +139,6 @@ struct var *setvar(const char *name, const char *val, int flags);
intmax_t setvarint(const char *, intmax_t, int);
struct var *setvareq(char *s, int flags);
struct strlist;
-void listsetvar(struct strlist *, int);
char *lookupvar(const char *);
intmax_t lookupvarint(const char *);
char **listvars(int, int, char ***);
@@ -147,7 +146,7 @@ char **listvars(int, int, char ***);
int showvars(const char *, int, int);
int exportcmd(int, char **);
int localcmd(int, char **);
-void mklocal(char *);
+void mklocal(char *name, int flags);
struct localvar_list *pushlocalvars(void);
void poplocalvars(int);
void unwindlocalvars(struct localvar_list *stop);