The C Compiler System
Introduction The "C" programming language is rapidly growing in popularity and seems destined to become one of the most popular programming languages used for microcomputers. The rapid rise in the use of C is not surprising. C is an incredibly versatile and efficient language that can handle tasks that previously would have required complex assembly language programming. C was originally developed at Bell Telephone Laboratories as an implementation language for the UNIX operating system by Brian Kernighan and Dennis Ritchie. They also wrote a book titled The C Programming Language which is universally accepted as the standard for the language. It is an interesting reflection on the language that although no formal industry-wide standard was ever developed for C, programs written in C tend to be far more portable between radically different computer systems as compared to so-called standardized languages such as BASIC, COBOL, and PASCAL. The reason C is so portable is that the language is so inherently expandable that is some special function is required, the user can create a portable extension to the language, as opposed to the common practice of adding additional statements to the language. For example, the number of special-purpose BASIC dialects defies all reason. A lesser factor is the underlying UNIX operating system, which is also sufficiently versatile to discourage bastardization of the language. Indeed, standard C compilers and Unix are intimately related. Fortunately, the 6809 microprocessor, the OS-9 operating system, and the C language form an outstanding combination. The 6809 was specifically designed to efficiently run high-level languages, and its stack-oriented instruction set and versatile repertoire of addressing modes handle the C language very well. As mentioned previously, UNIX and C are closely related, and because OS-9 is derived from UNIX, it also supports C to the degree that almost any application written in C can be transported from a UNIX system to an OS-9 system, recompiled, and correctly executed.
The Language Implementation OS-9 C is implemented almost exactly as described in 'The C Programming Language' by Kernighan and Ritchie (hereafter referred to as K&R). Allthough this version of C follows the specification faithfully, there are some differences. The differences mostly reflect parts of C that are obsolete or the constraints imposed by memory size limitations.
Differences from the K & R Specification
Enhancements and Extensions
The <quote>Direct</quote> Storage Class
Embedded Assembly Language
Control Character Escape Sequences
Implementation-dependent Characteristics
Data Representation and Storage Requirements
Register Variables
Access To Command Line Parameters
System Calls and the Standard Library
Operating System Calls
The Standard Library
Run-time Arithmetic Error Handling
Achieving Maximum Program Performance
Programming Considerations
The Optimizer Pass
The Profiler
C Compiler Component Files and File Usage
Temporary Files
Running the Compiler
Compiler Option Flags The compiler recognizes several command-line option flags which modify the compilation process where needed. All flags are recognized before compilation commences so the flags may be placed anywhere on the command line. Flags may be ran together as in "-ro", except where a flag is followed by something else; see "-f=" and "-d" for examples. -A suppresses assembly, leaving the output as assembler code in a file whose name is postfixed ".a". -E=<number> Set the edition number constant byte to the number given. This is an OS-9 convention for memory modules. -O inhibits the assembly code optimizer pass. The optimizer will shorten object code by about 11% with a comparable increase in speed and is recommended for production versions of de-bugged programs. -P invokes the profiler to generate function frequency statistics after program execution. -R suppresses linking library modules into an executable program. Outputs are left in files with postfixes ".r". -M=<memory size> will instruct the linker to allocate <memory size> for data, stack, and parameter area. Memory size may be expressed in pages (an integer) or in kilobytes by appending "k" to an integer. For more details of the use of this option, see the "Memory Management" section of this manual. -L=<filename> specifies a library to be searched by the linker before the Standard Library and system interface. -F=<path> overrides the above output file naming. The output file will be left with <filename> as its name. This flag does not make sense in multiple source mode, and either the -a or -r flag is also present. The module will be called the last name in <path>. -C will output the source code as comments with the assembler code. -S stops the generation of stack-checking code. -S should only be used with great care when the appication is extremely time-critical and when the use of the stack by compiler generated code is fully understood. -D<identifier> is equivalent to "#define <identifier>" written in the source file. -D is useful where different versions of a program are maintained in one source file and differentiated by means of the "#ifdef" of "#ifndef" pre-processor directives. If the <identifier> is used as a macro for expansion by the pre-processor, "1"(one) will be the expanded "value" unless the form "-d<identifier>=<string>" is used in which case the expansion will be <string>. Command Line and Option Flag Examples command line action output file(s) cc prg.c compile to an executable program prg cc prg.c -a compile to assembly language source code prg.a cc prg.c -r compile to relocatable module prg.r cc prg1.c prg2.c prg3.c compile to executable program prg1.r, prg2.r, prg3.r, output cc prg1.c prg2.a prg3.r compile prg1.c, assemble prg2.a and combine all into and executable program prg1.r, prg2.r cc prg1.c prg2.c -a compile to assembly language source code prg1.a, prg2.a cc prg1.c prg2.c -f=prg compile to executable program prg