[net.micro.atari16] Problems with Lattice C and PC HACK

rwb@druxu.UUCP (BlackR) (06/19/86)

<is there still a line eater?>
As promised, here are the problems I have encounterd in compiling PC
HACK with the Lattice C compiler, that I attribute to the Lattice
package.  Though I will mention them in the context of PC HACK, other
Lattice C users may recognize the symptoms in things they have done.

1) max() is #define'd in a header file (#define max(a,b) (a<b ? b: a)). 
In one function, it was used as a formal parameter
(function(..,max,..)).  The compiler didn't like the formal parameter.
Solution: change the name of the formal parameter.

2) one function declared 7 formal parameters, all with a register
storage class.  The second pass of the compiler died with a CXERR
message and no indication of where.  Solution: remove the register
storage class specifier (I suspect that the compiler has an internal
limit of 5 or 6 register storage class formal parameters).

3) the linker saw all symbols as upper case letters (e.g. monname() and
Monname() were both seen as MONNAME by the linker, and it complained
about a multiply defined symbol).  Solution: change the name of one
function in the source (be sure to also change all references to it).

4) some files would not link.  The linker complained about an "error in
relocatable file".  In the process of breaking the unlinkable files into
pieces, to find what was wrong, I discovered that each piece would link.
One would think that the compiler was running out of
memory; however, I could find no relationship between file size and
ability to link.  The largest file failed to link, but it also failed to
link after it was broken into three pieces, with each piece being small
to medium sized.  Furthermore, the second largest file linked with no
problems, but smaller files would not.  Solution: modularize.  Break
your files into small units and be careful about how variables are
shared between files.

5) some messages sent to the screen were incomplete.  The strncpy
library routine ALWAYS places a null character ('\0') at the end of the
copied string.  The standard UNIX(r) routine places a null at the end of
a string only if one is found in the source string before the specified
number of bytes is copied.  Solution: write a different strncpy routine.

6) address error bombs when reading or writing "bones" files to or from
the RAM disk (I lied.  I don't think this is a Lattice problem, because
I had the same problem when using GEMDOS disk read and write calls). 
The mushroom (cherry bomb?) analyzer told me the bad instruction was a
MOV.W (A0),(A1) and one of the registers was an odd address.  The source
code I had for a RAM disk had no MOV.W instructions (all MOV.B), so I
couldn't identify the culprit.  I tried the similar code in a small
program and everything worked fine.  I eventually figured out that the
error occured when writing (reading) the second sector of a file when the
first sector was several even number of byte writes (reads), a single
byte write (read), then a large write (read) of several thousand bytes.
Solution: be sure an even number of bytes are written (read) in each
read or write call.

7) bus error bombs when writing or reading the "bones" files (those
files gave me a lot of trouble).  This one was traced to something the
compiler is doing.  Here is what the variable declaration looked like:
	struct permonst mons[]={
		some initializations
	}
	struct permonst pm_ghost={ initialization};

Later, a pointer was set to &pm_ghost and &mons was subtracted from it,
yielding the index of pm_ghost in the mons array (even though it wasn't
in the array).  The result should have been 0x39, but it was 0x60039. 
The linker map showed that pm_ghost was 0x39*sizeof(permonst) bytes away
from mons[0].  Solution: fold pm_ghost and similar structures into the
mons array of structures.  I haven't looked at the code generated, but
it appears the compiler is performing array bounds checking.

8) "record" files (containing the scores from previous games) gets
garbage.  This has been traced to the scanf() library routine, but it
isn't consistent.  Sometimes the scores will be read fine and later,
one won't (even if it was read fine earlier).  Solution: other than
write my own scanf, I haven't found one.

Conclusions: as most software developers know, after you see the
problem, the solution is frequently obvious.  I found it very difficult
to find some of these problems because I didn't write the source and
because it is so large.  So, I am posting these notes in hopes someone
else will be spared some effort.

Rodney Black
AT&T Information Systems
Denver, CO.
...!druxu!rwb