summary refs log tree commit diff
path: root/Src/subst.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/subst.c')
-rw-r--r--Src/subst.c62
1 files changed, 56 insertions, 6 deletions
diff --git a/Src/subst.c b/Src/subst.c
index da3db5844..defb53bd9 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1649,7 +1649,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		 * necessary joining of arrays until this point
 		 * to avoid the multsub() horror.
 		 */
-		int tmplen = arrlen(v->pm->gets.afn(v->pm));
+		int tmplen = arrlen(v->pm->gsu.a->getfn(v->pm));
 
 		if (v->start < 0)
 		    v->start += tmplen + v->inv;
@@ -1667,7 +1667,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		 * Bet that's easier said than done.
 		 */
 		val = getstrvalue(v);
-		fwidth = v->pm->ct ? v->pm->ct : (int)strlen(val);
+		fwidth = v->pm->width ? v->pm->width : (int)strlen(val);
 		switch (v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) {
 		    char *t;
 		    unsigned int t0;
@@ -1695,17 +1695,67 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 			int zero = 1;
 
 			if (strlen(val) < fwidth) {
+			    char *valprefend = val;
 			    if (v->pm->flags & PM_RIGHT_Z) {
-				for (t = val; iblank(*t); t++);
-				if (!*t || !idigit(*t))
+				/*
+				 * 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 = val; iblank(*t); t++)
+				    ;
+				/*
+				 * Allow padding after initial minus
+				 * for numeric variables.
+				 */
+				if ((v->pm->flags &
+				     (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) &&
+				    *t == '-')
+				    t++;
+				/*
+				 * Allow padding after initial 0x or
+				 * base# for integer variables.
+				 */
+				if (v->pm->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->flags &
+					 (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) {
+				    /* zero always OK */
+				} else if (!idigit(*t))
 				    zero = 0;
 			    }
 			    t = (char *) hcalloc(fwidth + 1);
 			    memset(t, (((v->pm->flags & PM_RIGHT_B) || !zero) ?
 				       ' ' : '0'), fwidth);
+			    /*
+			     * How can the following trigger?  We
+			     * haven't altered val or fwidth since
+			     * the last time we tested this.
+			     */
 			    if ((t0 = strlen(val)) > fwidth)
 				t0 = fwidth;
-			    strcpy(t + (fwidth - t0), val);
+			    /*
+			     * Copy - or 0x or base# before any padding
+			     * zeroes.
+			     */
+			    if (zero && val != valprefend) {
+				int preflen = valprefend - val;
+				memcpy(t, val, preflen);
+				strcpy(t + (fwidth - t0) + preflen,
+				       valprefend);
+			    } else
+				strcpy(t + (fwidth - t0), val);
 			    val = t;
 			} else {
 			    t = (char *) hcalloc(fwidth + 1);
@@ -2019,7 +2069,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		    if (arrasg > 1) {
 			Param pm = sethparam(idbeg, a);
 			if (pm)
-			    aval = paramvalarr(pm->gets.hfn(pm), hkeys|hvals);
+			    aval = paramvalarr(pm->gsu.h->getfn(pm), hkeys|hvals);
 		    } else
 			setaparam(idbeg, a);
 		} else {