diff mbox

eval: Replace external use of mklocal with listsetvar

Message ID 20180509085612.dr72efjltbjxcjfr@gondor.apana.org.au (mailing list archive)
State Superseded
Delegated to: Herbert Xu
Headers show

Commit Message

Herbert Xu May 9, 2018, 8:56 a.m. UTC
This patch adds support for listsetvar to be used for setting local
variables in bulk through the VLOCAL flag.

It also removes the use of mklocal in evalcommand, and replaces it
with listsetvar.

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

Patch

diff --git a/src/eval.c b/src/eval.c
index 39c4e41..23be7ba 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -714,6 +714,7 @@  evalcommand(union node *cmd, int flags)
 	int execcmd;
 	int status;
 	char **nargv;
+	int vflags;
 
 	errlinno = lineno = cmd->ncmd.linno;
 	if (funcline)
@@ -769,8 +770,6 @@  evalcommand(union node *cmd, int flags)
 		spp = varlist.lastp;
 		expandarg(argp, &varlist, EXP_VARTILDE);
 
-		mklocal((*spp)->text);
-
 		/*
 		 * Modify the command lookup path, if a PATH= assignment
 		 * is present
@@ -852,6 +851,13 @@  bail:
 
 	jp = NULL;
 
+	if (cmdentry.cmdtype == CMDBUILTIN && (spclbltin > 0 || argc == 0))
+		vflags = execcmd && argc > 1 ? VEXPORT : 0;
+	else
+		vflags = VLOCAL | (cmdentry.cmdtype == CMDNORMAL ?
+				   VEXPORT | VNOFUNC : 0);
+	listsetvar(varlist.list, vflags);
+
 	/* Execute the command. */
 	switch (cmdentry.cmdtype) {
 	default:
@@ -863,16 +869,10 @@  bail:
 				break;
 			FORCEINTON;
 		}
-		listsetvar(varlist.list, VEXPORT|VSTACK);
 		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:
diff --git a/src/var.c b/src/var.c
index cc6f7f2..c877f68 100644
--- a/src/var.c
+++ b/src/var.c
@@ -116,6 +116,7 @@  STATIC struct var *vartab[VTABSIZE];
 STATIC struct var **hashvar(const char *);
 STATIC int vpcmp(const void *, const void *);
 STATIC struct var **findvar(struct var **, const char *);
+static void mklocal(char *name, int flags);
 
 /*
  * Initialize the varable symbol tables and import the environment
@@ -325,7 +326,10 @@  listsetvar(struct strlist *list, int flags)
 		return;
 	INTOFF;
 	do {
-		setvareq(lp->text, flags);
+		if (flags & VLOCAL)
+			mklocal(lp->text, flags & ~VLOCAL);
+		else
+			setvareq(lp->text, flags);
 	} while ((lp = lp->next));
 	INTON;
 }
@@ -475,7 +479,7 @@  localcmd(int argc, char **argv)
 
 	argv = argptr;
 	while ((name = *argv++) != NULL) {
-		mklocal(name);
+		mklocal(name, 0);
 	}
 	return 0;
 }
@@ -488,7 +492,7 @@  localcmd(int argc, char **argv)
  * "-" as a special case.
  */
 
-void mklocal(char *name)
+static void mklocal(char *name, int flags)
 {
 	struct localvar *lvp;
 	struct var **vpp;
@@ -509,16 +513,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/src/var.h b/src/var.h
index 872e2db..60eac4b 100644
--- a/src/var.h
+++ b/src/var.h
@@ -50,6 +50,7 @@ 
 #define VNOFUNC		0x40	/* don't call the callback function */
 #define VNOSET		0x80	/* do not set variable - just readonly test */
 #define VNOSAVE		0x100	/* when text is on the heap before setvareq */
+#define VLOCAL		0x200	/* Tell listsetvar to call mklocal */
 
 
 struct var {
@@ -151,7 +152,6 @@  char **listvars(int, int, char ***);
 int showvars(const char *, int, int);
 int exportcmd(int, char **);
 int localcmd(int, char **);
-void mklocal(char *);
 struct localvar_list *pushlocalvars(void);
 void poplocalvars(int);
 void unwindlocalvars(struct localvar_list *stop);