bug-bash
[Top][All Lists]
Advanced

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

Re: Unexpected line number at BASH_LINENO[i]


From: Chet Ramey
Subject: Re: Unexpected line number at BASH_LINENO[i]
Date: Tue, 12 Jul 2022 16:23:36 -0400
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.11.0

On 7/7/22 8:42 AM, Michal Berger wrote:
> BASH_VERSION: 5.1.4(1)-release (shipped with Debian 11)
> 
> Considering script like this:
> 
> 1       #!/usr/bin/env bash
> 2
> 3       set -o errexit
> 4       set -o errtrace
> 5
> 6       bt() {
> 7               local line file file_v
> 8
> 9               for ((idx = 1; idx < ${#FUNCNAME[@]}; idx++)); do
> 10                      read -r line _ file < <(caller $((idx - 1)))
> 11                      file_v=${file//[\/\.]/_}
> 12
> 13                      [[ -f $file ]] || continue
> 14
> 15                      if [[ ! -v $file_v ]]; then
> 16                              mapfile -t "${file_v}_ref" <"$file"
> 17                      fi
> 18                      local -n file_ref=${file_v}_ref
> 19
> 20                      echo "$file -> $line: ${file_ref[line - 1]}"
> 21              done
> 22
> 23      }
> 24
> 25      a() {
> 26              false \
> 27                      foo \
> 28                      bar
> 29      }
> 30
> 31      trap 'bt' ERR
> 32
> 33      a
> 
> With a()'s `false` triggering the ERR trap I would expect output from bt()
> to point at line 26, however, the BASH_LINENO holds, surprisingly to me,
> line 27:
> 
> $ bash  ./t
> ./t -> 27:              foo \
> ./t -> 33: a
> 
> If I don't break the failing line then the BASH_LINENO is set just fine:

This is an artifact of using bison, because we end up building commands
bottom up. The parser knows when it's parsed a complete simple command,
but not really where it was when it started, so it kind of has to guess.
It uses the line number that's current when it has read enough to start
constructing the simple command.

This strategy is usually right, but can be fooled by multi-line commands
like yours.

In this case, by the time we start building the simple command, the
backslash-newline has already been consumed, and the line number
incremented to 27.

So, to sum up, the line number associated with the simple command -- which
ends up being `false foo bar' -- is the line number where the parser was
when it decided what it had was a simple command, which is when it
determined the WORD token it had parsed (`false') wasn't followed by
anything that would make it something other than a simple command (e.g.,
a `()').

-- 
``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]