This is a list of all the routines in the Small C compiler along with their argument lists, their attributes and the function of the routine. Please note that in many cases the C keywords are written in upper case. This is not to imply that they may appear that way in a source program. In fact, the compiler currently requires that the keywords be lower case. addglb(sname,id,typ,value,stg) [cc3.c] sname [*CHAR] - identifier to add id [CHAR] - id class typ [CHAR] - type of variable value [INT] - value to be assigned stg [CHAR] - storage class The specified identifier is added to the global symbol table with the attributes specified by the other parameters. addloc(sname,id,typ,value,stg) [cc3.c] sname [*CHAR] - identifier to be added id [CHAR] - class of identifier typ [CHAR] - type of identifier value [INT] - value to be assigned stg [CHAR] - storage class of variable Add the specified identifier to the local symbol table with the attributes specified. addwhile(ptr) [cc3.c] ptr [INT[]] - array of while queue information The specified information is placed on top of the while queue. This queue maintains information on the currently active while and for loops. This array is organized as: U1EntryU0 U1FunctionU0 0 Pointer to extent of local symbol table 1 Stack pointer at start of block 2 Branch target for next iteration 4 Branch target outside of block Although referenced as a queue by the code, this is actually a stack. alpha(c) [cc3.c] c [CHAR] - character to test Returns 1 if c is an alphabetic (upper or lower case) or an underscore. an(c) [cc3.c] c [CHAR] - character to test Returns 1 if c is alphanumeric and 0 otherwise. ask() [cc1.c] Prompt user for parameters that control the execution. These include C text as comments, global definitions and starting label value callfunction(ptr) [cc3.c] ptr [*CHAR] - Pointer to symbol table entry for routine or 0. Called to parse a function invocation. If ptr is not 0 then a named routine is being called, else, the routine address has already been determined and is in the primary register. The list of actual parameters is parsed and code is generated for each expression and its value is pushed onto the stack. The call is generated and code is emitted to clean up the space on the stack used by the parameters. ch() [cc3.c] Return the current character from the input line. The pointer into the line is not changed so ch can be called a number of times to examine the same character. closeout() [cc1.c] Close the current output file, if one is open. compound() [cc2.c] Parses a compound statement, that is {statement-list}. It ensures that the the {} are properly balanced. This routine will definitely be recursively invoked. declext() [cc1.c] Parses the EXTERN { CHAR | INT } var-list ; statement when it occurs outside of a routine definition. It calls upon declglb to do the work. decllex() [cc1.c] Parses the EXTERN { CHAR | INT } var-list ; statement when it occurs within a routine definition. It calls upon declloc to do the work. declglb(typ,stg) [cc1.c] typ [INT] - Data type of variables to be defined. stg [CHAR] - Storage class of variables to be defined. Handles parsing the list of identifiers in the current type definition statement. It parses the var-list mentioned in decllex and declext. The identifiers are entered in the global symbol table with the data type and storage class specified. declloc(typ,stg) [cc1.c] typ [INT] - Data type of variables being defined. stg [CHAR} - Storage class of the variables Analagous to declglb, except the identifiers are entered into the local symbol table. This symbol table is purged at the end of each routine. delwhile() [cc3.c] Delete the top entry from the while queue. doasm() [cc2.c] Handle the #asm statement. All text up to the next occurence of #endasm will be copied to the object file without modification. This permits the inclusion of handwritten assembly language at the programmers discretion. He must worry about variables, stacks, and all the rest to keep the C environment intact. dobreak() [cc2.c] Parse and generate code for the BREAK statement to leave the nearest encompassing (lexically) FOR or WHILE statement. The proper label for the branch instruction is determined from the while queue. *** The BREAK from a SWITCH is not yet implemented *** since the SWITCH is not yet implemented. docont() [cc2.c] Parse the CONTINUE statement. This will cause a branch to the next iteration of the FOR or WHILE statement in which it appears. The proper label for the branch statement is determine from the while queue. dofor() [cc2.c] Parse the FOR(expr; expr; expr) {} statement. The necessary entries are made in the while queue to ensure that the BREAK and CONTINUE statements work correctly. The full syntax of the FOR is accepted, including null expressions. Optimal code is not generated in these cases. doif() [cc2.c] Parses the IF(...) statement along with the optional ELSE clause. doinclude() [cc1.c] Opens the file specified in the #include statement. It is assumed that this is the only thing on the line otherwise the open may fail. Further, the standard C syntax of "filename" and are not handled. doreturn() [cc2.c] Parse and genrate code for the RETURN expr; statement. Code is generated to clean up the stack and return to the calling routine. dowhile() [cc2.c] Parse and generate code for the while statement. This also adds the necessary information to the while queue so that the BREAK and CONTINUE statements will work correctly. dumpglbs() [cc1.c] Dump global variables to the object file. This handles all those variables that need to be defined and also generates external statements for those that are declared as such. *** This is not complete as of 18 Jan 81 pending *** more information on the MASSM assembler and *** linker. Currently a comment is generated so *** no assembly errors will occur. dumplits() [cc1.c] Defines the literals that the compiler generated for strings and such. These are formatted to avoid long lines. endst() [cc3.c] This skips over any blanks or tabs and returns TRUE if we are at the end of a line or at the end of a statement (;). errorsummary() [cc1.c] Generates an error summary report to the currently selected output file. findglb(sname) [cc3.c] sname [*CHAR] - identifier to be looked up The global symbol table is searched looking for the specified name. If found, the address of the entry in the symbol table is returned. Otherwise 0 is returned. findlog(sname) [cc3.c] sname [*CHAR] - identifier to be looked up The local symbol table is searched for the specified identifier. If found, the address of the symbol table entry is returned. Otherwise 0 is returned. There are only 2 symbol tables used by the compiler, the local and the global. Since routines cannot be defined within routines this is sufficient. gch() [cc3.c] Return the next character in the current input line updating the index. Thus, each time gch is called, the next character in the line will be returned. The line is not advanced when the last character is read. getarg(t) [cc2.c] t [INT] - type of argument being defined. getarg is called to parse the type declaration of parameters to routines. The identifiers are entered into the local symbol table and their stack offset is determined. *** Please note that the argument declarations must *** appear in the same order as they appear in the *** parameter list and the number must match exactly. *** Their appearance in the parameter list serves only *** to determine the number of parameters; their order *** and address is determined by the declaration. *** This is not required by the standard C syntax. getlabel() [cc3.c] Return the next internal label for use. This is simply an integer that is increment upon every reference to getlabel. The actual label is built by converting this value to ASCII and prefixing with "CC" to make it a valid label for the assembler. illname() [cc3.c] Issue the "illegal name" error message and clean up to a point where we can continue parsing (via junk). inbyte() [cc3.c] Reads the next line from the current input file and preprocesses it. When processed, the first character of the line is returned. inchar() [cc3.c] Returns the next character from the input file. If there are any characters remaining in the current line, the next one is returned (see gch). If not, a new line is read (via inline) and the first character is returned. This differs from inbyte in that inchar does U1notU0 preprocess the line. inline() [cc3.c] Reads the next line from the current input file. Tabs and form feeds are converted to blanks. Should end of file occur, the input file is closed and if processing an include file, the original input is restored. junk() [cc3.c] Read past the current token in the input stream. If the current character is an alphanumeric, read until we get to a non alphanumeric. If the current character is not an alphanumeric, read until we get to one. This routine is called when an error occurs. The goal is to get back into synch with something we probably can parse. keepch(c) [cc4.c] c [CHAR] - character to be kept The specified character is placed at the current location in the macro line??? kill() [cc3.c] Pitch the current input line. That is the current line is set to the empty or null line. multidef(sname) [cc3.c] sname [*CHAR] - identifer Issue message indicating that the "sname" is multiply defined. needbrack(str) [cc3.c] str [*CHAR] - Pointer to string defining bracket required. If the next token in the input stream is not the specified bracket, an appropriate error message is generated. This is typically called with ")" and "}". needlval() [cc3.c] Issues the error message "must be L-value". needsub() [cc2.c] Parses the size of an array. That is the constant expression that occurs between the square brackets. At present this constant expression is limited to a constant or null string ([]). The value returned is the value of the constant specified, or 0 if the size were null. newfunc() [cc2.c] Parses the definition of a routine. This includes the parameter list, parameter definition and body. *** At present, the function definition cannot *** be typed. That is, no CHAR or INT or STATIC *** keyword can appear without confusing the *** parse. nch() [cc3.c] Return the next character from the input line. If the end of line has been reached, 0 is returned. Note that the pointer into the line is not modified. This means that nch can be used to look ahead a single character. ns() [cc2.c] Ensures that the next token in the input stream is a semicolon. If not, an error message is generated, but the parse continues. numeric(c) [cc3.c] c [CHAR] - character to test Returns 1 if c is a numeric (0 ... 9) and 0 otherwise. openin() [cc1.c] Prompts the user for the name of the next input file and opens it. If the file name were null, end of file is indicated. openout() [cc1.c] Prompts the user for the name of the output object file and opens it. parse() [cc1.c] Parses the top level module statements. These include data definitions such as EXTERN and CHAR and INT along with the definitions of functions. *** At present STATICs are not parsed, nor are *** functions allowed to be defined with attributes *** applied to their return values. pl(str) [cc3.c] str [*CHAR] - string to print Prints an end of line followed by the string (null delimited) to the terminal. printlabel(label) [cc3.c] label [INT] - integer value of internal label The integer is converted to ASCII prefixed with the string "CC" to form a valid label. This string is written to the current output file. readwhile() [cc3.c] Return a pointer to the top entry on the while queue. Zero is returned if the queue is empty in addition to issuing an error message. statement() [cc2.c] statement is called to parse a statement in the language. It is keyword driven off of the next token in the input stream. If no keyword is found, an expression is assumed. symname(sname) [cc3.c] sname [*CHAR] - identifier from input stream Tests the next identifier from the input stream to ensure that it is a valid identifier. If so, 1 is returned as the value of the routine and the identifier is returned in sname. If the next token is not a valid identifier 0 is returned and sname is not modified.