summaryrefslogtreecommitdiff
path: root/Src/subst.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/subst.c')
-rw-r--r--Src/subst.c120
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);
}