aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-26 19:22:34 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-26 20:33:51 +0200
commitb8ab27bf53797ec98c7c7d1c80a5a0a062f273a5 (patch)
tree14362945f3667333a676736f5d689c3330735050
parentcf3a796dd1dfe53f7d67507f7f4d5c05cc7ebc8d (diff)
downloadbusybox-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.c57
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
9170static struct localvar *localvars; 9170struct localvar_list {
9171 struct localvar_list *next;
9172 struct localvar *lv;
9173};
9174
9175static 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;
9176static void 9181static void
9177poplocalvars(void) 9182poplocalvars(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 */
9221static void
9222pushlocalvars(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
9204static int 9234static int
9205evalfun(struct funcnode *func, int argc, char **argv, int flags) 9235evalfun(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