Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

524 lines
14 KiB
C

/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "lo68.h"
char tfilname[];
char etexstr[];
char edatstr[];
char eendstr[];
int debug;
int exstat;
/* get one symbol entry from the input file and put it into*/
/* the symbol table entry pointed to by lmte*/
getsym() /* rewritten for vax */
{
register int i;
long lvalue;
char *p;
short wvalue;
p = lmte;
for(i=SYNAMLEN; --i != -1; ) /* 2 may 83 */
*p++ = getc(&ibuf); /* get name */
if (lgetw(&wvalue, &ibuf) == -1)
printf(": error reading symbol table entry\n");
else if (lgetl(&lvalue ,&ibuf) == -1)
printf(": error reading symbol table entry\n"); /* symbol value */
((struct symtab *)lmte)->flags = wvalue;
((struct symtab *)lmte)->vl1 = lvalue;
#ifdef DEBUG
printf("\tname= %s, flags= %o, val= %d\n", ((struct symtab *)lmte)->name,
((struct symtab *)lmte)->flags, ((struct symtab *)lmte)->vl1);
#endif
}
/* relocate the symbol value pointed to by lmte according to*/
/* symbol type and corresponding relocation base*/
relocsym()
{
long l;
if(((struct symtab *)lmte)->flags&SYXR) /*external*/
return;
if(((struct symtab *)lmte)->flags&SYTX)
l = textbase;
else if(((struct symtab *)lmte)->flags&SYDA)
l = database;
else if(((struct symtab *)lmte)->flags&SYBS)
l = bssbase;
else if(((struct symtab *)lmte)->flags&SYEQ) /*equated*/
return; /* abs*/
else {
printf(": name = %s -- Invalid ",((struct symtab *)lmte)->name);
printf("symbol flags: 0%o\n",(int)((struct symtab *)lmte)->flags);
endit(-1);
}
((struct symtab *)lmte)->vl1 += l;
}
#define ADDSYM "addsym: file=%s symbol=%s flags=%o\n"
/*
* add a symbol to the symbol table
* if symbol is an external, put it on eirt even if it does
* already exist
* if symbol is a global, put it on girt and error if it exists
* in any case, add it to the end of the symbol table
* if libflg is set, we are searching a library. In this case, when
* a global is encountered, search the external symbols and set
* extmatch if a match is found.
*/
addsym(libflg)
{
register char *p;
if(debug)
printf(ADDSYM,ifilname,lmte,(int)((struct symtab *)lmte)->flags);
if(((struct symtab *)lmte)->flags&SYXR) { /*external*/
p = lemt(eirt);
mmte();
}
else if(((struct symtab *)lmte)->flags&SYGL) { /*global*/
if(libflg) { /*global in a library*/
p = lemt(eirt); /*look up in externals*/
if(p != lmte) { /*found a match*/
extmatch++;
}
}
p = lemt(girt);
if(p == lmte)
mmte();
else if(((struct symtab *)p)->flags!=((struct symtab *)lmte)->flags ||
((struct symtab *)p)->vl1 != ((struct symtab *)lmte)->vl1) {
dupdef:
if(libflg) {
noload++;
lastdup = p;
}
else
prdup(p); /*dup defn msg*/
}
else {
addmte(); /* put entry in for external #`s */
}
}
else { /*normal symbol*/
if(((struct symtab *)lmte)->name[0] == 'L') /*compiler label*/
return;
if(Xflag==0) /*dont save local symbols*/
return;
addmte();
}
}
prdup(p)
char *p;
{
printf(": %s duplicate definition in %s\n",p,ifilname);
exstat++;
}
/* initialize the symbol table and the heads of the hash lists*/
intsytab()
{
register char **p1, **p2;
register i;
long longtmp;
#ifndef VMS
bmte = sbrk(SYTESIZE*SZMT+2);
#else
/* sub 1 from sbrk size on vax since in rounds up to next multiple of 512 */
bmte = sbrk(SYTESIZE*SZMT+1);
#endif
longtmp = (long)bmte; /* 11 apr 83, for vax */
if(longtmp&1L) /* 11 apr 83, for vax */
bmte++;
emte = bmte + SYTESIZE*SZMT; /*end of main table*/
lmte=bmte; /*beginning main table*/
cszmt = SZMT; /*current size of main table*/
p1 = eirt;
p2 = girt;
for(i=32; --i != -1; ) { /* 2 may 83 */
*p1++ = (char *)p1;
*p1++ = (char *)0;
*p2++ = (char *)p2;
*p2++ = (char *)0;
}
}
/*
* method for looking up entries in the main table
*
* Note: The entry to be looked up must be placed at the end
* of the main table. The global cell 'lmte'(last main
* entry) points to the next available entry in the main
* table. The address of an initial reference table must
* also be provided.
* 1) Compute the hash code for the symbol and add it to the base address
* of the initial reference table given as input. Thus, two words are
* accessed which define the chain on which the symbol must be if it is
* in the table at all.
* 2) Alter the table link of the last symbol in the chain so that it
* points to the symbol being looked up. Note that the symbol to be
* looked up is always placed at the end of the main table before
* calling the lookup routine. This essentially adds one more element
* to the end of the chain, namely the symbol to be looked up.
* 3) Now start at the first symbol in the chain and follow the chain
* looking for a symbol equal to the smbol being looked up. It is
* quaranteed that such a symbol will be found because it is always
* the last symbol on the chain.
* 4) When the symbol is found, check to see if it is the last symbol
* on the chain. If not, the symbol being looked for is in the table
* and has been found. If it is the last symbol, the symbol being
* looked up is not in the table.
* 5) In the case the looked up symbol is not found, it is usually added
* to the end of the table. This is done simply by changing the
* initial reference table entry which points to the previous
* last symbol on the chain so that is now points to the symbol at the
* end of the main table. In case the symbol just looked up is not to
* be added to the main table then no action is needed . This means
* that the table link of the last symbol on a chain may point any-
* where.
* look up entry in the main table
* call with:
* address of initial reference table
* entry to be looked up at the end of the main table
* returns:
* a pointer to the entry. if this pointer is equal to
* lmte then the symbol was not previously in the table.
*/
char *
lemt(airt)
char **airt;
{
register struct symtab *mtpt; /* 14 apr 83, from char * */
pirt = airt + hash(); /*pointer to entry in irt*/
/*pointer to first entry in chain*/
mtpt = (struct symtab *)((struct irts *)((struct irts *)pirt)->irfe);
if(mtpt==0) /*empty chain*/
mtpt = (struct symtab *)lmte; /*start at end of main table*/
else /*last entry in chain is new symbol*/
((struct symtab *)((struct irts *)pirt)->irle)->tlnk = lmte;
return(nextsy(mtpt)); /*return next match on chain*/
}
/*
* locate the next symbol on a given hash chain with the same name as lmte
* return a pointer to it. When this pointer is equal to lmte, the
* chain has been completely searched.
*/
char *
nextsy(amtpt)
char *amtpt;
{
register char *mtpt;
register char *p1, *p2;
register int i;
mtpt = amtpt;
/*loop to locate entry in main table*/
lemtl:
p1 = &((struct symtab *)mtpt)->name[0];
p2 = &((struct symtab *)lmte)->name[0];
for(i=SYNAMLEN; --i != -1; ) { /* 2 may 83 */
if(*p1++ != *p2++) { /* changed to char ptr compares */
mtpt = ((struct symtab *)mtpt)->tlnk; /*go to next entry in chain*/
goto lemtl;
}
}
return(mtpt);
}
/*
*make an entry in the main table
* assumes:
* entry to be made is pointed at by lmte
* pirt points to the correct initial reference table entry
*/
mmte()
{
((struct irts *)pirt)->irle = lmte; /*pointer to last entry in chain*/
if(((struct irts *)pirt)->irfe == 0) /*first entry in chain*/
((struct irts *)pirt)->irfe = lmte;
addmte();
}
/* add the symbol pointed to by lmte to symbol table*/
addmte()
{
lmte += SYTESIZE; /*bump last main table entry pointer*/
if(lmte>=emte) { /*main table overflow*/
#ifndef VMS
if(sbrk(SYTESIZE*ICRSZMT) == (char *)-1){ /*get more memory*/
#else
/* sub 1 from sbrk size on vax since in rounds up to next multiple of 512 */
if(sbrk(SYTESIZE*ICRSZMT-1) == (char *)-1){ /*get more memory*/
#endif
printf(": symbol table overflow\n");
exit(-1);
}
else { /*move end of main table*/
emte += SYTESIZE*ICRSZMT;
cszmt += ICRSZMT;
}
}
}
/* compute a hash code for the last entry in the main table*/
/* returns the hash code*/
hash()
{
register ht1, i; /*temps*/
register char *p;
ht1 = 0;
p = &((struct symtab *)lmte)->name[0];
for(i=SYNAMLEN; --i != -1; ) /* 2 may 83 */
ht1 += *p++;
return(ht1&(SZIRT-2)); /*make hash code even and between 0 and 62*/
}
/*
* pack a string into an entry in the main table
* call with:
* pointer to the string
* pointer to desired entry in the main table
*/
pack(apkstr,apkptr)
char *apkstr;
char *apkptr;
{
register i;
register char *pkstr, *pkptr;
pkstr = apkstr;
pkptr = apkptr;
for(i=SYNAMLEN; --i != -1; ) /* 2 may 83 */
*pkptr++ = *pkstr++; /* changed to char ptr move */
}
/*save the current state of the symbol table -- it may be restored later*/
savsymtab()
{
register char **p1, **p2;
register i;
savlmte = lmte;
p2 = eirt;
p1 = saveirt;
for(i = SZIRT; --i != -1; ) /* 2 may 83 */
*p1++ = *p2++;
p2 = girt;
p1 = savgirt;
for(i = SZIRT; --i != -1; ) /* 2 may 83 */
*p1++ = *p2++;
}
/*restore the symbol table as it was when we last saved it*/
restsymtab()
{
register char **p1, **p2;
register i;
lmte = savlmte;
p1 = eirt;
p2 = saveirt;
for(i = SZIRT; --i != -1; ) /* 2 may 83 */
*p1++ = *p2++;
p1 = girt;
p2 = savgirt;
for(i = SZIRT; --i != -1; ) /* 2 may 83 */
*p1++ = *p2++;
}
/*
* resolve the external variable addresses and set the
* base address of the data and bss segments.
* also allocate storage for the common variables.
*/
resolve()
{
register char *p;
textsize = textbase - textstart;
datasize = database;
bsssize = bssbase;
if(Dflag)
database = datastart;
else if(shtext) { /*shared text - move start of data*/
if(shtext == -1) { /* 2k boundary */
database = (textbase+SH2BOUND)&~(SH2BOUND-1);
datastart = database;
}
else { /* 4k boundary */
database = (textbase+SHBOUND)&~(SHBOUND-1);
datastart = database;
}
}
else if(isplit) { /* i & d split*/
database = 0;
datastart = 0;
}
else {
database = (textbase+1)&~1;
datastart = database;
}
if(Bflag)
bssbase = bssstart;
else {
bssbase = (database+datasize+1)&~1;
bssstart = bssbase;
}
textbase = textstart;
fixsyms(); /*relocate symbols with addresses*/
fixexts(); /*fix external addresses & commons*/
if(etextptr) {
pack(etexstr,lmte);
p = lemt(eirt);
do {
((struct symtab *)p)->vl1 = textbase + textsize; /*[vlh]4.2*/
((struct symtab *)p)->flags &= ~SYXR; /*no longer external*/
((struct symtab *)p)->flags |= SYDF|SYGL;
} while((p = nextsy(((struct symtab *)p)->tlnk)) != lmte);
}
if(edataptr) {
pack(edatstr,lmte);
p=lemt(eirt);
do {
((struct symtab *)p)->vl1 = database+datasize; /*[vlh]4.2*/
((struct symtab *)p)->flags &= ~SYXR; /*no longer external*/
((struct symtab *)p)->flags |= SYDF|SYGL;
} while((p = nextsy(((struct symtab *)p)->tlnk)) != lmte);
}
if(endptr) {
pack(eendstr,lmte);
p = lemt(eirt);
do {
((struct symtab *)p)->vl1 = bssbase+bsssize; /*[vlh]4.2*/
((struct symtab *)p)->flags &= ~SYXR; /*no longer external*/
((struct symtab *)p)->flags |= SYDF|SYGL;
} while((p = nextsy(((struct symtab *)p)->tlnk)) != lmte);
}
}
/* fix symbol addresses that have been assigned by adding in*/
/* database and bssbase*/
fixsyms() /*look at each symbol*/
{
register struct symtab *p;
for(p = (struct symtab *)bmte; p<(struct symtab *)lmte; p++) {
if(p->flags&SYXR)
continue;
if(p->flags&SYDA) /*data symbol*/
p->vl1 += database;
else if(p->flags&SYBS) /* bss symbol*/
p->vl1 += bssbase;
}
}
/* get addresses for all external symbols and common symbols*/
fixexts()
{
register char *p;
register char **sx1, **sx2;
for(sx1=eirt; sx1<&eirt[63]; sx1 += 2) { /*go thru externals*/
if(*(sx2 = sx1+1)==0) /*this chain empty*/
continue;
/* go thru symbols on chain*/
sx2 = (char **)*sx2; /*first entry on this chain*/
while(1) {
if(((struct symtab *)sx2)->vl1)
asgncomn(sx2); /*assign a common address*/
else
asgnext(sx2); /*match to a global*/
p = (char *)sx2;
if(p == *sx1) /*end of chain*/
break;
sx2 = (char **)((struct symtab *)sx2)->tlnk; /*next entry in chain*/
}
}
}
/* print a symbol name for an error message*/
prtsym(ap)
char *ap;
{
register i;
register char *p;
p = ap;
for(i = SYNAMLEN; --i != -1; ) { /* 2 may 83 */
if(*p)
putchar(*p++);
else
break;
}
putchar('\n');
}
/* output symbol table to file*/
osymt()
{
register struct symtab *p;
register int cnt;
stlen = 0;
cnt = 0;
if(sflag) /*no symbol table desired*/
return;
/* now output the symbols deleting externals*/
for(p = (struct symtab *)bmte; p < (struct symtab *)lmte; p++) {
if(p->flags&SYXR) /*external symbol*/
continue;
if((p->flags&SYGL)==0 && (p->name[0]=='L' || Xflag==0))
continue;
osyme(p);
cnt++;
}
}
/* output symbols in a form to be read by a debugger*/
/* call with pointer to symbol table entry*/
osyme(aosypt)
struct symtab *aosypt;
{
register struct symtab *osypt;
register char *p1;
register int i;
osypt = aosypt; /*pointer to symbol table entry*/
stlen += OSTSIZE; /*one more symbol out*/
/*output symbol to loader file*/
p1 = &(osypt->name[0]);
for(i = SYNAMLEN; --i != -1; ) /*output symbol name*/
putc(*p1++,&obuf);
lputw(&osypt->flags,&obuf); /*output symbol flags*/
lputl(&osypt->vl1,&obuf); /*output symbol value*/
}