Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: PATCH: fix command substitution parsing



On Wed, 07 Jan 2015 16:48:36 +0000
Peter Stephenson <p.stephenson@xxxxxxxxxxx> wrote:
> I did this by allowing lexsave() and lexrestore() to save and restore
> different layers separately.  This is made a bit hairy by the fact that
> zsh doesn't really have layers.  However, it looks like I've basically
> got away with saving and restoring the parser and lexer while keeping
> history and input continuous.
>...
> I'll probably follow up on those changes and turn lexsave() and
> lexrestore() into context save and restore dispatching to different
> modules, which is sort of starting to look like a respectable
> implementation.

I'm a bit sorry I thought of this; I can't see it leading to any good.
Still...

This creates a separate module context.c with zcontext_save() and
zcontext_restore() and makes each of hist.c, lex.c and parse.c
responsible for its own variables, initialisation as well as save and
restore.  The problem is the notion of "its own variables" isn't very
well defined with the not very well defined interface between the
modules.  I've gone with the approach that where the variable is defined
is where it belongs.

This exposed various duplications in initialising some of the key
variables, in particular incmdpos, which I've tried to tame.  The
function init_parse_status(), although a fairly insignificant function,
illustrates the problem:  the variables "belong" to parse.c so are
initialised there but also need initialising for lexical analysis not
tied to syntactic parsing.  So there's some duplication, but it is at
least in one well-defined place with a comment saying so.

"inredir" was set to 0 on saving the context.  I strongly suspect that
what was really needed was setting to 0 with the other similar variables
when initialising the context nested (in C lexical scope) inside the one
being saved, so I've done that.  However, this raises questions of
whether other variables being reset on saving the context should also be
handled like that.

Also, a couple of variables including inredir weren't being saved and
restored at all, which isn't safe for asynchronous use by traps, so I've
saved them.  I haven't checked generally for this; this was just the key
set defined at the top of parse.c.

Some variables can possibly now become statics, although not many ---
the parse.c ones were the ones used for signalling with lex.c, so remain
global, and the lex.c ones could already be static if appropriate
because the save and restore were done there.  To be checked.

Although this tidies up save and restore, it would be more pukka to pass
down variables on the stack.  I don't think that's really feasible
without switching to an object orientated language.  Only Mikael's
theoretical infinite number of novices with typewriters can do that...

And so on.

And this doesn't even fix anything ever reported.

pws


From 6822e89da93051d07222af52ba5253d1854b2b27 Mon Sep 17 00:00:00 2001
From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Date: Thu, 8 Jan 2015 21:39:26 +0000
Subject: [PATCH] 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

diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index f505605..000f9da 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 2a80e6c..43dd4e2 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 37d2c0a..9b3277a 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 950c22f..f18ad17 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 d210826..8abe728 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 0000000..bd8d191
--- /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 ab92910..7b64951 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 e65d78b..447f00e 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 080fc85..e7d86fe 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 d440f3d..69441b2 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 fa37ca3..0b54a90 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 899f121..3950ad1 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 475b782..8fb4f97 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 9a8c923..f0379d2 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"
-- 
2.1.0




Messages sorted by: Reverse Date, Date, Thread, Author