From 2d03aa87fbdd371209aa63869d42686338d6a96b Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 16 Dec 2007 14:05:14 +0000 Subject: 24264: restrict effect of 24234 to parameter substitution code and document --- Src/params.c | 232 ++++++++++++++++++++++++++++++----------------------------- Src/subst.c | 5 +- Src/zsh.h | 3 +- 3 files changed, 123 insertions(+), 117 deletions(-) (limited to 'Src') diff --git a/Src/params.c b/Src/params.c index 9ebb98dcf..0b372bf25 100644 --- a/Src/params.c +++ b/Src/params.c @@ -1889,129 +1889,131 @@ getstrvalue(Value v) break; } - if (v->pm->node.flags & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z)) { - int fwidth = v->pm->width ? v->pm->width : MB_METASTRLEN(s); - switch (v->pm->node.flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) { - char *t, *tend; - unsigned int t0; - - case PM_LEFT: - case PM_LEFT | PM_RIGHT_Z: - t = s; - if (v->pm->node.flags & PM_RIGHT_Z) - while (*t == '0') - t++; - else - while (iblank(*t)) - t++; - MB_METACHARINIT(); - for (tend = t, t0 = 0; t0 < fwidth && *tend; t0++) - tend += MB_METACHARLEN(tend); - /* - * t0 is the number of characters from t used, - * hence (fwidth - t0) is the number of padding - * characters. fwidth is a misnomer: we use - * character counts, not character widths. - * - * (tend - t) is the number of bytes we need - * to get fwidth characters or the entire string; - * the characters may be multiple bytes. - */ - fwidth -= t0; /* padding chars remaining */ - t0 = tend - t; /* bytes to copy from string */ - s = (char *) hcalloc(t0 + fwidth + 1); - memcpy(s, t, t0); - if (fwidth) - memset(s + t0, ' ', fwidth); - s[t0 + fwidth] = '\0'; - break; - case PM_RIGHT_B: - case PM_RIGHT_Z: - case PM_RIGHT_Z | PM_RIGHT_B: - { - int zero = 1; - /* Calculate length in possibly multibyte chars */ - unsigned int charlen = MB_METASTRLEN(s); - - if (charlen < fwidth) { - char *valprefend = s; - int preflen; - if (v->pm->node.flags & PM_RIGHT_Z) { - /* - * This is a documented feature: when deciding - * whether to pad with zeroes, ignore - * leading blanks already in the value; - * only look for numbers after that. - * Not sure how useful this really is. - * It's certainly confusing to code around. - */ - for (t = s; iblank(*t); t++) - ; - /* - * Allow padding after initial minus - * for numeric variables. - */ - if ((v->pm->node.flags & - (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) && - *t == '-') - t++; + if (v->flags & VALFLAG_SUBST) { + if (v->pm->node.flags & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z)) { + int fwidth = v->pm->width ? v->pm->width : MB_METASTRLEN(s); + switch (v->pm->node.flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) { + char *t, *tend; + unsigned int t0; + + case PM_LEFT: + case PM_LEFT | PM_RIGHT_Z: + t = s; + if (v->pm->node.flags & PM_RIGHT_Z) + while (*t == '0') + t++; + else + while (iblank(*t)) + t++; + MB_METACHARINIT(); + for (tend = t, t0 = 0; t0 < fwidth && *tend; t0++) + tend += MB_METACHARLEN(tend); + /* + * t0 is the number of characters from t used, + * hence (fwidth - t0) is the number of padding + * characters. fwidth is a misnomer: we use + * character counts, not character widths. + * + * (tend - t) is the number of bytes we need + * to get fwidth characters or the entire string; + * the characters may be multiple bytes. + */ + fwidth -= t0; /* padding chars remaining */ + t0 = tend - t; /* bytes to copy from string */ + s = (char *) hcalloc(t0 + fwidth + 1); + memcpy(s, t, t0); + if (fwidth) + memset(s + t0, ' ', fwidth); + s[t0 + fwidth] = '\0'; + break; + case PM_RIGHT_B: + case PM_RIGHT_Z: + case PM_RIGHT_Z | PM_RIGHT_B: + { + int zero = 1; + /* Calculate length in possibly multibyte chars */ + unsigned int charlen = MB_METASTRLEN(s); + + if (charlen < fwidth) { + char *valprefend = s; + int preflen; + if (v->pm->node.flags & PM_RIGHT_Z) { + /* + * This is a documented feature: when deciding + * whether to pad with zeroes, ignore + * leading blanks already in the value; + * only look for numbers after that. + * Not sure how useful this really is. + * It's certainly confusing to code around. + */ + for (t = s; iblank(*t); t++) + ; + /* + * Allow padding after initial minus + * for numeric variables. + */ + if ((v->pm->node.flags & + (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) && + *t == '-') + t++; + /* + * Allow padding after initial 0x or + * base# for integer variables. + */ + if (v->pm->node.flags & PM_INTEGER) { + if (isset(CBASES) && + t[0] == '0' && t[1] == 'x') + t += 2; + else if ((valprefend = strchr(t, '#'))) + t = valprefend + 1; + } + valprefend = t; + if (!*t) + zero = 0; + else if (v->pm->node.flags & + (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) { + /* zero always OK */ + } else if (!idigit(*t)) + zero = 0; + } + /* number of characters needed for padding */ + fwidth -= charlen; + /* bytes from original string */ + t0 = strlen(s); + t = (char *) hcalloc(fwidth + t0 + 1); + /* prefix guaranteed to be single byte chars */ + preflen = valprefend - s; + memset(t + preflen, + (((v->pm->node.flags & PM_RIGHT_B) + || !zero) ? ' ' : '0'), fwidth); /* - * Allow padding after initial 0x or - * base# for integer variables. + * Copy - or 0x or base# before any padding + * zeroes. */ - if (v->pm->node.flags & PM_INTEGER) { - if (isset(CBASES) && - t[0] == '0' && t[1] == 'x') - t += 2; - else if ((valprefend = strchr(t, '#'))) - t = valprefend + 1; - } - valprefend = t; - if (!*t) - zero = 0; - else if (v->pm->node.flags & - (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) { - /* zero always OK */ - } else if (!idigit(*t)) - zero = 0; + if (preflen) + memcpy(t, s, preflen); + memcpy(t + preflen + fwidth, + valprefend, t0 - preflen); + t[fwidth + t0] = '\0'; + s = t; + } else { + /* Need to skip (charlen - fwidth) chars */ + for (t0 = charlen - fwidth; t0; t0--) + s += MB_METACHARLEN(s); } - /* number of characters needed for padding */ - fwidth -= charlen; - /* bytes from original string */ - t0 = strlen(s); - t = (char *) hcalloc(fwidth + t0 + 1); - /* prefix guaranteed to be single byte chars */ - preflen = valprefend - s; - memset(t + preflen, - (((v->pm->node.flags & PM_RIGHT_B) - || !zero) ? ' ' : '0'), fwidth); - /* - * Copy - or 0x or base# before any padding - * zeroes. - */ - if (preflen) - memcpy(t, s, preflen); - memcpy(t + preflen + fwidth, - valprefend, t0 - preflen); - t[fwidth + t0] = '\0'; - s = t; - } else { - /* Need to skip (charlen - fwidth) chars */ - for (t0 = charlen - fwidth; t0; t0--) - s += MB_METACHARLEN(s); } + break; } + } + switch (v->pm->node.flags & (PM_LOWER | PM_UPPER)) { + case PM_LOWER: + s = casemodify(s, CASMOD_LOWER); + break; + case PM_UPPER: + s = casemodify(s, CASMOD_UPPER); break; } } - switch (v->pm->node.flags & (PM_LOWER | PM_UPPER)) { - case PM_LOWER: - s = casemodify(s, CASMOD_LOWER); - break; - case PM_UPPER: - s = casemodify(s, CASMOD_UPPER); - break; - } if (v->start == 0 && v->end == -1) return s; diff --git a/Src/subst.c b/Src/subst.c index e8257163b..22b4cfe08 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2059,8 +2059,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) * There really is a value. Padding and case * transformations used to be handled here, but * are now handled in getstrvalue() for greater - * consistency. + * consistency. However, we get unexpected effects + * if we allow them to applied on every call, so + * set the flag that allows them to be substituted. */ + v->flags |= VALFLAG_SUBST; val = getstrvalue(v); } } diff --git a/Src/zsh.h b/Src/zsh.h index 5354e9663..fb4d51ecd 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -599,7 +599,8 @@ struct value { enum { VALFLAG_INV = 0x0001, /* We are performing inverse subscripting */ - VALFLAG_EMPTY = 0x0002 /* Subscripted range is empty */ + VALFLAG_EMPTY = 0x0002, /* Subscripted range is empty */ + VALFLAG_SUBST = 0x0004 /* Substitution, so apply padding, case flags */ }; #define MAX_ARRLEN 262144 -- cgit 1.4.1