/************************************************************************* Copyright (c) 1984 by Nick de Smith This software is supplied for interest and non-profit making purposes only. Under no circumstance shall it be lent, copied or otherwise used for profit. All rights regarding the use and ownership of this software shall at all times remain with the author, who does not guarantee the accuracy or reliabilty of this software and who will not accept any liability for its use. This software may not be copied or distributed without the inclusion of the above copyright notice. January 31st 1984 *************************************************************************/ /************************************************************************* Program : CAM Module : SYMB.C Author : Nick de Smith November/December 1982 Description : Symbol table management for CAM *************************************************************************/ #define MODULE #include #include "cam.h" /************************************************************************* * * * i n s e r t * ----------- * * Insert a symbol into the relevent part of the symbol table. This * is a really horrid piece of code; maybe I'll pretty it up sometime. * *************************************************************************/ global insert(seg, offset, name, flags) int seg, name[], flags; unsigned int offset; { register SYMBOL_PTR s_ptr; register SYMBOL_PTR ptr; register PSECT_PTR p_ptr; SYMBOL_PTR add_symb(); char *radnam(); dbg("Adding symbol \"%s\", seg: %03o, off: %o, flags: %o\n", radnam(name), seg, offset, flags); if (flags & S_GREF) { if (ref_st) ref_end = add_symb(&(ref_end->s_next), offset, name, flags, NULL); else ref_end = add_symb(&ref_st, offset, name, flags, NULL); return; } if (flags & S_GABS) { if (abs_st) abs_end = add_symb(&(abs_end->s_next), offset, name, flags, NULL); else abs_end = add_symb(&abs_st, offset, name, flags, NULL); return; } p_ptr = &segtbl[seg]; if (!(ptr = p_ptr->p_symb)) { add_symb(&(p_ptr->p_symb), offset, name, flags, NULL); return; } if (ptr->s_offset > offset) { add_symb(&(p_ptr->p_symb), offset, name, flags, ptr); return; } if (ptr->s_offset == offset) { if (flags & S_WEAK) { ptr->s_flags |= flags & ~S_WEAK; return; } add_symb(&(p_ptr->p_symb), offset, name, flags, ptr); return; } s_ptr = ptr->s_next; while (s_ptr) { if (offset <= s_ptr->s_offset && flags & S_STRONG) break; if (offset < s_ptr->s_offset) break; if (offset == s_ptr->s_offset) if (flags & S_WEAK) { s_ptr->s_flags |= flags & ~S_WEAK; return; } else break; ptr = s_ptr; s_ptr = s_ptr->s_next; } add_symb(&(ptr->s_next), offset, name, flags, s_ptr); } /************************************************************************* * * * a d d _ s y m b * --------------- * * Add a new symbol into the right tree * *************************************************************************/ local SYMBOL_PTR add_symb(from, offset, name, flags, next) SYMBOL_PTR *from; unsigned int offset; int name[], flags; SYMBOL_PTR next; { register SYMBOL_PTR s_ptr; SYMBOL_PTR new_symb(); s_ptr = *from = new_symb(); s_ptr->s_flags = flags | S_VALID; s_ptr->s_name[0] = name[0]; s_ptr->s_name[1] = name[1]; s_ptr->s_offset = offset; s_ptr->s_next = next; return (s_ptr); } /************************************************************************* * * * f i n d * ------- * * Find the segment number for the named psect. * *************************************************************************/ global find(name) int name[]; { register int i; char *radnam(); for (i = 0; i <= seg_max; i++) if (segtbl[i].p_name[0] == name[0] && segtbl[i].p_name[1] == name[1] ) return(i); bug("Failed to find psect \"%s\"", radnam(name)); } /************************************************************************* * * * l o o k u p * ----------- * * Lookup a symbol by segment and offset in the symbol table. * *************************************************************************/ global SYMBOL_PTR lookup(seg, offset) int seg; register unsigned int offset; { register SYMBOL_PTR s_ptr; s_ptr = segtbl[seg].p_symb; while (s_ptr) { if (s_ptr->s_offset == offset) return(s_ptr); s_ptr = s_ptr->s_next; } return (NULL); } /************************************************************************* * * * s _ i n d e x * ------------- * * Find the 'n'th occurrence of the relevant symbol. Note that the * first occurence of a symbol is the passed pointer. * *************************************************************************/ global SYMBOL_PTR s_index(s_ptr, index) register SYMBOL_PTR s_ptr; int index; { register int offset, temp; offset = s_ptr->s_offset; for (temp = 1; temp < index; temp++) if (!(s_ptr = s_ptr->s_next) || s_ptr->s_offset != offset) return(NULL); return(s_ptr); } /************************************************************************* * * * l _ n a m e * ----------- * * Rename all weak symbols with decent, mnemonic labels. * *************************************************************************/ global l_name() { int seg; char t_buff[6]; char l_lab1, l_lab2, l_lab3; register SYMBOL_PTR s_ptr; l_lab1 = l_lab2 = l_lab3 = '0'; for (seg = 0; seg <= seg_max; seg++) { s_ptr = segtbl[seg].p_symb; while (s_ptr) { if (s_ptr->s_flags & S_WEAK) { t_buff[0] = 'L'; t_buff[1] = '0'; t_buff[2] = '$'; t_buff[3] = l_lab3; t_buff[4] = l_lab2; t_buff[5] = l_lab1; if ((s_ptr->s_flags & (S_CREF | S_DREF)) == (S_CREF | S_DREF)) t_buff[0] = 'B'; else if (s_ptr->s_flags & S_DREF) t_buff[0] = 'D'; else if (s_ptr->s_flags & S_CREF) t_buff[0] = 'C'; if (s_ptr->s_flags & S_LOCAL) t_buff[1] |= 1; if (s_ptr->s_flags & S_EXT) t_buff[1] |= 2; ascr50(6, t_buff, s_ptr->s_name); if (++l_lab1 > '9') { l_lab1 = '0'; l_lab2++; } if (l_lab2 > '9') { l_lab2 = '0'; l_lab3++; } if (l_lab3 == ('9' + 1)) l_lab3 = 'A'; } s_ptr = s_ptr->s_next; } } } /************************************************************************* * * * n e w _ s y m b * --------------- * * Allocate space for a new symbol. Fatal error if no space * is left. * *************************************************************************/ local SYMBOL_PTR new_symb() { register char *temp; char *malloc(); if (!(temp = malloc(sizeof (SYMBOL)))) bug("Symbol space exhausted"); return((SYMBOL_PTR) temp); }