[comp.unix.questions] weird if-then-else behavior in "csh"

mckenney@acf2.NYU.EDU (Alan Michael McKenney) (06/13/89)

Subject: Wierd "csh" behavior with nested if-then-else

[ Note: please reply to mckenney@acf8.nyu.edu -- I am posting from a ]
[                                ^^^^                                ]
[ different machine because of software problems on acf8.            ]


    The following behaves as expected, if executed by "csh" using
the "source" command:
------------------------------------------------------------------------
if ( 1 == 2 ) then
	echo "first if clause (begin) (shouldn't print)"
	if ( 3 == 2 ) then
		echo "second if clause (shouldn't print)"
	else
		echo "else of second if clause (shouldn't print)"
	endif
	echo "first if clause (end) (shouldn't print)"
else
	echo "else of first if clause (should print)"
	if ( 1 == 1 ) then
		echo  "third if clause (should print)"
	endif
endif
------------------------------------------------------------------------

    The following doesn't:
------------------------------------------------------------------------
if ( 1 == 2 ) then
	echo "first if clause (begin) (shouldn't print)"
	if( 3 == 2 ) then
		echo "second if clause (shouldn't print)"
	else
		echo "else of second if clause (shouldn't print)"
	endif
	echo "first if clause (end) (shouldn't print)"
else
	echo "else of first if clause (should print)"
	if ( 1 == 1 ) then
		echo  "third if clause (should print)"
	endif
endif
------------------------------------------------------------------------
the lines marked "should print" aren't, while the 3rd and 4th that say
"shouldn't print" are printed.  The only difference between the two is
that the second "if" in the second file is immediately followed by
"(", rather than " (".  (In general, the "if" command seems to require
spaces in many non-intuitive places.)

    I have observed this behavior on a VAX running 4.3BSD, a Sun-4
running SunOS-3.2 (I think), and a Sun-3 running "Sun UNIX 4.2 Release
3.5".

    Is this a bug, a feature, or what?

    And further, is there any good guide as to where spaces are required
in "if" statements in "csh" (other than just putting them everywhere
that they are legal)?


Alan McKenney        E-mail:  mckenney@acf8.nyu.edu          (INTERNET)
Courant Institute,NYU         ...!cmcl2!acf8!mckenney        (UUCP)
-- 
Alan McKenney        E-mail:  mckenney@acf8.nyu.edu          (INTERNET)
Courant Institute,NYU         ...!uunet!cmcl2!acf8!mckenney  (UUCP)

chris@mimsy.UUCP (Chris Torek) (06/14/89)

In article <540@acf2.NYU.EDU> mckenney@acf2.NYU.EDU (Alan Michael McKenney) writes:
>... The only difference between the [csh if/then/else example that works
>and the one that does not] is that the second "if" in the second file is
>immediately followed by "(", rather than " (".  (In general, the "if"
>command seems to require spaces in many non-intuitive places.)

In general, the C shell's `parser' does not.  (Parse, that is.)

>    Is this a bug, a feature, or what?

How could it be anything but a bug?  It is not documented. :-)

>    And further, is there any good guide as to where spaces are required
>in "if" statements in "csh" (other than just putting them everywhere
>that they are legal)?

The trick is that, when skipping a false `if', the C shell uses a
completely different routine than when it is reading commands for
the purpose of actually executing them.  The latter routine breaks
things at spaces, parentheses, and other `special' characters, while
the former breaks only at spaces.  The false-if-skipping-code looks
for a line which, after being broken at spaces, starts with `if'
and ends with `then', with code like the following:

	count = 1;
	do {
		read line;
		break at spaces;
		if (strcmp(word[0], "endif") == 0)
			count--;
		else if (strcmp(word[0], "if") == 0 &&
		    strcmp(word[nwords-1], "then") == 0)
			count++;
	} while (count);

So:

	if (0) then		# enter above pseudo-code
		if then		# count now reaches 2
		if obviously&*csh[ would (never? like this` then # now 3
		endif this is bad	# now 2
		endif		# now 1
	endif			# count reaches 0
	echo this gets echoed.	# and we revert to the normal parser

But if you take out the first `if (0) then' you get an error (`if:
Expression syntax'); if you take out the first and second you get a
different error (`Unmatched `.').  If you put arguments after `endif'
inside a true `if' you get still another error.

The false-if-skipping-code recognises only `first word is "if",
last word is "then"', and breaks only at whitespace, so if you always
put a space after an `if' and one before a `then', you should never
have trouble.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris