diff options
Diffstat (limited to 'Src/params.c')
-rw-r--r-- | Src/params.c | 153 |
1 files changed, 121 insertions, 32 deletions
diff --git a/Src/params.c b/Src/params.c index d92dd228a..75eff1ebb 100644 --- a/Src/params.c +++ b/Src/params.c @@ -27,6 +27,8 @@ * */ +#include <assert.h> + #include "zsh.mdh" #include "params.pro" @@ -264,6 +266,7 @@ typedef struct iparam { void *gsu; /* get/set/unset methods */ int base; /* output base */ int width; /* output 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 */ @@ -274,7 +277,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 +290,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 +325,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,22 +334,22 @@ 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), -#define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} -#define IPDEF7R(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_DONTIMPORT_SUID},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} -#define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} +#define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,0,NULL,NULL,NULL,0} +#define IPDEF7R(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_DONTIMPORT_SUID},BR((void *)B),GSU(varscalar_gsu),0,0,0,NULL,NULL,NULL,0} +#define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,0,NULL,NULL,NULL,0} IPDEF7("OPTARG", &zoptarg), IPDEF7("NULLCMD", &nullcmd), IPDEF7U("POSTEDIT", &postedit), @@ -361,7 +364,7 @@ IPDEF7("PS3", &prompt3), IPDEF7R("PS4", &prompt4), IPDEF7("SPROMPT", &sprompt), -#define IPDEF9F(A,B,C,D) {{NULL,A,D|PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(vararray_gsu),0,0,NULL,C,NULL,0} +#define IPDEF9F(A,B,C,D) {{NULL,A,D|PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(vararray_gsu),0,0,0,NULL,C,NULL,0} #define IPDEF9(A,B,C) IPDEF9F(A,B,C,0) IPDEF9F("*", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), IPDEF9F("@", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), @@ -370,9 +373,9 @@ IPDEF9F("@", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), * This empty row indicates the end of parameters available in * all emulations. */ -{{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}, -#define IPDEF8(A,B,C,D) {{NULL,A,D|PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(colonarr_gsu),0,0,NULL,C,NULL,0} +#define IPDEF8(A,B,C,D) {{NULL,A,D|PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(colonarr_gsu),0,0,0,NULL,C,NULL,0} IPDEF8("CDPATH", &cdpath, "cdpath", 0), IPDEF8("FIGNORE", &fignore, "fignore", 0), IPDEF8("FPATH", &fpath, "fpath", 0), @@ -385,7 +388,7 @@ IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, "zsh_eval_context", PM_READONLY), /* MODULE_PATH is not imported for security reasons */ IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED), -#define IPDEF10(A,B) {{NULL,A,PM_ARRAY|PM_SPECIAL},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0} +#define IPDEF10(A,B) {{NULL,A,PM_ARRAY|PM_SPECIAL},BR(NULL),GSU(B),10,0,0,NULL,NULL,NULL,0} /* * The following parameters are not available in sh/ksh compatibility * @@ -420,7 +423,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}, }; /* @@ -440,7 +443,7 @@ IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, NULL, PM_READONLY), /* MODULE_PATH is not imported for security reasons */ IPDEF8("MODULE_PATH", &module_path, NULL, PM_DONTIMPORT|PM_RESTRICTED), -{{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}, }; /* @@ -744,6 +747,20 @@ static int dontimport(int flags) return 0; } +/**/ +int +arrcachelen(Param pm) +{ + int len; + + len = pm->length; + if (len == 0 && pm->u.arr) { + len = arrlen(pm->u.arr); + pm->length = len; + } + return len; +} + /* Set up parameter hash table. This will add predefined * * parameter entries as well as setting up parameter table * * entries for environment variables we inherit. */ @@ -991,7 +1008,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 +1121,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 +1570,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 +1598,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) { @@ -2140,10 +2168,20 @@ getstrvalue(Value v) if (v->isarr) s = sepjoin(ss, NULL, 1); else { - if (v->start < 0) - v->start += arrlen(ss); - s = (arrlen_le(ss, v->start) || v->start < 0) ? - (char *) hcalloc(1) : ss[v->start]; + if (v->pm->node.flags & PM_CACHELEN) { + len = arrcachelen(v->pm); + if (v->pm->node.flags & PM_CHECKLEN) + assert(v->pm->length == arrlen(ss)); + if (v->start < 0) + v->start += len; + s = (v->start >= len || v->start < 0) ? + (char *) hcalloc(1) : ss[v->start]; + } else { + if (v->start < 0) + v->start += arrlen(ss); + s = (arrlen_le(ss, v->start) || v->start < 0) ? + (char *) hcalloc(1) : ss[v->start]; + } } return s; case PM_INTEGER: @@ -2341,10 +2379,20 @@ getarrvalue(Value v) s = getvaluearr(v); if (v->start == 0 && v->end == -1) return s; - if (v->start < 0) - v->start += arrlen(s); - if (v->end < 0) - v->end += arrlen(s) + 1; + if (v->pm->node.flags & PM_CACHELEN) { + int len = arrcachelen(v->pm); + if (v->pm->node.flags & PM_CHECKLEN) + assert(v->pm->length == arrlen(s)); + if (v->start < 0) + v->start += len; + if (v->end < 0) + v->end += len + 1; + } else { + if (v->start < 0) + v->start += arrlen(s); + if (v->end < 0) + v->end += arrlen(s) + 1; + } /* Null if 1) array too short, 2) index still negative */ if (v->end <= v->start) { @@ -2353,7 +2401,8 @@ getarrvalue(Value v) else if (v->start < 0) { s = arrdup_max(nular, 1); } - else if (arrlen_le(s, v->start)) { + else if ((v->pm->node.flags & PM_CACHELEN) ? + v->start > v->pm->length : arrlen_le(s, v->start)) { /* Handle $ary[i,i] consistently for any $i > $#ary * and $ary[i,j] consistently for any $j > $i > $#ary */ @@ -2714,10 +2763,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)) { @@ -2810,6 +2864,7 @@ setarrvalue(Value v, char **val) v->pm->gsu.a->setfn(v->pm, new); } + v->pm->length = post_assignment_length; DPUTS2(p - new != post_assignment_length, "setarrvalue: wrong allocation: %d 1= %lu", post_assignment_length, (unsigned long)(p - new)); @@ -2880,14 +2935,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 +3127,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 +3233,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 +3259,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 +3276,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; } } |