[gnu.bash.bug] Strange behavior with functions

trost@reed.bitnet (Bill Trost) (12/20/89)

The noise on alt.sources.wanted about file reversal made me come up
with this little program:

#!/local/bin/bash
# Yes, all through this I should be using "$@", but that's for version
# 1.05 (I have 1.04)

rv () {
	[ $# = 0 ] && {
		# Call this block A
		local line=empty\?\?\?
		read line || return
		echo Read: "$line" 2>&1
		rv
		echo "$line"
		# end A
		return
	}
	# Call this block B
	local f=$1
	shift
	[ $# = 0 ] || rv $*
	rv < $f
}

rv $*


Now, if I run this with no arguments (using /etc/motd as stdin), it
works on the Decstation and longjmp botches after echoing "empty" on
the Vax.  If I run it with one argument, it does a longjmp botch after
echoing "empty" on either machine.

Then, if I swap blocks A and B and change the "&&" to a "||", with no
arguments it works on the DECstation, but it prints "empty" for the
first line and never prints the first line of the file (which should
be printed last).

Of course, Chet has probably already fixed it....  :-)

bfox@sbphy.ai.mit.edu (Brian Fox) (12/21/89)

   Date: 19 Dec 89 23:46:35 GMT
   From: tektronix!reed!trost@cis.ohio-state.edu  (Bill Trost)
   Sender: bug-bash-request@prep.ai.mit.edu

   The noise on alt.sources.wanted about file reversal made me come up
   with this little program:

   #!/local/bin/bash
   # Yes, all through this I should be using "$@", but that's for version
   # 1.05 (I have 1.04)

   rv () {
	   [ $# = 0 ] && {
		   # Call this block A
		   local line=empty\?\?\?
		   read line || return
		   echo Read: "$line" 2>&1
		   rv
		   echo "$line"
		   # end A
		   return
	   }
	   # Call this block B
	   local f=$1
	   shift
	   [ $# = 0 ] || rv $*
	   rv < $f
   }

   rv $*


   Now, if I run this with no arguments (using /etc/motd as stdin), it
   works on the Decstation and longjmp botches after echoing "empty" on
   the Vax.  If I run it with one argument, it does a longjmp botch after
   echoing "empty" on either machine.

   Then, if I swap blocks A and B and change the "&&" to a "||", with no
   arguments it works on the DECstation, but it prints "empty" for the
   first line and never prints the first line of the file (which should
   be printed last).

   Of course, Chet has probably already fixed it....  :-)

Probably!  But on the off chance that he hasn't, could you send me a
typescript of the session?

Thanks,

	Brian

trost%REED.BITNET@MITVMA.MIT.EDU (12/21/89)

Heh, this should cover it.  This was run on the DECstation --- which
now seems to be running differently than when I first posted about this.

bash$ cat /etc/motd
Ultrix Worksystem V2.0 (Rev. 7) System #1: Tue Aug 29 22:41:48 EDT 1989
I would encourage everyone to not rlogin to this machine from the DECstations
to do things, but instead do stuff from the machine you're on.  If that is
impossible for some reason, fix it, or send mail to trost repeatedly (but not
too often) until he does.
bash$ ./rv /etc/motd
Read: Ultrix Worksystem V2.0 (Rev. 7) System #1: Tue Aug 29 22:41:48 EDT 1989
Read: I would encourage everyone to not rlogin to this machine from the DECstati
Read: to do things, but instead do stuff from the machine you're on. If that is
Read: impossible for some reason, fix it, or send mail to trost repeatedly (but
Read: too often) until he does.
empty???
longjmp botch

bash$ ./rv < /etc/motd
Read: Ultrix Worksystem V2.0 (Rev. 7) System #1: Tue Aug 29 22:41:48 EDT 1989
Read: I would encourage everyone to not rlogin to this machine from the DECstati
Read: to do things, but instead do stuff from the machine you're on. If that is
Read: impossible for some reason, fix it, or send mail to trost repeatedly (but
Read: too often) until he does.
empty???
longjmp botch

