Re: [1003.1(2013)/Issue7+TC1 0000953]: Alias expansion is under-specified

2019-01-27 Thread Harald van Dijk

On 27/01/2019 21:17, Stephane Chazelas wrote:

2019-01-27 02:29:04 +, Harald van Dijk:
[...]

This proposed resolution does not leave empty aliases (aliases not resulting
in any token) unspecified. I mentioned them before, because they are
mishandled by at least one shell:

   $ dash -c 'alias empty=
   empty'
   dash: 2: Syntax error: end of file unexpected

I'd be perfectly okay with considering that a bug in dash (I personally
consider it exactly that, and it's easy to fix), but I do not know whether
there are different situations in other shells that also fail for other
reasons and require major changes to their implementations of aliases to
solve.

[...]

But then again

alias empty=
{ empty; }

or

(empty)

Also fails in many shells (and don't fail in some shells where
{ ;} or () otherwise fails).

The problem is not that much about empty aliases here but about
when alias expansion results in no command where that's not
expected.


I cannot find any shell in which { empty; } and { ; } behave 
differently. ksh and zsh accept this, with or without the empty alias. 
Everything else I tried (bash, bosh, dash, mksh, pdksh, yash) rejects 
it, again with or without the empty alias.


I cannot find any shell in which (empty) and ( ) behave differently. 
mksh, pdksh and zsh accept this, everything else I tried rejects this, 
with or without the alias.


I can find one where () and ( ) behave differently, zsh, which also 
makes it one where () and (empty) behave differently. That is because () 
is read as a single token, but either the space or the empty alias 
forces it to be read as two separate single-character tokens.



Empty aliases are useful and often used in things like:

if [ "$DEBUG" ]; then
   alias ifdebug=
else
   alias ifdebug='#'
fi

ifdebug log "$(cmd)"


If it were implemented with a function instead, cmd would still
be run. aliases avoids that but you need to remember to keep
your debug commands on a single line.


You could avoid empty aliases here to let it work in dash and support 
multi-line commands at the same time:


  if [ "$DEBUG" ]; then
alias ifdebug=': && '
  else
alias ifdebug=': || '
  fi


And dash has no issue with that code.


It does have an issue with exactly what you wrote: try putting ifdebug 
before the very last line in a script, in the non-DEBUG case where the 
command is commented out.


Cheers,
Harald van Dijk



Re: [1003.1(2013)/Issue7+TC1 0000953]: Alias expansion is under-specified

2019-01-27 Thread Stephane Chazelas
2019-01-27 02:29:04 +, Harald van Dijk:
[...]
> This proposed resolution does not leave empty aliases (aliases not resulting
> in any token) unspecified. I mentioned them before, because they are
> mishandled by at least one shell:
> 
>   $ dash -c 'alias empty=
>   empty'
>   dash: 2: Syntax error: end of file unexpected
> 
> I'd be perfectly okay with considering that a bug in dash (I personally
> consider it exactly that, and it's easy to fix), but I do not know whether
> there are different situations in other shells that also fail for other
> reasons and require major changes to their implementations of aliases to
> solve.
[...]

But then again

alias empty=
{ empty; }

or

(empty)

Also fails in many shells (and don't fail in some shells where
{ ;} or () otherwise fails).

The problem is not that much about empty aliases here but about
when alias expansion results in no command where that's not
expected.

Empty aliases are useful and often used in things like:

if [ "$DEBUG" ]; then
  alias ifdebug=
else
  alias ifdebug='#'
fi

ifdebug log "$(cmd)"


If it were implemented with a function instead, cmd would still
be run. aliases avoids that but you need to remember to keep
your debug commands on a single line.

And dash has no issue with that code. I'd say it's unlikely for
the dash issue (which I'd agree to call a bug) to be hit in
practice though you could imagine convoluted things like:

if [ "$DEBUG" ]; then
  alias ifdebug= endifdebug=
else
  alias ifdebug='if false; then' endifdebug=fi
fi

ifdebug
  cmd
endifdebug

-- 
Stephane