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