diff options
Diffstat (limited to 'Src/subst.c')
-rw-r--r-- | Src/subst.c | 120 |
1 files changed, 85 insertions, 35 deletions
diff --git a/Src/subst.c b/Src/subst.c index 1aa9b982e..f52bcdfc8 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -195,7 +195,7 @@ stringsubst(LinkList list, LinkNode node, int pf_flags, int asssub) while (!errflag && (c = *str)) { if ((qt = c == Qstring) || c == String) { - if ((c = str[1]) == Inpar) { + if ((c = str[1]) == Inpar || c == Inparmath) { if (!qt) list->list.flags |= LF_ARRAY; str++; @@ -258,24 +258,34 @@ stringsubst(LinkList list, LinkNode node, int pf_flags, int asssub) skipparens(Inpar, Outpar, &str); #endif str--; - } else { - endchar = c; - *str = '\0'; - - while (*++str != endchar) - DPUTS(!*str, "BUG: parse error in command substitution"); - } - *str++ = '\0'; - if (endchar == Outpar && str2[1] == '(' && str[-2] == ')') { + } else if (c == Inparmath) { /* Math substitution of the form $((...)) */ - str[-2] = '\0'; + str[-1] = '\0'; + while (*str != Outparmath && *str) + str++; + if (*str != Outparmath) { + zerr("failed to find end of math substitution"); + return NULL; + } + str[-1] = '\0'; if (isset(EXECOPT)) - str = arithsubst(str2 + 2, &str3, str); + str = arithsubst(str2 + 2, &str3, str+1); else strncpy(str3, str2, 1); setdata(node, (void *) str3); continue; + } else { + endchar = c; + *str = '\0'; + + while (*++str != endchar) { + if (!*str) { + zerr("failed to find end of command substitution"); + return NULL; + } + } } + *str++ = '\0'; /* It is a command substitution, which will be parsed again * * by the lexer, so we untokenize it first, but we cannot use * @@ -298,7 +308,7 @@ stringsubst(LinkList list, LinkNode node, int pf_flags, int asssub) if (endchar == Outpar) str2--; if (!(s = (char *) ugetnode(pl))) { - str = strcpy(str2, str); + str = (char *)memmove(str2, str, strlen(str)+1); continue; } if (!qt && (pf_flags & PREFORK_SINGLE) && isset(GLOBSUBST)) @@ -1306,7 +1316,7 @@ get_intarg(char **s, int *delmatchp) p = dupstring(*s + arglen); *s = t + arglen; *t = sav; - if (parsestr(p)) + if (parsestr(&p)) return -1; singsub(&p); if (errflag) @@ -1317,7 +1327,7 @@ get_intarg(char **s, int *delmatchp) if (ret < 0) ret = -ret; *delmatchp = arglen; - return ret < 0 ? -ret : ret; + return ret; } /* Parsing for the (e) flag. */ @@ -1329,18 +1339,21 @@ subst_parse_str(char **sp, int single, int err) *sp = s = dupstring(*sp); - if (!(err ? parsestr(s) : parsestrnoerr(s))) { + if (!(err ? parsestr(&s) : parsestrnoerr(&s))) { + *sp = s; if (!single) { int qt = 0; - for (; *s; s++) + for (; *s; s++) { if (!qt) { if (*s == Qstring) *s = String; else if (*s == Qtick) *s = Tick; - } else if (*s == Dnull) + } + if (*s == Dnull) qt = !qt; + } } return 0; } @@ -1385,12 +1398,23 @@ static char * untok_and_escape(char *s, int escapes, int tok_arg) { int klen; - char *dst; + char *dst = NULL; - untokenize(dst = dupstring(s)); - if (escapes) { - dst = getkeystring(dst, &klen, GETKEYS_SEP, NULL); - dst = metafy(dst, klen, META_HREALLOC); + if (escapes && (*s == String || *s == Qstring) && s[1]) { + char *pstart = s+1, *pend; + for (pend = pstart; *pend; pend++) + if (!iident(*pend)) + break; + if (!*pend) { + dst = dupstring(getsparam(pstart)); + } + } + if (dst == NULL) { + untokenize(dst = dupstring(s)); + if (escapes) { + dst = getkeystring(dst, &klen, GETKEYS_SEP, NULL); + dst = metafy(dst, klen, META_HREALLOC); + } } if (tok_arg) shtokenize(dst); @@ -1426,7 +1450,8 @@ check_colon_subscript(char *str, char **endp) } sav = **endp; **endp = '\0'; - if (parsestr(str = dupstring(str))) + str = dupstring(str); + if (parsestr(&str)) return NULL; singsub(&str); remnulargs(str); @@ -2192,12 +2217,28 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) */ idbeg = s; if ((subexp = (inbrace && s[-1] && isstring(*s) && - (s[1] == Inbrace || s[1] == Inpar)))) { + (s[1] == Inbrace || s[1] == Inpar || s[1] == Inparmath)))) { int sav; int quoted = *s == Qstring; + int outtok; val = s++; - skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s); + switch (*s) { + case Inbrace: + outtok = Outbrace; + break; + case Inpar: + outtok = Outpar; + break; + case Inparmath: + outtok = Outparmath; + break; + default: + /* "Can't Happen" (TM) */ + DPUTS(1, "Nested substitution: This Can't Happen (TM)"); + return NULL; + } + skipparens(*s, outtok, &s); sav = *s; *s = 0; /* @@ -2811,7 +2852,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) haserr = parse_subst_string(s); noerrs = one; if (!quoteerr) { - errflag = oef; + /* Retain user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); if (haserr) shtokenize(s); } else if (haserr || errflag) { @@ -3238,8 +3280,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) haserr = 1; } noerrs = one; - if (!quoteerr) - errflag = oef; + if (!quoteerr) { + /* Retain user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); + } if (haserr || errflag) return NULL; } @@ -3472,8 +3516,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) untokenize(*ap); } noerrs = one; - if (!quoteerr) - errflag = oef; + if (!quoteerr) { + /* Retain any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); + } else if (haserr || errflag) { zerr("parse error in parameter value"); return NULL; @@ -3505,8 +3551,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) noerrs = 1; haserr = parse_subst_string(val); noerrs = one; - if (!quoteerr) - errflag = oef; + if (!quoteerr) { + /* Retain any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); + } else if (haserr || errflag) { zerr("parse error in parameter value"); return NULL; @@ -4075,7 +4123,8 @@ modify(char **str, char **ptr) noerrs = 1; parse_subst_string(copy); noerrs = one; - errflag = oef; + /* Retain any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); remnulargs(copy); untokenize(copy); } @@ -4150,7 +4199,8 @@ modify(char **str, char **ptr) noerrs = 1; parse_subst_string(*str); noerrs = one; - errflag = oef; + /* Retain any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); remnulargs(*str); untokenize(*str); } |