xref: /csrg-svn/old/as.vax/assyms.c (revision 14450)
15828Srrh /*
25828Srrh  *	Copyright (c) 1982 Regents of the University of California
35828Srrh  */
45828Srrh #ifndef lint
5*14450Srrh static char sccsid[] = "@(#)assyms.c 4.14 08/11/83";
65828Srrh #endif not lint
75828Srrh 
8600Sbill #include <stdio.h>
9600Sbill #include <ctype.h>
10600Sbill #include "as.h"
11600Sbill #include "asscan.h"
12600Sbill #include "assyms.h"
13600Sbill 
14600Sbill /*
15600Sbill  *	Managers for chunks of symbols allocated from calloc()
16600Sbill  *	We maintain a linked list of such chunks.
17600Sbill  *
18600Sbill  */
19600Sbill struct	allocbox	*allochead;	/*head of chunk list*/
20600Sbill struct	allocbox	*alloctail;	/*tail*/
21600Sbill struct	allocbox	*newbox;	/*for creating a new chunk*/
22600Sbill struct	symtab		*nextsym;	/*next symbol free*/
23600Sbill int			symsleft;	/*slots left in current chunk*/
24600Sbill 
25600Sbill struct	symtab		**symptrs;
26600Sbill struct	symtab		**symdelim[NLOC + NLOC +1];
27600Sbill struct	symtab		**symptrub;
28600Sbill /*
29600Sbill  *	Managers for the dynamically extendable hash table
30600Sbill  */
31600Sbill struct	hashdallop	*htab;
32600Sbill 
335828Srrh Iptr	*itab[NINST];	/*maps opcodes to instructions*/
34600Sbill /*
35600Sbill  *	Counts what went into the symbol table, so that the
36600Sbill  *	size of the symbol table can be computed.
37600Sbill  */
38600Sbill int	nsyms;		/* total number in the symbol table */
39600Sbill int	njxxx;		/* number of jxxx entrys */
40600Sbill int	nforgotten;	/* number of symbols erroneously entered */
41600Sbill int	nlabels;	/* number of label entries */
42600Sbill 
43600Sbill /*
44600Sbill  *	Managers of the symbol literal storage.
45600Sbill  */
46600Sbill struct	strpool		*strplhead = 0;
47600Sbill 
48600Sbill symtabinit()
49600Sbill {
50600Sbill 	allochead = 0;
51600Sbill 	alloctail = 0;
52600Sbill 	nextsym = 0;
53600Sbill 	symsleft = 0;
54600Sbill 	strpoolalloc();		/* get the first strpool storage area */
55600Sbill 	htab = 0;
56600Sbill 	htaballoc();		/* get the first part of the hash table */
57600Sbill }
58600Sbill 
59600Sbill /*
60600Sbill  *	Install all known instructions in the symbol table
61600Sbill  */
62600Sbill syminstall()
63600Sbill {
645828Srrh 	register	Iptr	ip;
65600Sbill 	register	struct	symtab	**hp;
66600Sbill 	register	char	*p1, *p2;
675828Srrh 	register	int	i;
68600Sbill 
695828Srrh 	for (i = 0; i < NINST; i++)
705828Srrh 		itab[i] = (Iptr*)BADPOINT;
715828Srrh 
7213514Srrh 	for (ip = (Iptr)instab; FETCHNAME(ip)[0]; ip++) {
7313514Srrh 		p1 = FETCHNAME(ip);
74600Sbill 		p2 = yytext;
75600Sbill 		while (*p2++ = *p1++);
76600Sbill 		hp = lookup(0);		/* 0 => don't install this*/
77600Sbill 		if (*hp==NULL) {
78600Sbill 			*hp = (struct symtab *)ip;
79634Shenry 			if (   (ip->s_tag!=INSTn)
80634Shenry 			    && (ip->s_tag!=INST0)
81634Shenry 			    && (ip->s_tag!=0))
82600Sbill 				continue; /* was pseudo-op */
835828Srrh 			if (itab[ip->i_eopcode] == (Iptr*)BADPOINT){
845828Srrh 				itab[ip->i_eopcode] =
855828Srrh 					(Iptr*)ClearCalloc(256, sizeof(Iptr));
865828Srrh 				for (i = 0; i < 256; i++)
875828Srrh 					itab[ip->i_eopcode][i] =
885828Srrh 						(Iptr)BADPOINT;
895828Srrh 			}
905828Srrh 			itab[ip->i_eopcode][ip->i_popcode] = ip;
91600Sbill 		}
92600Sbill 	}
93600Sbill }	/*end of syminstall*/
94600Sbill 
95*14450Srrh #define ISLABEL(sp) \
96*14450Srrh 	(   (!savelabels) \
97*14450Srrh 	 && (sp->s_tag == LABELID) \
98*14450Srrh 	 && (STRPLACE(sp) & STR_CORE) \
99*14450Srrh 	 && (FETCHNAME(sp)[0] == 'L'))
100600Sbill /*
101600Sbill  *	Assign final values to symbols,
102600Sbill  *	and overwrite the index field with its relative position in
103600Sbill  *	the symbol table we give to the loader.
104600Sbill  */
105600Sbill extern struct exec hdr;
106600Sbill 
107600Sbill freezesymtab()
108600Sbill {
109600Sbill 	register	struct	symtab	*sp;
110600Sbill 				long	bs;
111600Sbill 	register	int	relpos = 0;
112600Sbill 	register	struct	symtab		*ubsp;
113600Sbill 	register	struct	allocbox	*allocwalk;
114600Sbill 
115600Sbill 	DECLITERATE(allocwalk, sp, ubsp)
116600Sbill 	{
117634Shenry 		if (sp->s_tag >= IGNOREBOUND)
118600Sbill 			continue; 		/*totally ignore jxxx entries */
119600Sbill 		/*
120600Sbill 		 *	Ignore stabs, but give them a symbol table index
121600Sbill 		 */
122634Shenry 		if (sp->s_type & STABFLAG)
123600Sbill 			goto assignindex;
124634Shenry 		if ((sp->s_type&XTYPE)==XUNDEF)
125634Shenry 			sp->s_type = XXTRN+XUNDEF;
126634Shenry 		else if ((sp->s_type&XTYPE)==XDATA)
127634Shenry 			sp->s_value += usedot[sp->s_index].e_xvalue;
128634Shenry 		else if ((sp->s_type&XTYPE)==XTEXT)
129634Shenry 			sp->s_value += usedot[sp->s_index].e_xvalue;
130634Shenry 		else if ((sp->s_type&XTYPE)==XBSS) {
131634Shenry 			bs = sp->s_value;
132634Shenry 			sp->s_value = hdr.a_bss + datbase;
133600Sbill 			hdr.a_bss += bs;
134600Sbill 		}
135600Sbill 	   assignindex:
136*14450Srrh 		if (!ISLABEL(sp))
137*14450Srrh 			sp->s_index = relpos++;
138600Sbill 	}
139600Sbill }
140600Sbill 
141600Sbill /*
142600Sbill  *	For all of the stabs that had their final value undefined during pass 1
143600Sbill  *	and during pass 2 assign a final value.
144600Sbill  *	We have already given stab entrys a initial approximation
145600Sbill  *	when we constsructed the sorted symbol table.
146600Sbill  *	Iteration order doesn't matter.
147600Sbill  */
14812592Scsvaf 
14912592Scsvaf stabfix()
15012592Scsvaf {
151600Sbill 	register struct symtab *sp, **cosp;
152600Sbill 	register struct symtab *p;
153600Sbill 
154600Sbill 	SYMITERATE(cosp, sp){
155634Shenry 		if(sp->s_ptype && (sp->s_type & STABFLAG)) {
156634Shenry 			p = sp->s_dest;
15712592Scsvaf /*
15812592Scsvaf  * STABFLOATING indicates that the offset has been saved in s_desc, s_other
15912592Scsvaf  */
16012592Scsvaf 			if(sp->s_tag == STABFLOATING) {
16112592Scsvaf 			  sp->s_value = ( ( ((unsigned char) sp->s_other) << 16)  					| ( (unsigned short) sp->s_desc )  );
16212592Scsvaf 			  sp->s_value = sp->s_value + p->s_value;
16312592Scsvaf 			}
16412592Scsvaf 			else sp->s_value = p->s_value;
165634Shenry 			sp->s_index = p->s_index;
166634Shenry 			sp->s_type = p->s_type;
16712592Scsvaf 
16812592Scsvaf 
169600Sbill 		}
170600Sbill 	}
171600Sbill }
172600Sbill 
173600Sbill char *Calloc(number, size)
174600Sbill 	int	number, size;
175600Sbill {
176600Sbill 	register	char *newstuff;
1775828Srrh 	char	*sbrk();
1785828Srrh 	newstuff = sbrk(number*size);
179600Sbill 	if ((int)newstuff == -1){
180600Sbill 		yyerror("Ran out of Memory");
181600Sbill 		delexit();
182600Sbill 	}
183600Sbill 	return(newstuff);
184600Sbill }
185600Sbill 
186600Sbill char *ClearCalloc(number, size)
187600Sbill 	int	number, size;
188600Sbill {
189600Sbill 	register	char	*newstuff;		/* r11 */
190600Sbill 	register	int	length = number * size;	/* r10 */
1915828Srrh #ifdef lint
1925828Srrh 	length = length;
1935828Srrh #endif length
194600Sbill 	newstuff = Calloc(number, size);
195600Sbill 	asm("movc5 $0, (r0), $0, r10, (r11)");
196600Sbill 	return(newstuff);
197600Sbill }
198600Sbill 
199600Sbill struct symtab *symalloc()
200600Sbill {
201600Sbill 	if (symsleft == 0){
202600Sbill 		newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
203600Sbill 		symsleft = SYMDALLOP;
204600Sbill 		nextsym = &newbox->symslots[0];
205600Sbill 		if (alloctail == 0){
206600Sbill 			allochead = alloctail = newbox;
207600Sbill 		} else {
208600Sbill 			alloctail->nextalloc = newbox;
209600Sbill 			alloctail = newbox;
210600Sbill 		}
211600Sbill 	}
212600Sbill 	--symsleft;
213600Sbill 	++nsyms;
214600Sbill 	return(nextsym++);
215600Sbill }
216600Sbill 
217600Sbill strpoolalloc()
218600Sbill {
219600Sbill 	register	struct	strpool	*new;
220600Sbill 
221600Sbill 	new = (struct strpool *)Calloc(1, sizeof (struct strpool));
222600Sbill 	new->str_nalloc = 0;
223600Sbill 	new->str_next = strplhead;
224600Sbill 	strplhead = new;
225600Sbill }
226600Sbill 
227600Sbill symcmp(Pptr, Qptr)
228600Sbill 	struct symtab **Pptr, **Qptr;
229600Sbill {
230600Sbill 	register struct symtab *p = *Pptr;
231600Sbill 	register struct symtab *q = *Qptr;
232634Shenry 	if (p->s_index < q->s_index)
233600Sbill 		return(-1);
234634Shenry 	if (p->s_index > q->s_index)
235600Sbill 		return(1);
236634Shenry 	if (p->s_value < q->s_value)
237600Sbill 		return(-1);
238634Shenry 	if (p->s_value > q->s_value)
239600Sbill 		return(1);
240600Sbill 	/*
241600Sbill 	 *	Force jxxx entries to virtually preceed labels defined
242600Sbill 	 *	to follow the jxxxx instruction, so that bumping the
243600Sbill 	 *	jxxx instruction correctly fixes up the following labels
244600Sbill 	 */
245634Shenry 	if (p->s_tag >= IGNOREBOUND)	/*p points to a jxxx*/
246600Sbill 		return(-1);
247634Shenry 	if (q->s_tag >= IGNOREBOUND)
248600Sbill 		return(1);
249600Sbill 	/*
250600Sbill 	 *	both are now just plain labels; the relative order doesn't
251600Sbill 	 *	matter.  Both can't be jxxxes, as they would have different
252600Sbill 	 *	values.
253600Sbill 	 */
254600Sbill 	return(0);
255600Sbill }	/*end of symcmp*/
256600Sbill 
257600Sbill /*
258600Sbill  *	We construct the auxiliary table of pointers, symptrs and
259600Sbill  *	symdelim
260600Sbill  *	We also assign preliminary values to stab entries that did not yet
261600Sbill  *	have an absolute value (because they initially referred to
262600Sbill  *	forward references). We don't worry about .stabds, as they
263600Sbill  *	already have an estimated final value
264600Sbill  */
265600Sbill 
266600Sbill sortsymtab()
267600Sbill {
268600Sbill 	register	struct	symtab	*sp;
269600Sbill 	register	struct	symtab	**cowalk;
270600Sbill 	register	struct	allocbox	*allocwalk;
271600Sbill 			struct	symtab	*ubsp;
272600Sbill 				int	segno;
273600Sbill 				int	slotno;
274600Sbill 				int	symsin;	/*number put into symptrs*/
275600Sbill 
276600Sbill 	symptrs =  (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
277600Sbill 	/*
278600Sbill 	 *	Allocate one word at the beginning of the symptr array
279600Sbill 	 *	so that backwards scans through the symptr array will
280600Sbill 	 *	work correctly while scanning through the zeroth segment
281600Sbill 	 */
282600Sbill 	*symptrs++ = 0;
283600Sbill 	cowalk = symptrs;
284600Sbill 	symsin = 0;
285600Sbill 	DECLITERATE(allocwalk, sp, ubsp) {
286634Shenry 		if (sp->s_ptype && (sp->s_type &STABFLAG)){
287634Shenry 			sp->s_value = sp->s_dest->s_value;
288634Shenry 			sp->s_index = sp->s_dest->s_index;
289600Sbill 		}
290600Sbill 		if (symsin >= nsyms)
291600Sbill 			yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
292600Sbill 		*cowalk++ = sp;
293600Sbill 		symsin++;
294600Sbill 	}
295600Sbill 	if (symsin != nsyms)
296600Sbill 		yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
297600Sbill 			symsin, nsyms);
298600Sbill 	symptrub = &symptrs[nsyms ];
299600Sbill 	qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
300600Sbill 	symdelim[0] = symptrs;
301600Sbill 	for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
302600Sbill 	     segno < NLOC + NLOC;
303600Sbill 	     segno++, slotno++){
304634Shenry 		for (; sp && sp->s_index == segno; sp = *++cowalk);
305600Sbill 		symdelim[slotno] = cowalk;	/*forms the ub delimeter*/
306600Sbill 	}
307600Sbill }	/*end of sortsymtab*/
308600Sbill 
309600Sbill #ifdef DEBUG
310600Sbill dumpsymtab()
311600Sbill {
312600Sbill 	register	int	segno;
313600Sbill 	register	struct symtab *sp, **cosp, *ub;
314600Sbill 	char		*tagstring();
315600Sbill 
316600Sbill 	printf("Symbol Table dump:\n");
317600Sbill 	for (segno = 0; segno < NLOC + NLOC; segno++){
318600Sbill 		printf("Segment number: %d\n", segno);
319600Sbill 		SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
320600Sbill 			printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
32113514Srrh 				segno, FETCHNAME(sp),
322634Shenry 				sp->s_value, sp->s_index,
323634Shenry 				tagstring(sp->s_tag));
324600Sbill 			printf("\t\ttype: %d jxbump %d jxfear: %d\n",
325634Shenry 				sp->s_type, sp->s_jxbump, sp->s_jxfear);
326600Sbill 		}
327600Sbill 		printf("\n\n");
328600Sbill 	}
329600Sbill }
330600Sbill 
331600Sbill static	char tagbuff[4];
332600Sbill 
333600Sbill char *tagstring(tag)
334600Sbill 	unsigned	char	tag;
335600Sbill {
336600Sbill 	switch(tag){
337600Sbill 		case JXACTIVE:		return("active");
338600Sbill 		case JXNOTYET:		return("notyet");
339600Sbill 		case JXALIGN:		return("align");
340600Sbill 		case JXQUESTIONABLE:	return("jxquestionable");
341600Sbill 		case JXINACTIVE:	return("inactive");
342600Sbill 		case JXTUNNEL:		return("tunnel");
343600Sbill 		case OBSOLETE:		return("obsolete");
344600Sbill 		case IGNOREBOUND:	return("ignorebound");
345600Sbill 		case STABFLOATING:	return("stabfloating");
346600Sbill 		case STABFIXED:		return("stabfixed");
347600Sbill 		case LABELID:		return("labelid");
348600Sbill 		case OKTOBUMP:		return("oktobump");
349600Sbill 		case ISET:		return("iset");
350600Sbill 		case ILSYM:		return("ilsym");
351600Sbill 		default:		sprintf(tagbuff,"%d", tag);
352600Sbill 					return(tagbuff);
353600Sbill 	}
354600Sbill }
355600Sbill #endif DEBUG
356600Sbill 
357600Sbill htaballoc()
358600Sbill {
359600Sbill 	register	struct	hashdallop	*new;
360600Sbill 	new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
361600Sbill 	if (htab == 0)
362600Sbill 		htab = new;
363600Sbill 	else {		/* add AFTER the 1st slot */
364600Sbill 		new->h_next = htab->h_next;
365600Sbill 		htab->h_next = new;
366600Sbill 	}
367600Sbill }
368600Sbill 
369600Sbill #define 	HASHCLOGGED	(NHASH / 2)
370600Sbill 
371600Sbill /*
372600Sbill  *	Lookup a symbol stored in extern yytext.
373600Sbill  *	All strings passed in via extern yytext had better have
374600Sbill  *	a trailing null.  Strings are placed in yytext for hashing by
375600Sbill  *	syminstall() and by yylex();
376600Sbill  *
377600Sbill  *	We take pains to avoid function calls; this functdion
378600Sbill  *	is called quite frequently, and the calls overhead
379600Sbill  *	in the vax contributes significantly to the overall
380600Sbill  *	execution speed of as.
381600Sbill  */
382600Sbill struct symtab **lookup(instflg)
383600Sbill 	int	instflg;		/* 0: don't install */
384600Sbill {
385600Sbill 	static	 int		initialprobe;
386600Sbill 	register struct	symtab 	**hp;
387600Sbill 	register char 		*from;
388600Sbill 	register char		*to;
389600Sbill 	register	int	len;
390600Sbill 	register	int	nprobes;
39113514Srrh 	static	struct	hashdallop *hdallop;
39213514Srrh 	static	struct	symtab	**emptyslot;
39313514Srrh 	static 	struct	hashdallop *emptyhd;
39413514Srrh 	static	struct	symtab	**hp_ub;
395600Sbill 
396600Sbill 	emptyslot = 0;
397600Sbill 	for (nprobes = 0, from = yytext;
398600Sbill 	     *from;
399600Sbill 	     nprobes <<= 2, nprobes += *from++)
400600Sbill 		continue;
401600Sbill 	nprobes += from[-1] << 5;
402600Sbill 	nprobes %= NHASH;
403600Sbill 	if (nprobes < 0)
404600Sbill 		nprobes += NHASH;
405600Sbill 
406600Sbill 	initialprobe = nprobes;
407600Sbill 	for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
408600Sbill 		for (hp = &(hdallop->h_htab[initialprobe]),
409600Sbill 				nprobes = 1,
410600Sbill 				hp_ub = &(hdallop->h_htab[NHASH]);
411600Sbill 		     (*hp) && (nprobes < NHASH);
412600Sbill 				hp += nprobes,
413600Sbill 				hp -= (hp >= hp_ub) ? NHASH:0,
414600Sbill 				nprobes += 2)
415600Sbill 		{
416600Sbill 			from = yytext;
41713514Srrh 			to = FETCHNAME(*hp);
418600Sbill 			while (*from && *to)
419600Sbill 				if (*from++ != *to++)
420600Sbill 					goto nextprobe;
421600Sbill 			if (*to == *from)	/*assert both are == 0*/
422600Sbill 				return(hp);
42313522Srrh 		nextprobe: ;
424600Sbill 		}
425600Sbill 		if (*hp == 0 && emptyslot == 0 &&
426600Sbill 		    hdallop->h_nused < HASHCLOGGED) {
427600Sbill 			emptyslot = hp;
428600Sbill 			emptyhd = hdallop;
429600Sbill 		}
430600Sbill 	}
431600Sbill 	if (emptyslot == 0) {
432600Sbill 		htaballoc();
433600Sbill 		hdallop = htab->h_next;		/* aren't we smart! */
434600Sbill 		hp = &hdallop->h_htab[initialprobe];
435600Sbill 	} else {
436600Sbill 		hdallop = emptyhd;
437600Sbill 		hp = emptyslot;
438600Sbill 	}
439600Sbill 	if (instflg) {
440600Sbill 		*hp = symalloc();
441600Sbill 		hdallop->h_nused++;
44213447Srrh 		for (from = yytext, len = 0; *from++; len++)
443600Sbill 			continue;
44413572Srrh 		(*hp)->s_name = (char *)savestr(yytext, len + 1, STR_BOTH);
445600Sbill 	}
446600Sbill 	return(hp);
447600Sbill }	/*end of lookup*/
44813447Srrh /*
44913572Srrh  *	save a string str with len in the places indicated by place
45013447Srrh  */
45113572Srrh struct strdesc *savestr(str, len, place)
45213447Srrh 	char	*str;
45313572Srrh 	int	len;
45413572Srrh 	int	place;
455600Sbill {
45613514Srrh 	reg	struct	strdesc	*res;
45713514Srrh 		int	tlen;
45813572Srrh 	/*
45913572Srrh 	 *	Compute the total length of the record to live in core
46013572Srrh 	 */
46113514Srrh 	tlen = sizeof(struct strdesc) - sizeof(res->sd_string);
46213572Srrh 	if (place & STR_CORE)
46313572Srrh 		tlen += len;
46413572Srrh 	/*
46513572Srrh 	 *	See if there is enough space for the record,
46613572Srrh 	 *	and allocate the record.
46713572Srrh 	 */
46813514Srrh 	if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc))
469600Sbill 		strpoolalloc();
47013514Srrh 	res = (struct strdesc *)(strplhead->str_names + strplhead->str_nalloc);
47113572Srrh 	/*
47213572Srrh 	 *	Save the string information that is always present
47313572Srrh 	 */
47413572Srrh 	res->sd_stroff = strfilepos;
47513572Srrh 	res->sd_strlen = len;
47613572Srrh 	res->sd_place = place;
47713572Srrh 	/*
47813572Srrh 	 *	Now, save the string itself.  If str is null, then
47913572Srrh 	 *	the characters have already been dumped to the file
48013572Srrh 	 */
48113572Srrh 	if ((place & STR_CORE) && str)
48213572Srrh 		movestr(res[0].sd_string, str, len);
48313572Srrh 	if (place & STR_FILE){
48413572Srrh 		if (str){
48513572Srrh 			fwrite(str, 1, len, strfile);
48613572Srrh 		}
48713572Srrh 		strfilepos += len;
48813572Srrh 	}
48913572Srrh 	/*
49013572Srrh 	 *	Adjust the in core string pool size
49113572Srrh 	 */
49213514Srrh 	strplhead->str_nalloc += tlen;
49313447Srrh 	return(res);
494600Sbill }
495600Sbill /*
496600Sbill  *	The relocation information is saved internally in an array of
497600Sbill  *	lists of relocation buffers.  The relocation buffers are
498600Sbill  *	exactly the same size as a token buffer; if we use VM for the
499600Sbill  *	temporary file we reclaim this storage, otherwise we create
500600Sbill  *	them by mallocing.
501600Sbill  */
502600Sbill #define	RELBUFLG	TOKBUFLG
503600Sbill #define	NRELOC		((TOKBUFLG - \
504600Sbill 			  (sizeof (int) + sizeof (struct relbufdesc *)) \
505600Sbill 			) / (sizeof (struct relocation_info)))
506600Sbill 
507600Sbill struct	relbufdesc{
508600Sbill 	int	rel_count;
509600Sbill 	struct	relbufdesc	*rel_next;
510600Sbill 	struct	relocation_info	rel_reloc[NRELOC];
511600Sbill };
512600Sbill extern	struct	relbufdesc	*tok_free;
513600Sbill #define	rel_free tok_free
514600Sbill static	struct	relbufdesc	*rel_temp;
515634Shenry struct	relocation_info r_can_1PC;
516634Shenry struct	relocation_info	r_can_0PC;
517600Sbill 
518600Sbill initoutrel()
519600Sbill {
520634Shenry 	r_can_0PC.r_address = 0;
521634Shenry 	r_can_0PC.r_symbolnum = 0;
522634Shenry 	r_can_0PC.r_pcrel = 0;
523634Shenry 	r_can_0PC.r_length = 0;
524634Shenry 	r_can_0PC.r_extern = 0;
525634Shenry 
526634Shenry 	r_can_1PC = r_can_0PC;
527600Sbill 	r_can_1PC.r_pcrel = 1;
528600Sbill }
529600Sbill 
530675Shenry outrel(xp, reloc_how)
531675Shenry 	register	struct	exp	*xp;
5325828Srrh 	int		reloc_how;	/* TYPB..TYPH + (possibly)RELOC_PCREL */
533600Sbill {
534675Shenry 	struct		relocation_info	reloc;
535675Shenry 	register	int	x_type_mask;
53613447Srrh 			int	pcrel;
537600Sbill 
538675Shenry 	x_type_mask = xp->e_xtype & ~XFORW;
539675Shenry 	pcrel = reloc_how & RELOC_PCREL;
540675Shenry 	reloc_how &= ~RELOC_PCREL;
541675Shenry 
542600Sbill 	if (bitoff&07)
543600Sbill 		yyerror("Padding error");
544675Shenry 	if (x_type_mask == XUNDEF)
545600Sbill 		yyerror("Undefined reference");
546600Sbill 
547675Shenry 	if ( (x_type_mask != XABS) || pcrel ) {
548675Shenry 		if (ty_NORELOC[reloc_how])
5495828Srrh 			yyerror("Illegal Relocation of floating or large int number.");
550675Shenry 		reloc = pcrel ? r_can_1PC : r_can_0PC;
551634Shenry 		reloc.r_address = dotp->e_xvalue -
552640Sbill 		    ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
553675Shenry 		reloc.r_length = ty_nlg[reloc_how];
554675Shenry 		switch(x_type_mask){
555600Sbill 			case XXTRN | XUNDEF:
556675Shenry 				reloc.r_symbolnum = xp->e_xname->s_index;
557600Sbill 				reloc.r_extern = 1;
558600Sbill 				break;
559600Sbill 			default:
560675Shenry 				if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
561675Shenry 					x_type_mask = XTEXT | (x_type_mask&XXTRN);
562675Shenry 				reloc.r_symbolnum = x_type_mask;
563600Sbill 				break;
564600Sbill 		}
565600Sbill 		if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
566600Sbill 			if (rel_free){
567600Sbill 				rel_temp = rel_free;
568600Sbill 				rel_free = rel_temp->rel_next;
569600Sbill 			} else {
570600Sbill 				rel_temp = (struct relbufdesc *)
571600Sbill 					Calloc(1,sizeof (struct relbufdesc));
572600Sbill 			}
573600Sbill 			rel_temp->rel_count = 0;
574600Sbill 			rel_temp->rel_next = relfil;
575600Sbill 			relfil = rusefile[dotp - &usedot[0]] = rel_temp;
576600Sbill 		}
577600Sbill 		relfil->rel_reloc[relfil->rel_count++] = reloc;
578600Sbill 	}
579600Sbill 	/*
580600Sbill 	 *	write the unrelocated value to the text file
581600Sbill 	 */
582675Shenry 	dotp->e_xvalue += ty_nbyte[reloc_how];
583675Shenry 	if (pcrel)
584675Shenry 		xp->e_xvalue -= dotp->e_xvalue;
5855828Srrh 	switch(reloc_how){
5865828Srrh 	case TYPO:
5875828Srrh 	case TYPQ:
5885828Srrh 
5895828Srrh 	case TYPF:
5905828Srrh 	case TYPD:
5915828Srrh 	case TYPG:
5925828Srrh 	case TYPH:
5935828Srrh 		bignumwrite(xp->e_number, reloc_how);
5945828Srrh 		break;
5955828Srrh 
5965828Srrh 	default:
5975828Srrh 		bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
5985828Srrh 		break;
5995828Srrh 	}
600600Sbill }
601600Sbill /*
602600Sbill  *	Flush out all of the relocation information.
603600Sbill  *	Note that the individual lists of buffers are in
604600Sbill  *	reverse order, so we must reverse them
605600Sbill  */
606600Sbill off_t closeoutrel(relocfile)
607600Sbill 	BFILE	*relocfile;
608600Sbill {
609600Sbill 	int	locindex;
610600Sbill 	u_long	Closeoutrel();
611600Sbill 
612600Sbill 	trsize = 0;
613600Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
614600Sbill 		trsize += Closeoutrel(rusefile[locindex], relocfile);
615600Sbill 	}
616600Sbill 	drsize = 0;
617600Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
618600Sbill 		drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
619600Sbill 	}
620600Sbill 	return(trsize + drsize);
621600Sbill }
622600Sbill 
623600Sbill u_long Closeoutrel(relfil, relocfile)
624600Sbill 	struct	relbufdesc	*relfil;
625600Sbill 	BFILE	*relocfile;
626600Sbill {
627600Sbill 	u_long	tail;
628600Sbill 	if (relfil == 0)
629600Sbill 		return(0L);
630600Sbill 	tail = Closeoutrel(relfil->rel_next, relocfile);
631600Sbill 	bwrite((char *)&relfil->rel_reloc[0],
632600Sbill 		relfil->rel_count * sizeof (struct relocation_info),
633600Sbill 		relocfile);
634600Sbill 	return(tail + relfil->rel_count * sizeof (struct relocation_info));
635600Sbill }
636600Sbill 
637634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
638600Sbill int sizesymtab()
639600Sbill {
640634Shenry 	return (sizeof (struct nlist) * NOUTSYMS);
641600Sbill }
642600Sbill /*
643600Sbill  *	Write out n symbols to file f, beginning at p
644600Sbill  *	ignoring symbols that are obsolete, jxxx instructions, and
645600Sbill  *	possibly, labels
646600Sbill  */
647600Sbill int symwrite(symfile)
648600Sbill 	BFILE *symfile;
649600Sbill {
65013514Srrh 		int	symsout;		/*those actually written*/
65113514Srrh 		int	symsdesired = NOUTSYMS;
65213514Srrh 	reg	struct	symtab *sp, *ub;
65313514Srrh 		char	*name;			/* temp to save the name */
654*14450Srrh 		int	totalstr;
655634Shenry 	/*
656634Shenry 	 *	We use sp->s_index to hold the length of the
657634Shenry 	 *	name; it isn't used for anything else
658634Shenry 	 */
659600Sbill 	register	struct	allocbox	*allocwalk;
660600Sbill 
661600Sbill 	symsout = 0;
662*14450Srrh 	totalstr = sizeof(totalstr);
663*14450Srrh 	DECLITERATE(allocwalk, sp, ub) {
664634Shenry 		if (sp->s_tag >= IGNOREBOUND)
665600Sbill 			continue;
666*14450Srrh 		if (ISLABEL(sp))
667600Sbill 			continue;
668600Sbill 		symsout++;
669634Shenry 		name = sp->s_name;		/* save pointer */
67013447Srrh 		/*
67113447Srrh 		 *	the length of the symbol table string
672*14450Srrh 		 *	always includes the trailing null;
673*14450Srrh 		 *	blast the pointer to its a.out value.
67413447Srrh 		 */
67513514Srrh 		if (sp->s_name && (sp->s_index = STRLEN(sp))){
676*14450Srrh 			sp->s_nmx = totalstr;
677*14450Srrh 			totalstr += sp->s_index;
678634Shenry 		} else {
67913447Srrh 			sp->s_nmx = 0;
680634Shenry 		}
681*14450Srrh 		if (sp->s_ptype != 0)
682*14450Srrh 			sp->s_type = sp->s_ptype;
683*14450Srrh 		else
684*14450Srrh 			sp->s_type = (sp->s_type & (~XFORW));
685640Sbill 		if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
686640Sbill 			sp->s_type = N_TEXT | (sp->s_type & N_EXT);
6875828Srrh 		bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile);
688634Shenry 		sp->s_name = name;		/* restore pointer */
689600Sbill 	}
690600Sbill 	if (symsout != symsdesired)
691600Sbill 		yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
692600Sbill 			symsout, symsdesired);
693600Sbill 	/*
694*14450Srrh 	 *	Construct the string pool from the symbols that were written,
695*14450Srrh 	 *	possibly fetching from the string file if the string
696*14450Srrh 	 *	is not core resident.
697600Sbill 	 */
698*14450Srrh 	bwrite(&totalstr, sizeof(totalstr), symfile);
699*14450Srrh 	symsout = 0;
700*14450Srrh 	DECLITERATE(allocwalk, sp, ub) {
701*14450Srrh 		if (sp->s_tag >= IGNOREBOUND)
702*14450Srrh 			continue;
703*14450Srrh 		if (ISLABEL(sp))
704*14450Srrh 			continue;
705*14450Srrh 		symsout++;
706*14450Srrh 		if (STRLEN(sp) > 0){
707*14450Srrh 		 if (STRPLACE(sp) & STR_CORE){
708*14450Srrh 			bwrite(FETCHNAME(sp), STRLEN(sp), symfile);
709*14450Srrh 		 } else if (STRPLACE(sp) & STR_FILE){
710*14450Srrh 			char	rbuf[2048];
711*14450Srrh 			int	left, nread;
712*14450Srrh 			fseek(strfile, STROFF(sp), 0);
713*14450Srrh 			for (left = STRLEN(sp); left > 0; left -= nread){
714*14450Srrh 				nread = fread(rbuf, sizeof(char),
715*14450Srrh 					min(sizeof(rbuf), left), strfile);
716*14450Srrh 				if (nread == 0)
717*14450Srrh 					break;
718*14450Srrh 				bwrite(rbuf, nread, symfile);
719*14450Srrh 			}
720*14450Srrh 		 }
72113447Srrh 		}
722600Sbill 	}
723*14450Srrh 	if (symsout != symsdesired)
724*14450Srrh 		yyerror("INTERNAL ERROR: Wrote %d strings, wanted %d\n",
725*14450Srrh 			symsout, symsdesired);
726600Sbill }
727