diff options
-rw-r--r-- | Config/version.mk | 4 | ||||
-rw-r--r-- | Src/Modules/zutil.c | 10 | ||||
-rw-r--r-- | Src/Zle/compcore.c | 2 | ||||
-rw-r--r-- | Src/Zle/computil.c | 15 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 6 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 2 | ||||
-rw-r--r-- | Src/builtin.c | 30 | ||||
-rw-r--r-- | Src/glob.c | 2 | ||||
-rw-r--r-- | Src/params.c | 82 | ||||
-rw-r--r-- | Src/prompt.c | 2 | ||||
-rw-r--r-- | Src/subst.c | 27 | ||||
-rw-r--r-- | Src/utils.c | 6 | ||||
-rw-r--r-- | Src/zsh.h | 5 |
13 files changed, 132 insertions, 61 deletions
diff --git a/Config/version.mk b/Config/version.mk index 0ebed5e78..a15ccb964 100644 --- a/Config/version.mk +++ b/Config/version.mk @@ -27,5 +27,5 @@ # This must also serve as a shell script, so do not add spaces around the # `=' signs. -VERSION=5.3.1-dev-0 -VERSION_DATE='December 22, 2016' +VERSION=5.3.1-dev-0-badarrays +VERSION_DATE='May 28, 2017' diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 19a8306b5..82542cf4f 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -42,11 +42,11 @@ savematch(MatchData *m) char **a; queue_signals(); - a = getaparam("match"); + a = getaparam("match", NULL); m->match = a ? zarrdup(a) : NULL; - a = getaparam("mbegin"); + a = getaparam("mbegin", NULL); m->mbegin = a ? zarrdup(a) : NULL; - a = getaparam("mend"); + a = getaparam("mend", NULL); m->mend = a ? zarrdup(a) : NULL; unqueue_signals(); } @@ -402,7 +402,7 @@ evalstyle(Stypat p) errflag = ef | (errflag & ERRFLAG_INT); queue_signals(); - if ((ret = getaparam("reply"))) + if ((ret = getaparam("reply", NULL))) ret = arrdup(ret); else if ((str = getsparam("reply"))) { ret = (char **) hcalloc(2 * sizeof(char *)); @@ -1343,7 +1343,7 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp) int len; queue_signals(); - mend = getaparam("mend"); + mend = getaparam("mend", NULL); len = atoi(mend[0]); unqueue_signals(); diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index d1cf7a08a..5fc15b0d3 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -1971,7 +1971,7 @@ get_user_var(char *nam) char **arr = NULL, *val; queue_signals(); - if ((arr = getaparam(nam)) || (arr = gethparam(nam))) + if ((arr = getaparam(nam, NULL)) || (arr = gethparam(nam))) arr = (incompfunc ? arrdup(arr) : arr); else if ((val = getsparam(nam))) { arr = (char **) zhalloc(2*sizeof(char *)); diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index e704f9ffa..7ffe00df4 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -871,7 +871,7 @@ bin_compdescribe(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } else { char **opts; - if (!(opts = getaparam(args[4]))) { + if (!(opts = getaparam(args[4], NULL))) { zwarnnam(nam, "unknown parameter: %s", args[4]); return 1; } @@ -4929,17 +4929,16 @@ bin_compfiles(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) return 1; } queue_signals(); - if (!(tmp = getaparam(args[1]))) { - unqueue_signals(); + if (!(tmp = getaparam(args[1], NULL))) { zwarnnam(nam, "unknown parameter: %s", args[1]); return 0; } for (l = newlinklist(); *tmp; tmp++) addlinknode(l, quotestring(*tmp, QT_BACKSLASH_PATTERN)); set_list_array(args[1], cf_pats((args[0][1] == 'P'), !!args[0][2], - l, getaparam(args[2]), args[3], + l, getaparam(args[2], NULL), args[3], args[4], args[5], - getaparam(args[6]), args + 7)); + getaparam(args[6], NULL), args + 7)); unqueue_signals(); return 0; } @@ -4960,12 +4959,12 @@ bin_compfiles(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) return 1; } queue_signals(); - tmp = getaparam(args[2]); + tmp = getaparam(args[2], NULL); l = newlinklist(); if (tmp) for (; *tmp; tmp++) addlinknode(l, *tmp); - if (!(tmp = getaparam(args[1]))) { + if (!(tmp = getaparam(args[1], NULL))) { unqueue_signals(); zwarnnam(nam, "unknown parameter: %s", args[1]); return 0; @@ -4990,7 +4989,7 @@ bin_compfiles(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) return 1; } queue_signals(); - if (!(tmp = getaparam(args[1]))) { + if (!(tmp = getaparam(args[1], NULL))) { unqueue_signals(); zwarnnam(nam, "unknown parameter: %s", args[1]); return 0; diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 6c271b5d0..dda2f56e6 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1193,6 +1193,7 @@ char * zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) { char *s, **bracket; + int bracket_len; int old_errno = errno; int tmout = getiparam("TMOUT"); @@ -1328,7 +1329,8 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) if (zleline && *zleline) redrawhook(); - if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2) + if ((bracket = getaparam("zle_bracketed_paste", &bracket_len)) && + bracket_len == 2) fputs(*bracket, shout); zrefresh(); @@ -1340,7 +1342,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) "ZLE_VARED_ABORTED" : "ZLE_LINE_ABORTED", zlegetline(NULL, NULL)); - if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2) + if ((bracket = getaparam("zle_bracketed_paste", &bracket_len)) && bracket_len == 2) fputs(bracket[1], shout); if (done && !exit_pending && !errflag) diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index d0dd1ef06..a64e2f29e 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -313,7 +313,7 @@ static const REFRESH_ELEMENT zr_start_ellipsis[] = { static void zle_set_highlight(void) { - char **atrs = getaparam("zle_highlight"); + char **atrs = getaparam("zle_highlight", NULL); int special_atr_on_set = 0; int region_atr_on_set = 0; int isearch_atr_on_set = 0; diff --git a/Src/builtin.c b/Src/builtin.c index 063644efb..d54b0f41c 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -30,6 +30,8 @@ /* this is defined so we get the prototype for open_memstream */ #define _GNU_SOURCE 1 +#include <assert.h> + #include "zsh.mdh" #include "builtin.pro" @@ -53,7 +55,7 @@ static struct builtin builtins[] = BUILTIN("cd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "qsPL", NULL), BUILTIN("chdir", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "qsPL", NULL), BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL), - BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klmprtuxz", NULL), + BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "ACE:%F:%HL:%R:%TUZ:%acfghi:%klmprtuxz", NULL), BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL), BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmprs", NULL), BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL), @@ -86,7 +88,7 @@ static struct builtin builtins[] = BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL), BUILTIN("kill", BINF_HANDLES_OPTS, bin_kill, 0, -1, 0, NULL, NULL), BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL), - BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%ahi:%lprtux", NULL), + BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "ACE:%F:%HL:%R:%TUZ:%achi:%lprtux", NULL), BUILTIN("log", 0, bin_log, 0, 0, 0, NULL, NULL), BUILTIN("logout", 0, bin_break, 0, 1, BIN_LOGOUT, NULL, NULL), @@ -106,7 +108,7 @@ static struct builtin builtins[] = BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL), BUILTIN("r", 0, bin_fc, 0, -1, BIN_R, "IlLnr", NULL), BUILTIN("read", 0, bin_read, 0, -1, 0, "cd:ek:%lnpqrst:%zu:AE", NULL), - BUILTIN("readonly", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, BIN_READONLY, "AE:%F:%HL:%R:%TUZ:%afghi:%lptux", "r"), + BUILTIN("readonly", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, BIN_READONLY, "ACE:%F:%HL:%R:%TUZ:%acfghi:%lptux", "r"), BUILTIN("rehash", 0, bin_hash, 0, 0, 0, "df", "r"), BUILTIN("return", BINF_PSPECIAL, bin_break, 0, 1, BIN_RETURN, NULL, NULL), BUILTIN("set", BINF_PSPECIAL | BINF_HANDLES_OPTS, bin_set, 0, -1, 0, NULL, NULL), @@ -120,7 +122,7 @@ static struct builtin builtins[] = BUILTIN("trap", BINF_PSPECIAL | BINF_HANDLES_OPTS, bin_trap, 0, -1, 0, NULL, NULL), BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL), BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsSw", "v"), - BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klprtuxmz", NULL), + BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "ACE:%F:%HL:%R:%TUZ:%acfghi:%klprtuxmz", NULL), BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL), BUILTIN("unalias", 0, bin_unhash, 0, -1, BIN_UNALIAS, "ams", NULL), BUILTIN("unfunction", 0, bin_unhash, 1, -1, BIN_UNFUNCTION, "m", "f"), @@ -673,11 +675,9 @@ bin_set(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) if (array) { /* create an array with the specified elements */ char **a = NULL, **y; - int len = arrlen(args); - - if (array < 0 && (a = getaparam(arrayname))) { - int al = arrlen(a); + int len = arrlen(args), al; + if (array < 0 && (a = getaparam(arrayname, &al))) { if (al > len) len = al; } @@ -3611,7 +3611,10 @@ bin_unset(char *name, char **argv, Options ops, int func) } else { /* start is after the element for reverse index */ int start = vbuf.start - !!(vbuf.flags & VALFLAG_INV); - if (arrlen_gt(vbuf.pm->u.arr, start)) { + if (!(vbuf.pm->node.flags & PM_CACHELEN)) + vbuf.pm->length = arrlen(vbuf.pm->u.arr); + assert(vbuf.pm->length == arrlen(vbuf.pm->u.arr)); + if (start < vbuf.pm->length) { char *arr[2]; arr[0] = ""; arr[1] = 0; @@ -5264,7 +5267,7 @@ bin_shift(char *name, char **argv, Options ops, UNUSED(int func)) /* optional argument can be either numeric or an array */ queue_signals(); - if (*argv && !getaparam(*argv)) + if (*argv && !getaparam(*argv, NULL)) num = mathevali(*argv++); if (num < 0) { @@ -5274,9 +5277,10 @@ bin_shift(char *name, char **argv, Options ops, UNUSED(int func)) } if (*argv) { + int len = 0; for (; *argv; argv++) - if ((s = getaparam(*argv))) { - if (arrlen_lt(s, num)) { + if ((s = getaparam(*argv, &len))) { + if (num > len) { zwarnnam(name, "shift count must be <= $#"); ret++; continue; @@ -5284,7 +5288,7 @@ bin_shift(char *name, char **argv, Options ops, UNUSED(int func)) if (OPT_ISSET(ops,'p')) { char **s2, **src, **dst; int count; - l = arrlen(s); + l = len; src = s; dst = s2 = (char **)zalloc((l - num + 1) * sizeof(char *)); for (count = l - num; count; count--) diff --git a/Src/glob.c b/Src/glob.c index af5d0821c..aeb5fd204 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -3860,7 +3860,7 @@ qualsheval(char *name, UNUSED(struct stat *buf), UNUSED(off_t days), char *str) errflag = ef | (errflag & ERRFLAG_INT); lastval = lv; - if (!(inserts = getaparam("reply")) && + if (!(inserts = getaparam("reply", NULL)) && !(inserts = gethparam("reply"))) { char *tmp; diff --git a/Src/params.c b/Src/params.c index d92dd228a..8d6cd0ee5 100644 --- a/Src/params.c +++ b/Src/params.c @@ -27,6 +27,8 @@ * */ +#include <assert.h> + #include "zsh.mdh" #include "params.pro" @@ -274,7 +276,7 @@ typedef struct iparam { static initparam special_params[] ={ #define GSU(X) BR((GsuScalar)(void *)(&(X))) #define NULL_GSU BR((GsuScalar)(void *)NULL) -#define IPDEF1(A,B,C) {{NULL,A,PM_INTEGER|PM_SPECIAL|C},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0} +#define IPDEF1(A,B,C) {{NULL,A,PM_INTEGER|PM_SPECIAL|C},BR(NULL),GSU(B),10,0,0,NULL,NULL,NULL,0} IPDEF1("#", pound_gsu, PM_READONLY), IPDEF1("ERRNO", errno_gsu, PM_UNSET), IPDEF1("GID", gid_gsu, PM_DONTIMPORT | PM_RESTRICTED), @@ -287,7 +289,7 @@ IPDEF1("UID", uid_gsu, PM_DONTIMPORT | PM_RESTRICTED), IPDEF1("EUID", euid_gsu, PM_DONTIMPORT | PM_RESTRICTED), IPDEF1("TTYIDLE", ttyidle_gsu, PM_READONLY), -#define IPDEF2(A,B,C) {{NULL,A,PM_SCALAR|PM_SPECIAL|C},BR(NULL),GSU(B),0,0,NULL,NULL,NULL,0} +#define IPDEF2(A,B,C) {{NULL,A,PM_SCALAR|PM_SPECIAL|C},BR(NULL),GSU(B),0,0,0,NULL,NULL,NULL,0} IPDEF2("USERNAME", username_gsu, PM_DONTIMPORT|PM_RESTRICTED), IPDEF2("-", dash_gsu, PM_READONLY), IPDEF2("histchars", histchars_gsu, PM_DONTIMPORT), @@ -322,7 +324,7 @@ LCIPDEF("LC_TIME"), # endif #endif /* USE_LOCALE */ -#define IPDEF4(A,B) {{NULL,A,PM_INTEGER|PM_READONLY|PM_SPECIAL},BR((void *)B),GSU(varint_readonly_gsu),10,0,NULL,NULL,NULL,0} +#define IPDEF4(A,B) {{NULL,A,PM_INTEGER|PM_READONLY|PM_SPECIAL},BR((void *)B),GSU(varint_readonly_gsu),10,0,0,NULL,NULL,NULL,0} IPDEF4("!", &lastpid), IPDEF4("$", &mypid), IPDEF4("?", &lastval), @@ -331,15 +333,15 @@ IPDEF4("LINENO", &lineno), IPDEF4("PPID", &ppid), IPDEF4("ZSH_SUBSHELL", &zsh_subshell), -#define IPDEF5(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0} -#define IPDEF5U(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0} +#define IPDEF5(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL},BR((void *)B),GSU(F),10,0,0,NULL,NULL,NULL,0} +#define IPDEF5U(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(F),10,0,0,NULL,NULL,NULL,0} IPDEF5("COLUMNS", &zterm_columns, zlevar_gsu), IPDEF5("LINES", &zterm_lines, zlevar_gsu), IPDEF5U("ZLE_RPROMPT_INDENT", &rprompt_indent, rprompt_indent_gsu), IPDEF5("SHLVL", &shlvl, varinteger_gsu), /* Don't import internal integer status variables. */ -#define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0} +#define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,0,NULL,NULL,NULL,0} IPDEF6("OPTIND", &zoptind, varinteger_gsu), IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu), IPDEF6("TRY_BLOCK_INTERRUPT", &try_interrupt, varinteger_gsu), @@ -420,7 +422,7 @@ IPDEF9F("path", &path, "PATH", PM_RESTRICTED), IPDEF10("pipestatus", pipestatus_gsu), -{{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0}, +{{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,0,NULL,NULL,NULL,0}, }; /* @@ -991,7 +993,7 @@ createparam(char *name, int flags) } pm = oldpm; - pm->base = pm->width = 0; + pm->base = pm->width = pm->length = 0; oldpm = pm->old; } else { pm = (Param) zshcalloc(sizeof *pm); @@ -1104,6 +1106,7 @@ copyparam(Param tpm, Param pm, int fakecopy) */ tpm->node.flags = pm->node.flags; tpm->base = pm->base; + tpm->length = pm->length; tpm->width = pm->width; tpm->level = pm->level; if (!fakecopy) @@ -1552,7 +1555,12 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w, ta = getarrvalue(v); if (!ta || !*ta) return !down; - len = arrlen(ta); + if (v->pm->node.flags & PM_CACHELEN) { + len = arrcachelen(v->pm); + if (v->pm->node.flags & PM_CHECKLEN) + assert(len == arrlen(ta)); + } else + len = arrlen(ta); if (beg < 0) beg += len; if (down) { @@ -1575,7 +1583,12 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w, } } else if (word) { ta = sepsplit(d = s = getstrvalue(v), sep, 1, 1); - len = arrlen(ta); + if (v->pm->node.flags & PM_CACHELEN) { + len = arrcachelen(v->pm); + if (v->pm->node.flags & PM_CHECKLEN) + assert(len == arrlen(ta)); + } else + len = arrlen(ta); if (beg < 0) beg += len; if (down) { @@ -2714,10 +2727,15 @@ setarrvalue(Value v, char **val) char **const old = v->pm->gsu.a->getfn(v->pm); char **new; char **p, **q, **r; /* index variables */ - const int pre_assignment_length = arrlen(old); + int pre_assignment_length = arrcachelen(v->pm); int post_assignment_length; int i; + if (v->pm->node.flags & PM_CACHELEN) { + if (v->pm->node.flags & PM_CHECKLEN) + assert(v->pm->length == arrlen(old)); + } else + pre_assignment_length = arrlen(old); q = old; if ((v->flags & VALFLAG_INV) && unset(KSHARRAYS)) { @@ -2880,14 +2898,25 @@ getsparam_u(char *s) /**/ mod_export char ** -getaparam(char *s) +getaparam(char *s, int *len) { struct value vbuf; Value v; if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) && PM_TYPE(v->pm->node.flags) == PM_ARRAY) + { + if (len) { + if (v->pm->node.flags & PM_CACHELEN) { + *len = arrcachelen(v->pm); + if (v->pm->node.flags & PM_CHECKLEN) + assert (*len == arrlen(v->pm->gsu.a->getfn(v->pm))); + } else + *len = arrlen(v->pm->gsu.a->getfn(v->pm)); + } + //fprintf(stderr, "%i %i\n", v->pm->length, arrlen(v->pm->gsu.a->getfn(v->pm))); return v->pm->gsu.a->getfn(v->pm); + } return NULL; } @@ -3061,7 +3090,10 @@ assignsparam(char *s, char *val, int flags) return v->pm; /* avoid later setstrvalue() call */ case PM_ARRAY: if (unset(KSHARRAYS)) { - v->start = arrlen(v->pm->gsu.a->getfn(v->pm)); + if (v->pm->node.flags & PM_CACHELEN) + v->start = arrcachelen(v->pm); + else + v->start = arrlen(v->pm->gsu.a->getfn(v->pm)); v->end = v->start + 1; } else { /* ksh appends scalar to first element */ @@ -3164,6 +3196,8 @@ assignaparam(char *s, char **val, int flags) char **new; int lv = arrlen(val); + v->pm->length = lv + 1; + new = (char **) zalloc(sizeof(char *) * (lv + 2)); *new = ztrdup(getstrvalue(v)); memcpy(new+1, val, sizeof(char *) * (lv + 1)); @@ -3188,7 +3222,16 @@ assignaparam(char *s, char **val, int flags) if (flags & ASSPM_AUGMENT) { if (v->start == 0 && v->end == -1) { if (PM_TYPE(v->pm->node.flags) & PM_ARRAY) { - v->start = arrlen(v->pm->gsu.a->getfn(v->pm)); + if (v->pm->node.flags & PM_CACHELEN) { + v->start = + //arrlen(v->pm->gsu.a->getfn(v->pm)); + arrcachelen(v->pm); + if (v->pm->node.flags & PM_CHECKLEN) + assert(v->pm->length == arrlen(v->pm->gsu.a->getfn(v->pm))); + } else { + v->start = + arrlen(v->pm->gsu.a->getfn(v->pm)); + } v->end = v->start + 1; } else if (PM_TYPE(v->pm->node.flags) & PM_HASHED) v->start = -1, v->end = 0; @@ -3196,7 +3239,16 @@ assignaparam(char *s, char **val, int flags) if (v->end > 0) v->start = v->end--; else if (PM_TYPE(v->pm->node.flags) & PM_ARRAY) { - v->end = arrlen(v->pm->gsu.a->getfn(v->pm)) + v->end; + if (v->pm->node.flags & PM_CACHELEN) { + v->end + //= arrlen(v->pm->gsu.a->getfn(v->pm)) + v->end; + += arrcachelen(v->pm); + if (v->pm->node.flags & PM_CHECKLEN) + assert(v->pm->length == arrlen(v->pm->gsu.a->getfn(v->pm))); + } else { + v->end + = arrlen(v->pm->gsu.a->getfn(v->pm)) + v->end; + } v->start = v->end + 1; } } diff --git a/Src/prompt.c b/Src/prompt.c index c478e69fb..a8bb10329 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -1889,7 +1889,7 @@ allocate_colour_buffer(void) if (colseq_buf_allocs++) return; - atrs = getaparam("zle_highlight"); + atrs = getaparam("zle_highlight", NULL); if (atrs) { for (; *atrs; atrs++) { if (strpfx("fg_start_code:", *atrs)) { diff --git a/Src/subst.c b/Src/subst.c index 5b1bf8988..a73ac4737 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -27,6 +27,8 @@ * */ +#include <assert.h> + #include "zsh.mdh" #include "subst.pro" @@ -35,6 +37,8 @@ /**/ char nulstring[] = {Nularg, '\0'}; +int arrcachelen(Param pm); + /* Do substitutions before fork. These are: * - Process substitution: <(...), >(...), =(...) * - Parameter substitution @@ -2555,9 +2559,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, * necessary joining of arrays until this point * to avoid the multsub() horror. */ - - /* arrlen() is expensive, so only compute it if needed. */ - int tmplen = -1; + int tmplen; + if (v->pm->node.flags & PM_CACHELEN) { + tmplen = arrcachelen(v->pm); + if (v->pm->node.flags & PM_CHECKLEN) + assert(tmplen == arrlen(v->pm->gsu.a->getfn(v->pm))); + } else + tmplen = -1; if (v->start < 0) { tmplen = arrlen(v->pm->gsu.a->getfn(v->pm)); @@ -3068,11 +3076,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, val = dupstring(""); } else { char *sval; - zip = getaparam(s); + int ziplen; + zip = getaparam(s, &ziplen); if (!zip) { sval = getsparam(s); if (sval) zip = hmkarray(sval); + ziplen = 1; + ziplen = !!sval; } if (!isarr) { aval = mkarray(val); @@ -3080,9 +3091,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, } if (zip) { char **out; - int alen, ziplen, outlen, i = 0; + int alen, outlen, i = 0; alen = arrlen(aval); - ziplen = arrlen(zip); outlen = shortest ^ (alen > ziplen) ? alen : ziplen; if (!shortest && (alen == 0 || ziplen == 0)) { if (ziplen) @@ -3112,6 +3122,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, } else if (inbrace && (*s == '|' || *s == Bar || *s == '*' || *s == Star)) { int intersect = (*s == '*' || *s == Star); + int compare_len; char **compare, **ap, **apsrc; ++s; if (*itype_end(s, IIDENT, 0)) { @@ -3119,9 +3130,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, zerr("not an identifier: %s", s); return NULL; } - compare = getaparam(s); + compare = getaparam(s, &compare_len); if (compare) { - HashTable ht = newuniqtable(arrlen(compare)+1); + HashTable ht = newuniqtable(compare_len+1); int present; for (ap = compare; *ap; ap++) (void)addhashnode2(ht, *ap, (HashNode) diff --git a/Src/utils.c b/Src/utils.c index acb891d82..579ab3be8 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1501,7 +1501,7 @@ callhookfunc(char *name, LinkList lnklst, int arrayp, int *retval) memcpy(arrnam, name, namlen); memcpy(arrnam + namlen, HOOK_SUFFIX, HOOK_SUFFIX_LEN); - if ((arrptr = getaparam(arrnam))) { + if ((arrptr = getaparam(arrnam, NULL))) { arrptr = arrdup(arrptr); for (; *arrptr; arrptr++) { if ((shfunc = getshfunc(*arrptr))) { @@ -3810,7 +3810,7 @@ subst_string_by_func(Shfunc func, char *arg1, char *orig) if (doshfunc(func, l, 1)) ret = NULL; else - ret = getaparam("reply"); + ret = getaparam("reply", NULL); sfcontext = osc; stopmsg = osm; @@ -3842,7 +3842,7 @@ subst_string_by_hook(char *name, char *arg1, char *orig) memcpy(arrnam, name, namlen); memcpy(arrnam + namlen, HOOK_SUFFIX, HOOK_SUFFIX_LEN); - if ((arrptr = getaparam(arrnam))) { + if ((arrptr = getaparam(arrnam, NULL))) { /* Guard against internal modification of the array */ arrptr = arrdup(arrptr); for (; *arrptr; arrptr++) { diff --git a/Src/zsh.h b/Src/zsh.h index 405b27490..7df5add86 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1779,6 +1779,7 @@ struct param { int base; /* output base or floating point prec */ int width; /* field width */ + int length; /* length of array */ char *env; /* location in environment, if exported */ char *ename; /* name of corresponding environment var */ Param old; /* old struct for use with local */ @@ -1833,6 +1834,8 @@ struct tieddata { #define PM_KSHSTORED (1<<17) /* function stored in ksh form */ #define PM_ZSHSTORED (1<<18) /* function stored in zsh form */ +#define PM_CACHELEN (1<<19) /* length is cached */ +#define PM_CHECKLEN (1<<20) /* cached length is checked */ /* Remaining flags do not correspond directly to command line arguments */ #define PM_DONTIMPORT_SUID (1<<19) /* do not import if running setuid */ @@ -1854,7 +1857,7 @@ struct tieddata { #define PM_NAMEDDIR (1<<30) /* has a corresponding nameddirtab entry */ /* The option string corresponds to the first of the variables above */ -#define TYPESET_OPTSTR "aiEFALRZlurtxUhHTkz" +#define TYPESET_OPTSTR "aiEFALRZlurtxUhHTkzcC" /* These typeset options take an optional numeric argument */ #define TYPESET_OPTNUM "LRZiEF" |