[comp.bugs.4bsd] csh problem involving nested ifs?

marty@wuphys.UUCP (Marty Olevitch) (07/10/89)

It appears that csh does not correctly handle nested if-then-else
statements. The following script illustrates the problem, which appears
in versions of csh on MORE/bsd (mt Xinu 4.3), SunOS 3.1, SunOS 4.0, and
Ultrix 2.0. Am I missing some bug in this script? If not, it looks like
a bug in csh (an equivalent sh program works fine).

#! /bin/csh
set v1 = $1
set v2 = $2
echo "v1 = $v1 and v2 = $v2"
if($v1 == 1) then
	echo checkpoint 1
	if($v2 == 1) then
		echo 11
	else 
		echo 12
	endif
	echo checkpoint 2
else 
	echo checkpoint 3
	if($v2 == 1) then
		echo 21
	else 
		echo 22
	endif
	echo checkpoint 4
endif

Here is a little chart showing the command lines issued, the expected
results, and the actual results.

command line	expect			get
------------	------			-------
iftest 1 1	checkpoint 1		checkpoint 1
		11			11
		checkpoint 2		checkpoint 2
					checkpoint 4
					
iftest 1 2	checkpoint 1		checkpoint 1
		12			12
		checkpoint 2		checkpoint 2
					checkpoint 4
						
iftest 2 1	checkpoint 3		12
		21			checkpoint 2
		checkpoint 4		checkpoint 4

iftest 2 2	checkpoint 3		12
		22			checkpoint 2
		checkpoint 4		checkpoint 4

Marty Olevitch				Internet: marty@wuphys.wustl.edu
Washington University			UUCP:     uunet!wugate!wuphys!marty
Physics Department, Campus Box 1105	Bitnet:   marty@wuphys.WUSTL
St Louis MO 63130 USA			Tel:      (314) 889-6285

tale@pawl.rpi.edu (David C Lawrence) (07/11/89)

In <685@wuphys.UUCP> marty@wuphys.UUCP (Marty Olevitch) writes:
Marty> It appears that csh does not correctly handle nested if-then-else
Marty> statements. The following script illustrates the problem, which appears
Marty> in versions of csh on MORE/bsd (mt Xinu 4.3), SunOS 3.1, SunOS 4.0, and
Marty> Ultrix 2.0. Am I missing some bug in this script? If not, it looks like
Marty> a bug in csh (an equivalent sh program works fine).

Yes it's a bug, no it's not a bug.  It's one of those ambivalent
things.  If you know what it is, you adjust your style by one
character or so and life goes on correctly again.

Major hacking on the script follows ...
Marty> #! /bin/csh
[...]
Marty> if($v1 == 1) then
Marty> 	echo checkpoint 1
Marty> 	if($v2 == 1) then
[...]
Marty> 	if($v2 == 1) then
[...]

If you change the "if(" to "if (" in each of the nested conditionals
you should find that your problem has vanished.  The problem is that
whitespace becomes significant within the first if block, at least as
far as further nested if blocks are concerned.  The parser used within
the if block is not the same one which parsed out the top if.

