-*- Text -*- CC65 preliminary doc CC65 is a PD C compiler for Atari 8-bit computers. Using it: Essentially, all you do to use CC65 is start it up and hand it a file name to compile. This can be done either on a command line, or by typing it in at the prompt after CC65 starts up. Input files are assumed to be C source. Extension .C is assumed if not specified. Include files are currently assumed to be on the same drive as the C source file. [If anyone can think of a better way to do this, please tell me] Switches: -v Verbose. -v once means print function names as they're encountered. Twice prints source lines as they're read. -d Debug. Turns on various debugging code. CC65 processes a source file and produces a file with the same name, and extension .M65, ie if you compile foo.c, you'll get foo.m65. The assembler language produced is suitable for feeding to RA65, although you could probably get it to work by defining a couple of macros using something like MAC/65. What it understands: CC65 understands the following primitive datatypes: char 8 bits int 16 bits short 16 bits long 16 bits (sorry) floats are not supported, though they probably could be without too much effort. Structs and unions, arrays, and pointers are all supported in the usual fashion (at least I think it's the usual fashion; I'm not a C weenie by trade, and I didn't have the stomach to research it in detail) You may have structs containing pointers, pointers to pointers, pointers to structs, etc, etc, ie all the things that other Small-C variants don't do. One peculiar caution about structs: field names in structs are part of a GLOBAL namespace, rather than a namespace per structure kind, as mopst modern compilers use. This means that if you try to say struct frob $( char blech $); struct frobozz $( int blech $); you'll get griped at, because it thinks field 'blech' is multiply defined. (I'm told this was once considered a feature, but hey, everybody in the 14th century had lice...) Enums are not currently supported in the native CC65, to save space, though the cross-compiler variant does hack them. They could easily be put back at the cost of some symbol space. CC65 supports all the usual flow of control constructions, for; while; switch; do .. while; goto, etc. Other syntactoids: CC65 has the usual problem of C compilers on Ataris, namely that Atascii doesn't contain braces and tilde characters. We use the same kludge, $(, $) and $- in place of $(, $), and $-. Temporary vars: CC65 supports temps as foo() $( gubbish(); $( int baz; /* temps in inner code fragment! */ char quux; more_gubbish(); $) yet_more_gubbish(); $) In line assembly code: You can embed assembly language in your C source by using the magic keywords #asm and #endasm. Everything between those lines is copied verbatim into the assembler output file. Ex: frobozz() $( #asm inc _foo #endasm $) generates something like: _frobozz: jsr enterfn inc _foo jmp exitfun You can also use #asm outside functions, as #asm _foo: .word 0 #endasm This is particularly useful for doing things like declaring things to be on page 0; for instance: #asm _foo = $B0 #endasm extern int foo; Subsequent references to foo will generate the correct (page 0) variants of the instructions. Accessing local variables in inline assembly code: This is tricky. Sigh. See internal.doc for details of the stack layout. Magic symbols: CC65 understands two magic preprocessor symbols, NOARGC and FIXARGC. These are primarily used when trying to reduce code size, and improve performance. Defining these symbols have the following effects: NOARGC Do not pass arg count. If defined, called functions will not have an arg count passed to them. FIXARGC Fixed arg count. If defined, functions will not expect to have an arg count passed to them. The way these work can be tricky: a function compiled with NOARGC may ONLY call functions compiled with FIXARGC. The reverse is not true; functions compiled with FIXARGC may call anything, since they DO pass argcounts. Functions compiled with FIXARGC may be called from anything as long as exactly the right number of args is passed; any argcounts will be ignored. Known bugs: You can only use 256 bytes of local stack space per function. This is due to the way I did the local-var addressing. Ordinarily, this isn't a problem, but you should watch out for things like: foo() $( char bar[500]; ... $) The structure-frobbing code doesn't know enough to correctly pass the address of a structure, when calling some function on it, and generates bogus code. That means when you want to say frobnicate(structure); you have to say frobnicate(&structure); There are still bugs in the conditional-evaluation code generator. If your "if (...)" statements are behaving in funny fashion, check the generated code carefully. You can't put comments on lines with #-sign directives at the front. Where it came from: The geneology of CC65 is complex. It started life as a hack based on a CPM version of Small-C, and lived in that form as a cross-compiler for a couple of years. It was later updated to use the internal expression-grokking guts of another Small-C variant, this time for the PC. Finally, it inherited most of the parser etc from CC8, which appears from the source to be yet another Small-C variant. The rest of the system and support programs RA65, LINK65, LIBR65 etc, were written by JRD. Much of the runtime support was also written by JRD; some was inherited from the PC version of Small-C.