bug-bash
[Top][All Lists]
Advanced

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

Re: Incorrect LINENO with exported nested functions with loops


From: Tom Coleman
Subject: Re: Incorrect LINENO with exported nested functions with loops
Date: Thu, 7 Oct 2021 09:33:09 +1100

I was actually incorrect about something in here. Initially I discovered
the bug when this was in two scripts. I've discovered that it is actually
much simpler and nothing to do with exporting functions. Updated script is
below.

>From examination I've done to date, using BASH 5.1.8, each function is
setting up their loop COMMAND variables in order from top to bottom. The
inner for loops are done first and works outwards. For the "bad_lineno"
function, it does the arithmetic for loop first. This somehow breaks the
setting of the line number of the outer, generic for loop. I'm not familiar
with looking at things like parse.y, so I am not sure I can debug this
further and provide a fix.

#!/bin/bash
export PS4='+PS4 + L$LINENO + '
f1() {
  for d in 1 2 3; do
    break
  done
}
good_lineno() {
  for i in 1; do
    for j in 3; do
      :
    done
  done
}
bad_lineno() {
  for k in 1; do
    for ((l=3; l<=3; l++)); do
      :
    done
  done
}
set -x
echo "for i in 1 line number should be 9 and is"
good_lineno
echo "for k in 1 line number should be 16 but is not"
bad_lineno

On Thu, Oct 7, 2021 at 7:43 AM L A Walsh <bash@tlinx.org> wrote:

>
>
> On 2021/10/05 16:25, Tom Coleman wrote
> > Repeat-By:
> >         Below is a sample script to replicate the bug in LINENO.
> >
> ---
> 1st prob: scrip doesn't work as is.
> >  /tmp/lnno
> /tmp/lnno: line 23: syntax error near unexpected token `done'
> /tmp/lnno: line 23: ` done'
> ----
> added the line numbers indenting and uncommenting the 2nd for loop to
> prevent the above syntax error:
>
> 01 #!/bin/bash
> 02 # vim=:SetNumberAndWidth
> 03 setx() { trap unsetx EXIT; set -x; } ; unsetx() { set +x;}
> 04 export
> PS4='>${BASH_SOURCE:+${BASH_SOURCE/$HOME/\~}}#${LINENO}${FUNCNAME:+(${FUNCNAME})}>
>
> '
> 05 setup() {
> 06   DO_BACKUP() {
> 07     for d in 1 2 3; do
> 08       break
> 09     done
> 10   }
> 11   export -f DO_BACKUP
> 12 }
> 13 run() {
> 14  for i in 1; do
> 15    #for j in 1; do  # Uncomment this 'j' loop instead of the next and
> LINENO is correct
> 16    for ((j=1; j<=2; j++)); do  # Uncomment this 'j' loop and LINENO
> is incorrect
> 17        true
> 18    done
> 19  done
> 20 }
> 21 setx
> 22 setup
> 23 run
> 24
> 25 # vim  ts=2 sw=2
>
> >         The LINENO variable for the 'i' loop which is printed out by the
> > PS4 is incorrect when that DO_BACKUP function is exported, and the second
> > 'j' loop is uncommented.
> -----like this, right?:
> >  /tmp/lnno
> >/tmp/lnno#22> setup
> >/tmp/lnno#11(setup)> export -f DO_BACKUP
> >/tmp/lnno#23> run
> >/tmp/lnno#25(run)> for i in 1
> >/tmp/lnno#16(run)> (( j=1 ))
> >/tmp/lnno#16(run)> (( j<=2 ))
> >/tmp/lnno#17(run)> true
> >/tmp/lnno#16(run)> (( j++ ))
> >/tmp/lnno#16(run)> (( j<=2 ))
> >/tmp/lnno#17(run)> true
> >/tmp/lnno#16(run)> (( j++ ))
> >/tmp/lnno#16(run)> (( j<=2 ))
> >/tmp/lnno#1> unsetx
> >/tmp/lnno#3(unsetx)> set +x
>
>
>
> >  If you instead uncomment the first 'j' loop, the
> > LINENO variables are correct. If DO_BACKUP does not have a loop inside
> it, the LINENO variables are all correct.
> >
> ----
>     So you are saying that using the 1st j loop instead of the 2nd,
> then whether or not "DO_BACKUP" has a loop inside, LINENO is correct?
> So that is what one would expect, right?.
>
>     So the main problem above is the line after
> ">/tmp/lnno#23 run", where the "for i in 1" is listed as being on
> ">/tmp/lnno#25"  #(line 25)?
>
> And if DO_BACKUP is not exported, then all the line numbers are
> correct, like:
> >  /tmp/lnno
> >/tmp/lnno#23> setup
> >/tmp/lnno#24> run
> >/tmp/lnno#14(run)> for i in 1
> >/tmp/lnno#15(run)> for j in 1
> >/tmp/lnno#16(run)> DO_BACKUP
> >/tmp/lnno#7(DO_BACKUP)> for d in 1 2 3
> >/tmp/lnno#8(DO_BACKUP)> break
> >/tmp/lnno#18(run)> true
> >/tmp/lnno#1> unsetx
> >/tmp/lnno#3(unsetx)> set +x
>
>
> Yeah, that's interesting, have you tried the latest version
> of bash to see if it does the same thing?  I still need to compile it.
>
> If you export functions, they can do weird things with
> numbering.
>
> Like at your bash prompt, try:
>
>
> imafunc() { echo $LINENO; }; export -f imafunc
> echo $LINENO; imafunc; echo $LINENO
>
>
>
>
>
>
> > #!/bin/bash
> > export PS4='+L$LINENO + '
> > setup() {
> > DO_BACKUP() {
> >   for d in 1 2 3; do
> >     break
> >   done
> > }
> > export -f DO_BACKUP
> > }
> > run() {
> >     for i in 1; do
> >         #for j in 1; do  # Uncomment this 'j' loop instead of the next
> and
> > LINENO is correct
> >         #for ((j=1; j<=2; j++)); do  # Uncomment this 'j' loop and LINENO
> > is incorrect
> >             true
> >         done
> >     done
> > }
> > set -x
> > setup
> > run
> >
> > ########
> >
> > Example output with first 'j' loop uncommented:
> >
> > $ bash run.sh
> > +L20 + setup
> > +L9 + export -f DO_BACKUP
> > +L21 + run
> > +L12 + for i in 1
> > +L13 + for j in 1
> > +L15 + true
> >
> > Example output with the second 'j' loop uncommented:
> >
> > $ bash run.sh
> > +L20 + setup
> > +L9 + export -f DO_BACKUP
> > +L21 + run
> > +L5 + for i in 1
> > +L14 + (( j=1 ))
> > +L14 + (( j<=1 ))
> > +L15 + true
> > +L14 + (( j++ ))
> > +L14 + (( j<=1 ))
> >
> >
> > Regards,
> > Tom Coleman
> >
>


reply via email to

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