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>
This commit is contained in:
parent
cf3a796dd1
commit
b8ab27bf53
57
shell/ash.c
57
shell/ash.c
@ -9167,7 +9167,12 @@ optschanged(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct localvar *localvars;
|
struct localvar_list {
|
||||||
|
struct localvar_list *next;
|
||||||
|
struct localvar *lv;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct localvar_list *localvar_stack;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called after a function returns.
|
* Called after a function returns.
|
||||||
@ -9176,11 +9181,19 @@ static struct localvar *localvars;
|
|||||||
static void
|
static void
|
||||||
poplocalvars(void)
|
poplocalvars(void)
|
||||||
{
|
{
|
||||||
struct localvar *lvp;
|
struct localvar_list *ll;
|
||||||
|
struct localvar *lvp, *next;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
|
|
||||||
while ((lvp = localvars) != NULL) {
|
INT_OFF;
|
||||||
localvars = lvp->next;
|
ll = localvar_stack;
|
||||||
|
localvar_stack = ll->next;
|
||||||
|
|
||||||
|
next = ll->lv;
|
||||||
|
free(ll);
|
||||||
|
|
||||||
|
while ((lvp = next) != NULL) {
|
||||||
|
next = lvp->next;
|
||||||
vp = lvp->vp;
|
vp = lvp->vp;
|
||||||
TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
|
TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
|
||||||
if (vp == NULL) { /* $- saved */
|
if (vp == NULL) { /* $- saved */
|
||||||
@ -9199,19 +9212,34 @@ poplocalvars(void)
|
|||||||
}
|
}
|
||||||
free(lvp);
|
free(lvp);
|
||||||
}
|
}
|
||||||
|
INT_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new localvar environment.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pushlocalvars(void)
|
||||||
|
{
|
||||||
|
struct localvar_list *ll;
|
||||||
|
|
||||||
|
INT_OFF;
|
||||||
|
ll = ckzalloc(sizeof(*ll));
|
||||||
|
/*ll->lv = NULL; - zalloc did it */
|
||||||
|
ll->next = localvar_stack;
|
||||||
|
localvar_stack = ll;
|
||||||
|
INT_ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
evalfun(struct funcnode *func, int argc, char **argv, int flags)
|
evalfun(struct funcnode *func, int argc, char **argv, int flags)
|
||||||
{
|
{
|
||||||
volatile struct shparam saveparam;
|
volatile struct shparam saveparam;
|
||||||
struct localvar *volatile savelocalvars;
|
|
||||||
struct jmploc *volatile savehandler;
|
struct jmploc *volatile savehandler;
|
||||||
struct jmploc jmploc;
|
struct jmploc jmploc;
|
||||||
int e;
|
int e;
|
||||||
|
|
||||||
saveparam = shellparam;
|
saveparam = shellparam;
|
||||||
savelocalvars = localvars;
|
|
||||||
savehandler = exception_handler;
|
savehandler = exception_handler;
|
||||||
e = setjmp(jmploc.loc);
|
e = setjmp(jmploc.loc);
|
||||||
if (e) {
|
if (e) {
|
||||||
@ -9219,7 +9247,6 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
|
|||||||
}
|
}
|
||||||
INT_OFF;
|
INT_OFF;
|
||||||
exception_handler = &jmploc;
|
exception_handler = &jmploc;
|
||||||
localvars = NULL;
|
|
||||||
shellparam.malloced = 0;
|
shellparam.malloced = 0;
|
||||||
func->count++;
|
func->count++;
|
||||||
funcnest++;
|
funcnest++;
|
||||||
@ -9230,13 +9257,13 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
|
|||||||
shellparam.optind = 1;
|
shellparam.optind = 1;
|
||||||
shellparam.optoff = -1;
|
shellparam.optoff = -1;
|
||||||
#endif
|
#endif
|
||||||
|
pushlocalvars();
|
||||||
evaltree(func->n.narg.next, flags & EV_TESTED);
|
evaltree(func->n.narg.next, flags & EV_TESTED);
|
||||||
|
poplocalvars();
|
||||||
funcdone:
|
funcdone:
|
||||||
INT_OFF;
|
INT_OFF;
|
||||||
funcnest--;
|
funcnest--;
|
||||||
freefunc(func);
|
freefunc(func);
|
||||||
poplocalvars();
|
|
||||||
localvars = savelocalvars;
|
|
||||||
freeparam(&shellparam);
|
freeparam(&shellparam);
|
||||||
shellparam = saveparam;
|
shellparam = saveparam;
|
||||||
exception_handler = savehandler;
|
exception_handler = savehandler;
|
||||||
@ -9265,7 +9292,7 @@ mklocal(char *name)
|
|||||||
* x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
|
* x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
|
||||||
* x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
|
* x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
|
||||||
*/
|
*/
|
||||||
lvp = localvars;
|
lvp = localvar_stack->lv;
|
||||||
while (lvp) {
|
while (lvp) {
|
||||||
if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
|
if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
|
||||||
if (eq)
|
if (eq)
|
||||||
@ -9310,8 +9337,8 @@ mklocal(char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
lvp->vp = vp;
|
lvp->vp = vp;
|
||||||
lvp->next = localvars;
|
lvp->next = localvar_stack->lv;
|
||||||
localvars = lvp;
|
localvar_stack->lv = lvp;
|
||||||
ret:
|
ret:
|
||||||
INT_ON;
|
INT_ON;
|
||||||
}
|
}
|
||||||
@ -9324,7 +9351,7 @@ localcmd(int argc UNUSED_PARAM, char **argv)
|
|||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (!funcnest)
|
if (!localvar_stack)
|
||||||
ash_msg_and_raise_error("not in a function");
|
ash_msg_and_raise_error("not in a function");
|
||||||
|
|
||||||
argv = argptr;
|
argv = argptr;
|
||||||
@ -13570,6 +13597,10 @@ reset(void)
|
|||||||
/* from redir.c: */
|
/* from redir.c: */
|
||||||
while (redirlist)
|
while (redirlist)
|
||||||
popredir(/*drop:*/ 0, /*restore:*/ 0);
|
popredir(/*drop:*/ 0, /*restore:*/ 0);
|
||||||
|
|
||||||
|
/* from var.c: */
|
||||||
|
while (localvar_stack)
|
||||||
|
poplocalvars();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PROFILE
|
#if PROFILE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user