[net.micro.mac] Megamax bug?

gjs@k.cs.cmu.edu (Gregory Stein) (06/09/86)

Keywords:


I'm working in Megamax C, and I noticed a problem while I was in the
debugger.  It comes from these statements:

	for (i = ntables; i--; ) <statement>
	if (i == -1) <more statements>

I would expect this to get the value of i, decrement the stored value,
and then exit or execute the statement.  Rather, it tests the value
before it decrements, and the loop exits with i = 0.  Is this a bug
in the code generation, or is C supposed to do this?

	Greg

kim@analog.UUCP (Kim Helliwell ) (06/11/86)

> Keywords:
> 
> 
> I'm working in Megamax C, and I noticed a problem while I was in the
> debugger.  It comes from these statements:
> 
> 	for (i = ntables; i--; ) <statement>
> 	if (i == -1) <more statements>
> 
> I would expect this to get the value of i, decrement the stored value,
> and then exit or execute the statement.  Rather, it tests the value
> before it decrements, and the loop exits with i = 0.  Is this a bug
> in the code generation, or is C supposed to do this?
> 
> 	Greg

It's not a MegaMax bug, it's a Greg bug (:-).  You have the i-- in the
slot that is supposed to be the termination condition--so your description
sounds like exactly what I would expect to happen.  If you want the i--
to decrement i without testing it for equality to 0 first, it has to
be after the second semicolon:

	for (i = ntables; ; i--) <statement>
	if (i = -1) <more statements>

Kim Helliwell

maclab@reed.UUCP (Mac DLab) (06/13/86)

> > Keywords:
> > 
> > 
> > I'm working in Megamax C, and I noticed a problem while I was in the
> > debugger.  It comes from these statements:
> > 
> > 	for (i = ntables; i--; ) <statement>
> > 	if (i == -1) <more statements>
> > 
> > I would expect this to get the value of i, decrement the stored value,
> > and then exit or execute the statement.  Rather, it tests the value
> > before it decrements, and the loop exits with i = 0.  Is this a bug
> > in the code generation, or is C supposed to do this?
> > 
> > 	Greg
> 
> It's not a MegaMax bug, it's a Greg bug (:-).  

Oops!  Guess Greg just can't get Rascal out of his head!

Scott G.

njt@fisher.UUCP (Nathaniel Thurston) (06/14/86)

In article <219@analog.UUCP> kim@analog.UUCP (Kim Helliwell) writes:
>> 	for (i = ntables; i--; ) <statement>
>> 	if (i == -1) <more statements>
>> 
>> I would expect this to get the value of i, decrement the stored value,
>> and then exit or execute the statement.  Rather, it tests the value
>> before it decrements, and the loop exits with i = 0.  Is this a bug
>> in the code generation, or is C supposed to do this?
>> 
>> 	Greg
>
>	for (i = ntables; ; i--) <statement>
>	if (i = -1) <more statements>
>
>Kim Helliwell

You're both wrong.  The first loop should perform the action Greg describes,
using the value before decrementing.  To have C test the value after
decrementing, use --i.  In the "fix" that Kim gives, the loop will never
exit without a break statement.
The correct code is:
	for (i = ntables; --i; ) <statement>
	if (i == -1) <more statements>
-- 

Nathaniel Thurston
UUCP:   {allegra, astrovax, princeton, twg} !fisher!njt
BELL:   (609) 683-0543
USnail: 106 FitzRandolph Rd., Princeton, NJ 08544

matt@ucla-cs.UUCP (06/16/86)

In article <1436@fisher.UUCP>, njt@fisher.UUCP (Nathaniel Thurston) writes:
- In article <219@analog.UUCP> kim@analog.UUCP (Kim Helliwell) writes:
- >> 	for (i = ntables; i--; ) <statement>
- >> 	if (i == -1) <more statements>
- >> 
- >> I would expect this to get the value of i, decrement the stored value,
- >> and then exit or execute the statement.  Rather, it tests the value
- >> before it decrements, and the loop exits with i = 0.  Is this a bug
- >> in the code generation, or is C supposed to do this?
- >> 
- >> 	Greg
- >
- >	for (i = ntables; ; i--) <statement>
- >	if (i = -1) <more statements>
- >
- >Kim Helliwell
- 
- You're both wrong.  The first loop should perform the action Greg describes,
- using the value before decrementing.  To have C test the value after
- decrementing, use --i.  In the "fix" that Kim gives, the loop will never
- exit without a break statement.
- The correct code is:
- 	for (i = ntables; --i; ) <statement>
- 	if (i == -1) <more statements>
- -- 
- 

