xref: /csrg-svn/old/as.vax/assyms.c (revision 600)
1*600Sbill /* Copyright (c) 1980 Regents of the University of California */
2*600Sbill static	char sccsid[] = "@(#)assyms.c 4.1 08/13/80";
3*600Sbill #include <stdio.h>
4*600Sbill #include <ctype.h>
5*600Sbill #include <sys/types.h>
6*600Sbill #include <a.out.h>
7*600Sbill #include "as.h"
8*600Sbill #include "asscan.h"
9*600Sbill #include "assyms.h"
10*600Sbill 
11*600Sbill /*
12*600Sbill  *	Managers for chunks of symbols allocated from calloc()
13*600Sbill  *	We maintain a linked list of such chunks.
14*600Sbill  *
15*600Sbill  */
16*600Sbill struct	allocbox	*allochead;	/*head of chunk list*/
17*600Sbill struct	allocbox	*alloctail;	/*tail*/
18*600Sbill struct	allocbox	*newbox;	/*for creating a new chunk*/
19*600Sbill struct	symtab		*nextsym;	/*next symbol free*/
20*600Sbill int			symsleft;	/*slots left in current chunk*/
21*600Sbill 
22*600Sbill struct	symtab		**symptrs;
23*600Sbill struct	symtab		**symdelim[NLOC + NLOC +1];
24*600Sbill struct	symtab		**symptrub;
25*600Sbill /*
26*600Sbill  *	Managers for the dynamically extendable hash table
27*600Sbill  */
28*600Sbill struct	hashdallop	*htab;
29*600Sbill 
30*600Sbill struct	instab		*itab[NINST];	/*maps opcodes to instructions*/
31*600Sbill /*
32*600Sbill  *	Counts what went into the symbol table, so that the
33*600Sbill  *	size of the symbol table can be computed.
34*600Sbill  */
35*600Sbill int	nsyms;		/* total number in the symbol table */
36*600Sbill int	njxxx;		/* number of jxxx entrys */
37*600Sbill int	nforgotten;	/* number of symbols erroneously entered */
38*600Sbill int	nlabels;	/* number of label entries */
39*600Sbill int	hshused;	/* number of hash slots used */
40*600Sbill 
41*600Sbill /*
42*600Sbill  *	Managers of the symbol literal storage.
43*600Sbill  *	If we have flexible names, then we allocate BUFSIZ long
44*600Sbill  *	string, and pack strings into that.  Otherwise, we allocate
45*600Sbill  *	symbol storage in fixed hunks NCPS long when we allocate space
46*600Sbill  *	for other symbol attributes.
47*600Sbill  */
48*600Sbill #ifdef	FLEXNAMES
49*600Sbill struct	strpool		*strplhead = 0;
50*600Sbill #else
51*600Sbill char			*namebuffer;
52*600Sbill #endif
53*600Sbill 
54*600Sbill symtabinit()
55*600Sbill {
56*600Sbill 	allochead = 0;
57*600Sbill 	alloctail = 0;
58*600Sbill 	nextsym = 0;
59*600Sbill 	symsleft = 0;
60*600Sbill #ifdef FLEXNAMES
61*600Sbill 	strpoolalloc();		/* get the first strpool storage area */
62*600Sbill #endif FLEXNAMES
63*600Sbill 	htab = 0;
64*600Sbill 	htaballoc();		/* get the first part of the hash table */
65*600Sbill }
66*600Sbill 
67*600Sbill /*
68*600Sbill  *	Install all known instructions in the symbol table
69*600Sbill  */
70*600Sbill syminstall()
71*600Sbill {
72*600Sbill 	register	struct	instab	*ip;
73*600Sbill 	register	struct	symtab	**hp;
74*600Sbill 	register	char	*p1, *p2;
75*600Sbill 
76*600Sbill 	for (ip=instab; ip->name!=0; ip++) {
77*600Sbill 		p1 = ip->name;
78*600Sbill 		p2 = yytext;
79*600Sbill 		while (*p2++ = *p1++);
80*600Sbill 		hp = lookup(0);		/* 0 => don't install this*/
81*600Sbill 		if (*hp==NULL) {
82*600Sbill 			*hp = (struct symtab *)ip;
83*600Sbill 			if (   (ip->tag!=INSTn)
84*600Sbill 			    && (ip->tag!=INST0)
85*600Sbill 			    && (ip->tag!=0))
86*600Sbill 				continue; /* was pseudo-op */
87*600Sbill 			itab[ip->opcode & 0xFF] = ip;
88*600Sbill 		}
89*600Sbill 	}
90*600Sbill }	/*end of syminstall*/
91*600Sbill 
92*600Sbill 
93*600Sbill /*
94*600Sbill  *	Assign final values to symbols,
95*600Sbill  *	and overwrite the index field with its relative position in
96*600Sbill  *	the symbol table we give to the loader.
97*600Sbill  */
98*600Sbill extern struct exec hdr;
99*600Sbill 
100*600Sbill freezesymtab()
101*600Sbill {
102*600Sbill 	register	struct	symtab	*sp;
103*600Sbill 				long	bs;
104*600Sbill 	register	int	relpos = 0;
105*600Sbill 	register	struct	symtab		*ubsp;
106*600Sbill 	register	struct	allocbox	*allocwalk;
107*600Sbill 
108*600Sbill 	DECLITERATE(allocwalk, sp, ubsp)
109*600Sbill 	{
110*600Sbill 		if (sp->tag >= IGNOREBOUND)
111*600Sbill 			continue; 		/*totally ignore jxxx entries */
112*600Sbill 		/*
113*600Sbill 		 *	Ignore stabs, but give them a symbol table index
114*600Sbill 		 */
115*600Sbill 		if (sp->type & STABFLAG)
116*600Sbill 			goto assignindex;
117*600Sbill 		if ((sp->type&XTYPE)==XUNDEF)
118*600Sbill 			sp->type = XXTRN+XUNDEF;
119*600Sbill 		else if ((sp->type&XTYPE)==XDATA)
120*600Sbill 			sp->value += usedot[sp->index].xvalue;
121*600Sbill 		else if ((sp->type&XTYPE)==XTEXT)
122*600Sbill 			sp->value += usedot[sp->index].xvalue;
123*600Sbill 		else if ((sp->type&XTYPE)==XBSS) {
124*600Sbill 			bs = sp->value;
125*600Sbill 			sp->value = hdr.a_bss + datbase;
126*600Sbill 			hdr.a_bss += bs;
127*600Sbill 		}
128*600Sbill 	   assignindex:
129*600Sbill 		if (    (sp->name[0] != 'L')
130*600Sbill 		     || (sp->tag != LABELID)
131*600Sbill 		     || savelabels
132*600Sbill 		     )			/*then, we will write it later on*/
133*600Sbill 				sp->index = relpos++;
134*600Sbill 	}
135*600Sbill }
136*600Sbill 
137*600Sbill 
138*600Sbill 
139*600Sbill /*
140*600Sbill  *	For all of the stabs that had their final value undefined during pass 1
141*600Sbill  *	and during pass 2 assign a final value.
142*600Sbill  *	We have already given stab entrys a initial approximation
143*600Sbill  *	when we constsructed the sorted symbol table.
144*600Sbill  *	Iteration order doesn't matter.
145*600Sbill  */
146*600Sbill stabfix() {
147*600Sbill 	register struct symtab *sp, **cosp;
148*600Sbill 	register struct symtab *p;
149*600Sbill 
150*600Sbill 	SYMITERATE(cosp, sp){
151*600Sbill 		if(sp->ptype && (sp->type & STABFLAG)) {
152*600Sbill 			p = sp->dest;
153*600Sbill 			sp->value = p->value;
154*600Sbill 			sp->index = p->index;
155*600Sbill 			sp->type = p->type;
156*600Sbill 		}
157*600Sbill 	}
158*600Sbill }
159*600Sbill 
160*600Sbill char *Calloc(number, size)
161*600Sbill 	int	number, size;
162*600Sbill {
163*600Sbill 	register	char *newstuff;
164*600Sbill 	newstuff = (char *)sbrk(number*size);
165*600Sbill 	if ((int)newstuff == -1){
166*600Sbill 		yyerror("Ran out of Memory");
167*600Sbill 		delexit();
168*600Sbill 	}
169*600Sbill 	return(newstuff);
170*600Sbill }
171*600Sbill 
172*600Sbill char *ClearCalloc(number, size)
173*600Sbill 	int	number, size;
174*600Sbill {
175*600Sbill 	register	char	*newstuff;		/* r11 */
176*600Sbill 	register	int	length = number * size;	/* r10 */
177*600Sbill 	newstuff = Calloc(number, size);
178*600Sbill 	asm("movc5 $0, (r0), $0, r10, (r11)");
179*600Sbill 	return(newstuff);
180*600Sbill }
181*600Sbill 
182*600Sbill struct symtab *symalloc()
183*600Sbill {
184*600Sbill 	if (symsleft == 0){
185*600Sbill 		newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
186*600Sbill 		symsleft = SYMDALLOP;
187*600Sbill 		nextsym = &newbox->symslots[0];
188*600Sbill #ifndef FLEXNAMES
189*600Sbill 		namebuffer = &newbox->symnames[0];
190*600Sbill #endif not FLEXNAMES
191*600Sbill 		if (alloctail == 0){
192*600Sbill 			allochead = alloctail = newbox;
193*600Sbill 		} else {
194*600Sbill 			alloctail->nextalloc = newbox;
195*600Sbill 			alloctail = newbox;
196*600Sbill 		}
197*600Sbill 	}
198*600Sbill 	--symsleft;
199*600Sbill 	++nsyms;
200*600Sbill #ifndef FLEXNAMES
201*600Sbill 	nextsym->name = namebuffer;
202*600Sbill 	namebuffer += NCPS;
203*600Sbill #endif not FLEXNAMES
204*600Sbill 	return(nextsym++);
205*600Sbill }
206*600Sbill 
207*600Sbill #ifdef FLEXNAMES
208*600Sbill strpoolalloc()
209*600Sbill {
210*600Sbill 	register	struct	strpool	*new;
211*600Sbill 
212*600Sbill 	new = (struct strpool *)Calloc(1, sizeof (struct strpool));
213*600Sbill 	new->str_nalloc = 0;
214*600Sbill 	new->str_next = strplhead;
215*600Sbill 	strplhead = new;
216*600Sbill }
217*600Sbill #endif FLEXNAMES
218*600Sbill 
219*600Sbill symcmp(Pptr, Qptr)
220*600Sbill 	struct symtab **Pptr, **Qptr;
221*600Sbill {
222*600Sbill 	register struct symtab *p = *Pptr;
223*600Sbill 	register struct symtab *q = *Qptr;
224*600Sbill 	if (p->index < q->index)
225*600Sbill 		return(-1);
226*600Sbill 	if (p->index > q->index)
227*600Sbill 		return(1);
228*600Sbill 	if (p->value < q->value)
229*600Sbill 		return(-1);
230*600Sbill 	if (p->value > q->value)
231*600Sbill 		return(1);
232*600Sbill 	/*
233*600Sbill 	 *	Force jxxx entries to virtually preceed labels defined
234*600Sbill 	 *	to follow the jxxxx instruction, so that bumping the
235*600Sbill 	 *	jxxx instruction correctly fixes up the following labels
236*600Sbill 	 */
237*600Sbill 	if (p->tag >= IGNOREBOUND)	/*p points to a jxxx*/
238*600Sbill 		return(-1);
239*600Sbill 	if (q->tag >= IGNOREBOUND)
240*600Sbill 		return(1);
241*600Sbill 	/*
242*600Sbill 	 *	both are now just plain labels; the relative order doesn't
243*600Sbill 	 *	matter.  Both can't be jxxxes, as they would have different
244*600Sbill 	 *	values.
245*600Sbill 	 */
246*600Sbill 	return(0);
247*600Sbill }	/*end of symcmp*/
248*600Sbill 
249*600Sbill /*
250*600Sbill  *	We construct the auxiliary table of pointers, symptrs and
251*600Sbill  *	symdelim
252*600Sbill  *	We also assign preliminary values to stab entries that did not yet
253*600Sbill  *	have an absolute value (because they initially referred to
254*600Sbill  *	forward references). We don't worry about .stabds, as they
255*600Sbill  *	already have an estimated final value
256*600Sbill  */
257*600Sbill 
258*600Sbill sortsymtab()
259*600Sbill {
260*600Sbill 	register	struct	symtab	*sp;
261*600Sbill 	register	struct	symtab	**cowalk;
262*600Sbill 	register	struct	allocbox	*allocwalk;
263*600Sbill 			struct	symtab	*ubsp;
264*600Sbill 				int	segno;
265*600Sbill 				int	slotno;
266*600Sbill 				int	symsin;	/*number put into symptrs*/
267*600Sbill 
268*600Sbill 	symptrs =  (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
269*600Sbill 	/*
270*600Sbill 	 *	Allocate one word at the beginning of the symptr array
271*600Sbill 	 *	so that backwards scans through the symptr array will
272*600Sbill 	 *	work correctly while scanning through the zeroth segment
273*600Sbill 	 */
274*600Sbill 	*symptrs++ = 0;
275*600Sbill 	cowalk = symptrs;
276*600Sbill 	symsin = 0;
277*600Sbill 	DECLITERATE(allocwalk, sp, ubsp) {
278*600Sbill 		if (sp->ptype && (sp->type &STABFLAG)){
279*600Sbill 			sp->value = sp->dest->value;
280*600Sbill 			sp->index = sp->dest->index;
281*600Sbill 		}
282*600Sbill 		if (symsin >= nsyms)
283*600Sbill 			yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
284*600Sbill 		*cowalk++ = sp;
285*600Sbill 		symsin++;
286*600Sbill 	}
287*600Sbill 	if (symsin != nsyms)
288*600Sbill 		yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
289*600Sbill 			symsin, nsyms);
290*600Sbill 	symptrub = &symptrs[nsyms ];
291*600Sbill 	qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
292*600Sbill 	symdelim[0] = symptrs;
293*600Sbill 	for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
294*600Sbill 	     segno < NLOC + NLOC;
295*600Sbill 	     segno++, slotno++){
296*600Sbill 		for (; sp && sp->index == segno; sp = *++cowalk);
297*600Sbill 		symdelim[slotno] = cowalk;	/*forms the ub delimeter*/
298*600Sbill 	}
299*600Sbill }	/*end of sortsymtab*/
300*600Sbill 
301*600Sbill #ifdef DEBUG
302*600Sbill dumpsymtab()
303*600Sbill {
304*600Sbill 	register	int	segno;
305*600Sbill 	register	struct symtab *sp, **cosp, *ub;
306*600Sbill 	char		*tagstring();
307*600Sbill 
308*600Sbill 	printf("Symbol Table dump:\n");
309*600Sbill 	for (segno = 0; segno < NLOC + NLOC; segno++){
310*600Sbill 		printf("Segment number: %d\n", segno);
311*600Sbill 		SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
312*600Sbill #ifdef FLEXNAMES
313*600Sbill 			printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
314*600Sbill 				segno, sp->name,
315*600Sbill 				sp->value, sp->index,
316*600Sbill 				tagstring(sp->tag));
317*600Sbill #else not FLEXNAMES
318*600Sbill 			printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n",
319*600Sbill 				segno, NCPS, NCPS, sp->name,
320*600Sbill 				sp->value, sp->index,
321*600Sbill 				tagstring(sp->tag));
322*600Sbill #endif not FLEXNAMES
323*600Sbill 			printf("\t\ttype: %d jxbump %d jxfear: %d\n",
324*600Sbill 				sp->type, sp->jxbump, sp->jxfear);
325*600Sbill 		}
326*600Sbill 		printf("\n\n");
327*600Sbill 	}
328*600Sbill }
329*600Sbill 
330*600Sbill static	char tagbuff[4];
331*600Sbill 
332*600Sbill char *tagstring(tag)
333*600Sbill 	unsigned	char	tag;
334*600Sbill {
335*600Sbill 	switch(tag){
336*600Sbill 		case JXACTIVE:		return("active");
337*600Sbill 		case JXNOTYET:		return("notyet");
338*600Sbill 		case JXALIGN:		return("align");
339*600Sbill 		case JXQUESTIONABLE:	return("jxquestionable");
340*600Sbill 		case JXINACTIVE:	return("inactive");
341*600Sbill 		case JXTUNNEL:		return("tunnel");
342*600Sbill 		case OBSOLETE:		return("obsolete");
343*600Sbill 		case IGNOREBOUND:	return("ignorebound");
344*600Sbill 		case STABFLOATING:	return("stabfloating");
345*600Sbill 		case STABFIXED:		return("stabfixed");
346*600Sbill 		case LABELID:		return("labelid");
347*600Sbill 		case OKTOBUMP:		return("oktobump");
348*600Sbill 		case ISET:		return("iset");
349*600Sbill 		case ILSYM:		return("ilsym");
350*600Sbill 		default:		sprintf(tagbuff,"%d", tag);
351*600Sbill 					return(tagbuff);
352*600Sbill 	}
353*600Sbill }
354*600Sbill #endif DEBUG
355*600Sbill 
356*600Sbill htaballoc()
357*600Sbill {
358*600Sbill 	register	struct	hashdallop	*new;
359*600Sbill 	new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
360*600Sbill 	if (htab == 0)
361*600Sbill 		htab = new;
362*600Sbill 	else {		/* add AFTER the 1st slot */
363*600Sbill 		new->h_next = htab->h_next;
364*600Sbill 		htab->h_next = new;
365*600Sbill 	}
366*600Sbill }
367*600Sbill 
368*600Sbill #define 	HASHCLOGGED	(NHASH / 2)
369*600Sbill 
370*600Sbill /*
371*600Sbill  *	Lookup a symbol stored in extern yytext.
372*600Sbill  *	All strings passed in via extern yytext had better have
373*600Sbill  *	a trailing null.  Strings are placed in yytext for hashing by
374*600Sbill  *	syminstall() and by yylex();
375*600Sbill  *
376*600Sbill  *	We take pains to avoid function calls; this functdion
377*600Sbill  *	is called quite frequently, and the calls overhead
378*600Sbill  *	in the vax contributes significantly to the overall
379*600Sbill  *	execution speed of as.
380*600Sbill  */
381*600Sbill struct symtab **lookup(instflg)
382*600Sbill 	int	instflg;		/* 0: don't install */
383*600Sbill {
384*600Sbill 	static	 int		initialprobe;
385*600Sbill 	register struct	symtab 	**hp;
386*600Sbill 	register char 		*from;
387*600Sbill 	register char		*to;
388*600Sbill 	register	int	len;
389*600Sbill 	register	int	nprobes;
390*600Sbill 	static	 struct hashdallop *hdallop;
391*600Sbill 	static	 struct symtab	**emptyslot;
392*600Sbill 	static 	 struct hashdallop *emptyhd;
393*600Sbill 	static	 struct	symtab	**hp_ub;
394*600Sbill 
395*600Sbill 	emptyslot = 0;
396*600Sbill 	for (nprobes = 0, from = yytext;
397*600Sbill 	     *from;
398*600Sbill 	     nprobes <<= 2, nprobes += *from++)
399*600Sbill 		continue;
400*600Sbill 	nprobes += from[-1] << 5;
401*600Sbill 	nprobes %= NHASH;
402*600Sbill 	if (nprobes < 0)
403*600Sbill 		nprobes += NHASH;
404*600Sbill 
405*600Sbill 	initialprobe = nprobes;
406*600Sbill 	for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
407*600Sbill 		for (hp = &(hdallop->h_htab[initialprobe]),
408*600Sbill 				nprobes = 1,
409*600Sbill 				hp_ub = &(hdallop->h_htab[NHASH]);
410*600Sbill 		     (*hp) && (nprobes < NHASH);
411*600Sbill 				hp += nprobes,
412*600Sbill 				hp -= (hp >= hp_ub) ? NHASH:0,
413*600Sbill 				nprobes += 2)
414*600Sbill 		{
415*600Sbill 			from = yytext;
416*600Sbill 			to = (*hp)->name;
417*600Sbill #ifndef FLEXNAMES
418*600Sbill 			for (len = 0; (len<NCPS) && *from; len++)
419*600Sbill 				if (*from++ != *to++)
420*600Sbill 					goto nextprobe;
421*600Sbill 			if (len >= NCPS)	/*both are maximal length*/
422*600Sbill 				return(hp);
423*600Sbill 			if (*to == 0)		/*assert *from == 0*/
424*600Sbill 				return(hp);
425*600Sbill #else FLEXNAMES
426*600Sbill 			while (*from && *to)
427*600Sbill 				if (*from++ != *to++)
428*600Sbill 					goto nextprobe;
429*600Sbill 			if (*to == *from)	/*assert both are == 0*/
430*600Sbill 				return(hp);
431*600Sbill #endif FLEXNAMES
432*600Sbill 
433*600Sbill 	nextprobe: ;
434*600Sbill 		}
435*600Sbill 		if (*hp == 0 && emptyslot == 0 &&
436*600Sbill 		    hdallop->h_nused < HASHCLOGGED) {
437*600Sbill 			emptyslot = hp;
438*600Sbill 			emptyhd = hdallop;
439*600Sbill 		}
440*600Sbill 	}
441*600Sbill 	if (emptyslot == 0) {
442*600Sbill 		htaballoc();
443*600Sbill 		hdallop = htab->h_next;		/* aren't we smart! */
444*600Sbill 		hp = &hdallop->h_htab[initialprobe];
445*600Sbill 	} else {
446*600Sbill 		hdallop = emptyhd;
447*600Sbill 		hp = emptyslot;
448*600Sbill 	}
449*600Sbill 	if (instflg) {
450*600Sbill 		*hp = symalloc();
451*600Sbill 		hdallop->h_nused++;
452*600Sbill #ifndef FLEXNAMES
453*600Sbill 		for(len = 0, from = yytext, to = (*hp)->name; (len<NCPS); len++)
454*600Sbill  			if ((*to++ = *from++) == '\0')
455*600Sbill  				break;
456*600Sbill #else FLEXNAMES
457*600Sbill 		for (from = yytext, len = 1; *from++; len++)
458*600Sbill 			continue;
459*600Sbill 		if (len >= (STRPOOLDALLOP - strplhead->str_nalloc))
460*600Sbill 			strpoolalloc();
461*600Sbill 		for ( (*hp)->name = to = strplhead->str_names + strplhead->str_nalloc, from = yytext;
462*600Sbill 		     ( (*to++ = *from++) != '\0'); )
463*600Sbill 			continue;
464*600Sbill 		strplhead->str_nalloc += len;
465*600Sbill #endif FLEXNAMES
466*600Sbill 	}
467*600Sbill 	return(hp);
468*600Sbill }	/*end of lookup*/
469*600Sbill 
470*600Sbill char *savestr(str)
471*600Sbill 	char *str;
472*600Sbill {
473*600Sbill 	register int len;
474*600Sbill 	register char *from, *to;
475*600Sbill 	char *res;
476*600Sbill 
477*600Sbill 	for (from = str, len = 1; *from++; len++)
478*600Sbill 		continue;
479*600Sbill 	if (len >= (STRPOOLDALLOP - strplhead->str_nalloc))
480*600Sbill 		strpoolalloc();
481*600Sbill 	for ( res = to = strplhead->str_names + strplhead->str_nalloc, from = str;
482*600Sbill 		     ( (*to++ = *from++) != '\0'); )
483*600Sbill 			continue;
484*600Sbill 	strplhead->str_nalloc += len;
485*600Sbill 	return (res);
486*600Sbill }
487*600Sbill 
488*600Sbill /*
489*600Sbill  *	The following two tables are indexed by
490*600Sbill  *		{LEN1,LEN2,LEN4,LEN8} | {PCREL,0}
491*600Sbill  *	Note that PCREL = 1
492*600Sbill  */
493*600Sbill int	reflen[] = 	{0,   0, 1, 1, 2, 2, 4, 4, 8, 8};
494*600Sbill int	lgreflen[] = 	{-1, -1, 0, 0, 1, 1, 2, 2, 3, 3};
495*600Sbill 
496*600Sbill /*
497*600Sbill  *	The relocation information is saved internally in an array of
498*600Sbill  *	lists of relocation buffers.  The relocation buffers are
499*600Sbill  *	exactly the same size as a token buffer; if we use VM for the
500*600Sbill  *	temporary file we reclaim this storage, otherwise we create
501*600Sbill  *	them by mallocing.
502*600Sbill  */
503*600Sbill #define	RELBUFLG	TOKBUFLG
504*600Sbill #define	NRELOC		((TOKBUFLG - \
505*600Sbill 			  (sizeof (int) + sizeof (struct relbufdesc *)) \
506*600Sbill 			) / (sizeof (struct relocation_info)))
507*600Sbill 
508*600Sbill struct	relbufdesc{
509*600Sbill 	int	rel_count;
510*600Sbill 	struct	relbufdesc	*rel_next;
511*600Sbill 	struct	relocation_info	rel_reloc[NRELOC];
512*600Sbill };
513*600Sbill extern	struct	relbufdesc	*tok_free;
514*600Sbill #define	rel_free tok_free
515*600Sbill static	struct	relbufdesc	*rel_temp;
516*600Sbill struct	relocation_info r_can_1PC = {0,0,0,0,0,0};
517*600Sbill struct	relocation_info	r_can_0PC = {0,0,0,0,0,0};
518*600Sbill 
519*600Sbill initoutrel()
520*600Sbill {
521*600Sbill 	r_can_1PC.r_pcrel = 1;
522*600Sbill }
523*600Sbill 
524*600Sbill outrel(pval,reftype,reltype,xsym)
525*600Sbill 	long 		*pval;
526*600Sbill 	register int 	reftype,reltype;
527*600Sbill 	struct symtab 	*xsym;
528*600Sbill {
529*600Sbill /*
530*600Sbill  *	reftype: PCREL or not, plus length LEN1, LEN2, LEN4, LEN8
531*600Sbill  *	reltype: csect ("segment") number (XTEXT, XDATA, ...) associated with 'val'
532*600Sbill  * 	xsym: symbol table pointer
533*600Sbill  */
534*600Sbill 	short	this_reflen;
535*600Sbill 	struct	relocation_info	reloc;
536*600Sbill 
537*600Sbill 	this_reflen = reflen[reftype];
538*600Sbill 	if (bitoff&07)
539*600Sbill 		yyerror("Padding error");
540*600Sbill 	reltype &= ~XFORW;
541*600Sbill 	if (reltype == XUNDEF)
542*600Sbill 		yyerror("Undefined reference");
543*600Sbill 
544*600Sbill 	if (reltype != XABS || reftype & PCREL) {
545*600Sbill 		reloc = (reftype & PCREL)? r_can_1PC : r_can_0PC;
546*600Sbill 		reloc.r_address = dotp->xvalue -
547*600Sbill 			( (dotp < &usedot[NLOC]) ? 0 : datbase );
548*600Sbill 		reloc.r_length = lgreflen[reftype];
549*600Sbill 		switch(reltype){
550*600Sbill 			case XXTRN | XUNDEF:
551*600Sbill 				reloc.r_symbolnum = xsym->index;
552*600Sbill 				reloc.r_extern = 1;
553*600Sbill 				break;
554*600Sbill 			default:
555*600Sbill 				reloc.r_symbolnum = reltype;
556*600Sbill 				break;
557*600Sbill 		}
558*600Sbill 		if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
559*600Sbill 			if (rel_free){
560*600Sbill 				rel_temp = rel_free;
561*600Sbill 				rel_free = rel_temp->rel_next;
562*600Sbill 			} else {
563*600Sbill 				rel_temp = (struct relbufdesc *)
564*600Sbill 					Calloc(1,sizeof (struct relbufdesc));
565*600Sbill 			}
566*600Sbill 			rel_temp->rel_count = 0;
567*600Sbill 			rel_temp->rel_next = relfil;
568*600Sbill 			relfil = rusefile[dotp - &usedot[0]] = rel_temp;
569*600Sbill 		}
570*600Sbill 		relfil->rel_reloc[relfil->rel_count++] = reloc;
571*600Sbill 	}
572*600Sbill 	/*
573*600Sbill 	 *	write the unrelocated value to the text file
574*600Sbill 	 */
575*600Sbill 	dotp->xvalue += this_reflen;
576*600Sbill 	if (reftype & PCREL)
577*600Sbill 		*pval -= dotp->xvalue;
578*600Sbill 	bwrite((char *)pval, this_reflen, txtfil);
579*600Sbill }
580*600Sbill /*
581*600Sbill  *	Flush out all of the relocation information.
582*600Sbill  *	Note that the individual lists of buffers are in
583*600Sbill  *	reverse order, so we must reverse them
584*600Sbill  */
585*600Sbill off_t closeoutrel(relocfile)
586*600Sbill 	BFILE	*relocfile;
587*600Sbill {
588*600Sbill 	int	locindex;
589*600Sbill 	u_long	Closeoutrel();
590*600Sbill 
591*600Sbill 	trsize = 0;
592*600Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
593*600Sbill 		trsize += Closeoutrel(rusefile[locindex], relocfile);
594*600Sbill 	}
595*600Sbill 	drsize = 0;
596*600Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
597*600Sbill 		drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
598*600Sbill 	}
599*600Sbill 	return(trsize + drsize);
600*600Sbill }
601*600Sbill 
602*600Sbill u_long Closeoutrel(relfil, relocfile)
603*600Sbill 	struct	relbufdesc	*relfil;
604*600Sbill 	BFILE	*relocfile;
605*600Sbill {
606*600Sbill 	u_long	tail;
607*600Sbill 	if (relfil == 0)
608*600Sbill 		return(0L);
609*600Sbill 	tail = Closeoutrel(relfil->rel_next, relocfile);
610*600Sbill 	bwrite((char *)&relfil->rel_reloc[0],
611*600Sbill 		relfil->rel_count * sizeof (struct relocation_info),
612*600Sbill 		relocfile);
613*600Sbill 	return(tail + relfil->rel_count * sizeof (struct relocation_info));
614*600Sbill }
615*600Sbill 
616*600Sbill int sizesymtab()
617*600Sbill {
618*600Sbill 	struct symtab *sp;
619*600Sbill 
620*600Sbill #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
621*600Sbill 
622*600Sbill 	return (
623*600Sbill 		(
624*600Sbill #ifndef FLEXNAMES
625*600Sbill 		 NCPS
626*600Sbill #else FLEXNAMES
627*600Sbill 		 sizeof (long)
628*600Sbill #endif FLEXNAMES
629*600Sbill 		 + sizeof (sp->ptype)
630*600Sbill 		 + sizeof (sp->other)
631*600Sbill 		 + sizeof (sp->desc)
632*600Sbill 		 + sizeof (sp->value)
633*600Sbill 		)
634*600Sbill 		*	NOUTSYMS
635*600Sbill 	);
636*600Sbill }
637*600Sbill 
638*600Sbill #ifdef FLEXNAMES
639*600Sbill /*
640*600Sbill  *	We write out the flexible length character strings for  names
641*600Sbill  *	in two stages.
642*600Sbill  *	1)	We have always! maintain a fixed sized name list entry;
643*600Sbill  *	the string is indexed by a four byte quantity from the beginning
644*600Sbill  *	of the string pool area.  Index 0 is reserved, and indicates
645*600Sbill  *	that there is no associated string. The first valid index is 4.
646*600Sbill  *	2)	 We concatenate together and write all of the strings
647*600Sbill  *	in the string pool at the end of the name list. The first
648*600Sbill  *	four bytes in the string pool are indexed only by 0 (see above);
649*600Sbill  *	they contain the total number of bytes in the string pool.
650*600Sbill  */
651*600Sbill #endif FLEXNAMES
652*600Sbill 
653*600Sbill /*
654*600Sbill  *	Write out n symbols to file f, beginning at p
655*600Sbill  *	ignoring symbols that are obsolete, jxxx instructions, and
656*600Sbill  *	possibly, labels
657*600Sbill  */
658*600Sbill 
659*600Sbill int symwrite(symfile)
660*600Sbill 	BFILE *symfile;
661*600Sbill {
662*600Sbill 	int	symsout;			/*those actually written*/
663*600Sbill 	int	symsdesired = NOUTSYMS;
664*600Sbill 	register	struct	symtab *sp, *ub;
665*600Sbill #ifdef FLEXNAMES
666*600Sbill 	register	int	len;
667*600Sbill 	long		stroff	= sizeof (stroff);
668*600Sbill #endif FLEXNAMES
669*600Sbill 
670*600Sbill 	register	struct	allocbox	*allocwalk;
671*600Sbill 
672*600Sbill 	symsout = 0;
673*600Sbill 	DECLITERATE(allocwalk, sp, ub)
674*600Sbill 	{
675*600Sbill 		if (sp->tag >= IGNOREBOUND)
676*600Sbill 			continue;
677*600Sbill 		if ((sp->name[0] == 'L') && (sp->tag == LABELID) && !savelabels)
678*600Sbill 			continue;
679*600Sbill 		symsout++;
680*600Sbill #ifndef FLEXNAMES
681*600Sbill 		bwrite(sp->name, NCPS, symfile);
682*600Sbill #else FLEXNAMES
683*600Sbill 		len = strlen(sp->name);
684*600Sbill 		if (len != 0) {
685*600Sbill 			bwrite(&stroff, sizeof (stroff), symfile);
686*600Sbill 			stroff += len + 1;
687*600Sbill 		} else
688*600Sbill 			bwrite("\0\0\0\0", sizeof (stroff), symfile);
689*600Sbill #endif FLEXNAMES
690*600Sbill 		sp->type &= ~XFORW;
691*600Sbill 		bputc( ( (sp->ptype != 0) ? sp->ptype : sp->type ),
692*600Sbill 			symfile);
693*600Sbill 	/*
694*600Sbill 	 *	WATCH OUT.  THIS DEPENDS THAT THE ALLOCATION OF
695*600Sbill 	 *	the four fields ptype, other, desc and value are
696*600Sbill 	 *	contiguous, which is compiler dependent.
697*600Sbill 	 */
698*600Sbill 		bwrite((char *)&(sp->other),
699*600Sbill 			  sizeof (sp->other)
700*600Sbill 			+ sizeof (sp->desc)
701*600Sbill 		        + sizeof (sp->value),
702*600Sbill 		       symfile
703*600Sbill 		);
704*600Sbill 	}
705*600Sbill 	if (symsout != symsdesired)
706*600Sbill 		yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
707*600Sbill 			symsout, symsdesired);
708*600Sbill #ifdef FLEXNAMES
709*600Sbill 	/*
710*600Sbill 	 *	Pass 2 through the string pool
711*600Sbill 	 */
712*600Sbill 	symsout = 0;
713*600Sbill 	bwrite(&stroff, sizeof (stroff), symfile);
714*600Sbill 	stroff = sizeof (stroff);
715*600Sbill 	symsout = 0;
716*600Sbill 	DECLITERATE(allocwalk, sp, ub)
717*600Sbill 	{
718*600Sbill 		if (sp->tag >= IGNOREBOUND)
719*600Sbill 			continue;
720*600Sbill 		if ((sp->name[0] == 'L') && (sp->tag == LABELID) && !savelabels)
721*600Sbill 			continue;
722*600Sbill 		len = strlen(sp->name);
723*600Sbill 		if (len)
724*600Sbill 			bwrite(sp->name, len + 1, symfile);
725*600Sbill 	}
726*600Sbill #endif FLEXNAMES
727*600Sbill }
728