(Reposting)Arithmetic bug in csh. An explanation and a question.

Michael Greim greim at sbsvax.UUCP
Mon Apr 18 21:28:49 AEST 1988


{ This is a reposting. Mailer ihnp4%moss%research.att.com%uunet at unido.uucp
bounced my original posting, so I don't know whether this got out or not.  }

Hello netland,

Just recently Paul Heckbert raised an interesting question concerning
the way the csh is evaluating expressions. (See also comp.bugs.4bsd)

The Berkely manuals doesn't mention anything concerning right associativity,
but by the simple examples

>The command	@ x = 0 - 1 + 2		sets x to -3	(should be 1)
>
>The command	@ x = 0 - 1 - 2		sets x to 1	(should be -3)

you can see, that expressions are evaluated from right to left.

The SUN manuals state, as Wayne Mesard, Michael Thompson and I posted:

>From csh(1):
>Expressions and Operators
>[...]
>     *   /   %
>          multiplication, division, remainder  (These  are  right
>          associative,  which  can  lead  to  unexpected results.
>          Group combinations explicitly with parentheses.)
>     +   -
>          addition, subtraction (also right associative)

I just took the time to look into the source.
The syntax of expression is :

exp0  : exp1  { "||" exp0 }
exp1  : exp2  { "&&" exp1 }
exp2  : exp2a { "|" exp2 }
exp2a : exp2b { "^" exp2a }
exp2b : exp2c { "&" exp2b }
exp2c : exp3  { EQOP exp3 }
exp3  : exp3a { RELOP exp3 }
exp3a : exp4  { SHIFT exp3a }
exp4  : exp5  { ADDOP exp4 }
exp5  : exp6  { MULOP exp5 }
exp6  : "!" exp6
      | "~" exp6
      | "(" exp0 ")"
      | "{" ... "}"
      | -[erwxfdzo] name

EQOP  : "==" | "!=" | "=~" | "!~"
RELOP : "<=" | ">=" | "<" | ">" 
SHIFT : "<<" | ">>"
ADDOP : "+" | "-"
MULOP : "*" | "/" | "%"

Here '{ .. }' means that '...' is optional, '[...]' means: one of the
letters of '...', the rest of the notation should be too obvious to
need elaboration.
The expressions are parsed top-down, the routines have the same names
as the right hand sides of the above productions, except for EQOP,
RELOP, ... which are recognized separately.
The typical way of evaluation is :
	call first_routine
	if there is an operator {
		remember that operator
		call second_routine
		perform operation on results of first and second routines
	}
This causes right-to-left evaluation for all operators except
the EQOP's.
Another example :
if ( -1 > -2 > -3 ) then
	echo "true"
else
	echo "false"
endif
First, "-1" is evaluated, then "-2 > -3", which yields "1", then "-1 > 1" which
yields "0", hence "false" is printed.

This right associativity is of course going against what one would exspect.
(I hope my English is understandibilitish :-)
It is relativly easy to change the source to get left-associativity :
just take out the recursion and write it as while stat's, like :
	call first_routine
	while there is an operator {
		remember that operator
		call second_routine
		perform operation on results of first and second routines
	}
The syntax has to be rewritten, like:
exp0  : exp1  { "||" exp1 }*
exp1  : exp2  { "&&" exp2 }*
exp2  : exp2a { "|" exp2a }*
...

("*" means "repeat" like in regular expressions)

Now we come to the problem :
IS IT REALLY NECESSARY TO DO THIS?
And:
WHO CAN DECIDE?
And:
WHY BEAT A DEAD HORSE? (except for the fun of it ;-/

Any ideas and comments anybody ?

		Michael

PS: I will change my local csh version to get left associativity, and
	implement some other changes too, like an operator '.' for
	concatenation of strings (to get complicated patterns) and
	enabeling evaluation of `...` as a primitive.
-- 
+------------------------------------------------------------------------------+
| UUCP:  ...!uunet!unido!sbsvax!greim   | Michael T. Greim                     |
|        or greim at sbsvax.UUCP           | Universitaet des Saarlandes          |
| CSNET: greim%sbsvax.uucp at Germany.CSnet| FB 10 - Informatik (Dept. of CS)     |
| ARPA:  greim%sbsvax.uucp at uunet.UU.NET | Bau 36, Im Stadtwald 15              |
| Phone: +49 681 302 2434               | D-6600 Saarbruecken 11, West Germany |
+------------------------------------------------------------------------------+
| These lines are intentionally filled with something to prevent users from    |
| getting the idea that it were empty by mistake rather than intent.           |
+------------------------------------------------------------------------------+



More information about the Comp.unix.questions mailing list