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