xref: /csrg-svn/old/as.vax/assyms.c (revision 19833)
15828Srrh /*
2*19833Sdist  * Copyright (c) 1982 Regents of the University of California.
3*19833Sdist  * All rights reserved.  The Berkeley software License Agreement
4*19833Sdist  * specifies the terms and conditions for redistribution.
55828Srrh  */
6*19833Sdist 
75828Srrh #ifndef lint
8*19833Sdist static char sccsid[] = "@(#)assyms.c	5.1 (Berkeley) 04/30/85";
95828Srrh #endif not lint
105828Srrh 
11600Sbill #include <stdio.h>
12600Sbill #include <ctype.h>
13600Sbill #include "as.h"
14600Sbill #include "asscan.h"
15600Sbill #include "assyms.h"
16600Sbill 
17600Sbill /*
18600Sbill  *	Managers for chunks of symbols allocated from calloc()
19600Sbill  *	We maintain a linked list of such chunks.
20600Sbill  *
21600Sbill  */
22600Sbill struct	allocbox	*allochead;	/*head of chunk list*/
23600Sbill struct	allocbox	*alloctail;	/*tail*/
24600Sbill struct	allocbox	*newbox;	/*for creating a new chunk*/
25600Sbill struct	symtab		*nextsym;	/*next symbol free*/
26600Sbill int			symsleft;	/*slots left in current chunk*/
27600Sbill 
28600Sbill struct	symtab		**symptrs;
29600Sbill struct	symtab		**symdelim[NLOC + NLOC +1];
30600Sbill struct	symtab		**symptrub;
31600Sbill /*
32600Sbill  *	Managers for the dynamically extendable hash table
33600Sbill  */
34600Sbill struct	hashdallop	*htab;
35600Sbill 
365828Srrh Iptr	*itab[NINST];	/*maps opcodes to instructions*/
37600Sbill /*
38600Sbill  *	Counts what went into the symbol table, so that the
39600Sbill  *	size of the symbol table can be computed.
40600Sbill  */
41600Sbill int	nsyms;		/* total number in the symbol table */
42600Sbill int	njxxx;		/* number of jxxx entrys */
43600Sbill int	nforgotten;	/* number of symbols erroneously entered */
44600Sbill int	nlabels;	/* number of label entries */
45600Sbill 
46600Sbill /*
47600Sbill  *	Managers of the symbol literal storage.
48600Sbill  */
49600Sbill struct	strpool		*strplhead = 0;
50600Sbill 
51600Sbill symtabinit()
52600Sbill {
53600Sbill 	allochead = 0;
54600Sbill 	alloctail = 0;
55600Sbill 	nextsym = 0;
56600Sbill 	symsleft = 0;
57600Sbill 	strpoolalloc();		/* get the first strpool storage area */
58600Sbill 	htab = 0;
59600Sbill 	htaballoc();		/* get the first part of the hash table */
60600Sbill }
61600Sbill 
62600Sbill /*
63600Sbill  *	Install all known instructions in the symbol table
64600Sbill  */
65600Sbill syminstall()
66600Sbill {
675828Srrh 	register	Iptr	ip;
68600Sbill 	register	struct	symtab	**hp;
69600Sbill 	register	char	*p1, *p2;
705828Srrh 	register	int	i;
71600Sbill 
725828Srrh 	for (i = 0; i < NINST; i++)
735828Srrh 		itab[i] = (Iptr*)BADPOINT;
745828Srrh 
7513514Srrh 	for (ip = (Iptr)instab; FETCHNAME(ip)[0]; ip++) {
7613514Srrh 		p1 = FETCHNAME(ip);
77600Sbill 		p2 = yytext;
78600Sbill 		while (*p2++ = *p1++);
79600Sbill 		hp = lookup(0);		/* 0 => don't install this*/
80600Sbill 		if (*hp==NULL) {
81600Sbill 			*hp = (struct symtab *)ip;
82634Shenry 			if (   (ip->s_tag!=INSTn)
83634Shenry 			    && (ip->s_tag!=INST0)
84634Shenry 			    && (ip->s_tag!=0))
85600Sbill 				continue; /* was pseudo-op */
865828Srrh 			if (itab[ip->i_eopcode] == (Iptr*)BADPOINT){
875828Srrh 				itab[ip->i_eopcode] =
885828Srrh 					(Iptr*)ClearCalloc(256, sizeof(Iptr));
895828Srrh 				for (i = 0; i < 256; i++)
905828Srrh 					itab[ip->i_eopcode][i] =
915828Srrh 						(Iptr)BADPOINT;
925828Srrh 			}
935828Srrh 			itab[ip->i_eopcode][ip->i_popcode] = ip;
94600Sbill 		}
95600Sbill 	}
96600Sbill }	/*end of syminstall*/
97600Sbill 
9814450Srrh #define ISLABEL(sp) \
9914450Srrh 	(   (!savelabels) \
10014450Srrh 	 && (sp->s_tag == LABELID) \
10114450Srrh 	 && (STRPLACE(sp) & STR_CORE) \
10214450Srrh 	 && (FETCHNAME(sp)[0] == 'L'))
103600Sbill /*
104600Sbill  *	Assign final values to symbols,
105600Sbill  *	and overwrite the index field with its relative position in
106600Sbill  *	the symbol table we give to the loader.
107600Sbill  */
108600Sbill extern struct exec hdr;
109600Sbill 
110600Sbill freezesymtab()
111600Sbill {
112600Sbill 	register	struct	symtab	*sp;
113600Sbill 				long	bs;
114600Sbill 	register	int	relpos = 0;
115600Sbill 	register	struct	symtab		*ubsp;
116600Sbill 	register	struct	allocbox	*allocwalk;
117600Sbill 
118600Sbill 	DECLITERATE(allocwalk, sp, ubsp)
119600Sbill 	{
120634Shenry 		if (sp->s_tag >= IGNOREBOUND)
121600Sbill 			continue; 		/*totally ignore jxxx entries */
122600Sbill 		/*
123600Sbill 		 *	Ignore stabs, but give them a symbol table index
124600Sbill 		 */
125634Shenry 		if (sp->s_type & STABFLAG)
126600Sbill 			goto assignindex;
127634Shenry 		if ((sp->s_type&XTYPE)==XUNDEF)
128634Shenry 			sp->s_type = XXTRN+XUNDEF;
129634Shenry 		else if ((sp->s_type&XTYPE)==XDATA)
130634Shenry 			sp->s_value += usedot[sp->s_index].e_xvalue;
131634Shenry 		else if ((sp->s_type&XTYPE)==XTEXT)
132634Shenry 			sp->s_value += usedot[sp->s_index].e_xvalue;
133634Shenry 		else if ((sp->s_type&XTYPE)==XBSS) {
134634Shenry 			bs = sp->s_value;
135634Shenry 			sp->s_value = hdr.a_bss + datbase;
136600Sbill 			hdr.a_bss += bs;
137600Sbill 		}
138600Sbill 	   assignindex:
13914450Srrh 		if (!ISLABEL(sp))
14014450Srrh 			sp->s_index = relpos++;
141600Sbill 	}
142600Sbill }
143600Sbill 
144600Sbill /*
145600Sbill  *	For all of the stabs that had their final value undefined during pass 1
146600Sbill  *	and during pass 2 assign a final value.
147600Sbill  *	We have already given stab entrys a initial approximation
148600Sbill  *	when we constsructed the sorted symbol table.
149600Sbill  *	Iteration order doesn't matter.
150600Sbill  */
15112592Scsvaf 
15212592Scsvaf stabfix()
15312592Scsvaf {
154600Sbill 	register struct symtab *sp, **cosp;
155600Sbill 	register struct symtab *p;
156600Sbill 
157600Sbill 	SYMITERATE(cosp, sp){
158634Shenry 		if(sp->s_ptype && (sp->s_type & STABFLAG)) {
159634Shenry 			p = sp->s_dest;
16012592Scsvaf /*
16112592Scsvaf  * STABFLOATING indicates that the offset has been saved in s_desc, s_other
16212592Scsvaf  */
16312592Scsvaf 			if(sp->s_tag == STABFLOATING) {
16412592Scsvaf 			  sp->s_value = ( ( ((unsigned char) sp->s_other) << 16)  					| ( (unsigned short) sp->s_desc )  );
16512592Scsvaf 			  sp->s_value = sp->s_value + p->s_value;
16612592Scsvaf 			}
16712592Scsvaf 			else sp->s_value = p->s_value;
168634Shenry 			sp->s_index = p->s_index;
169634Shenry 			sp->s_type = p->s_type;
17012592Scsvaf 
17112592Scsvaf 
172600Sbill 		}
173600Sbill 	}
174600Sbill }
175600Sbill 
176600Sbill char *Calloc(number, size)
177600Sbill 	int	number, size;
178600Sbill {
179600Sbill 	register	char *newstuff;
1805828Srrh 	char	*sbrk();
1815828Srrh 	newstuff = sbrk(number*size);
182600Sbill 	if ((int)newstuff == -1){
183600Sbill 		yyerror("Ran out of Memory");
184600Sbill 		delexit();
185600Sbill 	}
186600Sbill 	return(newstuff);
187600Sbill }
188600Sbill 
189600Sbill char *ClearCalloc(number, size)
190600Sbill 	int	number, size;
191600Sbill {
192600Sbill 	register	char	*newstuff;		/* r11 */
193600Sbill 	register	int	length = number * size;	/* r10 */
1945828Srrh #ifdef lint
1955828Srrh 	length = length;
1965828Srrh #endif length
197600Sbill 	newstuff = Calloc(number, size);
198600Sbill 	asm("movc5 $0, (r0), $0, r10, (r11)");
199600Sbill 	return(newstuff);
200600Sbill }
201600Sbill 
202600Sbill struct symtab *symalloc()
203600Sbill {
204600Sbill 	if (symsleft == 0){
205600Sbill 		newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
206600Sbill 		symsleft = SYMDALLOP;
207600Sbill 		nextsym = &newbox->symslots[0];
208600Sbill 		if (alloctail == 0){
209600Sbill 			allochead = alloctail = newbox;
210600Sbill 		} else {
211600Sbill 			alloctail->nextalloc = newbox;
212600Sbill 			alloctail = newbox;
213600Sbill 		}
214600Sbill 	}
215600Sbill 	--symsleft;
216600Sbill 	++nsyms;
217600Sbill 	return(nextsym++);
218600Sbill }
219600Sbill 
220600Sbill strpoolalloc()
221600Sbill {
222600Sbill 	register	struct	strpool	*new;
223600Sbill 
224600Sbill 	new = (struct strpool *)Calloc(1, sizeof (struct strpool));
225600Sbill 	new->str_nalloc = 0;
226600Sbill 	new->str_next = strplhead;
227600Sbill 	strplhead = new;
228600Sbill }
229600Sbill 
230600Sbill symcmp(Pptr, Qptr)
231600Sbill 	struct symtab **Pptr, **Qptr;
232600Sbill {
233600Sbill 	register struct symtab *p = *Pptr;
234600Sbill 	register struct symtab *q = *Qptr;
235634Shenry 	if (p->s_index < q->s_index)
236600Sbill 		return(-1);
237634Shenry 	if (p->s_index > q->s_index)
238600Sbill 		return(1);
239634Shenry 	if (p->s_value < q->s_value)
240600Sbill 		return(-1);
241634Shenry 	if (p->s_value > q->s_value)
242600Sbill 		return(1);
243600Sbill 	/*
244600Sbill 	 *	Force jxxx entries to virtually preceed labels defined
245600Sbill 	 *	to follow the jxxxx instruction, so that bumping the
246600Sbill 	 *	jxxx instruction correctly fixes up the following labels
247600Sbill 	 */
248634Shenry 	if (p->s_tag >= IGNOREBOUND)	/*p points to a jxxx*/
249600Sbill 		return(-1);
250634Shenry 	if (q->s_tag >= IGNOREBOUND)
251600Sbill 		return(1);
252600Sbill 	/*
253600Sbill 	 *	both are now just plain labels; the relative order doesn't
254600Sbill 	 *	matter.  Both can't be jxxxes, as they would have different
255600Sbill 	 *	values.
256600Sbill 	 */
257600Sbill 	return(0);
258600Sbill }	/*end of symcmp*/
259600Sbill 
260600Sbill /*
261600Sbill  *	We construct the auxiliary table of pointers, symptrs and
262600Sbill  *	symdelim
263600Sbill  *	We also assign preliminary values to stab entries that did not yet
264600Sbill  *	have an absolute value (because they initially referred to
265600Sbill  *	forward references). We don't worry about .stabds, as they
266600Sbill  *	already have an estimated final value
267600Sbill  */
268600Sbill 
269600Sbill sortsymtab()
270600Sbill {
271600Sbill 	register	struct	symtab	*sp;
272600Sbill 	register	struct	symtab	**cowalk;
273600Sbill 	register	struct	allocbox	*allocwalk;
274600Sbill 			struct	symtab	*ubsp;
275600Sbill 				int	segno;
276600Sbill 				int	slotno;
277600Sbill 				int	symsin;	/*number put into symptrs*/
278600Sbill 
279600Sbill 	symptrs =  (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
280600Sbill 	/*
281600Sbill 	 *	Allocate one word at the beginning of the symptr array
282600Sbill 	 *	so that backwards scans through the symptr array will
283600Sbill 	 *	work correctly while scanning through the zeroth segment
284600Sbill 	 */
285600Sbill 	*symptrs++ = 0;
286600Sbill 	cowalk = symptrs;
287600Sbill 	symsin = 0;
288600Sbill 	DECLITERATE(allocwalk, sp, ubsp) {
289634Shenry 		if (sp->s_ptype && (sp->s_type &STABFLAG)){
290634Shenry 			sp->s_value = sp->s_dest->s_value;
291634Shenry 			sp->s_index = sp->s_dest->s_index;
292600Sbill 		}
293600Sbill 		if (symsin >= nsyms)
294600Sbill 			yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
295600Sbill 		*cowalk++ = sp;
296600Sbill 		symsin++;
297600Sbill 	}
298600Sbill 	if (symsin != nsyms)
299600Sbill 		yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
300600Sbill 			symsin, nsyms);
301600Sbill 	symptrub = &symptrs[nsyms ];
302600Sbill 	qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
303600Sbill 	symdelim[0] = symptrs;
304600Sbill 	for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
305600Sbill 	     segno < NLOC + NLOC;
306600Sbill 	     segno++, slotno++){
307634Shenry 		for (; sp && sp->s_index == segno; sp = *++cowalk);
308600Sbill 		symdelim[slotno] = cowalk;	/*forms the ub delimeter*/
309600Sbill 	}
310600Sbill }	/*end of sortsymtab*/
311600Sbill 
312600Sbill #ifdef DEBUG
313600Sbill dumpsymtab()
314600Sbill {
315600Sbill 	register	int	segno;
316600Sbill 	register	struct symtab *sp, **cosp, *ub;
317600Sbill 	char		*tagstring();
318600Sbill 
319600Sbill 	printf("Symbol Table dump:\n");
320600Sbill 	for (segno = 0; segno < NLOC + NLOC; segno++){
321600Sbill 		printf("Segment number: %d\n", segno);
322600Sbill 		SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
323600Sbill 			printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
32413514Srrh 				segno, FETCHNAME(sp),
325634Shenry 				sp->s_value, sp->s_index,
326634Shenry 				tagstring(sp->s_tag));
327600Sbill 			printf("\t\ttype: %d jxbump %d jxfear: %d\n",
328634Shenry 				sp->s_type, sp->s_jxbump, sp->s_jxfear);
329600Sbill 		}
330600Sbill 		printf("\n\n");
331600Sbill 	}
332600Sbill }
333600Sbill 
334600Sbill static	char tagbuff[4];
335600Sbill 
336600Sbill char *tagstring(tag)
337600Sbill 	unsigned	char	tag;
338600Sbill {
339600Sbill 	switch(tag){
340600Sbill 		case JXACTIVE:		return("active");
341600Sbill 		case JXNOTYET:		return("notyet");
342600Sbill 		case JXALIGN:		return("align");
343600Sbill 		case JXQUESTIONABLE:	return("jxquestionable");
344600Sbill 		case JXINACTIVE:	return("inactive");
345600Sbill 		case JXTUNNEL:		return("tunnel");
346600Sbill 		case OBSOLETE:		return("obsolete");
347600Sbill 		case IGNOREBOUND:	return("ignorebound");
348600Sbill 		case STABFLOATING:	return("stabfloating");
349600Sbill 		case STABFIXED:		return("stabfixed");
350600Sbill 		case LABELID:		return("labelid");
351600Sbill 		case OKTOBUMP:		return("oktobump");
352600Sbill 		case ISET:		return("iset");
353600Sbill 		case ILSYM:		return("ilsym");
354600Sbill 		default:		sprintf(tagbuff,"%d", tag);
355600Sbill 					return(tagbuff);
356600Sbill 	}
357600Sbill }
358600Sbill #endif DEBUG
359600Sbill 
360600Sbill htaballoc()
361600Sbill {
362600Sbill 	register	struct	hashdallop	*new;
363600Sbill 	new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
364600Sbill 	if (htab == 0)
365600Sbill 		htab = new;
366600Sbill 	else {		/* add AFTER the 1st slot */
367600Sbill 		new->h_next = htab->h_next;
368600Sbill 		htab->h_next = new;
369600Sbill 	}
370600Sbill }
371600Sbill 
372600Sbill #define 	HASHCLOGGED	(NHASH / 2)
373600Sbill 
374600Sbill /*
375600Sbill  *	Lookup a symbol stored in extern yytext.
376600Sbill  *	All strings passed in via extern yytext had better have
377600Sbill  *	a trailing null.  Strings are placed in yytext for hashing by
378600Sbill  *	syminstall() and by yylex();
379600Sbill  *
380600Sbill  *	We take pains to avoid function calls; this functdion
381600Sbill  *	is called quite frequently, and the calls overhead
382600Sbill  *	in the vax contributes significantly to the overall
383600Sbill  *	execution speed of as.
384600Sbill  */
385600Sbill struct symtab **lookup(instflg)
386600Sbill 	int	instflg;		/* 0: don't install */
387600Sbill {
388600Sbill 	static	 int		initialprobe;
389600Sbill 	register struct	symtab 	**hp;
390600Sbill 	register char 		*from;
391600Sbill 	register char		*to;
392600Sbill 	register	int	len;
393600Sbill 	register	int	nprobes;
39413514Srrh 	static	struct	hashdallop *hdallop;
39513514Srrh 	static	struct	symtab	**emptyslot;
39613514Srrh 	static 	struct	hashdallop *emptyhd;
39713514Srrh 	static	struct	symtab	**hp_ub;
398600Sbill 
399600Sbill 	emptyslot = 0;
400600Sbill 	for (nprobes = 0, from = yytext;
401600Sbill 	     *from;
402600Sbill 	     nprobes <<= 2, nprobes += *from++)
403600Sbill 		continue;
404600Sbill 	nprobes += from[-1] << 5;
405600Sbill 	nprobes %= NHASH;
406600Sbill 	if (nprobes < 0)
407600Sbill 		nprobes += NHASH;
408600Sbill 
409600Sbill 	initialprobe = nprobes;
410600Sbill 	for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
411600Sbill 		for (hp = &(hdallop->h_htab[initialprobe]),
412600Sbill 				nprobes = 1,
413600Sbill 				hp_ub = &(hdallop->h_htab[NHASH]);
414600Sbill 		     (*hp) && (nprobes < NHASH);
415600Sbill 				hp += nprobes,
416600Sbill 				hp -= (hp >= hp_ub) ? NHASH:0,
417600Sbill 				nprobes += 2)
418600Sbill 		{
419600Sbill 			from = yytext;
42013514Srrh 			to = FETCHNAME(*hp);
421600Sbill 			while (*from && *to)
422600Sbill 				if (*from++ != *to++)
423600Sbill 					goto nextprobe;
424600Sbill 			if (*to == *from)	/*assert both are == 0*/
425600Sbill 				return(hp);
42613522Srrh 		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++;
44513447Srrh 		for (from = yytext, len = 0; *from++; len++)
446600Sbill 			continue;
44713572Srrh 		(*hp)->s_name = (char *)savestr(yytext, len + 1, STR_BOTH);
448600Sbill 	}
449600Sbill 	return(hp);
450600Sbill }	/*end of lookup*/
45113447Srrh /*
45213572Srrh  *	save a string str with len in the places indicated by place
45313447Srrh  */
45413572Srrh struct strdesc *savestr(str, len, place)
45513447Srrh 	char	*str;
45613572Srrh 	int	len;
45713572Srrh 	int	place;
458600Sbill {
45913514Srrh 	reg	struct	strdesc	*res;
46013514Srrh 		int	tlen;
46113572Srrh 	/*
46213572Srrh 	 *	Compute the total length of the record to live in core
46313572Srrh 	 */
46413514Srrh 	tlen = sizeof(struct strdesc) - sizeof(res->sd_string);
46513572Srrh 	if (place & STR_CORE)
46613572Srrh 		tlen += len;
46713572Srrh 	/*
46813572Srrh 	 *	See if there is enough space for the record,
46913572Srrh 	 *	and allocate the record.
47013572Srrh 	 */
47113514Srrh 	if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc))
472600Sbill 		strpoolalloc();
47313514Srrh 	res = (struct strdesc *)(strplhead->str_names + strplhead->str_nalloc);
47413572Srrh 	/*
47513572Srrh 	 *	Save the string information that is always present
47613572Srrh 	 */
47713572Srrh 	res->sd_stroff = strfilepos;
47813572Srrh 	res->sd_strlen = len;
47913572Srrh 	res->sd_place = place;
48013572Srrh 	/*
48113572Srrh 	 *	Now, save the string itself.  If str is null, then
48213572Srrh 	 *	the characters have already been dumped to the file
48313572Srrh 	 */
48413572Srrh 	if ((place & STR_CORE) && str)
48513572Srrh 		movestr(res[0].sd_string, str, len);
48613572Srrh 	if (place & STR_FILE){
48713572Srrh 		if (str){
48813572Srrh 			fwrite(str, 1, len, strfile);
48913572Srrh 		}
49013572Srrh 		strfilepos += len;
49113572Srrh 	}
49213572Srrh 	/*
49313572Srrh 	 *	Adjust the in core string pool size
49413572Srrh 	 */
49513514Srrh 	strplhead->str_nalloc += tlen;
49613447Srrh 	return(res);
497600Sbill }
498600Sbill /*
499600Sbill  *	The relocation information is saved internally in an array of
500600Sbill  *	lists of relocation buffers.  The relocation buffers are
501600Sbill  *	exactly the same size as a token buffer; if we use VM for the
502600Sbill  *	temporary file we reclaim this storage, otherwise we create
503600Sbill  *	them by mallocing.
504600Sbill  */
505600Sbill #define	RELBUFLG	TOKBUFLG
506600Sbill #define	NRELOC		((TOKBUFLG - \
507600Sbill 			  (sizeof (int) + sizeof (struct relbufdesc *)) \
508600Sbill 			) / (sizeof (struct relocation_info)))
509600Sbill 
510600Sbill struct	relbufdesc{
511600Sbill 	int	rel_count;
512600Sbill 	struct	relbufdesc	*rel_next;
513600Sbill 	struct	relocation_info	rel_reloc[NRELOC];
514600Sbill };
515600Sbill extern	struct	relbufdesc	*tok_free;
516600Sbill #define	rel_free tok_free
517600Sbill static	struct	relbufdesc	*rel_temp;
518634Shenry struct	relocation_info r_can_1PC;
519634Shenry struct	relocation_info	r_can_0PC;
520600Sbill 
521600Sbill initoutrel()
522600Sbill {
523634Shenry 	r_can_0PC.r_address = 0;
524634Shenry 	r_can_0PC.r_symbolnum = 0;
525634Shenry 	r_can_0PC.r_pcrel = 0;
526634Shenry 	r_can_0PC.r_length = 0;
527634Shenry 	r_can_0PC.r_extern = 0;
528634Shenry 
529634Shenry 	r_can_1PC = r_can_0PC;
530600Sbill 	r_can_1PC.r_pcrel = 1;
531600Sbill }
532600Sbill 
533675Shenry outrel(xp, reloc_how)
534675Shenry 	register	struct	exp	*xp;
5355828Srrh 	int		reloc_how;	/* TYPB..TYPH + (possibly)RELOC_PCREL */
536600Sbill {
537675Shenry 	struct		relocation_info	reloc;
538675Shenry 	register	int	x_type_mask;
53913447Srrh 			int	pcrel;
540600Sbill 
541675Shenry 	x_type_mask = xp->e_xtype & ~XFORW;
542675Shenry 	pcrel = reloc_how & RELOC_PCREL;
543675Shenry 	reloc_how &= ~RELOC_PCREL;
544675Shenry 
545600Sbill 	if (bitoff&07)
546600Sbill 		yyerror("Padding error");
547675Shenry 	if (x_type_mask == XUNDEF)
548600Sbill 		yyerror("Undefined reference");
549600Sbill 
550675Shenry 	if ( (x_type_mask != XABS) || pcrel ) {
551675Shenry 		if (ty_NORELOC[reloc_how])
5525828Srrh 			yyerror("Illegal Relocation of floating or large int number.");
553675Shenry 		reloc = pcrel ? r_can_1PC : r_can_0PC;
554634Shenry 		reloc.r_address = dotp->e_xvalue -
555640Sbill 		    ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
556675Shenry 		reloc.r_length = ty_nlg[reloc_how];
557675Shenry 		switch(x_type_mask){
558600Sbill 			case XXTRN | XUNDEF:
559675Shenry 				reloc.r_symbolnum = xp->e_xname->s_index;
560600Sbill 				reloc.r_extern = 1;
561600Sbill 				break;
562600Sbill 			default:
563675Shenry 				if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
564675Shenry 					x_type_mask = XTEXT | (x_type_mask&XXTRN);
565675Shenry 				reloc.r_symbolnum = x_type_mask;
566600Sbill 				break;
567600Sbill 		}
568600Sbill 		if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
569600Sbill 			if (rel_free){
570600Sbill 				rel_temp = rel_free;
571600Sbill 				rel_free = rel_temp->rel_next;
572600Sbill 			} else {
573600Sbill 				rel_temp = (struct relbufdesc *)
574600Sbill 					Calloc(1,sizeof (struct relbufdesc));
575600Sbill 			}
576600Sbill 			rel_temp->rel_count = 0;
577600Sbill 			rel_temp->rel_next = relfil;
578600Sbill 			relfil = rusefile[dotp - &usedot[0]] = rel_temp;
579600Sbill 		}
580600Sbill 		relfil->rel_reloc[relfil->rel_count++] = reloc;
581600Sbill 	}
582600Sbill 	/*
583600Sbill 	 *	write the unrelocated value to the text file
584600Sbill 	 */
585675Shenry 	dotp->e_xvalue += ty_nbyte[reloc_how];
586675Shenry 	if (pcrel)
587675Shenry 		xp->e_xvalue -= dotp->e_xvalue;
5885828Srrh 	switch(reloc_how){
5895828Srrh 	case TYPO:
5905828Srrh 	case TYPQ:
5915828Srrh 
5925828Srrh 	case TYPF:
5935828Srrh 	case TYPD:
5945828Srrh 	case TYPG:
5955828Srrh 	case TYPH:
5965828Srrh 		bignumwrite(xp->e_number, reloc_how);
5975828Srrh 		break;
5985828Srrh 
5995828Srrh 	default:
6005828Srrh 		bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
6015828Srrh 		break;
6025828Srrh 	}
603600Sbill }
604600Sbill /*
605600Sbill  *	Flush out all of the relocation information.
606600Sbill  *	Note that the individual lists of buffers are in
607600Sbill  *	reverse order, so we must reverse them
608600Sbill  */
609600Sbill off_t closeoutrel(relocfile)
610600Sbill 	BFILE	*relocfile;
611600Sbill {
612600Sbill 	int	locindex;
613600Sbill 	u_long	Closeoutrel();
614600Sbill 
615600Sbill 	trsize = 0;
616600Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
617600Sbill 		trsize += Closeoutrel(rusefile[locindex], relocfile);
618600Sbill 	}
619600Sbill 	drsize = 0;
620600Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
621600Sbill 		drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
622600Sbill 	}
623600Sbill 	return(trsize + drsize);
624600Sbill }
625600Sbill 
626600Sbill u_long Closeoutrel(relfil, relocfile)
627600Sbill 	struct	relbufdesc	*relfil;
628600Sbill 	BFILE	*relocfile;
629600Sbill {
630600Sbill 	u_long	tail;
631600Sbill 	if (relfil == 0)
632600Sbill 		return(0L);
633600Sbill 	tail = Closeoutrel(relfil->rel_next, relocfile);
634600Sbill 	bwrite((char *)&relfil->rel_reloc[0],
635600Sbill 		relfil->rel_count * sizeof (struct relocation_info),
636600Sbill 		relocfile);
637600Sbill 	return(tail + relfil->rel_count * sizeof (struct relocation_info));
638600Sbill }
639600Sbill 
640634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
641600Sbill int sizesymtab()
642600Sbill {
643634Shenry 	return (sizeof (struct nlist) * NOUTSYMS);
644600Sbill }
645600Sbill /*
646600Sbill  *	Write out n symbols to file f, beginning at p
647600Sbill  *	ignoring symbols that are obsolete, jxxx instructions, and
648600Sbill  *	possibly, labels
649600Sbill  */
650600Sbill int symwrite(symfile)
651600Sbill 	BFILE *symfile;
652600Sbill {
65313514Srrh 		int	symsout;		/*those actually written*/
65413514Srrh 		int	symsdesired = NOUTSYMS;
65513514Srrh 	reg	struct	symtab *sp, *ub;
65613514Srrh 		char	*name;			/* temp to save the name */
65714450Srrh 		int	totalstr;
658634Shenry 	/*
659634Shenry 	 *	We use sp->s_index to hold the length of the
660634Shenry 	 *	name; it isn't used for anything else
661634Shenry 	 */
662600Sbill 	register	struct	allocbox	*allocwalk;
663600Sbill 
664600Sbill 	symsout = 0;
66514450Srrh 	totalstr = sizeof(totalstr);
66614450Srrh 	DECLITERATE(allocwalk, sp, ub) {
667634Shenry 		if (sp->s_tag >= IGNOREBOUND)
668600Sbill 			continue;
66914450Srrh 		if (ISLABEL(sp))
670600Sbill 			continue;
671600Sbill 		symsout++;
672634Shenry 		name = sp->s_name;		/* save pointer */
67313447Srrh 		/*
67413447Srrh 		 *	the length of the symbol table string
67514450Srrh 		 *	always includes the trailing null;
67614450Srrh 		 *	blast the pointer to its a.out value.
67713447Srrh 		 */
67813514Srrh 		if (sp->s_name && (sp->s_index = STRLEN(sp))){
67914450Srrh 			sp->s_nmx = totalstr;
68014450Srrh 			totalstr += sp->s_index;
681634Shenry 		} else {
68213447Srrh 			sp->s_nmx = 0;
683634Shenry 		}
68414450Srrh 		if (sp->s_ptype != 0)
68514450Srrh 			sp->s_type = sp->s_ptype;
68614450Srrh 		else
68714450Srrh 			sp->s_type = (sp->s_type & (~XFORW));
688640Sbill 		if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
689640Sbill 			sp->s_type = N_TEXT | (sp->s_type & N_EXT);
6905828Srrh 		bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile);
691634Shenry 		sp->s_name = name;		/* restore pointer */
692600Sbill 	}
693600Sbill 	if (symsout != symsdesired)
694600Sbill 		yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
695600Sbill 			symsout, symsdesired);
696600Sbill 	/*
69714450Srrh 	 *	Construct the string pool from the symbols that were written,
69814450Srrh 	 *	possibly fetching from the string file if the string
69914450Srrh 	 *	is not core resident.
700600Sbill 	 */
70114450Srrh 	bwrite(&totalstr, sizeof(totalstr), symfile);
70214450Srrh 	symsout = 0;
70314450Srrh 	DECLITERATE(allocwalk, sp, ub) {
70414450Srrh 		if (sp->s_tag >= IGNOREBOUND)
70514450Srrh 			continue;
70614450Srrh 		if (ISLABEL(sp))
70714450Srrh 			continue;
70814450Srrh 		symsout++;
70914450Srrh 		if (STRLEN(sp) > 0){
71014450Srrh 		 if (STRPLACE(sp) & STR_CORE){
71114450Srrh 			bwrite(FETCHNAME(sp), STRLEN(sp), symfile);
71214450Srrh 		 } else if (STRPLACE(sp) & STR_FILE){
71314450Srrh 			char	rbuf[2048];
71414450Srrh 			int	left, nread;
71514450Srrh 			fseek(strfile, STROFF(sp), 0);
71614450Srrh 			for (left = STRLEN(sp); left > 0; left -= nread){
71714450Srrh 				nread = fread(rbuf, sizeof(char),
71814450Srrh 					min(sizeof(rbuf), left), strfile);
71914450Srrh 				if (nread == 0)
72014450Srrh 					break;
72114450Srrh 				bwrite(rbuf, nread, symfile);
72214450Srrh 			}
72314450Srrh 		 }
72413447Srrh 		}
725600Sbill 	}
72614450Srrh 	if (symsout != symsdesired)
72714450Srrh 		yyerror("INTERNAL ERROR: Wrote %d strings, wanted %d\n",
72814450Srrh 			symsout, symsdesired);
729600Sbill }
730