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