tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Unanticipated /bin/sh change a few weeks ago

It has been brought to my attention (off list) that the change to
the way that the ! command (reserved word) is permitted to be used
in /bin/sh has affected one use case that wasn't anticipated - that is,
the possibility never occurred to me.

That is defining a function as

	func() ! simple_command

no longer works, though we still permit

	func() simple_command

(Both of which are non-standard extensions to the POSIX sh definition.)

The change happened because we actually permit

	func() command

and one of the possibilities for "command" is "simple_command" and
simple_command (used to) permit a leading ! reserved word, and does
not any more.

! is now only permitted in (at the start of) a pipeline, which in normal
use is the only place it makes sense (and is what the standard defines)
and a pipeline is not one of the elements of a command (rather a command is
one of the elements of a pipeline.)

I see four possibilities to deal with this...

1. leave it as it is now,
	func() ! simple_command
   is non-standard usage,
	func() { ! simple_command; }
   works, and is standard (works everywhere).

2. Change the definition of a function definition (in our sh) from

	name "()" command
	name "()" pipeline

   which would automatically permit the "! simple_command" case,
   and would also permit

	func() ls | wc -l

   and similar.  It would make it harder to include a function definition
   in a pipeline however, and that is a standard blessed use case, not that
   it is a useful endeavour (definitions do not read or write anything, so
   defining a function with stdin or stdout redirected from/to some other
   command isn't really useful - and what's more isn't guaranteed to work
   anyway, as pipelines are permitted to be executed in sub-shells, and if
   they were, the function definition, if embedded in a pipeline, would never
   become visible in the shell.)

   If we go this route, we could instead permit and_or (instead of command
   or pipeline) - though I have not thought through the implications of that
   one.   Going all the way and allowing a list would break too much I suspect.

   [ and_or would allow "func() command && other" to be a definition, rather
     than meaning "if the definition succeeds (they always do) run "other",
     Allowing "list" would mean "func() command; command & command" would
     all be a definition - but in that case, I suspect the definition would
     continue growing until EOF, there would be nothing to stop it, where
    "EOF" here includes the end of some embedding syntax element, if any.

3. Change the definition of a function definition (in our sh) to

	name "()" [ "!" ] command

   which would put back the functionality that was removed - and a little
   more, as that would also permit

	func() ! { command; command...; }

   and similar.   This one has least effect (of any change) upon the
   language the shell implements, but would be one more hack...
   If we did this we might actually want to make it
	name "()" [ "!" [ "!" ] ] command

   for consistency with what we allow in pipelines (again, non-standard.)

4. Put back BOGUS_NOT_COMMAND  (allowing ! in bizarre places) or perhaps
   just in the (still bizarre) case in simple_command.

   This one I would really prefer if we not do.

Which of those do people think best?   Does anyone (else) use the

	func() ! command

method of defining a function?


ps: none of this has anything at all to do with using a function after it
is defined.   For that a function is just one case of a simple_command.

Home | Main Index | Thread Index | Old Index