tech-userlevel archive

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

Re: ${LINENO} implementation change for /bin/sh

In this message ...

    Date:        Sun, 07 May 2017 23:34:40 +0700
    Message-ID:  <>

I asked ...

  | The are two questions I still would appreciate answers to:
  | 1) from the quote above:
  | 	(numbered starting with 1) within a script or function


  | That's the obvious place where we add an option [...]
  | For now the option is called "funclinereset" (I always accept
  | suggestions for better names!)

I have one off list opinion that the option is a reasonable approach,
and one off-list suggestion "something derived from
 ``function relative line numbers'' " for the name...

But no concrete suggestions.

  | Now to the question...  what should the default for this be?

And (in one of the above) a suggestion that keeping the default the
way /bin/sh has done it in the past is best.   But that was partly
based upon the theory that POSIX supports this interpretation, and
while I still have no answers from people who really should know,
I am beginning to believe that it is not the correct interpretation.

That is:

LINENO  Set by the shell to a decimal number representing the current
        sequential line number (numbered starting with 1) within a script
        or function before it executes each command.

is followed by (after a sentence saying that if the user fiddles with
LINENO we can do whatever we like thereafter...)

       If the shell is not currently executing a script or function,
       the value of LINENO is unspecified.

which kind of suggests, that in the author's mind at least, there are
three scenarios for use of LINENO, when it is in a script, when it is
in a function that is not in a script. and when it is elsewhere, and
it may very well be that the "within a script or function" is intended
to mean "within a script, or a function that is not in a script".
It could even be that it means the call of the function is not in a
script (so a function called from the command line, interacively, would
have LINENO set to 1 for it, but the same func called from a script would

It is all kind of confusing and underspecified....   but I am certainly
not as sure now about what POSIX is trying to say than I was earlier,
so at least until we get a clarification - which might be a long time,
if (or more likely when) I submit a bug report, it will, if current
progress is any guide, take at least a year before it gets considered,
and at least the beginnings of an answer appear (though we may get
unauthoritative opinions sooner) and if there is no obvious answer
at that time, it could take months more for an actual solution.

I have however, upon the assumption that we have been wrong about what
POSIX wants here (and only if that is true) a couple of different ideas
for how we can eat our cake and have it too...

First, because POSIX (very clearly) says that assignment to LINENO means
anything goes, we could allow

	func() {

		echo ${LINENO} == 3

to produce "3 == 3".   And then when the function has exited, LINENO
goes back to the way it was before.   That's entirely within the
spirit of what POSIX is saying (assuming they do not already mean that
LINENO starts at 1 in every function.)

Unfortuately that one would be a real bitch to implement...   And it would
certainly not even have a chance of being workable unless we ditch the
current LINENO hack completely (which we may do anyway, eventually.)

But another, similar possibility, could be much easier...

	func() {
		local LINENO

		echo ${LINENO} == 4

"local" is not a POSIX command, so can do just about anything, including

Also note that in the first example, setting LINENO (which could be to
any value not just 1) would cause LINENO to be that value for that line,
then increment, whereas the local variant would make uses of LINENO in
the function be numbered from 1 within the function, and there line 1
is the line containing the '{', so the echo here is on line 4.

Only references to LINENO after it is declared local would be affected
though (unlike C, "local" (etc) is an executable statement, not a syntax
declaration, so can be placed anywhere any other command can go.)

This one I think (though I have not tried it) is implementable, though
with more work than the option version, but to me appears a little cleaner
and removes both of the questions above - no new option means no need
to invent a name for it, and no need to consider its default value.
It would mean that the bash, ksh93, /bin/ksh, ... interpretation of how
LINENO works in functions embedded in scripts would be adopted by
default though.

So, what does everyone think about that way?

One more relevant point, I think, in our shell, really, the shell is
*always* executing a script, there is no real distinction between reading
a file from stdin (sh < file) and doing it as "sh file", nor does it
matter if we are reading stdin and that is a keyboard (or equiv, some
kind of tty device).   (There are obvious differences when reading a
device that allows interactive editing, but they don't affect the parser
or above.)

So, unlike what (might have been) in the author of the relevant text's
mind, for us, we are always "reading a script", wherever the input
happens to be coming from (and once I get around to adding parameter
expansion, etc, to PS1 (et al)) we will be able to do

	PS1='[${LINENO}] $ '

and it will (or should) work just fine - whereas for POSIX this is
definitely an unspecified use, and anything (any value anyway) could
be output.  Parameter expansion of the PSn prompts is relatively
simple to add - just has not moved up the todo list high enough (not a
real big challenge to do, so ...)  but it will come, not too far away
I hope.

The second question was ...

  | 2) - this is a technical question rather than philosophical,
	[ initialising a union ]
  | So, can someone give me an example of how to do this?

I did my own research and that is fixed now...


Home | Main Index | Thread Index | Old Index