# enter_id_decl --- given a pointer to an identifer name, a # a storage class, mode, and parameter list, # enter an identifier in the symbol table subroutine enter_id_decl (id, mode, xsc, params, arg, body) pointer id # text pointer in, pointer to SYM entry out pointer mode # pointer to the mode of the identifier integer xsc # storage class of the identifier pointer params # for functions: parameter list in declaration; # LAMBDA for function decls with body integer arg # YES when declaration a formal parameter integer body # YES when declaring a function with a body include "c1_com.r.i" integer sc, obj integer findsym, compare_mode, new_obj, new_sym, old_sym pointer q, np pointer makesym untyped info (IDSIZE) if (id == LAMBDA) # in case of someone else's error return for (q = params; q ~= LAMBDA; q = PARAMNEXT (q)) if (PARAMTEXT (q) ~= LAMBDA) { ERROR_SYMBOL (Mem (PARAMTEXT (q))) SYNERR ("Named parameters not allowed in this declaration"p) } sc = xsc np = id if (arg == YES) { if (sc ~= DEFAULT_SC && sc ~= REGISTER_SC) { ERROR_SYMBOL (Mem (id)) SYNERR ("Illegal storage class for a parameter"p) sc = DEFAULT_SC } if (MODETYPE (mode) == FUNCTION_MODE) { ERROR_SYMBOL (Mem (id)) SYNERR ("Functions cannot be passed as parameters"p) call create_mode (mode, POINTER_MODE, 0) } call modify_param_mode (mode) } if (MODETYPE (mode) == FUNCTION_MODE) { mode = MODEPARENT (mode) call modify_param_mode (mode) call create_mode (mode, FUNCTION_MODE, 0) } if (sc == TYPEDEF_SC) { if (findsym (Mem (np), q, IDCLASS) == YES && SYMLL (q) == Ll) SYNERR ("Identifier defined twice"p) id = new_sym (Mem (np), mode, sc, arg, Ll, 0, YES) } else if (Ll == 1) { # It's an external definition if (MODETYPE (mode) == FUNCTION_MODE && body == YES) { if (sc == REGISTER_SC || sc == AUTO_SC || sc == EXTERN_SC) { ERROR_SYMBOL (Mem (np)) SYNERR ("Invalid storage class on a function definition"p) sc = DEFAULT_SC } if (findsym (Mem (np), q, IDCLASS) == NO) id = new_sym (Mem (np), mode, sc, arg, Ll, new_obj (0), YES) else if (SYMISDEF (q) == YES) { ERROR_SYMBOL (Mem (np)) SYNERR ("Function defined twice in this file"p) id = old_sym (q, sc, mode, YES) } else { # Function is previously declared if (compare_mode (mode, SYMMODE (q)) == NO) WARNING ("Declaration conflicts with previous declaration"p) if (sc == DEFAULT_SC) # use the previous declaration sc = SYMSC (q) else if (SYMSC (q) == EXTERN_SC) # sc must be STATIC WARNING ("EXTERN function may not be redeclared STATIC"p) if (SYMOBJ (q) == 0) SYMOBJ (q) = new_obj (0) id = old_sym (q, sc, mode, YES) } } else if (MODETYPE (mode) == FUNCTION_MODE) { if (sc == REGISTER_SC || sc == AUTO_SC || sc == STATIC_SC) { ERROR_SYMBOL (Mem (np)) SYNERR ("Invalid storage class on a function declaration"p) sc = DEFAULT_SC } if (findsym (Mem (np), q, IDCLASS) == NO) { id = new_sym (Mem (np), mode, sc, arg, Ll, 0, NO) SYMPLIST (id) = params params = LAMBDA } else if (SYMISDEF (q) == YES) { ERROR_SYMBOL (Mem (np)) SYNERR ("Function defined twice in this file"p) id = old_sym (q, sc, mode, YES) } else { # Function is previously declared if (compare_mode (mode, SYMMODE (q)) == NO) WARNING ("Declaration conflicts with previous declaration"p) if (sc == DEFAULT_SC) sc = SYMSC (q) id = old_sym (q, sc, mode, SYMISDEF (q)) if (SYMPLIST (id) == LAMBDA) { SYMPLIST (id) = params params = LAMBDA } } } else { # It's not a function if (sc == REGISTER_SC || sc == AUTO_SC) { ERROR_SYMBOL (Mem (np)) WARNING ("Invalid storage class on an external declaration"p) sc = DEFAULT_SC } if (findsym (Mem (np), q, IDCLASS) == NO) if (sc == EXTERN_SC) id = new_sym (Mem (np), mode, sc, arg, Ll, 0, NO) else if (sc == STATIC_SC) # kludge so we can remember if obj was static & not emit # ENT for it - only when static is redecl extern id = new_sym (Mem (np), mode, sc, arg, Ll, new_obj (0), STATIC_SC) else id = new_sym (Mem (np), mode, sc, arg, Ll, new_obj (0), YES) else { # Identifier previously declared at Ll 1 if (compare_mode (mode, SYMMODE (q)) == NO) { ERROR_SYMBOL (Mem (np)) WARNING ("Declaration conflicts with previous declaration"p) } if (sc == EXTERN_SC) { # ignore redefinition as EXTERN - won't define # more storage if 'is_stored' thinks sc = EXTERN # if the old object was static, then SYMISDEF = # STATIC_SC, otherwise it's YES - & we keep track # of redefinitions id = old_sym (q, sc, mode, SYMISDEF (q)) } else { # new symbol not EXTERN # if old symbol is EXTERN, new sc supercedes it; # otherwise, squawk & redefine old symbol if ((SYMSC (q) ~= EXTERN_SC) || # if sc = EXTERN && the symbol is already defined, # then we can't allocate more space for it - for # really bizarre things like # # int gorf; # extern gorf; # static gorf; (SYMSC (q) == EXTERN_SC && SYMISDEF (q) ~= NO)) { ERROR_SYMBOL (Mem (np)) SYNERR ("Identifier defined twice"p) } if (SYMOBJ (q) == 0) # take care of undef EXTERN SYMOBJ (q) = new_obj (0) if (sc == STATIC_SC) id = old_sym (q, sc, mode, STATIC_SC) # you never know else id = old_sym (q, sc, mode, YES) # use most recent definition } } } } else { # Ll > 1 It's an internal definition if (MODETYPE (mode) == FUNCTION_MODE) { if (sc == REGISTER_SC || sc == AUTO_SC || sc == STATIC_SC) { ERROR_SYMBOL (Mem (np)) SYNERR ("Invalid storage class on a function declaration"p) sc = DEFAULT_SC } if (findsym (Mem (np), q, IDCLASS) == NO) { id = new_sym (Mem (np), mode, sc, arg, 1, 0, NO) id = new_sym (Mem (np), mode, sc, arg, Ll, 0, NO) SYMPLIST (id) = params params = LAMBDA } else if (SYMLL (q) == Ll) { ERROR_SYMBOL (Mem (np)) SYNERR ("Function defined twice"p) } else if (findsym (Mem (np), q, IDCLASS, 1) == YES) { if (compare_mode (mode, SYMMODE (q)) == NO) WARNING ("Declaration conflicts with previous declaration"p) if (sc == DEFAULT_SC) sc = SYMSC (q) else if (SYMSC (q) == STATIC_SC) WARNING ("STATIC function may not be redeclared EXTERN"p) id = old_sym (q, sc, mode, SYMISDEF (q)) if (SYMPLIST (id) == LAMBDA) { SYMPLIST (id) = params params = LAMBDA } } else # Function is declared at another LL, but not 1 FATAL ("Function declared at level other than 1"p) } else { # It's not a function if (sc == DEFAULT_SC) # put it on the stack sc = AUTO_SC if (findsym (Mem (np), q, IDCLASS) == NO) { if (sc == EXTERN_SC) { id = new_sym (Mem (np), mode, sc, arg, 1, 0, NO) id = new_sym (Mem (np), mode, sc, arg, Ll, 0, NO) } else id = new_sym (Mem (np), mode, sc, arg, Ll, new_obj (0), NO) } else if (SYMLL (q) == Ll) { ERROR_SYMBOL (Mem (np)) SYNERR ("Identifier defined twice at current level"p) } else if (sc == EXTERN_SC && findsym (Mem (np), q, IDCLASS, 1) == YES) { # defined at lexical level 1 - don't need new def if (compare_mode (mode, SYMMODE (q)) == NO) { ERROR_SYMBOL (Mem (np)) WARNING ("Declaration conflicts with previous declaration"p) } # I don't know why this works! # id = old_sym (q, sc, mode, SYMISDEF (q)) } else { # Identifier is declared at another LL if (sc == EXTERN_SC) { # it's either a forward definition or a *real* # external (defined outside of this file) id = new_sym (Mem (np), mode, sc, arg, 1, 0, NO) id = new_sym (Mem (np), mode, sc, arg, Ll, 0, NO) } else id = new_sym (Mem (np), mode, sc, arg, Ll, new_obj (0), NO) } } } call dsfree (np) # free the saved text space while (params ~= LAMBDA) { # free the parameter list if it wasn't used if (PARAMTEXT (params) ~= LAMBDA) call dsfree (PARAMTEXT (params)) q = PARAMNEXT (params) call dsfree (params) params = q } return end # enter_sm_decl --- given a pointer to an identifer name, a mode, # and parameter list, enter a stucture member # into the symbol table subroutine enter_sm_decl (id, mode, params, loc) pointer id, mode, params longint loc include "c1_com.r.i" integer findsym, compare_mode pointer q pointer makesym longint get_long untyped info (IDSIZE) if (id == LAMBDA) # in case of someone else's error return if (MODETYPE (mode) == FUNCTION_MODE) { SYNERR ("Functions cannot be part of a 'struct'"p) call create_mode (mode, POINTER_MODE, 0) } if (params ~= LAMBDA) { SYNERR ("Parameters not allowed in struct member"p) while (params ~= LAMBDA) { q = PARAMNEXT (params) call dsfree (params) params = q } } if (findsym (Mem (id), q, SMCLASS) == YES && SYMLL (q) == Ll) { select (SYMTYPE (q)) when (STSYMTYPE) { ERROR_SYMBOL (Mem (id)) SYNERR ("Identifier already defined as struct tag"p) } when (SMSYMTYPE) if (get_long (loc) ~= get_long (SYMOFFS (q)) || compare_mode (mode, SYMMODE (q)) == NO) { ERROR_SYMBOL (Mem (id)) SYNERR ("Struct member conflicts with previous definition"p) } call dsfree (id) id = q return } q = id id = makesym (Mem (id), SMSYMTYPE, Ll) call dsfree (q) # free the saved text space SYMMODE (id) = mode SYMPARAM (id) = -1 SYMSC (id) = DEFAULT_SC SYMOBJ (id) = 0 call put_long (SYMOFFS (id), loc) return end # declare_label --- declare the current symbol as a label subroutine declare_label (flag) integer flag include "c1_com.r.i" integer findsym, makesym, new_obj if (findsym (Symtext, Symptr, IDCLASS) == NO || SYMLL (Symptr) <= 1) { Symptr = makesym (Symtext, IDSYMTYPE, 2) SYMSC (Symptr) = STATIC_SC SYMMODE (Symptr) = Label_mode_ptr SYMPARAM (Symptr) = flag SYMOBJ (Symptr) = new_obj (0) return } if (SYMMODE (Symptr) ~= Label_mode_ptr) { SYNERR ("Label already declared but not as label"p) return } if (SYMPARAM (Symptr) == YES && flag == YES) SYNERR ("Label already declared"p) if (flag == YES) SYMPARAM (Symptr) = YES return end # check_declaration --- check if current symbol has been declared; # if not, create a dummy symbol subroutine check_declaration (class) integer class include "c1_com.r.i" integer findsym, new_obj pointer q if (findsym (Symtext, Symptr, class) == NO) { SYNERR ("Identifier not declared"p) call gen_int (0) } else if (SYMTYPE (Symptr) == COSYMTYPE) call gen_int (SYMOBJ (Symptr)) else if (SYMTYPE (Symptr) ~= IDSYMTYPE && SYMTYPE (Symptr) ~= SMSYMTYPE) { SYNERR ("Identifier is not a variable"p) call gen_int (0) } else { if (SYMTYPE (Symptr) == IDSYMTYPE && SYMOBJ (Symptr) == 0) { # Add an object number on reference SYMOBJ (Symptr) = new_obj (0) if (SYMLL (Symptr) > 1 && findsym (Symtext, q, class, 1) == YES && SYMOBJ (q) == 0) SYMOBJ (q) = SYMOBJ (Symptr) DBG (42, call print (ERROUT, "check_declaration: '*s' first ref*n"s, DB Symtext)) } call gen_opnd (Symptr) } return end # clean_up_ll --- check for undefined symbols and labels subroutine clean_up_ll include "c1_com.r.i" pointer p, q pointer accesssym character str (MAXTOK) p = LAMBDA for (q = accesssym (Ll, str, p, IDCLASS); q ~= LAMBDA; q = accesssym (Ll, str, p, IDCLASS)) { DBG (42, if (SYMOBJ (q) == 0) { DB call print (ERROUT, "Unref: '*s' "s, str) DB call dump_sym_entry (q); call print (ERROUT, "*n"s)}) if (SYMMODE (q) == Label_mode_ptr && SYMPARAM (q) == NO) { ERROR_SYMBOL (str) SYNERR ("Undefined label"p) } if (SYMPARAM (q) == 0) { ERROR_SYMBOL (str) SYNERR ("Declared as parameter but not in parameter list"p) } if (SYMTYPE (q) == ENSYMTYPE && MODESMLIST (SYMMODE (q)) == LAMBDA) { ERROR_SYMBOL (str) SYNERR ("'Enum' referenced but not defined"p) } } p = LAMBDA for (q = accesssym (Ll, str, p, SMCLASS); q ~= LAMBDA; q = accesssym (Ll, str, p, SMCLASS)) { if (SYMTYPE (q) == STSYMTYPE && MODESMLIST (SYMMODE (q)) == LAMBDA) { ERROR_SYMBOL (str) SYNERR ("'Struct' referenced but not defined"p) } } return end # check_function_declaration --- handle default function declarations) subroutine check_function_declaration include "c1_com.r.i" integer findsym, new_obj pointer q pointer mode pointer sdupl mode = Int_mode_ptr call create_mode (mode, FUNCTION_MODE, 0) if (findsym (Symtext, Symptr, IDCLASS) == NO) { Symptr = sdupl (Symtext) call enter_id_decl (Symptr, mode, EXTERN_SC, LAMBDA, NO, NO) } else if (MODETYPE (SYMMODE (Symptr)) == FUNCTION_MODE) ; else if (SYMLL (Symptr) == Ll) SYNERR ("Usage conflicts with previous declaration"p) else { Symptr = sdupl (Symtext) call enter_id_decl (Symptr, mode, EXTERN_SC, LAMBDA, NO, NO) } if (SYMOBJ (Symptr) == 0) { # Add an object number on reference SYMOBJ (Symptr) = new_obj (0) if (SYMLL (Symptr) > 1 && findsym (Symtext, q, IDCLASS, 1) == YES && SYMOBJ (q) == 0) SYMOBJ (q) = SYMOBJ (Symptr) DBG (42, call print (ERROUT, "check_function_declaration: '*s' first ref*n"s, DB Symtext)) } call gen_opnd (Symptr) return end # allocate_storage --- perform storage allocation subroutine allocate_storage (id) pointer id include "c1_com.r.i" integer is_stored longint sz longint sizeof_mode if (is_stored (id) == NO) return sz = sizeof_mode (SYMMODE (id)) if (sz == 0) SYNERR ("Data object may not have zero size"p) else if (sz >= (intl (MAXUNSIGNED) + 1) * 8) SYNERR ("Data object may not be larger than 65535 words"p) DBG (29, call print (ERROUT, "in allocate_storage: id=*i sz=*l l=*i*n"s, DB id, sz, SYMOBJ (id))) return end # alloc_struct --- increment the size of a structure or union by the # specified size subroutine alloc_struct (mp, len) pointer mp longint len include "c1_com.r.i" longint get_long if (MODETYPE (mp) == STRUCT_MODE) call put_long (MODELEN (mp), get_long (MODELEN (mp)) + len) else if (get_long (MODELEN (mp)) < len) call put_long (MODELEN (mp), len) return end # wsize --- compute the size in words given the size in bits integer function wsize (b) longint b include "c1_com.r.i" wsize = (b + 15) / 16 DBG (38, call print (ERROUT, "in wsize: b=*l, w=*i*n"s, b, wsize)) return end # alloc_temp --- allocate a temporary variable pointer function alloc_temp (mp) pointer mp include "c1_com.r.i" integer obj integer new_obj character str (20) pointer p pointer new_sym obj = new_obj (0) call encode (str, 20, "#temp*i"s, obj) p = new_sym (str, mp, AUTO_SC, NO, Ll, obj, NO) call out_var (p) call out_oper (NULL_OP) call out_size (SYMMODE (p)) return (p) end