diff options
Diffstat (limited to 'Src')
-rw-r--r-- | Src/Builtins/rlimits.awk | 1 | ||||
-rw-r--r-- | Src/Builtins/rlimits.c | 72 | ||||
-rw-r--r-- | Src/Modules/parameter.c | 8 | ||||
-rw-r--r-- | Src/Zle/zle_keymap.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_move.c | 33 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 15 | ||||
-rw-r--r-- | Src/Zle/zle_utils.c | 38 | ||||
-rw-r--r-- | Src/builtin.c | 111 | ||||
-rw-r--r-- | Src/compat.c | 4 | ||||
-rw-r--r-- | Src/exec.c | 157 | ||||
-rw-r--r-- | Src/hashtable.c | 16 | ||||
-rw-r--r-- | Src/hist.c | 2 | ||||
-rw-r--r-- | Src/init.c | 114 | ||||
-rw-r--r-- | Src/jobs.c | 12 | ||||
-rw-r--r-- | Src/lex.c | 107 | ||||
-rw-r--r-- | Src/math.c | 68 | ||||
-rw-r--r-- | Src/options.c | 81 | ||||
-rw-r--r-- | Src/parse.c | 54 | ||||
-rw-r--r-- | Src/prototypes.h | 9 | ||||
-rw-r--r-- | Src/signals.c | 5 | ||||
-rw-r--r-- | Src/subst.c | 16 | ||||
-rw-r--r-- | Src/utils.c | 30 | ||||
-rw-r--r-- | Src/zsh.h | 45 | ||||
-rw-r--r-- | Src/zsh_system.h | 4 |
24 files changed, 730 insertions, 274 deletions
diff --git a/Src/Builtins/rlimits.awk b/Src/Builtins/rlimits.awk index 418206a66..bf914814d 100644 --- a/Src/Builtins/rlimits.awk +++ b/Src/Builtins/rlimits.awk @@ -42,6 +42,7 @@ BEGIN {limidx = 0} if (limnam == "MEMLOCK") { msg[limnum] = "Mmemorylocked" } if (limnam == "NOFILE") { msg[limnum] = "Ndescriptors" } if (limnam == "NPROC") { msg[limnum] = "Nmaxproc" } + if (limnam == "NTHR") { msg[limnum] = "Nmaxthr" } if (limnam == "OFILE") { msg[limnum] = "Ndescriptors" } if (limnam == "PTHREAD") { msg[limnum] = "Nmaxpthreads" } if (limnam == "RSS") { msg[limnum] = "Mresident" } diff --git a/Src/Builtins/rlimits.c b/Src/Builtins/rlimits.c index 670516169..eedfa969c 100644 --- a/Src/Builtins/rlimits.c +++ b/Src/Builtins/rlimits.c @@ -238,32 +238,32 @@ printulimit(char *nam, int lim, int hard, int head) switch (lim) { case RLIMIT_CORE: if (head) - printf("-c: core file size (blocks) "); + printf("-c: core file size (blocks) "); if (limit != RLIM_INFINITY) limit /= 512; break; case RLIMIT_DATA: if (head) - printf("-d: data seg size (kbytes) "); + printf("-d: data seg size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; case RLIMIT_FSIZE: if (head) - printf("-f: file size (blocks) "); + printf("-f: file size (blocks) "); if (limit != RLIM_INFINITY) limit /= 512; break; # ifdef HAVE_RLIMIT_SIGPENDING case RLIMIT_SIGPENDING: if (head) - printf("-i: pending signals "); + printf("-i: pending signals "); break; # endif # ifdef HAVE_RLIMIT_MEMLOCK case RLIMIT_MEMLOCK: if (head) - printf("-l: locked-in-memory size (kb) "); + printf("-l: locked-in-memory size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; @@ -273,7 +273,7 @@ printulimit(char *nam, int lim, int hard, int head) # if defined(HAVE_RLIMIT_RSS) && !defined(RLIMIT_VMEM_IS_RSS) && !defined(RLIMIT_RSS_IS_AS) case RLIMIT_RSS: if (head) - printf("-m: resident set size (kbytes) "); + printf("-m: resident set size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; @@ -281,7 +281,7 @@ printulimit(char *nam, int lim, int hard, int head) # if defined(HAVE_RLIMIT_VMEM) && defined(HAVE_RLIMIT_RSS) && defined(RLIMIT_VMEM_IS_RSS) case RLIMIT_VMEM: if (head) - printf("-m: memory size (kb) "); + printf("-m: memory size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; @@ -289,35 +289,41 @@ printulimit(char *nam, int lim, int hard, int head) # ifdef HAVE_RLIMIT_NOFILE case RLIMIT_NOFILE: if (head) - printf("-n: file descriptors "); + printf("-n: file descriptors "); break; # endif /* HAVE_RLIMIT_NOFILE */ # ifdef HAVE_RLIMIT_MSGQUEUE case RLIMIT_MSGQUEUE: if (head) - printf("-q: bytes in POSIX msg queues "); + printf("-q: bytes in POSIX msg queues "); break; # endif case RLIMIT_STACK: if (head) - printf("-s: stack size (kbytes) "); + printf("-s: stack size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; case RLIMIT_CPU: if (head) - printf("-t: cpu time (seconds) "); + printf("-t: cpu time (seconds) "); break; # ifdef HAVE_RLIMIT_NPROC case RLIMIT_NPROC: if (head) - printf("-u: processes "); + printf("-u: processes "); break; # endif /* HAVE_RLIMIT_NPROC */ +# ifdef HAVE_RLIMIT_NTHR + case RLIMIT_NTHR: + if (head) + printf("-r: threads "); + break; +#endif /* HAVE_RLIMIT_NTHR */ # if defined(HAVE_RLIMIT_VMEM) && (!defined(HAVE_RLIMIT_RSS) || !defined(RLIMIT_VMEM_IS_RSS)) case RLIMIT_VMEM: if (head) - printf("-v: virtual memory size (kb) "); + printf("-v: virtual memory size (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; @@ -325,7 +331,7 @@ printulimit(char *nam, int lim, int hard, int head) # if defined HAVE_RLIMIT_AS && !defined(RLIMIT_VMEM_IS_AS) case RLIMIT_AS: if (head) - printf("-v: address space (kb) "); + printf("-v: address space (kbytes) "); if (limit != RLIM_INFINITY) limit /= 1024; break; @@ -333,13 +339,13 @@ printulimit(char *nam, int lim, int hard, int head) # ifdef HAVE_RLIMIT_LOCKS case RLIMIT_LOCKS: if (head) - printf("-x: file locks "); + printf("-x: file locks "); break; # endif /* HAVE_RLIMIT_LOCKS */ # ifdef HAVE_RLIMIT_AIO_MEM case RLIMIT_AIO_MEM: if (head) - printf("-N %2d: AIO locked-in-memory (kb) ", RLIMIT_AIO_MEM); + printf("-N %2d: AIO locked-in-memory (kbytes)", RLIMIT_AIO_MEM); if (limit != RLIM_INFINITY) limit /= 1024; break; @@ -347,44 +353,42 @@ printulimit(char *nam, int lim, int hard, int head) # ifdef HAVE_RLIMIT_AIO_OPS case RLIMIT_AIO_OPS: if (head) - printf("-N %2d: AIO operations ", RLIMIT_AIO_OPS); + printf("-N %2d: AIO operations ", RLIMIT_AIO_OPS); break; # endif /* HAVE_RLIMIT_AIO_OPS */ # ifdef HAVE_RLIMIT_TCACHE case RLIMIT_TCACHE: if (head) - printf("-N %2d: cached threads ", RLIMIT_TCACHE); + printf("-N %2d: cached threads ", RLIMIT_TCACHE); break; # endif /* HAVE_RLIMIT_TCACHE */ # ifdef HAVE_RLIMIT_SBSIZE case RLIMIT_SBSIZE: if (head) - printf("-N %2d: socket buffer size (kb) ", RLIMIT_SBSIZE); - if (limit != RLIM_INFINITY) - limit /= 1024; + printf("-b: socket buffer size (bytes) ", RLIMIT_SBSIZE); break; # endif /* HAVE_RLIMIT_SBSIZE */ # ifdef HAVE_RLIMIT_PTHREAD case RLIMIT_PTHREAD: if (head) - printf("-N %2d: threads per process ", RLIMIT_PTHREAD); + printf("-N %2d: threads per process ", RLIMIT_PTHREAD); break; # endif /* HAVE_RLIMIT_PTHREAD */ # ifdef HAVE_RLIMIT_NICE case RLIMIT_NICE: if (head) - printf("-e: max nice "); + printf("-e: max nice "); break; # endif /* HAVE_RLIMIT_NICE */ # ifdef HAVE_RLIMIT_RTPRIO case RLIMIT_RTPRIO: if (head) - printf("-r: max rt priority "); + printf("-r: max rt priority "); break; # endif /* HAVE_RLIMIT_RTPRIO */ default: if (head) - printf("-N %2d: ", lim); + printf("-N %2d: ", lim); break; } /* display the limit */ @@ -776,21 +780,31 @@ bin_ulimit(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) case 'c': res = RLIMIT_CORE; break; -# ifdef HAVE_RLIMIT_RSS - case 'm': - res = RLIMIT_RSS; +# ifdef HAVE_RLIMIT_SBSIZE + case 'b': + res = RLIMIT_SBSIZE; break; -# endif /* HAVE_RLIMIT_RSS */ +# endif /* HAVE_RLIMIT_SBSIZE */ # ifdef HAVE_RLIMIT_MEMLOCK case 'l': res = RLIMIT_MEMLOCK; break; # endif /* HAVE_RLIMIT_MEMLOCK */ +# ifdef HAVE_RLIMIT_RSS + case 'm': + res = RLIMIT_RSS; + break; +# endif /* HAVE_RLIMIT_RSS */ # ifdef HAVE_RLIMIT_NOFILE case 'n': res = RLIMIT_NOFILE; break; # endif /* HAVE_RLIMIT_NOFILE */ +# ifdef HAVE_RLIMIT_NTHR + case 'r': + res = RLIMIT_NTHR; + break; +# endif /* HAVE_RLIMIT_NTHR */ # ifdef HAVE_RLIMIT_NPROC case 'u': res = RLIMIT_NPROC; diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 4d29ba635..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) { @@ -771,7 +771,7 @@ setpmoption(Param pm, char *value) zwarn("invalid value: %s", value); else if (!(n = optlookup(pm->node.nam))) zwarn("no such option: %s", pm->node.nam); - else if (dosetopt(n, (value && strcmp(value, "off")), 0)) + else if (dosetopt(n, (value && strcmp(value, "off")), 0, opts)) zwarn("can't change option: %s", pm->node.nam); zsfree(value); } @@ -784,7 +784,7 @@ unsetpmoption(Param pm, UNUSED(int exp)) if (!(n = optlookup(pm->node.nam))) zwarn("no such option: %s", pm->node.nam); - else if (dosetopt(n, 0, 0)) + else if (dosetopt(n, 0, 0, opts)) zwarn("can't change option: %s", pm->node.nam); } @@ -812,7 +812,7 @@ setpmoptions(UNUSED(Param pm), HashTable ht) if (!val || (strcmp(val, "on") && strcmp(val, "off"))) zwarn("invalid value: %s", val); else if (dosetopt(optlookup(hn->nam), - (val && strcmp(val, "off")), 0)) + (val && strcmp(val, "off")), 0, opts)) zwarn("can't change option: %s", hn->nam); } deleteparamtable(ht); diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index c3731c47b..e21e769bd 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -912,7 +912,7 @@ bin_bindkey_new(char *name, UNUSED(char *kmname), Keymap km, char **argv, UNUSED if(argv[1]) { km = openkeymap(argv[1]); if(!km) { - zwarnnam(name, "no such keymap `%s'", argv[0]); + zwarnnam(name, "no such keymap `%s'", argv[1]); return 1; } } else diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c index 0e940bc21..d5f464c2c 100644 --- a/Src/Zle/zle_move.c +++ b/Src/Zle/zle_move.c @@ -679,7 +679,7 @@ vifindnextchar(char **args) if ((vfindchar = vigetkey()) != ZLEEOF) { vfinddir = 1; tailadd = 0; - return virepeatfind(args); + return vifindchar(0, args); } return 1; } @@ -691,7 +691,7 @@ vifindprevchar(char **args) if ((vfindchar = vigetkey()) != ZLEEOF) { vfinddir = -1; tailadd = 0; - return virepeatfind(args); + return vifindchar(0, args); } return 1; } @@ -703,7 +703,7 @@ vifindnextcharskip(char **args) if ((vfindchar = vigetkey()) != ZLEEOF) { vfinddir = 1; tailadd = -1; - return virepeatfind(args); + return vifindchar(0, args); } return 1; } @@ -715,14 +715,14 @@ vifindprevcharskip(char **args) if ((vfindchar = vigetkey()) != ZLEEOF) { vfinddir = -1; tailadd = 1; - return virepeatfind(args); + return vifindchar(0, args); } return 1; } /**/ int -virepeatfind(char **args) +vifindchar(int repeat, char **args) { int ocs = zlecs, n = zmult; @@ -735,6 +735,16 @@ virepeatfind(char **args) zmult = n; return ret; } + if (repeat && tailadd != 0) { + if (vfinddir > 0) { + if(zlecs < zlell && (ZLE_INT_T)zleline[zlecs+1] == vfindchar) + INCCS(); + } + else { + if(zlecs > 0 && (ZLE_INT_T)zleline[zlecs-1] == vfindchar) + DECCS(); + } + } while (n--) { do { if (vfinddir > 0) @@ -760,19 +770,28 @@ virepeatfind(char **args) /**/ int +virepeatfind(char **args) +{ + return vifindchar(1, args); +} + +/**/ +int virevrepeatfind(char **args) { int ret; if (zmult < 0) { zmult = -zmult; - ret = virepeatfind(args); + ret = vifindchar(1, args); zmult = -zmult; return ret; } + tailadd = -tailadd; vfinddir = -vfinddir; - ret = virepeatfind(args); + ret = vifindchar(1, args); vfinddir = -vfinddir; + tailadd = -tailadd; return ret; } 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/Zle/zle_utils.c b/Src/Zle/zle_utils.c index cf6787f3a..d0e7b5542 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1363,6 +1363,10 @@ static struct change *nextchanges, *endnextchanges; static zlong undo_changeno; +/* If non-zero, the last increment to undo_changeno was for the variable */ + +static int undo_set_by_variable; + /**/ void initundo(void) @@ -1373,6 +1377,7 @@ initundo(void) curchange->del = curchange->ins = NULL; curchange->dell = curchange->insl = 0; curchange->changeno = undo_changeno = 0; + undo_set_by_variable = 0; lastline = zalloc((lastlinesz = linesz) * ZLE_CHAR_SIZE); ZS_memcpy(lastline, zleline, (lastll = zlell)); lastcs = zlecs; @@ -1498,6 +1503,7 @@ mkundoent(void) ch->prev = NULL; } ch->changeno = ++undo_changeno; + undo_set_by_variable = 0; endnextchanges = ch; } @@ -1520,23 +1526,25 @@ setlastline(void) int undo(char **args) { - zlong last_change = (zlong)0; + zlong last_change; if (*args) - { last_change = zstrtol(*args, NULL, 0); - } + else + last_change = (zlong)-1; handleundo(); do { - if(!curchange->prev) + struct change *prev = curchange->prev; + if(!prev) return 1; - if (unapplychange(curchange->prev)) - curchange = curchange->prev; + if (prev->changeno < last_change) + break; + if (unapplychange(prev)) + curchange = prev; else break; - } while (*args ? curchange->changeno != last_change : - (curchange->flags & CH_PREV)); + } while (last_change >= (zlong)0 || (curchange->flags & CH_PREV)); setlastline(); return 0; } @@ -1660,6 +1668,16 @@ zlecallhook(char *name, char *arg) zlong get_undo_current_change(UNUSED(Param pm)) { - return undo_changeno; + if (undo_set_by_variable) { + /* We were the last to increment this, doesn't need another one. */ + return undo_changeno; + } + undo_set_by_variable = 1; + /* + * Increment the number in case a change is in progress; + * we don't want to back off what's already been done when + * we return to this change number. This eliminates any + * problem about the point where a change is numbered. + */ + return ++undo_changeno; } - diff --git a/Src/builtin.c b/Src/builtin.c index b5a98cbd2..90fe1a6c5 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, "mktTUwXz", "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), @@ -548,8 +548,8 @@ bin_set(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) /* Obsolescent sh compatibility: set - is the same as set +xv * * and set - args is the same as set +xv -- args */ if (!EMULATION(EMULATE_ZSH) && *args && **args == '-' && !args[0][1]) { - dosetopt(VERBOSE, 0, 0); - dosetopt(XTRACE, 0, 0); + dosetopt(VERBOSE, 0, 0, opts); + dosetopt(XTRACE, 0, 0, opts); if (!args[1]) return 0; } @@ -580,7 +580,7 @@ bin_set(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } if(!(optno = optlookup(*args))) zerrnam(nam, "no such option: %s", *args); - else if(dosetopt(optno, action, 0)) + else if(dosetopt(optno, action, 0, opts)) zerrnam(nam, "can't change option: %s", *args); break; } else if(**args == 'A') { @@ -601,7 +601,7 @@ bin_set(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) else { if (!(optno = optlookupc(**args))) zerrnam(nam, "bad option: -%c", **args); - else if(dosetopt(optno, action, 0)) + else if(dosetopt(optno, action, 0, opts)) zerrnam(nam, "can't change option: -%c", **args); } } @@ -1414,6 +1414,12 @@ bin_fc(char *nam, char **argv, Options ops, int func) unqueue_signals(); return 0; } + + if (zleactive) { + zwarnnam(nam, "no interactive history within ZLE"); + return 1; + } + /* put foo=bar type arguments into the substitution list */ while (*argv && equalsplit(*argv, &s)) { Asgment a = (Asgment) zhalloc(sizeof *a); @@ -1727,8 +1733,12 @@ fclist(FILE *f, Options ops, zlong first, zlong last, if (f == stdout) { nicezputs(s, f); putc('\n', f); - } else - fprintf(f, "%s\n", s); + } else { + int len; + unmetafy(s, &len); + fwrite(s, 1, len, f); + putc('\n', f); + } } /* move on to the next history line, or quit the loop */ if (first < last) { @@ -2449,7 +2459,20 @@ bin_typeset(char *name, char **argv, Options ops, int func) && (locallevel == pm->level || !(on & PM_LOCAL))) { if (pm->node.flags & PM_TIED) { unqueue_signals(); - zerrnam(name, "can't tie already tied scalar: %s", asg0.name); + if (!strcmp(asg->name, pm->ename)) { + /* + * Already tied in the fashion requested. + */ + struct tieddata *tdp = (struct tieddata*)pm->u.data; + /* Update join character */ + tdp->joinchar = joinchar; + if (asg0.value) + setsparam(asg0.name, ztrdup(asg0.value)); + return 0; + } else { + zerrnam(name, "can't tie already tied scalar: %s", + asg0.name); + } return 1; } if (!asg0.value && !(PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED))) @@ -2672,6 +2695,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')) + off |= PM_TAGGED_LOCAL; if (OPT_MINUS(ops,'z')) { on |= PM_ZSHSTORED; off |= PM_KSHSTORED; @@ -2861,7 +2888,7 @@ bin_functions(char *name, char **argv, Options ops, int func) if ((pprog = patcompile(*argv, PAT_STATIC, 0))) { /* with no options, just print all functions matching the glob pattern */ queue_signals(); - if (!(on|off)) { + if (!(on|off) && !OPT_ISSET(ops,'X')) { scanmatchtable(shfunctab, pprog, 1, 0, DISABLED, shfunctab->printnode, pflags); } else { @@ -2923,8 +2950,7 @@ bin_functions(char *name, char **argv, Options ops, int func) shf = (Shfunc) zshcalloc(sizeof *shf); shf->node.flags = on; shf->funcdef = mkautofn(shf); - /* No sticky emulation for autoloaded functions */ - shf->emulation = 0; + shfunc_set_sticky(shf); shfunctab->addnode(shfunctab, ztrdup(*argv), shf); if (signum != -1) { @@ -4987,11 +5013,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 ret = 1; - char saveopts[OPT_SIZE]; + int saveemulation, savehackchar; + int ret = 1, new_emulation; + 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) { @@ -5024,7 +5054,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) /* with single argument set current emulation */ if (!argv[1]) { - emulate(shname, OPT_ISSET(ops,'R')); + emulate(shname, OPT_ISSET(ops,'R'), &emulation, opts); if (OPT_ISSET(ops,'L')) opts[LOCALOPTIONS] = opts[LOCALTRAPS] = 1; return 0; @@ -5032,8 +5062,14 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) argv++; memcpy(saveopts, opts, sizeof(opts)); + memcpy(new_opts, opts, sizeof(opts)); savehackchar = keyboardhackchar; - cmd = parseopts("emulate", &argv); + emulate(shname, OPT_ISSET(ops,'R'), &new_emulation, new_opts); + optlist = newlinklist(); + if (parseopts("emulate", &argv, new_opts, &cmd, optlist)) { + ret = 1; + goto restore; + } /* parseopts() has consumed anything that looks like an option */ if (*argv) { @@ -5041,6 +5077,9 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) goto restore; } + saveemulation = emulation; + emulation = new_emulation; + memcpy(opts, new_opts, sizeof(opts)); /* If "-c command" is given, evaluate command using specified * emulation mode. */ @@ -5053,15 +5092,41 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) } else return 0; - saveemulation = emulation; - savesticky_emulation = sticky_emulation; - emulate(shname, OPT_ISSET(ops,'R')); - sticky_emulation = emulation; + 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; - restore: memcpy(opts, saveopts, sizeof(opts)); +restore: keyboardhackchar = savehackchar; inittyptab(); /* restore banghist */ return ret; diff --git a/Src/compat.c b/Src/compat.c index e36de3219..cc4e876da 100644 --- a/Src/compat.c +++ b/Src/compat.c @@ -630,7 +630,7 @@ strtoul(nptr, endptr, base) #endif /* HAVE_STRTOUL */ /**/ -#ifdef BROKEN_WCWIDTH +#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 */ +#endif /* BROKEN_WCWIDTH && (__STDC_ISO_10646__ || __APPLE__) */ diff --git a/Src/exec.c b/Src/exec.c index 6ebc9c014..1ecbc3967 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -404,7 +404,17 @@ execcursh(Estate state, int do_exec) /* Skip word only used for try/always */ state->pc++; - if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob)) + /* + * The test thisjob != -1 was added because sometimes thisjob + * can be invalid at this point. The case in question was + * in a precmd function after operations involving background + * jobs. + * + * This is because sometimes we bypass job control to execute + * very simple functions via execssimple(). + */ + if (!list_pipe && thisjob != -1 && thisjob != list_pipe_job && + !hasprocs(thisjob)) deletejob(jobtab + thisjob, 0); cmdpush(CS_CURSH); execlist(state, 1, do_exec); @@ -1064,7 +1074,7 @@ static int execsimple(Estate state) { wordcode code = *state->pc++; - int lv; + int lv, otj; if (errflag) return (lastval = 1); @@ -1075,6 +1085,13 @@ execsimple(Estate state) code = wc_code(*state->pc++); + /* + * Because we're bypassing job control, ensure the called + * code doesn't see the current job. + */ + otj = thisjob; + thisjob = -1; + if (code == WC_ASSIGN) { cmdoutval = 0; addvars(state, state->pc - 1, 0); @@ -1086,6 +1103,8 @@ execsimple(Estate state) } else lv = (execfuncs[code - WC_CURSH])(state, 0); + thisjob = otj; + return lastval = lv; } @@ -1188,6 +1207,9 @@ execlist(Estate state, int dont_change_job, int exiting) } else donedebug = intrap ? 1 : 0; + /* Reset donetrap: this ensures that a trap is only * + * called once for each sublist that fails. */ + donetrap = 0; if (ltype & Z_SIMPLE) { next = state->pc + WC_LIST_SKIP(code); if (donedebug != 2) @@ -1195,9 +1217,6 @@ execlist(Estate state, int dont_change_job, int exiting) state->pc = next; goto sublist_done; } - /* Reset donetrap: this ensures that a trap is only * - * called once for each sublist that fails. */ - donetrap = 0; /* Loop through code followed by &&, ||, or end of sublist. */ code = *state->pc++; @@ -4248,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) { /* @@ -4300,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. */ /**/ @@ -4313,7 +4372,9 @@ execshfunc(Shfunc shf, LinkList args) if (errflag) return; - if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob)) { + /* thisjob may be invalid if we're called via execsimple: see execcursh */ + if (!list_pipe && thisjob != -1 && thisjob != list_pipe_job && + !hasprocs(thisjob)) { /* Without this deletejob the process table * * would be filled by a recursive function. */ last_file_list = jobtab[thisjob].filelist; @@ -4458,6 +4519,45 @@ loadautofn(Shfunc shf, int fksh, int autol) } /* + * 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 * * name is the name of the function @@ -4484,11 +4584,13 @@ 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; + 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 @@ -4526,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. @@ -4541,14 +4643,38 @@ 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(); + 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; - 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 +4759,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) optcind = oldoptcind; zoptind = oldzoptind; scriptname = oldscriptname; + oflags = ooflags; if (restore_sticky) { /* @@ -4642,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 be71a1cc9..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)); } @@ -923,12 +932,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/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 6f14943e1..8467a739c 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 && @@ -246,7 +246,8 @@ parseargs(char **argv, char **runscript) opts[SHINSTDIN] = 0; opts[SINGLECOMMAND] = 0; - cmd = parseopts(NULL, &argv); + if (parseopts(NULL, &argv, opts, &cmd, NULL)) + exit(1); paramlist = znewlinklist(); if (*argv) { @@ -276,18 +277,58 @@ parseargs(char **argv, char **runscript) argzero = ztrdup(argzero); } +/* Insert into list in order of pointer value */ + /**/ -mod_export char * -parseopts(char *nam, char ***argvp) +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, + LinkList optlist) { int optionbreak = 0; int action, optno; - char *cmd = 0; /* deliberately hides static */ char **argv = *argvp; -#define WARN_OPTION(F, S) if (nam) zwarnnam(nam, F, S); else zerr(F, S) -#define LAST_OPTION(N) \ - if (nam) { if (*argv) argv++; goto doneargv; } else exit(N) + *cmdp = 0; +#define WARN_OPTION(F, S) \ + do { \ + if (nam) \ + zwarnnam(nam, F, S); \ + else \ + zerr(F, S); \ + } while (0) +#define LAST_OPTION(N) \ + do { \ + if (nam) { \ + if (*argv) \ + argv++; \ + goto doneargv; \ + } else exit(N); \ + } while(0) /* loop through command line options (begins with "-" or "+") */ while (!optionbreak && *argv && (**argv == '-' || **argv == '+')) { @@ -327,26 +368,30 @@ parseopts(char *nam, char ***argvp) optionbreak = 1; } else if (**argv == 'c') { /* -c command */ - cmd = *argv; - opts[INTERACTIVE] &= 1; + *cmdp = *argv; + new_opts[INTERACTIVE] &= 1; scriptname = scriptfilename = ztrdup("zsh"); } else if (**argv == 'o') { if (!*++*argv) argv++; if (!*argv) { WARN_OPTION("string expected after -o", NULL); - LAST_OPTION(1); + return 1; } longoptions: if (!(optno = optlookup(*argv))) { WARN_OPTION("no such option: %s", *argv); - LAST_OPTION(1); + return 1; } else if (optno == RESTRICTED && !nam) { restricted = action; } else if ((optno == EMACSMODE || optno == VIMODE) && nam) { WARN_OPTION("can't change option: %s", *argv); - } else if (dosetopt(optno, action, !nam) && 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))) { @@ -355,37 +400,41 @@ parseopts(char *nam, char ***argvp) if (!isspace(STOUC(**argv))) { badoptionstring: WARN_OPTION("bad option string: '%s'", args); - LAST_OPTION(1); + return 1; } break; } else { if (!(optno = optlookupc(**argv))) { WARN_OPTION("bad option: -%c", **argv); - LAST_OPTION(1); + return 1; } else if (optno == RESTRICTED && !nam) { restricted = action; } else if ((optno == EMACSMODE || optno == VIMODE) && nam) { WARN_OPTION("can't change option: %s", *argv); - } else if (dosetopt(optno, action, !nam) && 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); + } } } } argv++; } doneoptions: - if (cmd) { + if (*cmdp) { if (!*argv) { - WARN_OPTION("string expected after -%s", cmd); - LAST_OPTION(1); + WARN_OPTION("string expected after -%s", *cmdp); + return 1; } - cmd = *argv++; + *cmdp = *argv++; } doneargv: *argvp = argv; - return cmd; + return 0; } - + /**/ static void printhelp(void) @@ -1162,7 +1211,7 @@ init_misc(void) #else if (*zsh_name == 'r' || restricted) #endif - dosetopt(RESTRICTED, 1, 0); + dosetopt(RESTRICTED, 1, 0, opts); if (cmd) { if (SHIN >= 10) fclose(bshin); @@ -1225,7 +1274,7 @@ source(char *s) subsh = 0; lineno = 1; loops = 0; - dosetopt(SHINSTDIN, 0, 1); + dosetopt(SHINSTDIN, 0, 1, opts); scriptname = s; scriptfilename = s; @@ -1297,7 +1346,7 @@ source(char *s) thisjob = cj; /* current job number */ lineno = oldlineno; /* our current lineno */ loops = oloops; /* the # of nested loops we are in */ - dosetopt(SHINSTDIN, oldshst, 1); /* SHINSTDIN option */ + dosetopt(SHINSTDIN, oldshst, 1, opts); /* SHINSTDIN option */ errflag = 0; if (!exit_pending) retflag = 0; @@ -1535,7 +1584,7 @@ zsh_main(UNUSED(int argc), char **argv) fdtable = zshcalloc(fdtable_size*sizeof(*fdtable)); createoptiontable(); - emulate(zsh_name, 1); /* initialises most options */ + emulate(zsh_name, 1, &emulation, opts); /* initialises most options */ opts[LOGINSHELL] = (**argv == '-'); opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid()); opts[USEZLE] = 1; /* may be unset in init_io() */ @@ -1559,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/jobs.c b/Src/jobs.c index c9c549e1e..0dbb10b4f 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -209,7 +209,13 @@ findproc(pid_t pid, Job *jptr, Process *pptr, int aux) int hasprocs(int job) { - Job jn = jobtab + job; + Job jn; + + if (job < 0) { + DPUTS(1, "job number invalid in hasprocs"); + return 0; + } + jn = jobtab + job; return jn->procs || jn->auxprocs; } @@ -868,6 +874,8 @@ should_report_time(Job j) /* can this ever happen? */ if (!j->procs) return 0; + if (zleactive) + return 0; #ifdef HAVE_GETRUSAGE reporttime -= j->procs->ti.ru_utime.tv_sec + j->procs->ti.ru_stime.tv_sec; @@ -1735,12 +1743,14 @@ init_jobs(char **argv, char **envp) goto done; p = strchr(q, 0); } +#if !defined(HAVE_PUTENV) && !defined(USE_SET_UNSET_ENV) for(; *envp; envp++) { q = *envp; if(q != p+1) goto done; p = strchr(q, 0); } +#endif done: hackspace = p - hackzero; #endif @@ -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 @@ -1259,51 +1265,53 @@ gettokstr(int c, int sub) break; goto brk; case LX2_EQUALS: - if (intpos) { - e = hgetc(); - if (e != '(') { - hungetc(e); - lexstop = 0; - c = Equals; - } else { - add(Equals); - if (skipcomm()) { - peek = LEXERR; - goto brk; - } - c = Outpar; - } - } else if (!sub && peek != ENVSTRING && - incmdpos && !bct && !brct) { - char *t = tokstr; - if (idigit(*t)) - while (++t < bptr && idigit(*t)); - else { - int sav = *bptr; - *bptr = '\0'; - t = itype_end(t, IIDENT, 0); - if (t < bptr) { - skipparens(Inbrack, Outbrack, &t); + if (!sub) { + if (intpos) { + e = hgetc(); + if (e != '(') { + hungetc(e); + lexstop = 0; + c = Equals; } else { - *bptr = sav; + add(Equals); + if (skipcomm()) { + peek = LEXERR; + goto brk; + } + c = Outpar; } - } - if (*t == '+') - t++; - if (t == bptr) { - e = hgetc(); - if (e == '(' && incmdpos) { + } else if (peek != ENVSTRING && + incmdpos && !bct && !brct) { + char *t = tokstr; + if (idigit(*t)) + while (++t < bptr && idigit(*t)); + else { + int sav = *bptr; *bptr = '\0'; - return ENVARRAY; + t = itype_end(t, IIDENT, 0); + if (t < bptr) { + skipparens(Inbrack, Outbrack, &t); + } else { + *bptr = sav; + } } - hungetc(e); - lexstop = 0; - peek = ENVSTRING; - intpos = 2; + if (*t == '+') + t++; + if (t == bptr) { + e = hgetc(); + if (e == '(' && incmdpos) { + *bptr = '\0'; + return ENVARRAY; + } + hungetc(e); + lexstop = 0; + peek = ENVSTRING; + intpos = 2; + } else + c = Equals; } else c = Equals; - } else - c = Equals; + } break; case LX2_BKSLASH: c = hgetc(); @@ -1692,6 +1700,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 +1712,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 +1729,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/math.c b/Src/math.c index cca521098..e90d6a59a 100644 --- a/Src/math.c +++ b/Src/math.c @@ -447,12 +447,13 @@ lexconstant(void) if (*nptr == '-') nptr++; - if (*nptr == '0') + if (*nptr == '0' && + (memchr(nptr, '.', strlen(nptr)) == NULL)) { nptr++; if (*nptr == 'x' || *nptr == 'X') { /* Let zstrtol parse number with base */ - yyval.u.l = zstrtol(ptr, &ptr, 0); + yyval.u.l = zstrtol_underscore(ptr, &ptr, 0, 1); /* Should we set lastbase here? */ lastbase = 16; return NUM; @@ -466,13 +467,13 @@ lexconstant(void) * it can't be a base indication (always decimal) * or a floating point number. */ - for (ptr2 = nptr; idigit(*ptr2); ptr2++) + for (ptr2 = nptr; idigit(*ptr2) || *ptr2 == '_'; ptr2++) ; if (ptr2 > nptr && *ptr2 != '.' && *ptr2 != 'e' && *ptr2 != 'E' && *ptr2 != '#') { - yyval.u.l = zstrtol(ptr, &ptr, 0); + yyval.u.l = zstrtol_underscore(ptr, &ptr, 0, 1); lastbase = 8; return NUM; } @@ -481,17 +482,43 @@ lexconstant(void) } else { - while (idigit(*nptr)) + while (idigit(*nptr) || *nptr == '_') nptr++; } if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') { + char *ptr2; /* it's a float */ yyval.type = MN_FLOAT; #ifdef USE_LOCALE prev_locale = dupstring(setlocale(LC_NUMERIC, NULL)); setlocale(LC_NUMERIC, "POSIX"); #endif + if (*nptr == '.') { + nptr++; + while (idigit(*nptr) || *nptr == '_') + nptr++; + } + if (*nptr == 'e' || *nptr == 'E') { + nptr++; + if (*nptr == '+' || *nptr == '-') + nptr++; + while (idigit(*nptr) || *nptr == '_') + nptr++; + } + for (ptr2 = ptr; ptr2 < nptr; ptr2++) { + if (*ptr2 == '_') { + int len = nptr - ptr; + ptr = strdup(ptr); + for (ptr2 = ptr; len; len--) { + if (*ptr2 == '_') + chuck(ptr2); + else + ptr2++; + } + break; + } + } yyval.u.d = strtod(ptr, &nptr); #ifdef USE_LOCALE if (prev_locale) setlocale(LC_NUMERIC, prev_locale); @@ -503,11 +530,12 @@ lexconstant(void) ptr = nptr; } else { /* it's an integer */ - yyval.u.l = zstrtol(ptr, &ptr, 10); + yyval.u.l = zstrtol_underscore(ptr, &ptr, 10, 1); if (*ptr == '#') { ptr++; - yyval.u.l = zstrtol(ptr, &ptr, lastbase = yyval.u.l); + lastbase = yyval.u.l; + yyval.u.l = zstrtol_underscore(ptr, &ptr, lastbase, 1); } } return NUM; @@ -1053,14 +1081,34 @@ op(int what) return; if (c.type == MN_FLOAT) c.u.d = a.u.d / b.u.d; - else - c.u.l = a.u.l / b.u.l; + else { + /* + * Avoid exception when dividing the smallest + * negative integer by -1. Always treat it the + * same as multiplication. This still doesn't give + * numerically the right answer in two's complement, + * but treating both these in the same way seems + * reasonable. + */ + if (b.u.l == -1) + c.u.l = - a.u.l; + else + c.u.l = a.u.l / b.u.l; + } break; case MOD: case MODEQ: if (!notzero(b)) return; - c.u.l = a.u.l % b.u.l; + /* + * Avoid exception as above. + * Any integer mod -1 is the same as any integer mod 1 + * i.e. zero. + */ + if (b.u.l == -1) + c.u.l = 0; + else + c.u.l = a.u.l % b.u.l; break; case PLUS: case PLUSEQ: diff --git a/Src/options.c b/Src/options.c index c6db75372..b36bd9944 100644 --- a/Src/options.c +++ b/Src/options.c @@ -35,21 +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]; - + /* Option name hash table */ /**/ mod_export HashTable optiontab; - + /* The canonical option name table */ #define OPT_CSH EMULATE_CSH @@ -70,7 +70,7 @@ mod_export HashTable optiontab; /* option is an alias to an other option */ #define OPT_ALIAS (EMULATE_UNUSED<<2) -#define defset(X) (!!((X)->node.flags & emulation)) +#define defset(X, my_emulation) (!!((X)->node.flags & my_emulation)) /* * Note that option names should usually be fewer than 20 characters long @@ -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}, @@ -160,7 +161,7 @@ static struct optname optns[] = { {{NULL, "histverify", 0}, HISTVERIFY}, {{NULL, "hup", OPT_EMULATE|OPT_ZSH}, HUP}, {{NULL, "ignorebraces", OPT_EMULATE|OPT_SH}, IGNOREBRACES}, -{{NULL, "ignoreclosebraces", 0}, IGNORECLOSEBRACES}, +{{NULL, "ignoreclosebraces", OPT_EMULATE}, IGNORECLOSEBRACES}, {{NULL, "ignoreeof", 0}, IGNOREEOF}, {{NULL, "incappendhistory", 0}, INCAPPENDHISTORY}, {{NULL, "interactive", OPT_SPECIAL}, INTERACTIVE}, @@ -439,11 +440,11 @@ printoptionnode(HashNode hn, int set) if (optno < 0) optno = -optno; if (isset(KSHOPTIONPRINT)) { - if (defset(on)) + if (defset(on, emulation)) printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on"); else printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off"); - } else if (set == (isset(optno) ^ defset(on))) { + } else if (set == (isset(optno) ^ defset(on, emulation))) { if (set ^ isset(optno)) fputs("no", stdout); puts(on->node.nam); @@ -475,6 +476,15 @@ createoptiontable(void) optiontab->addnode(optiontab, on->node.nam, on); } +/* Emulation appropriate to the setemulate function */ + +static int setemulate_emulation; + +/* Option array manipulated within the setemulate function */ + +/**/ +static char *setemulate_opts; + /* Setting of default options */ /**/ @@ -490,20 +500,22 @@ setemulate(HashNode hn, int fully) if (!(on->node.flags & OPT_ALIAS) && ((fully && !(on->node.flags & OPT_SPECIAL)) || (on->node.flags & OPT_EMULATE))) - opts[on->optno] = defset(on); + setemulate_opts[on->optno] = defset(on, setemulate_emulation); } /**/ void -installemulation(void) +installemulation(int new_emulation, char *new_opts) { + setemulate_emulation = new_emulation; + setemulate_opts = new_opts; scanhashtable(optiontab, 0, 0, 0, setemulate, - !!(emulation & EMULATE_FULLY)); + !!(new_emulation & EMULATE_FULLY)); } /**/ void -emulate(const char *zsh_name, int fully) +emulate(const char *zsh_name, int fully, int *new_emulation, char *new_opts) { char ch = *zsh_name; @@ -512,17 +524,17 @@ emulate(const char *zsh_name, int fully) /* Work out the new emulation mode */ if (ch == 'c') - emulation = EMULATE_CSH; + *new_emulation = EMULATE_CSH; else if (ch == 'k') - emulation = EMULATE_KSH; + *new_emulation = EMULATE_KSH; else if (ch == 's' || ch == 'b') - emulation = EMULATE_SH; + *new_emulation = EMULATE_SH; else - emulation = EMULATE_ZSH; + *new_emulation = EMULATE_ZSH; if (fully) - emulation |= EMULATE_FULLY; - installemulation(); + *new_emulation |= EMULATE_FULLY; + installemulation(*new_emulation, new_opts); if (funcstack && funcstack->tp == FS_FUNC) { /* @@ -532,9 +544,9 @@ 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; + new_opts[XTRACE] = 1; } } } @@ -545,7 +557,7 @@ emulate(const char *zsh_name, int fully) static void setoption(HashNode hn, int value) { - dosetopt(((Optname) hn)->optno, value, 0); + dosetopt(((Optname) hn)->optno, value, 0, opts); } /**/ @@ -582,7 +594,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) } if(!(optno = optlookup(*args))) zwarnnam(nam, "no such option: %s", *args); - else if(dosetopt(optno, action, 0)) + else if(dosetopt(optno, action, 0, opts)) zwarnnam(nam, "can't change option: %s", *args); break; } else if(**args == 'm') { @@ -590,7 +602,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) } else { if (!(optno = optlookupc(**args))) zwarnnam(nam, "bad option: -%c", **args); - else if(dosetopt(optno, action, 0)) + else if(dosetopt(optno, action, 0, opts)) zwarnnam(nam, "can't change option: -%c", **args); } } @@ -603,7 +615,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) while (*args) { if(!(optno = optlookup(*args++))) zwarnnam(nam, "no such option: %s", args[-1]); - else if(dosetopt(optno, !isun, 0)) + else if(dosetopt(optno, !isun, 0, opts)) zwarnnam(nam, "can't change option: %s", args[-1]); } } else { @@ -713,7 +725,7 @@ static char *rparams[] = { /**/ mod_export int -dosetopt(int optno, int value, int force) +dosetopt(int optno, int value, int force, char *new_opts) { if(!optno) return -1; @@ -735,7 +747,7 @@ dosetopt(int optno, int value, int force) return -1; } else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN || optno == SINGLECOMMAND)) { - if (opts[optno] == value) + if (new_opts[optno] == value) return 0; /* it is not permitted to change the value of these options */ return -1; @@ -751,7 +763,7 @@ dosetopt(int optno, int value, int force) #endif /* HAVE_SETUID */ #ifdef JOB_CONTROL } else if (!force && optno == MONITOR && value) { - if (opts[optno] == value) + if (new_opts[optno] == value) return 0; if (SHTTY != -1) { origpgrp = GETPGRP(); @@ -767,15 +779,15 @@ dosetopt(int optno, int value, int force) 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); - opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0; + new_opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0; } else if (optno == SUNKEYBOARDHACK) { /* for backward compatibility */ keyboardhackchar = (value ? '`' : '\0'); } - opts[optno] = value; + new_opts[optno] = value; if (optno == BANGHIST || optno == SHINSTDIN) inittyptab(); return 0; @@ -817,10 +829,11 @@ printoptionnodestate(HashNode hn, int hadplus) int optno = on->optno; if (hadplus) { - if (defset(on) != isset(optno)) - printf("set -o %s%s\n", defset(on) ? "no" : "", on->node.nam); + if (defset(on, emulation) != isset(optno)) + printf("set -o %s%s\n", defset(on, emulation) ? + "no" : "", on->node.nam); } else { - if (defset(on)) + if (defset(on, emulation)) printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on"); else printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off"); diff --git a/Src/parse.c b/Src/parse.c index e4d038b6e..0f5d99cef 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 */ @@ -1607,6 +1610,11 @@ par_simple(int *complex, int nr) } else if (tok == ENVARRAY) { int oldcmdpos = incmdpos, n, type2; + /* + * We consider array setting complex because it can + * contain process substitutions, which need a valid job. + */ + *complex = c = 1; p = ecadd(0); incmdpos = 0; if ((type2 = strlen(tokstr) - 1) && tokstr[type2] == '+') { @@ -2110,7 +2118,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 +2379,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 +2397,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 +2415,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 +2453,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 +2472,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; } @@ -3479,7 +3487,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/prototypes.h b/Src/prototypes.h index f059b6620..00988ac4c 100644 --- a/Src/prototypes.h +++ b/Src/prototypes.h @@ -49,11 +49,18 @@ extern int tgetent _((char *bp, TC_CONST char *name)); extern int tgetnum _((char *id)); extern int tgetflag _((char *id)); extern char *tgetstr _((char *id, char **area)); -extern char *tgoto _((TC_CONST char *cm, int destcol, int destline)); extern int tputs _((TC_CONST char *cp, int affcnt, int (*outc) (int))); #undef TC_CONST #endif +/* + * Some systems that do have termcap headers nonetheless don't + * declare tgoto, so we detect if that is missing separately. + */ +#ifdef TGOTO_PROTO_MISSING +char *tgoto(const char *cap, int col, int row); +#endif + /* MISSING PROTOTYPES FOR VARIOUS OPERATING SYSTEMS */ #if defined(__hpux) && defined(_HPUX_SOURCE) && !defined(_XPG4_EXTENDED) 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/subst.c b/Src/subst.c index 932f41287..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; @@ -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/utils.c b/Src/utils.c index d35ca1dfd..26e2a5c2c 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -2030,13 +2030,20 @@ skipparens(char inpar, char outpar, char **s) return level; } +/**/ +mod_export zlong +zstrtol(const char *s, char **t, int base) +{ + return zstrtol_underscore(s, t, base, 0); +} + /* Convert string to zlong (see zsh.h). This function (without the z) * * is contained in the ANSI standard C library, but a lot of them seem * * to be broken. */ /**/ mod_export zlong -zstrtol(const char *s, char **t, int base) +zstrtol_underscore(const char *s, char **t, int base, int underscore) { const char *inp, *trunc = NULL; zulong calc = 0, newcalc = 0; @@ -2062,22 +2069,24 @@ zstrtol(const char *s, char **t, int base) if (base < 2 || base > 36) { zerr("invalid base (must be 2 to 36 inclusive): %d", base); return (zlong)0; - } else if (base <= 10) - for (; *s >= '0' && *s < ('0' + base); s++) { - if (trunc) + } else if (base <= 10) { + for (; (*s >= '0' && *s < ('0' + base)) || + (underscore && *s == '_'); s++) { + if (trunc || *s == '_') continue; newcalc = calc * base + *s - '0'; if (newcalc < calc) { - trunc = s; - continue; + trunc = s; + continue; } calc = newcalc; } - else + } else { for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10)) - || (*s >= 'A' && *s < ('A' + base - 10)); s++) { - if (trunc) + || (*s >= 'A' && *s < ('A' + base - 10)) + || (underscore && *s == '_'); s++) { + if (trunc || *s == '_') continue; newcalc = calc*base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9); if (newcalc < calc) @@ -2087,6 +2096,7 @@ zstrtol(const char *s, char **t, int base) } calc = newcalc; } + } /* * Special case: check for a number that was just too long for @@ -2877,7 +2887,7 @@ zjoin(char **arr, int delim, int heap) * of items into an array of strings. */ /**/ -char ** +mod_export char ** colonsplit(char *s, int uniq) { int ct; @@ -232,7 +232,7 @@ enum { * appear in strings and don't necessarily represent a single character. */ -enum { +enum lextok { NULLTOK, /* 0 */ SEPER, NEWLIN, @@ -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. */ @@ -1554,6 +1555,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 */ @@ -1969,6 +1971,7 @@ enum { COMPLETEINWORD, CORRECT, CORRECTALL, + CONTINUEONERROR, CPRECEDENCES, CSHJUNKIEHISTORY, CSHJUNKIELOOPS, @@ -2103,6 +2106,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]) @@ -2111,6 +2120,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 */ /***********************************************/ @@ -2135,6 +2165,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 +2183,7 @@ struct ttyinfo { # endif # endif # endif +#endif /* flags for termflags */ @@ -2678,7 +2710,14 @@ 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 +/* + * 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) diff --git a/Src/zsh_system.h b/Src/zsh_system.h index f20a7bb90..f38533023 100644 --- a/Src/zsh_system.h +++ b/Src/zsh_system.h @@ -874,7 +874,3 @@ extern short ospeed; # endif # endif #endif - -#ifdef TGOTO_PROTO_MISSING -char *tgoto(const char *cap, int col, int row); -#endif |