xref: /csrg-svn/old/as.vax/assyms.c (revision 675)
1600Sbill /* Copyright (c) 1980 Regents of the University of California */
2*675Shenry static	char sccsid[] = "@(#)assyms.c 4.5 08/20/80";
3600Sbill #include <stdio.h>
4600Sbill #include <ctype.h>
5600Sbill #include "as.h"
6600Sbill #include "asscan.h"
7600Sbill #include "assyms.h"
8600Sbill 
9600Sbill /*
10600Sbill  *	Managers for chunks of symbols allocated from calloc()
11600Sbill  *	We maintain a linked list of such chunks.
12600Sbill  *
13600Sbill  */
14600Sbill struct	allocbox	*allochead;	/*head of chunk list*/
15600Sbill struct	allocbox	*alloctail;	/*tail*/
16600Sbill struct	allocbox	*newbox;	/*for creating a new chunk*/
17600Sbill struct	symtab		*nextsym;	/*next symbol free*/
18600Sbill int			symsleft;	/*slots left in current chunk*/
19600Sbill 
20600Sbill struct	symtab		**symptrs;
21600Sbill struct	symtab		**symdelim[NLOC + NLOC +1];
22600Sbill struct	symtab		**symptrub;
23600Sbill /*
24600Sbill  *	Managers for the dynamically extendable hash table
25600Sbill  */
26600Sbill struct	hashdallop	*htab;
27600Sbill 
28600Sbill struct	instab		*itab[NINST];	/*maps opcodes to instructions*/
29600Sbill /*
30600Sbill  *	Counts what went into the symbol table, so that the
31600Sbill  *	size of the symbol table can be computed.
32600Sbill  */
33600Sbill int	nsyms;		/* total number in the symbol table */
34600Sbill int	njxxx;		/* number of jxxx entrys */
35600Sbill int	nforgotten;	/* number of symbols erroneously entered */
36600Sbill int	nlabels;	/* number of label entries */
37600Sbill int	hshused;	/* number of hash slots used */
38600Sbill 
39600Sbill /*
40600Sbill  *	Managers of the symbol literal storage.
41600Sbill  *	If we have flexible names, then we allocate BUFSIZ long
42600Sbill  *	string, and pack strings into that.  Otherwise, we allocate
43600Sbill  *	symbol storage in fixed hunks NCPS long when we allocate space
44600Sbill  *	for other symbol attributes.
45600Sbill  */
46600Sbill #ifdef	FLEXNAMES
47600Sbill struct	strpool		*strplhead = 0;
48634Shenry #endif	FLEXNAMES
49600Sbill 
50600Sbill symtabinit()
51600Sbill {
52600Sbill 	allochead = 0;
53600Sbill 	alloctail = 0;
54600Sbill 	nextsym = 0;
55600Sbill 	symsleft = 0;
56600Sbill #ifdef FLEXNAMES
57600Sbill 	strpoolalloc();		/* get the first strpool storage area */
58600Sbill #endif FLEXNAMES
59600Sbill 	htab = 0;
60600Sbill 	htaballoc();		/* get the first part of the hash table */
61600Sbill }
62600Sbill 
63600Sbill /*
64600Sbill  *	Install all known instructions in the symbol table
65600Sbill  */
66600Sbill syminstall()
67600Sbill {
68600Sbill 	register	struct	instab	*ip;
69600Sbill 	register	struct	symtab	**hp;
70600Sbill 	register	char	*p1, *p2;
71600Sbill 
72634Shenry #ifdef FLEXNAMES
73634Shenry 	for (ip = (struct instab *)instab; ip->s_name != 0; ip++) {
74634Shenry #else not FLEXNAMES
75634Shenry 	for (ip = (struct instab *)instab; ip->s_name[0] != '\0'; ip++){
76634Shenry #endif not FLEXNAMES
77634Shenry 		p1 = ip->s_name;
78600Sbill 		p2 = yytext;
79600Sbill 		while (*p2++ = *p1++);
80600Sbill 		hp = lookup(0);		/* 0 => don't install this*/
81600Sbill 		if (*hp==NULL) {
82600Sbill 			*hp = (struct symtab *)ip;
83634Shenry 			if (   (ip->s_tag!=INSTn)
84634Shenry 			    && (ip->s_tag!=INST0)
85634Shenry 			    && (ip->s_tag!=0))
86600Sbill 				continue; /* was pseudo-op */
87634Shenry 			itab[ip->i_opcode & 0xFF] = ip;
88600Sbill 		}
89600Sbill 	}
90600Sbill }	/*end of syminstall*/
91600Sbill 
92600Sbill 
93600Sbill /*
94600Sbill  *	Assign final values to symbols,
95600Sbill  *	and overwrite the index field with its relative position in
96600Sbill  *	the symbol table we give to the loader.
97600Sbill  */
98600Sbill extern struct exec hdr;
99600Sbill 
100600Sbill freezesymtab()
101600Sbill {
102600Sbill 	register	struct	symtab	*sp;
103600Sbill 				long	bs;
104600Sbill 	register	int	relpos = 0;
105600Sbill 	register	struct	symtab		*ubsp;
106600Sbill 	register	struct	allocbox	*allocwalk;
107600Sbill 
108600Sbill 	DECLITERATE(allocwalk, sp, ubsp)
109600Sbill 	{
110634Shenry 		if (sp->s_tag >= IGNOREBOUND)
111600Sbill 			continue; 		/*totally ignore jxxx entries */
112600Sbill 		/*
113600Sbill 		 *	Ignore stabs, but give them a symbol table index
114600Sbill 		 */
115634Shenry 		if (sp->s_type & STABFLAG)
116600Sbill 			goto assignindex;
117634Shenry 		if ((sp->s_type&XTYPE)==XUNDEF)
118634Shenry 			sp->s_type = XXTRN+XUNDEF;
119634Shenry 		else if ((sp->s_type&XTYPE)==XDATA)
120634Shenry 			sp->s_value += usedot[sp->s_index].e_xvalue;
121634Shenry 		else if ((sp->s_type&XTYPE)==XTEXT)
122634Shenry 			sp->s_value += usedot[sp->s_index].e_xvalue;
123634Shenry 		else if ((sp->s_type&XTYPE)==XBSS) {
124634Shenry 			bs = sp->s_value;
125634Shenry 			sp->s_value = hdr.a_bss + datbase;
126600Sbill 			hdr.a_bss += bs;
127600Sbill 		}
128600Sbill 	   assignindex:
129634Shenry 		if (    (sp->s_name[0] != 'L')
130634Shenry 		     || (sp->s_tag != LABELID)
131600Sbill 		     || savelabels
132600Sbill 		     )			/*then, we will write it later on*/
133634Shenry 				sp->s_index = relpos++;
134600Sbill 	}
135600Sbill }
136600Sbill 
137600Sbill 
138600Sbill 
139600Sbill /*
140600Sbill  *	For all of the stabs that had their final value undefined during pass 1
141600Sbill  *	and during pass 2 assign a final value.
142600Sbill  *	We have already given stab entrys a initial approximation
143600Sbill  *	when we constsructed the sorted symbol table.
144600Sbill  *	Iteration order doesn't matter.
145600Sbill  */
146600Sbill stabfix() {
147600Sbill 	register struct symtab *sp, **cosp;
148600Sbill 	register struct symtab *p;
149600Sbill 
150600Sbill 	SYMITERATE(cosp, sp){
151634Shenry 		if(sp->s_ptype && (sp->s_type & STABFLAG)) {
152634Shenry 			p = sp->s_dest;
153634Shenry 			sp->s_value = p->s_value;
154634Shenry 			sp->s_index = p->s_index;
155634Shenry 			sp->s_type = p->s_type;
156600Sbill 		}
157600Sbill 	}
158600Sbill }
159600Sbill 
160600Sbill char *Calloc(number, size)
161600Sbill 	int	number, size;
162600Sbill {
163600Sbill 	register	char *newstuff;
164600Sbill 	newstuff = (char *)sbrk(number*size);
165600Sbill 	if ((int)newstuff == -1){
166600Sbill 		yyerror("Ran out of Memory");
167600Sbill 		delexit();
168600Sbill 	}
169600Sbill 	return(newstuff);
170600Sbill }
171600Sbill 
172600Sbill char *ClearCalloc(number, size)
173600Sbill 	int	number, size;
174600Sbill {
175600Sbill 	register	char	*newstuff;		/* r11 */
176600Sbill 	register	int	length = number * size;	/* r10 */
177600Sbill 	newstuff = Calloc(number, size);
178600Sbill 	asm("movc5 $0, (r0), $0, r10, (r11)");
179600Sbill 	return(newstuff);
180600Sbill }
181600Sbill 
182600Sbill struct symtab *symalloc()
183600Sbill {
184600Sbill 	if (symsleft == 0){
185600Sbill 		newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
186600Sbill 		symsleft = SYMDALLOP;
187600Sbill 		nextsym = &newbox->symslots[0];
188600Sbill 		if (alloctail == 0){
189600Sbill 			allochead = alloctail = newbox;
190600Sbill 		} else {
191600Sbill 			alloctail->nextalloc = newbox;
192600Sbill 			alloctail = newbox;
193600Sbill 		}
194600Sbill 	}
195600Sbill 	--symsleft;
196600Sbill 	++nsyms;
197600Sbill 	return(nextsym++);
198600Sbill }
199600Sbill 
200600Sbill #ifdef FLEXNAMES
201600Sbill strpoolalloc()
202600Sbill {
203600Sbill 	register	struct	strpool	*new;
204600Sbill 
205600Sbill 	new = (struct strpool *)Calloc(1, sizeof (struct strpool));
206600Sbill 	new->str_nalloc = 0;
207600Sbill 	new->str_next = strplhead;
208600Sbill 	strplhead = new;
209600Sbill }
210600Sbill #endif FLEXNAMES
211600Sbill 
212600Sbill symcmp(Pptr, Qptr)
213600Sbill 	struct symtab **Pptr, **Qptr;
214600Sbill {
215600Sbill 	register struct symtab *p = *Pptr;
216600Sbill 	register struct symtab *q = *Qptr;
217634Shenry 	if (p->s_index < q->s_index)
218600Sbill 		return(-1);
219634Shenry 	if (p->s_index > q->s_index)
220600Sbill 		return(1);
221634Shenry 	if (p->s_value < q->s_value)
222600Sbill 		return(-1);
223634Shenry 	if (p->s_value > q->s_value)
224600Sbill 		return(1);
225600Sbill 	/*
226600Sbill 	 *	Force jxxx entries to virtually preceed labels defined
227600Sbill 	 *	to follow the jxxxx instruction, so that bumping the
228600Sbill 	 *	jxxx instruction correctly fixes up the following labels
229600Sbill 	 */
230634Shenry 	if (p->s_tag >= IGNOREBOUND)	/*p points to a jxxx*/
231600Sbill 		return(-1);
232634Shenry 	if (q->s_tag >= IGNOREBOUND)
233600Sbill 		return(1);
234600Sbill 	/*
235600Sbill 	 *	both are now just plain labels; the relative order doesn't
236600Sbill 	 *	matter.  Both can't be jxxxes, as they would have different
237600Sbill 	 *	values.
238600Sbill 	 */
239600Sbill 	return(0);
240600Sbill }	/*end of symcmp*/
241600Sbill 
242600Sbill /*
243600Sbill  *	We construct the auxiliary table of pointers, symptrs and
244600Sbill  *	symdelim
245600Sbill  *	We also assign preliminary values to stab entries that did not yet
246600Sbill  *	have an absolute value (because they initially referred to
247600Sbill  *	forward references). We don't worry about .stabds, as they
248600Sbill  *	already have an estimated final value
249600Sbill  */
250600Sbill 
251600Sbill sortsymtab()
252600Sbill {
253600Sbill 	register	struct	symtab	*sp;
254600Sbill 	register	struct	symtab	**cowalk;
255600Sbill 	register	struct	allocbox	*allocwalk;
256600Sbill 			struct	symtab	*ubsp;
257600Sbill 				int	segno;
258600Sbill 				int	slotno;
259600Sbill 				int	symsin;	/*number put into symptrs*/
260600Sbill 
261600Sbill 	symptrs =  (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
262600Sbill 	/*
263600Sbill 	 *	Allocate one word at the beginning of the symptr array
264600Sbill 	 *	so that backwards scans through the symptr array will
265600Sbill 	 *	work correctly while scanning through the zeroth segment
266600Sbill 	 */
267600Sbill 	*symptrs++ = 0;
268600Sbill 	cowalk = symptrs;
269600Sbill 	symsin = 0;
270600Sbill 	DECLITERATE(allocwalk, sp, ubsp) {
271634Shenry 		if (sp->s_ptype && (sp->s_type &STABFLAG)){
272634Shenry 			sp->s_value = sp->s_dest->s_value;
273634Shenry 			sp->s_index = sp->s_dest->s_index;
274600Sbill 		}
275600Sbill 		if (symsin >= nsyms)
276600Sbill 			yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
277600Sbill 		*cowalk++ = sp;
278600Sbill 		symsin++;
279600Sbill 	}
280600Sbill 	if (symsin != nsyms)
281600Sbill 		yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
282600Sbill 			symsin, nsyms);
283600Sbill 	symptrub = &symptrs[nsyms ];
284600Sbill 	qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
285600Sbill 	symdelim[0] = symptrs;
286600Sbill 	for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
287600Sbill 	     segno < NLOC + NLOC;
288600Sbill 	     segno++, slotno++){
289634Shenry 		for (; sp && sp->s_index == segno; sp = *++cowalk);
290600Sbill 		symdelim[slotno] = cowalk;	/*forms the ub delimeter*/
291600Sbill 	}
292600Sbill }	/*end of sortsymtab*/
293600Sbill 
294600Sbill #ifdef DEBUG
295600Sbill dumpsymtab()
296600Sbill {
297600Sbill 	register	int	segno;
298600Sbill 	register	struct symtab *sp, **cosp, *ub;
299600Sbill 	char		*tagstring();
300600Sbill 
301600Sbill 	printf("Symbol Table dump:\n");
302600Sbill 	for (segno = 0; segno < NLOC + NLOC; segno++){
303600Sbill 		printf("Segment number: %d\n", segno);
304600Sbill 		SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
305600Sbill #ifdef FLEXNAMES
306600Sbill 			printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
307634Shenry 				segno, sp->s_name,
308634Shenry 				sp->s_value, sp->s_index,
309634Shenry 				tagstring(sp->s_tag));
310600Sbill #else not FLEXNAMES
311600Sbill 			printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n",
312634Shenry 				segno, NCPS, NCPS, sp->s_name,
313634Shenry 				sp->s_value, sp->s_index,
314634Shenry 				tagstring(sp->s_tag));
315600Sbill #endif not FLEXNAMES
316600Sbill 			printf("\t\ttype: %d jxbump %d jxfear: %d\n",
317634Shenry 				sp->s_type, sp->s_jxbump, sp->s_jxfear);
318600Sbill 		}
319600Sbill 		printf("\n\n");
320600Sbill 	}
321600Sbill }
322600Sbill 
323600Sbill static	char tagbuff[4];
324600Sbill 
325600Sbill char *tagstring(tag)
326600Sbill 	unsigned	char	tag;
327600Sbill {
328600Sbill 	switch(tag){
329600Sbill 		case JXACTIVE:		return("active");
330600Sbill 		case JXNOTYET:		return("notyet");
331600Sbill 		case JXALIGN:		return("align");
332600Sbill 		case JXQUESTIONABLE:	return("jxquestionable");
333600Sbill 		case JXINACTIVE:	return("inactive");
334600Sbill 		case JXTUNNEL:		return("tunnel");
335600Sbill 		case OBSOLETE:		return("obsolete");
336600Sbill 		case IGNOREBOUND:	return("ignorebound");
337600Sbill 		case STABFLOATING:	return("stabfloating");
338600Sbill 		case STABFIXED:		return("stabfixed");
339600Sbill 		case LABELID:		return("labelid");
340600Sbill 		case OKTOBUMP:		return("oktobump");
341600Sbill 		case ISET:		return("iset");
342600Sbill 		case ILSYM:		return("ilsym");
343600Sbill 		default:		sprintf(tagbuff,"%d", tag);
344600Sbill 					return(tagbuff);
345600Sbill 	}
346600Sbill }
347600Sbill #endif DEBUG
348600Sbill 
349600Sbill htaballoc()
350600Sbill {
351600Sbill 	register	struct	hashdallop	*new;
352600Sbill 	new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
353600Sbill 	if (htab == 0)
354600Sbill 		htab = new;
355600Sbill 	else {		/* add AFTER the 1st slot */
356600Sbill 		new->h_next = htab->h_next;
357600Sbill 		htab->h_next = new;
358600Sbill 	}
359600Sbill }
360600Sbill 
361600Sbill #define 	HASHCLOGGED	(NHASH / 2)
362600Sbill 
363600Sbill /*
364600Sbill  *	Lookup a symbol stored in extern yytext.
365600Sbill  *	All strings passed in via extern yytext had better have
366600Sbill  *	a trailing null.  Strings are placed in yytext for hashing by
367600Sbill  *	syminstall() and by yylex();
368600Sbill  *
369600Sbill  *	We take pains to avoid function calls; this functdion
370600Sbill  *	is called quite frequently, and the calls overhead
371600Sbill  *	in the vax contributes significantly to the overall
372600Sbill  *	execution speed of as.
373600Sbill  */
374600Sbill struct symtab **lookup(instflg)
375600Sbill 	int	instflg;		/* 0: don't install */
376600Sbill {
377600Sbill 	static	 int		initialprobe;
378600Sbill 	register struct	symtab 	**hp;
379600Sbill 	register char 		*from;
380600Sbill 	register char		*to;
381600Sbill 	register	int	len;
382600Sbill 	register	int	nprobes;
383600Sbill 	static	 struct hashdallop *hdallop;
384600Sbill 	static	 struct symtab	**emptyslot;
385600Sbill 	static 	 struct hashdallop *emptyhd;
386600Sbill 	static	 struct	symtab	**hp_ub;
387600Sbill 
388600Sbill 	emptyslot = 0;
389600Sbill 	for (nprobes = 0, from = yytext;
390600Sbill 	     *from;
391600Sbill 	     nprobes <<= 2, nprobes += *from++)
392600Sbill 		continue;
393600Sbill 	nprobes += from[-1] << 5;
394600Sbill 	nprobes %= NHASH;
395600Sbill 	if (nprobes < 0)
396600Sbill 		nprobes += NHASH;
397600Sbill 
398600Sbill 	initialprobe = nprobes;
399600Sbill 	for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
400600Sbill 		for (hp = &(hdallop->h_htab[initialprobe]),
401600Sbill 				nprobes = 1,
402600Sbill 				hp_ub = &(hdallop->h_htab[NHASH]);
403600Sbill 		     (*hp) && (nprobes < NHASH);
404600Sbill 				hp += nprobes,
405600Sbill 				hp -= (hp >= hp_ub) ? NHASH:0,
406600Sbill 				nprobes += 2)
407600Sbill 		{
408600Sbill 			from = yytext;
409634Shenry 			to = (*hp)->s_name;
410600Sbill #ifndef FLEXNAMES
411600Sbill 			for (len = 0; (len<NCPS) && *from; len++)
412600Sbill 				if (*from++ != *to++)
413600Sbill 					goto nextprobe;
414600Sbill 			if (len >= NCPS)	/*both are maximal length*/
415600Sbill 				return(hp);
416600Sbill 			if (*to == 0)		/*assert *from == 0*/
417600Sbill 				return(hp);
418600Sbill #else FLEXNAMES
419600Sbill 			while (*from && *to)
420600Sbill 				if (*from++ != *to++)
421600Sbill 					goto nextprobe;
422600Sbill 			if (*to == *from)	/*assert both are == 0*/
423600Sbill 				return(hp);
424600Sbill #endif FLEXNAMES
425600Sbill 
426600Sbill 	nextprobe: ;
427600Sbill 		}
428600Sbill 		if (*hp == 0 && emptyslot == 0 &&
429600Sbill 		    hdallop->h_nused < HASHCLOGGED) {
430600Sbill 			emptyslot = hp;
431600Sbill 			emptyhd = hdallop;
432600Sbill 		}
433600Sbill 	}
434600Sbill 	if (emptyslot == 0) {
435600Sbill 		htaballoc();
436600Sbill 		hdallop = htab->h_next;		/* aren't we smart! */
437600Sbill 		hp = &hdallop->h_htab[initialprobe];
438600Sbill 	} else {
439600Sbill 		hdallop = emptyhd;
440600Sbill 		hp = emptyslot;
441600Sbill 	}
442600Sbill 	if (instflg) {
443600Sbill 		*hp = symalloc();
444600Sbill 		hdallop->h_nused++;
445600Sbill #ifndef FLEXNAMES
446634Shenry 		for(len = 0, from = yytext, to = (*hp)->s_name; (len<NCPS); len++)
447600Sbill  			if ((*to++ = *from++) == '\0')
448600Sbill  				break;
449600Sbill #else FLEXNAMES
450600Sbill 		for (from = yytext, len = 1; *from++; len++)
451600Sbill 			continue;
452600Sbill 		if (len >= (STRPOOLDALLOP - strplhead->str_nalloc))
453600Sbill 			strpoolalloc();
454634Shenry 		for ( (*hp)->s_name = to = strplhead->str_names + strplhead->str_nalloc, from = yytext;
455600Sbill 		     ( (*to++ = *from++) != '\0'); )
456600Sbill 			continue;
457600Sbill 		strplhead->str_nalloc += len;
458600Sbill #endif FLEXNAMES
459600Sbill 	}
460600Sbill 	return(hp);
461600Sbill }	/*end of lookup*/
462600Sbill 
463600Sbill char *savestr(str)
464600Sbill 	char *str;
465600Sbill {
466600Sbill 	register int len;
467600Sbill 	register char *from, *to;
468600Sbill 	char *res;
469600Sbill 
470600Sbill 	for (from = str, len = 1; *from++; len++)
471600Sbill 		continue;
472600Sbill 	if (len >= (STRPOOLDALLOP - strplhead->str_nalloc))
473600Sbill 		strpoolalloc();
474600Sbill 	for ( res = to = strplhead->str_names + strplhead->str_nalloc, from = str;
475600Sbill 		     ( (*to++ = *from++) != '\0'); )
476600Sbill 			continue;
477600Sbill 	strplhead->str_nalloc += len;
478600Sbill 	return (res);
479600Sbill }
480600Sbill 
481600Sbill /*
482600Sbill  *	The relocation information is saved internally in an array of
483600Sbill  *	lists of relocation buffers.  The relocation buffers are
484600Sbill  *	exactly the same size as a token buffer; if we use VM for the
485600Sbill  *	temporary file we reclaim this storage, otherwise we create
486600Sbill  *	them by mallocing.
487600Sbill  */
488600Sbill #define	RELBUFLG	TOKBUFLG
489600Sbill #define	NRELOC		((TOKBUFLG - \
490600Sbill 			  (sizeof (int) + sizeof (struct relbufdesc *)) \
491600Sbill 			) / (sizeof (struct relocation_info)))
492600Sbill 
493600Sbill struct	relbufdesc{
494600Sbill 	int	rel_count;
495600Sbill 	struct	relbufdesc	*rel_next;
496600Sbill 	struct	relocation_info	rel_reloc[NRELOC];
497600Sbill };
498600Sbill extern	struct	relbufdesc	*tok_free;
499600Sbill #define	rel_free tok_free
500600Sbill static	struct	relbufdesc	*rel_temp;
501634Shenry struct	relocation_info r_can_1PC;
502634Shenry struct	relocation_info	r_can_0PC;
503600Sbill 
504600Sbill initoutrel()
505600Sbill {
506634Shenry 	r_can_0PC.r_address = 0;
507634Shenry 	r_can_0PC.r_symbolnum = 0;
508634Shenry 	r_can_0PC.r_pcrel = 0;
509634Shenry 	r_can_0PC.r_length = 0;
510634Shenry 	r_can_0PC.r_extern = 0;
511634Shenry 
512634Shenry 	r_can_1PC = r_can_0PC;
513600Sbill 	r_can_1PC.r_pcrel = 1;
514600Sbill }
515600Sbill 
516*675Shenry outrel(xp, reloc_how)
517*675Shenry 	register	struct	exp	*xp;
518*675Shenry 	int		reloc_how;	/* TYPB..TYPD + (possibly)RELOC_PCREL */
519600Sbill {
520*675Shenry 	struct		relocation_info	reloc;
521*675Shenry 	register	int	x_type_mask;
522*675Shenry 	int		pcrel;
523600Sbill 
524*675Shenry 	x_type_mask = xp->e_xtype & ~XFORW;
525*675Shenry 	pcrel = reloc_how & RELOC_PCREL;
526*675Shenry 	reloc_how &= ~RELOC_PCREL;
527*675Shenry 
528600Sbill 	if (bitoff&07)
529600Sbill 		yyerror("Padding error");
530*675Shenry 	if (x_type_mask == XUNDEF)
531600Sbill 		yyerror("Undefined reference");
532600Sbill 
533*675Shenry 	if ( (x_type_mask != XABS) || pcrel ) {
534*675Shenry 		if (ty_NORELOC[reloc_how])
535*675Shenry 			yyerror("Illegal Relocation of float, double or quad.");
536*675Shenry 		reloc = pcrel ? r_can_1PC : r_can_0PC;
537634Shenry 		reloc.r_address = dotp->e_xvalue -
538640Sbill 		    ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
539*675Shenry 		reloc.r_length = ty_nlg[reloc_how];
540*675Shenry 		switch(x_type_mask){
541600Sbill 			case XXTRN | XUNDEF:
542*675Shenry 				reloc.r_symbolnum = xp->e_xname->s_index;
543600Sbill 				reloc.r_extern = 1;
544600Sbill 				break;
545600Sbill 			default:
546*675Shenry 				if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
547*675Shenry 					x_type_mask = XTEXT | (x_type_mask&XXTRN);
548*675Shenry 				reloc.r_symbolnum = x_type_mask;
549600Sbill 				break;
550600Sbill 		}
551600Sbill 		if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
552600Sbill 			if (rel_free){
553600Sbill 				rel_temp = rel_free;
554600Sbill 				rel_free = rel_temp->rel_next;
555600Sbill 			} else {
556600Sbill 				rel_temp = (struct relbufdesc *)
557600Sbill 					Calloc(1,sizeof (struct relbufdesc));
558600Sbill 			}
559600Sbill 			rel_temp->rel_count = 0;
560600Sbill 			rel_temp->rel_next = relfil;
561600Sbill 			relfil = rusefile[dotp - &usedot[0]] = rel_temp;
562600Sbill 		}
563600Sbill 		relfil->rel_reloc[relfil->rel_count++] = reloc;
564600Sbill 	}
565600Sbill 	/*
566600Sbill 	 *	write the unrelocated value to the text file
567600Sbill 	 */
568*675Shenry 	dotp->e_xvalue += ty_nbyte[reloc_how];
569*675Shenry 	if (pcrel)
570*675Shenry 		xp->e_xvalue -= dotp->e_xvalue;
571*675Shenry 	bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
572600Sbill }
573600Sbill /*
574600Sbill  *	Flush out all of the relocation information.
575600Sbill  *	Note that the individual lists of buffers are in
576600Sbill  *	reverse order, so we must reverse them
577600Sbill  */
578600Sbill off_t closeoutrel(relocfile)
579600Sbill 	BFILE	*relocfile;
580600Sbill {
581600Sbill 	int	locindex;
582600Sbill 	u_long	Closeoutrel();
583600Sbill 
584600Sbill 	trsize = 0;
585600Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
586600Sbill 		trsize += Closeoutrel(rusefile[locindex], relocfile);
587600Sbill 	}
588600Sbill 	drsize = 0;
589600Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
590600Sbill 		drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
591600Sbill 	}
592600Sbill 	return(trsize + drsize);
593600Sbill }
594600Sbill 
595600Sbill u_long Closeoutrel(relfil, relocfile)
596600Sbill 	struct	relbufdesc	*relfil;
597600Sbill 	BFILE	*relocfile;
598600Sbill {
599600Sbill 	u_long	tail;
600600Sbill 	if (relfil == 0)
601600Sbill 		return(0L);
602600Sbill 	tail = Closeoutrel(relfil->rel_next, relocfile);
603600Sbill 	bwrite((char *)&relfil->rel_reloc[0],
604600Sbill 		relfil->rel_count * sizeof (struct relocation_info),
605600Sbill 		relocfile);
606600Sbill 	return(tail + relfil->rel_count * sizeof (struct relocation_info));
607600Sbill }
608600Sbill 
609634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
610600Sbill int sizesymtab()
611600Sbill {
612634Shenry 	return (sizeof (struct nlist) * NOUTSYMS);
613600Sbill }
614600Sbill 
615600Sbill #ifdef FLEXNAMES
616600Sbill /*
617600Sbill  *	We write out the flexible length character strings for  names
618600Sbill  *	in two stages.
619600Sbill  *	1)	We have always! maintain a fixed sized name list entry;
620600Sbill  *	the string is indexed by a four byte quantity from the beginning
621600Sbill  *	of the string pool area.  Index 0 is reserved, and indicates
622600Sbill  *	that there is no associated string. The first valid index is 4.
623600Sbill  *	2)	 We concatenate together and write all of the strings
624600Sbill  *	in the string pool at the end of the name list. The first
625600Sbill  *	four bytes in the string pool are indexed only by 0 (see above);
626600Sbill  *	they contain the total number of bytes in the string pool.
627600Sbill  */
628600Sbill #endif FLEXNAMES
629600Sbill 
630600Sbill /*
631600Sbill  *	Write out n symbols to file f, beginning at p
632600Sbill  *	ignoring symbols that are obsolete, jxxx instructions, and
633600Sbill  *	possibly, labels
634600Sbill  */
635600Sbill 
636600Sbill int symwrite(symfile)
637600Sbill 	BFILE *symfile;
638600Sbill {
639600Sbill 	int	symsout;			/*those actually written*/
640600Sbill 	int	symsdesired = NOUTSYMS;
641600Sbill 	register	struct	symtab *sp, *ub;
642600Sbill #ifdef FLEXNAMES
643634Shenry 	char		*name;			/* temp to save the name */
644600Sbill 	long		stroff	= sizeof (stroff);
645634Shenry 	/*
646634Shenry 	 *	We use sp->s_index to hold the length of the
647634Shenry 	 *	name; it isn't used for anything else
648634Shenry 	 */
649600Sbill #endif FLEXNAMES
650600Sbill 
651600Sbill 	register	struct	allocbox	*allocwalk;
652600Sbill 
653600Sbill 	symsout = 0;
654600Sbill 	DECLITERATE(allocwalk, sp, ub)
655600Sbill 	{
656634Shenry 		if (sp->s_tag >= IGNOREBOUND)
657600Sbill 			continue;
658634Shenry 		if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels)
659600Sbill 			continue;
660600Sbill 		symsout++;
661634Shenry 
662634Shenry #ifdef FLEXNAMES
663634Shenry 		name = sp->s_name;		/* save pointer */
664634Shenry 		if ( (sp->s_index = strlen(sp->s_name)) != 0){
665634Shenry 			sp->s_nmx = stroff;	/* clobber pointer */
666634Shenry 			stroff += sp->s_index + 1;
667634Shenry 		} else {
668634Shenry 			sp->s_nmx = 0;		/* clobber pointer */
669634Shenry 		}
670634Shenry #endif
671634Shenry 		sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW));
672640Sbill 		if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
673640Sbill 			sp->s_type = N_TEXT | (sp->s_type & N_EXT);
674634Shenry 		bwrite(&sp->s_nm, sizeof (struct nlist), symfile);
675634Shenry #ifdef FLEXNAMES
676634Shenry 		sp->s_name = name;		/* restore pointer */
677600Sbill #endif FLEXNAMES
678600Sbill 	}
679600Sbill 	if (symsout != symsdesired)
680600Sbill 		yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
681600Sbill 			symsout, symsdesired);
682600Sbill #ifdef FLEXNAMES
683600Sbill 	/*
684600Sbill 	 *	Pass 2 through the string pool
685600Sbill 	 */
686600Sbill 	symsout = 0;
687600Sbill 	bwrite(&stroff, sizeof (stroff), symfile);
688600Sbill 	stroff = sizeof (stroff);
689600Sbill 	symsout = 0;
690600Sbill 	DECLITERATE(allocwalk, sp, ub)
691600Sbill 	{
692634Shenry 		if (sp->s_tag >= IGNOREBOUND)
693600Sbill 			continue;
694634Shenry 		if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels)
695600Sbill 			continue;
696634Shenry 		sp->s_index = strlen(sp->s_name);
697634Shenry 		if (sp->s_index)
698634Shenry 			bwrite(sp->s_name, sp->s_index + 1, symfile);
699600Sbill 	}
700600Sbill #endif FLEXNAMES
701600Sbill }
702