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