From a2159285e80508bb682d90a71270fbddada8bd05 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Fri, 18 Jun 1999 10:55:45 +0000 Subject: zsh-3.1.5-pws-22 --- Src/Builtins/rlimits.c | 17 +- Src/Makefile.in | 8 +- Src/Modules/zftp.c | 11 +- Src/Zle/zle_misc.c | 5 +- Src/Zle/zle_tricky.c | 91 +++---- Src/builtin.c | 63 ++--- Src/cond.c | 91 +++---- Src/exec.c | 396 +++++++++++++++++------------- Src/glob.c | 24 +- Src/hashtable.c | 4 +- Src/hist.c | 110 ++++++--- Src/init.c | 31 ++- Src/jobs.c | 35 +-- Src/lex.c | 76 +++++- Src/linklist.c | 4 +- Src/loop.c | 64 ++--- Src/math.c | 14 +- Src/mem.c | 55 ++++- Src/params.c | 21 +- Src/parse.c | 56 ++++- Src/signals.c | 2 +- Src/subst.c | 4 +- Src/text.c | 36 +-- Src/utils.c | 641 +++++++++++++++---------------------------------- Src/zsh.export | 3 +- Src/zsh.h | 14 +- Src/zsh.mdd | 11 +- 27 files changed, 966 insertions(+), 921 deletions(-) (limited to 'Src') diff --git a/Src/Builtins/rlimits.c b/Src/Builtins/rlimits.c index f8167a106..505b024e4 100644 --- a/Src/Builtins/rlimits.c +++ b/Src/Builtins/rlimits.c @@ -222,8 +222,21 @@ printulimit(int lim, int hard, int head) /* display the limit */ if (limit == RLIM_INFINITY) printf("unlimited\n"); - else - printf("%ld\n", (long)limit); + else { +# ifdef RLIM_T_IS_QUAD_T + printf("%qd\n", limit); +# else +# ifdef RLIM_T_IS_LONG_LONG + printf("%lld\n", limit); +# else +# ifdef RLIM_T_IS_UNSIGNED + printf("%lu\n", limit); +# else + printf("%ld\n", limit); +# endif /* RLIM_T_IS_UNSIGNED */ +# endif /* RLIM_T_IS_LONG_LONG */ +# endif /* RLIM_T_IS_QUAD_T */ + } } /* limit: set or show resource limits. The variable hard indicates * diff --git a/Src/Makefile.in b/Src/Makefile.in index dd96aaf90..e98a696e4 100644 --- a/Src/Makefile.in +++ b/Src/Makefile.in @@ -205,8 +205,12 @@ clean: clean-modules distclean: distclean-modules realclean: realclean-modules -mostlyclean-modules clean-modules distclean-modules realclean-modules: Makemod - @$(MAKE) -f Makemod $(MAKEDEFS) `echo $@ | sed 's/-modules//'` +# Don't remake Makemod just to delete things, even if it doesn't exist. +mostlyclean-modules clean-modules distclean-modules realclean-modules: + if test -f Makemod; then \ + @$(MAKE) -f Makemod $(MAKEDEFS) `echo $@ | sed 's/-modules//'`; \ + fi; \ + exit 0 @CLEAN_MK@ diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index 873617e95..63bca854c 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -230,7 +230,7 @@ static char *lastmsg, lastcodestr[4]; static int lastcode; /* flag for remote system is UNIX --- useful to know as things are simpler */ -static int zfis_unix, zfpassive_conn; +static int zfpassive_conn; /* remote system has size, mdtm commands */ enum { @@ -1786,7 +1786,6 @@ zftp_open(char *name, char **args, int flags) return 1; } - zfis_unix = 0; zfhas_size = zfhas_mdtm = ZFCP_UNKN; zdfd = -1; /* initial status: open, ASCII data, stream mode 'n' stuff */ @@ -2039,14 +2038,12 @@ zftp_login(char *name, char **args, int flags) /* * Use binary for transfers. This simple test saves much * hassle for all concerned, particularly me. + * + * We could set this based just on the UNIX part, + * but I don't really know the consequences of that. */ zfstatus |= ZFST_IMAG; - zfis_unix = 1; } - /* - * we could set zfis_unix based just on the UNIX part, - * but I don't really know the consequences of that. - */ zfsetparam("ZFTP_SYSTEM", systype, ZFPM_READONLY); } zfstatus |= ZFST_SYST; diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index c12c5894b..e2ccfbc46 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -788,9 +788,8 @@ static char *suffixfunc; void makesuffix(int n) { - suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] = - suffixlen[';'] = suffixlen['|'] = suffixlen['&'] = - suffixlen['<'] = suffixlen['>'] = n; + suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] = + suffixlen[';'] = suffixlen['&'] = suffixlen['|'] = n; } /* Set up suffix for parameter names: the last n characters are a suffix * diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 281fe211d..8c2ae7bb6 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -681,12 +681,11 @@ cmphaswilds(char *str) /* Check if we have to complete a parameter name. */ static char * -check_param(char *s, int set, char **ep) +check_param(char *s, int set, int test) { char *p; - int bq = 0, eq = 0, i; - if (!ep) + if (!test) ispar = parq = eparq = 0; /* Try to find a `$'. */ for (p = s + offs; p > s && *p != String && *p != Qstring; p--); @@ -726,9 +725,9 @@ check_param(char *s, int set, char **ep) e = b; if (br) { - while (*e == (ep ? Dnull : '"')) - e++, parq++, bq++; - if (!ep) + while (*e == (test ? Dnull : '"')) + e++, parq++; + if (!test) b = e; } /* Find the end of the name. */ @@ -749,14 +748,12 @@ check_param(char *s, int set, char **ep) if (offs <= e - s && offs >= b - s && n <= 0) { if (br) { p = e; - while (*p == (ep ? Dnull : '"')) - p++, parq--, eparq++, eq++; + while (*p == (test ? Dnull : '"')) + p++, parq--, eparq++; } /* It is. */ - if (ep) { - *ep = e; + if (test) return b; - } /* If we were called from makecomplistflags(), we have to set the * global variables. */ @@ -765,21 +762,12 @@ check_param(char *s, int set, char **ep) mflags |= CMF_PARBR; /* Get the prefix (anything up to the character before the name). */ - for (i = eq, p = e; i; i--, p++) - *p = '.'; - isuf = quotename(e, NULL); - for (i = eq, p = isuf; i; i--, p++) - *p = '"'; + isuf = dupstring(e); + untokenize(isuf); *e = '\0'; ripre = dupstring(s); ripre[b - s] = '\0'; - for (i = bq, p = ripre + (b - s) - 1; i; i--, p--) - *p = '.'; - ipre = quotename(ripre, NULL); - for (i = bq, p = ripre + strlen(ripre) - 1; i; i--, p--) - *p = '"'; - for (i = bq, p = ipre + strlen(ipre) - 1; i; i--, p--) - *p = '"'; + ipre = dupstring(ripre); untokenize(ipre); } else @@ -1231,8 +1219,7 @@ get_comp_string(void) clwpos = -1; lexsave(); inpush(dupstrspace((char *) linptr), 0, NULL); - strinbeg(); - stophist = 2; + strinbeg(0); i = tt0 = cp = rd = ins = oins = linarr = parct = ia = 0; /* This loop is possibly the wrong way to do this. It goes through * @@ -1535,11 +1522,12 @@ get_comp_string(void) /* This variable will hold the current word in quoted form. */ qword = ztrdup(s); offs = cs - wb; - if ((p = check_param(s, 0, &tt))) { - for (; *p == Dnull; p++) - *p = '"'; - for (; *tt == Dnull; tt++) - *tt = '"'; + if ((p = check_param(s, 0, 1))) { + for (p = s; *p; p++) + if (*p == Dnull) + *p = '"'; + else if (*p == Snull) + *p = '\''; } if (*s == Snull || *s == Dnull) { char *q = (*s == Snull ? "'" : "\""), *n = tricat(qipre, q, ""); @@ -3427,7 +3415,7 @@ add_match_data(int alt, char *str, Cline line, Aminfo ai = (alt ? fainfo : ainfo); int palen, salen, qipl, ipl, pl, ppl, qisl, isl, psl; - palen = salen = qipl = ipl = pl = ppl = isl = psl = 0; + palen = salen = qipl = ipl = pl = ppl = qisl = isl = psl = 0; DPUTS(!line, "BUG: add_match_data() without cline"); @@ -4369,10 +4357,10 @@ docompletion(char *s, int lst, int incmd) invalidatelist(); /* Print the explanation strings if needed. */ - if (!showinglist && validlist && nmatches != 1) { + if (!showinglist && validlist && usemenu != 2 && nmatches != 1) { Cmgroup g = amatches; Cexpl *e; - int up = 0, tr = 1; + int up = 0, tr = 1, nn = 0; if (!nmatches) feep(); @@ -4385,7 +4373,12 @@ docompletion(char *s, int lst, int incmd) trashzle(); tr = 0; } + if (nn) { + up++; + putc('\n', shout); + } up += printfmt((*e)->str, (*e)->count, 1); + nn = 1; } e++; } @@ -4915,6 +4908,9 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) int ois = instring, oib = inbackt; char *tmp, *p, *ns, *ol = (char *) line, sav, oaq = autoq, *qp, *qs; + swb = swe = soffs = 0; + ns = NULL; + /* Put the string in the lexer buffer and call the lexer to * * get the words we have to expand. */ zleparse = 1; @@ -4930,8 +4926,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) inpush(dupstrspace(tmp), 0, NULL); line = (unsigned char *) tmp; ll = tl - 1; - strinbeg(); - stophist = 2; + strinbeg(0); noaliases = 1; do { ctxtlex(); @@ -4979,11 +4974,21 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) ll = oll; if (cur < 0 || i < 1) return 1; + owb = offs; + offs = soffs; + if ((p = check_param(ns, 0, 1))) { + for (p = ns; *p; p++) + if (*p == Dnull) + *p = '"'; + else if (*p == Snull) + *p = '\''; + } + offs = owb; if (*ns == Snull || *ns == Dnull) { instring = (*ns == Snull ? 1 : 2); inbackt = 0; swb++; - if (ns[strlen(ns) - 1] == *ns) + if (ns[strlen(ns) - 1] == *ns && ns[1]) swe--; autoq = (*ns == Snull ? '\'' : '"'); } else { @@ -5028,7 +5033,8 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) char **ow = clwords, *os = cmdstr, *oqp = qipre, *oqs = qisuf; int olws = clwsize, olwn = clwnum, olwp = clwpos; int obr = brange, oer = erange, oof = offs; - + unsigned long occ = ccont; + clwsize = clwnum = countlinknodes(foo); clwords = (char **) zalloc((clwnum + 1) * sizeof(char *)); for (n = firstnode(foo), i = 0; n; incnode(n), i++) { @@ -5043,7 +5049,9 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) qipre = qp; qisuf = qs; offs = soffs; + ccont = CC_CCCONT; makecomplistcmd(ns, !clwpos, CFN_FIRST); + ccont = occ; offs = oof; zsfree(cmdstr); cmdstr = os; @@ -6341,7 +6349,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) tmpbuf = (char *)zhalloc(strlen(cc->str) + 5); sprintf(tmpbuf, "foo %s", cc->str); /* KLUDGE! */ inpush(tmpbuf, 0, NULL); - strinbeg(); + strinbeg(0); noaliases = 1; do { ctxtlex(); @@ -6502,7 +6510,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) int oldn = clwnum, oldp = clwpos; unsigned long occ = ccont; - ccont = 0; + ccont = CC_CCCONT; /* So we restrict the words-array. */ if (brange >= clwnum) @@ -8099,14 +8107,13 @@ doexpandhist(void) lexsave(); /* We push ol as it will remain unchanged */ inpush((char *) ol, 0, NULL); - strinbeg(); + strinbeg(1); noaliases = 1; noerrs = 1; exlast = inbufct; do { ctxtlex(); } while (tok != ENDINPUT && tok != LEXERR); - stophist = 2; while (!lexstop) hgetc(); /* We have to save errflags because it's reset in lexrestore. Since * @@ -8178,7 +8185,7 @@ getcurcmd(void) metafy_line(); inpush(dupstrspace((char *) line), 0, NULL); unmetafy_line(); - strinbeg(); + strinbeg(1); pushheap(); do { curlincmd = incmdpos; diff --git a/Src/builtin.c b/Src/builtin.c index 4c9b159dd..d74d9cd88 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -43,7 +43,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, bin_alias, 0, -1, 0, "Lgmr", NULL), - BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "t", "u"), + BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "tU", "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), @@ -64,7 +64,7 @@ static struct builtin builtins[] = BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL), BUILTIN("fc", BINF_FCOPTS, bin_fc, 0, -1, BIN_FC, "nlreIRWAdDfEim", NULL), BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL), - BUILTIN("functions", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "mtu", NULL), + BUILTIN("functions", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "mtuU", 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, "dfmrv", NULL), @@ -209,7 +209,7 @@ execbuiltin(LinkList args, Builtin bn) LinkNode n; char ops[MAX_OPS], *arg, *pp, *name, **argv, **oargv, *optstr; char *oxarg, *xarg = NULL; - int flags, sense, argc = 0, execop; + int flags, sense, argc = 0, execop, xtr = isset(XTRACE), lxarg = 0; /* initialise some static variables */ auxdata = NULL; @@ -250,12 +250,21 @@ execbuiltin(LinkList args, Builtin bn) break; } /* save the options in xarg, for execution tracing */ - if (xarg) { - oxarg = tricat(xarg, " ", arg); - zsfree(xarg); - xarg = oxarg; - } else - xarg = ztrdup(arg); + if (xtr) { + if (xarg) { + int l = strlen(arg) + lxarg + 1; + + oxarg = zhalloc(l + 1); + strcpy(oxarg, xarg); + oxarg[lxarg] = ' '; + strcpy(oxarg + lxarg + 1, arg); + xarg = oxarg; + lxarg = l + 1; + } else { + xarg = dupstring(arg); + lxarg = strlen(xarg); + } + } /* handle -- or - (ops['-']), and + (ops['-'] and ops['+']) */ if (arg[1] == '-') arg++; @@ -283,7 +292,6 @@ execbuiltin(LinkList args, Builtin bn) if(*arg == Meta) *++arg ^= 32; zerr("bad option: -%c", NULL, *arg); - zsfree(xarg); return 1; } arg = (char *) ugetnode(args); @@ -330,7 +338,6 @@ execbuiltin(LinkList args, Builtin bn) while ((*argv++ = (char *)ugetnode(args))); argv = oargv; if (errflag) { - zsfree(xarg); errflag = 0; return 1; } @@ -339,12 +346,11 @@ execbuiltin(LinkList args, Builtin bn) if (argc < bn->minargs || (argc > bn->maxargs && bn->maxargs != -1)) { zwarnnam(name, (argc < bn->minargs) ? "not enough arguments" : "too many arguments", NULL, 0); - zsfree(xarg); return 1; } /* display execution trace information, if required */ - if (isset(XTRACE)) { + if (xtr) { fprintf(stderr, "%s%s", (prompt4) ? prompt4 : "", name); if (xarg) fprintf(stderr, " %s", xarg); @@ -353,7 +359,6 @@ execbuiltin(LinkList args, Builtin bn) fputc('\n', stderr); fflush(stderr); } - zsfree(xarg); /* call the handler function, and return its return value */ return (*(bn->handlerfunc)) (name, argv, ops, bn->funcid); } @@ -1824,17 +1829,18 @@ bin_functions(char *name, char **argv, char *ops, int func) int on = 0, off = 0; /* Do we have any flags defined? */ - if (ops['u'] || ops['t']) { - if (ops['u'] == 1) - on |= PM_UNDEFINED; - else if (ops['u'] == 2) - off |= PM_UNDEFINED; - - if (ops['t'] == 1) - on |= PM_TAGGED; - else if (ops['t'] == 2) - off |= PM_TAGGED; - } + if (ops['u'] == 1) + on |= PM_UNDEFINED; + else if (ops['u'] == 2) + off |= PM_UNDEFINED; + if (ops['U'] == 1) + on |= PM_UNALIASED|PM_UNDEFINED; + else if (ops['U'] == 2) + off |= PM_UNALIASED; + if (ops['t'] == 1) + on |= PM_TAGGED; + else if (ops['t'] == 2) + off |= PM_TAGGED; if (off & PM_UNDEFINED) { zwarnnam(name, "invalid option(s)", NULL, 0); @@ -1845,6 +1851,8 @@ bin_functions(char *name, char **argv, char *ops, int func) * are given, we will print only functions containing these * * flags, else we'll print them all. */ if (!*argv) { + if (ops['U'] && !ops['u']) + on &= ~PM_UNDEFINED; scanhashtable(shfunctab, 1, on|off, DISABLED, shfunctab->printnode, 0); return 0; } @@ -3078,8 +3086,7 @@ bin_eval(char *nam, char **argv, char *ops, int func) List list; inpush(zjoin(argv, ' '), 0, NULL); - strinbeg(); - stophist = 2; + strinbeg(0); list = parse_list(); strinend(); inpop(); @@ -3584,7 +3591,7 @@ bin_trap(char *name, char **argv, char *ops, int func) if (!sigfuncs[sig]) printf("trap -- '' %s\n", sigs[sig]); else { - s = getpermtext((void *) dupstruct((void *) sigfuncs[sig])); + s = getpermtext((void *) sigfuncs[sig]); printf("trap -- "); quotedzputs(s, stdout); printf(" %s\n", sigs[sig]); diff --git a/Src/cond.c b/Src/cond.c index a8387a454..98deea2bf 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -42,6 +42,7 @@ int evalcond(Cond c) { struct stat *st; + char *left, *right = NULL; switch (c->type) { case COND_NOT: @@ -103,107 +104,109 @@ evalcond(Cond c) return 0; } } - singsub((char **)&c->left); - untokenize(c->left); + left = dupstring((char *) c->left); + singsub(&left); + untokenize(left); if (c->right) { - singsub((char **)&c->right); + right = dupstring((char *) c->right); + singsub(&right); if (c->type != COND_STREQ && c->type != COND_STRNEQ) - untokenize(c->right); + untokenize(right); } if (tracingcond) { if (c->type < COND_MOD) { - char *rt = (char *)c->right; + char *rt = (char *)right; if (c->type == COND_STREQ || c->type == COND_STRNEQ) { rt = dupstring(rt); untokenize(rt); } - fprintf(stderr, " %s %s %s", (char *)c->left, condstr[c->type], + fprintf(stderr, " %s %s %s", (char *)left, condstr[c->type], rt); } else - fprintf(stderr, " -%c %s", c->type, (char *)c->left); + fprintf(stderr, " -%c %s", c->type, (char *)left); } switch (c->type) { case COND_STREQ: - return matchpat(c->left, c->right); + return matchpat(left, right); case COND_STRNEQ: - return !matchpat(c->left, c->right); + return !matchpat(left, right); case COND_STRLT: - return strcmp(c->left, c->right) < 0; + return strcmp(left, right) < 0; case COND_STRGTR: - return strcmp(c->left, c->right) > 0; + return strcmp(left, right) > 0; case 'e': case 'a': - return (doaccess(c->left, F_OK)); + return (doaccess(left, F_OK)); case 'b': - return (S_ISBLK(dostat(c->left))); + return (S_ISBLK(dostat(left))); case 'c': - return (S_ISCHR(dostat(c->left))); + return (S_ISCHR(dostat(left))); case 'd': - return (S_ISDIR(dostat(c->left))); + return (S_ISDIR(dostat(left))); case 'f': - return (S_ISREG(dostat(c->left))); + return (S_ISREG(dostat(left))); case 'g': - return (!!(dostat(c->left) & S_ISGID)); + return (!!(dostat(left) & S_ISGID)); case 'k': - return (!!(dostat(c->left) & S_ISVTX)); + return (!!(dostat(left) & S_ISVTX)); case 'n': - return (!!strlen(c->left)); + return (!!strlen(left)); case 'o': - return (optison(c->left)); + return (optison(left)); case 'p': - return (S_ISFIFO(dostat(c->left))); + return (S_ISFIFO(dostat(left))); case 'r': - return (doaccess(c->left, R_OK)); + return (doaccess(left, R_OK)); case 's': - return ((st = getstat(c->left)) && !!(st->st_size)); + return ((st = getstat(left)) && !!(st->st_size)); case 'S': - return (S_ISSOCK(dostat(c->left))); + return (S_ISSOCK(dostat(left))); case 'u': - return (!!(dostat(c->left) & S_ISUID)); + return (!!(dostat(left) & S_ISUID)); case 'w': - return (doaccess(c->left, W_OK)); + return (doaccess(left, W_OK)); case 'x': if (privasserted()) { - mode_t mode = dostat(c->left); + mode_t mode = dostat(left); return (mode & S_IXUGO) || S_ISDIR(mode); } - return doaccess(c->left, X_OK); + return doaccess(left, X_OK); case 'z': - return (!strlen(c->left)); + return (!strlen(left)); case 'h': case 'L': - return (S_ISLNK(dolstat(c->left))); + return (S_ISLNK(dolstat(left))); case 'O': - return ((st = getstat(c->left)) && st->st_uid == geteuid()); + return ((st = getstat(left)) && st->st_uid == geteuid()); case 'G': - return ((st = getstat(c->left)) && st->st_gid == getegid()); + return ((st = getstat(left)) && st->st_gid == getegid()); case 'N': - return ((st = getstat(c->left)) && st->st_atime <= st->st_mtime); + return ((st = getstat(left)) && st->st_atime <= st->st_mtime); case 't': - return isatty(matheval(c->left)); + return isatty(matheval(left)); case COND_EQ: - return matheval(c->left) == matheval(c->right); + return matheval(left) == matheval(right); case COND_NE: - return matheval(c->left) != matheval(c->right); + return matheval(left) != matheval(right); case COND_LT: - return matheval(c->left) < matheval(c->right); + return matheval(left) < matheval(right); case COND_GT: - return matheval(c->left) > matheval(c->right); + return matheval(left) > matheval(right); case COND_LE: - return matheval(c->left) <= matheval(c->right); + return matheval(left) <= matheval(right); case COND_GE: - return matheval(c->left) >= matheval(c->right); + return matheval(left) >= matheval(right); case COND_NT: case COND_OT: { time_t a; - if (!(st = getstat(c->left))) + if (!(st = getstat(left))) return 0; a = st->st_mtime; - if (!(st = getstat(c->right))) + if (!(st = getstat(right))) return 0; return (c->type == COND_NT) ? a > st->st_mtime : a < st->st_mtime; } @@ -212,11 +215,11 @@ evalcond(Cond c) dev_t d; ino_t i; - if (!(st = getstat(c->left))) + if (!(st = getstat(left))) return 0; d = st->st_dev; i = st->st_ino; - if (!(st = getstat(c->right))) + if (!(st = getstat(right))) return 0; return d == st->st_dev && i == st->st_ino; } diff --git a/Src/exec.c b/Src/exec.c index 952dfbb78..5cfe3e3ef 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -139,8 +139,7 @@ parse_string(char *s) lexsave(); inpush(s, 0, NULL); - strinbeg(); - stophist = 2; + strinbeg(0); l = parse_list(); strinend(); inpop(); @@ -298,12 +297,12 @@ static char list_pipe_text[JOBTEXTSIZE]; /**/ static int -execcursh(Cmd cmd) +execcursh(Cmd cmd, LinkList args, int flags) { if (!list_pipe) deletejob(jobtab + thisjob); - execlist(cmd->u.list, 1, cmd->flags & CFLAG_EXEC); - cmd->u.list = NULL; + execlist(cmd->u.list, 1, flags & CFLAG_EXEC); + return lastval; } @@ -718,7 +717,6 @@ execlist(List list, int dont_change_job, int exiting) /* Reset donetrap: this ensures that a trap is only * * called once for each sublist that fails. */ donetrap = 0; - simplifyright(list); slist = list->left; /* Loop through code followed by &&, ||, or end of sublist. */ @@ -1009,11 +1007,13 @@ execpline2(Pline pline, int how, int input, int output, int last1) lineno = pline->left->lineno; if (pline_level == 1) - strcpy(list_pipe_text, getjobtext((void *) pline->left)); - if (pline->type == END) { + if (!sfcontext) + strcpy(list_pipe_text, getjobtext((void *) pline->left)); + else + list_pipe_text[0] = '\0'; + if (pline->type == END) execcmd(pline->left, input, output, how, last1 ? 1 : 2); - pline->left = NULL; - } else { + else { int old_list_pipe = list_pipe; mpipe(pipes); @@ -1046,11 +1046,10 @@ execpline2(Pline pline, int how, int input, int output, int last1) _exit(lastval); } } else { - /* otherwise just do the pipeline normally. */ + /* otherwise just do the pipeline normally. */ subsh_close = pipes[0]; execcmd(pline->left, input, pipes[1], how, 0); } - pline->left = NULL; zclose(pipes[1]); if (pline->right) { /* if another execpline() is invoked because the command is * @@ -1102,13 +1101,17 @@ makecline(LinkList list) void untokenize(char *s) { - for (; *s; s++) - if (itok(*s)) { - if (*s == Nularg) - chuck(s--); - else - *s = ztokens[*s - Pound]; - } + if (*s) { + char *p = s, c; + + while ((c = *s++)) + if (itok(c)) { + if (c != Nularg) + *p++ = ztokens[c - Pound]; + } else + *p++ = c; + *p = '\0'; + } } /* Open a file for writing redicection */ @@ -1152,34 +1155,34 @@ clobber_open(struct redir *f) static void closemn(struct multio **mfds, int fd) { - struct multio *mn = mfds[fd]; - char buf[TCBUFSIZE]; - int len, i; + if (fd >= 0 && mfds[fd] && mfds[fd]->ct >= 2) { + struct multio *mn = mfds[fd]; + char buf[TCBUFSIZE]; + int len, i; - if (fd < 0 || !mfds[fd] || mfds[fd]->ct < 2) - return; - if (zfork()) { - for (i = 0; i < mn->ct; i++) - zclose(mn->fds[i]); - zclose(mn->pipe); - mn->ct = 1; - mn->fds[0] = fd; - return; - } - /* pid == 0 */ - closeallelse(mn); - if (mn->rflag) { - /* tee process */ - while ((len = read(mn->pipe, buf, TCBUFSIZE)) > 0) + if (zfork()) { for (i = 0; i < mn->ct; i++) - write(mn->fds[i], buf, len); - } else { - /* cat process */ - for (i = 0; i < mn->ct; i++) - while ((len = read(mn->fds[i], buf, TCBUFSIZE)) > 0) - write(mn->pipe, buf, len); + zclose(mn->fds[i]); + zclose(mn->pipe); + mn->ct = 1; + mn->fds[0] = fd; + return; + } + /* pid == 0 */ + closeallelse(mn); + if (mn->rflag) { + /* tee process */ + while ((len = read(mn->pipe, buf, TCBUFSIZE)) > 0) + for (i = 0; i < mn->ct; i++) + write(mn->fds[i], buf, len); + } else { + /* cat process */ + for (i = 0; i < mn->ct; i++) + while ((len = read(mn->fds[i], buf, TCBUFSIZE)) > 0) + write(mn->pipe, buf, len); + } + _exit(0); } - _exit(0); } /* close all the mnodes (failure) */ @@ -1273,9 +1276,10 @@ static void addvars(LinkList l, int export) { Varasg v; + LinkNode n; LinkList vl; int xtr; - char **arr, **ptr; + char **arr, **ptr, *name; xtr = isset(XTRACE); if (xtr && nonempty(l)) { @@ -1283,26 +1287,30 @@ addvars(LinkList l, int export) doneps4 = 1; } - while (nonempty(l)) { - v = (Varasg) ugetnode(l); - singsub(&v->name); + for (n = firstnode(l); n; incnode(n)) { + v = (Varasg) getdata(n); + name = dupstring(v->name); + singsub(&name); if (errflag) return; - untokenize(v->name); + untokenize(name); if (xtr) - fprintf(stderr, "%s=", v->name); + fprintf(stderr, "%s=", name); if (v->type == PM_SCALAR) { vl = newlinklist(); - addlinknode(vl, v->str); + addlinknode(vl, dupstring(v->str)); } else - vl = v->arr; - prefork(vl, v->type == PM_SCALAR ? (PF_SINGLE|PF_ASSIGN) : PF_ASSIGN); - if (errflag) - return; - if (isset(GLOBASSIGN) || v->type != PM_SCALAR) - globlist(vl); - if (errflag) - return; + vl = listdup(v->arr); + if (vl) { + prefork(vl, v->type == PM_SCALAR ? (PF_SINGLE|PF_ASSIGN) : + PF_ASSIGN); + if (errflag) + return; + if (isset(GLOBASSIGN) || v->type != PM_SCALAR) + globlist(vl); + if (errflag) + return; + } if (v->type == PM_SCALAR && (empty(vl) || !nextnode(firstnode(vl)))) { Param pm; char *val; @@ -1319,7 +1327,7 @@ addvars(LinkList l, int export) if (export) { if (export < 0) { /* We are going to fork so do not bother freeing this */ - pm = (Param) paramtab->removenode(paramtab, v->name); + pm = (Param) paramtab->removenode(paramtab, name); if (isset(RESTRICTED) && (pm->flags & PM_RESTRICTED)) { zerr("%s: restricted", pm->nam, 0); zsfree(val); @@ -1328,18 +1336,22 @@ addvars(LinkList l, int export) } allexp = opts[ALLEXPORT]; opts[ALLEXPORT] = 1; - pm = setsparam(v->name, val); + pm = setsparam(name, val); opts[ALLEXPORT] = allexp; } else - pm = setsparam(v->name, val); + pm = setsparam(name, val); if (errflag) return; continue; } - ptr = arr = (char **) zalloc(sizeof(char **) * (countlinknodes(vl) + 1)); + if (vl) { + ptr = arr = (char **) zalloc(sizeof(char **) * + (countlinknodes(vl) + 1)); - while (nonempty(vl)) - *ptr++ = ztrdup((char *) ugetnode(vl)); + while (nonempty(vl)) + *ptr++ = ztrdup((char *) ugetnode(vl)); + } else + ptr = arr = (char **) zalloc(sizeof(char **)); *ptr = NULL; if (xtr) { @@ -1348,7 +1360,7 @@ addvars(LinkList l, int export) fprintf(stderr, "%s ", *ptr); fprintf(stderr, ") "); } - setaparam(v->name, arr); + setaparam(name, arr); if (errflag) return; } @@ -1364,15 +1376,19 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) struct multio *mfds[10]; char *text; int save[10]; - int fil, dfil, is_cursh, type, i; + int fil, dfil, is_cursh, type, flags, i; int nullexec = 0, assign = 0, forked = 0; int is_shfunc = 0, is_builtin = 0, is_exec = 0; /* Various flags to the command. */ int cflags = 0, checked = 0; + LinkList vars, redir; doneps4 = 0; - args = cmd->args; + args = listdup(cmd->args); type = cmd->type; + flags = cmd->flags; + redir = dupheaplist(cmd->redir); + vars = cmd->vars; for (i = 0; i < 10; i++) { save[i] = -2; @@ -1381,7 +1397,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) /* If the command begins with `%', then assume it is a * * reference to a job in the job table. */ - if (type == SIMPLE && nonempty(args) && + if (type == SIMPLE && args && nonempty(args) && *(char *)peekfirst(args) == '%') { pushnode(args, dupstring((how & Z_DISOWN) ? "disown" : (how & Z_ASYNC) ? "bg" : "fg")); @@ -1393,7 +1409,8 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) * job currently in the job table. If it does, then we treat it * * as a command to resume this job. */ if (isset(AUTORESUME) && type == SIMPLE && (how & Z_SYNC) && - nonempty(args) && empty(cmd->redir) && !input && + args && nonempty(args) && + (!cmd->redir || empty(cmd->redir)) && !input && !nextnode(firstnode(args))) { if (unset(NOTIFY)) scanjobs(); @@ -1407,7 +1424,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) * only works in simple cases. has_token() is called to make sure * * this really is a simple case. */ if (type == SIMPLE) { - while (nonempty(args)) { + while (args && nonempty(args)) { char *cmdarg = (char *) peekfirst(args); checked = !has_token(cmdarg); if (!checked) @@ -1444,7 +1461,8 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) } /* Do prefork substitutions */ - prefork(args, (assign || isset(MAGICEQUALSUBST)) ? PF_TYPESET : 0); + if (args) + prefork(args, (assign || isset(MAGICEQUALSUBST)) ? PF_TYPESET : 0); if (type == SIMPLE) { int unglobbed = 0; @@ -1453,7 +1471,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) char *cmdarg; if (!(cflags & BINF_NOGLOB)) - while (!checked && !errflag && nonempty(args) && + while (!checked && !errflag && args && nonempty(args) && has_token((char *) peekfirst(args))) glob(args, firstnode(args)); else if (!unglobbed) { @@ -1465,12 +1483,12 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) /* Current shell should not fork unless the * * exec occurs at the end of a pipeline. */ if ((cflags & BINF_EXEC) && last1 == 2) - cmd->flags |= CFLAG_EXEC; + flags |= CFLAG_EXEC; /* Empty command */ - if (empty(args)) { - if (nonempty(cmd->redir)) { - if (cmd->flags & CFLAG_EXEC) { + if (!args || empty(args)) { + if (redir && nonempty(redir)) { + if (flags & CFLAG_EXEC) { /* Was this "exec < foobar"? */ nullexec = 1; break; @@ -1480,17 +1498,23 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) errflag = lastval = 1; return; } else if (readnullcmd && *readnullcmd && - ((Redir) peekfirst(cmd->redir))->type == READ && - !nextnode(firstnode(cmd->redir))) { + ((Redir) peekfirst(redir))->type == READ && + !nextnode(firstnode(redir))) { + if (!args) + args = newlinklist(); addlinknode(args, dupstring(readnullcmd)); - } else + } else { + if (!args) + args = newlinklist(); addlinknode(args, dupstring(nullcmd)); + } } else if ((cflags & BINF_PREFIX) && (cflags & BINF_COMMAND)) { lastval = 0; return; } else { cmdoutval = 0; - addvars(cmd->vars, 0); + if (vars) + addvars(vars, 0); if (errflag) lastval = errflag; else @@ -1502,7 +1526,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) return; } } else if (isset(RESTRICTED) && (cflags & BINF_EXEC) && - (cmd->flags & CFLAG_EXEC)) { + (flags & CFLAG_EXEC)) { zerrnam("exec", "%s: restricted", (char *) getdata(firstnode(args)), 0); lastval = 1; return; @@ -1548,22 +1572,32 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) } /* Get the text associated with this command. */ - if (jobbing || (how & Z_TIMED)) + if (!sfcontext && (jobbing || (how & Z_TIMED))) text = getjobtext((void *) cmd); else text = NULL; /* Set up special parameter $_ */ - zsfree(underscore); - if (nonempty(args) - && (underscore = ztrdup((char *) getdata(lastnode(args))))) - untokenize(underscore); - else - underscore = ztrdup(""); + if (args && nonempty(args)) { + char *u = (char *) getdata(lastnode(args)); + + if (u) { + int ul = strlen(u); + + if (ul >= underscorelen) { + zfree(underscore, underscorelen); + underscore = (char *) zalloc(underscorelen = ul + 32); + } + strcpy(underscore, u); + } else + *underscore = '\0'; + } else + *underscore = '\0'; /* Warn about "rm *" */ if (type == SIMPLE && interact && unset(RMSTARSILENT) - && isset(SHINSTDIN) && nonempty(args) && nextnode(firstnode(args)) + && isset(SHINSTDIN) && args && nonempty(args) + && nextnode(firstnode(args)) && !strcmp(peekfirst(args), "rm")) { LinkNode node, next; @@ -1596,11 +1630,11 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) if (type == SIMPLE && !nullexec) { char *s; char trycd = (isset(AUTOCD) && isset(SHINSTDIN) - && empty(cmd->redir) && !empty(args) + && (!redir || empty(redir)) && args && !empty(args) && !nextnode(firstnode(args)) && *(char *)peekfirst(args)); - DPUTS(empty(args), "BUG: empty(args) in exec.c"); + DPUTS((!args || empty(args)), "BUG: empty(args) in exec.c"); if (!hn) { /* Resolve external commands */ char *cmdarg = (char *) peekfirst(args); @@ -1652,7 +1686,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) * current shell. * **************************************************************************/ - if ((how & Z_ASYNC) || (!(cmd->flags & CFLAG_EXEC) && + if ((how & Z_ASYNC) || (!(flags & CFLAG_EXEC) && (((is_builtin || is_shfunc) && output) || (!is_cursh && (last1 != 1 || sigtrapped[SIGZERR] || sigtrapped[SIGEXIT] || havefiles()))))) { @@ -1677,10 +1711,13 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) #endif if (how & Z_ASYNC) { lastpid = (zlong) pid; - } else if (!jobtab[thisjob].stty_in_env && nonempty(cmd->vars)) { + } else if (!jobtab[thisjob].stty_in_env && + vars && nonempty(vars)) { /* search for STTY=... */ - while (nonempty(cmd->vars)) - if (!strcmp(((Varasg) ugetnode(cmd->vars))->name, "STTY")) { + LinkNode n; + + for (n = firstnode(vars); n; incnode(n)) + if (!strcmp(((Varasg) getdata(n))->name, "STTY")) { jobtab[thisjob].stty_in_env = 1; break; } @@ -1713,7 +1750,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) is_exec = 1; } - if (!(cflags & BINF_NOGLOB)) + if (args && !(cflags & BINF_NOGLOB)) globlist(args); if (errflag) { lastval = 1; @@ -1727,11 +1764,12 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) addfd(forked, save, mfds, 1, output, 1); /* Do process substitutions */ - spawnpipes(cmd->redir); + if (redir) + spawnpipes(redir); /* Do io redirections */ - while (nonempty(cmd->redir)) { - fn = (Redir) ugetnode(cmd->redir); + while (redir && nonempty(redir)) { + fn = (Redir) ugetnode(redir); DPUTS(fn->type == HEREDOC || fn->type == HEREDOCDASH, "BUG: unexpanded here document"); if (fn->type == INPIPE) { @@ -1749,7 +1787,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) } addfd(forked, save, mfds, fn->fd1, fn->fd2, 1); } else { - if (fn->type != HERESTR && xpandredir(fn, cmd->redir)) + if (fn->type != HERESTR && xpandredir(fn, redir)) continue; if (errflag) { closemnodes(mfds); @@ -1870,15 +1908,15 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) if (is_exec) entersubsh(how, type != SUBSH ? 2 : 1, 1); if (type >= CURSH) { - static int (*func[]) _((Cmd)) = { + static int (*func[]) _((Cmd, LinkList, int)) = { execcursh, exectime, execfuncdef, execfor, execwhile, execrepeat, execif, execcase, execselect, execcond, execarith, execautofn }; if (last1 == 1) - cmd->flags |= CFLAG_EXEC; - lastval = (func[type - CURSH]) (cmd); + flags |= CFLAG_EXEC; + lastval = (func[type - CURSH]) (cmd, args, flags); } else if (is_builtin || is_shfunc) { LinkList restorelist = 0, removelist = 0; /* builtin or shell function */ @@ -1889,11 +1927,11 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) !(hn->flags & BINF_PSPECIAL)))) save_params(cmd, &restorelist, &removelist); - if (cmd->vars) { + if (vars) { /* Export this if the command is a shell function, * but not if it's a builtin. */ - addvars(cmd->vars, is_shfunc); + addvars(vars, is_shfunc); if (errflag) { restore_params(restorelist, removelist); lastval = 1; @@ -1904,6 +1942,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) if (is_shfunc) { /* It's a shell function */ + #ifdef PATH_DEV_FD int i; @@ -1914,7 +1953,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) if (subsh_close >= 0) zclose(subsh_close); subsh_close = -1; - execshfunc(cmd, (Shfunc) hn); + execshfunc(cmd, (Shfunc) hn, args); #ifdef PATH_DEV_FD for (i = 10; i <= max_zsh_fd; i++) if (fdtable[i] > 1) @@ -1943,7 +1982,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) clearerr(stdout); } - if (cmd->flags & CFLAG_EXEC) { + if (flags & CFLAG_EXEC) { if (subsh) _exit(lastval); @@ -1957,7 +1996,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) restore_params(restorelist, removelist); } else { - if (cmd->flags & CFLAG_EXEC) { + if (flags & CFLAG_EXEC) { setiparam("SHLVL", --shlvl); /* If we are exec'ing a command, and we are not * * in a subshell, then save the history file. */ @@ -1965,8 +2004,8 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) savehistfile(NULL, 1, HFILE_USE_OPTIONS); } if (type == SIMPLE) { - if (cmd->vars) { - addvars(cmd->vars, -1); + if (vars) { + addvars(vars, -1); if (errflag) _exit(1); } @@ -1981,7 +2020,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1) #endif execute((Cmdnam) hn, cflags & BINF_DASH); } else { /* ( ... ) */ - DPUTS(cmd->vars && nonempty(cmd->vars), + DPUTS(vars && nonempty(vars), "BUG: assigment before complex command"); list_pipe = 0; if (subsh_close >= 0) @@ -2011,7 +2050,11 @@ save_params(Cmd cmd, LinkList *restore_p, LinkList *remove_p) char *s; MUSTUSEHEAP("save_params()"); - + + if (!cmd->vars) { + *restore_p = *remove_p = NULL; + return; + } *restore_p = newlinklist(); *remove_p = newlinklist(); @@ -2283,8 +2326,9 @@ getoutput(char *cmd, int qt) return NULL; if (list != &dummy_list && !list->right && !list->left->flags && list->left->type == END && list->left->left->type == END && - (c = list->left->left->left)->type == SIMPLE && empty(c->args) && - empty(c->vars) && nonempty(c->redir) && + (c = list->left->left->left)->type == SIMPLE && + (!c->args || empty(c->args)) && + (!c->vars || empty(c->vars)) && c->redir && nonempty(c->redir) && !nextnode(firstnode(c->redir)) && (r = (Redir) getdata(firstnode(c->redir)))->fd1 == 0 && r->type == READ) { @@ -2613,7 +2657,7 @@ extern int tracingcond; /**/ static int -execcond(Cmd cmd) +execcond(Cmd cmd, LinkList args, int flags) { int stat; if (isset(XTRACE)) { @@ -2633,18 +2677,19 @@ execcond(Cmd cmd) /**/ static int -execarith(Cmd cmd) +execarith(Cmd cmd, LinkList args, int flags) { char *e; zlong val = 0; if (isset(XTRACE)) fprintf(stderr, "%s((", prompt4 ? prompt4 : ""); - while ((e = (char *) ugetnode(cmd->args))) { - if (isset(XTRACE)) - fprintf(stderr, " %s", e); - val = matheval(e); - } + if (args) + while ((e = (char *) ugetnode(args))) { + if (isset(XTRACE)) + fprintf(stderr, " %s", e); + val = matheval(e); + } if (isset(XTRACE)) { fprintf(stderr, " ))\n"); fflush(stderr); @@ -2657,7 +2702,7 @@ execarith(Cmd cmd) /**/ static int -exectime(Cmd cmd) +exectime(Cmd cmd, LinkList args, int flags) { int jb; @@ -2675,30 +2720,33 @@ exectime(Cmd cmd) /**/ static int -execfuncdef(Cmd cmd) +execfuncdef(Cmd cmd, LinkList args, int flags) { Shfunc shf; char *s; int signum; - PERMALLOC { - while ((s = (char *) ugetnode(cmd->args))) { - shf = (Shfunc) zalloc(sizeof *shf); - shf->funcdef = (List) dupstruct(cmd->u.list); - shf->flags = 0; - - /* is this shell function a signal trap? */ - if (!strncmp(s, "TRAP", 4) && (signum = getsignum(s + 4)) != -1) { - if (settrap(signum, shf->funcdef)) { - freestruct(shf->funcdef); - zfree(shf, sizeof *shf); - LASTALLOC_RETURN 1; - } - sigtrapped[signum] |= ZSIG_FUNC; - } - shfunctab->addnode(shfunctab, ztrdup(s), shf); - } - } LASTALLOC; + if (args) { + PERMALLOC { + while ((s = (char *) ugetnode(args))) { + shf = (Shfunc) zalloc(sizeof *shf); + shf->funcdef = (List) dupstruct(cmd->u.list); + shf->flags = 0; + + /* is this shell function a signal trap? */ + if (!strncmp(s, "TRAP", 4) && + (signum = getsignum(s + 4)) != -1) { + if (settrap(signum, shf->funcdef)) { + freestruct(shf->funcdef); + zfree(shf, sizeof *shf); + LASTALLOC_RETURN 1; + } + sigtrapped[signum] |= ZSIG_FUNC; + } + shfunctab->addnode(shfunctab, ztrdup(s), shf); + } + } LASTALLOC; + } if(isset(HISTNOFUNCTIONS)) remhist(); return 0; @@ -2708,7 +2756,7 @@ execfuncdef(Cmd cmd) /**/ static void -execshfunc(Cmd cmd, Shfunc shf) +execshfunc(Cmd cmd, Shfunc shf, LinkList args) { LinkList last_file_list = NULL; @@ -2726,16 +2774,17 @@ execshfunc(Cmd cmd, Shfunc shf) if (isset(XTRACE)) { LinkNode lptr; fprintf(stderr, "%s", prompt4 ? prompt4 : prompt4); - for (lptr = firstnode(cmd->args); lptr; incnode(lptr)) { - if (lptr != firstnode(cmd->args)) - fputc(' ', stderr); - fprintf(stderr, "%s", (char *)getdata(lptr)); - } + if (args) + for (lptr = firstnode(args); lptr; incnode(lptr)) { + if (lptr != firstnode(args)) + fputc(' ', stderr); + fprintf(stderr, "%s", (char *)getdata(lptr)); + } fputc('\n', stderr); fflush(stderr); } - doshfunc(shf->nam, shf->funcdef, cmd->args, shf->flags, 0); + doshfunc(shf->nam, shf->funcdef, args, shf->flags, 0); if (!list_pipe) deletefilelist(last_file_list); @@ -2749,10 +2798,16 @@ execshfunc(Cmd cmd, Shfunc shf) /**/ static int -execautofn(Cmd cmd) +execautofn(Cmd cmd, LinkList args, int flags) { Shfunc shf = cmd->u.autofn->shf; - List l = getfpfunc(shf->nam); + int noalias = noaliases; + List l; + + noaliases = (shf->flags & PM_UNALIASED); + l = getfpfunc(shf->nam); + noaliases = noalias; + if(l == &dummy_list) { zerr("%s: function definition file not found", shf->nam, 0); return 1; @@ -2773,9 +2828,7 @@ execautofn(Cmd cmd) } LASTALLOC; shf->flags &= ~PM_UNDEFINED; } - HEAPALLOC { - execlist(dupstruct(shf->funcdef), 1, 0); - } LASTALLOC; + execlist(shf->funcdef, 1, 0); return lastval; } @@ -2822,7 +2875,8 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval) LinkNode node; node = doshargs->first; - pparams = x = (char **) zcalloc(((sizeof *x) * (1 + countlinknodes(doshargs)))); + pparams = x = (char **) zcalloc(((sizeof *x) * + (1 + countlinknodes(doshargs)))); if (isset(FUNCTIONARGZERO)) { oargv0 = argzero; argzero = ztrdup((char *) node->dat); @@ -2901,7 +2955,7 @@ void runshfunc(List list, FuncWrap wrap, char *name) { int cont; - char *ou; + VARARR(char, ou, underscorelen); while (wrap) { wrap->module->wrapper++; @@ -2917,11 +2971,9 @@ runshfunc(List list, FuncWrap wrap, char *name) wrap = wrap->next; } startparamscope(); - ou = underscore; - underscore = ztrdup(underscore); - execlist(dupstruct(list), 1, 0); - zsfree(underscore); - underscore = ou; + strcpy(ou, underscore); + execlist(list, 1, 0); + strcpy(underscore, ou); endparamscope(); } @@ -2949,20 +3001,18 @@ getfpfunc(char *s) unmetafy(buf, NULL); if (!access(buf, R_OK) && (fd = open(buf, O_RDONLY | O_NOCTTY)) != -1) { if ((len = lseek(fd, 0, 2)) != -1) { + d = (char *) zalloc(len + 1); lseek(fd, 0, 0); - d = (char *) zcalloc(len + 1); if (read(fd, d, len) == len) { close(fd); + d[len] = '\0'; d = metafy(d, len, META_REALLOC); HEAPALLOC { r = parse_string(d); } LASTALLOC; - zfree(d, len + 1); return r; - } else { - zfree(d, len + 1); + } else close(fd); - } } else { close(fd); } @@ -2995,9 +3045,10 @@ stripkshdef(List l, char *name) if(p->right) return l; c = p->left; - if(c->type != FUNCDEF || c->flags || - nonempty(c->redir) || nonempty(c->vars) || - empty(c->args) || lastnode(c->args) != firstnode(c->args) || + if (c->type != FUNCDEF || c->flags || + (c->redir && nonempty(c->redir)) || (c->vars && nonempty(c->vars)) || + !c->args || empty(c->args) || + lastnode(c->args) != firstnode(c->args) || strcmp(name, peekfirst(c->args))) return l; return c->u.list; @@ -3076,8 +3127,7 @@ execsave(void) es->trapreturn = trapreturn; es->noerrs = noerrs; es->subsh_close = subsh_close; - es->underscore = underscore; - underscore = ztrdup(underscore); + es->underscore = ztrdup(underscore); es->next = exstack; exstack = es; noerrs = cmdoutpid = 0; @@ -3105,8 +3155,8 @@ execrestore(void) trapreturn = exstack->trapreturn; noerrs = exstack->noerrs; subsh_close = exstack->subsh_close; - zsfree(underscore); - underscore = exstack->underscore; + strcpy(underscore, exstack->underscore); + zsfree(exstack->underscore); en = exstack->next; free(exstack); exstack = en; diff --git a/Src/glob.c b/Src/glob.c index 35aa447de..93b497632 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -744,7 +744,7 @@ parsecomp(int gflag) pptr++; } - if (*pptr == Inpar && pptr[1] == Pound) { + if (*pptr == Inpar && pptr[1] == Pound && isset(EXTENDEDGLOB)) { /* Found some globbing flags */ char *eptr = pptr; if (kshfunc != KF_NONE) @@ -3432,17 +3432,17 @@ tokenize(char *s) void remnulargs(char *s) { - int nl = *s; - char *t = s; - - while (*s) - if (INULL(*s)) - chuck(s); - else - s++; - if (!*t && nl) { - t[0] = Nularg; - t[1] = '\0'; + if (*s) { + char *t = s, *p = s, c; + + while ((c = *s++)) + if (!INULL(c)) + *p++ = c; + *p = '\0'; + if (!*t) { + t[0] = Nularg; + t[1] = '\0'; + } } } diff --git a/Src/hashtable.c b/Src/hashtable.c index b534d8ac1..e80461b4e 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -880,7 +880,7 @@ printshfuncnode(HashNode hn, int printflags) return; } - t = getpermtext((void *) dupstruct((void *) f->funcdef)); + t = getpermtext((void *) f->funcdef); quotedzputs(f->nam, stdout); printf(" () {\n\t"); zputs(t, stdout); @@ -1327,7 +1327,7 @@ addhistnode(HashTable ht, char *nam, void *nodeptr) { HashNode oldnode = addhashnode2(ht, nam, nodeptr); Histent he = (Histent)nodeptr; - if (oldnode && oldnode != nodeptr) { + if (oldnode && oldnode != (HashNode)nodeptr) { if (he->flags & HIST_MAKEUNIQUE || (he->flags & HIST_FOREIGN && (Histent)oldnode == he->up)) { he->flags |= HIST_DUP; diff --git a/Src/hist.c b/Src/hist.c index 4d672deab..49dac724c 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -30,6 +30,27 @@ #include "zsh.mdh" #include "hist.pro" +/* Functions to call for getting/ungetting a character and for history + * word control. */ + +/**/ +int (*hgetc) _((void)); + +/**/ +void (*hungetc) _((int)); + +/**/ +void (*hwaddc) _((int)); + +/**/ +void (*hwbegin) _((int)); + +/**/ +void (*hwend) _((void)); + +/**/ +void (*addtoline) _((int)); + /* != 0 means history substitution is turned off */ /**/ @@ -159,12 +180,11 @@ int hlinesz; /* default event (usually curhist-1, that is, "!!") */ static int defev; - + /* add a character to the current history word */ -/**/ -void -hwaddc(int c) +static void +ihwaddc(int c) { /* Only if history line exists and lexing has not finished. */ if (chline && !(errflag || lexstop)) { @@ -182,7 +202,7 @@ hwaddc(int c) if (hptr - chline >= hlinesz) { int oldsiz = hlinesz; - chline = realloc(chline, hlinesz = oldsiz + 16); + chline = realloc(chline, hlinesz = oldsiz + 64); hptr = chline + oldsiz; } } @@ -192,12 +212,12 @@ hwaddc(int c) * zsh expands history (see doexpandhist() in zle_tricky.c). It also * * calculates the new cursor position after the expansion. It is called * * from hgetc() and from gettok() in lex.c for characters in comments. */ - + /**/ void -addtoline(int c) +iaddtoline(int c) { - if (! expanding || lexstop) + if (!expanding || lexstop) return; if (qbang && c == bangchar && stophist < 2) { exlast--; @@ -216,9 +236,8 @@ addtoline(int c) line[cs++] = itok(c) ? ztokens[c - Pound] : c; } -/**/ -int -hgetc(void) +static int +ihgetc(void) { int c = ingetc(); @@ -234,7 +253,7 @@ hgetc(void) } if ((inbufflags & INP_HIST) && !stophist) { /* the current character c came from a history expansion * - * (inbufflags && INP_HIST) and history is not disabled * + * (inbufflags & INP_HIST) and history is not disabled * * (e.g. we are not inside single quotes). In that case, \! * * should be treated as ! (since this \! came from a previous * * history line where \ was used to escape the bang). So if * @@ -606,9 +625,8 @@ histsubchar(int c) /* unget a char and remove it from chline. It can only be used * * to unget a character returned by hgetc. */ -/**/ -void -hungetc(int c) +static void +ihungetc(int c) { int doit = 1; @@ -641,10 +659,10 @@ hungetc(int c) /**/ void -strinbeg(void) +strinbeg(int dohist) { strin++; - hbegin(); + hbegin(dohist); lexinit(); } @@ -661,17 +679,49 @@ strinend(void) histdone = 0; } +/* dummy functions to use instead of hwaddc(), hwbegin(), and hwend() when + * they aren't needed */ + +static void +nohw(int c) +{ +} + +static void +nohwe(void) +{ +} + /* initialize the history mechanism */ /**/ void -hbegin(void) +hbegin(int dohist) { isfirstln = isfirstch = 1; errflag = histdone = spaceflag = 0; - stophist = (!interact || unset(BANGHIST) || unset(SHINSTDIN)) << 1; - chline = hptr = zcalloc(hlinesz = 16); - chwords = zalloc((chwordlen = 16)*sizeof(short)); + stophist = (dohist ? ((!interact || unset(SHINSTDIN)) << 1) : 2); + if (stophist == 2 || (inbufflags & INP_ALIAS)) { + chline = hptr = NULL; + hlinesz = 0; + chwords = NULL; + chwordlen = 0; + hgetc = ingetc; + hungetc = inungetc; + hwaddc = nohw; + hwbegin = nohw; + hwend = nohwe; + addtoline = nohw; + } else { + chline = hptr = zcalloc(hlinesz = 64); + chwords = zalloc((chwordlen = 64) * sizeof(short)); + hgetc = ihgetc; + hungetc = ihungetc; + hwaddc = ihwaddc; + hwbegin = ihwbegin; + hwend = ihwend; + addtoline = iaddtoline; + } chwordpos = 0; if (histactive & HA_JUNKED) @@ -864,7 +914,8 @@ hend(void) int flag, save = 1; char *hf = getsparam("HISTFILE"); - DPUTS(!chline, "BUG: chline is NULL in hend()"); + DPUTS(stophist != 2 && !(inbufflags & INP_ALIAS) && !chline, + "BUG: chline is NULL in hend()"); if (histdone & HISTFLAG_SETTY) settyinfo(&shttyinfo); if (!(histactive & HA_NOINC)) { @@ -1005,8 +1056,10 @@ int hwgetword = -1; /**/ void -hwbegin(int offset) +ihwbegin(int offset) { + if (stophist == 2 || strin) + return; if (chwordpos%2) chwordpos--; /* make sure we're on a word start, not end */ /* If we're expanding an alias, we should overwrite the expansion @@ -1023,15 +1076,18 @@ hwbegin(int offset) /**/ void -hwend(void) +ihwend(void) { + if (stophist == 2 || strin) + return; if (chwordpos%2 && chline) { /* end of word reached and we've already begun a word */ if (hptr > chline + chwords[chwordpos-1]) { chwords[chwordpos++] = hptr - chline; if (chwordpos >= chwordlen) { chwords = (short *) realloc(chwords, - (chwordlen += 16)*sizeof(short)); + (chwordlen += 32) * + sizeof(short)); } if (hwgetword > -1) { /* We want to reuse the current word position */ @@ -1606,7 +1662,7 @@ readhistfile(char *fn, int err, int readflags) else if (!lockhistfile(fn, 1)) return; if ((in = fopen(unmeta(fn), "r"))) { - nwordlist = 16; + nwordlist = 64; wordlist = (short *)zalloc(nwordlist*sizeof(short)); bufsiz = 1024; buf = zalloc(bufsiz); @@ -1717,7 +1773,7 @@ readhistfile(char *fn, int err, int readflags) if (*pt) { if (nwordpos >= nwordlist) wordlist = (short *) realloc(wordlist, - (nwordlist += 16)*sizeof(short)); + (nwordlist += 64)*sizeof(short)); wordlist[nwordpos++] = pt - start; while (*pt && !inblank(*pt)) pt++; diff --git a/Src/init.c b/Src/init.c index f9e6574dd..89cbf2a8b 100644 --- a/Src/init.c +++ b/Src/init.c @@ -37,6 +37,14 @@ /**/ int noexitct = 0; +/* buffer for $_ and its length */ + +/**/ +char *underscore; + +/**/ +int underscorelen; + /* what level of sourcing we are at */ /**/ @@ -94,7 +102,7 @@ loop(int toplevel, int justonce) if (interact) preprompt(); } - hbegin(); /* init history mech */ + hbegin(1); /* init history mech */ intr(); /* interrupts on */ lexinit(); /* initialize lexical state */ if (!(list = parse_event())) { /* if we couldn't parse a list */ @@ -128,6 +136,8 @@ loop(int toplevel, int justonce) if (stopmsg) /* unset 'you have stopped jobs' flag */ stopmsg--; execlist(list, 0, 0); + if (toplevel) + freestructs(); tok = toksav; if (toplevel) noexitct = 0; @@ -550,8 +560,20 @@ setupvals(void) cdpath = mkarray(NULL); manpath = mkarray(NULL); fignore = mkarray(NULL); -#ifdef FUNCTION_DIR - fpath = mkarray(ztrdup(FUNCTION_DIR)); +#ifdef FPATH_DIR +# ifdef FPATH_SUBDIRS + { + char *fpath_subdirs[] = FPATH_SUBDIRS; + int len = sizeof(fpath_subdirs)/sizeof(char *), j; + + fpath = zalloc((len+1)*sizeof(char *)); + for (j = 0; j < len; j++) + fpath[j] = tricat(FPATH_DIR, "/", fpath_subdirs[j]); + fpath[len] = NULL; + } +# else + fpath = mkarray(ztrdup(FPATH_DIR)); +# endif #else fpath = mkarray(NULL); #endif @@ -582,7 +604,8 @@ setupvals(void) ifs = ztrdup(DEFAULT_IFS); wordchars = ztrdup(DEFAULT_WORDCHARS); postedit = ztrdup(""); - underscore = ztrdup(""); + underscore = (char *) zalloc(underscorelen = 32); + *underscore = '\0'; zoptarg = ztrdup(""); zoptind = 1; diff --git a/Src/jobs.c b/Src/jobs.c index 7b0eca6b6..31861e284 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -65,10 +65,6 @@ struct tms shtms; /**/ int ttyfrozen; -/* empty job structure for quick clearing of jobtab entries */ - -static struct job zero; /* static variables are initialized to zero */ - static struct timeval dtimeval, now; /* Diff two timevals for elapsed-time computations */ @@ -244,8 +240,11 @@ update_job(Job jn) adjustwinsize(0); } } + } else if (list_pipe && (val & 0200) && inforeground == 1) { + breaks = loops; + errflag = 1; + inerrflush(); } - if (somestopped && jn->stat & STAT_SUPERJOB) return; jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED : @@ -663,14 +662,16 @@ deletejob(Job jn) nx = pn->next; zfree(pn, sizeof(struct process)); } - zsfree(jn->pwd); - deletefilelist(jn->filelist); if (jn->ty) zfree(jn->ty, sizeof(struct ttyinfo)); - *jn = zero; + jn->gleader = jn->other = 0; + jn->stat = jn->stty_in_env = 0; + jn->procs = NULL; + jn->filelist = NULL; + jn->ty = NULL; } /* add a process to the current job */ @@ -831,7 +832,12 @@ waitjob(int job, int sig) void waitjobs(void) { - waitjob(thisjob, 0); + Job jn = jobtab + thisjob; + + if (jn->procs) + waitjob(thisjob, 0); + else + deletejob(jn); thisjob = -1; } @@ -843,12 +849,9 @@ clearjobtab(void) { int i; - for (i = 1; i < MAXJOB; i++) { - if (jobtab[i].pwd) - zsfree(jobtab[i].pwd); + for (i = 1; i < MAXJOB; i++) if (jobtab[i].ty) zfree(jobtab[i].ty, sizeof(struct ttyinfo)); - } memset(jobtab, 0, sizeof(jobtab)); /* zero out table */ } @@ -864,7 +867,11 @@ initjob(void) for (i = 1; i < MAXJOB; i++) if (!jobtab[i].stat) { jobtab[i].stat = STAT_INUSE; - jobtab[i].pwd = ztrdup(pwd); + if (strlen(pwd) >= PATH_MAX) { + memcpy(jobtab[i].pwd, pwd, PATH_MAX); + jobtab[i].pwd[PATH_MAX] = '\0'; + } else + strcpy(jobtab[i].pwd, pwd); jobtab[i].gleader = 0; return i; } diff --git a/Src/lex.c b/Src/lex.c index 7371243a7..8dc836329 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -179,6 +179,12 @@ struct lexstack { int hwgetword; int lexstop; struct heredocs *hdocs; + int (*hgetc) _((void)); + void (*hungetc) _((int)); + void (*hwaddc) _((int)); + void (*hwbegin) _((int)); + void (*hwend) _((void)); + void (*addtoline) _((int)); unsigned char *cstack; int csp; @@ -226,6 +232,12 @@ lexsave(void) ls->hwgetword = hwgetword; ls->lexstop = lexstop; ls->hdocs = hdocs; + ls->hgetc = hgetc; + ls->hungetc = hungetc; + ls->hwaddc = hwaddc; + ls->hwbegin = hwbegin; + ls->hwend = hwend; + ls->addtoline = addtoline; cmdsp = 0; inredir = 0; hdocs = NULL; @@ -271,6 +283,12 @@ lexrestore(void) hwgetword = lstack->hwgetword; lexstop = lstack->lexstop; hdocs = lstack->hdocs; + hgetc = lstack->hgetc; + hungetc = lstack->hungetc; + hwaddc = lstack->hwaddc; + hwbegin = lstack->hwbegin; + hwend = lstack->hwend; + addtoline = lstack->addtoline; hlinesz = lstack->hlinesz; errflag = 0; @@ -783,7 +801,7 @@ gettok(void) static int gettokstr(int c, int sub) { - int bct = 0, pct = 0, brct = 0; + int bct = 0, pct = 0, brct = 0, fdpar = 0; int intpos = 1, in_brace_param = 0; int peek, inquote; #ifdef DEBUG @@ -798,8 +816,12 @@ gettokstr(int c, int sub) for (;;) { int act; int e; + int inbl = inblank(c); + + if (fdpar && !inbl && c != ')') + fdpar = 0; - if (inblank(c) && !in_brace_param && !pct) + if (inbl && !in_brace_param && !pct) act = LX2_BREAK; else { act = lexact2[STOUC(c)]; @@ -822,6 +844,12 @@ gettokstr(int c, int sub) add(Meta); break; case LX2_OUTPAR: + if (fdpar) { + /* this is a single word `( )', treat as INOUTPAR */ + add(c); + *bptr = '\0'; + return INOUTPAR; + } if ((sub || in_brace_param) && isset(SHGLOB)) break; if (!in_brace_param && !pct--) { @@ -898,11 +926,40 @@ gettokstr(int c, int sub) e = hgetc(); hungetc(e); lexstop = 0; - if (e == ')' || - (incmdpos && !brct && peek != ENVSTRING)) + /* For command words, parentheses are only + * special at the start. But now we're tokenising + * the remaining string. So I don't see what + * the old incmdpos test here is for. + * pws 1999/6/8 + * + * Oh, no. + * func1( ) + * is a valid function definition in [k]sh. The best + * thing we can do, without really nasty lookahead tricks, + * is break if we find a blank after a parenthesis. At + * least this can't happen inside braces or brackets. We + * only allow this with SHGLOB (set for both sh and ksh). + * + * Things like `print @( |foo)' should still + * work, because [k]sh don't allow multiple words + * in a function definition, so we only do this + * in command position. + * pws 1999/6/14 + */ + if (e == ')' || (isset(SHGLOB) && inblank(e) && !bct && + !brct && !intpos && incmdpos)) goto brk; } - pct++; + /* + * This also handles the [k]sh `foo( )' function definition. + * Maintain a variable fdpar, set as long as a single set of + * parentheses contains only space. Then if we get to the + * closing parenthesis and it is still set, we can assume we + * have a function definition. Only do this at the start of + * the word, since the (...) must be a separate token. + */ + if (!pct++ && isset(SHGLOB) && intpos && !bct && !brct) + fdpar = 1; } c = Inpar; break; @@ -1294,8 +1351,7 @@ parsestr(char *s) lexsave(); untokenize(s); inpush(dupstring(s), 0, NULL); - strinbeg(); - stophist = 2; + strinbeg(0); len = 0; bptr = tokstr = s; bsiz = l + 1; @@ -1331,8 +1387,7 @@ parse_subst_string(char *s) lexsave(); untokenize(s); inpush(dupstring(s), 0, NULL); - strinbeg(); - stophist = 2; + strinbeg(0); len = 0; bptr = tokstr = s; bsiz = l + 1; @@ -1377,8 +1432,7 @@ exalias(void) if (!tokstr) { yytext = tokstrings[tok]; - if (yytext) - yytext = dupstring(yytext); + return 0; } diff --git a/Src/linklist.c b/Src/linklist.c index 62a962595..e3cb4d626 100644 --- a/Src/linklist.c +++ b/Src/linklist.c @@ -38,7 +38,7 @@ newlinklist(void) { LinkList list; - list = (LinkList) alloc(sizeof *list); + list = (LinkList) ncalloc(sizeof *list); list->first = NULL; list->last = (LinkNode) list; return list; @@ -53,7 +53,7 @@ insertlinknode(LinkList list, LinkNode node, void *dat) LinkNode tmp, new; tmp = node->next; - node->next = new = (LinkNode) alloc(sizeof *tmp); + node->next = new = (LinkNode) ncalloc(sizeof *tmp); new->last = node; new->dat = dat; new->next = tmp; diff --git a/Src/loop.c b/Src/loop.c index 070173fa2..07a7a56b0 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -44,21 +44,18 @@ int contflag; /**/ int breaks; - + /**/ int -execfor(Cmd cmd) +execfor(Cmd cmd, LinkList args, int flags) { - List list; Forcmd node; char *str; - int val = 0; - LinkList args; + zlong val = 0; node = cmd->u.forcmd; - args = cmd->args; if (node->condition) { - str = node->name; + str = dupstring(node->name); singsub(&str); if (!errflag) matheval(str); @@ -69,7 +66,7 @@ execfor(Cmd cmd) args = newlinklist(); for (x = pparams; *x; x++) - addlinknode(args, ztrdup(*x)); + addlinknode(args, dupstring(*x)); } lastval = 0; loops++; @@ -95,13 +92,12 @@ execfor(Cmd cmd) if (!val) break; } else { - str = (char *) ugetnode(args); - if (!str) + if (!args || !(str = (char *) ugetnode(args))) break; setsparam(node->name, ztrdup(str)); } - list = (List) dupstruct(node->list); - execlist(list, 1, (cmd->flags & CFLAG_EXEC) && empty(args)); + execlist(node->list, 1, + (flags & CFLAG_EXEC) && args && empty(args)); if (breaks) { breaks--; if (breaks || !contflag) @@ -129,27 +125,24 @@ execfor(Cmd cmd) /**/ int -execselect(Cmd cmd) +execselect(Cmd cmd, LinkList args, int flags) { - List list; Forcmd node; char *str, *s; - LinkList args; LinkNode n; int i; FILE *inp; size_t more; node = cmd->u.forcmd; - args = cmd->args; if (!node->inflag) { char **x; args = newlinklist(); for (x = pparams; *x; x++) - addlinknode(args, ztrdup(*x)); + addlinknode(args, dupstring(*x)); } - if (empty(args)) + if (!args || empty(args)) return 1; loops++; lastval = 0; @@ -196,8 +189,7 @@ execselect(Cmd cmd) str = ""; } setsparam(node->name, ztrdup(str)); - list = (List) dupstruct(node->list); - execlist(list, 1, 0); + execlist(node->list, 1, 0); freeheap(); if (breaks) { breaks--; @@ -278,9 +270,8 @@ selectlist(LinkList l, size_t start) /**/ int -execwhile(Cmd cmd) +execwhile(Cmd cmd, LinkList args, int flags) { - List list; struct whilecmd *node; int olderrexit, oldval; @@ -290,9 +281,8 @@ execwhile(Cmd cmd) pushheap(); loops++; for (;;) { - list = (List) dupstruct(node->cont); noerrexit = 1; - execlist(list, 1, 0); + execlist(node->cont, 1, 0); noerrexit = olderrexit; if (!((lastval == 0) ^ node->cond)) { if (breaks) @@ -300,8 +290,7 @@ execwhile(Cmd cmd) lastval = oldval; break; } - list = (List) dupstruct(node->loop); - execlist(list, 1, 0); + execlist(node->loop, 1, 0); if (breaks) { breaks--; if (breaks || !contflag) @@ -322,22 +311,20 @@ execwhile(Cmd cmd) /**/ int -execrepeat(Cmd cmd) +execrepeat(Cmd cmd, LinkList args, int flags) { - List list; int count; lastval = 0; - if (empty(cmd->args) || nextnode(firstnode(cmd->args))) { + if (!args || empty(args) || nextnode(firstnode(args))) { zerr("bad argument for repeat", NULL, 0); return 1; } - count = atoi(peekfirst(cmd->args)); + count = atoi(peekfirst(args)); pushheap(); loops++; while (count--) { - list = (List) dupstruct(cmd->u.list); - execlist(list, 1, 0); + execlist(cmd->u.list, 1, 0); freeheap(); if (breaks) { breaks--; @@ -357,7 +344,7 @@ execrepeat(Cmd cmd) /**/ int -execif(Cmd cmd) +execif(Cmd cmd, LinkList args, int flags) { struct ifcmd *node; int olderrexit; @@ -380,7 +367,7 @@ execif(Cmd cmd) noerrexit = olderrexit; if (*t) - execlist(*t, 1, cmd->flags & CFLAG_EXEC); + execlist(*t, 1, flags & CFLAG_EXEC); else lastval = 0; @@ -389,7 +376,7 @@ execif(Cmd cmd) /**/ int -execcase(Cmd cmd) +execcase(Cmd cmd, LinkList args, int flags) { struct casecmd *node; char *word; @@ -400,18 +387,18 @@ execcase(Cmd cmd) l = node->lists; p = node->pats; - word = *p++; + word = dupstring(*p++); singsub(&word); untokenize(word); lastval = 0; if (node) { while (*p) { - char *pat = *p + 1; + char *pat = dupstring(*p + 1); singsub(&pat); if (matchpat(word, pat)) { do { - execlist(*l++, 1, **p == ';' && (cmd->flags & CFLAG_EXEC)); + execlist(*l++, 1, **p == ';' && (flags & CFLAG_EXEC)); } while(**p++ == '&' && *p); break; } @@ -421,4 +408,3 @@ execcase(Cmd cmd) } return lastval; } - diff --git a/Src/math.c b/Src/math.c index efbf22e44..7e7e557ed 100644 --- a/Src/math.c +++ b/Src/math.c @@ -733,9 +733,9 @@ mathevall(char *s, int prek, char **ep) char *xptr; zlong xyyval; LV xyylval; - char **xlvals = 0; + char **xlvals = 0, *nlvals[LVCOUNT]; int xsp; - struct mathvalue *xstack = 0; + struct mathvalue *xstack = 0, nstack[STACKSZ]; zlong ret; xlastbase = xnoeval = xunary = xlvc = xyyval = xyylval = xsp = 0; @@ -753,9 +753,10 @@ mathevall(char *s, int prek, char **ep) xsp = sp; xstack = stack; } - stack = (struct mathvalue *)zalloc(STACKSZ*sizeof(struct mathvalue)); + stack = nstack; lastbase = -1; - lvals = (char **)zcalloc(LVCOUNT*sizeof(char *)); + memset(nlvals, 0, LVCOUNT*sizeof(char *)); + lvals = nlvals; lvc = 0; ptr = s; sp = -1; @@ -769,8 +770,6 @@ mathevall(char *s, int prek, char **ep) ret = stack[0].val; - zfree(lvals, LVCOUNT*sizeof(char *)); - zfree(stack, STACKSZ*sizeof(struct mathvalue)); if (--mlevel) { lastbase = xlastbase; noeval = xnoeval; @@ -827,7 +826,8 @@ mathevalarg(char *s, char **ss) static void mathparse(int pc) { - int q, otok, onoeval; + zlong q; + int otok, onoeval; if (errflag) return; diff --git a/Src/mem.c b/Src/mem.c index 97ff7fdc2..7f3b4688f 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -97,7 +97,7 @@ static int h_m[1025], h_push, h_pop, h_free; #endif #define H_ISIZE sizeof(zlong) -#define HEAPSIZE (8192 - H_ISIZE) +#define HEAPSIZE (16384 - H_ISIZE) #define HEAP_ARENA_SIZE (HEAPSIZE - sizeof(struct heap)) #define HEAPFREE (16384 - H_ISIZE) @@ -133,6 +133,10 @@ global_permalloc(void) static Heap heaps; +/* first heap with free space, not always correct */ + +static Heap fheap; + /* Use new heaps from now on. This returns the old heap-list. */ /**/ @@ -141,7 +145,7 @@ new_heaps(void) { Heap h = heaps; - heaps = NULL; + fheap = heaps = NULL; return h; } @@ -160,6 +164,7 @@ old_heaps(Heap old) zfree(h, sizeof(*h)); } heaps = old; + fheap = NULL; } /* Temporarily switch to other heaps (or back again). */ @@ -171,6 +176,7 @@ switch_heaps(Heap new) Heap h = heaps; heaps = new; + fheap = NULL; return h; } @@ -208,6 +214,8 @@ freeheap(void) #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG) h_free++; #endif + + fheap = NULL; for (h = heaps; h; h = hn) { hn = h->next; if (h->sp) { @@ -215,6 +223,8 @@ freeheap(void) memset(arena(h) + h->sp->used, 0xff, h->used - h->sp->used); #endif h->used = h->sp->used; + if (!fheap && h->used < HEAP_ARENA_SIZE) + fheap = h; hl = h; } else zfree(h, HEAPSIZE); @@ -238,6 +248,7 @@ popheap(void) h_pop++; #endif + fheap = NULL; for (h = heaps; h; h = hn) { hn = h->next; if ((hs = h->sp)) { @@ -246,6 +257,8 @@ popheap(void) memset(arena(h) + hs->used, 0xff, h->used - hs->used); #endif h->used = hs->used; + if (!fheap && h->used < HEAP_ARENA_SIZE) + fheap = h; zfree(hs, sizeof(*hs)); hl = h; @@ -275,13 +288,12 @@ zhalloc(size_t size) /* find a heap with enough free space */ - for (h = heaps; h; h = h->next) { + for (h = (fheap ? fheap : heaps); h; h = h->next) { if (HEAP_ARENA_SIZE >= (n = size + h->used)) { h->used = n; return arena(h) + n - size; } } - { Heap hp; /* not found, allocate new heap */ @@ -311,6 +323,7 @@ zhalloc(size_t size) hp->next = h; else heaps = h; + fheap = NULL; unqueue_signals(); return arena(h); @@ -361,6 +374,7 @@ hrealloc(char *p, size_t old, size_t new) ph->next = h->next; else heaps = h->next; + fheap = NULL; zfree(h, HEAPSIZE); return NULL; } @@ -593,6 +607,16 @@ struct m_hdr { #define M_ISIZE (sizeof(zlong)) #define M_MIN (2 * M_ISIZE) +/* M_FREE is the number of bytes that have to be free before memory is + * given back to the system + * M_KEEP is the number of bytes that will be kept when memory is given + * back; note that this has to be less than M_FREE + * M_ALLOC is the number of extra bytes to request from the system */ + +#define M_FREE 65536 +#define M_KEEP 32768 +#define M_ALLOC M_KEEP + /* a pointer to the last free block, a pointer to the free list (the blocks on this list are kept in order - lowest address first) */ @@ -623,13 +647,13 @@ static char *m_high, *m_low; #define M_SIDX(S) ((S) / M_ISIZE) -#define M_SNUM 50 +#define M_SNUM 128 #define M_SLEN(M) ((M)->len / M_SNUM) #define M_SBLEN(S) ((S) * M_SNUM + sizeof(struct m_shdr *) + \ sizeof(zlong) + sizeof(struct m_hdr *)) #define M_BSLEN(S) (((S) - sizeof(struct m_shdr *) - \ sizeof(zlong) - sizeof(struct m_hdr *)) / M_SNUM) -#define M_NSMALL 8 +#define M_NSMALL 13 static struct m_hdr *m_small[M_NSMALL]; @@ -691,9 +715,9 @@ malloc(MALLOC_ARG_T size) m->used++; /* if all small blocks in this block are allocated, the block is - put at the end of the list blocks wth small blocks of this + put at the end of the list blocks with small blocks of this size (i.e., we try to keep blocks with free blocks at the - beginning of the list, to make the search faster */ + beginning of the list, to make the search faster) */ if (m->used == M_SNUM && m->next) { for (mt = m; mt->next; mt = mt->next); @@ -753,15 +777,24 @@ malloc(MALLOC_ARG_T size) for (mp = NULL, m = m_free; m && m->len < size; mp = m, m = m->next); } if (!m) { + long nal; /* no matching free block was found, we have to request new memory from the system */ - n = (size + M_HSIZE + m_pgsz - 1) & ~(m_pgsz - 1); + n = (size + M_HSIZE + M_ALLOC + m_pgsz - 1) & ~(m_pgsz - 1); if (((char *)(m = (struct m_hdr *)sbrk(n))) == ((char *)-1)) { DPUTS(1, "MEM: allocation error at sbrk."); unqueue_signals(); return NULL; } + if ((nal = ((long)(char *)m) & (M_ALIGN-1))) { + if ((char *)sbrk(M_ALIGN - nal) == (char *)-1) { + DPUTS(1, "MEM: allocation error at sbrk."); + unqueue_signals(); + return NULL; + } + m = (struct m_hdr *) ((char *)m + (M_ALIGN - nal)); + } /* set m_low, for the check in free() */ if (!m_low) m_low = (char *)m; @@ -1034,8 +1067,8 @@ zfree(void *p, int sz) and now there is more than one page size of memory, we can give it back to the system (and we do it ;-) */ if ((((char *)m_lfree) + M_ISIZE + m_lfree->len) == m_high && - m_lfree->len >= m_pgsz + M_MIN) { - long n = (m_lfree->len - M_MIN) & ~(m_pgsz - 1); + m_lfree->len >= m_pgsz + M_MIN + M_FREE) { + long n = (m_lfree->len - M_MIN - M_KEEP) & ~(m_pgsz - 1); m_lfree->len -= n; if (brk(m_high -= n) == -1) { diff --git a/Src/params.c b/Src/params.c index 75910c6fd..b9f3d33a0 100644 --- a/Src/params.c +++ b/Src/params.c @@ -52,7 +52,6 @@ char **pparams, /* $argv */ /**/ char *argzero, /* $0 */ - *underscore, /* $_ */ *home, /* $HOME */ *hostnam, /* $HOST */ *ifs, /* $IFS */ @@ -232,11 +231,6 @@ IPDEF9("manpath", &manpath, "MANPATH"), IPDEF9("psvar", &psvar, "PSVAR"), IPDEF9("watch", &watch, "WATCH"), -/*TEST BEGIN*/ -#define IPDEF10(A) {NULL,A,PM_HASHED|PM_SPECIAL|PM_DONTIMPORT,BR((void *)0),SFN(hashsetfn),GFN(hashgetfn),stdunsetfn,0,NULL,NULL,NULL,0} -IPDEF10("testhash"), -/*TEST END*/ - #ifdef DYNAMIC IPDEF9F("module_path", &module_path, "MODULE_PATH", PM_RESTRICTED), #endif @@ -723,16 +717,13 @@ isident(char *s) #endif } -static char **garr; - /**/ static zlong getarg(char **str, int *inv, Value v, int a2, zlong *w) { - int num = 1, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash; - int beg = 0, hasbeg = 0; + int hasbeg = 0, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash; char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt; - zlong r = 0; + zlong num = 1, beg = 0, r = 0; Comp c; ishash = (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED); @@ -1147,7 +1138,6 @@ fetchvalue(char **pptr, int bracks, int flags) int ppar = 0; s = t = *pptr; - garr = NULL; if (idigit(*s)) { if (bracks >= 0) @@ -1638,7 +1628,7 @@ setaparam(char *s, char **val) if (!(v = getvalue(&s, 1))) createparam(t, PM_ARRAY); *ss = '['; - if (PM_TYPE(v->pm->flags) == PM_HASHED) { + if (v && PM_TYPE(v->pm->flags) == PM_HASHED) { zerr("attempt to set slice of associative array", NULL, 0); freearray(val); errflag = 1; @@ -2466,7 +2456,10 @@ wordcharssetfn(Param pm, char *x) char * underscoregetfn(Param pm) { - return underscore; + char *u = dupstring(underscore); + + untokenize(u); + return u; } /* Function to get value for special parameter `TERM' */ diff --git a/Src/parse.c b/Src/parse.c index 043aa0f0d..520181750 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -298,6 +298,8 @@ par_pline(void) rdr->type = MERGEOUT; rdr->fd1 = 2; rdr->name = dupstring("1"); + if (!c->redir) + c->redir = newlinklist(); addlinknode(c->redir, rdr); cmdpush(CS_ERRPIPE); @@ -330,11 +332,14 @@ par_cmd(void) c = (Cmd) make_cmd(); c->lineno = lineno; - c->args = newlinklist(); - c->redir = newlinklist(); - c->vars = newlinklist(); - while (IS_REDIROP(tok)) - par_redir(c->redir); + c->args = NULL; + c->vars = NULL; + if (IS_REDIROP(tok)) { + c->redir = newlinklist(); + while (IS_REDIROP(tok)) + par_redir(c->redir); + } else + c->redir = NULL; switch (tok) { case FOR: cmdpush(CS_FOR); @@ -399,6 +404,8 @@ par_cmd(void) break; case DINPAR: c->type = CARITH; + if (!c->args) + c->args = newlinklist(); addlinknode(c->args, tokstr); yylex(); break; @@ -407,8 +414,12 @@ par_cmd(void) return NULL; break; } - while (IS_REDIROP(tok)) - par_redir(c->redir); + if (IS_REDIROP(tok)) { + if (!c->redir) + c->redir = newlinklist(); + while (IS_REDIROP(tok)) + par_redir(c->redir); + } incmdpos = 1; incasepat = 0; incond = 0; @@ -460,6 +471,8 @@ par_for(Cmd c) f->inflag = 1; incmdpos = 0; yylex(); + if (!c->args) + c->args = newlinklist(); c->args = par_wordlist(); if (tok != SEPER) YYERRORV; @@ -467,6 +480,8 @@ par_for(Cmd c) f->inflag = 1; incmdpos = 0; yylex(); + if (!c->args) + c->args = newlinklist(); c->args = par_nl_wordlist(); if (tok != OUTPAR) YYERRORV; @@ -819,6 +834,8 @@ par_repeat(Cmd c) yylex(); if (tok != STRING) YYERRORV; + if (!c->args) + c->args = newlinklist(); addlinknode(c->args, tokstr); incmdpos = 1; yylex(); @@ -966,6 +983,8 @@ par_simple(Cmd c) v->str = p + 1; } else equalsplit(tokstr, &v->str); + if (!c->vars) + c->vars = newlinklist(); addlinknode(c->vars, v); isnull = 0; } else if (tok == ENVARRAY) { @@ -982,6 +1001,8 @@ par_simple(Cmd c) if (tok != OUTPAR) YYERROR; incmdpos = oldcmdpos; + if (!c->vars) + c->vars = newlinklist(); addlinknode(c->vars, v); isnull = 0; } else @@ -993,9 +1014,13 @@ par_simple(Cmd c) for (;;) { if (tok == STRING) { incmdpos = 0; + if (!c->args) + c->args = newlinklist(); addlinknode(c->args, tokstr); yylex(); } else if (IS_REDIROP(tok)) { + if (!c->redir) + c->redir = newlinklist(); par_redir(c->redir); } else if (tok == INOUTPAR) { incmdpos = 1; @@ -1011,15 +1036,26 @@ par_simple(Cmd c) YYERROR; } yylex(); - } else - c->u.list = (List) expandstruct((struct node *) par_cmd(), N_LIST); + } else { + List l; + Sublist sl; + Pline pl; + + l = (List) allocnode(N_LIST); + l->type = Z_SYNC; + l->left = sl = (Sublist) allocnode(N_SUBLIST); + sl->type = END; + sl->left = pl = (Pline) allocnode(N_PLINE); + pl->type = END; + pl->left = par_cmd(); + } cmdpop(); c->type = FUNCDEF; } else break; isnull = 0; } - if (isnull && empty(c->redir)) + if (isnull && (!c->redir || empty(c->redir))) return NULL; incmdpos = 1; return c; diff --git a/Src/signals.c b/Src/signals.c index 3e655cbfd..f69da0140 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -719,7 +719,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn) freelinklist(args, (FreeFunc) NULL); zsfree(name); } else HEAPALLOC { - execlist(dupstruct(sigfn), 1, 0); + execlist(sigfn, 1, 0); } LASTALLOC; if (trapreturn > 0) trapret = trapreturn; diff --git a/Src/subst.c b/Src/subst.c index 0017b205e..d85d73f58 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -53,9 +53,9 @@ prefork(LinkList list, int flags) MUSTUSEHEAP("prefork"); for (node = firstnode(list); node; incnode(node)) { - char *str, *str3; + char *str; - str = str3 = (char *)getdata(node); + str = (char *)getdata(node); if ((*str == Inang || *str == Outang || *str == Equals) && str[1] == Inpar) { if (*str == Inang || *str == Outang) diff --git a/Src/text.c b/Src/text.c index d3eafaf9f..73b9088f2 100644 --- a/Src/text.c +++ b/Src/text.c @@ -169,7 +169,6 @@ gettext2(struct node *n) if (_List(n)->type & Z_DISOWN) taddstr("|"); } - simplifyright(_List(n)); if (_List(n)->right) { if (tnewlins) taddnl(); @@ -460,22 +459,23 @@ getsimptext(Cmd cmd) { LinkNode n; - for (n = firstnode(cmd->vars); n; incnode(n)) { - struct varasg *v = (struct varasg *)getdata(n); - - taddstr(v->name); - taddchr('='); - if (PM_TYPE(v->type) == PM_ARRAY) { - taddchr('('); - taddlist(v->arr); - taddstr(") "); - } else if (PM_TYPE(v->type) == PM_HASHED) { - /* XXX */ - } else { - taddstr(v->str); - taddchr(' '); + if (cmd->vars) + for (n = firstnode(cmd->vars); n; incnode(n)) { + struct varasg *v = (struct varasg *)getdata(n); + + taddstr(v->name); + taddchr('='); + if (PM_TYPE(v->type) == PM_ARRAY) { + taddchr('('); + taddlist(v->arr); + taddstr(") "); + } else if (PM_TYPE(v->type) == PM_HASHED) { + /* XXX */ + } else { + taddstr(v->str); + taddchr(' '); + } } - } taddlist(cmd->args); } @@ -490,6 +490,8 @@ getredirs(Cmd cmd) "<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">" }; + if (!cmd->redir) + return; taddchr(' '); for (n = firstnode(cmd->redir); n; incnode(n)) { struct redir *f = (struct redir *)getdata(n); @@ -537,7 +539,7 @@ taddlist(LinkList l) { LinkNode n; - if (!(n = firstnode(l))) + if (!l || !(n = firstnode(l))) return; for (; n; incnode(n)) { taddstr(getdata(n)); diff --git a/Src/utils.c b/Src/utils.c index 32588b4c3..ba4f3dc9d 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -853,61 +853,131 @@ int resetneeded; int winchanged; #endif -/* check the size of the window and adjust if necessary. * - * The value of from: * - * 0: called from update_job or setupvals * - * 1: called from the SIGWINCH handler * - * 2: the user have just changed LINES manually * - * 3: the user have just changed COLUMNS manually */ - -/**/ -void -adjustwinsize(int from) +static int +adjustlines(int signalled) { - int oldcols = columns, oldrows = lines; + int oldlines = lines; #ifdef TIOCGWINSZ - static int userlines, usercols; - - if (SHTTY == -1) - return; - - if (from == 2) - userlines = lines > 0; - if (from == 3) - usercols = columns > 0; - - if (!ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize)) { - if (!userlines || from == 1) - lines = shttyinfo.winsize.ws_row; - if (!usercols || from == 1) - columns = shttyinfo.winsize.ws_col; + if (signalled || lines <= 0) + lines = shttyinfo.winsize.ws_row; + else + shttyinfo.winsize.ws_row = lines; +#endif /* TIOCGWINSZ */ + if (lines <= 0) { + DPUTS(signalled, "BUG: Impossible TIOCGWINSZ rows"); + lines = tclines > 0 ? tclines : 24; } -#endif /* TIOCGWINSZ */ - if (lines <= 0) - lines = tclines > 0 ? tclines : 24; - if (columns <= 0) - columns = tccolumns > 0 ? tccolumns : 80; if (lines > 2) termflags &= ~TERM_SHORT; else termflags |= TERM_SHORT; + + return (lines != oldlines); +} + +static int +adjustcolumns(int signalled) +{ + int oldcolumns = columns; + +#ifdef TIOCGWINSZ + if (signalled || columns <= 0) + columns = shttyinfo.winsize.ws_col; + else + shttyinfo.winsize.ws_col = columns; +#endif /* TIOCGWINSZ */ + if (columns <= 0) { + DPUTS(signalled, "BUG: Impossible TIOCGWINSZ cols"); + columns = tccolumns > 0 ? tccolumns : 80; + } + if (columns > 2) termflags &= ~TERM_NARROW; else termflags |= TERM_NARROW; + return (columns != oldcolumns); +} + +/* check the size of the window and adjust if necessary. * + * The value of from: * + * 0: called from update_job or setupvals * + * 1: called from the SIGWINCH handler * + * 2: called from the LINES parameter callback * + * 3: called from the COLUMNS parameter callback */ + +/**/ +void +adjustwinsize(int from) +{ + static int getwinsz = 1; + int ttyrows = shttyinfo.winsize.ws_row; + int ttycols = shttyinfo.winsize.ws_col; + int resetzle = 0; + + if (getwinsz || from == 1) { #ifdef TIOCGWINSZ - if (interact && from >= 2) { - shttyinfo.winsize.ws_row = lines; - shttyinfo.winsize.ws_col = columns; + if (SHTTY == -1) + return; + if (ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize) == 0) { + resetzle = (ttyrows != shttyinfo.winsize.ws_row || + ttycols != shttyinfo.winsize.ws_col); + if (from == 0 && resetzle && ttyrows && ttycols) + from = 1; /* Signal missed while a job owned the tty? */ + ttyrows = shttyinfo.winsize.ws_row; + ttycols = shttyinfo.winsize.ws_col; + } else { + /* Set to unknown on failure */ + shttyinfo.winsize.ws_row = 0; + shttyinfo.winsize.ws_col = 0; + resetzle = 1; + } +#else + resetzle = from == 1; +#endif /* TIOCGWINSZ */ + } /* else + return; */ + + switch (from) { + case 0: + case 1: + getwinsz = 0; + /* Calling setiparam() here calls this function recursively, but * + * because we've already called adjustlines() and adjustcolumns() * + * here, recursive calls are no-ops unless a signal intervenes. * + * The commented "else return;" above might be a safe shortcut, * + * but I'm concerned about what happens on race conditions; e.g., * + * suppose the user resizes his xterm during `eval $(resize)'? */ + if (adjustlines(from) && zgetenv("LINES")) + setiparam("LINES", lines); + if (adjustcolumns(from) && zgetenv("COLUMNS")) + setiparam("COLUMNS", columns); + getwinsz = 1; + break; + case 2: + resetzle = adjustlines(0); + break; + case 3: + resetzle = adjustcolumns(0); + break; + } + +#ifdef TIOCGWINSZ + if (interact && from >= 2 && + (shttyinfo.winsize.ws_row != ttyrows || + shttyinfo.winsize.ws_col != ttycols)) { + /* shttyinfo.winsize is already set up correctly */ ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize); } -#endif +#endif /* TIOCGWINSZ */ - if (zleactive && (from >= 2 || oldcols != columns || oldrows != lines)) { - resetneeded = winchanged = 1; + if (zleactive && resetzle) { +#ifdef TIOCGWINSZ + winchanged = +#endif /* TIOCGWINSZ */ + resetneeded = 1; zrefresh(); } } @@ -1733,13 +1803,12 @@ char * sepjoin(char **s, char *sep) { char *r, *p, **t; - int l, sl, elide = 0; + int l, sl; char sepbuf[3]; if (!*s) return ""; if (!sep) { - elide = 1; sep = sepbuf; sepbuf[0] = *ifs; sepbuf[1] = *ifs == Meta ? ifs[1] ^ 32 : '\0'; @@ -1853,329 +1922,21 @@ allocnode(int type) { struct node *n; - n = (struct node *) alloc(sizetab[type]); + n = (struct node *) ncalloc(sizetab[type]); memset((void *) n, 0, sizetab[type]); n->ntype = flagtab[type]; - if (useheap) - n->ntype |= NT_HEAP; return (void *) n; } + +/* duplicate a syntax tree */ /**/ void * dupstruct(void *a) -{ - struct node *n, *r; - - n = (struct node *) a; - if (!a || ((List) a) == &dummy_list) - return (void *) a; - - if ((n->ntype & NT_HEAP) && !useheap) { - HEAPALLOC { - n = (struct node *) dupstruct2((void *) n); - } LASTALLOC; - n = simplifystruct(n); - } - r = (struct node *)dupstruct2((void *) n); - - if (!(n->ntype & NT_HEAP) && useheap) - r = expandstruct(r, N_LIST); - - return (void *) r; -} - -/**/ -static struct node * -simplifystruct(struct node *n) -{ - if (!n || ((List) n) == &dummy_list) - return n; - - switch (NT_TYPE(n->ntype)) { - case N_LIST: - { - List l = (List) n; - - l->left = (Sublist) simplifystruct((struct node *)l->left); - if ((l->type & Z_SYNC) && !l->right) - return (struct node *)l->left; - } - break; - case N_SUBLIST: - { - Sublist sl = (Sublist) n; - - sl->left = (Pline) simplifystruct((struct node *)sl->left); - if (sl->type == END && !sl->flags && !sl->right) - return (struct node *)sl->left; - } - break; - case N_PLINE: - { - Pline pl = (Pline) n; - - pl->left = (Cmd) simplifystruct((struct node *)pl->left); - if (pl->type == END && !pl->right) - return (struct node *)pl->left; - } - break; - case N_CMD: - { - Cmd c = (Cmd) n; - int i = 0; - - if (empty(c->args)) - c->args = NULL, i++; - if (empty(c->redir)) - c->redir = NULL, i++; - if (empty(c->vars)) - c->vars = NULL, i++; - - c->u.list = (List) simplifystruct((struct node *)c->u.list); - if (i == 3 && !c->flags && - (c->type == CWHILE || c->type == CIF || - c->type == COND)) - return (struct node *)c->u.list; - } - break; - case N_FOR: - { - Forcmd f = (Forcmd) n; - - f->list = (List) simplifystruct((struct node *)f->list); - } - break; - case N_CASE: - { - struct casecmd *c = (struct casecmd *)n; - List *l; - - for (l = c->lists; *l; l++) - *l = (List) simplifystruct((struct node *)*l); - } - break; - case N_IF: - { - struct ifcmd *i = (struct ifcmd *)n; - List *l; - - for (l = i->ifls; *l; l++) - *l = (List) simplifystruct((struct node *)*l); - for (l = i->thenls; *l; l++) - *l = (List) simplifystruct((struct node *)*l); - } - break; - case N_WHILE: - { - struct whilecmd *w = (struct whilecmd *)n; - - w->cont = (List) simplifystruct((struct node *)w->cont); - w->loop = (List) simplifystruct((struct node *)w->loop); - } - } - - return n; -} - -/**/ -struct node * -expandstruct(struct node *n, int exp) -{ - struct node *m; - - if (!n || ((List) n) == &dummy_list) - return n; - - if (exp != N_COUNT && exp != NT_TYPE(n->ntype)) { - switch (exp) { - case N_LIST: - { - List l; - - m = (struct node *) allocnode(N_LIST); - l = (List) m; - l->type = Z_SYNC; - l->left = (Sublist) expandstruct(n, N_SUBLIST); - - return (struct node *)l; - } - case N_SUBLIST: - { - Sublist sl; - - m = (struct node *) allocnode(N_SUBLIST); - sl = (Sublist) m; - sl->type = END; - sl->left = (Pline) expandstruct(n, N_PLINE); - - return (struct node *)sl; - } - case N_PLINE: - { - Pline pl; - - m = (struct node *) allocnode(N_PLINE); - pl = (Pline) m; - pl->type = END; - pl->left = (Cmd) expandstruct(n, N_CMD); - - return (struct node *)pl; - } - case N_CMD: - { - Cmd c; - - m = (struct node *) allocnode(N_CMD); - c = (Cmd) m; - switch (NT_TYPE(n->ntype)) { - case N_WHILE: - c->type = CWHILE; - break; - case N_IF: - c->type = CIF; - break; - case N_COND: - c->type = COND; - } - c->u.list = (List) expandstruct(n, NT_TYPE(n->ntype)); - c->args = newlinklist(); - c->vars = newlinklist(); - c->redir = newlinklist(); - - return (struct node *)c; - } - } - } else - switch (NT_TYPE(n->ntype)) { - case N_LIST: - { - List l = (List) n; - - l->left = (Sublist) expandstruct((struct node *)l->left, - N_SUBLIST); - l->right = (List) expandstruct((struct node *)l->right, - N_LIST); - } - break; - case N_SUBLIST: - { - Sublist sl = (Sublist) n; - - sl->left = (Pline) expandstruct((struct node *)sl->left, - N_PLINE); - sl->right = (Sublist) expandstruct((struct node *)sl->right, - N_SUBLIST); - } - break; - case N_PLINE: - { - Pline pl = (Pline) n; - - pl->left = (Cmd) expandstruct((struct node *)pl->left, - N_CMD); - pl->right = (Pline) expandstruct((struct node *)pl->right, - N_PLINE); - } - break; - case N_CMD: - { - Cmd c = (Cmd) n; - - if (!c->args) - c->args = newlinklist(); - if (!c->vars) - c->vars = newlinklist(); - if (!c->redir) - c->redir = newlinklist(); - - switch (c->type) { - case CFOR: - case CSELECT: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_FOR); - break; - case CWHILE: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_WHILE); - break; - case CIF: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_IF); - break; - case CCASE: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_CASE); - break; - case COND: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_COND); - break; - case ZCTIME: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_SUBLIST); - break; - case AUTOFN: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_AUTOFN); - break; - default: - c->u.list = (List) expandstruct((struct node *)c->u.list, - N_LIST); - } - } - break; - case N_FOR: - { - Forcmd f = (Forcmd) n; - - f->list = (List) expandstruct((struct node *)f->list, - N_LIST); - } - break; - case N_CASE: - { - struct casecmd *c = (struct casecmd *)n; - List *l; - - for (l = c->lists; *l; l++) - *l = (List) expandstruct((struct node *)*l, N_LIST); - } - break; - case N_IF: - { - struct ifcmd *i = (struct ifcmd *)n; - List *l; - - for (l = i->ifls; *l; l++) - *l = (List) expandstruct((struct node *)*l, N_LIST); - for (l = i->thenls; *l; l++) - *l = (List) expandstruct((struct node *)*l, N_LIST); - } - break; - case N_WHILE: - { - struct whilecmd *w = (struct whilecmd *)n; - - w->cont = (List) expandstruct((struct node *)w->cont, - N_LIST); - w->loop = (List) expandstruct((struct node *)w->loop, - N_LIST); - } - } - - return n; -} - -/* duplicate a syntax tree */ - -/**/ -static void * -dupstruct2(void *a) { void **onodes, **nnodes, *ret, *n, *on; - int type, heap; + int type; size_t nodeoffs; if (!a || ((List) a) == &dummy_list) @@ -2183,53 +1944,33 @@ dupstruct2(void *a) type = *(int *)a; ret = alloc(sizetab[NT_TYPE(type)]); memcpy(ret, a, nodeoffs = offstab[NT_TYPE(type)]); - *(int*)ret = (type & ~NT_HEAP) | (useheap ? NT_HEAP : 0); onodes = (void **) ((char *)a + nodeoffs); nnodes = (void **) ((char *)ret + nodeoffs); - heap = type & NT_HEAP; for (type = (type & 0xffff00) >> 4; (type >>= 4); *nnodes++ = n) { if (!(on = *onodes++)) n = NULL; else { switch (type & 0xf) { case NT_NODE: - n = dupstruct2(on); + n = dupstruct(on); break; case NT_STR: n = dupstring(on); break; case NT_LIST | NT_NODE: - if (heap) { - if (useheap) - n = duplist(on, (VFunc) dupstruct2); - else - n = list2arr(on, (VFunc) dupstruct2); - } - else if (useheap) - n = arr2list(on, (VFunc) dupstruct2); - else - n = duparray(on, (VFunc) dupstruct2); + n = duplist(on, (VFunc) dupstruct); break; case NT_LIST | NT_STR: - if (heap) { - if (useheap) - n = duplist(on, (VFunc) dupstring); - else - n = list2arr(on, (VFunc) ztrdup); - } - else if (useheap) - n = arr2list(on, (VFunc) dupstring); - else - n = duparray(on, (VFunc) ztrdup); + n = duplist(on, (VFunc) (useheap ? dupstring : ztrdup)); break; case NT_NODE | NT_ARR: - n = duparray(on, (VFunc) dupstruct2); + n = duparray(on, (VFunc) dupstruct); break; case NT_STR | NT_ARR: n = duparray(on, (VFunc) (useheap ? dupstring : ztrdup)); break; default: - DPUTS(1, "BUG: bad node type in dupstruct2()"); + DPUTS(1, "BUG: bad node type in dupstruct()"); abort(); } } @@ -2237,19 +1978,46 @@ dupstruct2(void *a) return ret; } -/* free a syntax tree */ +/* Free a syntax tree. Now, freestruct() only registers everything that + * has to be freed. Later, freestructs() will be called to do the real + * work. This is to avoid having functions that are currently executed + * free themselves by re-defining themselves. */ + +static LinkList freeslist = NULL; /**/ void freestruct(void *a) { - void **nodes, *n; - int type, size; - if (!a || ((List) a) == &dummy_list) return; - type = * (int *) a; + PERMALLOC { + if (!freeslist) + freeslist = newlinklist(); + addlinknode(freeslist, a); + } LASTALLOC; +} + +/**/ +void +freestructs(void) +{ + void *a; + + if (freeslist) + while ((a = getlinknode(freeslist))) + ifreestruct(a); +} + +/**/ +static void +ifreestruct(void *a) +{ + void **nodes, *n; + int type, size; + + type = *(int *) a; nodes = (void **) ((char *)a + offstab[NT_TYPE(type)]); size = sizetab[NT_TYPE(type)]; for (type = (type & 0xffff00) >> 4; (type >>= 4);) { @@ -2262,6 +2030,8 @@ freestruct(void *a) zsfree((char *) n); break; case NT_LIST | NT_NODE: + freelinklist((LinkList) n, (FreeFunc) freestruct); + break; case NT_NODE | NT_ARR: { void **p = (void **) n; @@ -2272,6 +2042,8 @@ freestruct(void *a) break; } case NT_LIST | NT_STR: + freelinklist((LinkList) n, (FreeFunc) zsfree); + break; case NT_STR | NT_ARR: freearray((char **) n); break; @@ -2287,58 +2059,46 @@ freestruct(void *a) } /**/ -static LinkList -duplist(LinkList l, VFunc func) +LinkList +dupheaplist(LinkList l) { - LinkList ret; - LinkNode node; - - ret = newlinklist(); - for (node = firstnode(l); node; incnode(node)) - addlinknode(ret, func(getdata(node))); - return ret; -} - -/**/ -char ** -duparray(char **arr, VFunc func) -{ - char **ret, **rr; - - ret = (char **) alloc((arrlen(arr) + 1) * sizeof(char *)); - for (rr = ret; *arr;) - *rr++ = (char *)func(*arr++); - *rr = NULL; + if (!l) + return NULL; - return ret; + return duplist(l, (VFunc) dupstruct); } /**/ -static char ** -list2arr(LinkList l, VFunc func) +static LinkList +duplist(LinkList l, VFunc func) { - char **arr, **r; - LinkNode n; - - arr = r = (char **) alloc((countlinknodes(l) + 1) * sizeof(char *)); + if (l && nonempty(l)) { + LinkList ret; + LinkNode node; - for (n = firstnode(l); n; incnode(n)) - *r++ = (char *)func(getdata(n)); - *r = NULL; - - return arr; + ret = newlinklist(); + for (node = firstnode(l); node; incnode(node)) + addlinknode(ret, func(getdata(node))); + return ret; + } + return NULL; } /**/ -static LinkList -arr2list(char **arr, VFunc func) +char ** +duparray(char **arr, VFunc func) { - LinkList l = newlinklist(); + if (arr && *arr) { + char **ret, **rr, *p; - while (*arr) - addlinknode(l, func(*arr++)); + ret = (char **) alloc((arrlen(arr) + 1) * sizeof(char *)); + for (rr = ret; (p = *arr++);) + *rr++ = (char *)func(p); + *rr = NULL; - return l; + return ret; + } + return NULL; } /**/ @@ -2384,28 +2144,6 @@ equalsplit(char *s, char **t) return 0; } -/* see if the right side of a list is trivial */ - -/**/ -void -simplifyright(List l) -{ - Cmd c; - - if (l == &dummy_list || !l->right) - return; - if (l->right->right || l->right->left->right || - l->right->left->flags || l->right->left->left->right || - l->left->flags) - return; - c = l->left->left->left; - if (c->type != SIMPLE || nonempty(c->args) || nonempty(c->redir) - || nonempty(c->vars)) - return; - l->right = NULL; - return; -} - /* the ztypes table */ /**/ @@ -2470,6 +2208,25 @@ arrdup(char **s) return y; } +/* Duplicate a list of strings. */ + +/**/ +LinkList +listdup(LinkList l) +{ + if (!l) + return NULL; + else { + LinkList r = newlinklist(); + LinkNode n; + + for (n = firstnode(l); n; incnode(n)) + addlinknode(r, dupstring((char *) getdata(n))); + + return r; + } +} + /**/ char ** listarr(LinkList l) diff --git a/Src/zsh.export b/Src/zsh.export index ef9fca8c6..72779e24a 100644 --- a/Src/zsh.export +++ b/Src/zsh.export @@ -75,6 +75,7 @@ findcmd firsthist freearray freeheap +freelinklist freestruct getaparam gethashnode @@ -113,6 +114,7 @@ hist_skip_flags holdintr hptr hrealloc +ifs inbufct incmdpos incond @@ -179,7 +181,6 @@ path pathchecked popheap postedit -pparams ppid prefork prepromptfns diff --git a/Src/zsh.h b/Src/zsh.h index 4d46beada..e7b6e5ae0 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -47,7 +47,11 @@ */ #ifdef ZSH_64_BIT_TYPE typedef ZSH_64_BIT_TYPE zlong; -typedef unsigned ZSH_64_BIT_TYPE zulong; +#ifdef ZSH_64_BIT_UTYPE +typedef ZSH_64_BIT_UTYPE zulong; +#else +typedef unsigned zlong zulong; +#endif #else typedef long zlong; typedef unsigned long zulong; @@ -352,7 +356,6 @@ struct node { #define NT_N(T, N) (((T) >> (8 + (N) * 4)) & 0xf) #define NT_SET(T0, T1, T2, T3, T4) \ ((T0) | ((T1) << 8) | ((T2) << 12) | ((T3) << 16) | ((T4) << 20)) -#define NT_HEAP (1 << 30) /* tree element for lists */ @@ -605,7 +608,7 @@ struct job { pid_t gleader; /* process group leader of this job */ pid_t other; /* subjob id or subshell pid */ int stat; /* see STATs below */ - char *pwd; /* current working dir of shell when * + char pwd[PATH_MAX + 1]; /* current working dir of shell when * * this job was spawned */ struct process *procs; /* list of processes */ LinkList filelist; /* list of files to delete when done */ @@ -948,7 +951,12 @@ struct param { #define PM_READONLY (1<<8) /* readonly */ #define PM_TAGGED (1<<9) /* tagged */ #define PM_EXPORTED (1<<10) /* exported */ + +/* The following are the same since they * + * both represent -U option to typeset */ #define PM_UNIQUE (1<<11) /* remove duplicates */ +#define PM_UNALIASED (1<<11) /* do not expand aliases when autoloading */ + #define PM_TIED (1<<12) /* array tied to colon-path or v.v. */ #define PM_SPECIAL (1<<13) /* special builtin parameter */ #define PM_DONTIMPORT (1<<14) /* do not import this variable */ diff --git a/Src/zsh.mdd b/Src/zsh.mdd index bd9aabc2e..ef04658b1 100644 --- a/Src/zsh.mdd +++ b/Src/zsh.mdd @@ -31,7 +31,16 @@ version.h: $(sdir_top)/Config/version.mk zshpaths.h: FORCE Makemod @echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp @if test x$(fndir) != xno; then \ - echo '#define FUNCTION_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \ + echo '#define FPATH_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \ + if test x$(FUNCTIONS_SUBDIRS) != x -a \ + x$(FUNCTIONS_SUBDIRS) != xno; then \ + fpath_tmp="`for f in $$FUNCTIONS_INSTALL; do \ + echo $$f | sed s%/.*%%; \ + done | sort | uniq`"; \ + fpath_tmp="`echo $$fpath_tmp | sed 's/ /\", \"/g'`"; \ + echo "#define FPATH_SUBDIRS { \"$$fpath_tmp\" }" \ + >>zshpaths.h.tmp; \ + fi; \ fi @if cmp -s zshpaths.h zshpaths.h.tmp; then \ rm -f zshpaths.h.tmp; \ -- cgit 1.4.1