From 85a698b8ec0c68ce6bf130dbe909ca5ff129c6d9 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 7 Aug 2012 18:29:02 +0000 Subject: YAMAMOTO Takashi: 30599: don't use replacement wcwidth if not ISO-10646 --- Src/zsh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Src/zsh.h') diff --git a/Src/zsh.h b/Src/zsh.h index cc3a67008..afe22f059 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2678,7 +2678,7 @@ typedef wint_t convchar_t; #define MB_METASTRWIDTH(str) mb_metastrlen(str, 1) #define MB_METASTRLEN2(str, widthp) mb_metastrlen(str, widthp) -#ifdef BROKEN_WCWIDTH +#if defined(BROKEN_WCWIDTH) && defined(__STDC_ISO_10646__) #define WCWIDTH(wc) mk_wcwidth(wc) #else #define WCWIDTH(wc) wcwidth(wc) -- cgit v1.2.3 From 97cf64a7ee90e7835f723b369fa1f7a35dfdb202 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 16 Aug 2012 19:12:26 +0000 Subject: Hiramatsu Yoshifumi: 30621 patch-ab (from NetBSD pkgsrc):compilation on __INTERIX --- ChangeLog | 7 ++++++- Src/zsh.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'Src/zsh.h') diff --git a/ChangeLog b/ChangeLog index 41172b1c1..fe9154528 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-08-16 Peter Stephenson + + * Hiramatsu Yoshifumi: 30621 patch-ab (from NetBSD pkgsrc): + compilation on __INTERIX + 2012-08-16 Peter Stephenson * 30619: Doc/Zsh/builtins.yo, Src/builtin.c, @@ -61,5 +66,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5696 $ +* $Revision: 1.5697 $ ***************************************************** diff --git a/Src/zsh.h b/Src/zsh.h index afe22f059..946102528 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2135,6 +2135,7 @@ struct ttyinfo { #endif }; +#ifndef __INTERIX /* defines for whether tabs expand to spaces */ #if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H) #define SGTTYFLAG shttyinfo.tio.c_oflag @@ -2152,6 +2153,7 @@ struct ttyinfo { # endif # endif # endif +#endif /* flags for termflags */ -- cgit v1.2.3 From 6f3ff6b653ca5e6f528bc46ec6295cb6d263a9fd Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 21 Aug 2012 18:03:01 +0000 Subject: 30633: "functions -T" only traces marked function, not called functions --- ChangeLog | 9 ++++++++- Doc/Zsh/builtins.yo | 25 ++++++++++++++----------- Src/builtin.c | 8 ++++++-- Src/exec.c | 15 +++++++++++++-- Src/hashtable.c | 7 ++++--- Src/options.c | 2 +- Src/subst.c | 2 ++ Src/zsh.h | 1 + 8 files changed, 49 insertions(+), 20 deletions(-) (limited to 'Src/zsh.h') diff --git a/ChangeLog b/ChangeLog index a2b415d83..78e4f92f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-08-21 Peter Stephenson + + * 30633: Doc/Zsh/builtins.yo, Src/builtin.c, Src/exec.c, + Src/hashtable.c, Src/options.c, Src/subst.c, Src/zsh.h: + "functions -T" traces only marked function and not called + functions unless also marked. + 2012-08-20 Peter Stephenson * Stepan Koltsov: 30634: Functions/Misc/zmv: use (q-) quoting @@ -88,5 +95,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5704 $ +* $Revision: 1.5705 $ ***************************************************** diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 894f65a3e..0e5353633 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -620,7 +620,7 @@ Equivalent to tt(typeset -E), except that options irrelevant to floating point numbers are not permitted. ) findex(functions) -xitem(tt(functions) [ {tt(PLUS())|tt(-)}tt(UXkmtuz) ] [ var(name) ... ]) +xitem(tt(functions) [ {tt(PLUS())|tt(-)}tt(UXkmtTuz) ] [ var(name) ... ]) xitem(tt(functions -M) var(mathfn) [ var(min) [ var(max) [ var(shellfn) ] ] ]) xitem(tt(functions -M) [ tt(-m) var(pattern) ... ]) item(tt(functions +M) [ tt(-m) ] var(mathfn))( @@ -1555,6 +1555,7 @@ export. Setting the value using the scalar version causes a split on all separators (which cannot be quoted). It is possible to use the same two tied variables with a different separator character in which case the variables remain joined as before but the separator is changed. +This flag has a different meaning when used with tt(-f); see below. The tt(-g) (global) flag is treated specially: it means that any resulting parameter will not be restricted to local scope. Note that this @@ -1652,16 +1653,18 @@ shown. ) item(tt(-f))( The names refer to functions rather than parameters. No assignments -can be made, and the only other valid flags are tt(-t), tt(-k), tt(-u), -tt(-U) and tt(-z). The flag tt(-t) turns on execution tracing for this -function. The tt(-u) and tt(-U) flags cause the function to be -marked for autoloading; tt(-U) also causes alias expansion to be -suppressed when the function is loaded. The tt(fpath) parameter -will be searched to find the function definition when the function -is first referenced; see noderef(Functions). The tt(-k) and tt(-z) flags -make the function be loaded using ksh-style or zsh-style autoloading -respectively. If neither is given, the setting of the KSH_AUTOLOAD option -determines how the function is loaded. +can be made, and the only other valid flags are tt(-t), tt(-T), tt(-k), +tt(-u), tt(-U) and tt(-z). The flag tt(-t) turns on execution tracing +for this function; the flag tt(-T) does the same, but turns off tracing +on any function called from the present one, unless that function also +has the tt(-t) or tt(-T) flag. The tt(-u) and tt(-U) flags cause the +function to be marked for autoloading; tt(-U) also causes alias +expansion to be suppressed when the function is loaded. The tt(fpath) +parameter will be searched to find the function definition when the +function is first referenced; see noderef(Functions). The tt(-k) and +tt(-z) flags make the function be loaded using ksh-style or zsh-style +autoloading respectively. If neither is given, the setting of the +KSH_AUTOLOAD option determines how the function is loaded. ) item(tt(-h))( Hide: only useful for special parameters (those marked `' in the table in diff --git a/Src/builtin.c b/Src/builtin.c index ce7d6a563..3925edd10 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -46,7 +46,7 @@ static struct builtin builtins[] = BUILTIN(".", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL), BUILTIN(":", BINF_PSPECIAL, bin_true, 0, -1, 0, NULL, NULL), BUILTIN("alias", BINF_MAGICEQUALS | BINF_PLUSOPTS, bin_alias, 0, -1, 0, "Lgmrs", NULL), - BUILTIN("autoload", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "ktUwXz", "u"), + BUILTIN("autoload", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "ktTUwXz", "u"), BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL), BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL), BUILTIN("bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL), @@ -72,7 +72,7 @@ static struct builtin builtins[] = BUILTIN("fc", 0, bin_fc, 0, -1, BIN_FC, "aAdDe:EfiIlmnpPrRt:W", NULL), BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL), BUILTIN("float", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "E:%F:%HL:%R:%Z:%ghlprtux", "E"), - BUILTIN("functions", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "kmMtuUz", NULL), + BUILTIN("functions", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "kmMtTuUz", NULL), BUILTIN("getln", 0, bin_read, 0, -1, 0, "ecnAlE", "zr"), BUILTIN("getopts", 0, bin_getopts, 2, -1, 0, NULL, NULL), BUILTIN("hash", BINF_MAGICEQUALS, bin_hash, 0, -1, 0, "Ldfmrv", NULL), @@ -2685,6 +2685,10 @@ bin_functions(char *name, char **argv, Options ops, int func) on |= PM_TAGGED; else if (OPT_PLUS(ops,'t')) off |= PM_TAGGED; + if (OPT_MINUS(ops,'T')) + on |= PM_TAGGED_LOCAL; + else if (OPT_PLUS(ops,'T')) + on |= PM_TAGGED_LOCAL; if (OPT_MINUS(ops,'z')) { on |= PM_ZSHSTORED; off |= PM_KSHSTORED; diff --git a/Src/exec.c b/Src/exec.c index 6ebc9c014..a40838f91 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4484,11 +4484,12 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) int *oldpipestats = NULL; char saveopts[OPT_SIZE], *oldscriptname = scriptname; char *name = shfunc->node.nam; - int flags = shfunc->node.flags; + int flags = shfunc->node.flags, ooflags; char *fname = dupstring(name); int obreaks, saveemulation, savesticky_emulation, restore_sticky; Eprog prog; struct funcstack fstack; + static int oflags; #ifdef MAX_FUNCTION_DEPTH static int funcdepth; #endif @@ -4547,8 +4548,17 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) } else restore_sticky = 0; - if (flags & PM_TAGGED) + if (flags & (PM_TAGGED|PM_TAGGED_LOCAL)) opts[XTRACE] = 1; + else if (oflags & PM_TAGGED_LOCAL) + opts[XTRACE] = 0; + ooflags = oflags; + /* + * oflags is static, because we compare it on the next recursive + * call. Hence also we maintain ooflags for restoring the previous + * value of oflags after the call. + */ + oflags = flags; opts[PRINTEXITVALUE] = 0; if (doshargs) { LinkNode node; @@ -4633,6 +4643,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) optcind = oldoptcind; zoptind = oldzoptind; scriptname = oldscriptname; + oflags = ooflags; if (restore_sticky) { /* diff --git a/Src/hashtable.c b/Src/hashtable.c index be71a1cc9..b472e40b9 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -923,12 +923,13 @@ printshfuncnode(HashNode hn, int printflags) printf("%c undefined\n\t", hashchar); else t = getpermtext(f->funcdef, NULL, 1); - if (f->node.flags & PM_TAGGED) + if (f->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL)) printf("%c traced\n\t", hashchar); if (!t) { - char *fopt = "Utkz"; + char *fopt = "UtTkz"; int flgs[] = { - PM_UNALIASED, PM_TAGGED, PM_KSHSTORED, PM_ZSHSTORED, 0 + PM_UNALIASED, PM_TAGGED, PM_TAGGED_LOCAL, + PM_KSHSTORED, PM_ZSHSTORED, 0 }; int fl;; diff --git a/Src/options.c b/Src/options.c index c6db75372..609c28fd1 100644 --- a/Src/options.c +++ b/Src/options.c @@ -532,7 +532,7 @@ emulate(const char *zsh_name, int fully) * close enough. */ Shfunc shf = (Shfunc)shfunctab->getnode(shfunctab, funcstack->name); - if (shf && (shf->node.flags & PM_TAGGED)) { + if (shf && (shf->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL))) { /* Tracing is on, so set xtrace */ opts[XTRACE] = 1; } diff --git a/Src/subst.c b/Src/subst.c index 932f41287..b0c15d048 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2314,6 +2314,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) val = dyncat(val, "-readonly"); if (f & PM_TAGGED) val = dyncat(val, "-tag"); + if (f & PM_TAGGED_LOCAL) + val = dyncat(val, "-tag_local"); if (f & PM_EXPORTED) val = dyncat(val, "-export"); if (f & PM_UNIQUE) diff --git a/Src/zsh.h b/Src/zsh.h index 946102528..b9f2846f7 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1554,6 +1554,7 @@ struct tieddata { #define PM_HIDE (1<<14) /* Special behaviour hidden by local */ #define PM_HIDEVAL (1<<15) /* Value not shown in `typeset' commands */ #define PM_TIED (1<<16) /* array tied to colon-path or v.v. */ +#define PM_TAGGED_LOCAL (1<<16) /* (function): non-recursive PM_TAGGED */ #define PM_KSHSTORED (1<<17) /* function stored in ksh form */ #define PM_ZSHSTORED (1<<18) /* function stored in zsh form */ -- cgit v1.2.3 From 13b8a25456f038e0dbf7daf187cb0e5b9b9558c9 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 23 Aug 2012 19:19:26 +0000 Subject: Jun T.: 30640: MacOS doesn't define __STDC_ISO_10646__ but we need the replacement wcwidth function anyway --- ChangeLog | 8 +++++++- Src/compat.c | 4 ++-- Src/zsh.h | 9 ++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'Src/zsh.h') diff --git a/ChangeLog b/ChangeLog index f391bce0a..d1c87a57f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-08-23 Peter Stephenson + + * Jun T: 30640 (plus additional comment): Src/zsh.h, + Src/compat.c: MacOS doesn't define __STDC_ISO_10646__ but we + need the replacement wcwidth() anyway. + 2012-08-23 Peter Stephenson * Aaron Schrab: 30636: Completion/Unix/Command/_telnet: @@ -108,5 +114,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5709 $ +* $Revision: 1.5710 $ ***************************************************** diff --git a/Src/compat.c b/Src/compat.c index 6d08dab94..cc4e876da 100644 --- a/Src/compat.c +++ b/Src/compat.c @@ -630,7 +630,7 @@ strtoul(nptr, endptr, base) #endif /* HAVE_STRTOUL */ /**/ -#if defined(BROKEN_WCWIDTH) && defined(__STDC_ISO_10646__) +#if defined(BROKEN_WCWIDTH) && (defined(__STDC_ISO_10646__) || defined(__APPLE__)) /* * This is an implementation of wcwidth() and wcswidth() (defined in @@ -949,5 +949,5 @@ int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n) #endif /* 0 */ /**/ -#endif /* BROKEN_WCWIDTH && __STDC_ISO_10646__ */ +#endif /* BROKEN_WCWIDTH && (__STDC_ISO_10646__ || __APPLE__) */ diff --git a/Src/zsh.h b/Src/zsh.h index b9f2846f7..e20838249 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2681,7 +2681,14 @@ typedef wint_t convchar_t; #define MB_METASTRWIDTH(str) mb_metastrlen(str, 1) #define MB_METASTRLEN2(str, widthp) mb_metastrlen(str, widthp) -#if defined(BROKEN_WCWIDTH) && defined(__STDC_ISO_10646__) +/* + * We replace broken implementations with one that uses Unicode + * characters directly as wide characters. In principle this is only + * likely to work if __STDC_ISO_10646__ is defined, since that's pretty + * much what the definition tells us. However, we happen to know this + * works on MacOS which doesn't define that. + */ +#if defined(BROKEN_WCWIDTH) && (defined(__STDC_ISO_10646__) || defined(__APPLE__)) #define WCWIDTH(wc) mk_wcwidth(wc) #else #define WCWIDTH(wc) wcwidth(wc) -- cgit v1.2.3 From eb562c9f2c8af43957b023325119d912fa3897b3 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 5 Oct 2012 21:35:05 +0000 Subject: 30715: use enum lextok for variables containing lexical tokens --- ChangeLog | 8 +++++++- Src/Zle/zle_tricky.c | 15 +++++++++------ Src/init.c | 2 +- Src/lex.c | 27 +++++++++++++++++---------- Src/parse.c | 47 +++++++++++++++++++++++++---------------------- Src/subst.c | 14 +++++++------- Src/zsh.h | 2 +- 7 files changed, 67 insertions(+), 48 deletions(-) (limited to 'Src/zsh.h') diff --git a/ChangeLog b/ChangeLog index de241b8ad..ebfcfea66 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-10-05 Peter Stephenson + + * 30715: Src/init.c, Src/lex.c, Src/parse.c, Src/subst.c, + Src/zsh.h, Src/Zle/zle_tricky.c: use a named enum for + lexical tokens. + 2012-10-03 Peter Stephenson * users/17305: Doc/Zsh/expn.yo: fix documentation for ordering @@ -217,5 +223,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5733 $ +* $Revision: 1.5734 $ ***************************************************** diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 6fa887a1e..78a9fa490 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -1071,7 +1071,8 @@ has_real_token(const char *s) static char * get_comp_string(void) { - int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins, ia, parct, varq = 0; + enum lextok t0, tt0; + int i, j, k, cp, rd, sl, ocs, ins, oins, ia, parct, varq = 0; int ona = noaliases; /* * Index of word being considered @@ -1152,7 +1153,8 @@ get_comp_string(void) lexflags = LEXFLAGS_ZLE; inpush(dupstrspace(linptr), 0, NULL); strinbeg(0); - wordpos = tt0 = cp = rd = ins = oins = linarr = parct = ia = redirpos = 0; + wordpos = cp = rd = ins = oins = linarr = parct = ia = redirpos = 0; + tt0 = NULLTOK; /* This loop is possibly the wrong way to do this. It goes through * * the previously massaged command line using the lexer. It stores * @@ -1238,7 +1240,8 @@ get_comp_string(void) if (tt) break; /* Otherwise reset the variables we are collecting data in. */ - wordpos = tt0 = cp = rd = ins = redirpos = 0; + wordpos = cp = rd = ins = redirpos = 0; + tt0 = NULLTOK; } if (lincmd && (tok == STRING || tok == FOR || tok == FOREACH || tok == SELECT || tok == REPEAT || tok == CASE)) { @@ -1251,7 +1254,7 @@ get_comp_string(void) if (wordpos != redirpos) wordpos = redirpos = 0; } - if (!lexflags && !tt0) { + if (!lexflags && tt0 == NULLTOK) { /* This is done when the lexer reached the word the cursor is on. */ tt = tokstr ? dupstring(tokstr) : NULL; @@ -1352,7 +1355,7 @@ get_comp_string(void) (sl - 1) : (zlemetacs_qsub - wb)]); } } while (tok != LEXERR && tok != ENDINPUT && - (tok != SEPER || (lexflags && !tt0))); + (tok != SEPER || (lexflags && tt0 == NULLTOK))); /* Calculate the number of words stored in the clwords array. */ clwnum = (tt || !wordpos) ? wordpos : wordpos - 1; zsfree(clwords[clwnum]); @@ -1388,7 +1391,7 @@ get_comp_string(void) if (inwhat == IN_MATH) s = NULL; - else if (!t0 || t0 == ENDINPUT) { + else if (t0 == NULLTOK || t0 == ENDINPUT) { /* There was no word (empty line). */ s = ztrdup(""); we = wb = zlemetacs; diff --git a/Src/init.c b/Src/init.c index 6f14943e1..d1e2bed3c 100644 --- a/Src/init.c +++ b/Src/init.c @@ -149,7 +149,7 @@ loop(int toplevel, int justonce) continue; } if (hend(prog)) { - int toksav = tok; + enum lextok toksav = tok; non_empty = 1; if (toplevel && diff --git a/Src/lex.c b/Src/lex.c index 1cf3611c9..2c738c005 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -42,7 +42,7 @@ char *zshlextext; /**/ mod_export char *tokstr; /**/ -mod_export int tok; +mod_export enum lextok tok; /**/ mod_export int tokfd; @@ -207,7 +207,7 @@ struct lexstack { int hlinesz; char *hline; char *hptr; - int tok; + enum lextok tok; int isnewlin; char *tokstr; char *zshlextext; @@ -470,6 +470,10 @@ ctxtlex(void) case DINBRACK: incmdpos = 0; break; + + default: + /* nothing to do, keep compiler happy */ + break; } if (tok != DINPAR) infor = tok == FOR ? 2 : 0; @@ -698,11 +702,12 @@ isnumglob(void) } /**/ -static int +static enum lextok gettok(void) { int c, d; - int peekfd = -1, peek; + int peekfd = -1; + enum lextok peek; beginning: tokstr = NULL; @@ -1007,12 +1012,13 @@ gettok(void) */ /**/ -static int +static enum lextok gettokstr(int c, int sub) { int bct = 0, pct = 0, brct = 0, fdpar = 0; int intpos = 1, in_brace_param = 0; - int peek, inquote, unmatched = 0; + int inquote, unmatched = 0; + enum lextok peek; #ifdef DEBUG int ocmdsp = cmdsp; #endif @@ -1692,6 +1698,7 @@ parse_subst_string(char *s) { int c, l = strlen(s), err; char *ptr; + enum lextok ctok; if (!*s || !strcmp(s, nulstring)) return 0; @@ -1703,14 +1710,14 @@ parse_subst_string(char *s) bptr = tokstr = s; bsiz = l + 1; c = hgetc(); - c = gettokstr(c, 1); + ctok = gettokstr(c, 1); err = errflag; strinend(); inpop(); DPUTS(cmdsp, "BUG: parse_subst_string: cmdstack not empty."); lexrestore(); errflag = err; - if (c == LEXERR) { + if (ctok == LEXERR) { untokenize(s); return 1; } @@ -1720,9 +1727,9 @@ parse_subst_string(char *s) * before lexrestore()) == l, but that's not necessarily the case if * we stripped an RCQUOTE. */ - if (c != STRING || (errflag && !noerrs)) { + if (ctok != STRING || (errflag && !noerrs)) { fprintf(stderr, "Oops. Bug in parse_subst_string: %s\n", - errflag ? "errflag" : "c != STRING"); + errflag ? "errflag" : "ctok != STRING"); fflush(stderr); untokenize(s); return 1; diff --git a/Src/parse.c b/Src/parse.c index e4d038b6e..8d2878cd7 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -666,7 +666,8 @@ par_sublist(int *complex) *complex |= c; if (tok == DBAR || tok == DAMPER) { - int qtok = tok, sl; + enum lextok qtok = tok; + int sl; cmdpush(tok == DBAR ? CS_CMDOR : CS_CMDAND); zshlex(); @@ -1176,7 +1177,8 @@ par_case(int *complex) static void par_if(int *complex) { - int oecused = ecused, xtok, p, pp, type, usebrace = 0; + int oecused = ecused, p, pp, type, usebrace = 0; + enum lextok xtok; unsigned char nc; p = ecadd(0); @@ -1367,7 +1369,8 @@ par_repeat(int *complex) static void par_subsh(int *complex) { - int oecused = ecused, otok = tok, p, pp; + enum lextok otok = tok; + int oecused = ecused, p, pp; p = ecadd(0); /* Extra word only needed for always block */ @@ -2110,7 +2113,7 @@ par_cond_2(void) && !s1[2]); condlex(); if (tok == INANG || tok == OUTANG) { - int xtok = tok; + enum lextok xtok = tok; condlex(); if (tok != STRING) YYERROR(ecused); @@ -2371,7 +2374,7 @@ freeeprog(Eprog p) /**/ char * -ecgetstr(Estate s, int dup, int *tok) +ecgetstr(Estate s, int dup, int *tokflag) { static char buf[4]; wordcode c = *s->pc++; @@ -2389,8 +2392,8 @@ ecgetstr(Estate s, int dup, int *tok) } else { r = s->strs + (c >> 2); } - if (tok) - *tok = (c & 1); + if (tokflag) + *tokflag = (c & 1); /*** Since function dump files are mapped read-only, avoiding to * to duplicate strings when they don't contain tokens may fail @@ -2407,33 +2410,33 @@ ecgetstr(Estate s, int dup, int *tok) /**/ char * -ecrawstr(Eprog p, Wordcode pc, int *tok) +ecrawstr(Eprog p, Wordcode pc, int *tokflag) { static char buf[4]; wordcode c = *pc; if (c == 6 || c == 7) { - if (tok) - *tok = (c & 1); + if (tokflag) + *tokflag = (c & 1); return ""; } else if (c & 2) { buf[0] = (char) ((c >> 3) & 0xff); buf[1] = (char) ((c >> 11) & 0xff); buf[2] = (char) ((c >> 19) & 0xff); buf[3] = '\0'; - if (tok) - *tok = (c & 1); + if (tokflag) + *tokflag = (c & 1); return buf; } else { - if (tok) - *tok = (c & 1); + if (tokflag) + *tokflag = (c & 1); return p->strs + (c >> 2); } } /**/ char ** -ecgetarr(Estate s, int num, int dup, int *tok) +ecgetarr(Estate s, int num, int dup, int *tokflag) { char **ret, **rp; int tf = 0, tmp = 0; @@ -2445,15 +2448,15 @@ ecgetarr(Estate s, int num, int dup, int *tok) tf |= tmp; } *rp = NULL; - if (tok) - *tok = tf; + if (tokflag) + *tokflag = tf; return ret; } /**/ LinkList -ecgetlist(Estate s, int num, int dup, int *tok) +ecgetlist(Estate s, int num, int dup, int *tokflag) { if (num) { LinkList ret; @@ -2464,12 +2467,12 @@ ecgetlist(Estate s, int num, int dup, int *tok) setsizednode(ret, i, ecgetstr(s, dup, &tmp)); tf |= tmp; } - if (tok) - *tok = tf; + if (tokflag) + *tokflag = tf; return ret; } - if (tok) - *tok = 0; + if (tokflag) + *tokflag = 0; return NULL; } diff --git a/Src/subst.c b/Src/subst.c index b0c15d048..974a8456d 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1215,7 +1215,7 @@ get_strarg(char *s, int *lenp) { convchar_t del; int len; - char tok = 0; + char ctok = 0; MB_METACHARINIT(); len = MB_METACHARLENCONV(s, &del); @@ -1243,25 +1243,25 @@ get_strarg(char *s, int *lenp) del = ZWC('>'); break; case Inpar: - tok = Outpar; + ctok = Outpar; break; case Inang: - tok = Outang; + ctok = Outang; break; case Inbrace: - tok = Outbrace; + ctok = Outbrace; break; case Inbrack: - tok = Outbrack; + ctok = Outbrack; break; } - if (tok) { + if (ctok) { /* * Looking for a matching token; we want the literal byte, * not a decoded multibyte character, so search specially. */ - while (*s && *s != tok) + while (*s && *s != ctok) s++; } else { convchar_t del2; diff --git a/Src/zsh.h b/Src/zsh.h index e20838249..fee27ac10 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -232,7 +232,7 @@ enum { * appear in strings and don't necessarily represent a single character. */ -enum { +enum lextok { NULLTOK, /* 0 */ SEPER, NEWLIN, -- cgit v1.2.3 From 4b86cc48f704152ccca13c50bc3acd59b4217ecc Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 11 Oct 2012 20:14:01 +0000 Subject: 30726: make shell options passed to emulate stick along with the emulation --- ChangeLog | 11 ++++- Doc/Zsh/builtins.yo | 4 ++ Src/Modules/parameter.c | 2 +- Src/builtin.c | 50 +++++++++++++++++----- Src/exec.c | 107 +++++++++++++++++++++++++++++++++++++++++++++--- Src/hashtable.c | 9 ++++ Src/init.c | 44 ++++++++++++++++---- Src/options.c | 18 +++----- Src/parse.c | 2 +- Src/signals.c | 5 ++- Src/zsh.h | 30 +++++++++++++- Test/B07emulate.ztst | 46 +++++++++++++++++++++ 12 files changed, 287 insertions(+), 41 deletions(-) (limited to 'Src/zsh.h') diff --git a/ChangeLog b/ChangeLog index 5a69f0174..4b1508a47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-10-11 Peter Stephenson + + * 30726: Doc/Zsh/builtins.yo, Src/builtin.c, Src/exec.c, + Src/hashtable.c, Src/init.c, Src/options.c, Src/parse.c, + Src/signals.c, Src/zsh.h, Src/Modules/parameter.c, + Test/B07emulate.ztst: extend 30722 to handle the case + where shell options passed to the emulate command need + propagating to sticky emulation. + 2012-10-11 Peter Stephenson * 30724: Src/exec.c, Src/jobs.c: shell code optimised to use @@ -260,5 +269,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5744 $ +* $Revision: 1.5745 $ ***************************************************** diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index f7924a072..37319c9b0 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -462,6 +462,10 @@ sitem(4.)(The presence or absence of the tt(-R) switch to tt(emulate) corresponds to different sticky emulation modes, so for example `tt(emulate sh -c)', `tt(emulate -R sh -c)' and `tt(emulate csh -c)' are treated as three distinct sticky emulations.) +sitem(5.)(Difference in shell options supplied in addition to the +basic emulation also mean the sticky emulations are different, so for +example `tt(emulate zsh -c)' and `tt(emulate zsh -o cbases -c)' are +treated as distinct sticky emulations.) endsitem() ) findex(enable) diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index f19dfce4f..a029c9cb4 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -289,7 +289,7 @@ setfunction(char *name, char *val, int dis) shf = (Shfunc) zshcalloc(sizeof(*shf)); shf->funcdef = dupeprog(prog, 0); shf->node.flags = dis; - shf->emulation = sticky_emulation; + shfunc_set_sticky(shf); if (!strncmp(name, "TRAP", 4) && (sn = getsignum(name + 4)) != -1) { diff --git a/Src/builtin.c b/Src/builtin.c index 5cb643f23..8a83df711 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -2944,7 +2944,7 @@ bin_functions(char *name, char **argv, Options ops, int func) shf = (Shfunc) zshcalloc(sizeof *shf); shf->node.flags = on; shf->funcdef = mkautofn(shf); - shf->emulation = sticky_emulation; + shfunc_set_sticky(shf); shfunctab->addnode(shfunctab, ztrdup(*argv), shf); if (signum != -1) { @@ -5007,11 +5007,15 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) { int opt_L = OPT_ISSET(ops, 'L'); int opt_R = OPT_ISSET(ops, 'R'); - int saveemulation, savesticky_emulation, savehackchar; + int saveemulation, savehackchar; int ret = 1, new_emulation; - char saveopts[OPT_SIZE], new_opts[OPT_SIZE], savesticky_opts[OPT_SIZE]; + char saveopts[OPT_SIZE], new_opts[OPT_SIZE]; char *cmd = 0; const char *shname = *argv; + LinkList optlist; + LinkNode optnode; + Emulation_options save_sticky; + OptIndex *on_ptr, *off_ptr; /* without arguments just print current emulation */ if (!shname) { @@ -5055,7 +5059,8 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) memcpy(new_opts, opts, sizeof(opts)); savehackchar = keyboardhackchar; emulate(shname, OPT_ISSET(ops,'R'), &new_emulation, new_opts); - if (parseopts("emulate", &argv, new_opts, &cmd)) { + optlist = newlinklist(); + if (parseopts("emulate", &argv, new_opts, &cmd, optlist)) { ret = 1; goto restore; } @@ -5081,15 +5086,40 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) } else return 0; - savesticky_emulation = sticky_emulation; - sticky_emulation = emulation; - memcpy(savesticky_opts, sticky_opts, sizeof(opts)); - memcpy(sticky_opts, opts, sizeof(opts)); + save_sticky = sticky; + sticky = hcalloc(sizeof(*sticky)); + sticky->emulation = emulation; + for (optnode = firstnode(optlist); optnode; incnode(optnode)) { + /* Data is index into new_opts */ + char *optptr = (char *)getdata(optnode); + if (*optptr) + sticky->n_on_opts++; + else + sticky->n_off_opts++; + } + if (sticky->n_on_opts) + on_ptr = sticky->on_opts = + zhalloc(sticky->n_on_opts * sizeof(*sticky->on_opts)); + else + on_ptr = NULL; + if (sticky->n_off_opts) + off_ptr = sticky->off_opts = zhalloc(sticky->n_off_opts * + sizeof(*sticky->off_opts)); + else + off_ptr = NULL; + for (optnode = firstnode(optlist); optnode; incnode(optnode)) { + /* Data is index into new_opts */ + char *optptr = (char *)getdata(optnode); + int optno = optptr - new_opts; + if (*optptr) + *on_ptr++ = optno; + else + *off_ptr++ = optno; + } ret = eval(argv); - sticky_emulation = savesticky_emulation; + sticky = save_sticky; emulation = saveemulation; memcpy(opts, saveopts, sizeof(opts)); - memcpy(sticky_opts, savesticky_opts, sizeof(opts)); restore: keyboardhackchar = savehackchar; inittyptab(); /* restore banghist */ diff --git a/Src/exec.c b/Src/exec.c index b2224cfb3..74b14d54d 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4267,7 +4267,7 @@ execfuncdef(Estate state, UNUSED(int do_exec)) shf->node.flags = 0; shf->filename = ztrdup(scriptfilename); shf->lineno = lineno; - shf->emulation = sticky_emulation; + shfunc_set_sticky(shf); if (!names) { /* @@ -4319,6 +4319,46 @@ execfuncdef(Estate state, UNUSED(int do_exec)) return ret; } +/* Duplicate a sticky emulation */ + +/**/ + +mod_export Emulation_options +sticky_emulation_dup(Emulation_options src, int useheap) +{ + Emulation_options newsticky = useheap ? + hcalloc(sizeof(*src)) : zshcalloc(sizeof(*src)); + newsticky->emulation = src->emulation; + if (src->n_on_opts) { + size_t sz = src->n_on_opts * sizeof(*src->on_opts); + newsticky->n_on_opts = src->n_on_opts; + newsticky->on_opts = useheap ? zhalloc(sz) : zalloc(sz); + memcpy(newsticky->on_opts, src->on_opts, sz); + } + if (src->n_off_opts) { + size_t sz = src->n_off_opts * sizeof(*src->off_opts); + newsticky->n_off_opts = src->n_off_opts; + newsticky->off_opts = useheap ? zhalloc(sz) : zalloc(sz); + memcpy(newsticky->off_opts, src->off_opts, sz); + } + + return newsticky; +} + +/* Set the sticky emulation attributes for a shell function */ + +/**/ + +mod_export void +shfunc_set_sticky(Shfunc shf) +{ + if (sticky) + shf->sticky = sticky_emulation_dup(sticky, 0); + else + shf->sticky = NULL; +} + + /* Main entry point to execute a shell function. */ /**/ @@ -4478,6 +4518,45 @@ loadautofn(Shfunc shf, int fksh, int autol) return shf; } +/* + * Check if a sticky emulation differs from the current one. + */ + +/**/ + +int sticky_emulation_differs(Emulation_options sticky2) +{ + /* If no new sticky emulation, not a different emulation */ + if (!sticky2) + return 0; + /* If no current sticky emulation, different */ + if (!sticky) + return 1; + /* If basic emulation different, different */ + if (sticky->emulation != sticky2->emulation) + return 1; + /* If differing numbers of options, different */ + if (sticky->n_on_opts != sticky2->n_on_opts || + sticky->n_off_opts != sticky2->n_off_opts) + return 1; + /* + * We need to compare option arrays, if non-null. + * We made parseopts() create the list of options in option + * order to make this easy. + */ + /* If different options turned on, different */ + if (sticky->n_on_opts && + memcmp(sticky->on_opts, sticky2->on_opts, + sticky->n_on_opts * sizeof(*sticky->on_opts)) != 0) + return 1; + /* If different options turned on, different */ + if (sticky->n_off_opts && + memcmp(sticky->off_opts, sticky2->off_opts, + sticky->n_off_opts * sizeof(*sticky->off_opts)) != 0) + return 1; + return 0; +} + /* * execute a shell function * @@ -4507,10 +4586,11 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) char *name = shfunc->node.nam; int flags = shfunc->node.flags, ooflags; char *fname = dupstring(name); - int obreaks, saveemulation, savesticky_emulation, restore_sticky; + int obreaks, saveemulation, restore_sticky; Eprog prog; struct funcstack fstack; static int oflags; + Emulation_options save_sticky = NULL; #ifdef MAX_FUNCTION_DEPTH static int funcdepth; #endif @@ -4548,9 +4628,9 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) * function we need to restore the original options on exit. */ memcpy(saveopts, opts, sizeof(opts)); saveemulation = emulation; - savesticky_emulation = sticky_emulation; + save_sticky = sticky; - if (shfunc->emulation && sticky_emulation != shfunc->emulation) { + if (sticky_emulation_differs(shfunc->sticky)) { /* * Function is marked for sticky emulation. * Enable it now. @@ -4563,9 +4643,24 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) * * This propagates the sticky emulation to subfunctions. */ - emulation = sticky_emulation = shfunc->emulation; + sticky = sticky_emulation_dup(shfunc->sticky, 1); + emulation = sticky->emulation; restore_sticky = 1; installemulation(emulation, opts); + if (sticky->n_on_opts) { + OptIndex *onptr; + for (onptr = sticky->on_opts; + onptr < sticky->on_opts + sticky->n_on_opts; + onptr++) + opts[*onptr] = 1; + } + if (sticky->n_off_opts) { + OptIndex *offptr; + for (offptr = sticky->off_opts; + offptr < sticky->off_opts + sticky->n_off_opts; + offptr++) + opts[*offptr] = 0; + } } else restore_sticky = 0; @@ -4674,7 +4769,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) */ memcpy(opts, saveopts, sizeof(opts)); emulation = saveemulation; - sticky_emulation = savesticky_emulation; + sticky = save_sticky; } else if (isset(LOCALOPTIONS)) { /* restore all shell options except PRIVILEGED and RESTRICTED */ saveopts[PRIVILEGED] = opts[PRIVILEGED]; diff --git a/Src/hashtable.c b/Src/hashtable.c index b472e40b9..ef187927b 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -888,6 +888,15 @@ freeshfuncnode(HashNode hn) if (shf->funcdef) freeeprog(shf->funcdef); zsfree(shf->filename); + if (shf->sticky) { + if (shf->sticky->n_on_opts) + zfree(shf->sticky->on_opts, + shf->sticky->n_on_opts * sizeof(*shf->sticky->on_opts)); + if (shf->sticky->n_off_opts) + zfree(shf->sticky->off_opts, + shf->sticky->n_off_opts * sizeof(*shf->sticky->off_opts)); + zfree(shf->sticky, sizeof(*shf->sticky)); + } zfree(shf, sizeof(struct shfunc)); } diff --git a/Src/init.c b/Src/init.c index 8f6c0ec6d..6c2ba13e4 100644 --- a/Src/init.c +++ b/Src/init.c @@ -246,7 +246,7 @@ parseargs(char **argv, char **runscript) opts[SHINSTDIN] = 0; opts[SINGLECOMMAND] = 0; - if (parseopts(NULL, &argv, opts, &cmd)) + if (parseopts(NULL, &argv, opts, &cmd, NULL)) exit(1); paramlist = znewlinklist(); @@ -277,15 +277,37 @@ parseargs(char **argv, char **runscript) argzero = ztrdup(argzero); } +/* Insert into list in order of pointer value */ + +/**/ +static void +parseopts_insert(LinkList optlist, void *ptr) +{ + LinkNode node; + + for (node = firstnode(optlist); node; incnode(node)) { + if (ptr < getdata(node)) { + insertlinknode(optlist, prevnode(node), ptr); + return; + } + } + + addlinknode(optlist, ptr); +} + /* * Parse shell options. * If nam is not NULL, this is called from a command; don't * exit on failure. + * + * If optlist is not NULL, it used to form a list of pointers + * into new_opts indicating which options have been changed. */ /**/ mod_export int -parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp) +parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp, + LinkList optlist) { int optionbreak = 0; int action, optno; @@ -364,8 +386,12 @@ parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp) restricted = action; } else if ((optno == EMACSMODE || optno == VIMODE) && nam) { WARN_OPTION("can't change option: %s", *argv); - } else if (dosetopt(optno, action, !nam, new_opts) && nam) { - WARN_OPTION("can't change option: %s", *argv); + } else { + if (dosetopt(optno, action, !nam, new_opts) && nam) { + WARN_OPTION("can't change option: %s", *argv); + } else if (optlist) { + parseopts_insert(optlist, new_opts+optno); + } } break; } else if (isspace(STOUC(**argv))) { @@ -385,8 +411,12 @@ parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp) restricted = action; } else if ((optno == EMACSMODE || optno == VIMODE) && nam) { WARN_OPTION("can't change option: %s", *argv); - } else if (dosetopt(optno, action, !nam, new_opts) && nam) { - WARN_OPTION("can't change option: -%c", **argv); + } else { + if (dosetopt(optno, action, !nam, new_opts) && nam) { + WARN_OPTION("can't change option: -%c", **argv); + } else if (optlist) { + parseopts_insert(optlist, new_opts+optno); + } } } } @@ -396,7 +426,7 @@ parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp) if (*cmdp) { if (!*argv) { WARN_OPTION("string expected after -%s", *cmdp); - exit(1); + return 1; } *cmdp = *argv++; } diff --git a/Src/options.c b/Src/options.c index 87e9abe2d..80fef3d00 100644 --- a/Src/options.c +++ b/Src/options.c @@ -35,29 +35,21 @@ /**/ mod_export int emulation; -/* current sticky emulation: 0 means none */ +/* current sticky emulation: sticky = NULL means none */ /**/ -mod_export int sticky_emulation; +mod_export Emulation_options sticky; /* the options; e.g. if opts[SHGLOB] != 0, SH_GLOB is turned on */ - + /**/ mod_export char opts[OPT_SIZE]; -/* - * the options that need setting for current sticky emulation, if any: - * same format as opts. - */ - -/**/ -mod_export char sticky_opts[OPT_SIZE]; - /* Option name hash table */ /**/ mod_export HashTable optiontab; - + /* The canonical option name table */ #define OPT_CSH EMULATE_CSH @@ -786,7 +778,7 @@ dosetopt(int optno, int value, int force, char *new_opts) return -1; #endif /* GETPWNAM_FAKED */ } else if ((optno == EMACSMODE || optno == VIMODE) && value) { - if (sticky_emulation) + if (sticky && sticky->emulation) return -1; zleentry(ZLE_CMD_SET_KEYMAP, optno); new_opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0; diff --git a/Src/parse.c b/Src/parse.c index 8d2878cd7..096faa072 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -3482,7 +3482,7 @@ dump_autoload(char *nam, char *file, int on, Options ops, int func) shf = (Shfunc) zshcalloc(sizeof *shf); shf->node.flags = on; shf->funcdef = mkautofn(shf); - shf->emulation = 0; + shf->sticky = NULL; shfunctab->addnode(shfunctab, ztrdup(fdname(n) + fdhtail(n)), shf); if (OPT_ISSET(ops,'X') && eval_autoload(shf, shf->node.nam, ops, func)) ret = 1; diff --git a/Src/signals.c b/Src/signals.c index ad688094b..046ee6a4a 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -755,7 +755,10 @@ dosavetrap(int sig, int level) newshf->node.flags = shf->node.flags; newshf->funcdef = dupeprog(shf->funcdef, 0); newshf->filename = ztrdup(shf->filename); - newshf->emulation = shf->emulation; + if (shf->sticky) { + newshf->sticky = sticky_emulation_dup(shf->sticky, 0); + } else + newshf->sticky = 0; if (shf->node.flags & PM_UNDEFINED) newshf->funcdef->shf = newshf; } diff --git a/Src/zsh.h b/Src/zsh.h index fee27ac10..e51572bcf 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -407,6 +407,7 @@ typedef struct cmdnam *Cmdnam; typedef struct complist *Complist; typedef struct conddef *Conddef; typedef struct dirsav *Dirsav; +typedef struct emulation_options *Emulation_options; typedef struct features *Features; typedef struct feature_enables *Feature_enables; typedef struct funcstack *Funcstack; @@ -1099,7 +1100,7 @@ struct shfunc { char *filename; /* Name of file located in */ zlong lineno; /* line number in above file */ Eprog funcdef; /* function definition */ - int emulation; /* sticky emulation for function */ + Emulation_options sticky; /* sticky emulation definitions, if any */ }; /* Shell function context types. */ @@ -2104,6 +2105,12 @@ enum { OPT_SIZE }; +/* + * Size required to fit an option number. + * If OPT_SIZE goes above 256 this will need to expand. + */ +typedef unsigned char OptIndex; + #undef isset #define isset(X) (opts[X]) #define unset(X) (!opts[X]) @@ -2112,6 +2119,27 @@ enum { #define jobbing (isset(MONITOR)) #define islogin (isset(LOGINSHELL)) +/* + * Record of emulation and options that need to be set + * for a full "emulate". + */ +struct emulation_options { + /* The emulation itself */ + int emulation; + /* The number of options in on_opts. */ + int n_on_opts; + /* The number of options in off_opts. */ + int n_off_opts; + /* + * Array of options to be turned on. + * Only options specified explicitly in the emulate command + * are recorded. Null if n_on_opts is zero. + */ + OptIndex *on_opts; + /* Array of options to be turned off, similar. */ + OptIndex *off_opts; +}; + /***********************************************/ /* Definitions for terminal and display control */ /***********************************************/ diff --git a/Test/B07emulate.ztst b/Test/B07emulate.ztst index 569640bb4..315206a20 100644 --- a/Test/B07emulate.ztst +++ b/Test/B07emulate.ztst @@ -201,3 +201,49 @@ emulate zsh -o fixallmybugs 'print This was executed, bad' 1:emulate -c with incorrect options ?(eval):emulate:1: no such option: fixallmybugs + + emulate zsh -c ' + func() { [[ -o extendedglob ]] || print extendedglob is off } + ' + func + emulate zsh -o extendedglob -c ' + func() { [[ -o extendedglob ]] && print extendedglob is on } + ' + func +0:options specified alongside emulation are also sticky +>extendedglob is off +>extendedglob is on + + emulate zsh -o extendedglob -c ' + func_inner() { setopt nobareglobqual } + ' + emulate zsh -o extendedglob -c ' + func_outer() { + func_inner + [[ -o bareglobqual ]] || print bareglobqual was turned off + [[ -o extendedglob ]] && print extendedglob is on, though + } + ' + [[ -o extendedglob ]] || print extendedglob is initially off + func_outer +0:options propagate between identical emulations +>extendedglob is initially off +>bareglobqual was turned off +>extendedglob is on, though + + emulate zsh -o extendedglob -c ' + func_inner() { setopt nobareglobqual } + ' + emulate zsh -o extendedglob -o cbases -c ' + func_outer() { + func_inner + [[ -o bareglobqual ]] && print bareglobqual is still on + [[ -o extendedglob ]] && print extendedglob is on, too + } + ' + [[ -o extendedglob ]] || print extendedglob is initially off + func_outer +0:options do not propagate between different emulations +>extendedglob is initially off +>bareglobqual is still on +>extendedglob is on, too -- cgit v1.2.3 From 7c56d771840a9f335b2e21290c8cbf714264bc66 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 15 Nov 2012 21:08:15 +0000 Subject: 30789: Add CONTINUE_ON_ERROR for old behaviour. New behaviour is for scripts to exit on error instead of returning to top level and executing the next command. --- ChangeLog | 8 +++++++- Doc/Zsh/grammar.yo | 53 +++++++++++++++++++++++++++++++++++++++++++++++++-- Doc/Zsh/options.yo | 16 ++++++++++++++++ Src/hist.c | 2 +- Src/init.c | 9 +++++++-- Src/options.c | 1 + Src/zsh.h | 1 + Test/A04redirect.ztst | 12 ++++++------ 8 files changed, 90 insertions(+), 12 deletions(-) (limited to 'Src/zsh.h') diff --git a/ChangeLog b/ChangeLog index d65cfa957..36bac2884 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2012-11-15 Peter Stephenson + * 30789: Doc/Zsh/grammar.yo, Doc/Zsh/options.yo, Src/hist.c, + Src/init.c, Src/options.c, Src/zsh.h, Test/A04redirect.zsh: add + CONTINUE_ON_ERROR option for compatibility but turn it off: + scripts exit on an error instead of returning to the top-level + like interactive shells. + * 30800: Michal Halenka: Completion/Unix/Command/_arping: fix option. @@ -335,5 +341,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5760 $ +* $Revision: 1.5761 $ ***************************************************** diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index 1eb358ea3..e1b2f0ea6 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -438,7 +438,7 @@ where var(term) is at least one newline or tt(;). A short form of tt(select). ) enditem() -texinode(Reserved Words)(Comments)(Alternate Forms For Complex Commands)(Shell Grammar) +texinode(Reserved Words)(Errors)(Alternate Forms For Complex Commands)(Shell Grammar) sect(Reserved Words) cindex(reserved words) findex(disable, use of) @@ -451,7 +451,56 @@ select coproc nocorrect foreach end ! [[ { }) Additionally, `tt(})' is recognized in any position if neither the tt(IGNORE_BRACES) option nor the tt(IGNORE_CLOSE_BRACES) option is set. -texinode(Comments)(Aliasing)(Reserved Words)(Shell Grammar) +texinode(Errors)(Comments)(Reserved Words)(Shell Grammar) +sect(Errors) +cindex(errors, handling of) +Certain errors are treated as fatal by the shell: in an interactive +shell, they cause control to return to the command line, and in a +non-interactive shell they cause the shell to be aborted. In older +versions of zsh, a non-interactive shell running a script would not +abort completely, but would resume execution at the next command to be +read from the script, skipping the remainder of any functions or +shell constructs such as loops or conditions; this somewhat illogical +behaviour can be recovered by setting the option tt(CONTINUE_ON_ERROR). + +Fatal errors found in non-interactive shells include: +startlist() +list(Failure to parse shell options passed when invoking the shell) +list(Failure to change options with the tt(set) builtin) +list(Parse errors of all sorts, including failures to parse +mathematical expressions) +list(Failures to set or modify variable behaviour with tt(typeset), +tt(local), tt(declare), tt(export), tt(integer), tt(float)) +list(Execution of incorrectly positioned loop control structures +(tt(continue), tt(break))) +list(Attempts to use regular expression with no regular expression +module available) +list(Disallowed operations when the tt(RESTRICTED) options is set) +list(Failure to create a pipe needed for a pipeline) +list(Failure to create a multio) +list(Failure to autoload a module needed for a declared shell feature) +list(Errors creating command or process substitutions) +list(Syntax errors in glob qualifiers) +list(File generation errors where not caught by the option tt(BAD_PATTERN)) +list(All bad patterns used for matching within case statements) +list(File generation failures where not caused by tt(NO_MATCH) or +list(All file generation errors where the pattern was used to create a +multio) +list(Memory errors where detected by the shell) +list(Invalid subscripts to shell variables) +list(Attempts to assign read-only variables) +list(Logical errors with variables such as assignment to the wrong type) +list(Use of invalid variable names) +list(Errors in variable substitution syntax) +list(Failure to convert characters in tt($')...tt(') expressions) +similar options) +endlist() + +If the tt(POSIX_BUILTINS) option is set, more errors associated with +shell builtin commands are treated as fatal, as specified by the POSIX +standard. + +texinode(Comments)(Aliasing)(Errors)(Shell Grammar) sect(Comments) cindex(comments) pindex(INTERACTIVE_COMMENTS, use of) diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 3114ecc05..6c8d423cb 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1733,6 +1733,22 @@ Make the tt(echo) builtin compatible with the BSD manref(echo)(1) command. This disables backslashed escape sequences in echo strings unless the tt(-e) option is specified. ) +pindex(CONTINUE_ON_ERROR) +pindex(NO_CONTINUE_ON_ERROR) +pindex(CONTINUEONERROR) +pindex(NOCONTINUEONERROR) +cindex(error, option to continue script on) +item(tt(CONTINUE_ON_ERROR))( +If a fatal error is encountered (see +ifnzman(noderef(Errors))\ +ifzman(the section ERRORS in zmanref(zshmisc))), and the code is running +in a script, the shell will resume execution at the next statement +in the script at the top level, in other words outside all functions +or shell constructs such as loops and conditions. This mimics the +behaviour of interactive shells, where the shell returns to the +line editor to read a new command; it was the normal behaviour in versions +of zsh before 5.0.1. +) pindex(CSH_JUNKIE_HISTORY) pindex(NO_CSH_JUNKIE_HISTORY) pindex(CSHJUNKIEHISTORY) diff --git a/Src/hist.c b/Src/hist.c index 0e63dca37..561e2acd5 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -573,7 +573,7 @@ histsubchar(int c) } else { herrflush(); unqueue_signals(); - zerr("Ambiguous history reference"); + zerr("ambiguous history reference"); return -1; } diff --git a/Src/init.c b/Src/init.c index 6c2ba13e4..8467a739c 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1608,15 +1608,20 @@ zsh_main(UNUSED(int argc), char **argv) * We only do this at top level, because if we are * executing stuff we may refer to them by job pointer. */ + int errexit = 0; maybeshrinkjobtab(); do { /* Reset return from top level which gets us back here */ retflag = 0; loop(1,0); + if (errflag && !interact && !isset(CONTINUEONERROR)) { + errexit = 1; + break; + } } while (tok != ENDINPUT && (tok != LEXERR || isset(SHINSTDIN))); - if (tok == LEXERR) { - /* Make sure a parse error exits with non-zero status */ + if (tok == LEXERR || errexit) { + /* Make sure a fatal error exits with non-zero status */ if (!lastval) lastval = 1; stopmsg = 1; diff --git a/Src/options.c b/Src/options.c index 80fef3d00..b36bd9944 100644 --- a/Src/options.c +++ b/Src/options.c @@ -113,6 +113,7 @@ static struct optname optns[] = { {{NULL, "combiningchars", 0}, COMBININGCHARS}, {{NULL, "completealiases", 0}, COMPLETEALIASES}, {{NULL, "completeinword", 0}, COMPLETEINWORD}, +{{NULL, "continueonerror", 0}, CONTINUEONERROR}, {{NULL, "correct", 0}, CORRECT}, {{NULL, "correctall", 0}, CORRECTALL}, {{NULL, "cshjunkiehistory", OPT_EMULATE|OPT_CSH}, CSHJUNKIEHISTORY}, diff --git a/Src/zsh.h b/Src/zsh.h index e51572bcf..207ef1836 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1971,6 +1971,7 @@ enum { COMPLETEINWORD, CORRECT, CORRECTALL, + CONTINUEONERROR, CPRECEDENCES, CSHJUNKIEHISTORY, CSHJUNKIELOOPS, diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst index d3c0a4a99..b8086e724 100644 --- a/Test/A04redirect.ztst +++ b/Test/A04redirect.ztst @@ -419,26 +419,26 @@ >output ?zsh:.:2: no such file or directory: /nonexistent/nonexistent - $ZTST_testdir/../Src/zsh -f <<<' + $ZTST_testdir/../Src/zsh -f -o CONTINUE_ON_ERROR <<<' readonly foo foo=bar set output echo output' -0:failed assignment on posix special, NO_POSIX_BUILTINS +0:failed assignment on posix special, CONTINUE_ON_ERROR >output ?zsh: read-only variable: foo - $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS <<<' + $ZTST_testdir/../Src/zsh -f <<<' readonly foo foo=bar set output echo output' -1:failed assignment on posix special, POSIX_BUILTINS +1:failed assignment on posix special, NO_CONTINUE_ON_ERROR ?zsh: read-only variable: foo - $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS <<<' + $ZTST_testdir/../Src/zsh -f -o CONTINUE_ON_ERROR <<<' readonly foo foo=bar echo output echo output' -0:failed assignment on non-posix-special, POSIX_BUILTINS +0:failed assignment on non-posix-special, CONTINUE_ON_ERROR >output ?zsh: read-only variable: foo -- cgit v1.2.3