bash$ ./gurk < /etc/motd
Read Ultrix Worksystem V2.0 (Rev. 7) System #1: Tue Aug 29 22:41:48 EDT 1989
Read I would encourage everyone to not rlogin to this machine from the DECstatio
Read to do things, but instead do stuff from the machine you're on. If that is
Read impossible for some reason, fix it, or send mail to trost repeatedly (but n
Read too often) until he does.
empty???
too often) until he does.
impossible for some reason, fix it, or send mail to trost repeatedly (but not
to do things, but instead do stuff from the machine you're on. If that is
I would encourage everyone to not rlogin to this machine from the DECstations
bash$ ./gurk /etc/motd
Read Ultrix Worksystem V2.0 (Rev. 7) System #1: Tue Aug 29 22:41:48 EDT 1989
Read I would encourage everyone to not rlogin to this machine from the DECstatio
Read to do things, but instead do stuff from the machine you're on. If that is
Read impossible for some reason, fix it, or send mail to trost repeatedly (but n
Read too often) until he does.
empty???
too often) until he does.
impossible for some reason, fix it, or send mail to trost repeatedly (but not
to do things, but instead do stuff from the machine you're on. If that is
I would encourage everyone to not rlogin to this machine from the DECstations
longjmp botch

bash$ cat rv
   rv () {
           [ $# = 0 ] && {
                   # Call this block A
                   local line=empty\?\?\?
                   read line || return
                   echo Read: "$line" 2>&1
                   rv
                   echo "$line"
                   # end A
                   return
           }
           # Call this block B
           local f=$1
           shift
           [ $# = 0 ] || rv $*
           rv < $f
   }

   rv $*
bash$ cat gurk
#!/local/bin/bash

rv () {
        [ $# = 0 ] || {
                local f=$1
                shift
                [ $# = 0 ] || rv $*
                rv < $f
                return 0
        }
        local line=empty\?\?\?
        read line || return
        echo Read "$line" 2>&1
        rv
        echo "$line"
}

rv $*
bash$ set
_=/etc/motd
OLDPWD=/bassoon/u/ss/trost
EUID=236
UID=236
HISTSIZE=500
HISTFILE=/u/ss/trost/.bash_history
BASH_VERSION=0.00.4
PWD=/tmp
MAILCHECK=60
IFS=

PS2=bash>
PS1=bash\$
VISUAL=/bin/ed
USER=trost
TTY=ttyp3
TEXINPUTS=.:/u/ss/trost/lib/tex:/usr/lib/tex/macros
TEXEDIT=/bin/ed
TERM=emacs
SHLVL=2
SHELL=/local/bin/bash
RNINIT=-i1 -T -hReferences -hMessage-Id -hlines -e -d/u/ss/trost/.news
PRINTER=katy
PATH=/u/ss/trost/.bin/vishnu:/u/ss/trost/.bin:/local/bin:/local/bin/xclients:/us
PAGER=less
MAIL=/u/ss/trost/.mail/inbox:/u/ss/trost/.mail/root:/u/ss/trost/.mail/twatch:/et
LESS=sMqtwp
JOVERC=/u/ss/trost/.joverc
HUNT=name=default,mapkey=;G
HOST=vishnu
HOME=/u/ss/trost
EDITOR=/bin/ed
DISPLAY=bassoon:0
COLS=22
BASH=/local/bin/bash
TERMCAP=emacs:co#80:tc=unknown:
EMACS=t
bash$

trost@reed.bitnet (Bill Trost) (12/21/89)

	#!/local/bin/bash
	# Yes, all through this I should be using "$@", but that's for version
	# 1.05 (I have 1.04)

	rv () {
	[ $# = 0 ] && {
		# Call this block A
		local line=empty\?\?\?
		read line || return
		echo Read: "$line" 2>&1
		rv
		echo "$line"
		# end A
		return
		}	
...

By the way, someone should probably add this to the Official
Collection of Shell Scripts Which Severely Bash on Bash.

Gads, I haven't even *tried* to reverse /etc/termcap --- yet.

chet@cwns1.CWRU.EDU (Chet Ramey) (12/21/89)

In article <13771@reed.UUCP> trost@reed.bitnet (Bill Trost) writes:

[another neat script, this one for reversing files]

>Of course, Chet has probably already fixed it....  :-)

Yup, and I sent the fix to Brian again today (just for good measure :-). 
If anyone's interested, it has to do with using a single global jump_buf to
implement `return' with longjmp.  This obviously screws recursive functions
or functions that call other functions; the first function to call `return'
gets the right jump_buf and leaves all the others in the twilight zone (I've
seen `main' get re-executed on my IBM RT running 4.3 for a really 
pathological case).

Chet Ramey

-- 
Chet Ramey
Network Services Group				"Where's my froggie?"
Case Western Reserve University
chet@ins.CWRU.Edu			

chet@cwns1.CWRU.EDU (Chet Ramey) (12/21/89)

In article <8912201910.AA16864@.reed.bitnet> trost%REED.BITNET@MITVMA.MIT.EDU writes:

>bash$ cat rv
>   rv () {
>           [ $# = 0 ] && {
>                   # Call this block A
>                   local line=empty\?\?\?

I seem to have not fixed this completely, or maybe I'm just confused.  I
did fix the longjmp botch problem, but I don't think this line is doing
what everyone thinks it should be doing.  The `local' part works simply
because rv is a function, and you can declare local variables in a function.
The `{' doesn't really begin a new block with a separate context; on the
contrary, it guarantees that the block will be executed in the *current*
shell, with the *current* context.

Anyway, I don't think it should work as written.  This isn't C.  (If everyone
else thinks otherwise, I'm pretty sure I have a fix for it.  But I'm just not
convinced that it ever should have worked.)

Chet Ramey
-- 
Chet Ramey
Network Services Group				"Where's my froggie?"
Case Western Reserve University
chet@ins.CWRU.Edu			

chet@cwns1.CWRU.EDU (Chet Ramey) (12/21/89)

In article <1989Dec21.013833.6811@usenet.ins.cwru.edu> I wrote:

	[Stupidity.  Mind-boggling stupidity.  Cursed be NNTP
	 and fast article propogation.  Gawd, it's embarassing]

I have fixed the bug, and I will send the fix to Brian.  Here's what I get
now:

usenet$ type rv
rv is a function
rv ()
{
[ $# = 0 ]&& {
local line=empty\?\?\?;
read line|| return;
echo Read: "$line" 2>&1 ;
rv;
echo "$line";
return;
};
local f=$1;
shift;
[ $# = 0 ]|| rv $*;
rv <$f ;
}
usenet$ rv ~/foo
Read: 1
Read: 2
Read: 3
Read: 4
Read: 5
5
4
3
2
1


It required changing a single line of code.  Funny how this one hasn't hit
before; *all* instances of functions executing `return' have always had
this bug.

Chet Ramey

-- 
Chet Ramey
Network Services Group				"Where's my froggie?"
Case Western Reserve University
chet@ins.CWRU.Edu