I believe Greg is right.  When the loop falls through, `i' should end
up as -1.  If in fact it does not, the C compiler forgot to generate
the trailing DEC instruction on that branch of the test.  This seems
serious, since checking a post-condition like this is fairly common in
C; are you sure?

Kim's code is wrong, and would never exit (empty condition == true).
Also the trailing test has an assignment (i = -1) instead of a
conditional (i == -1).  Thus, that test would always succeed.

Nathaniel's code is wrong, since I presume Greg intended to execute the
<more statements> line if the loop fell through (vs. a `break');
these statements would not be executed if the loop fell through at
i==0.  The correct condition here (if it were the right test, which it
ISN'T for traversing arrays) would be `if (i == 0) ...'.

Sigh.

						- Matt
------- 
UUCP:   {ucbvax,ihnp4,randvax,trwrb!trwspp,ism780}!ucla-cs!matt
ARPA:   matt@LOCUS.UCLA.EDU

baron@runx.OZ (Jason Haines) (06/17/86)

>I'm working in Megamax C, and I noticed a problem while I was in the
>debugger.  It comes from these statements:
>
>	for (i = ntables; i--; ) <statement>
>	if (i == -1) <more statements>
>
>I would expect this to get the value of i, decrement the stored value,
>and then exit or execute the statement.  Rather, it tests the value
>before it decrements, and the loop exits with i = 0.  Is this a bug
>in the code generation, or is C supposed to do this?
>
>	Greg

NEVER confuse the For statement - for(pre-int,test,re-init) <statement block>

Try the following:

	for (i = ntables;;i--) <statement>
	if (i == -1) < more statements>


/* Jason Haines            ACSnet: baron@runx
 * 73 Davidson Avenue      CSNET:  baron@runx.oz
 * Concord NSW 2137        ARPA:   baron%runx.oz@seismo.css.gov
 * AUSTRALIA               
 * 
 * UUCP:
 *   {enea,hplabs,mcvax,prlb2,seismo,ubc-vision,ukc}!munnari!runx.oz!baron
 */

bart@reed.UUCP (Bart Massey) (06/18/86)

In article <219@analog.UUCP> kim@analog.UUCP (Kim Helliwell) writes:
>Greg Stein at CMU said...
> > I'm working in Megamax C, and I noticed a problem while I was in the
> > debugger.  It comes from these statements:
> > 
> > 	for (i = ntables; i--; ) <statement>
> > 	if (i == -1) <more statements>
> > 
> > I would expect this to get the value of i, decrement the stored value,
> > and then exit or execute the statement.  Rather, it tests the value
> > before it decrements, and the loop exits with i = 0.  Is this a bug
> > in the code generation, or is C supposed to do this?
> 
> It's not a MegaMax bug, it's a Greg bug (:-).  You have the i-- in the
> slot that is supposed to be the termination condition--so your description
> sounds like exactly what I would expect to happen.  If you want the i--
> to decrement i without testing it for equality to 0 first, it has to
> be after the second semicolon:
> 
> 	for (i = ntables; ; i--) <statement>
> 	if (i = -1) <more statements>

It may be that you have to do this, (BTW, you almost certainly meant
"for(i = ntables; i; i--) <statement>") but it's not a "Greg Bug", it's
a Megamax bug.  Here's a copy of what I wrote Greg, which he probably
didn't receive, because of mailer problems...  (Sorry, Greg).

K&R specify (page 202) that

	for( i = ntables; i--; )
		<statement>

should be equivalent to

	i = ntables;
	while( i-- )
		<statement>

They also specify that

	"When postfix -- is applied to an lvalue the result is the value of
the object referred to by the lvalue.  After the result is noted, the object
is incremented in the same manner as for the prefix -- operator." (page 187)

Putting this all together...

Imagine that ntables is 37.  The while statement will clearly decrement "i"
down to one.  Then what will happen?  Answer:  one is boolean true, so "i"
will be decremented to zero.  The statement will be executed.  zero is
boolean false.  So the statement won't be executed.  BUT "I" WILL STILL BE
DECREMENTED, as a result of evaluating "i--".  Thus, the <statement> will
be executed 37 times, (with i = 37 downto 1), and "i" will end up with the
value -1.

As a cross check, our 4.2BSD C compiler (reasonably close to K&R), when
fed the original "for" statement, does indeed set "i" to -1.

The Megamax C compiler is probably putting the branch on the wrong side
of the decrement.  Understandable (perhaps especially so to Greg, who
co-authored the original Rascal compiler), but wrong.

Sorry for the length of this posting, but it would have been hard for me
to say it shorter...

				Bart Massey
				..tektronix!reed!bart

pedz@megamax (06/20/86)

main()
{
	int i, j;

	for (i = 10; i--;);
	j = i;
}

CODE SEG "main"
main:/* global */
	LINK	A6,L$0
	MOVE	#10,-2(A6)
L3:
L4:
L2:
	MOVE	-2(A6),D0		<< Get i
	SUBQ	#1,-2(A6)		<< do the decrement
	TST	D0			<< do the test
	BNE.S	L3
L5:
	MOVE	-2(A6),-4(A6)
L1:
	UNLK	A6
	RTS
L$0:	.EQU	#-4
_initargcv:/* global */
	RTS

Matt gets the cookie this time.  The original bug notice was correct
in his statements about how C should behave.  The above code segment
shows that in the current release, this is not a bug.  I am reasonable
sure that it has never been a bug but perhaps someone has a really old
version.  I would suggest that the original poster disassemble his
output and look at the code.  I am sure it will be different from
above but the important thing is that the decrement is done before the
test.

Perry Smith
pedz@megamax

kim@analog.UUCP (Kim Helliwell ) (06/24/86)

I submitted the following source to my Megamax compiler:

	#include <stdio.h>

	main()
	{
	    int i;

	    for (i=10;i--;)
	    {
		printf("%d\n",i);
	    }

	    printf("%d\n",i);
	}

The final value of i was -1, so I don't really think there is a MegaMax
bug.

Kim Helliwell

tim@ism780c.UUCP (06/25/86)

When are you guys gonna release 3.0?  I am using HFS now, and would
like to be able to use Megamax C also...
-- 
Tim Smith                       USENET: sdcrdcf!ism780c!tim || ima!ism780!tim
"hey, bay-BEE'...hey, bay-BEE'" Compuserve: 72257,3706
				Delphi || GEnie: mnementh

jdb@mordor.ARPA (John Bruner) (06/25/86)

Regarding Megamax bugs, I've discovered that the (2.1b) compiler seems
to have trouble with type casts, particularly those in which a value
is cast to a narrower type.  For instance, one bug which really drove
me crazy recently was a piece of code approximately like this:

	struct win_info *w;
	typedef unsigned char row_t, col_t;

	tty_erasep(w, (row_t)0, (col_t)0);

The code it generated was (approximately):

	CLR.W	-(SP)
	CLR.W	-(SP)
	MOVE.L	A2,-(SP)
	JSR	tty_erasep
	ADDQ	#4,SP		<<- 4, not 8

Another problem I had with casts occurred when I was initializing a
data structure.  The first element of the structure was an unsigned int.
I initialized it to (unsigned)-1 [using a macro].  The compiler
generated the correct initialization code but didn't allocate enough
space in the data segment; hence, the structure overlapped variables
declared later.  This also was a real "joy" to find.

I don't seem to have as much difficulty with casts to wider types.
Since I redefine NULL to be 0 (instead of the incorrect 0L defined
in <stdio.h>) I don't run into this problem.

Also I discovered that pointers to functions cannot be compared
(except to NULL), because two pointers to the same function may not
have the same representation.  (I understand why this is so, but
it is annoying nonetheless.)
-- 
  John Bruner (S-1 Project, Lawrence Livermore National Laboratory)
  MILNET: jdb@mordor [jdb@s1-c.ARPA]	(415) 422-0758
  UUCP: ...!ucbvax!decwrl!mordor!jdb 	...!seismo!mordor!jdb