http://t3x.org/subc/README-2nd-ed.html (light|dark)
This source file is part of the SubC compiler, which is described in the book
Practical Compiler Construction
You might prefer to download the compiler source code. It is in the public domain.
SubC Compiler, Version 2022-05-02
By Nils M Holm, 2011--2022
Placed in the public domain.
Where the concept of the public domain does not apply,
distributed under the Creative Commons Zero (CC0) license
(see file CC0).
SUMMARY
SubC is a compiler for a (mostly) strict and sane subset of
C as described in "The C Programming Language", 2nd Ed.
The language is also known informally as "ANSI C" or "C89".
The compiler is described in great detail in the book
"Practical Compiler Construction" (2nd Ed.), which can be
purchased at Lulu.com. See http://t3x.org/reload/
This archive contains the SubC compiler as discussed in the
second edition of the book. It contains many fixes that have
been collected since the publication of the first edition.
See the file "Fixes" for details.
The SubC compiler can compile itself. Unlike many other small C
compilers, it does not bend the rules, though. Its code passes
"gcc -Wall -pedantic" with little or no warnings (depending on
the gcc version).
The compiler generates code for GAS-386, the GNU assembler
for the 386 processor. Its runtime environment is designed
to run on FreeBSD systems, but it should be easy to port to
other unixish 32-bit systems. Even porting it to a 64-bit
platform should not be too hard.
SubC is fast and simple. Its output is typically small (due
to a non-bloated library), but not very runtime efficient,
because it employs none of the code synthesis or optimization
strategies explained in the book.
CONTENTS
The root directory of this archive contains the source code for
the SubC compiler itself.
lib/ contains the source code for the SubC library (libscc)
and the runtime startup module (crt0).
include/ contains the header files of the SubC library.
book/ contains source code for the code generators and
optimizers discussed in the later chapters of the book.
It also contains a YACCable version of the formal
grammar that is used to describe SubC in the book.
tests/ contains various programs for testing the correctness
of SubC.
DIFFERENCES BETWEEN SUBC AND FULL C89
(From Practical Compiler Construction)
o The following keywords are not recognized:
auto, const, double, float, goto, long, register, short,
signed, struct, typedef, union, unsigned, volatile.
o There are only two data types: the signed int and the
unsigned char; there are also void pointers, and there
is limited support for int(*)() (pointers to functions
of type int).
o No more than two levels of indirection are supported, and
arrays are limited to one dimension, i.e. valid declarators
are limited to x, x[], *x, *x[], **x (and (*x)()).
o K&R-style function declarations (with parameter
declarations between the parameter list and function body)
are not accepted.
o There are no ``register'', ``volatile'', or ``const''
variables. No register allocation takes place, so all
variables are implicitly ``volatile''.
o There is no typedef.
o There are no unsigned integers and no long integers.
o There are no struct or union data types.
o Only int, char and array of int and char types can be
initialized in their declarations; pointers can be
initialized with 0 (but not with NULL).
o The enum statement does not define a new data type. but
merely a set of constants.
o Local arrays cannot have initializers.
o There are no local extern qualifiers or enum statements.
o Local declarations are limited to the beginnings of function
bodies (they do not work in other compound statements).
o There are no static prototypes.
o Arguments of prototypes must be named.
o There is no goto.
o There are no parameterized macros.
o The #error, #if, #line, and #pragma
preprocessor commands are not recognized.
o The preprocessor does not recognize the # and ## operators.
o There may not be any blanks between the # that introduces
a preprocessor command and the subsequent command (e.g.:
"# define" would not be recognized as a valid command).
o Comments in preprocessor commands will cause trouble in
many cases and should be avoided.
o Preprocessor commands cannot span multiple lines, i.e. a
"\" at the end of a line will not continue a preprocessor
command.
o The sizeof operator is limited to types and single
identifiers; the operator requires parentheses.
o The address of an array must be specified as "&array[0]"
instead of "&array" (but just "array" also works).
o Subscripting an integer with a pointer (e.g. 1["foo"]) is
not supported.
o Function pointers are limited to one single type, int(*)(),
and they have no argument types.
o There is no assert() due to the lack of parameterized macros.
o The atexit() mechanism is limited to one function (this may
even be covered by TCPL2).
o Environments of setjmp() have to be defined as
int[_JMPBUF_SIZ]; instead of jmp_buf due to the lack of
typedef.
o FILE is an alias of int due to the lack of typedef and struct.
o The signal() function is missing. When included by linking
against the host's C library, it returns int due to the lack
of a more sophisticated type system; the return value must be
casted to int(*)().
o Most of the time-related functions are missing due to the lack
of structs; in particular: asctime(), gmtime(), localtime(),
mktime(), and strftime().
o The clock() function is missing, because CLOCKS_PER_SEC
varies among systems.
o The ctime() function ignores the time zone.
COMPILING THE COMPILER
On a FreeBSD system just type "make".
Without "make" the compiler can be bootstrapped by running:
cc -o scc0 *.c
To compile and package the runtime library:
./scc0 -c lib/*.c
ar -rc lib/libscc.a lib/*.o
ranlib lib/libscc.a
To compile the startup module:
as -o lib/crt0.o lib/crt0.s
TESTING THE COMPILER
To test the compiler either run "make test" or perform the
following steps:
./scc0 -o scc1 *.c
./scc1 -o scc *.c
cmp scc1 scc
There should not be any differences between the scc1 and scc
executables.
There is a simple test suite in the tests/ directory. To run
it, type "make test-all". Alternatively, individual tests can
be compiled and run separately, e.g.:
./scc tests/ptest.c && ./a.out && rm a.out
INSTALLING THE COMPILER
If you want to install the SubC compiler on your system, you
will have to change the SCCDIR variable, which points to the
base directory containing the SubC headers and runtime library.
SCCDIR defaults to "." and can be overridden on the command
line when compiling the compiler:
./scc1 -o scc -D 'SCCDIR="INSTALLDIR"' *.c
(where INSTALLDIR is where the compiler will be installed.)
You can place the 'scc' executable wherever you want. The
headers go to INSTALLDIR/include, the library 'lib/libscc.a'
and the startup module 'lib/crt0.o' go to INSTALLDIR/lib.
To test the installation just re-compile the compiler:
rm scc && scc -o scc *.c
CONTACT
Send feedback, suggestions, etc to:
n m h @ t 3 x . o r g
See http://t3x.org/contact.html for current ways through my
spam filter.