[comp.sys.mac.programmer] Think C bug

halpern@csri.toronto.edu (Charles Halpern) (08/07/89)

I am using Think C 3.02, and System 6.0.2 on a SE.  I have observed
the same bug on a Mac II.

This bug is easy to repeat, use any of the demo programs.

This is the bug: when a project is running with the Debugger, and
you hold the mouse button down, say while making a menu choice, after
some random amount of time (usually 5 seconds to 2 minutes) the
application will act as if mouse button is up (making an unintended
menu choice, for example).

I am NOT lifting my mouse button. 

This causes some trouble with the program I am writing. In the course
of dragging out rectangles, the final rectangle is often drawn before
the mouse button is lifted.

I am using the function StillDown in a tight loop.  I have verified 
that no MouseUp event is generated.  It's just that StillDown stops
being true prematurely.

Have others encountered this problem?
Is it fixed in 4.0?

Everything works fine without the Debugger.

siegel@endor.harvard.edu (Rich Siegel) (08/07/89)

In article <1989Aug6.155637.11270@jarvis.csri.toronto.edu> halpern@csri.toronto.edu (Charles Halpern) writes:
>
>This is the bug: when a project is running with the Debugger, and
>you hold the mouse button down, say while making a menu choice, after
>some random amount of time (usually 5 seconds to 2 minutes) the
>application will act as if mouse button is up (making an unintended
>menu choice, for example).
>
	We've seen this one sporadically; it's extremely hard to reproduce,
and seems to be exacerbated by using INITs that themselves bottleneck 
_StillDown.

	(A list of INITs you're using would be helpful.)

		--Rich
~~~~~~~~~~~~~~~
 Rich Siegel
 Staff Software Developer
 Symantec Corporation, Language Products Group
 Internet: siegel@endor.harvard.edu
 UUCP: ..harvard!endor!siegel

"When it comes to my health, I think of my body as a temple - or at least
a moderately well-managed Presbyterian youth center." - Emo Phillips

~~~~~~~~~~~~~~~

rick@Jessica.stanford.edu (Rick Wong) (08/08/89)

In article <2376@husc6.harvard.edu> siegel@endor.UUCP (Rich Siegel) writes:
>In article <1989Aug6.155637.11270@jarvis.csri.toronto.edu> halpern@csri.toronto.edu (Charles Halpern) writes:
>>
>>This is the bug: when a project is running with the Debugger, and
>>you hold the mouse button down, say while making a menu choice, after
>>some random amount of time (usually 5 seconds to 2 minutes) the
>>application will act as if mouse button is up (making an unintended
>>menu choice, for example).
>>
>	We've seen this one sporadically; it's extremely hard to reproduce,
>and seems to be exacerbated by using INITs that themselves bottleneck 
>_StillDown.
>

When I'm using THINK C, I see it quite consistently.  It happens in any
mouse-tracking loop that uses a high-level Event Manager function (Still-
Down, WaitNextEvent, GetNextEvent, and EventAvail).  You may find it
sporadic because your mouse-tracking loops don't last long enough.  On
my Mac II, it virtually always occurs within two minutes.  If you use
a low-level (OS) Event Manager function, such as GetOSEvent, the problem
doesn't occur.

It looks like the problem lies somewhere in the Debugger's patches to
the Event Manager.

I am using a "fresh" System 6.0.2, with NO INITs other than whatever
might be in my System file.

Rick Wong
rick@jessica.stanford.edu

james@utastro.UUCP (James McCartney) (08/08/89)

   The Think C editor sometimes crashes during a paste of clipboard containing
a lot of text (> 32K ?) . I notice this when I use Think C to paste together
big binhex files. Multifinder says : 'Think C unexpectedly quit (out of
application memory).'
   When it doesn't crash, it only pastes the first part (32K ?) of what I had
copied.

   --- James McCartney

siegel@endor.harvard.edu (Rich Siegel) (08/08/89)

In article <4168@utastro.UUCP> james@utastro.UUCP (James McCartney) writes:
>
>   The Think C editor sometimes crashes during a paste of clipboard containing
>a lot of text (> 32K ?) . I notice this when I use Think C to paste together
>big binhex files. Multifinder says : 'Think C unexpectedly quit (out of
>application memory).'

	That's the PE package throwing up its hands, a characteristic of
