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 /shell | |
| 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>
Diffstat (limited to 'shell')
| -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 |
