aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-05-24 15:31:27 +0800
committermaximilian attems <max@stro.at>2011-06-03 18:04:47 +0200
commit85712e2d1287222f27f470e04cf49394cfdcf81f (patch)
treeb8fe17116af27ca25d45f7f6dfd624d1ac79a26f
parent9d2bc6ea26d8b14fab0d78288db96cc06cef4545 (diff)
downloadklibc-85712e2d1287222f27f470e04cf49394cfdcf81f.tar.gz
[klibc] [VAR] Add localvars nesting
This patch adds localvars nesting infrastructure so we can reuse the localvars mechanism for command evaluation. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: maximilian attems <max@stro.at>
-rw-r--r--usr/dash/eval.c7
-rw-r--r--usr/dash/var.c50
-rw-r--r--usr/dash/var.h1
3 files changed, 47 insertions, 11 deletions
diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index 65562f1a8354c..e3737e9e76268 100644
--- a/usr/dash/eval.c
+++ b/usr/dash/eval.c
@@ -928,20 +928,17 @@ STATIC int
evalfun(struct funcnode *func, int argc, char **argv, int flags)
{
volatile struct shparam saveparam;
- struct localvar *volatile savelocalvars;
struct jmploc *volatile savehandler;
struct jmploc jmploc;
int e;
saveparam = shellparam;
- savelocalvars = localvars;
if ((e = setjmp(jmploc.loc))) {
goto funcdone;
}
INTOFF;
savehandler = handler;
handler = &jmploc;
- localvars = NULL;
shellparam.malloc = 0;
func->count++;
funcnest++;
@@ -950,13 +947,13 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
shellparam.p = argv + 1;
shellparam.optind = 1;
shellparam.optoff = -1;
+ pushlocalvars();
evaltree(&func->n, flags & EV_TESTED);
+ poplocalvars();
funcdone:
INTOFF;
funcnest--;
freefunc(func);
- poplocalvars();
- localvars = savelocalvars;
freeparam(&shellparam);
shellparam = saveparam;
handler = savehandler;
diff --git a/usr/dash/var.c b/usr/dash/var.c
index 2737fb116bb47..de1a5f54ea4ae 100644
--- a/usr/dash/var.c
+++ b/usr/dash/var.c
@@ -64,7 +64,12 @@
#define VTABSIZE 39
-struct localvar *localvars;
+struct localvar_list {
+ struct localvar_list *next;
+ struct localvar *lv;
+};
+
+MKINIT struct localvar_list *localvar_stack;
const char defpathvar[] =
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
@@ -139,6 +144,11 @@ INIT {
p = 0;
setpwd(p, 0);
}
+
+RESET {
+ while (localvar_stack)
+ poplocalvars();
+}
#endif
@@ -446,6 +456,9 @@ localcmd(int argc, char **argv)
{
char *name;
+ if (!localvar_stack)
+ sh_error("not in a function");
+
argv = argptr;
while ((name = *argv++) != NULL) {
mklocal(name);
@@ -497,8 +510,8 @@ mklocal(char *name)
}
}
lvp->vp = vp;
- lvp->next = localvars;
- localvars = lvp;
+ lvp->next = localvar_stack->lv;
+ localvar_stack->lv = lvp;
INTON;
}
@@ -511,11 +524,19 @@ mklocal(char *name)
void
poplocalvars(void)
{
- struct localvar *lvp;
+ struct localvar_list *ll;
+ struct localvar *lvp, *next;
struct var *vp;
- while ((lvp = localvars) != NULL) {
- localvars = lvp->next;
+ INTOFF;
+ ll = localvar_stack;
+ localvar_stack = ll->next;
+
+ next = ll->lv;
+ ckfree(ll);
+
+ while ((lvp = next) != NULL) {
+ next = lvp->next;
vp = lvp->vp;
TRACE(("poplocalvar %s", vp ? vp->text : "-"));
if (vp == NULL) { /* $- saved */
@@ -534,6 +555,23 @@ poplocalvars(void)
}
ckfree(lvp);
}
+ INTON;
+}
+
+
+/*
+ * Create a new localvar environment.
+ */
+void pushlocalvars(void)
+{
+ struct localvar_list *ll;
+
+ INTOFF;
+ ll = ckmalloc(sizeof(*ll));
+ ll->lv = NULL;
+ ll->next = localvar_stack;
+ localvar_stack = ll;
+ INTON;
}
diff --git a/usr/dash/var.h b/usr/dash/var.h
index e4e2cff56242d..32b0dde25cd61 100644
--- a/usr/dash/var.h
+++ b/usr/dash/var.h
@@ -139,6 +139,7 @@ char **listvars(int, int, char ***);
int showvars(const char *, int, int);
int exportcmd(int, char **);
int localcmd(int, char **);
+void pushlocalvars(void);
void poplocalvars(void);
int unsetcmd(int, char **);
int unsetvar(const char *);