diff options
Diffstat (limited to 'src/var.c')
-rw-r--r-- | src/var.c | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/src/var.c b/src/var.c index 2737fb1..de1a5f5 100644 --- a/src/var.c +++ b/src/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; } |