Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Singleton arrays treated as scalars (redux)



I think I've figured out why paramsubst() converts one-element arrays into
scalars.  Consider the case where zsh needs to expand

	some${param}thing

When param is a scalar, it simply concatenates "some" and "thing" with the
value, and then performs globsubst if necessary.

When param is an array of two or more elements, it concatenates "some" with
the first element and globsubsts, does globsubst on any internal elements,
and finally concatenates the last element with "thing" and does one last
globsubst on that.

The one-element array case can't be handled like the two-or-more case; it
must be handled like the scalar case.  So zsh does the simplest thing, and
turns the array into a scalar so that it will take that code branch.  This
also prevents it from attempting plan9 (rcexpandparam) concatenation when
there is only one element.

I think mult_isarr is being assigned from isarr early enough that this is
no longer an issue in 3.1.5, and as far as I can tell it's never been an
issue in 3.0.5 (that is, new 3.1.5-pws-* code is what brought all this up;
if someone has a counter-example please tell me).

However, there's one spot where I think mult_isarr is not correctly set,
and another spot where isarr is compared to 2 even though in that branch
it can't possibly have any value other than 0.  Patch appended, someone
please check it for sanity.

Index: Src/subst.c
@@ -1484,6 +1484,10 @@
 	val = dupstring("");
 	isarr = 0;
     } else if (isarr && aval && aval[0] && !aval[1]) {
+	/* treat a one-element array as a scalar for purposes of   *
+	 * concatenation with surrounding text (some${param}thing) *
+	 * and rc_expand_param handling.  Note: mult_isarr (above) *
+	 * propagates the true array type from nested expansions.  */
 	val = aval[0];
 	isarr = 0;
     }
@@ -1500,8 +1504,8 @@
 		val = aval[0];
 	    else
 		isarr = 2;
-	    mult_isarr = isarr;
 	}
+	mult_isarr = isarr;
     }
     if (casmod) {
 	if (isarr) {
@@ -1665,7 +1669,7 @@
 	    return NULL;
 	xlen = strlen(x);
 	*str = strcatsub(&y, ostr, aptr, x, xlen, fstr, globsubst);
-	if (qt && !*y && isarr != 2)
+	if (qt && !*y)
 	    y = dupstring(nulstring);
 	setdata(n, (void *) y);
     }

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com



Messages sorted by: Reverse Date, Date, Thread, Author