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

Re: Bug with bash emulation regarding ':'



On Jan 29,  6:36pm, Peter Stephenson wrote:
}
} > _test ()
} > {
} > 	array="one two three"
} > 	for e in $array
} > 	do
} > 		echo "'$e'"
} > 	done
} > }
} > 
} > l=
} > : ${l:=$(_test)}
} > echo "_${l}_"
} >...
} > _'one two three'_
} 
} presumably something is going on with quoting and/or tokenisation in or
} close to multsub(), which is some of the hairier code in substitution,
} when SH_WORD_SPLIT is in effect.

Given that this sorta kinda worked back in 4.2.x ... I think the problem
is explained by this comment (dates to 4.3.0-dev-4, which means this bug
has gone unnoticed for almost exactly five years):

2619   case '-':
2620       if (vunset) {
2621           int ws = opts[SHWORDSPLIT];
2622           val = dupstring(s);
2623           /* If word-splitting is enabled, we ask multsub() to split
2624            * the substituted string at unquoted whitespace.  Then, we
2625            * turn off spbreak so that no further splitting occurs.
2626            * This allows a construct such as ${1+"$@"} to correctly
2627            * keep its array splits, and weird constructs such as
2628            * ${str+"one two" "3 2 1" foo "$str"} to only be split
2629            * at the unquoted spaces. */
2630           opts[SHWORDSPLIT] = spbreak;
2631           multsub(&val, spbreak && !aspar, (aspar ? NULL : &aval), &isarr, NULL);
2632           opts[SHWORDSPLIT] = ws;
2633           copied = 1;
2634           spbreak = 0;

The breakage in this specific example is at 2658 where SHWORDSPIT has been
forced off, but there's probably another example where the above breaks too:

2648   case Equals:
2649       if (vunset) {
2650           int ws = opts[SHWORDSPLIT];
2651           char sav = *idend;
2652           int l;
2653 
2654           *idend = '\0';
2655           val = dupstring(s);
2656           if (spsep || !arrasg) {
2657               opts[SHWORDSPLIT] = 0;
2658               multsub(&val, 0, NULL, &isarr, NULL);
2659           } else {
2660               opts[SHWORDSPLIT] = spbreak;
2661               multsub(&val, spbreak, &aval, &isarr, NULL);
2662               spbreak = 0;
2663           }
2664           opts[SHWORDSPLIT] = ws;

The problem is that we want to suppress any further splitting in the
current shell, but when we enter the subshell for $(...) it should
revert to the original setting.  I'm not sure how to pass that down
the call stack appropriately.



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