/* gensym.c - generate symbol table for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "flag.h" #include "file.h" #include "globvar.h" FORWARD int printsym P((register struct sym_s *symptr, unsigned column)); FORWARD void sort P((struct sym_s **array, struct sym_s **top, bool_pt nameflag)); /* sort labels in symbol table on name and value */ /* if listing, write human-readable table to list file */ /* if symbol file, write machine-readable tables to it */ /* pointers become relative to start of file */ PUBLIC void gensym() { unsigned column; struct sym_s **copyptr; struct sym_s **copytop; register struct sym_s **hashptr; unsigned label_count; /* number of labels */ unsigned labels_length; /* length of all label strings */ struct sym_s **symlptr; /* start of symbol output list */ register struct sym_s *symptr; #ifdef BINSYM unsigned label_stringptr; /* offset of label str from start of file */ #endif int symcount = 0; labels_length = label_count = 0; /* make copy of all relavant symbol ptrs on heap */ /* original ptrs can now be modified, but need to be an array for sort */ for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) symcount++; while ((symptr = symptr->next) != NUL_PTR); symlptr = copyptr = asalloc( sizeof(struct sym_s *) * symcount); for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) { *copyptr++ = symptr; ++label_count; labels_length += symptr->length + 3; /* 3 for type, value */ } while ((symptr = symptr->next) != NUL_PTR); sort(symlptr, copyptr, TRUE); /* sort on name */ copytop = copyptr; if (list.global) { outfd = lstfil; writenl(); writesn("Symbols:"); for (copyptr = symlptr, column = 0; copyptr < copytop;) column = printsym(*copyptr++, column); if (column != 0) writenl(); } if ((outfd = symfil) != 0) { #ifndef BINSYM for (copyptr = symlptr; copyptr < copytop;) /* for (copyptr = spt; copyptr < spt_top;) */ { int sft; if((symptr = *copyptr++) == NUL_PTR ) continue; if( globals_only_in_obj && !(symptr->type & EXPBIT)) continue; writec(hexdigit[symptr->data & SEGM]); writec(' '); for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) writec(hexdigit[(symptr->value_reg_or_op.value>>sft) & 0xF]); writec(' '); writec(symptr->type & EXPBIT ? 'E' : '-'); writec(symptr->type & ENTBIT ? 'N' : '-'); writec(symptr->data & IMPBIT ? 'I' : '-'); writec(symptr->data & RELBIT ? 'R' : 'A'); writec(symptr->type & COMMBIT ? 'C' : '-'); writec(' '); write(outfd, symptr->name, (unsigned) (symptr->length)); /* printsym(*copyptr++, 0); */ writenl(); } #else writew(mapnum); label_count *= 2; /* now length of ptr table (2 bytes per ptr) */ label_stringptr = label_count + 6; /* offset to current string in symbol file */ /* 6 is length of header */ labels_length += label_stringptr; /* offset to ptr table sorted on value */ writew(labels_length + label_count); /* total length of symbol file */ writew(label_count); for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) (symptr->next = (struct sym_s *) label_stringptr)); /* reuse "next" to record string position */ label_stringptr += symptr->length + 3; } for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) symptr->value_reg_or_op.value); writec(symptr->type); write(outfd, symptr->name, (unsigned) (symptr->length - 1)); writec(symptr->name[symptr->length - 1] | 0x80); } sort(symlptr, copyptr, FALSE); /* sort on value */ for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) symptr->next); /* now has string position */ } #endif } } /* print symbol nicely formatted for given column */ PRIVATE int printsym(symptr, column) register struct sym_s *symptr; unsigned column; { unsigned char length; register struct sym_listing_s *listptr; char *outname; char *symname; listptr = (struct sym_listing_s *) temp_buf(); memset((char *) listptr, ' ', SYMLIS_LEN); listptr->nullterm = 0; if ((length = symptr->length) > SYMLIS_NAMELEN) { outname = listptr->name; outname[length = SYMLIS_NAMELEN] = '+'; } else outname = listptr->name; /*(listptr->name + SYMLIS_NAMELEN) - length;*/ symname = symptr->name; do *outname++ = *symname++; while (--length != 0); listptr->ar[0] = symptr->data & RELBIT ? 'R' : 'A'; listptr->segm[0] = hexdigit[symptr->data & SEGM]; if (symptr->type & COMMBIT) listptr->cein[0] = 'C'; else if (symptr->type & ENTBIT) listptr->cein[0] = 'N'; else if (symptr->type & EXPBIT) listptr->cein[0] = 'E'; else if (symptr->data & IMPBIT) listptr->cein[0] = 'I'; #if SIZEOF_OFFSET_T > 2 build_2hex_number((unsigned) (symptr->value_reg_or_op.value >> 16), listptr->value); #endif build_2hex_number((unsigned) symptr->value_reg_or_op.value, listptr->value); writes((char *) listptr); if ((column += SYMLIS_LEN) > (80 - SYMLIS_LEN)) { writenl(); column = 0; } return column; } /* shell sort symbols */ PRIVATE void sort(array, top, nameflag) struct sym_s **array; struct sym_s **top; bool_pt nameflag; { int gap; int i; int j; register struct sym_s **left; register struct sym_s **right; int size; struct sym_s *swap; size = top - array; /* choose gaps according to Knuth V3 p95 */ for (gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j) ; do { for (j = gap; j < size; ++j) for (i = j - gap; i >= 0; i -= gap) { left = &array[i]; right = &array[i + gap]; if ((bool_t) nameflag) { if (strcmp((*left)->name, (*right)->name) <= 0) break; } else if ((unsigned) (*left)->value_reg_or_op.value <= (*right)->value_reg_or_op.value) break; swap = *left; *left = *right; *right = swap; } } while ((gap /= 3) != 0); }