xref: /original-bsd/old/as.vax/assyms.c (revision 957a0273)
1 /*
2  *	Copyright (c) 1982 Regents of the University of California
3  */
4 #ifndef lint
5 static char sccsid[] = "@(#)assyms.c 4.7 02/14/82";
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 stabfix() {
162 	register struct symtab *sp, **cosp;
163 	register struct symtab *p;
164 
165 	SYMITERATE(cosp, sp){
166 		if(sp->s_ptype && (sp->s_type & STABFLAG)) {
167 			p = sp->s_dest;
168 			sp->s_value = p->s_value;
169 			sp->s_index = p->s_index;
170 			sp->s_type = p->s_type;
171 		}
172 	}
173 }
174 
175 char *Calloc(number, size)
176 	int	number, size;
177 {
178 	register	char *newstuff;
179 	char	*sbrk();
180 	newstuff = sbrk(number*size);
181 	if ((int)newstuff == -1){
182 		yyerror("Ran out of Memory");
183 		delexit();
184 	}
185 	return(newstuff);
186 }
187 
188 char *ClearCalloc(number, size)
189 	int	number, size;
190 {
191 	register	char	*newstuff;		/* r11 */
192 	register	int	length = number * size;	/* r10 */
193 #ifdef lint
194 	length = length;
195 #endif length
196 	newstuff = Calloc(number, size);
197 	asm("movc5 $0, (r0), $0, r10, (r11)");
198 	return(newstuff);
199 }
200 
201 struct symtab *symalloc()
202 {
203 	if (symsleft == 0){
204 		newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
205 		symsleft = SYMDALLOP;
206 		nextsym = &newbox->symslots[0];
207 		if (alloctail == 0){
208 			allochead = alloctail = newbox;
209 		} else {
210 			alloctail->nextalloc = newbox;
211 			alloctail = newbox;
212 		}
213 	}
214 	--symsleft;
215 	++nsyms;
216 	return(nextsym++);
217 }
218 
219 #ifdef FLEXNAMES
220 strpoolalloc()
221 {
222 	register	struct	strpool	*new;
223 
224 	new = (struct strpool *)Calloc(1, sizeof (struct strpool));
225 	new->str_nalloc = 0;
226 	new->str_next = strplhead;
227 	strplhead = new;
228 }
229 #endif FLEXNAMES
230 
231 symcmp(Pptr, Qptr)
232 	struct symtab **Pptr, **Qptr;
233 {
234 	register struct symtab *p = *Pptr;
235 	register struct symtab *q = *Qptr;
236 	if (p->s_index < q->s_index)
237 		return(-1);
238 	if (p->s_index > q->s_index)
239 		return(1);
240 	if (p->s_value < q->s_value)
241 		return(-1);
242 	if (p->s_value > q->s_value)
243 		return(1);
244 	/*
245 	 *	Force jxxx entries to virtually preceed labels defined
246 	 *	to follow the jxxxx instruction, so that bumping the
247 	 *	jxxx instruction correctly fixes up the following labels
248 	 */
249 	if (p->s_tag >= IGNOREBOUND)	/*p points to a jxxx*/
250 		return(-1);
251 	if (q->s_tag >= IGNOREBOUND)
252 		return(1);
253 	/*
254 	 *	both are now just plain labels; the relative order doesn't
255 	 *	matter.  Both can't be jxxxes, as they would have different
256 	 *	values.
257 	 */
258 	return(0);
259 }	/*end of symcmp*/
260 
261 /*
262  *	We construct the auxiliary table of pointers, symptrs and
263  *	symdelim
264  *	We also assign preliminary values to stab entries that did not yet
265  *	have an absolute value (because they initially referred to
266  *	forward references). We don't worry about .stabds, as they
267  *	already have an estimated final value
268  */
269 
270 sortsymtab()
271 {
272 	register	struct	symtab	*sp;
273 	register	struct	symtab	**cowalk;
274 	register	struct	allocbox	*allocwalk;
275 			struct	symtab	*ubsp;
276 				int	segno;
277 				int	slotno;
278 				int	symsin;	/*number put into symptrs*/
279 
280 	symptrs =  (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
281 	/*
282 	 *	Allocate one word at the beginning of the symptr array
283 	 *	so that backwards scans through the symptr array will
284 	 *	work correctly while scanning through the zeroth segment
285 	 */
286 	*symptrs++ = 0;
287 	cowalk = symptrs;
288 	symsin = 0;
289 	DECLITERATE(allocwalk, sp, ubsp) {
290 		if (sp->s_ptype && (sp->s_type &STABFLAG)){
291 			sp->s_value = sp->s_dest->s_value;
292 			sp->s_index = sp->s_dest->s_index;
293 		}
294 		if (symsin >= nsyms)
295 			yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
296 		*cowalk++ = sp;
297 		symsin++;
298 	}
299 	if (symsin != nsyms)
300 		yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
301 			symsin, nsyms);
302 	symptrub = &symptrs[nsyms ];
303 	qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
304 	symdelim[0] = symptrs;
305 	for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
306 	     segno < NLOC + NLOC;
307 	     segno++, slotno++){
308 		for (; sp && sp->s_index == segno; sp = *++cowalk);
309 		symdelim[slotno] = cowalk;	/*forms the ub delimeter*/
310 	}
311 }	/*end of sortsymtab*/
312 
313 #ifdef DEBUG
314 dumpsymtab()
315 {
316 	register	int	segno;
317 	register	struct symtab *sp, **cosp, *ub;
318 	char		*tagstring();
319 
320 	printf("Symbol Table dump:\n");
321 	for (segno = 0; segno < NLOC + NLOC; segno++){
322 		printf("Segment number: %d\n", segno);
323 		SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
324 #ifdef FLEXNAMES
325 			printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
326 				segno, sp->s_name,
327 				sp->s_value, sp->s_index,
328 				tagstring(sp->s_tag));
329 #else not FLEXNAMES
330 			printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n",
331 				segno, NCPS, NCPS, sp->s_name,
332 				sp->s_value, sp->s_index,
333 				tagstring(sp->s_tag));
334 #endif not FLEXNAMES
335 			printf("\t\ttype: %d jxbump %d jxfear: %d\n",
336 				sp->s_type, sp->s_jxbump, sp->s_jxfear);
337 		}
338 		printf("\n\n");
339 	}
340 }
341 
342 static	char tagbuff[4];
343 
344 char *tagstring(tag)
345 	unsigned	char	tag;
346 {
347 	switch(tag){
348 		case JXACTIVE:		return("active");
349 		case JXNOTYET:		return("notyet");
350 		case JXALIGN:		return("align");
351 		case JXQUESTIONABLE:	return("jxquestionable");
352 		case JXINACTIVE:	return("inactive");
353 		case JXTUNNEL:		return("tunnel");
354 		case OBSOLETE:		return("obsolete");
355 		case IGNOREBOUND:	return("ignorebound");
356 		case STABFLOATING:	return("stabfloating");
357 		case STABFIXED:		return("stabfixed");
358 		case LABELID:		return("labelid");
359 		case OKTOBUMP:		return("oktobump");
360 		case ISET:		return("iset");
361 		case ILSYM:		return("ilsym");
362 		default:		sprintf(tagbuff,"%d", tag);
363 					return(tagbuff);
364 	}
365 }
366 #endif DEBUG
367 
368 htaballoc()
369 {
370 	register	struct	hashdallop	*new;
371 	new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
372 	if (htab == 0)
373 		htab = new;
374 	else {		/* add AFTER the 1st slot */
375 		new->h_next = htab->h_next;
376 		htab->h_next = new;
377 	}
378 }
379 
380 #define 	HASHCLOGGED	(NHASH / 2)
381 
382 /*
383  *	Lookup a symbol stored in extern yytext.
384  *	All strings passed in via extern yytext had better have
385  *	a trailing null.  Strings are placed in yytext for hashing by
386  *	syminstall() and by yylex();
387  *
388  *	We take pains to avoid function calls; this functdion
389  *	is called quite frequently, and the calls overhead
390  *	in the vax contributes significantly to the overall
391  *	execution speed of as.
392  */
393 struct symtab **lookup(instflg)
394 	int	instflg;		/* 0: don't install */
395 {
396 	static	 int		initialprobe;
397 	register struct	symtab 	**hp;
398 	register char 		*from;
399 	register char		*to;
400 	register	int	len;
401 	register	int	nprobes;
402 	static	 struct hashdallop *hdallop;
403 	static	 struct symtab	**emptyslot;
404 	static 	 struct hashdallop *emptyhd;
405 	static	 struct	symtab	**hp_ub;
406 
407 	emptyslot = 0;
408 	for (nprobes = 0, from = yytext;
409 	     *from;
410 	     nprobes <<= 2, nprobes += *from++)
411 		continue;
412 	nprobes += from[-1] << 5;
413 	nprobes %= NHASH;
414 	if (nprobes < 0)
415 		nprobes += NHASH;
416 
417 	initialprobe = nprobes;
418 	for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
419 		for (hp = &(hdallop->h_htab[initialprobe]),
420 				nprobes = 1,
421 				hp_ub = &(hdallop->h_htab[NHASH]);
422 		     (*hp) && (nprobes < NHASH);
423 				hp += nprobes,
424 				hp -= (hp >= hp_ub) ? NHASH:0,
425 				nprobes += 2)
426 		{
427 			from = yytext;
428 			to = (*hp)->s_name;
429 #ifndef FLEXNAMES
430 			for (len = 0; (len<NCPS) && *from; len++)
431 				if (*from++ != *to++)
432 					goto nextprobe;
433 			if (len >= NCPS)	/*both are maximal length*/
434 				return(hp);
435 			if (*to == 0)		/*assert *from == 0*/
436 				return(hp);
437 #else FLEXNAMES
438 			while (*from && *to)
439 				if (*from++ != *to++)
440 					goto nextprobe;
441 			if (*to == *from)	/*assert both are == 0*/
442 				return(hp);
443 #endif FLEXNAMES
444 
445 	nextprobe: ;
446 		}
447 		if (*hp == 0 && emptyslot == 0 &&
448 		    hdallop->h_nused < HASHCLOGGED) {
449 			emptyslot = hp;
450 			emptyhd = hdallop;
451 		}
452 	}
453 	if (emptyslot == 0) {
454 		htaballoc();
455 		hdallop = htab->h_next;		/* aren't we smart! */
456 		hp = &hdallop->h_htab[initialprobe];
457 	} else {
458 		hdallop = emptyhd;
459 		hp = emptyslot;
460 	}
461 	if (instflg) {
462 		*hp = symalloc();
463 		hdallop->h_nused++;
464 #ifndef FLEXNAMES
465 		for(len = 0, from = yytext, to = (*hp)->s_name; (len<NCPS); len++)
466  			if ((*to++ = *from++) == '\0')
467  				break;
468 #else FLEXNAMES
469 		for (from = yytext, len = 1; *from++; len++)
470 			continue;
471 		if (len >= (STRPOOLDALLOP - strplhead->str_nalloc))
472 			strpoolalloc();
473 		for ( (*hp)->s_name = to = strplhead->str_names + strplhead->str_nalloc, from = yytext;
474 		     ( (*to++ = *from++) != '\0'); )
475 			continue;
476 		strplhead->str_nalloc += len;
477 #endif FLEXNAMES
478 	}
479 	return(hp);
480 }	/*end of lookup*/
481 
482 #ifdef FLEXNAMES
483 char *savestr(str)
484 	char *str;
485 {
486 	register int len;
487 	register char *from, *to;
488 	char *res;
489 
490 	for (from = str, len = 1; *from++; len++)
491 		continue;
492 	if (len >= (STRPOOLDALLOP - strplhead->str_nalloc))
493 		strpoolalloc();
494 	for ( res = to = strplhead->str_names + strplhead->str_nalloc, from = str;
495 		     ( (*to++ = *from++) != '\0'); )
496 			continue;
497 	strplhead->str_nalloc += len;
498 	return (res);
499 }
500 #endif FLEXNAMES
501 
502 /*
503  *	The relocation information is saved internally in an array of
504  *	lists of relocation buffers.  The relocation buffers are
505  *	exactly the same size as a token buffer; if we use VM for the
506  *	temporary file we reclaim this storage, otherwise we create
507  *	them by mallocing.
508  */
509 #define	RELBUFLG	TOKBUFLG
510 #define	NRELOC		((TOKBUFLG - \
511 			  (sizeof (int) + sizeof (struct relbufdesc *)) \
512 			) / (sizeof (struct relocation_info)))
513 
514 struct	relbufdesc{
515 	int	rel_count;
516 	struct	relbufdesc	*rel_next;
517 	struct	relocation_info	rel_reloc[NRELOC];
518 };
519 extern	struct	relbufdesc	*tok_free;
520 #define	rel_free tok_free
521 static	struct	relbufdesc	*rel_temp;
522 struct	relocation_info r_can_1PC;
523 struct	relocation_info	r_can_0PC;
524 
525 initoutrel()
526 {
527 	r_can_0PC.r_address = 0;
528 	r_can_0PC.r_symbolnum = 0;
529 	r_can_0PC.r_pcrel = 0;
530 	r_can_0PC.r_length = 0;
531 	r_can_0PC.r_extern = 0;
532 
533 	r_can_1PC = r_can_0PC;
534 	r_can_1PC.r_pcrel = 1;
535 }
536 
537 outrel(xp, reloc_how)
538 	register	struct	exp	*xp;
539 	int		reloc_how;	/* TYPB..TYPH + (possibly)RELOC_PCREL */
540 {
541 	struct		relocation_info	reloc;
542 	register	int	x_type_mask;
543 	int		pcrel;
544 
545 	x_type_mask = xp->e_xtype & ~XFORW;
546 	pcrel = reloc_how & RELOC_PCREL;
547 	reloc_how &= ~RELOC_PCREL;
548 
549 	if (bitoff&07)
550 		yyerror("Padding error");
551 	if (x_type_mask == XUNDEF)
552 		yyerror("Undefined reference");
553 
554 	if ( (x_type_mask != XABS) || pcrel ) {
555 		if (ty_NORELOC[reloc_how])
556 			yyerror("Illegal Relocation of floating or large int number.");
557 		reloc = pcrel ? r_can_1PC : r_can_0PC;
558 		reloc.r_address = dotp->e_xvalue -
559 		    ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
560 		reloc.r_length = ty_nlg[reloc_how];
561 		switch(x_type_mask){
562 			case XXTRN | XUNDEF:
563 				reloc.r_symbolnum = xp->e_xname->s_index;
564 				reloc.r_extern = 1;
565 				break;
566 			default:
567 				if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
568 					x_type_mask = XTEXT | (x_type_mask&XXTRN);
569 				reloc.r_symbolnum = x_type_mask;
570 				break;
571 		}
572 		if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
573 			if (rel_free){
574 				rel_temp = rel_free;
575 				rel_free = rel_temp->rel_next;
576 			} else {
577 				rel_temp = (struct relbufdesc *)
578 					Calloc(1,sizeof (struct relbufdesc));
579 			}
580 			rel_temp->rel_count = 0;
581 			rel_temp->rel_next = relfil;
582 			relfil = rusefile[dotp - &usedot[0]] = rel_temp;
583 		}
584 		relfil->rel_reloc[relfil->rel_count++] = reloc;
585 	}
586 	/*
587 	 *	write the unrelocated value to the text file
588 	 */
589 	dotp->e_xvalue += ty_nbyte[reloc_how];
590 	if (pcrel)
591 		xp->e_xvalue -= dotp->e_xvalue;
592 	switch(reloc_how){
593 	case TYPO:
594 	case TYPQ:
595 
596 	case TYPF:
597 	case TYPD:
598 	case TYPG:
599 	case TYPH:
600 		bignumwrite(xp->e_number, reloc_how);
601 		break;
602 
603 	default:
604 		bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
605 		break;
606 	}
607 }
608 /*
609  *	Flush out all of the relocation information.
610  *	Note that the individual lists of buffers are in
611  *	reverse order, so we must reverse them
612  */
613 off_t closeoutrel(relocfile)
614 	BFILE	*relocfile;
615 {
616 	int	locindex;
617 	u_long	Closeoutrel();
618 
619 	trsize = 0;
620 	for (locindex = 0; locindex < NLOC; locindex++){
621 		trsize += Closeoutrel(rusefile[locindex], relocfile);
622 	}
623 	drsize = 0;
624 	for (locindex = 0; locindex < NLOC; locindex++){
625 		drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
626 	}
627 	return(trsize + drsize);
628 }
629 
630 u_long Closeoutrel(relfil, relocfile)
631 	struct	relbufdesc	*relfil;
632 	BFILE	*relocfile;
633 {
634 	u_long	tail;
635 	if (relfil == 0)
636 		return(0L);
637 	tail = Closeoutrel(relfil->rel_next, relocfile);
638 	bwrite((char *)&relfil->rel_reloc[0],
639 		relfil->rel_count * sizeof (struct relocation_info),
640 		relocfile);
641 	return(tail + relfil->rel_count * sizeof (struct relocation_info));
642 }
643 
644 #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
645 int sizesymtab()
646 {
647 	return (sizeof (struct nlist) * NOUTSYMS);
648 }
649 
650 #ifdef FLEXNAMES
651 /*
652  *	We write out the flexible length character strings for  names
653  *	in two stages.
654  *	1)	We have always! maintain a fixed sized name list entry;
655  *	the string is indexed by a four byte quantity from the beginning
656  *	of the string pool area.  Index 0 is reserved, and indicates
657  *	that there is no associated string. The first valid index is 4.
658  *	2)	 We concatenate together and write all of the strings
659  *	in the string pool at the end of the name list. The first
660  *	four bytes in the string pool are indexed only by 0 (see above);
661  *	they contain the total number of bytes in the string pool.
662  */
663 #endif FLEXNAMES
664 
665 /*
666  *	Write out n symbols to file f, beginning at p
667  *	ignoring symbols that are obsolete, jxxx instructions, and
668  *	possibly, labels
669  */
670 
671 int symwrite(symfile)
672 	BFILE *symfile;
673 {
674 	int	symsout;			/*those actually written*/
675 	int	symsdesired = NOUTSYMS;
676 	register	struct	symtab *sp, *ub;
677 #ifdef FLEXNAMES
678 	char		*name;			/* temp to save the name */
679 	long		stroff	= sizeof (stroff);
680 	/*
681 	 *	We use sp->s_index to hold the length of the
682 	 *	name; it isn't used for anything else
683 	 */
684 #endif FLEXNAMES
685 
686 	register	struct	allocbox	*allocwalk;
687 
688 	symsout = 0;
689 	DECLITERATE(allocwalk, sp, ub)
690 	{
691 		if (sp->s_tag >= IGNOREBOUND)
692 			continue;
693 		if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels)
694 			continue;
695 		symsout++;
696 
697 #ifdef FLEXNAMES
698 		name = sp->s_name;		/* save pointer */
699 		if ( (sp->s_index = strlen(sp->s_name)) != 0){
700 			sp->s_nmx = stroff;	/* clobber pointer */
701 			stroff += sp->s_index + 1;
702 		} else {
703 			sp->s_nmx = 0;		/* clobber pointer */
704 		}
705 #endif
706 		sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW));
707 		if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
708 			sp->s_type = N_TEXT | (sp->s_type & N_EXT);
709 		bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile);
710 #ifdef FLEXNAMES
711 		sp->s_name = name;		/* restore pointer */
712 #endif FLEXNAMES
713 	}
714 	if (symsout != symsdesired)
715 		yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
716 			symsout, symsdesired);
717 #ifdef FLEXNAMES
718 	/*
719 	 *	Pass 2 through the string pool
720 	 */
721 	symsout = 0;
722 	bwrite((char *)&stroff, sizeof (stroff), symfile);
723 	stroff = sizeof (stroff);
724 	symsout = 0;
725 	DECLITERATE(allocwalk, sp, ub)
726 	{
727 		if (sp->s_tag >= IGNOREBOUND)
728 			continue;
729 		if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels)
730 			continue;
731 		sp->s_index = strlen(sp->s_name);
732 		if (sp->s_index)
733 			bwrite(sp->s_name, sp->s_index + 1, symfile);
734 	}
735 #endif FLEXNAMES
736 }
737