diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | Src/builtin.c | 35 | ||||
-rw-r--r-- | Src/lex.c | 8 | ||||
-rw-r--r-- | Src/params.c | 29 | ||||
-rw-r--r-- | Test/D06subscript.ztst | 8 |
5 files changed, 70 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog index 8636cd1a5..e477fdd60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2001-04-21 Bart Schaefer <schaefer@zsh.org> + + * 14060: Src/builtin.c, Src/lex.c, Src/params.c, + Test/D06subscript.ztst: Fix problem with ${array[ix]=value} + introduced by 14008; fix long-standing problems with + `noglob typeset array[ix]=value' and `typeset 12foo=bar'; + fix parsing problem with ((\[ ...)) introduced by 14051. + 2001-04-20 Clint Adams <schizo@debian.org> * 14055: Src/Modules/termcap.c: include termio.h if available. diff --git a/Src/builtin.c b/Src/builtin.c index 0f02ae0a9..bc1a35f90 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -1691,7 +1691,7 @@ typeset_single(char *cname, char *pname, Param pm, int func, pm->env = NULL; } if (value && !(pm = setsparam(pname, ztrdup(value)))) - return 0; + return NULL; } else if (value) { zwarnnam(cname, "can't assign new value for array %s", pname, 0); return NULL; @@ -1782,7 +1782,27 @@ typeset_single(char *cname, char *pname, Param pm, int func, pm->ct = auxlen; else pm->ct = 0; - } else { + } else if (strchr(pname, '[')) { + if (on & PM_READONLY) { + zerrnam(cname, + "%s: can't create readonly array elements", pname, 0); + return NULL; + } else if (PM_TYPE(on) == PM_SCALAR) { + /* + * This will either complain about bad identifiers, or will set + * a hash element or array slice. This once worked by accident, + * creating a stray parameter along the way via createparam(), + * now called below in the isident() branch. + */ + if (!(pm = setsparam(pname, ztrdup(value ? value : "")))) + return NULL; + value = NULL; + } else { + zerrnam(cname, + "%s: array elements must be scalar", pname, 0); + return NULL; + } + } else if (isident(pname)) { /* * Create a new node for a parameter with the flags in `on' minus the * readonly flag @@ -1790,6 +1810,9 @@ typeset_single(char *cname, char *pname, Param pm, int func, pm = createparam(pname, on & ~PM_READONLY); DPUTS(!pm, "BUG: parameter not created"); pm->ct = auxlen; + } else { + zerr("not an identifier: %s", pname, 0); + return NULL; } if (altpm && PM_TYPE(pm->flags) == PM_SCALAR) { @@ -1808,8 +1831,14 @@ typeset_single(char *cname, char *pname, Param pm, int func, else if (on & PM_LOCAL) pm->level = locallevel; if (value && !(pm->flags & (PM_ARRAY|PM_HASHED))) { + Param ipm = pm; if (!(pm = setsparam(pname, ztrdup(value)))) - return 0; + return NULL; + if (pm != ipm) { + DPUTS(ipm->flags != pm->flags, + "BUG: parameter recreated with wrong flags"); + unsetparam_pm(ipm, 0, 1); + } } else if (newspecial && !(pm->old->flags & PM_NORESTORE)) { /* * We need to use the special setting function to re-initialise diff --git a/Src/lex.c b/Src/lex.c index 46d83cb21..428e77431 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1303,9 +1303,9 @@ dquote_parse(char endchar, int sub) if (c != '\n') { if (c == '$' || c == '\\' || (c == '}' && !intick && bct) || c == endchar || c == '`' || - (math && (c == '[' || c == ']' || - c == '(' || c == ')' || - c == '{' || c == '}'))) + (endchar == ']' && (c == '[' || c == ']' || + c == '(' || c == ')' || + c == '{' || c == '}'))) add(Bnull); else { /* lexstop is implicitly handled here */ @@ -1390,7 +1390,7 @@ dquote_parse(char endchar, int sub) err = (!brct-- && math); break; case '"': - if (intick || (!endchar && !bct)) + if (intick || endchar == ']' || (!endchar && !bct)) break; if (bct) { add(Dnull); diff --git a/Src/params.c b/Src/params.c index aaeebce76..48b514008 100644 --- a/Src/params.c +++ b/Src/params.c @@ -765,10 +765,17 @@ isident(char *s) if (!*s) /* empty string is definitely not valid */ return 0; - /* find the first character in `s' not in the iident type table */ - for (ss = s; *ss; ss++) - if (!iident(*ss)) - break; + if (idigit(*s)) { + /* If the first character is `s' is a digit, then all must be */ + for (ss = ++s; *ss; ss++) + if (!idigit(*ss)) + break; + } else { + /* Find the first character in `s' not in the iident type table */ + for (ss = s; *ss; ss++) + if (!iident(*ss)) + break; + } /* If the next character is not [, then it is * * definitely not a valid identifier. */ @@ -1171,7 +1178,7 @@ getindex(char **pptr, Value v) int start, end, inv = 0; char *s = *pptr, *tbrack; - *s++ = Inbrack; + *s++ = '['; s = parse_subscript(s); /* Error handled after untokenizing */ /* Now we untokenize everthing except INULL() markers so we can check * * for the '*' and '@' special subscripts. The INULL()s are removed * @@ -1191,7 +1198,7 @@ getindex(char **pptr, Value v) return 1; } s = *pptr + 1; - if ((s[0] == '*' || s[0] == '@') && s[1] == Outbrack) { + if ((s[0] == '*' || s[0] == '@') && s + 1 == tbrack) { if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@') v->isarr |= SCANPM_ISVAR_AT; v->start = 0; @@ -1223,12 +1230,11 @@ getindex(char **pptr, Value v) } if (*s == ',') { zerr("invalid subscript", NULL, 0); - while (*s && *s != Outbrack) - s++; - *pptr = s; + *tbrack = ']'; + *pptr = tbrack+1; return 1; } - if (*s == Outbrack) + if (s == tbrack) s++; } else { int com; @@ -1243,7 +1249,7 @@ getindex(char **pptr, Value v) start--; else if (start == 0 && end == 0) end++; - if (*s == Outbrack) { + if (s == tbrack) { s++; if (v->isarr && start == end-1 && !com && (!(v->isarr & SCANPM_MATCHMANY) || @@ -1256,6 +1262,7 @@ getindex(char **pptr, Value v) s = *pptr; } } + *tbrack = ']'; *pptr = s; return 0; } diff --git a/Test/D06subscript.ztst b/Test/D06subscript.ztst index 6438dc040..861202544 100644 --- a/Test/D06subscript.ztst +++ b/Test/D06subscript.ztst @@ -128,3 +128,11 @@ >obrack obrack >] ] >backcbrack + + print -R ${A[${A[(r)\\\\\\\\\]]}]::=zounds} + print -R ${A[${A[(r)\\\\\\\\\]]}]} + print -R $A[\\\\\]] +0:Associative array substitution-assignment with reverse pattern subscript key +>zounds +>zounds +>zounds |