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

Re: Bug with bash emulation regarding ':'



On Feb 15, 12:36pm, Peter Stephenson wrote:
}
} To get this behaviour in zsh we'd have to do the assignment earlier
} than we currently do.  The assignments around line 2705 of subst.c would
} need to buried inside multsub() in such a way that any splitting owing to
} the top-level settings happened later --- which is very difficult since
} we rely on the nested substitution to do the splitting we see in the
} top-level parameter expansion because it parses it so knows how to split
} it.  Whether there are remaining gotchas owing to ordering I don't know.

I've been puzzling over this on and off for the last few days and it just
doesn't seem as though it ought to be that hard.

There are some comments in subst.c like this one:

	 * This is where we extract a value (we know now we have
	 * one) into the local parameters for a scalar (val) or
	 * array (aval) value.  TODO: move val and aval into
	 * a structure with a discriminator.  Hope we can make
	 * more things array values at this point and dearrayify later.
	 * v->isarr tells us whether the stuff from down below looks
	 * like an array.

So at first I was thinking that it might be time to do that, so multsub
could for example return both the split and not-split expansions of the
right-side of the assignment and the caller would then use one for the
assignment and the other for the inline expansion.  But then I traced
the call and discovered that the newlines have already been removed and
rejoined as spaces before multsub even returns; the call that handles
this branch doesn't even pass down the aval parameter.

Hence it appears "we rely on the nested substitution to do the splitting
we see in the top-level parameter expansion" is incorrect, at least in
this instance?

Consequently I tried this:

--- ../zsh-forge/current/Src/subst.c	2012-02-12 13:31:49.000000000 -0800
+++ Src/subst.c	2012-02-19 15:19:49.000000000 -0800
@@ -2693,7 +2693,7 @@
 		*idend = '\0';
 		val = dupstring(s);
 		if (spsep || !arrasg) {
-		    multsub(&val, PREFORK_NOSHWORDSPLIT, NULL, &isarr, NULL);
+		    multsub(&val, PREFORK_SINGLE|PREFORK_NOSHWORDSPLIT, NULL,
&isarr, NULL);
 		} else {
 		    if (spbreak)
 			split_flags = PREFORK_SPLIT|PREFORK_SHWORDSPLIT;

This faithfully reproduces the bash behavior in several tests I tried.
In fact it may be that PREFORK_SINGLE is the only thing needed there,
and PREFORK_NOSHWORDSPLIT is extraneous?  (Aside:  My first thought
was to use PREFORK_ASSIGN, but that's only used in filesub.  A more
thorough approach might be to teach multsub about assignment context.)

Have I missed something important?

(Chet Cc'd just for interest, he can probably be dropped from further
discussion on this topic.)



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