From 52b8303537015f603f35351abe2a01d8779868fe Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Mon, 17 Dec 2001 17:17:38 +0000 Subject: 16353: add += parameter assignments --- Src/exec.c | 11 +++-- Src/lex.c | 1 + Src/params.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- Src/parse.c | 27 +++++++++---- Src/text.c | 1 + Src/zsh.h | 10 ++++- 6 files changed, 156 insertions(+), 22 deletions(-) (limited to 'Src') diff --git a/Src/exec.c b/Src/exec.c index ed8293b24..e7b57967b 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1512,7 +1512,8 @@ addvars(Estate state, Wordcode pc, int export) if (htok) untokenize(name); if (xtr) - fprintf(xtrerr, "%s=", name); + fprintf(xtrerr, + WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC ? "%s+=" : "%s=", name); if ((isstr = (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR))) { init_list1(svl, ecgetstr(state, EC_DUPTOK, &htok)); vl = &svl; @@ -1561,10 +1562,12 @@ addvars(Estate state, Wordcode pc, int export) } allexp = opts[ALLEXPORT]; opts[ALLEXPORT] = 1; - pm = setsparam(name, val); + pm = assignsparam(name, val, + WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC); opts[ALLEXPORT] = allexp; } else - pm = setsparam(name, val); + pm = assignsparam(name, val, + WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC); if (errflag) { state->pc = opc; return; @@ -1587,7 +1590,7 @@ addvars(Estate state, Wordcode pc, int export) fprintf(xtrerr, "%s ", *ptr); fprintf(xtrerr, ") "); } - setaparam(name, arr); + assignaparam(name, arr, WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC); if (errflag) { state->pc = opc; return; diff --git a/Src/lex.c b/Src/lex.c index 245e7bb15..11404a646 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1140,6 +1140,7 @@ gettokstr(int c, int sub) skipparens(Inbrack, Outbrack, &t); } } + if (*t == '+') t++; if (t == bptr) { e = hgetc(); if (e == '(' && incmdpos) { diff --git a/Src/params.c b/Src/params.c index 5c4d61e69..6fb5da57f 100644 --- a/Src/params.c +++ b/Src/params.c @@ -1724,9 +1724,12 @@ setarrvalue(Value v, char **val) } if (v->start == 0 && v->end == -1) { if (PM_TYPE(v->pm->flags) == PM_HASHED) - arrhashsetfn(v->pm, val); + arrhashsetfn(v->pm, val, 0); else (v->pm->sets.afn) (v->pm, val); + } else if (v->start == -1 && v->end == 0 && + PM_TYPE(v->pm->flags) == PM_HASHED) { + arrhashsetfn(v->pm, val, 1); } else { char **old, **new, **p, **q, **r; int n, ll, i; @@ -1870,12 +1873,15 @@ gethkparam(char *s) /**/ mod_export Param -setsparam(char *s, char *val) +assignsparam(char *s, char *val, int augment) { struct value vbuf; Value v; char *t = s; - char *ss; + char *ss, *copy, *var; + size_t lv; + mnumber lhs, rhs; + int sstart; if (!isident(s)) { zerr("not an identifier: %s", s, 0); @@ -1893,8 +1899,10 @@ setsparam(char *s, char *val) } else { if (!(v = getvalue(&vbuf, &s, 1))) createparam(t, PM_SCALAR); - else if ((PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) && - !(v->pm->flags & (PM_SPECIAL|PM_TIED)) && unset(KSHARRAYS)) { + else if ((((v->pm->flags & PM_ARRAY) && !augment) || + (v->pm->flags & PM_HASHED)) && + !(v->pm->flags & (PM_SPECIAL|PM_TIED)) && + unset(KSHARRAYS)) { unsetparam(t); createparam(t, PM_SCALAR); v = NULL; @@ -1905,6 +1913,78 @@ setsparam(char *s, char *val) zsfree(val); return NULL; } + if (augment) { + if (v->start == 0 && v->end == -1) { + switch (PM_TYPE(v->pm->flags)) { + case PM_SCALAR: + v->start = INT_MAX; /* just append to scalar value */ + break; + case PM_INTEGER: + case PM_EFLOAT: + case PM_FFLOAT: + rhs = matheval(val); + lhs = getnumvalue(v); + if (lhs.type == MN_FLOAT) { + if ((rhs.type) == MN_FLOAT) + lhs.u.d = lhs.u.d + rhs.u.d; + else + lhs.u.d = lhs.u.d + (double)rhs.u.l; + } else { + if ((rhs.type) == MN_INTEGER) + lhs.u.l = lhs.u.l + rhs.u.l; + else + lhs.u.l = lhs.u.l + (zlong)rhs.u.d; + } + setnumvalue(v, lhs); + unqueue_signals(); + zsfree(val); + return v->pm; /* avoid later setstrvalue() call */ + case PM_ARRAY: + if (unset(KSHARRAYS)) { + v->start = arrlen(v->pm->gets.afn(v->pm)); + v->end = v->start + 1; + } else { + /* ksh appends scalar to first element */ + v->end = 1; + goto kshappend; + } + break; + } + } else { + switch (PM_TYPE(v->pm->flags)) { + case PM_SCALAR: + if (v->end > 0) + v->start = v->end; + else + v->start = v->end = strlen(v->pm->gets.cfn(v->pm)) + + v->end + 1; + break; + case PM_INTEGER: + case PM_EFLOAT: + case PM_FFLOAT: + unqueue_signals(); + zerr("attempt to add to slice of a numeric variable", + NULL, 0); + zsfree(val); + return NULL; + case PM_ARRAY: + kshappend: + /* treat slice as the end element */ + v->start = sstart = v->end > 0 ? v->end - 1 : v->end; + v->isarr = 0; + var = getstrvalue(v); + v->start = sstart; + copy = val; + lv = strlen(var); + val = (char *)zalloc(lv + strlen(var)); + strcpy(val, var); + strcpy(val + lv, copy); + zsfree(copy); + break; + } + } + } + setstrvalue(v, val); unqueue_signals(); return v->pm; @@ -1912,7 +1992,7 @@ setsparam(char *s, char *val) /**/ mod_export Param -setaparam(char *s, char **val) +assignaparam(char *s, char **val, int augment) { struct value vbuf; Value v; @@ -1946,6 +2026,18 @@ setaparam(char *s, char **val) else if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) && !(v->pm->flags & (PM_SPECIAL|PM_TIED))) { int uniq = v->pm->flags & PM_UNIQUE; + if (augment) { + /* insert old value at the beginning of the val array */ + char **new; + int lv = arrlen(val); + + new = (char **) zalloc(sizeof(char *) * (lv + 2)); + *new = ztrdup(getstrvalue(v)); + memcpy(new+1, val, sizeof(char *) * (lv + 1)); + free(val); + val = new; + + } unsetparam(t); createparam(t, PM_ARRAY | uniq); v = NULL; @@ -1954,8 +2046,27 @@ setaparam(char *s, char **val) if (!v) if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING))) { unqueue_signals(); + freearray(val); return NULL; } + + if (augment) { + if (v->start == 0 && v->end == -1) { + if (PM_TYPE(v->pm->flags) & PM_ARRAY) { + v->start = arrlen(v->pm->gets.afn(v->pm)); + v->end = v->start + 1; + } else if (PM_TYPE(v->pm->flags) & PM_HASHED) + v->start = -1, v->end = 0; + } else { + if (v->end > 0) + v->start = v->end--; + else if (PM_TYPE(v->pm->flags) & PM_ARRAY) { + v->end = arrlen(v->pm->gets.afn(v->pm)) + v->end; + v->start = v->end + 1; + } + } + } + setarrvalue(v, val); unqueue_signals(); return v->pm; @@ -2291,7 +2402,7 @@ hashsetfn(Param pm, HashTable x) /**/ static void -arrhashsetfn(Param pm, char **val) +arrhashsetfn(Param pm, char **val, int augment) { /* Best not to shortcut this by using the existing hash table, * * since that could cause trouble for special hashes. This way, * @@ -2309,7 +2420,8 @@ arrhashsetfn(Param pm, char **val) return; } if (alen) - ht = paramtab = newparamtable(17, pm->nam); + if (!(augment && (ht = paramtab = pm->gets.hfn(pm)))) + ht = paramtab = newparamtable(17, pm->nam); while (*aptr) { /* The parameter name is ztrdup'd... */ v->pm = createparam(*aptr, PM_SCALAR|PM_UNSET); diff --git a/Src/parse.c b/Src/parse.c index fefbbfe32..48332733b 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1488,11 +1488,17 @@ par_simple(int *complex, int nr) } else if (tok == ENVSTRING) { char *p, *name, *str; - ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, 0)); name = tokstr; - for (p = tokstr; *p && *p != Inbrack && *p != '='; p++); - if (*p == Inbrack && !skipparens(Inbrack, Outbrack, &p) && - *p == '=') { + for (p = tokstr; *p && *p != Inbrack && *p != '=' && *p != '+'; + p++); + if (*p == Inbrack) skipparens(Inbrack, Outbrack, &p); + if (*p == '+') { + *p++ = '\0'; + ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_INC, 0)); + } else + ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_NEW, 0)); + + if (*p == '=') { *p = '\0'; str = p + 1; } else @@ -1501,15 +1507,20 @@ par_simple(int *complex, int nr) ecstr(str); isnull = 0; } else if (tok == ENVARRAY) { - int oldcmdpos = incmdpos, n; + int oldcmdpos = incmdpos, n, type2; p = ecadd(0); incmdpos = 0; + if ((type2 = strlen(tokstr) - 1) && tokstr[type2] == '+') { + tokstr[type2] = '\0'; + type2 = WC_ASSIGN_INC; + } else + type2 = WC_ASSIGN_NEW; ecstr(tokstr); cmdpush(CS_ARRAY); yylex(); n = par_nl_wordlist(); - ecbuf[p] = WCB_ASSIGN(WC_ASSIGN_ARRAY, n); + ecbuf[p] = WCB_ASSIGN(WC_ASSIGN_ARRAY, type2, n); cmdpop(); if (tok != OUTPAR) YYERROR(oecused); @@ -2288,8 +2299,8 @@ init_eprog(void) #define FD_MINMAP 4096 #define FD_PRELEN 12 -#define FD_MAGIC 0x03040506 -#define FD_OMAGIC 0x06050403 +#define FD_MAGIC 0x04050607 +#define FD_OMAGIC 0x07060504 #define FDF_MAP 1 #define FDF_OTHER 2 diff --git a/Src/text.c b/Src/text.c index ddb4b8a2a..44527666d 100644 --- a/Src/text.c +++ b/Src/text.c @@ -323,6 +323,7 @@ gettext2(Estate state) break; case WC_ASSIGN: taddstr(ecgetstr(state, EC_NODUP, NULL)); + if (WC_ASSIGN_TYPE2(code) == WC_ASSIGN_INC) taddchr('+'); taddchr('='); if (WC_ASSIGN_TYPE(code) == WC_ASSIGN_ARRAY) { taddchr('('); diff --git a/Src/zsh.h b/Src/zsh.h index cd6caf3b3..28a3c20e9 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -591,10 +591,13 @@ struct eccstr { #define WCB_REDIR(T) wc_bld(WC_REDIR, (T)) #define WC_ASSIGN_TYPE(C) (wc_data(C) & ((wordcode) 1)) +#define WC_ASSIGN_TYPE2(C) ((wc_data(C) & ((wordcode) 2)) >> 1) #define WC_ASSIGN_SCALAR 0 #define WC_ASSIGN_ARRAY 1 -#define WC_ASSIGN_NUM(C) (wc_data(C) >> 1) -#define WCB_ASSIGN(T,N) wc_bld(WC_ASSIGN, ((T) | ((N) << 1))) +#define WC_ASSIGN_NEW 0 +#define WC_ASSIGN_INC 1 +#define WC_ASSIGN_NUM(C) (wc_data(C) >> 2) +#define WCB_ASSIGN(T,A,N) wc_bld(WC_ASSIGN, ((T) | ((A) << 1) | ((N) << 2))) #define WC_SIMPLE_ARGC(C) wc_data(C) #define WCB_SIMPLE(N) wc_bld(WC_SIMPLE, (N)) @@ -1198,6 +1201,9 @@ struct paramdef { { name, PM_ARRAY, (void *) var, (void *) arrvarsetfn, \ (void *) arrvargetfn, (void *) stdunsetfn } +#define setsparam(S,V) assignsparam(S,V,0) +#define setaparam(S,V) assignaparam(S,V,0) + /* node for named directory hash table (nameddirtab) */ struct nameddir { -- cgit 1.4.1