diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-26 19:22:34 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-26 20:33:51 +0200 |
commit | b8ab27bf53797ec98c7c7d1c80a5a0a062f273a5 (patch) | |
tree | 14362945f3667333a676736f5d689c3330735050 | |
parent | cf3a796dd1dfe53f7d67507f7f4d5c05cc7ebc8d (diff) | |
download | busybox-w32-b8ab27bf53797ec98c7c7d1c80a5a0a062f273a5.tar.gz busybox-w32-b8ab27bf53797ec98c7c7d1c80a5a0a062f273a5.tar.bz2 busybox-w32-b8ab27bf53797ec98c7c7d1c80a5a0a062f273a5.zip |
ash: [VAR] Add localvars nesting
Upstream commit:
Date: Mon, 24 May 2010 15:31:27 +0800
[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: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/shell/ash.c b/shell/ash.c index 915e86167..8bef78546 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -9167,7 +9167,12 @@ optschanged(void) | |||
9167 | #endif | 9167 | #endif |
9168 | } | 9168 | } |
9169 | 9169 | ||
9170 | static struct localvar *localvars; | 9170 | struct localvar_list { |
9171 | struct localvar_list *next; | ||
9172 | struct localvar *lv; | ||
9173 | }; | ||
9174 | |||
9175 | static struct localvar_list *localvar_stack; | ||
9171 | 9176 | ||
9172 | /* | 9177 | /* |
9173 | * Called after a function returns. | 9178 | * Called after a function returns. |
@@ -9176,11 +9181,19 @@ static struct localvar *localvars; | |||
9176 | static void | 9181 | static void |
9177 | poplocalvars(void) | 9182 | poplocalvars(void) |
9178 | { | 9183 | { |
9179 | struct localvar *lvp; | 9184 | struct localvar_list *ll; |
9185 | struct localvar *lvp, *next; | ||
9180 | struct var *vp; | 9186 | struct var *vp; |
9181 | 9187 | ||
9182 | while ((lvp = localvars) != NULL) { | 9188 | INT_OFF; |
9183 | localvars = lvp->next; | 9189 | ll = localvar_stack; |
9190 | localvar_stack = ll->next; | ||
9191 | |||
9192 | next = ll->lv; | ||
9193 | free(ll); | ||
9194 | |||
9195 | while ((lvp = next) != NULL) { | ||
9196 | next = lvp->next; | ||
9184 | vp = lvp->vp; | 9197 | vp = lvp->vp; |
9185 | TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-")); | 9198 | TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-")); |
9186 | if (vp == NULL) { /* $- saved */ | 9199 | if (vp == NULL) { /* $- saved */ |
@@ -9199,19 +9212,34 @@ poplocalvars(void) | |||
9199 | } | 9212 | } |
9200 | free(lvp); | 9213 | free(lvp); |
9201 | } | 9214 | } |
9215 | INT_ON; | ||
9216 | } | ||
9217 | |||
9218 | /* | ||
9219 | * Create a new localvar environment. | ||
9220 | */ | ||
9221 | static void | ||
9222 | pushlocalvars(void) | ||
9223 | { | ||
9224 | struct localvar_list *ll; | ||
9225 | |||
9226 | INT_OFF; | ||
9227 | ll = ckzalloc(sizeof(*ll)); | ||
9228 | /*ll->lv = NULL; - zalloc did it */ | ||
9229 | ll->next = localvar_stack; | ||
9230 | localvar_stack = ll; | ||
9231 | INT_ON; | ||
9202 | } | 9232 | } |
9203 | 9233 | ||
9204 | static int | 9234 | static int |
9205 | evalfun(struct funcnode *func, int argc, char **argv, int flags) | 9235 | evalfun(struct funcnode *func, int argc, char **argv, int flags) |
9206 | { | 9236 | { |
9207 | volatile struct shparam saveparam; | 9237 | volatile struct shparam saveparam; |
9208 | struct localvar *volatile savelocalvars; | ||
9209 | struct jmploc *volatile savehandler; | 9238 | struct jmploc *volatile savehandler; |
9210 | struct jmploc jmploc; | 9239 | struct jmploc jmploc; |
9211 | int e; | 9240 | int e; |
9212 | 9241 | ||
9213 | saveparam = shellparam; | 9242 | saveparam = shellparam; |
9214 | savelocalvars = localvars; | ||
9215 | savehandler = exception_handler; | 9243 | savehandler = exception_handler; |
9216 | e = setjmp(jmploc.loc); | 9244 | e = setjmp(jmploc.loc); |
9217 | if (e) { | 9245 | if (e) { |
@@ -9219,7 +9247,6 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) | |||
9219 | } | 9247 | } |
9220 | INT_OFF; | 9248 | INT_OFF; |
9221 | exception_handler = &jmploc; | 9249 | exception_handler = &jmploc; |
9222 | localvars = NULL; | ||
9223 | shellparam.malloced = 0; | 9250 | shellparam.malloced = 0; |
9224 | func->count++; | 9251 | func->count++; |
9225 | funcnest++; | 9252 | funcnest++; |
@@ -9230,13 +9257,13 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) | |||
9230 | shellparam.optind = 1; | 9257 | shellparam.optind = 1; |
9231 | shellparam.optoff = -1; | 9258 | shellparam.optoff = -1; |
9232 | #endif | 9259 | #endif |
9260 | pushlocalvars(); | ||
9233 | evaltree(func->n.narg.next, flags & EV_TESTED); | 9261 | evaltree(func->n.narg.next, flags & EV_TESTED); |
9262 | poplocalvars(); | ||
9234 | funcdone: | 9263 | funcdone: |
9235 | INT_OFF; | 9264 | INT_OFF; |
9236 | funcnest--; | 9265 | funcnest--; |
9237 | freefunc(func); | 9266 | freefunc(func); |
9238 | poplocalvars(); | ||
9239 | localvars = savelocalvars; | ||
9240 | freeparam(&shellparam); | 9267 | freeparam(&shellparam); |
9241 | shellparam = saveparam; | 9268 | shellparam = saveparam; |
9242 | exception_handler = savehandler; | 9269 | exception_handler = savehandler; |
@@ -9265,7 +9292,7 @@ mklocal(char *name) | |||
9265 | * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x | 9292 | * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x |
9266 | * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x | 9293 | * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x |
9267 | */ | 9294 | */ |
9268 | lvp = localvars; | 9295 | lvp = localvar_stack->lv; |
9269 | while (lvp) { | 9296 | while (lvp) { |
9270 | if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) { | 9297 | if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) { |
9271 | if (eq) | 9298 | if (eq) |
@@ -9310,8 +9337,8 @@ mklocal(char *name) | |||
9310 | } | 9337 | } |
9311 | } | 9338 | } |
9312 | lvp->vp = vp; | 9339 | lvp->vp = vp; |
9313 | lvp->next = localvars; | 9340 | lvp->next = localvar_stack->lv; |
9314 | localvars = lvp; | 9341 | localvar_stack->lv = lvp; |
9315 | ret: | 9342 | ret: |
9316 | INT_ON; | 9343 | INT_ON; |
9317 | } | 9344 | } |
@@ -9324,7 +9351,7 @@ localcmd(int argc UNUSED_PARAM, char **argv) | |||
9324 | { | 9351 | { |
9325 | char *name; | 9352 | char *name; |
9326 | 9353 | ||
9327 | if (!funcnest) | 9354 | if (!localvar_stack) |
9328 | ash_msg_and_raise_error("not in a function"); | 9355 | ash_msg_and_raise_error("not in a function"); |
9329 | 9356 | ||
9330 | argv = argptr; | 9357 | argv = argptr; |
@@ -13570,6 +13597,10 @@ reset(void) | |||
13570 | /* from redir.c: */ | 13597 | /* from redir.c: */ |
13571 | while (redirlist) | 13598 | while (redirlist) |
13572 | popredir(/*drop:*/ 0, /*restore:*/ 0); | 13599 | popredir(/*drop:*/ 0, /*restore:*/ 0); |
13600 | |||
13601 | /* from var.c: */ | ||
13602 | while (localvar_stack) | ||
13603 | poplocalvars(); | ||
13573 | } | 13604 | } |
13574 | 13605 | ||
13575 | #if PROFILE | 13606 | #if PROFILE |