.EQ delim $$ .EN .RP .TL ACK/CEM Compiler .br Reference Manual .AU Erik H. Baalbergen .AI Department of Mathematics and Computer Science Vrije Universiteit Amsterdam The Netherlands .AB no .AE .NH C Language .PP This section discusses the extensions to and deviations from the C language, as described in [1]. The issues are numbered according to the reference manual. .SH 2.2 Identifiers .PP Upper and lower case letters are different. The number of significant letters is 32 by default, but may be set to another value using the \fB\-M\fP option. The identifier length should be set according to the rest of the compilation programs. .SH 2.3 Keywords .SH \f5asm\fP .PP The keyword \f5asm\fP is recognized. However, the statement .DS .ft 5 asm(string); .ft R .DE is skipped, while a warning is given. .SH \f5enum\fP .PP The \f5enum\fP keyword is recognized and interpreted. .SH \f5entry\fP, \f5fortran\fP .PP The words \f5entry\fP and \f5fortran\fP are reserved under the restricted option. The words are not interpreted by the compiler. .SH 2.4.1 Integer Constants .PP The type of an integer constant is the first of the corresponding list in which its value can be represented. Decimal: \f5int, long, unsigned long\fP; octal or hexadecimal: \f5int, unsigned, long, unsigned long\fP; suffixed by the letter L or l: \f5long, unsigned long\fP. .SH 2.4.3 Character Constants .PP A character constant is a sequence of 1 up to \f5sizeof(int)\fP characters enclosed in single quotes. The value of a character constant '$c sub 1 c sub 2 ... c sub n$' is $d sub n + M \(mu d sub {n - 1} + ... + M sup {n - 1} \(mu d sub 2 + M sup n \(mu d sub 1$, where M is 1 + maximum unsigned number representable in an \f5unsigned char\fP, and $d sub i$ is the signed value (ASCII) of character $c sub i$. .SH 2.4.4 Floating Constants .PP The compiler does not support compile-time floating point arithmetic. .SH 2.6 Hardware characteristics .PP The compiler is capable of producing EM code for machines with the following properties .IP \(bu a \f5char\fP is 8 bits .IP \(bu the size of \f5int\fP is equal to the word size .IP \(bu the size of \f5short\fP may not exceed the size of \f5int\fP .IP \(bu the size of \f5int\fP may not exceed the size of \f5long\fP .IP \(bu the size of pointers is equal to the size of either \f5short\fP, \f5int\fP or \f5long\fP .LP .SH 4 What's in a name? .SH \f5char\fP .PP Objects of type \f5char\fP are taken to be signed. The combination \f5unsigned char\fP is legal. .SH \f5unsigned\fP .PP The type combinations \f5unsigned char\fP, \f5unsigned short\fP and \f5unsigned long\fP are supported. .SH \f5enum\fP .PP The data type \f5enum\fP is implemented as described in \fIRecent Changes to C\fP (see appendix A). .I Cem treats enumeration variables as if they were \f5int\fP. .SH \f5void\fP .PP Type \f5void\fP is implemented. The type specifies an empty set of values, which takes no storage space. .SH \fRFundamental types\fP .PP The names of the fundamental types can be redefined by the user, using \f5typedef\fP. .SH 7 Expressions .PP The order of evaluation of expressions depends on the complexity of the subexpressions. In case of commutative operations, the most complex subexpression is evaluated first. Parameter lists are evaluated from right to left. .SH 7.2 Unary operators .PP The type of a \f5sizeof\fP expression is \f5unsigned int\fP. .SH 7.13 Conditional operator .PP Both the second and the third expression in a conditional expression may include assignment operators. They may be structs or unions. .SH 7.14 Assignment operators .PP Structures may be assigned, passed as arguments to functions, and returned by functions. The types of operands taking part must be the same. .SH 8.2 Type specifiers .PP The combinations \f5unsigned char\fP, \f5unsigned short\fP and \f5unsigned long\fP are implemented. .SH 8.5 Structure and union declarations .PP Fields of any integral type, either signed or unsigned, are supported, as long as the type fits in a word on the target machine. .PP Fields are left adjusted by default; the first field is put into the left part of a word, the next one on the right side of the first one, etc. The \f5-Vr\fP option in the call of the compiler causes fields to be right adjusted within a machine word. .PP The tags of structs and unions occupy a different name space from that of variables and that of member names. .SH 9.7 Switch statement .PP The type of \fIexpression\fP in .DS .ft 5 \f5switch (\fP\fIexpression\fP\f5)\fP \fIstatement\fP .ft .DE must be integral. A warning is given under the restricted option if the type is \f5long\fP. .SH 10 External definitions .PP See [4] for a discussion on this complicated issue. .SH 10.1 External function definitions .PP Structures may be passed as arguments to functions, and returned by functions. .SH 11.1 Lexical scope .PP Typedef names may be redeclared like any other variable name; the ice mentioned in \(sc11.1 is walked correctly. .SH 12 Compiler control lines .PP Lines which do not occur within comment, and with \f5#\fP as first character, are interpreted as compiler control line. There may be an arbitrary number of spaces, tabs and comments (collectively referred as \fIwhite space\fP) following the \f5#\fP. Comments may contain newline characters. Control lines with only white space between the \f5#\fP and the line separator are skipped. .PP The #\f5include\fP, #\f5ifdef\fP, #\f5ifndef\fP, #\f5undef\fP, #\f5else\fP and #\f5endif\fP control lines and line directives consist of a fixed number of arguments. The list of arguments may be followed an arbitrary sequence of characters, in which comment is interpreted as such. (I.e., the text between \f5/*\fP and \f5*/\fP is skipped, regardless of newlines; note that commented-out lines beginning with \f5#\fP are not considered to be control lines.) .SH 12.1 Token replacement .PP The replacement text of macros is taken to be a string of characters, in which an identifier may stand for a formal parameter, and in which comment is interpreted as such. Comments and newline characters, preceeded by a backslash, in the replacement text are replaced by a space character. .PP The actual parameters of a macro are considered tokens and are balanced with regard to \f5()\fP, \f5{}\fP and \f5[]\fP. This prevents the use of macros like .DS .ft 5 CTL([) .ft .DE .PP Formal parameters of a macro must have unique names within the formal-parameter list of that macro. .PP A message is given at the definition of a macro if the macro has already been #\f5defined\fP, while the number of formal parameters differ or the replacement texts are not equal (apart from leading and trailing white space). .PP Recursive use of macros is detected by the compiler. .PP Standard #\f5defined\fP macros are .DS \f5__FILE__\fP name of current input file as string constant \f5__DATE__\fP curent date as string constant; e.g. \f5"Tue Wed 2 14:45:23 1986"\fP \f5__LINE__\fP current line number as an integer .DE .PP No message is given if \fIidentifier\fP is not known in .DS .ft 5 #undef \fIidentifier\fP .ft .DE .SH 12.2 File inclusion .PP A newline character is appended to each file which is included. .SH 12.3 Conditional compilation .PP The #\f5if\fP, #\f5ifdef\fP and #\f5ifndef\fP control lines may be followed by an arbitrary number of .DS .ft 5 #elif \fIconstant-expression\fP .ft .DE control lines, before the corresponding #\f5else\fP or #\f5endif\fP is encountered. The construct .DS .ft 5 #elif \fIconstant-expression\fP some text #endif /* corresponding to #elif */ .ft .DE is equivalent to .DS .ft 5 #else #if \fIconstant-expression\fP some text #endif /* corresponding to #if */ #endif /* corresponding to #else */ .ft .DE .PP The \fIconstant-expression\fP in #\f5if\fP and #\f5elif\fP control lines may contain the construction .DS .ft 5 defined(\fIidentifier\fP) .ft .DE which is replaced by \f51\fP, if \fIidentifier\fP has been #\f5defined\fP, and by \f50\fP, if not. .PP Comments in skipped lines are interpreted as such. .SH 12.4 Line control .PP Line directives may occur in the following forms: .DS .ft 5 #line \fIconstant\fP #line \fIconstant\fP "\fIfilename\fP" #\fIconstant\fP #\fIconstant\fP "\fIfilename\fP" .ft .DE Note that \fIfilename\fP is enclosed in double quotes. .SH 14.2 Functions .PP If a pointer to a function is called, the function the pointer points to is called instead. .SH 15 Constant expressions .PP The compiler distinguishes the following types of integral constant expressions .IP \(bu field-width specifier .IP \(bu case-entry specifier .IP \(bu array-size specifier .IP \(bu global variable initialization value .IP \(bu enum-value specifier .IP \(bu truth value in \f5#if\fP control line .LP .PP Constant integral expressions are compile-time evaluated while an effort is made to report overflow. Constant floating expressions are not compile-time evaluated. .NH Compiler flags .IP \fB\-C\fR Run the preprocessor stand-alone while maintaining the comments. Line directives are produced whenever needed. .IP \fB\-D\fP\fIname\fP=\fIstring-of-characters\fP .br Define \fIname\fR as macro with \fIstring-of-characters\fR as replacement text. .IP \fB\-D\fP\fIname\fP .br Equal to \fB\-D\fP\fIname\fP\fB=1\fP. .IP \fB\-E\fP Run the preprocessor stand alone, i.e., list the sequence of input tokens and delete any comments. Line directives are produced whenever needed. .IP \fB\-I\fIpath\fR .br Prepend \fIpath\fR to the list of include directories. To put the directories "include", "sys/h" and "util/h" into the include directory list in that order, the user has to specify .DS .ft 5 -Iinclude -Isys/h -Iutil/h .ft R .DE An empty \fIpath\fP causes the standard include directory (usually \f5/usr/include\fP) to be forgotten. .IP \fB\-M\fP\fIn\fP .br Set maximum significant identifier length to \fIn\fP. .IP \fB\-n\fP Suppress EM register messages. The user-declared variables are not stored into registers on the target machine. .IP \fB\-p\fP Generate the EM \fBfil\fP and \fBlin\fP instructions in order to enable an interpreter to keep track of the current location in the source code. .IP \fB\-P\fP Equivalent with \fB\-E\fP, but without line directives. .IP \fB\-R\fP Interpret the input as restricted C (according to the language as described in [1]). .IP \fB\-T\fP\fIpath\fP .br Create temporary files, if necessary, in directory \fIpath\fP. .IP \fB\-U\fP\fIname\fP .br Get rid of the compiler-predefined macro \fIname\fP, i.e., consider .DS .ft 5 #undef \fIname\fP .ft R .DE to appear in the beginning of the file. .IP \fB\-V\fIcm\fR.\fIn\fR,\ \fB\-V\fIcm\fR.\fIncm\fR.\fIn\fR\ ... .br Set the size and alignment requirements. The letter \fIc\fR indicates the simple type, which is one of \fBs\fR(short), \fBi\fR(int), \fBl\fR(long), \fBf\fR(float), \fBd\fR(double) or \fBp\fR(pointer). If \fIc\fR is \fBS\fP or \fBU\fP, then \fIn\fP is taken to be the initial alignment of structs or unions, respectively. The effective alignment of a struct or union is the least common multiple of the initial struct/union alignment and the alignments of its members. The \fIm\fR parameter can be used to specify the length of the type (in bytes) and the \fIn\fR parameter for the alignment of that type. Absence of \fIm\fR or \fIn\fR causes the default value to be retained. To specify that the bitfields should be right adjusted instead of the default left adjustment, specify \fBr\fR as \fIc\fR parameter. .IP \fB\-w\fR Suppress warning messages .IP \fB\-\-\fIcharacter\fR .br Set debug-flag \fIcharacter\fP. This enables some special features offered by a debug and develop version of the compiler. Some particular flags may be recognized, others may have surprising effects. .RS .IP \fBd\fP Generate a dependency graph, reflecting the calling structure of functions. Lines of the form .DS .ft 5 DFA: \fIcalling-function\fP: \fIcalled-function\fP .ft .DE are generated whenever a function call is encountered. .IP \fBf\fP Dump whole identifier table, including macros and reserved words. .IP \fBh\fP Supply hash-table statistics. .IP \fBi\fP Print names of included files. .IP \fBm\fP Supply statistics concerning the memory allocation. .IP \fBt\fP Dump table of identifiers. .IP \fBu\fP Generate extra statistics concerning the predefined types and identifiers. Works in combination with \fBf\fP or \fBt\fP. .IP \fBx\fP Print expression trees in human-readable format. .RE .LP .SH References .IP [1] Brian W. Kernighan, Dennis M. Ritchie, .I The C Programming Language .R .IP [2] L. Rosler, .I Draft Proposed Standard - Programming Language C, .R ANSI X3J11 Language Subcommittee .IP [3] Erik H. Baalbergen, Dick Grune, Maarten Waage, .I The CEM Compiler, .R Informatica Manual IM-4, Dept. of Mathematics and Computer Science, Vrije Universiteit, Amsterdam, The Netherlands .IP [4] Erik H. Baalbergen, .I Modeling global declarations in C, .R internal paper .LP .bp .SH Appendix A - Enumeration Type .PP The syntax is .sp .RS .I enum-specifier : .RS \&\f5enum\fP { \fIenum-list\fP } .br \&\f5enum\fP \fIidentifier\fP { \fIenum-list\fP } .br \&\f5enum\fP \fIidentifier\fP .RE .sp \&\fIenum-list\fP : .RS \&\fIenumerator\fP .br \&\fIenum-list\fP , \fIenumerator\fP .RE .sp \&\fIenumerator\fP : .RS \&\fIidentifier\fP .br \&\fIidentifier\fP = \fIconstant-expression\fP .RE .sp .RE The identifier has the same role as the structure tag in a struct specification. It names a particular enumeration type. .PP The identifiers in the enum-list are declared as constants, and may appear whenever constants are required. If no enumerators with .B = appear, then the values of the constants begin at 0 and increase by 1 as the declaration is read from left to right. An enumerator with .B = gives the associated identifier the value indicated; subsequent identifiers continue the progression from the assigned value. .PP Enumeration tags and constants must all be distinct, and, unlike structure tags and members, are drawn from the same set as ordinary identifiers. .PP Objects of a given enumeration type are regarded as having a type distinct from objects of all other types. .bp .SH Appendix B: C grammar in LL(1) form .PP The \fBbold-faced\fP and \fIitalicized\fP tokens represent terminal symbols. .vs 16 .nf \fBexternal definitions\fP program: external-definition* external-definition: ext-decl-specifiers [declarator [function | non-function] | '\fB;\fP'] | asm-statement ext-decl-specifiers: decl-specifiers? non-function: initializer? ['\fB,\fP' init-declarator]* '\fB;\fP' function: declaration* compound-statement .sp 1 \fBdeclarations\fP declaration: decl-specifiers init-declarator-list? '\fB;\fP' decl-specifiers: other-specifier+ [single-type-specifier other-specifier*]? | single-type-specifier other-specifier* other-specifier: \fBauto\fP | \fBstatic\fP | \fBextern\fP | \fBtypedef\fP | \fBregister\fP | \fBshort\fP | \fBlong\fP | \fBunsigned\fP type-specifier: decl-specifiers single-type-specifier: \fItype-identifier\fP | struct-or-union-specifier | enum-specifier init-declarator-list: init-declarator ['\fB,\fP' init-declarator]* init-declarator: declarator initializer? declarator: primary-declarator ['\fB(\fP' formal-list ? '\fB)\fP' | arrayer]* | '\fB*\fP' declarator primary-declarator: identifier | '\fB(\fP' declarator '\fB)\fP' arrayer: '\fB[\fP' constant-expression? '\fB]\fP' formal-list: formal ['\fB,\fP' formal]* formal: identifier enum-specifier: \fBenum\fP [enumerator-pack | identifier enumerator-pack?] enumerator-pack: '\fB{\fP' enumerator ['\fB,\fP' enumerator]* '\fB,\fP'? '\fB}\fP' enumerator: identifier ['\fB=\fP' constant-expression]? struct-or-union-specifier: [ \fBstruct\fP | \fBunion\fP] [ struct-declaration-pack | identifier struct-declaration-pack?] struct-declaration-pack: '\fB{\fP' struct-declaration+ '\fB}\fP' struct-declaration: type-specifier struct-declarator-list '\fB;\fP'? struct-declarator-list: struct-declarator ['\fB,\fP' struct-declarator]* struct-declarator: declarator bit-expression? | bit-expression bit-expression: '\fB:\fP' constant-expression initializer: '\fB=\fP'? initial-value cast: '\fB(\fP' type-specifier abstract-declarator '\fB)\fP' abstract-declarator: primary-abstract-declarator ['\fB(\fP' '\fB)\fP' | arrayer]* | '\fB*\fP' abstract-declarator primary-abstract-declarator: ['\fB(\fP' abstract-declarator '\fB)\fP']? .sp 1 \fBstatements\fP statement: expression-statement | label '\fB:\fP' statement | compound-statement | if-statement | while-statement | do-statement | for-statement | switch-statement | case-statement | default-statement | break-statement | continue-statement | return-statement | jump | '\fB;\fP' | asm-statement ; expression-statement: expression '\fB;\fP' label: identifier if-statement: \fBif\fP '\fB(\fP' expression '\fB)\fP' statement [\fBelse\fP statement]? while-statement: \fBwhile\fP '\fB(\fP' expression '\fB)\fP' statement do-statement: \fBdo\fP statement \fBwhile\fP '\fB(\fP' expression '\fB)\fP' '\fB;\fP' for-statement: \fBfor\fP '\fB(\fP' expression? '\fB;\fP' expression? '\fB;\fP' expression? '\fB)\fP' statement switch-statement: \fBswitch\fP '\fB(\fP' expression '\fB)\fP' statement case-statement: \fBcase\fP constant-expression '\fB:\fP' statement default-statement: \fBdefault\fP '\fB:\fP' statement break-statement: \fBbreak\fP '\fB;\fP' continue-statement: \fBcontinue\fP '\fB;\fP' return-statement: \fBreturn\fP expression? '\fB;\fP' jump: \fBgoto\fP identifier '\fB;\fP' compound-statement: '\fB{\fP' declaration* statement* '\fB}\fP' asm-statement: \fBasm\fP '\fB(\fP' \fIstring\fP '\fB)\fP' '\fB;\fP' .sp 1 \fBexpressions\fP initial-value: assignment-expression | initial-value-pack initial-value-pack: '\fB{\fP' initial-value-list '\fB}\fP' initial-value-list: initial-value ['\fB,\fP' initial-value]* '\fB,\fP'? primary: \fIidentifier\fP | constant | \fIstring\fP | '\fB(\fP' expression '\fB)\fP' secundary: primary [index-pack | parameter-pack | selection]* index-pack: '\fB[\fP' expression '\fB]\fP' parameter-pack: '\fB(\fP' parameter-list? '\fB)\fP' selection: ['\fB.\fP' | '\fB\->\fP'] identifier parameter-list: assignment-expression ['\fB,\fP' assignment-expression]* postfixed: secundary postop? unary: cast unary | postfixed | unop unary | size-of size-of: \fBsizeof\fP [cast | unary] binary-expression: unary [binop binary-expression]* conditional-expression: binary-expression ['\fB?\fP' expression '\fB:\fP' assignment-expression]? assignment-expression: conditional-expression [asgnop assignment-expression]? expression: assignment-expression ['\fB,\fP' assignment-expression]* unop: '\fB*\fP' | '\fB&\fP' | '\fB\-\fP' | '\fB!\fP' | '\fB~ \fP' | '\fB++\fP' | '\fB\-\-\fP' postop: '\fB++\fP' | '\fB\-\-\fP' multop: '\fB*\fP' | '\fB/\fP' | '\fB%\fP' addop: '\fB+\fP' | '\fB\-\fP' shiftop: '\fB<<\fP' | '\fB>>\fP' relop: '\fB<\fP' | '\fB>\fP' | '\fB<=\fP' | '\fB>=\fP' eqop: '\fB==\fP' | '\fB!=\fP' arithop: multop | addop | shiftop | '\fB&\fP' | '\fB^ \fP' | '\fB|\fP' binop: arithop | relop | eqop | '\fB&&\fP' | '\fB||\fP' asgnop: '\fB=\fP' | '\fB+\fP' '\fB=\fP' | '\fB\-\fP' '\fB=\fP' | '\fB*\fP' '\fB=\fP' | '\fB/\fP' '\fB=\fP' | '\fB%\fP' '\fB=\fP' | '\fB<<\fP' '\fB=\fP' | '\fB>>\fP' '\fB=\fP' | '\fB&\fP' '\fB=\fP' | '\fB^ \fP' '\fB=\fP' | '\fB|\fP' '\fB=\fP' | '\fB+=\fP' | '\fB\-=\fP' | '\fB*=\fP' | '\fB/=\fP' | '\fB%=\fP' | '\fB<<=\fP' | '\fB>>=\fP' | '\fB&=\fP' | '\fB^=\fP' | '\fB|=\fP' constant: \fIinteger\fP | \fIfloating\fP constant-expression: assignment-expression identifier: \fIidentifier\fP | \fItype-identifier\fP .fi