Dave
--
 (setq mail '("tale@pawl.rpi.edu" "tale@itsgw.rpi.edu" "tale@rpitsmts.bitnet"))
        "Drinking coffee for instant relaxation?  That's like drinking
               alcohol for instant motor skills."  -- Marc Price

chris@mimsy.UUCP (Chris Torek) (07/11/89)

In article <685@wuphys.UUCP> marty@wuphys.UUCP (Marty Olevitch) writes:
>It appears that csh does not correctly handle nested if-then-else
>statements.

This is false.  It does handle them, but it is finicky.

>Am I missing some bug in this script?

[all but the `if' lines deleted]

>if($v1 == 1) then
>	if($v2 == 1) then
>	if($v2 == 1) then

You must put a space after the `if', before the `('; and you must have
a space between the `)' and the `then' (which must be the last word on
the line, after stripping comments).

The reason is that the C shell's `skip to end of false construct' code
uses a completely different line parser than usual.  The `execute this line'
parser breaks lines at whitespace and at the characters ( ) & | and
perhaps a few others.  (&& and || are collected as a unit before causing
word breaks.)  The `skip to end of false if' routine winds up doing

	if (strcmp("if(", "if") == 0 && strcmp("then", "then") == 0)

in the particular cases given above.  Had you written

	if ($v2 == 1)then

it would have tried

	if (strcmp("if", "if") == 0 && strcmp(")then", "then") == 0)

and also failed.  Only

	if ($v2 == 1) then

and similar constructs pass its test.  (One such construct is

	if (this, {which is not &syntactically! correct, goes undetected then
		the c shell sucks
	endif

which counts as an `if-then' during false-if skipping, but causes an
error otherwise.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

envbvs@epb2.lbl.gov (Brian V. Smith) (07/11/89)

In article <685@wuphys.UUCP>, marty@wuphys.UUCP (Marty Olevitch) writes:
< 
< It appears that csh does not correctly handle nested if-then-else
< statements. The following script illustrates the problem, which appears
< in versions of csh on MORE/bsd (mt Xinu 4.3), SunOS 3.1, SunOS 4.0, and
< Ultrix 2.0. Am I missing some bug in this script? If not, it looks like
< a bug in csh (an equivalent sh program works fine).
< 

[ csh script follows ]

Well, on our Vaxstation II running Ultrix 2.0 machine and out
Vaxstation 2000's and II's running Ultrix 3.0, the script worked
just as it should (the "expected" results).

_____________________________________
Brian V. Smith    (bvsmith@lbl.gov)
Lawrence Berkeley Laboratory
We don't need no signatures!

envbvs@epb2.lbl.gov (Brian V. Smith) (07/11/89)

In article <TALE.89Jul10131139@imagine.pawl.rpi.edu>, tale@pawl.rpi.edu (David C Lawrence) writes:
< Yes it's a bug, no it's not a bug.  It's one of those ambivalent
< things.  If you know what it is, you adjust your style by one
< character or so and life goes on correctly again.
< 
< Major hacking on the script follows ...
< Marty> #! /bin/csh
< [...]
< Marty> if($v1 == 1) then
< Marty> 	echo checkpoint 1
< Marty> 	if($v2 == 1) then
< [...]
< Marty> 	if($v2 == 1) then
< [...]
< 
< If you change the "if(" to "if (" in each of the nested conditionals
< you should find that your problem has vanished.  The problem is that
< whitespace becomes significant within the first if block, at least as
< far as further nested if blocks are concerned.  The parser used within
< the if block is not the same one which parsed out the top if.

I *didn't* include the spaces as David recommends, and I still didn't see
the problem under Ultrix 2.0 OR Ultrix 3.0. The script (and, hence csh)
works fine.

I used "cut/paste" with X to copy the script, so I know I didn't make any typos.
_____________________________________

Brian V. Smith    (bvsmith@lbl.gov)
Lawrence Berkeley Laboratory
We don't need no signatures!

peter@ficc.uu.net (Peter da Silva) (07/11/89)

Basically, it is undesirable to use the 'C' shell for any complicated
scripts... or any scripts at all other than .cshrc and .login.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Business: peter@ficc.uu.net, +1 713 274 5180. | Th-th-th-that's all folks...
Personal: peter@sugar.hackercorp.com.   `-_-' |  -- Mel Blanc
Quote: Have you hugged your wolf today?  'U`  |     May 30 1908 - Jul 10 1989

grr@cbmvax.UUCP (George Robbins) (07/13/89)

In article <4948@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
> Basically, it is undesirable to use the 'C' shell for any complicated
> scripts... or any scripts at all other than .cshrc and .login.

This is a fairly widely held viewpoint, but when you get down to it,
neither the bourne shell, nor c-shell provide very elegant programming
languages.  C-shell does allow "prettier code", but the inconsistancies
will nip you from time to time.  Bourne shell scripts do have the
major advantage of being transportable back into the USG world, which
may or may not matter for the task at hand.

I here there's now a alt.computers.religion topic for just this sort of rwar...

-- 
George Robbins - now working for,	uucp: {uunet|pyramid|rutgers}!cbmvax!grr
but no way officially representing	arpa: cbmvax!grr@uunet.uu.net
Commodore, Engineering Department	fone: 215-431-9255 (only by moonlite)

hjg@amms4.UUCP (Harry Gross) (07/14/89)

In article <7293@cbmvax.UUCP> grr@cbmvax.UUCP (George Robbins) writes:

>I here there's now a alt.computers.religion topic for just this sort of rwar...
		      ^^^^^^^^^^^^^^^^^^^^^^

Read that as alt.religion.computers - it was created about a week or so ago, and
I already have 141 articles posted to it.

-- 
		Harry Gross				 |  reserved for
							 |  something really
Internet: hjg@amms4.UUCP   (we're working on registering)|  clever - any
UUCP: {jyacc, rna, bklyncis}!amms4!hjg			 |  suggestions?

tchrist@convex.UUCP| (Tom Christiansen) (07/15/89)

In article <7293@cbmvax.UUCP| grr@cbmvax.UUCP (George Robbins) writes:
|In article <4948@ficc.uu.net| peter@ficc.uu.net (Peter da Silva) writes:
|| Basically, it is undesirable to use the 'C' shell for any complicated
|| scripts... or any scripts at all other than .cshrc and .login.

sigh.  i used to disbelieve this.  i've learned the hard way.  it's
more true that not true.

|This is a fairly widely held viewpoint, but when you get down to it,
|neither the bourne shell, nor c-shell provide very elegant programming
|languages.  C-shell does allow "prettier code", but the inconsistancies [sic]
|will nip you from time to time.  Bourne shell scripts do have the
|major advantage of being transportable back into the USG world, which
|may or may not matter for the task at hand.

This is also so.   That's why where I used to write shell scripts with
reams of embedded awk and sed calls, I now use perl, another wonderful
piece of Larry Wall-ware.  It's a real programming language, optimized
for sysadmin tasks.  If you haven't looked at it, consider doing so.  
And it runs on a googol of architectures, thanks to a lot of work 
towards this goal and his metaconfig program.  Try it, you'll like it.


--tom