diff options
Diffstat (limited to 'Src')
-rw-r--r-- | Src/builtin.c | 17 | ||||
-rw-r--r-- | Src/hist.c | 2 | ||||
-rw-r--r-- | Src/lex.c | 39 | ||||
-rw-r--r-- | Src/math.c | 1 | ||||
-rw-r--r-- | Src/params.c | 89 |
5 files changed, 97 insertions, 51 deletions
diff --git a/Src/builtin.c b/Src/builtin.c index 627a3b82c..0f02ae0a9 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -1690,8 +1690,8 @@ typeset_single(char *cname, char *pname, Param pm, int func, delenv(pm->env); pm->env = NULL; } - if (value) - setsparam(pname, ztrdup(value)); + if (value && !(pm = setsparam(pname, ztrdup(value)))) + return 0; } else if (value) { zwarnnam(cname, "can't assign new value for array %s", pname, 0); return NULL; @@ -1807,9 +1807,10 @@ typeset_single(char *cname, char *pname, Param pm, int func, pm->level = keeplocal; else if (on & PM_LOCAL) pm->level = locallevel; - if (value && !(pm->flags & (PM_ARRAY|PM_HASHED))) - setsparam(pname, ztrdup(value)); - else if (newspecial && !(pm->old->flags & PM_NORESTORE)) { + if (value && !(pm->flags & (PM_ARRAY|PM_HASHED))) { + if (!(pm = setsparam(pname, ztrdup(value)))) + return 0; + } else if (newspecial && !(pm->old->flags & PM_NORESTORE)) { /* * We need to use the special setting function to re-initialise * the special parameter to empty. @@ -2061,12 +2062,6 @@ bin_typeset(char *name, char **argv, char *ops, int func) /* Take arguments literally. Don't glob */ while ((asg = getasg(*argv++))) { - /* check if argument is a valid identifier */ - if (!isident(asg->name)) { - zerr("not an identifier: %s", asg->name, 0); - returnval = 1; - continue; - } if (!typeset_single(name, asg->name, (Param) (paramtab == realparamtab ? gethashnode2(paramtab, asg->name) : diff --git a/Src/hist.c b/Src/hist.c index a80a21967..58fe748be 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -1011,7 +1011,6 @@ hend(Eprog prog) DPUTS(stophist != 2 && !(inbufflags & INP_ALIAS) && !chline, "BUG: chline is NULL in hend()"); queue_signals(); - hf = getsparam("HISTFILE"); if (histdone & HISTFLAG_SETTY) settyinfo(&shttyinfo); if (!(histactive & HA_NOINC)) @@ -1028,6 +1027,7 @@ hend(Eprog prog) && (hist_ignore_all_dups = isset(HISTIGNOREALLDUPS)) != 0) histremovedups(); /* For history sharing, lock history file once for both read and write */ + hf = getsparam("HISTFILE"); if (isset(SHAREHISTORY) && lockhistfile(hf, 0)) { readhistfile(hf, 0, HFILE_USE_OPTIONS | HFILE_FAST); curline.histnum = curhist+1; diff --git a/Src/lex.c b/Src/lex.c index de58ade7a..46d83cb21 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1302,10 +1302,13 @@ dquote_parse(char endchar, int sub) c = hgetc(); if (c != '\n') { if (c == '$' || c == '\\' || (c == '}' && !intick && bct) || - c == endchar || c == '`') + c == endchar || c == '`' || + (math && (c == '[' || c == ']' || + c == '(' || c == ')' || + c == '{' || c == '}'))) add(Bnull); else { - /* lexstop is implicitely handled here */ + /* lexstop is implicitly handled here */ add('\\'); goto cont; } @@ -1458,6 +1461,38 @@ parsestrnoerr(char *s) return err; } +/**/ +mod_export char * +parse_subscript(char *s) +{ + int l = strlen(s), err; + char *t; + + if (!*s || *s == ']') + return 0; + lexsave(); + untokenize(t = dupstring(s)); + inpush(t, 0, NULL); + strinbeg(0); + len = 0; + bptr = tokstr = s; + bsiz = l + 1; + err = dquote_parse(']', 1); + if (err) { + err = *bptr; + *bptr = 0; + untokenize(s); + *bptr = err; + s = 0; + } else + s = bptr; + strinend(); + inpop(); + DPUTS(cmdsp, "BUG: parse_subscript: cmdstack not empty."); + lexrestore(); + return s; +} + /* Tokenize a string given in s. Parsing is done as if s were a normal * * command-line argument but it may contain separators. This is used * * to parse the right-hand side of ${...%...} substitutions. */ diff --git a/Src/math.c b/Src/math.c index bad958243..0ea16e7ba 100644 --- a/Src/math.c +++ b/Src/math.c @@ -517,6 +517,7 @@ setvar(char *s, mnumber v) } if (noeval) return v; + untokenize(s); setnparam(s, v); return v; } diff --git a/Src/params.c b/Src/params.c index 90dd5f3c7..aaeebce76 100644 --- a/Src/params.c +++ b/Src/params.c @@ -770,38 +770,18 @@ isident(char *s) if (!iident(*ss)) break; -#if 0 - /* If this exhaust `s' or the next two characters * - * are [(, then it is a valid identifier. */ - if (!*ss || (*ss == '[' && ss[1] == '(')) - return 1; - - /* Else if the next character is not [, then it is * - * definitely not a valid identifier. */ - if (*ss != '[') - return 0; - - noeval = 1; - (void)mathevalarg(++ss, &ss); - if (*ss == ',') - (void)mathevalarg(++ss, &ss); - noeval = ne; /* restore the value of noeval */ - if (*ss != ']' || ss[1]) - return 0; - return 1; -#else /* If the next character is not [, then it is * - * definitely not a valid identifier. */ + * definitely not a valid identifier. */ if (!*ss) return 1; if (*ss != '[') return 0; - /* Require balanced [ ] pairs */ - if (skipparens('[', ']', &ss)) + /* Require balanced [ ] pairs with something between */ + if (!(ss = parse_subscript(++ss))) return 0; - return !*ss; -#endif + untokenize(s); + return !ss[1]; } /**/ @@ -933,8 +913,21 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) } for (t = s, i = 0; - (c = *t) && ((c != ']' && c != Outbrack && + (c = *t) && ((c != Outbrack && (ishash || c != ',')) || i); t++) { + /* Untokenize INULL() except before brackets, for parsestr() */ + if (INULL(c)) { + if (t[1] == '[' || t[1] == ']') { + /* This test handles nested subscripts in hash keys */ + if (ishash && i) + *t = ztokens[c - Pound]; + needtok = 1; + ++t; + } else + *t = ztokens[c - Pound]; + continue; + } + /* Inbrack and Outbrack are probably never found here ... */ if (c == '[' || c == Inbrack) i++; else if (c == ']' || c == Outbrack) @@ -946,11 +939,18 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) return 0; s = dupstrpfx(s, t - s); *str = tt = t; + /* If we're NOT reverse subscripting, strip the INULL()s so brackets * + * are not backslashed after parsestr(). Otherwise leave them alone * + * so that the brackets will be escaped when we patcompile() or when * + * subscript arithmetic is performed (for nested subscripts). */ + if (ishash && !rev) + remnulargs(s); if (needtok) { if (parsestr(s)) return 0; singsub(&s); - } + } else if (rev) + remnulargs(s); /* This is probably always a no-op, but ... */ if (!rev) { if (ishash) { HashTable ht = v->pm->gets.hfn(v->pm); @@ -1019,7 +1019,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) s = d; } } else { - if (!l || s[l - 1] != '*') { + if (!l || s[l - 1] != '*' || (l > 1 && s[l - 2] == '\\')) { d = (char *) hcalloc(l + 2); strcpy(d, s); strcat(d, "*"); @@ -1028,6 +1028,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) } } tokenize(s); + remnulargs(s); if (keymatch || (pprog = patcompile(s, 0, NULL))) { int len; @@ -1156,7 +1157,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) return r; } } - return 0; + return down ? 0 : len + 1; } } } @@ -1170,13 +1171,27 @@ getindex(char **pptr, Value v) int start, end, inv = 0; char *s = *pptr, *tbrack; - *s++ = '['; - for (tbrack = s; *tbrack && *tbrack != ']' && *tbrack != Outbrack; tbrack++) + *s++ = Inbrack; + 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 * + * in getarg() after we know whether we're doing reverse indexing. */ + for (tbrack = *pptr + 1; *tbrack && tbrack != s; tbrack++) { + if (INULL(*tbrack) && !*++tbrack) + break; if (itok(*tbrack)) *tbrack = ztokens[*tbrack - Pound]; - if (*tbrack == Outbrack) - *tbrack = ']'; - if ((s[0] == '*' || s[0] == '@') && s[1] == ']') { + } + /* If we reached the end of the string (s == NULL) we have an error */ + if (*tbrack) + *tbrack = Outbrack; + else { + zerr("invalid subscript", NULL, 0); + *pptr = tbrack; + return 1; + } + s = *pptr + 1; + if ((s[0] == '*' || s[0] == '@') && s[1] == Outbrack) { if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@') v->isarr |= SCANPM_ISVAR_AT; v->start = 0; @@ -1208,12 +1223,12 @@ getindex(char **pptr, Value v) } if (*s == ',') { zerr("invalid subscript", NULL, 0); - while (*s != ']' && *s != Outbrack) + while (*s && *s != Outbrack) s++; *pptr = s; return 1; } - if (*s == ']' || *s == Outbrack) + if (*s == Outbrack) s++; } else { int com; @@ -1228,7 +1243,7 @@ getindex(char **pptr, Value v) start--; else if (start == 0 && end == 0) end++; - if (*s == ']' || *s == Outbrack) { + if (*s == Outbrack) { s++; if (v->isarr && start == end-1 && !com && (!(v->isarr & SCANPM_MATCHMANY) || |