Compiler Sources

Source files in ANSI C for a compiler for a large subset of C. There is no doubt that there must be some things that I forgot about, and even a few bugs, but it does work. It was developed under FreeBSD, but uses nothing specific, so should work equally under any system supporting C.

Recommended Procedure: create a subdirectory to contain only the compiler sourse files, and download everything into it. I have changed the file names so that they all end in ".txt". This should prevent your software from trying to do anything strange with them. After downloading, change any file name that ends in "c.txt" to end in ".c" and any that ends in "h.txt" to ".h" (for example, cgc.txt and cgh.txt should be changed to cg.c and cg.h).
The files are as follows:
When you have all the files, compile each one separately, using the command (for example) cc -c io.c This way, when you make a change, you will only have to recompile the single changed file.
When you have compiled all the files, link together the object files with the command cc *.o -o comp This will only work if you have all the files in a subdirectory with nothing else. Otherwise you will have to list all the .o files separately: cc io.o la.o pa.o sa.o cg.o main.o -o comp
Run the compiler by typing comp (which will expect you to type a C program, or to read one from a file, comp filename.

The compiler produces a file called a.asm containing the assembly code that it generates. To actually run the generated code, you must also download and compile the assembler and machine emulator:
When those four or five files have been downloaded, compile them independently with these commands: cc as.c -o assem and cc ex.c -o execute. Do not use the -c flag to produce an object (.o) file, because it will get mixed in with all the other object files and cause millions of errors when you recompile the compiler with cc *.o -o comp.
        Once your compiler has produced an assembly code file (a.asm), you should look at it first to make sure it seems to be more-or-less OK. Then the command assem will assemble it. The assembler automatically looks for a file called a.asm and creates a pretend xeecutable file called a.exe. To run it, just type the command execute. The emulator automatically load a file called a.exe and runs it.
        If you want to debug or trace the execution of a program, execute can take up to two options: execute -trace runs the program, printing every instruction before it is executed, together with the first few things on the stack. execute -step does the same as -trace plus it waits for input before executing each instruction, allowing the user to inspect the contents of memory before continuing. If you run a program without the -step option and it gets stuck in a loop, typing control-C will turn the step option on.

Naturally, I didn't implement the whole C library. The compiler I've provided understands exactly five library functions: printint(i), printfloat(f), printstring(s), i=readint(), and f=readfloat(). The print functions take one parameter of the obvious type, print it on standard output, and return nothing. The read functions take no parameters, read a value of the obvious type for standard input, and return that value. You do not need to declare these functions, just use them.

Note that the slightly modified syntax used by this compiler requires that every declaration, even of a function with its body, must be terminated by a semicolon (for example: int f() { x=1; };) which would be wrong in standard C. You do not see the output produced for a declaration until the first symbol following that declaration has been accepted, so if you are using the system interactively, you might like to enter another extra semicolon after each function.