Subject: Re: [bug-diffutils] bug#24116: [platform-testers] new snapshot available: diffutils-3.3.50-0353

From: Jim Meyering <[email-masked]>
Date: Mon, 1 Aug 2016 08:37:44 -0700

On Mon, Aug 1, 2016 at 8:27 AM, Eric Blake <[email-masked]> wrote:
> On 07/31/2016 06:36 PM, Jim Meyering wrote:
>
>> dash's printf builtin handles \e differently -- that's easy to work
>> around: use \033, which *is* portable.
>> More surprising is that this generates no output:
>>
>>   dash -c 'f() { local t=$(printf '\''\t\t'\''); printf "$t"; }; f'
>
> That's because you made the classic mistake of using local AND assigning
> to the variable at the same time.
>
> This works:
>
> dash -c 'f() { local t; t=$(...); printf "$t"; }; f'
>
> The difference? There is a notion of an assignment context:
> http://austingroupbugs.net/view.php?id=351
>
> Bash treats 'local' like 'export' in introducing an assignment context
> (so "" around local t=$() is optional); but 'local' is not specified by
> POSIX, so dash does NOT treat it as an assignment context.  Since local
> is a command name, you MUST use "" in all subsequent words, or else
> defer the actual assignments to standalone statements, to get assignment
> context.
>
>>
>> I.e., piping it into wc -c prints 0.
>> With bash, it prints the expected pair of TAB bytes.
>> I found that I could work around this nonsensical behavior by hoisting
>> the "tab=..." definition up/out of those two functions, or by adding
>> standard-says-never-necessary double quotes like this:
>>
>>   dash -c 'f() { local t="$(printf '\''\t\t'\'')"; printf "$t"; }; f'
>
> Umm, the standard is silent.  local is not defined by the standard.
>
>>
>> However, I prefer not to work around it here (and in every other test
>> script where this comes up), and will insulate all of our test scripts
>> by rejecting any shell with that misbehavior, so plan to adjust
>> init.sh to select another shell when it finds this flaw.
>
> It's not a flaw in dash, but in your expectations.

Thanks for the explanation.

This is a corner of the non-standard that I prefer not to have to
remember and constantly work around. IMHO, bash and zsh get it right,
and dash chose behavior that makes shell scripting with it harder than
necessary.