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