From cfd91eac0732da8ece012ca4ab051d928a85c9dd Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Thu, 8 Jan 2015 21:39:26 +0000
Subject: Rearrange context saving.
Variables are now associated with the module that declares them, being
initialised and saved/restored there. However, as many variables are
used for communication between modules, many of them are set in multiple
places, so the assignment is ambiguous.
---
Src/Zle/compcore.c | 4 +-
Src/Zle/compctl.c | 8 +-
Src/Zle/textobjects.c | 4 +-
Src/Zle/zle_tricky.c | 24 ++--
Src/builtin.c | 8 +-
Src/context.c | 116 ++++++++++++++++++
Src/exec.c | 8 +-
Src/hist.c | 88 +++++++++++++-
Src/init.c | 4 +-
Src/lex.c | 321 ++++++++++----------------------------------------
Src/parse.c | 83 ++++++++++++-
Src/signals.c | 4 +-
Src/zsh.h | 65 ++++++++++
Src/zsh.mdd | 3 +-
14 files changed, 441 insertions(+), 299 deletions(-)
create mode 100644 Src/context.c
(limited to 'Src')
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index f5056058a..000f9da2a 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -1524,7 +1524,7 @@ set_comp_sep(void)
ol = zlemetaline;
addedx = 1;
noerrs = 1;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
/*
* tl is the length of the temporary string including
@@ -1673,7 +1673,7 @@ set_comp_sep(void)
inpop();
errflag &= ~ERRFLAG_ERROR;
noerrs = ne;
- lexrestore();
+ zcontext_restore();
wb = owb;
we = owe;
zlemetaline = ol;
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index 2a80e6c84..43dd4e2a9 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -2795,7 +2795,7 @@ sep_comp_string(char *ss, char *s, int noffs)
* get the words we have to expand. */
addedx = 1;
noerrs = 1;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
tmp = (char *) zhalloc(tl = sl + 3 + strlen(s));
strcpy(tmp, ss);
@@ -2849,7 +2849,7 @@ sep_comp_string(char *ss, char *s, int noffs)
inpop();
errflag &= ~ERRFLAG_ERROR;
noerrs = ne;
- lexrestore();
+ zcontext_restore();
wb = owb;
we = owe;
zlemetacs = ocs;
@@ -3707,7 +3707,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
/* Put the string in the lexer buffer and call the lexer to *
* get the words we have to expand. */
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
tmpbuf = (char *)zhalloc(strlen(cc->str) + 5);
sprintf(tmpbuf, "foo %s", cc->str); /* KLUDGE! */
@@ -3726,7 +3726,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
strinend();
inpop();
errflag &= ~ERRFLAG_ERROR;
- lexrestore();
+ zcontext_restore();
/* Fine, now do full expansion. */
prefork(foo, 0);
if (!errflag) {
diff --git a/Src/Zle/textobjects.c b/Src/Zle/textobjects.c
index 37d2c0ad9..9b3277a97 100644
--- a/Src/Zle/textobjects.c
+++ b/Src/Zle/textobjects.c
@@ -241,7 +241,7 @@ selectargument(UNUSED(char **args))
addedx = 0;
noerrs = 1;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ACTIVE;
linein = zlegetline(&ll, &cs);
zlemetall = ll;
@@ -277,7 +277,7 @@ selectargument(UNUSED(char **args))
inpop();
errflag &= ~ERRFLAG_ERROR;
noerrs = ne;
- lexrestore();
+ zcontext_restore();
zlemetacs = ocs;
wb = owb;
we = owe;
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index 950c22f38..f18ad170e 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -698,7 +698,7 @@ docomplete(int lst)
freeheap();
/* Save the lexer state, in case the completion code uses the lexer *
* somewhere (e.g. when processing a compctl -s flag). */
- lexsave();
+ zcontext_save();
if (inwhat == IN_ENV)
lincmd = 0;
if (s) {
@@ -868,7 +868,7 @@ docomplete(int lst)
} else
ret = 1;
/* Reset the lexer state, pop the heap. */
- lexrestore();
+ zcontext_restore();
popheap();
dat[0] = lst;
@@ -1164,7 +1164,7 @@ get_comp_string(void)
varname = NULL;
insubscr = 0;
clwpos = -1;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
inpush(dupstrspace(linptr), 0, NULL);
strinbeg(0);
@@ -1422,7 +1422,7 @@ get_comp_string(void)
zlemetall -= parend;
zlemetaline[zlemetall + addedx] = '\0';
}
- lexrestore();
+ zcontext_restore();
tt = NULL;
goto start;
}
@@ -1496,12 +1496,12 @@ get_comp_string(void)
if (tmp) {
tmp = NULL;
linptr = zlemetaline;
- lexrestore();
+ zcontext_restore();
addedx = 0;
goto start;
}
noaliases = ona;
- lexrestore();
+ zcontext_restore();
return NULL;
}
@@ -2151,7 +2151,7 @@ get_comp_string(void)
offs = boffs;
}
}
- lexrestore();
+ zcontext_restore();
return (char *)s;
}
@@ -2791,7 +2791,7 @@ doexpandhist(void)
expanding = 1;
excs = zlemetacs;
zlemetall = zlemetacs = 0;
- lexsave();
+ zcontext_save();
/* We push ol as it will remain unchanged */
inpush(ol, 0, NULL);
strinbeg(1);
@@ -2803,7 +2803,7 @@ doexpandhist(void)
} while (tok != ENDINPUT && tok != LEXERR);
while (!lexstop)
hgetc();
- /* We have to save errflags because it's reset in lexrestore. Since *
+ /* We have to save errflags because it's reset in zcontext_restore. Since *
* noerrs was set to 1 errflag is true if there was a habort() which *
* means that the expanded string is unusable. */
err = errflag;
@@ -2811,7 +2811,7 @@ doexpandhist(void)
noaliases = ona;
strinend();
inpop();
- lexrestore();
+ zcontext_restore();
expanding = 0;
if (!err) {
@@ -2910,7 +2910,7 @@ getcurcmd(void)
int curlincmd;
char *s = NULL;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
metafy_line();
inpush(dupstrspace(zlemetaline), 0, NULL);
@@ -2934,7 +2934,7 @@ getcurcmd(void)
inpop();
errflag &= ~ERRFLAG_ERROR;
unmetafy_line();
- lexrestore();
+ zcontext_restore();
return s;
}
diff --git a/Src/builtin.c b/Src/builtin.c
index d2108264f..8abe728db 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -6102,7 +6102,7 @@ bin_test(char *name, char **argv, UNUSED(Options ops), int func)
}
}
- lexsave();
+ zcontext_save();
testargs = argv;
tok = NULLTOK;
condlex = testlex;
@@ -6112,16 +6112,16 @@ bin_test(char *name, char **argv, UNUSED(Options ops), int func)
if (errflag) {
errflag &= ~ERRFLAG_ERROR;
- lexrestore();
+ zcontext_restore();
return 1;
}
if (!prog || tok == LEXERR) {
zwarnnam(name, tokstr ? "parse error" : "argument expected");
- lexrestore();
+ zcontext_restore();
return 1;
}
- lexrestore();
+ zcontext_restore();
if (*curtestarg) {
zwarnnam(name, "too many arguments");
diff --git a/Src/context.c b/Src/context.c
new file mode 100644
index 000000000..bd8d191bf
--- /dev/null
+++ b/Src/context.c
@@ -0,0 +1,116 @@
+/*
+ * context.c - context save and restore
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1992-1997 Paul Falstad
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Paul Falstad or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Paul Falstad and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Paul Falstad and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Paul Falstad and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+/*
+ * This short file provides a home for the stack of saved contexts.
+ * The actions for saving and restoring are encapsulated within
+ * individual modules.
+ */
+
+#include "zsh.mdh"
+#include "context.pro"
+
+struct context_stack {
+ struct context_stack *next;
+
+ struct hist_stack hist_stack;
+ struct lex_stack lex_stack;
+ struct parse_stack parse_stack;
+};
+
+static struct context_stack *cstack;
+
+/* save some or all of current context */
+
+/**/
+mod_export void
+zcontext_save_partial(int parts)
+{
+ struct context_stack *cs;
+
+ cs = (struct context_stack *)malloc(sizeof(struct context_stack));
+
+ if (parts & ZCONTEXT_HIST) {
+ hist_context_save(&cs->hist_stack, !cstack);
+ }
+ if (parts & ZCONTEXT_LEX) {
+ lex_context_save(&cs->lex_stack, !cstack);
+ }
+ if (parts & ZCONTEXT_PARSE) {
+ parse_context_save(&cs->parse_stack, !cstack);
+ }
+
+ cs->next = cstack;
+ cstack = cs;
+}
+
+/* save context in full */
+
+/**/
+mod_export void
+zcontext_save(void)
+{
+ zcontext_save_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
+}
+
+/* restore context or part thereof */
+
+/**/
+mod_export void
+zcontext_restore_partial(int parts)
+{
+ struct context_stack *cs = cstack;
+
+ DPUTS(!cstack, "BUG: zcontext_restore() without zcontext_save()");
+
+ queue_signals();
+ cstack = cstack->next;
+
+ if (parts & ZCONTEXT_HIST) {
+ hist_context_restore(&cs->hist_stack, !cstack);
+ }
+ if (parts & ZCONTEXT_LEX) {
+ lex_context_restore(&cs->lex_stack, !cstack);
+ }
+ if (parts & ZCONTEXT_PARSE) {
+ parse_context_restore(&cs->parse_stack, !cstack);
+ }
+
+ free(cs);
+
+ unqueue_signals();
+}
+
+/* restore full context */
+
+/**/
+mod_export void
+zcontext_restore(void)
+{
+ zcontext_restore_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
+}
diff --git a/Src/exec.c b/Src/exec.c
index ab9291024..7b6495113 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -217,7 +217,7 @@ parse_string(char *s, int reset_lineno)
Eprog p;
zlong oldlineno;
- lexsave();
+ zcontext_save();
inpush(s, INP_LINENO, NULL);
strinbeg(0);
oldlineno = lineno;
@@ -229,7 +229,7 @@ parse_string(char *s, int reset_lineno)
lastval = 1;
strinend();
inpop();
- lexrestore();
+ zcontext_restore();
return p;
}
@@ -3349,9 +3349,9 @@ execcmd(Estate state, int input, int output, int how, int last1)
* The copy uses the wordcode parsing area, so save and
* restore state.
*/
- lexsave();
+ zcontext_save();
redir_prog = eccopyredirs(&s);
- lexrestore();
+ zcontext_restore();
} else
redir_prog = NULL;
diff --git a/Src/hist.c b/Src/hist.c
index e65d78bfd..447f00e84 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -222,6 +222,85 @@ static int histsave_stack_pos = 0;
static zlong histfile_linect;
+/* save history context */
+
+/**/
+void
+hist_context_save(struct hist_stack *hs, int toplevel)
+{
+ if (toplevel) {
+ /* top level, make this version visible to ZLE */
+ zle_chline = chline;
+ /* ensure line stored is NULL-terminated */
+ if (hptr)
+ *hptr = '\0';
+ }
+ hs->histactive = histactive;
+ hs->histdone = histdone;
+ hs->stophist = stophist;
+ hs->hline = chline;
+ hs->hptr = hptr;
+ hs->chwords = chwords;
+ hs->chwordlen = chwordlen;
+ hs->chwordpos = chwordpos;
+ hs->hwgetword = hwgetword;
+ hs->hgetc = hgetc;
+ hs->hungetc = hungetc;
+ hs->hwaddc = hwaddc;
+ hs->hwbegin = hwbegin;
+ hs->hwend = hwend;
+ hs->addtoline = addtoline;
+ hs->hlinesz = hlinesz;
+ /*
+ * We save and restore the command stack with history
+ * as it's visible to the user interactively, so if
+ * we're preserving history state we'll continue to
+ * show the current set of commands from input.
+ */
+ hs->cstack = cmdstack;
+ hs->csp = cmdsp;
+
+ stophist = 0;
+ chline = NULL;
+ hptr = NULL;
+ histactive = 0;
+ cmdstack = (unsigned char *)zalloc(CMDSTACKSZ);
+ cmdsp = 0;
+}
+
+/**/
+void
+hist_context_restore(const struct hist_stack *hs, int toplevel)
+{
+ if (toplevel) {
+ /* Back to top level: don't need special ZLE value */
+ DPUTS(hs->hline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
+ zle_chline = NULL;
+ }
+ histactive = hs->histactive;
+ histdone = hs->histdone;
+ stophist = hs->stophist;
+ chline = hs->hline;
+ hptr = hs->hptr;
+ chwords = hs->chwords;
+ chwordlen = hs->chwordlen;
+ chwordpos = hs->chwordpos;
+ hwgetword = hs->hwgetword;
+ hgetc = hs->hgetc;
+ hungetc = hs->hungetc;
+ hwaddc = hs->hwaddc;
+ hwbegin = hs->hwbegin;
+ hwend = hs->hwend;
+ addtoline = hs->addtoline;
+ hlinesz = hs->hlinesz;
+ if (cmdstack)
+ zfree(cmdstack, CMDSTACKSZ);
+ cmdstack = hs->cstack;
+ cmdsp = hs->csp;
+}
+
+/* restore history context */
+
/* add a character to the current history word */
static void
@@ -815,6 +894,11 @@ strinbeg(int dohist)
strin++;
hbegin(dohist);
lexinit();
+ /*
+ * Also initialise some variables owned by the parser but
+ * used for communication between the parser and lexer.
+ */
+ init_parse_status();
}
/* done reading a string */
@@ -2992,7 +3076,7 @@ bufferwords(LinkList list, char *buf, int *index, int flags)
opts[RCQUOTES] = 0;
addedx = 0;
noerrs = 1;
- lexsave();
+ zcontext_save();
lexflags = flags | LEXFLAGS_ACTIVE;
/*
* Are we handling comments?
@@ -3189,7 +3273,7 @@ bufferwords(LinkList list, char *buf, int *index, int flags)
errflag &= ~ERRFLAG_ERROR;
nocomments = onc;
noerrs = ne;
- lexrestore();
+ zcontext_restore();
zlemetacs = ocs;
zlemetall = oll;
wb = owb;
diff --git a/Src/init.c b/Src/init.c
index 080fc8561..e7d86feac 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -107,7 +107,7 @@ loop(int toplevel, int justonce)
pushheap();
if (!toplevel)
- lexsave();
+ zcontext_save();
for (;;) {
freeheap();
if (stophist == 3) /* re-entry via preprompt() */
@@ -227,7 +227,7 @@ loop(int toplevel, int justonce)
}
err = errflag;
if (!toplevel)
- lexrestore();
+ zcontext_restore();
popheap();
if (err)
diff --git a/Src/lex.c b/Src/lex.c
index d440f3d70..69441b28d 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -203,263 +203,64 @@ static int dbparens;
static int len = 0, bsiz = 256;
static char *bptr;
-struct lexstack {
- struct lexstack *next;
-
- int incmdpos;
- int incond;
- int incasepat;
- int dbparens;
- int isfirstln;
- int isfirstch;
- int histactive;
- int histdone;
- int lexflags;
- int stophist;
- int hlinesz;
- char *hline;
- char *hptr;
- enum lextok tok;
- int isnewlin;
- char *tokstr;
- char *zshlextext;
- char *bptr;
- int bsiz;
- int len;
- int lex_add_raw;
- char *tokstr_raw;
- char *bptr_raw;
- int bsiz_raw;
- int len_raw;
- short *chwords;
- int chwordlen;
- int chwordpos;
- int hwgetword;
- int lexstop;
- struct heredocs *hdocs;
- int (*hgetc) _((void));
- void (*hungetc) _((int));
- void (*hwaddc) _((int));
- void (*hwbegin) _((int));
- void (*hwend) _((void));
- void (*addtoline) _((int));
-
- int eclen, ecused, ecnpats;
- Wordcode ecbuf;
- Eccstr ecstrs;
- int ecsoffs, ecssub, ecnfunc;
-
- unsigned char *cstack;
- int csp;
- zlong toklineno;
-};
-
-static struct lexstack *lstack = NULL;
-
-/* save the context or parts thereof */
-
-/* is this a hack or what? */
+/* save lexical context */
/**/
-mod_export void
-lexsave_partial(int parts)
-{
- struct lexstack *ls;
-
- ls = (struct lexstack *)malloc(sizeof(struct lexstack));
-
- if (parts & ZCONTEXT_LEX) {
- ls->incmdpos = incmdpos;
- ls->incond = incond;
- ls->incasepat = incasepat;
- ls->dbparens = dbparens;
- ls->isfirstln = isfirstln;
- ls->isfirstch = isfirstch;
- ls->lexflags = lexflags;
-
- ls->tok = tok;
- ls->isnewlin = isnewlin;
- ls->tokstr = tokstr;
- ls->zshlextext = zshlextext;
- ls->bptr = bptr;
- ls->bsiz = bsiz;
- ls->len = len;
- ls->lex_add_raw = lex_add_raw;
- ls->tokstr_raw = tokstr_raw;
- ls->bptr_raw = bptr_raw;
- ls->bsiz_raw = bsiz_raw;
- ls->len_raw = len_raw;
- ls->lexstop = lexstop;
- ls->toklineno = toklineno;
-
- tokstr = zshlextext = bptr = NULL;
- bsiz = 256;
- tokstr_raw = bptr_raw = NULL;
- bsiz_raw = len_raw = lex_add_raw = 0;
-
- inredir = 0;
- }
- if (parts & ZCONTEXT_HIST) {
- if (!lstack) {
- /* top level, make this version visible to ZLE */
- zle_chline = chline;
- /* ensure line stored is NULL-terminated */
- if (hptr)
- *hptr = '\0';
- }
- ls->histactive = histactive;
- ls->histdone = histdone;
- ls->stophist = stophist;
- ls->hline = chline;
- ls->hptr = hptr;
- ls->chwords = chwords;
- ls->chwordlen = chwordlen;
- ls->chwordpos = chwordpos;
- ls->hwgetword = hwgetword;
- ls->hgetc = hgetc;
- ls->hungetc = hungetc;
- ls->hwaddc = hwaddc;
- ls->hwbegin = hwbegin;
- ls->hwend = hwend;
- ls->addtoline = addtoline;
- ls->hlinesz = hlinesz;
- /*
- * We save and restore the command stack with history
- * as it's visible to the user interactively, so if
- * we're preserving history state we'll continue to
- * show the current set of commands from input.
- */
- ls->cstack = cmdstack;
- ls->csp = cmdsp;
-
- stophist = 0;
- chline = NULL;
- hptr = NULL;
- histactive = 0;
- cmdstack = (unsigned char *)zalloc(CMDSTACKSZ);
- cmdsp = 0;
- }
- if (parts & ZCONTEXT_PARSE) {
- ls->hdocs = hdocs;
- ls->eclen = eclen;
- ls->ecused = ecused;
- ls->ecnpats = ecnpats;
- ls->ecbuf = ecbuf;
- ls->ecstrs = ecstrs;
- ls->ecsoffs = ecsoffs;
- ls->ecssub = ecssub;
- ls->ecnfunc = ecnfunc;
- ecbuf = NULL;
- hdocs = NULL;
- }
-
- ls->next = lstack;
- lstack = ls;
-}
-
-/* save context in full */
-
-/**/
-mod_export void
-lexsave(void)
-{
- lexsave_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
-}
-
-/* restore context or part therefore */
-
-/**/
-mod_export void
-lexrestore_partial(int parts)
+void
+lex_context_save(struct lex_stack *ls, int toplevel)
{
- struct lexstack *ln = lstack;
-
- DPUTS(!lstack, "BUG: lexrestore() without lexsave()");
-
- queue_signals();
- lstack = lstack->next;
-
- if (parts & ZCONTEXT_LEX) {
- incmdpos = ln->incmdpos;
- incond = ln->incond;
- incasepat = ln->incasepat;
- dbparens = ln->dbparens;
- isfirstln = ln->isfirstln;
- isfirstch = ln->isfirstch;
- lexflags = ln->lexflags;
- tok = ln->tok;
- isnewlin = ln->isnewlin;
- tokstr = ln->tokstr;
- zshlextext = ln->zshlextext;
- bptr = ln->bptr;
- bsiz = ln->bsiz;
- len = ln->len;
- lex_add_raw = ln->lex_add_raw;
- tokstr_raw = ln->tokstr_raw;
- bptr_raw = ln->bptr_raw;
- bsiz_raw = ln->bsiz_raw;
- len_raw = ln->len_raw;
- lexstop = ln->lexstop;
- toklineno = ln->toklineno;
- }
-
- if (parts & ZCONTEXT_HIST) {
- if (!lstack) {
- /* Back to top level: don't need special ZLE value */
- DPUTS(ln->hline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
- zle_chline = NULL;
- }
- histactive = ln->histactive;
- histdone = ln->histdone;
- stophist = ln->stophist;
- chline = ln->hline;
- hptr = ln->hptr;
- chwords = ln->chwords;
- chwordlen = ln->chwordlen;
- chwordpos = ln->chwordpos;
- hwgetword = ln->hwgetword;
- hgetc = ln->hgetc;
- hungetc = ln->hungetc;
- hwaddc = ln->hwaddc;
- hwbegin = ln->hwbegin;
- hwend = ln->hwend;
- addtoline = ln->addtoline;
- hlinesz = ln->hlinesz;
- if (cmdstack)
- zfree(cmdstack, CMDSTACKSZ);
- cmdstack = ln->cstack;
- cmdsp = ln->csp;
- }
-
- if (parts & ZCONTEXT_PARSE) {
- if (ecbuf)
- zfree(ecbuf, eclen);
-
- hdocs = ln->hdocs;
- eclen = ln->eclen;
- ecused = ln->ecused;
- ecnpats = ln->ecnpats;
- ecbuf = ln->ecbuf;
- ecstrs = ln->ecstrs;
- ecsoffs = ln->ecsoffs;
- ecssub = ln->ecssub;
- ecnfunc = ln->ecnfunc;
-
- errflag &= ~ERRFLAG_ERROR;
- }
-
- free(ln);
-
- unqueue_signals();
+ (void)toplevel;
+
+ ls->dbparens = dbparens;
+ ls->isfirstln = isfirstln;
+ ls->isfirstch = isfirstch;
+ ls->lexflags = lexflags;
+
+ ls->tok = tok;
+ ls->tokstr = tokstr;
+ ls->zshlextext = zshlextext;
+ ls->bptr = bptr;
+ ls->bsiz = bsiz;
+ ls->len = len;
+ ls->lex_add_raw = lex_add_raw;
+ ls->tokstr_raw = tokstr_raw;
+ ls->bptr_raw = bptr_raw;
+ ls->bsiz_raw = bsiz_raw;
+ ls->len_raw = len_raw;
+ ls->lexstop = lexstop;
+ ls->toklineno = toklineno;
+
+ tokstr = zshlextext = bptr = NULL;
+ bsiz = 256;
+ tokstr_raw = bptr_raw = NULL;
+ bsiz_raw = len_raw = lex_add_raw = 0;
}
-/* complete restore context */
+/* restore lexical context */
/**/
mod_export void
-lexrestore(void)
+lex_context_restore(const struct lex_stack *ls, int toplevel)
{
- lexrestore_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
+ (void)toplevel;
+
+ dbparens = ls->dbparens;
+ isfirstln = ls->isfirstln;
+ isfirstch = ls->isfirstch;
+ lexflags = ls->lexflags;
+ tok = ls->tok;
+ tokstr = ls->tokstr;
+ zshlextext = ls->zshlextext;
+ bptr = ls->bptr;
+ bsiz = ls->bsiz;
+ len = ls->len;
+ lex_add_raw = ls->lex_add_raw;
+ tokstr_raw = ls->tokstr_raw;
+ bptr_raw = ls->bptr_raw;
+ bsiz_raw = ls->bsiz_raw;
+ len_raw = ls->len_raw;
+ lexstop = ls->lexstop;
+ toklineno = ls->toklineno;
}
/**/
@@ -634,9 +435,7 @@ initlextabs(void)
void
lexinit(void)
{
- incond = incasepat = nocorrect =
- infor = dbparens = lexstop = 0;
- incmdpos = 1;
+ nocorrect = dbparens = lexstop = 0;
tok = ENDINPUT;
}
@@ -1725,7 +1524,7 @@ parsestrnoerr(char *s)
{
int l = strlen(s), err;
- lexsave();
+ zcontext_save();
untokenize(s);
inpush(dupstring(s), 0, NULL);
strinbeg(0);
@@ -1737,7 +1536,7 @@ parsestrnoerr(char *s)
strinend();
inpop();
DPUTS(cmdsp, "BUG: parsestr: cmdstack not empty.");
- lexrestore();
+ zcontext_restore();
return err;
}
@@ -1756,7 +1555,7 @@ parse_subscript(char *s, int sub, int endchar)
if (!*s || *s == endchar)
return 0;
- lexsave();
+ zcontext_save();
untokenize(t = dupstring(s));
inpush(t, 0, NULL);
strinbeg(0);
@@ -1776,7 +1575,7 @@ parse_subscript(char *s, int sub, int endchar)
strinend();
inpop();
DPUTS(cmdsp, "BUG: parse_subscript: cmdstack not empty.");
- lexrestore();
+ zcontext_restore();
return s;
}
@@ -1794,7 +1593,7 @@ parse_subst_string(char *s)
if (!*s || !strcmp(s, nulstring))
return 0;
- lexsave();
+ zcontext_save();
untokenize(s);
inpush(dupstring(s), 0, NULL);
strinbeg(0);
@@ -1807,7 +1606,7 @@ parse_subst_string(char *s)
strinend();
inpop();
DPUTS(cmdsp, "BUG: parse_subst_string: cmdstack not empty.");
- lexrestore();
+ zcontext_restore();
/* Keep any interrupt error status */
errflag = err | (errflag & ERRFLAG_INT);
if (ctok == LEXERR) {
@@ -1817,7 +1616,7 @@ parse_subst_string(char *s)
#ifdef DEBUG
/*
* Historical note: we used to check here for olen (the value of len
- * before lexrestore()) == l, but that's not necessarily the case if
+ * before zcontext_restore()) == l, but that's not necessarily the case if
* we stripped an RCQUOTE.
*/
if (ctok != STRING || (errflag && !noerrs)) {
@@ -2047,7 +1846,7 @@ skipcomm(void)
new_len = len;
new_bsiz = bsiz;
- lexsave_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
+ zcontext_save_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
} else {
/*
* Set up for nested command subsitution, however
@@ -2063,7 +1862,7 @@ skipcomm(void)
new_len = len_raw;
new_bsiz = bsiz_raw;
- lexsave_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
+ zcontext_save_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
}
tokstr_raw = new_tokstr;
bsiz_raw = new_bsiz;
@@ -2090,7 +1889,7 @@ skipcomm(void)
*/
new_lexstop = lexstop;
- lexrestore_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
+ zcontext_restore_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
if (lex_add_raw) {
/*
diff --git a/Src/parse.c b/Src/parse.c
index fa37ca3d9..0b54a904d 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -31,7 +31,7 @@
#include "parse.pro"
/* != 0 if we are about to read a command word */
-
+
/**/
mod_export int incmdpos;
@@ -242,6 +242,67 @@ int ecsoffs, ecssub, ecnfunc;
#define EC_DOUBLE_THRESHOLD 32768
#define EC_INCREMENT 1024
+/* save parse context */
+
+/**/
+void
+parse_context_save(struct parse_stack *ps, int toplevel)
+{
+ (void)toplevel;
+
+ ps->incmdpos = incmdpos;
+ ps->aliasspaceflag = aliasspaceflag;
+ ps->incond = incond;
+ ps->inredir = inredir;
+ ps->incasepat = incasepat;
+ ps->isnewlin = isnewlin;
+ ps->infor = infor;
+
+ ps->hdocs = hdocs;
+ ps->eclen = eclen;
+ ps->ecused = ecused;
+ ps->ecnpats = ecnpats;
+ ps->ecbuf = ecbuf;
+ ps->ecstrs = ecstrs;
+ ps->ecsoffs = ecsoffs;
+ ps->ecssub = ecssub;
+ ps->ecnfunc = ecnfunc;
+ ecbuf = NULL;
+ hdocs = NULL;
+}
+
+/* restore parse context */
+
+/**/
+void
+parse_context_restore(const struct parse_stack *ps, int toplevel)
+{
+ (void)toplevel;
+
+ if (ecbuf)
+ zfree(ecbuf, eclen);
+
+ incmdpos = ps->incmdpos;
+ aliasspaceflag = ps->aliasspaceflag;
+ incond = ps->incond;
+ inredir = ps->inredir;
+ incasepat = ps->incasepat;
+ incasepat = ps->incasepat;
+ isnewlin = ps->isnewlin;
+ infor = ps->infor;
+
+ hdocs = ps->hdocs;
+ eclen = ps->eclen;
+ ecused = ps->ecused;
+ ecnpats = ps->ecnpats;
+ ecbuf = ps->ecbuf;
+ ecstrs = ps->ecstrs;
+ ecsoffs = ps->ecsoffs;
+ ecssub = ps->ecssub;
+ ecnfunc = ps->ecnfunc;
+
+ errflag &= ~ERRFLAG_ERROR;
+}
/* Adjust pointers in here-doc structs. */
@@ -359,6 +420,21 @@ ecstrcode(char *s)
} while (0)
+/**/
+mod_export void
+init_parse_status(void)
+{
+ /*
+ * These variables are currently declared by the parser, so we
+ * initialise them here. Possibly they are more naturally declared
+ * by the lexical anaylser; however, as they are used for signalling
+ * between the two it's a bit ambiguous. We clear them when
+ * using the lexical analyser for strings as well as here.
+ */
+ incasepat = incond = inredir = infor = 0;
+ incmdpos = 1;
+}
+
/* Initialise wordcode buffer. */
/**/
@@ -373,6 +449,8 @@ init_parse(void)
ecsoffs = ecnpats = 0;
ecssub = 0;
ecnfunc = 0;
+
+ init_parse_status();
}
/* Build eprog. */
@@ -539,9 +617,8 @@ parse_list(void)
int c = 0;
tok = ENDINPUT;
- incmdpos = 1;
- zshlex();
init_parse();
+ zshlex();
par_list(&c);
if (tok != ENDINPUT) {
clear_hdocs();
diff --git a/Src/signals.c b/Src/signals.c
index 899f1217b..3950ad1a2 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -1210,7 +1210,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
intrap++;
*sigtr |= ZSIG_IGNORED;
- lexsave();
+ zcontext_save();
/* execsave will save the old trap_return and trap_state */
execsave();
breaks = retflag = 0;
@@ -1265,7 +1265,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
new_trap_return = trap_return;
execrestore();
- lexrestore();
+ zcontext_restore();
if (new_trap_state == TRAP_STATE_FORCE_RETURN &&
/* zero return from function isn't special */
diff --git a/Src/zsh.h b/Src/zsh.h
index 475b7824f..8fb4f977a 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2691,6 +2691,71 @@ struct sortelt {
typedef struct sortelt *SortElt;
+/*********************************************************/
+/* Structures to save and restore for individual modules */
+/*********************************************************/
+
+/* History */
+struct hist_stack {
+ int histactive;
+ int histdone;
+ int stophist;
+ int hlinesz;
+ char *hline;
+ char *hptr;
+ short *chwords;
+ int chwordlen;
+ int chwordpos;
+ int hwgetword;
+ int (*hgetc) _((void));
+ void (*hungetc) _((int));
+ void (*hwaddc) _((int));
+ void (*hwbegin) _((int));
+ void (*hwend) _((void));
+ void (*addtoline) _((int));
+ unsigned char *cstack;
+ int csp;
+};
+
+/* Lexical analyser */
+struct lex_stack {
+ int dbparens;
+ int isfirstln;
+ int isfirstch;
+ int lexflags;
+ enum lextok tok;
+ char *tokstr;
+ char *zshlextext;
+ char *bptr;
+ int bsiz;
+ int len;
+ int lex_add_raw;
+ char *tokstr_raw;
+ char *bptr_raw;
+ int bsiz_raw;
+ int len_raw;
+ int lexstop;
+ zlong toklineno;
+};
+
+/* Parser */
+struct parse_stack {
+ struct heredocs *hdocs;
+
+ int incmdpos;
+ int aliasspaceflag;
+ int incond;
+ int inredir;
+ int incasepat;
+ int isnewlin;
+ int infor;
+
+ int eclen, ecused, ecnpats;
+ Wordcode ecbuf;
+ Eccstr ecstrs;
+ int ecsoffs, ecssub, ecnfunc;
+};
+
/************************/
/* Flags to casemodifiy */
/************************/
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index 9a8c923f9..f0379d2d1 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -9,7 +9,8 @@ alwayslink=1
# autobins not specified because of alwayslink
-objects="builtin.o compat.o cond.o exec.o glob.o hashtable.o hashnameddir.o \
+objects="builtin.o compat.o cond.o context.o \
+exec.o glob.o hashtable.o hashnameddir.o \
hist.o init.o input.o jobs.o lex.o linklist.o loop.o math.o \
mem.o module.o options.o params.o parse.o pattern.o prompt.o signals.o \
signames.o sort.o string.o subst.o text.o utils.o watch.o"
--
cgit 1.4.1