Op 23-09-20 om 15:11 schreef Geoff Clare via austin-group-l at The Open Group:
Playing around with export and readonly in shells that support array
assignments, it's clear that they are treating them as separate tokens
in the grammar in order to accept array assignment syntax:

     $ bash -c 'export a=(1 2 3); echo ${a[0]}'
     1
     $ bash -c 'e=export; $e a=(1 2 3); echo ${a[0]}'
     bash: -c: line 0: syntax error near unexpected token `('
     $  bash -c 'readonly a=(1 2 3); echo ${a[0]}'
     1
     $  bash -c 'r=readonly; $r a=(1 2 3); echo ${a[0]}'
     bash: -c: line 0: syntax error near unexpected token `('

     $ ksh -c 'export a=(1 2 3); echo ${a[0]}'
     1
     $ ksh -c 'e=export; $e a=(1 2 3); echo ${a[0]}'
     ksh: syntax error at line 1: `(' unexpected
     $ ksh -c 'readonly a=(1 2 3); echo ${a[0]}'
     1
     $ ksh -c 'r=readonly; $r a=(1 2 3); echo ${a[0]}'
     ksh: syntax error at line 1: `(' unexpected

In order to make "command export ..." and "command readonly ..."
work the same, all that's necessary is for those shells to treat
command as a separate token too.

The standard allows this special treatment of export and readonly
(and command) because it allows shells to extend the syntax such
that they accept input that would, according to the standard, be a
syntax error.

I would question that the currently published standard allows any regular builtin to override the regular shell grammar with special syntactic properties. What exactly do you base this on?

Aren't regular builtins supposed to be exactly equivalent to external commands, with every regular builtin being mandated to have a corresponding external version? How would you expect an external command to have special grammatical properties in the shell?

This is also not a majority shell behaviour. For instance, bash does not currently do this. I wonder if Chet has any plans of changing that now.

The resolution of this bug is particularly problematic for ksh93. The way the ksh93 parser implements this behaviour for 'command' is by internally parsing something like

        command export foo=bar

as

        foo=bar command export

i.e. a preceding assignment. The parser similarly reorders 'command readonly foo=bar' and 'command typeset foo=bar'. You can check this using set -o xtrace. And yes, this works even if you literally type the second variant, and even then the assignment will persist as exported (which is a clear violation of the standard, but this is how Korn et al have chosen to do it -- and fundamentally reworking the parser is not on the cards).

One side effect of this bizarre parser behaviour is that 'command' is unable to prevent the shell from exiting. Something like 'readonly foo; command export foo=bar' will exit the shell because 'foo=bar' is actually executed as an assignment preceding 'command', so the shell exits before the 'command' builtin is even run.

To fix this for the new POSIX mode of ksh 93u+m, I've disabled this parsing behaviour so that 'command' is treated as a regular builtin if the -o posix option is on, and 'typeset' falls back to parsing the assignment-arguments itself without any special grammatical properties (the code to do this was still present). This then allows 'command' to stop the shell from exiting on trying to modify a readonly variable.

But that does mean that 'command' behaves as a regular builtin with regular shell grammar as I believe the currently published POSIX standard specifies it, i.e., it disables both "special" and "declaration" properties of commands it runs.

The bug description claims that the situation for command is different
from export and readonly (it says "A similar argument could be made
for 'export' and 'readonly' themselves, but at least they are already
special built-in utilities").  This is a red herring.  Whether or not
a utility is a special built-in does not affect the grammar.

Note that I was careful to say "separate tokens", not "reserved words".
They are not being treated as reserved words, because they are subject
to alias expansion whereas reserved words are not.

(Note that both 'export' and 'readonly' are reserved words on zsh 5.1 and later, including in its POSIX mode. The 'disable -r' command can be used to disable the reserved words, reverting zsh to the original builtin commands.)

So I think that the normative text in Issue 8 draft 1 is fine as-is.
It meets the goal of requiring "command export args..." to expand its
arguments the same way as "export args...", and likewise for readonly,
and that remains a worthwhile goal.  All that is needed is to add some
explanatory rationale (to command, export, and readonly).

I question that this goal is worthwhile. I think it makes the shell grammar even more inconsistent than it already is and increases confusion. It also means that the standard now will not provide for any way to ensure regular shell grammar parsing for arbitrary commands, which was previously one of the functions of the 'command' builtin.

And, if my belief that the currently published standard does not allow this 'command' behaviour that the new version is planned to mandate is correct, this also means it's not possible for a shell's 'command' command to be compliant with the current version of the standard and the next version at the same time.

Unfortunately, this bug was marked as resolved just one day after you posted this 'possible solution', leaving little opportunity for me or anyone else to provide further input that might have influenced this bug's resolution. So does that mean this change is set in stone now?


--
||      modernish -- harness the shell
||      https://github.com/modernish/modernish
||
||      KornShell lives!
||      https://github.com/ksh93/ksh

  • Bug 1393 ("comman... Geoff Clare via austin-group-l at The Open Group
    • Re: Bug 1393 (&qu... Martijn Dekker via austin-group-l at The Open Group

Reply via email to