[Top][All Lists]

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

Re: caller returns wrong line number in command substitution

From: Chet Ramey
Subject: Re: caller returns wrong line number in command substitution
Date: Mon, 24 Oct 2022 15:55:30 -0400
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.3.3

On 10/18/22 1:47 PM, Andrew Neff via Bug reports for the GNU Bourne Again SHell wrote:

   Using the "caller" command on a line of bash code in a process substitution 
has been incorrect from bash 3.2 through 5.1, but I could write my code in such a way to 
work around it. Some of these workarounds no longer function in bash 5.2. I saw that you 
made some changes to this code [see below], however, I think they introduced another 
regression to how caller calculates the line offset. In the following tests, caller 
should always return the last line in a multi-line bash call, but that is not the case 
now in a process substitution in bash 5.2 (test 5)

Getting line numbers correct for multi-line simple commands has always been
tricky, given the bottom-up way you have to build commands with bison. You
don't really know you're parsing a simple command until you've parsed it,
so you know where you are when you're finished, but not really where you

For most single-line cases, it doesn't matter, but multi-line cases use the
line number when the parser finishes parsing the simple command.

So let's take a look at what happens for this script:

     1  function foobar()
     2  {
     3          caller >&2
     4  }
     5  true <(
     6    foobar "test2
     7  ...
     8      bar")

Running this script prints `10'. Why?

Well, it's a combination of things. First, the line number associated with
the `true' command is 8, since that's the line number when bison resolves
the `simple_command' production and we go off and create it.

Now, before that happens, we have to run the process substitution through
the parser so we can find the ending right paren. We use the same code used
to parse command substitutions, since they have the same requirements.
Rather than keep the original text around, which is difficult to do with
how the parser and lexer are structured, bash reconstitutes the text of the
process  substitution from the command it parses. This is syntactically
equivalent, but has the effect of throwing away leading and trailing
sequences of newlines, since those don't contribute to the command. (Your
suspicion about the new command substitution parsing code having an effect
here is correct.)

So when we go to perform word expansion on the process substitution, the
internal line number is 8, since that's the line number of the simple
command, and the command that's run by the shell forked to execute the
process substitution starts with `foobar' (not `\nfoobar').

The shell forks a child, and that child parses the string, starting at
line 8. The command consists of three lines: lines 8, 9, and 10. Since
the current line number is 10 when we finish parsing the simple command
and resolve the production, that's the line number associated with that
command. When the function is called, and `caller' does its thing, the
line number associated with the currently-executing command that called
the function is 10, and that's what it prints.

You should be able to puzzle out what happens for the other cases based
on this description.

``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet@case.edu    http://tiswww.cwru.edu/~chet/

reply via email to

[Prev in Thread] Current Thread [Next in Thread]