/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 27-Nov-85 | [1.16] Created * 28-Nov-85 | [1.37] Print symbols out unsigned * 4-Dec-85 | [1.108] Added check_sym * 4-Dec-85 | [1.121] Sort symbol table; do not print out literals * 24-Nov-91 | [1.177] memory.h => automem.h * 24-Nov-91 | [1.177] converted to C6.0 * 24-Nov-91 | [1.177] mach.h => machmem.h * 25-Nov-91 | [1.185] include \r in output to listing file (it is in * | binary mode for reasons obscure to me...) * 25-Nov-91 | [1.188] set X field to suppress dumping X symbols * 25-Nov-91 | [1.188] handle zone setting for literals of form +000 * 26-Nov-91 | [1.193] fixed bug in enter which did NULL pointer * | asssignment * 26-Nov-91 | [1.210] better multiply-defined symbol handling * 26-Nov-91 | [1.212] added start of litpoolmark structure so that * | multiple LTORGs have separate literal pools * 3-Dec-91 | [1.220] use C_bits to tag valid memory locs * 4-Dec-91 | [1.233] added proper LTORG resolution to literals in pool * 5-Dec-91 | [1.244] added heap scan *****************************************************************************/ /* Symbol table package */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define magic 0x07FE int protect = magic; /* watch for storage damage */ ste * symroot = NULL; ste * symtail = NULL; #define sym_debug false extern unsigned litpool; extern int dot; extern int star; extern unsigned maxdot; extern int sdot; extern boolean checksym; void sort_syms(void); extern FILE * listing; extern boolean debug; extern boolean debug_sym; #if OBSOLETE typedef struct litpoolmark { int thisline; /* line associated with LTORG/END */ ste * start; /* starting symbol for pass 2 resolution */ struct litpoolmark * next; /* next litpool, or NULL */ } litpoolmark; litpoolmark * ltorglist; #endif /**************************************************************************** * muldef * Inputs: * ste * sy: Symbol which is multiply-defined * char * msg: Message to issue, or NULL if default message only * Result: void * * Effect: * Issues a multiply-defined symbol message and sets sy->muldef true ****************************************************************************/ void muldef(ste * sy, char * msg) { char msgbuf[200]; sy->muldef = true; sprintf(msgbuf,"Multiply-defined symbol '%s'",sy->name); if(msg != NULL) { /* has msg */ strcat(msgbuf," "); strcat(msgbuf,msg); } /* has msg */ error(err_multiply_defined,msgbuf); } /**************************************************************************** * prsym * Inputs: * ste * sy: Symbol table entry * Effect: * Prints out the symbol table entry ****************************************************************************/ void prsym(ste * sy) { printf("0x%x: {\n",sy); printf(" next: 0x%x\n", sy->next); printf(" prev: 0x%x\n", sy->prev); printf(" name: 0x%x \"%s\"\n",sy->name,sy->name); printf(" val: %u\n",sy->val); printf(" lit: %s\n",(sy->lit ? "true" : "false")); if(sy->lit) { /* lit stuff */ printf(" resolved: %s\n",(sy->resolved ? "true" : "false")); printf(" lit_dumped: %s\n",(sy->lit_dumped ? "true" : "false")); printf(" line %d\n",sy->line); } /* lit stuff */ printf(" };\n"); } /**************************************************************************** * check_sym * Effect: * Checks for symbol table clobber ****************************************************************************/ void check_sym(char * msg) { ste * sym; struct _heapinfo hinfo; int heapstatus; #if 1 if(_nullcheck()) { /* failure */ error(err_label,"***NULL POINTER CLOBBER***"); printf("%s\n",msg); } /* failure */ #endif if(!debug_sym) return; if(protect != magic) { /* the magic goes away */ error(err_label,"***SYMBOL TABLE DAMAGED....protect word gone***"); printf("%s\n",msg); } /* the magic goes away */ if(symroot == NULL) { /* dead */ error(err_label,"***SYMBOL TABLE DAMAGED...symroot == NULL"); printf("%s\n",msg); return; } /* dead */ sym = symroot; while(sym != NULL) { /* scan */ if(sym->next != NULL && sym->next->prev != sym) { /* dead next */ error(err_label,"***SYMBOL TABLE DAMAGED...bad fwdpointer***"); printf("0x%x: next->0x%x, prev->0x%x, name=\"%s\", val=%d\n", sym,sym->next,sym->prev,sym->name,sym->val); printf(" next->prev = 0x%x != sym\n",sym->next->prev); printf("%s\n",msg); { /* dump table */ ste * sye; sye = symroot; while(sye != NULL) { /* dump it */ prsym(sye); if(sye->next != NULL && sye->next->prev != sye) break; sye = sye -> next; } /* dump it */ } /* dump table */ return; } /* dead next */ if(sym->prev != NULL && sym->prev->next != sym) { /* dead next */ error(err_label,"***SYMBOL TABLE DAMAGED...bad backpointer***"); printf("0x%x: next->0x%x, prev->0x%x, name=\"%s\", val=%d\n", sym,sym->next,sym->prev,sym->name,sym->val); printf(" prev->next = 0x%x != sym\n",sym->prev->next); printf("%s\n",msg); return; } /* dead next */ sym = sym->next; } /* scan */ hinfo._pentry = NULL; while ( (heapstatus = _heapwalk(&hinfo)) == _HEAPOK) { /* scan heap */ } /* scan heap */ switch(heapstatus) { /* decode status */ case _HEAPEMPTY: case _HEAPEND: break; case _HEAPBADPTR: printf("ERROR - bad heap pointer %p (%s)\n", hinfo._pentry, msg); break; case _HEAPBADBEGIN: printf("ERROR - bad heap begin (%s)\n",msg); break; case _HEAPBADNODE: printf("ERROR - bad heap node (%s)\n",msg); break; } /* decode status */ } /**************************************************************************** * enter * Inputs: * char * sym: Pointer to (NUL-terminated) label name string (in heap) * unsigned val: Value to attach to it * Result: ste * * NULL if symbol duplicated * non-NULL is symbol table entry * Effect: * Enters the symbol in the symbol table ****************************************************************************/ ste * enter(char * sym,unsigned val) { int i; ste * sy; if(checksym) { /* watch out for bogus resolution */ ste * this; this = symtail; while(this!=NULL) { /* search */ if(strcmp(this->name,sym) == 0) { /* same symbol */ if(!this->lit || !this->resolved) { /* check */ if(this->val == val) { /* redundant */ char msg[80]; sprintf(msg,"Redundant definition of '%s'==%d", sym,this->val); warning(err_label,msg); return this; } /* redundant */ else { /* duplicate */ char msg[80]; sprintf(msg,"Attempt to redefine '%s'==%d to %d", sym,this->val,val); error(err_label,msg); return NULL; } /* duplicate */ } /* check */ } /* same symbol */ this = this -> prev; } /* search */ } /* watch out for bogus resolution */ /* If we get here, we didn't find it; create an entry */ sy = (ste *) malloc(sizeof(ste)); sy->name = sym; sy->val = val; sy->next = symroot; sy->prev = NULL; if(sy->next != NULL) sy->next->prev = sy; sy->lit = false; /* Assume not literal */ sy->resolved = false; sy->lit_dumped = false; sy->var_size = false; sy->X = false; sy->muldef = false; sy->len = 0; symroot = sy; if(symtail == NULL) symtail = symroot; if(debug || debug_sym) { /* new value */ printf("enter: new symbol \"%s\" entered @0x%x, value %s\n", sym,sy,valstr(val)); } /* new value */ return sy; } /**************************************************************************** * sym_lookup * Inputs: * char * sym: Symbol to look up * int line: Line number we are currently at * Result: ste * * NULL if not found * otherwise, ste of symbol * Notes: * The symbol table is a linked list (yep, slow; for fast indexing * build an ancillary hash table, the fifoness is key to this algorithm) * * A literal marked as 'resolved' is resolved. Consider the program * 1 mlc @foo@,bar * 2 mlc @foo@,thud * 3 ltorg * 4 mlc @foo@,bar * 5 mlc @foo@,thud * 6 end whever * * The symbol values will be * ... @foo@[6] ... @foo@[3] * * on pass 1, the lookup on line 1 fails, and an 'enter' operation * will be done to put @foo@ into the symbol table. Its resolved * property is 'false'. The lookup on line 2 succeeds, so the * resolution is to the same literal. The LTORG on line 3 resolves * the literals and sets the resolved property to 'true'. The pass 1 * lookup for @foo@ on line 4 detects that 4 is > @foo@->line, and no * other @foo@ is found, so it returns NULL. 'enter' is called and * places a new @foo@, which has an as-yet-unresolved line and resolved * of false. The @foo@ on line 5 detects a resolved property on the * first @foo@, but the next one it finds is unresolved, so it returns * a pointer to it. * * on pass 2, two lookups will be done for @foo@ on lines 1 and 2. * The list is searched in reverse order, and the first @foo@ whose * line is > 1 or > 2 will be found. However, when the @foo@ on * line 4 is searched for, the @foo@ on line 3 is < 4 and it will be * ignored. This guarantees proper literal pool behavior. * ****************************************************************************/ static ste * sym_lookup(char * sym,int line) { ste * this; int i; this = symtail; while(this!=NULL) { /* search */ if(strcmp(this->name,sym) == 0) { /* name matched */ /* Names are same. Handle literal resolution */ if(this->resolved) { /* matching resolved literal */ /* Either we are in pass1 following a ltorg, or we are in pass2. In either case, if the resolution line event of the literal is less than our current line, it is in a previous literal pool */ if(this->line < line) goto next; } /* matching resolved literal */ if(debug || debug_sym) { /* new value */ printf("lookup: symbol \"%s\" found @0x%x, value %s\n", sym,this,valstr(this->val)); } /* new value */ return this; } /* name matched */ next: this = this -> prev; } /* search */ return NULL; } /**************************************************************************** * lookup * Inputs: * char * name: Name to look up * Result: ste * * Symbol table entry, or NULL if not found * Notes: * This is to simplify the interface; we need 'lit_lookup' which * handles the literals, and 'lookup' for names only. The generic * procedure is 'sym_lookup', and this is an interface to it ****************************************************************************/ ste * lookup(char * name) { return sym_lookup(name,0); } /**************************************************************************** * lit_lookup * Inputs: * char * name: name (literal value) to look up * int line: line on which it is found * Result: ste * * entry for this literal * NULL if not found or unresolved in current pool * (see sym_lookup for details of literal resolution) ****************************************************************************/ ste * lit_lookup(char * name, int line) { return sym_lookup(name,line); } /**************************************************************************** * ixname * Inputs: * unsigned val: Value which has indexed bits * Result: char * * Print string of index register ****************************************************************************/ char * ixname(unsigned val) { int i; static char name[10]; i = ixreg(val); if(i == 0) return ""; sprintf(name,"+X%d",i); return name; } /**************************************************************************** * list_syms * Effect: * Prints a (sorted?) symbol table on the listing stream ****************************************************************************/ void list_syms() { ste * sy; if(debug_sym) { /* debug list */ printf("Unsorted symbol table\n"); sy = symroot; while(sy != NULL) { /* scan and print */ prsym(sy); sy = sy->next; } /* scan and print */ } /* debug list */ pageheading(); sort_syms(); if(debug_sym) { /* debug sorted list */ printf("Sorted symbol table\n"); sy = symroot; while(sy != NULL) { /* scan and print */ prsym(sy); sy = sy->next; } /* scan and print */ } /* debug list */ sy = symroot; while(sy!=NULL) { /* list one */ if(!sy->lit && !sy->X) { check_heading(); fprintf(listing,"%c %-8s %05u%s\r\n", (sy->muldef ? 'M' : ' '), sy->name, unindexed(sy->val), ixname(sy->val) ); } sy = sy -> next; } /* list one */ } /**************************************************************************** * resolve_lits * Inputs: * int thisline: Line number which activated resolution * char * msg: Message to print in debug mode * Effect: * Resolves all outstanding literals relative to the litpool offset ****************************************************************************/ void resolve_lits(int thisline,char * msg) { ste * sy; unsigned litloc; if(debug) printf("Resolving literals (%s): litpool = %d\n",msg,litpool); sy = symroot; if(sy==NULL) return; while(sy->next != NULL) sy = sy->next; /* sy now points to the end of the symbol table. Walk backward, resolving literals */ while(sy != NULL) { /* resolve scan */ if(debug) printf("sy=0x%x(\"%s\" %c%c%c%c, val = %s)", sy, sy->name, (sy->lit ? 'L' : 'V'), (sy->resolved ? 'r' : ' '), (sy->lit_dumped ? 'd' : ' '), (sy->var_size ? '#' : ' '), valstr(sy->val)); if(debug && (sy->var_size || sy->len > 0)) printf(", len=%d",sy->len); #if 0 printf(", sy->next = 0x%x, sy->prev = 0x%x\n", sy->next, sy->prev); #endif if(debug) printf("\n"); if(sy->lit || sy->var_size) if(! sy->resolved) { /* resolve it */ sy -> val += litpool; litloc = sy -> val; sdot = star = dot = litloc+1; sy->resolved = true; sy->line = thisline; if(debug) printf("Lit[%d] %s = %d\n",thisline,sy->name,litloc); } /* resolve it */ sy = sy -> prev; } /* resolve scan */ if(debug) printf("End of resolution, new dot = %d\n",dot); } /**************************************************************************** * dump_lits * Inputs: * int thisline: Current line which activated dump (must be same as * line which activated resolution) * char * msg: Cheery debugging message to emit * Effect: * Dumps all the literals in the literal pool. Addresses assigned * must correspond ****************************************************************************/ void dump_lits(int thisline,char * msg) { ste * sy; int i; int end; unsigned thisloc; unsigned char zones; if(debug) printf("Dumping literals (%s), dot = %d\n",msg,dot); sy = symtail; if(sy==NULL) return; /* sy now points to the end of the symbol table. Walk backward, dumping literals */ while(sy != NULL) { /* dump scan */ unsigned litloc; /* We dump only the literals that should be dumped at this point. 'thisline' is either the line # of the 'END' statement or the 'LTORG' statement. */ if(sy->line != thisline) { /* not this pool */ sy = sy-> prev; continue; } /* not this pool */ if(!sy->lit && !sy->var_size) { /* skip it */ sy = sy -> prev; continue; } /* skip it */ if(! sy->resolved) { /* error */ printf("Error: unresolved literal @0x%x, %s\n",sy,sy->name); sy = sy->prev; continue; } /* error */ if(sy->lit_dumped) { /* already processed */ sy = sy->prev; continue; } /* already processed */ if(sy->lit) { /* literal */ thisloc = dot+litlen(sy->name)-1; if(thisloc != sy->val) { /* end of this phase */ char msg[150]; sprintf(msg,"Expected to place literal %.50s at %d, want to place it at %d\n", sy->name,sy->val,thisloc); error(err_label,msg); } /* end of this phase */ litloc = dot + litlen(sy->name) - 1; /* +0000 1..name) -0000 1..name) @....@ 1..name) - 1 */ zones = 0; switch(sy->name[0]) { /* add zones */ case '+': /* +0000 litlen == 4 ^ end */ zones = BA_bits; end = litlen(sy->name) + 1; break; case '-': /* +0000 litlen == 4 ^ end */ zones = B_bits; end = litlen(sy->name) + 1; break; case '@': case '\'': /* @....@ litlen == 4 ^ end */ zones = 0; end = litlen(sy->name) + 1; break; } /* add zones */ for(i=1; i < end; i++) { /* stuff it */ memory[check_memory(dot)] = C_bits | ascii_to_bcd(sy->name[i]) | (i==1 ? word_mark : 0); dot++; } /* stuff it */ memory[check_memory(dot - 1)] |= zones; if(debug) printf("Dumped %s @ %d\n",sy->name,litloc); sy->lit_dumped = true; /* Now put it on the listing file */ list_addr(litloc); list_lit(sy->name); } /* literal */ else if(sy->var_size) { /* var#n */ thisloc = dot + sy->len - 1; if(thisloc != sy->val) { /* phase error */ char msg[150]; sprintf(msg,"Expected to place %s#%d at %d, want to place it at %d\n", sy->name, sy->len, thisloc); error(err_label,msg); } /* phase error */ litloc = dot; for(i=0; i < sy->len; i++) { /* stuff it */ memory[check_memory(dot)] = C_bits | ascii_to_bcd(' ') | (i == 0 ? word_mark : 0); dot++; } /* stuff it */ if(debug) printf("Dumped %s#%d @ %d\n",sy->name, sy->len, litloc); sy->lit_dumped = true; list_addr(dot-1); list_var(sy->name, sy->len); } /* var#n */ emit_listing(); sy = sy -> prev; } /* dump scan */ star = sdot = dot; maxdot = dot; } /**************************************************************************** * symcomp * Inputs: * ste * * sy1: Pointer to first symbol table entry * ste * * sy2: Pointer to second symbol table entry * Result: int * -1: sy1 < sy2 * 0: sy1 == sy2 * +1: sym > sy2 ****************************************************************************/ int symcomp(ste * * sy1,ste * * sy2) { #if sym_debug printf("symcomp(0x%x (\"%s\"), 0x%x (\"%s\"))\n",*sy1,(*sy1)->name, *sy2, (*sy2)->name); #endif return strcmp((*sy1)->name, (*sy2)->name); } /**************************************************************************** * fill_syms * Inputs: * ste * syms[]: Array of pointer to stes * Effect: * copies all entries from sy to syms ****************************************************************************/ static void fill_syms(ste * syms[]) { int i; ste * sy; sy = symroot; i = 0; while(sy != NULL) { /* fill table */ #if sym_debug printf("0x%x = 0x%x (\"%s\")\n",&syms[i],sy,sy->name); #endif syms[i] = sy; sy = sy->next; i++; } /* fill table */ } /**************************************************************************** * resort * Inputs: * ste * syms[]: Pointer to vector of stes * int nsyms: Number of entries in vector * Effect: * Relinks the symbol table so it is in sorted order ****************************************************************************/ static void resort(ste * syms[],int nsyms) { int i; if(debug_sym) { /* print debug */ printf("resort(0x%x,%d)\n",syms,nsyms); for(i=0;inext, syms[i]->prev, syms[i]->name); } /* print debug */ for(i=0;iname); #endif syms[i] -> next = (i+1 < nsyms ? syms[i+1] : NULL); syms[i] -> prev = (i==0 ? NULL : syms[i-1]); if(debug_sym) { /* resort msg */ printf("syms[%d]=0x%x, nsyms = %d, next = 0x%x, prev = 0x%x\n", i, syms[i], nsyms, syms[i]->next, syms[i]->prev); } /* resort msg */ } /* resort */ symroot = *syms; } /**************************************************************************** * sort_syms * Effect: * Sorts the symbol table ****************************************************************************/ static void sort_syms() { int i; int nsyms; ste * sy; ste * * syms; nsyms = 0; sy = symroot; while(sy!=NULL) { /* count */ nsyms++; sy = sy->next; } /* count */ syms = (ste * *) malloc(nsyms * sizeof(ste *)); /* syms is now a pointer to an array of symbol table pointers. fill it, then sort it */ fill_syms(syms); qsort(syms,nsyms,sizeof(ste *),symcomp); /* List is now sorted. Rearrange its links */ resort(syms,nsyms); free(syms); }