PE that I dearly hate.

	Clipboard operations are limited to 32K (which isn't entirely
surprising). 

		--Rich

~~~~~~~~~~~~~~~
 Rich Siegel
 Staff Software Developer
 Symantec Corporation, Language Products Group
 Internet: siegel@endor.harvard.edu
 UUCP: ..harvard!endor!siegel

"When it comes to my health, I think of my body as a temple - or at least
a moderately well-managed Presbyterian youth center." - Emo Phillips

~~~~~~~~~~~~~~~

jeremyr@cs.qmc.ac.uk (Jeremy Roussak) (08/09/89)

While we're on the subject of bugs in LSC, here are a couple of
minor ones:

1.  The font popup menu in the Set Tabs & Font dialog pops up
in the wrong place if you have many (>20) fonts and have one
late in the list already selected.  Sometimes it appears an
inch or so above the dialog.  It then scrolls rapidly to Zapf
Dingbats, so a quick "click and release" leaves my code looking
rather weird!

2.  After the following declarations:

typedef struct
 {  long eric, fred;
 } foo;

foo xyzzy, plugh;
Boolean q;

the following works:

main()
 {  foo bar;
    if (q)
        bar = xyzzy;
    else
        bar = plugh;
 }

but this gives a compile error (illegal operation on structure,
or something similar:

main()
 {  foo bar;
    bar = q ? xyzzy: plugh;
 }

A bug, yes? Or am I missing something?

Jeremy Roussak

lim@iris.ucdavis.edu (Lloyd Lim) (02/07/90)

I'm using THINK C 4.0 and it won't accept the constant -2147483648 but it
does accept -2147483647 and 2147483647.  This value does fit in a long.
Curiously, it does accept 0x80000000 and -2147483647 - 1.

Isn't this a bug or am I going to be called bunky?

+++
Lloyd Lim     Internet: lim@iris.ucdavis.edu (128.120.57.20)
              Compuserve: 72647,660
              US Mail: 146 Lysle Leach Hall, U.C. Davis, Davis, CA 95616

yahnke@vms.macc.wisc.edu (Ross Yahnke, MACC) (02/07/90)

In article <6661@ucdavis.ucdavis.edu>, lim@iris.ucdavis.edu (Lloyd Lim) writes...
-I'm using THINK C 4.0 and it won't accept the constant -2147483648 but it
-does accept -2147483647 and 2147483647.  This value does fit in a long.
-Curiously, it does accept 0x80000000 and -2147483647 - 1.

Looks suspicious to me. Defining the constant -2147483647 and assigning
it to a long results in the assembly instruction:
  MOVE.L #$80000001, ...

But as you say, the compiler rejects the constant -2147483648. I wonder
though if the Think C folks are aware of this, cuz in their "limits.h"
header they've defined a constant LONG_MIN which in the documentation
is defined to be -2147483648 but in the actual header file is defined
as:
  #define LONG_MIN  (~2147483647)

which results in the assembly instruction:
  MOVE.L #$80000000, ...

Probably one of those pesky loose ends that M. Kahl never got to 
clearing up.... 

>>>      Internet: yahnke@macc.wisc.edu        <<<
>>>   Mille voix chuchottent <<c'est vrai>>    <<<

jskuskin@eleazar.dartmouth.edu (Jeffrey Kuskin) (02/08/90)

In article <6661@ucdavis.ucdavis.edu> lim@iris.ucdavis.edu (Lloyd Lim) writes:
>I'm using THINK C 4.0 and it won't accept the constant -2147483648 but it
>does accept -2147483647 and 2147483647.  This value does fit in a long.
>Curiously, it does accept 0x80000000 and -2147483647 - 1.
>
>Isn't this a bug or am I going to be called bunky?

Have a look at the manual, page 457, under the "constant too large"
error message explanation.  Evidentally, all integer constants must
have an *absoulte value* less than or equal to (2^31) - 1.

-- Jeff Kuskin, Dartmouth College

gstein@oracle.com (02/08/90)

Jeff Kuskin writes:
>In article <6661@ucdavis.ucdavis.edu> lim@iris.ucdavis.edu (Lloyd Lim) writes:
>>I'm using THINK C 4.0 and it won't accept the constant -2147483648 but it
>>does accept -2147483647 and 2147483647.  This value does fit in a long.
>>Curiously, it does accept 0x80000000 and -2147483647 - 1.
>>
>>Isn't this a bug or am I going to be called bunky?
>
>Have a look at the manual, page 457, under the "constant too large"
>error message explanation.  Evidentally, all integer constants must
>have an *absoulte value* less than or equal to (2^31) - 1.
>
>-- Jeff Kuskin, Dartmouth College
>

I would suspect that Think C does not recognize the "-" sign as a part
of the number, but instead parses the number as two distinct parts:

-2147483648  -->  {-}  {2147483648}

Think C (in a later phase) recognizes the application of the unary
minus to a constant, performs the negation on the constant, and
replaces the two tokens (syntax tree nodes) as a single constant.

Since it recognizes the number as a distinct value, it thinks you're
trying to give it a positive number that is too large.  Regarding the
hexadecimal number, it probably does not do any range checking while
it converts the text into an actual number.  The subtraction is legal
because Think C probably doesn't do any range checking as it optimizes
constant expressions.

Whether this is a bug or not, I can't really say.  I can say that Mike
probably won't fix this any time soon because it is a difficult
problem from a compiler's standpoint.  The compiler will gobble up the
unary minus before it reaches the constant (cuz it doesn't know that
it will be applied to a constant).  Once it hits the constant, it
would be kind of difficult to back up and see if the previous token
was a negative sign and to allow for that extra little bit of range.

So, I don't think you'll be getting called "bunky," whatever that is.
I doubt that the compiler will change to fix this "bug," though.  It
usually doesn't occur, anyhow, cuz writing the numeric representation
is not as self-documenting as 0x8000000 (which tells the programmer
that the MSB is set).  Or, if the number is to be used as a range, you
would use LONG_MIN (or whatever the #define is from <limits.h>).

Greg Stein	-- This posting bears no relation to my employer
Arpa: gstein%oracle.uucp@apple.com
UUCP: ..!{uunet,apple}!oracle!gstein

DN5@psuvm.psu.edu (02/08/90)

>In article <6661@ucdavis.ucdavis.edu> lim@iris.ucdavis.edu (Lloyd Lim) writes:
>>I'm using THINK C 4.0 and it won't accept the constant -2147483648 but it
>>does accept -2147483647 and 2147483647.  This value does fit in a long.
>>Curiously, it does accept 0x80000000 and -2147483647 - 1.
>>
>>Isn't this a bug or am I going to be called bunky?

Actually, this has a simple explanation (its still a bug, but an
understandable one :-) ).

Most numerical input routines I've seen flag any initial symbols that
they see (mostly "-"), and then convert the number.  +2147483648 is
too big to fit into a signed long.  The error gets checked after the
number is read in, and before the negative sign is used.  It would
be nice if the numerical input routine would special case this
number (and it wouldn't be too difficult).

Had the number not been too big, the negative sign would then be applied
to the number.


                         D. Jay Newman
                         dn5@psuvm.psu.edu

pepke@gw.scri.fsu.edu ("Eric Pepke") (02/09/90)

In article <1990Feb7.225358.1125@oracle.com> gstein@oracle.com writes:
> I would suspect that Think C does not recognize the "-" sign as a part
> of the number, but instead parses the number as two distinct parts:
> 
> -2147483648  -->  {-}  {2147483648}
> 
> Think C (in a later phase) recognizes the application of the unary
> minus to a constant, performs the negation on the constant, and
> replaces the two tokens (syntax tree nodes) as a single constant.

The general idea of parsing the number and then negating it is a pretty 
common way of doing things, but creating a negative constant should be the 
job of the lexical analyzer, not the parser.  You basically look at the 
sign, parse the number and create the value, and then optionally negate 
the value.  If you don't check for overflow when parsing the number, this 
method works just fine.  Parsing 2147483648 gives you 0x80000000, which 
interpreted as an unsigned long is 2147483648.  Negating this results in 
the same value, 0x80000000, which interpreted as a signed long is 
-2147483648.  No problem.  If you want to check for overflow before doing 
the negation, you have to treat this as a special case.

Even if you do something like -(2147483648) to force the parser rather 
than the lexical analyzer to do the negation, it should still work.  The 
compiler should recognize that 2147483648 is too big to be a signed long 
and therefore should be treated as unsigned.  It should then recognize 
that negation of this particular unsigned long producing a signed long is 
valid.  You're probably right, though--THINK C probably doesn't.

> Whether this is a bug or not, I can't really say.  I can say that Mike
> probably won't fix this any time soon because it is a difficult
> problem from a compiler's standpoint.

No, it's not really difficult; it just requires keeping the appropriate 
special cases in mind.  The biggest negative integer in 2's complement 
notation is a situation that is commonly missed.  Pascal gets around the 
problem by disallowing the biggest negative integer in its syntax.  Back 
in the old days when computers ran on kerosene, I had a Tiny Pascal 
compiler/P-code interpreter on a TRS-80 Model 1.  When I tried printing 
out -32768, it printed a strange set of characters, I think something like 
-(*).  I wondered why, but some years later a routine of mine to print 
numbers had the exact same problem.  It was easy to fix, but it required 
being aware of that special case and special consideration of the boundary 
conditions.

Eric Pepke                                     INTERNET: 
pepke@gw.scri.fsu.edu
Supercomputer Computations Research Institute  MFENET:   pepke@fsu
Florida State University                       SPAN:     scri::pepke
Tallahassee, FL 32306-4052                     BITNET:   pepke@fsu

Disclaimer: My employers seldom even LISTEN to my opinions.
Meta-disclaimer: Any society that needs disclaimers has too many lawyers.

pepke@gw.scri.fsu.edu ("Eric Pepke") (02/09/90)

In article <499@fsu.scri.fsu.edu> I write:
> The general idea of parsing the number and then negating it is a pretty 
> common way of doing things, but creating a negative constant should be 
the 
> job of the lexical analyzer, not the parser.  You basically look at the 

Sorry; this is wrong.  It has been pointed out to me that the C 
specification for an integer constant is a sequence of digits.

More for those who care:

K&R 2, section A2, p. 193:
"The type of an integer constant depends on its form, value, and suffix... 
 If it is unsuffixed and decimal, it has the first of these types in which 
its value can be represented: int, long int, unsigned long int."

K&R 2, section A6, p. 204:
"The negative of an unsigned quantity is computed by subtracting the 
promoted value from the largest value of the promoted type and adding one; 
but negative zero is zero."

K&R 2, section A6, p. 197:
"When any integer is converted to a signed type, the value is unchanged if 
it can be represented in the new type and is implementation-defined 
otherwise."

By these rules, 2,147,483,648 should have the type unsigned long int, as 
it is the first in the list that works.  Negation on this should produce 
2,147,483,648.  Conversion to a signed long is implementation-defined.  
The most reasonable is just to use the same bits, resulting in 
-2,147,483,648.

THINK C's behavior is, however, consistent with K&R 1, which does not 
specify a way of making decimal unsigned constants, either by default or 
explicitly with a U suffix.

Eric Pepke                                    INTERNET: pepke@gw.scri.fsu.edu
Supercomputer Computations Research Institute MFENET:   pepke@fsu
Florida State University                      SPAN:     scri::pepke
Tallahassee, FL 32306-4052                    BITNET:   pepke@fsu

Disclaimer: My employers seldom even LISTEN to my opinions.
Meta-disclaimer: Any society that needs disclaimers has too many lawyers.

lim@iris.ucdavis.edu (Lloyd Lim) (02/19/91)

I think I've ran across another pair of bugs in THINK C 4.0.2.  The following
code works OK with 68881 code generation off but doesn't when it's on.

double x;
unsigned long u;

x = ULONG_MAX;

u = 3.0e+9;

The first statement works normally but assigns a -1.0 when the 68881 option
is on.  The second statement also works normally but assigns 0x7FFFFFFF when
the 68881 is on.  It seems like THINK C forgets that unsigned longs exist.
Yes, you can work around it but it's annoying.

+++
Lloyd Lim     Internet: lim@iris.eecs.ucdavis.edu
              Compuserve: 72647,660
              US Mail: 215 Lysle Leach Hall, U.C. Davis, Davis, CA 95616

knoll@well.sf.ca.us (John Knoll) (02/22/91)

Today, I was trying to use the Toolbox function "FixATan2" as described in
Inside Mac 4.  The linker couldn't find this function.  I searched ALL
of the ".h" files to find where it was declared, but it doesn't appear
anywhere.
I've used this function successfully in MPW C.

Finally, I gave up and added the following to my code:

pascal Fixed FixATan2(Fixed,Fixed) = {0xA818};

and now everthing is cool.  What am I doing wrong?  Where is this function
declared?

lim@iris.ucdavis.edu (Lloyd Lim) (02/23/91)

In article <23282@well.sf.ca.us> knoll@well.sf.ca.us (John Knoll) writes:
>
>Today, I was trying to use the Toolbox function "FixATan2" as described in
>Inside Mac 4.  The linker couldn't find this function.  I searched ALL
>of the ".h" files to find where it was declared, but it doesn't appear
>anywhere.

They misspelled it as FixAtan2.  I put a #define in my ToolboxUtil.h to
correct it.  I reported this before and I'm sure other people have too.
There are also case problems with the routines for converting between
80 bit and 96 bit floating point numbers.

+++
Lloyd Lim     Internet: lim@iris.eecs.ucdavis.edu
              America Online: LimUnltd
              Compuserve: 72647,660
              US Mail: 215 Lysle Leach Hall, U.C. Davis, Davis, CA 95616

stas@brahms.udel.edu (Stanislaus Pietrucha) (05/20/91)

This is the weirdest I've ever seen, and I know it is a compiler error.
First of all I compiled the code in Think C and, what you see here works.
The problem is the field in the record struct, int dummy.  

If i try to run this code without the dummy field, it will crash whenever
I reference char last[24] (as i do in fgets(...p_current->last)).

If this isn't weird enough, if I switch the order of the fields in the record,
the error (bad field) is always the same. i.e. if i moved first where last is
then i could access last, but not first.  It's like a black hole.  Without
the dummy variable exactly where it is, whatever item (it seems) that is in
the 5th position is inaccessable.  What the heck is going on????

Take a look at the code:  
 
Here is the record structure:
struct customer_record
	{
	struct customer_record *prev;
	struct customer_record *next;
	char number[8];
	char first[20];
	int dummy;
	char last[24];
	char position[8];
	char team[40];
	char rookie[8];
	char sale[8];
	int quantity;
	};
 
here is the function in which the program blows up (when dummy not used) 
 
int file_to_list(FILE *datafile,struct customer_record *llist)
{
	char last[24],file_header[40];
	struct customer_record *p_current;
	int c, x, done, length = 0;
	int quantity;
	p_current = (struct customer_record *) malloc(sizeof
				(struct customer_record));
	llist = p_current; 
	p_current->prev = llist;
	fgets(file_header,40,datafile);
	printf("%s\n",file_header);
	while((c=getc(datafile)) != EOF)
	{
		ungetc(c,datafile);
		fgets(p_current->number,8,datafile);
		fgets(p_current->first,20,datafile);
		fgets(p_current->last,24,datafile);
		fgets(p_current->position,8,datafile);
		fgets(p_current->team,40,datafile);
		fgets(p_current->rookie,8,datafile);
		fgets(p_current->sale,8,datafile);
		fscanf(datafile,"%d\n",p_current->quantity);
		p_current->next = (struct customer_record *) malloc(sizeof
					(struct customer_record));
		p_current->next->prev = p_current;
		p_current = p_current->next;
	} 
	fclose(datafile);
	load_flag = 1;
}
 
 
--------------------And here is the data file:
Stan's Client List			/*file_header*/
1					/*number*/
Terri					/*first*/
Wache					/*last*/
HM					/*postition*/
Nashua Hornets				/*team*/
Y					/*rookie*/
N					/*sale*/
5					/*quantity*/
2				
Carol
Veach
MG
Philadelphia Waxers
N
N
6
-------------That's it
(The comments are for you, i.e. they are not actually in the data file)
 
Don't try to make sense of the data, it's personal.
 
Thanks for any help/input you can give me.
 
Stas