null indirection
[unix-history] / usr / src / old / as.tahoe / assyms.c
CommitLineData
3bcc59ff
KB
1/*
2 * Copyright (c) 1982 Regents of the University of California
3 */
4#ifndef lint
5static char sccsid[] = "@(#)assyms.c 4.14 8/11/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 */
19struct allocbox *allochead; /*head of chunk list*/
20struct allocbox *alloctail; /*tail*/
21struct allocbox *newbox; /*for creating a new chunk*/
22struct symtab *nextsym; /*next symbol free*/
23int symsleft; /*slots left in current chunk*/
24
25struct symtab **symptrs;
26struct symtab **symdelim[NLOC + NLOC +1];
27struct symtab **symptrub;
28/*
29 * Managers for the dynamically extendable hash table
30 */
31struct hashdallop *htab;
32
33Iptr 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 */
38int nsyms; /* total number in the symbol table */
39int njxxx; /* number of jxxx entrys */
40int nforgotten; /* number of symbols erroneously entered */
41int nlabels; /* number of label entries */
42
43/*
44 * Managers of the symbol literal storage.
45 */
46struct strpool *strplhead = 0;
47
48symtabinit()
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 */
62syminstall()
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)0xAAAAAAAA;
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 itab[ip->i_opcode & 0xFF] = ip;
84 }
85 }
86} /*end of syminstall*/
87
88#define ISLABEL(sp) \
89 ( (!savelabels) \
90 && (sp->s_tag == LABELID) \
91 && (STRPLACE(sp) & STR_CORE) \
92 && (FETCHNAME(sp)[0] == 'L'))
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 */
98extern struct exec hdr;
99
100freezesymtab()
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 (!ISLABEL(sp))
130 sp->s_index = relpos++;
131 }
132}
133
134/*
135 * For all of the stabs that had their final value undefined during pass 1
136 * and during pass 2 assign a final value.
137 * We have already given stab entrys a initial approximation
138 * when we constsructed the sorted symbol table.
139 * Iteration order doesn't matter.
140 */
141
142stabfix()
143{
144 register struct symtab *sp, **cosp;
145 register struct symtab *p;
146
147 SYMITERATE(cosp, sp){
148 if(sp->s_ptype && (sp->s_type & STABFLAG)) {
149 p = sp->s_dest;
150/*
151 * STABFLOATING indicates that the offset has been saved in s_desc, s_other
152 */
153 if(sp->s_tag == STABFLOATING) {
154 sp->s_value = ( ( ((unsigned char) sp->s_other) << 16) | ( (unsigned short) sp->s_desc ) );
155 sp->s_value = sp->s_value + p->s_value;
156 }
157 else sp->s_value = p->s_value;
158 sp->s_index = p->s_index;
159 sp->s_type = p->s_type;
160
161
162 }
163 }
164}
165
166char *Calloc(number, size)
167 int number, size;
168{
169 register char *newstuff;
170 char *sbrk();
171 newstuff = sbrk(number*size);
172 if ((int)newstuff == -1){
173 yyerror("Ran out of Memory");
174 delexit();
175 }
176 return(newstuff);
177}
178
179char *ClearCalloc(number, size)
180 int number, size;
181{
182 register char *newstuff; /* r11 */
183 register int length = number * size; /* r10 */
184#ifdef lint
185 length = length;
186#endif length
187 newstuff = Calloc(number, size);
188 strncpy (newstuff, "\0", length);
189 return(newstuff);
190}
191
192struct symtab *symalloc()
193{
194 if (symsleft == 0){
195 newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
196 symsleft = SYMDALLOP;
197 nextsym = &newbox->symslots[0];
198 if (alloctail == 0){
199 allochead = alloctail = newbox;
200 } else {
201 alloctail->nextalloc = newbox;
202 alloctail = newbox;
203 }
204 }
205 --symsleft;
206 ++nsyms;
207 return(nextsym++);
208}
209
210strpoolalloc()
211{
212 register struct strpool *new;
213
214 new = (struct strpool *)Calloc(1, sizeof (struct strpool));
215 new->str_nalloc = 0;
216 new->str_next = strplhead;
217 strplhead = new;
218}
219
220symcmp(Pptr, Qptr)
221 struct symtab **Pptr, **Qptr;
222{
223 register struct symtab *p = *Pptr;
224 register struct symtab *q = *Qptr;
225 if (p->s_index < q->s_index)
226 return(-1);
227 if (p->s_index > q->s_index)
228 return(1);
229 if (p->s_value < q->s_value)
230 return(-1);
231 if (p->s_value > q->s_value)
232 return(1);
233 /*
234 * Force jxxx entries to virtually preceed labels defined
235 * to follow the jxxxx instruction, so that bumping the
236 * jxxx instruction correctly fixes up the following labels
237 */
238 if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/
239 return(-1);
240 if (q->s_tag >= IGNOREBOUND)
241 return(1);
242 /*
243 * both are now just plain labels; the relative order doesn't
244 * matter. Both can't be jxxxes, as they would have different
245 * values.
246 */
247 return(0);
248} /*end of symcmp*/
249
250/*
251 * We construct the auxiliary table of pointers, symptrs and
252 * symdelim
253 * We also assign preliminary values to stab entries that did not yet
254 * have an absolute value (because they initially referred to
255 * forward references). We don't worry about .stabds, as they
256 * already have an estimated final value
257 */
258
259sortsymtab()
260{
261 register struct symtab *sp;
262 register struct symtab **cowalk;
263 register struct allocbox *allocwalk;
264 struct symtab *ubsp;
265 int segno;
266 int slotno;
267 int symsin; /*number put into symptrs*/
268
269 symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
270 /*
271 * Allocate one word at the beginning of the symptr array
272 * so that backwards scans through the symptr array will
273 * work correctly while scanning through the zeroth segment
274 */
275 *symptrs++ = 0;
276 cowalk = symptrs;
277 symsin = 0;
278 DECLITERATE(allocwalk, sp, ubsp) {
279 if (sp->s_ptype && (sp->s_type &STABFLAG)){
280 sp->s_value = sp->s_dest->s_value;
281 sp->s_index = sp->s_dest->s_index;
282 }
283 if (symsin >= nsyms)
284 yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
285 *cowalk++ = sp;
286 symsin++;
287 }
288 if (symsin != nsyms)
289 yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
290 symsin, nsyms);
291 symptrub = &symptrs[nsyms ];
292 qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
293 symdelim[0] = symptrs;
294 for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
295 segno < NLOC + NLOC;
296 segno++, slotno++){
297 for (; sp && sp->s_index == segno; sp = *++cowalk);
298 symdelim[slotno] = cowalk; /*forms the ub delimeter*/
299 }
300} /*end of sortsymtab*/
301
302#ifdef DEBUG
303dumpsymtab()
304{
305 register int segno;
306 register struct symtab *sp, **cosp, *ub;
307 char *tagstring();
308
309 printf("Symbol Table dump:\n");
310 for (segno = 0; segno < NLOC + NLOC; segno++){
311 printf("Segment number: %d\n", segno);
312 SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
313 printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
314 segno, sp->s_name ? FETCHNAME(sp) : "(NULL)",
315 sp->s_value, sp->s_index,
316 tagstring(sp->s_tag));
317 printf("\t\ttype: %d jxbump %d jxfear: %d\n",
318 sp->s_type, sp->s_jxbump, sp->s_jxfear);
319 }
320 printf("\n\n");
321 }
322}
323
324static char tagbuff[4];
325
326char *tagstring(tag)
327 unsigned char tag;
328{
329 switch(tag){
330 case JXACTIVE: return("active");
331 case JXNOTYET: return("notyet");
332 case JXALIGN: return("align");
333 case JXQUESTIONABLE: return("jxquestionable");
334 case JXINACTIVE: return("inactive");
335 case JXTUNNEL: return("tunnel");
336 case OBSOLETE: return("obsolete");
337 case IGNOREBOUND: return("ignorebound");
338 case STABFLOATING: return("stabfloating");
339 case STABFIXED: return("stabfixed");
340 case LABELID: return("labelid");
341 case OKTOBUMP: return("oktobump");
342 case ISET: return("iset");
343 case ILSYM: return("ilsym");
9bd38ba8 344 default: (void)sprintf(tagbuff,"%d", tag);
3bcc59ff
KB
345 return(tagbuff);
346 }
347}
348#endif DEBUG
349
350htaballoc()
351{
352 register struct hashdallop *new;
353 new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
354 if (htab == 0)
355 htab = new;
356 else { /* add AFTER the 1st slot */
357 new->h_next = htab->h_next;
358 htab->h_next = new;
359 }
360}
361
362#define HASHCLOGGED (NHASH / 2)
363
364/*
365 * Lookup a symbol stored in extern yytext.
366 * All strings passed in via extern yytext had better have
367 * a trailing null. Strings are placed in yytext for hashing by
368 * syminstall() and by yylex();
369 *
370 * We take pains to avoid function calls; this functdion
371 * is called quite frequently, and the calls overhead
372 * in the vax contributes significantly to the overall
373 * execution speed of as.
374 */
375struct symtab **lookup(instflg)
376 int instflg; /* 0: don't install */
377{
378 static int initialprobe;
379 register struct symtab **hp;
380 register char *from;
381 register char *to;
382 register int len;
383 register int nprobes;
384 static struct hashdallop *hdallop;
385 static struct symtab **emptyslot;
386 static struct hashdallop *emptyhd;
387 static struct symtab **hp_ub;
388
389 emptyslot = 0;
390 for (nprobes = 0, from = yytext;
391 *from;
392 nprobes <<= 2, nprobes += *from++)
393 continue;
394 nprobes += from[-1] << 5;
395 nprobes %= NHASH;
396 if (nprobes < 0)
397 nprobes += NHASH;
398
399 initialprobe = nprobes;
400 for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
401 for (hp = &(hdallop->h_htab[initialprobe]),
402 nprobes = 1,
403 hp_ub = &(hdallop->h_htab[NHASH]);
404 (*hp) && (nprobes < NHASH);
405 hp += nprobes,
406 hp -= (hp >= hp_ub) ? NHASH:0,
407 nprobes += 2)
408 {
409 from = yytext;
410 to = FETCHNAME(*hp);
411 while (*from && *to)
412 if (*from++ != *to++)
413 goto nextprobe;
414 if (*to == *from) /*assert both are == 0*/
415 return(hp);
416 nextprobe: ;
417 }
418 if (*hp == 0 && emptyslot == 0 &&
419 hdallop->h_nused < HASHCLOGGED) {
420 emptyslot = hp;
421 emptyhd = hdallop;
422 }
423 }
424 if (emptyslot == 0) {
425 htaballoc();
426 hdallop = htab->h_next; /* aren't we smart! */
427 hp = &hdallop->h_htab[initialprobe];
428 } else {
429 hdallop = emptyhd;
430 hp = emptyslot;
431 }
432 if (instflg) {
433 *hp = symalloc();
434 hdallop->h_nused++;
435 for (from = yytext, len = 0; *from++; len++)
436 continue;
437 (*hp)->s_name = (char *)savestr(yytext, len + 1, STR_BOTH);
438 }
439 return(hp);
440} /*end of lookup*/
441/*
442 * save a string str with len in the places indicated by place
443 */
444struct strdesc *savestr(str, len, place)
445 char *str;
446 int len;
447 int place;
448{
449 reg struct strdesc *res;
450 reg int tlen;
451 /*
452 * Compute the total length of the record to live in core
453 */
454 tlen = sizeof(struct strdesc) - sizeof(res->sd_string);
455 if (place & STR_CORE)
456 tlen += (len + 3) & ~3;
457 /*
458 * See if there is enough space for the record,
459 * and allocate the record.
460 */
461 if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc))
462 strpoolalloc();
463 res = (struct strdesc *)(strplhead->str_names +
464 strplhead->str_nalloc);
465 /*
466 * Save the string information that is always present
467 */
468 res->sd_stroff = strfilepos;
469 res->sd_strlen = len;
470 res->sd_place = place;
471 /*
472 * Now, save the string itself. If str is null, then
473 * the characters have already been dumped to the file
474 */
475 if ((place & STR_CORE) && str)
476 movestr(res[0].sd_string, str, len);
477 if (place & STR_FILE){
478 if (str){
479 fwrite(str, 1, len, strfile);
480 }
481 strfilepos += len;
482 }
483 /*
484 * Adjust the in core string pool size
485 */
486 strplhead->str_nalloc += tlen;
487 return(res);
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
501struct relbufdesc{
502 int rel_count;
503 struct relbufdesc *rel_next;
504 struct relocation_info rel_reloc[NRELOC];
505};
506extern struct relbufdesc *tok_free;
507#define rel_free tok_free
508static struct relbufdesc *rel_temp;
509struct relocation_info r_can_1PC;
510struct relocation_info r_can_0PC;
511
512initoutrel()
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
524outrel(xp, reloc_how)
525 register struct exp *xp;
526 int reloc_how; /* TYPB..TYPD + (possibly)RELOC_PCREL */
527{
528 struct relocation_info reloc;
529 register int x_type_mask;
530 int pcrel;
531
532 x_type_mask = xp->e_xtype & ~XFORW;
533 pcrel = reloc_how & RELOC_PCREL;
534 reloc_how &= ~RELOC_PCREL;
535
536 if (bitoff&07)
537 yyerror("Padding error");
538 if (x_type_mask == XUNDEF)
539 yyerror("Undefined reference");
540
541 if ( (x_type_mask != XABS) || pcrel ) {
542 if (ty_NORELOC[reloc_how])
543 yyerror("Illegal Relocation of floating or large int number.");
544 reloc = pcrel ? r_can_1PC : r_can_0PC;
545 reloc.r_address = dotp->e_xvalue -
546 ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
547 reloc.r_length = ty_nlg[reloc_how];
548 switch(x_type_mask){
549 case XXTRN | XUNDEF:
550 reloc.r_symbolnum = xp->e_xname->s_index;
551 reloc.r_extern = 1;
552 break;
553 default:
554 if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
555 x_type_mask = XTEXT | (x_type_mask&XXTRN);
556 reloc.r_symbolnum = x_type_mask;
557 break;
558 }
559 if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
560 if (rel_free){
561 rel_temp = rel_free;
562 rel_free = rel_temp->rel_next;
563 } else {
564 rel_temp = (struct relbufdesc *)
565 Calloc(1,sizeof (struct relbufdesc));
566 }
567 rel_temp->rel_count = 0;
568 rel_temp->rel_next = relfil;
569 relfil = rusefile[dotp - &usedot[0]] = rel_temp;
570 }
571 relfil->rel_reloc[relfil->rel_count++] = reloc;
572 }
573 /*
574 * write the unrelocated value to the text file
575 */
576 dotp->e_xvalue += ty_nbyte[reloc_how];
577 if (pcrel)
578 xp->e_xvalue -= dotp->e_xvalue;
579 switch(reloc_how){
580 case TYPQ:
581 bwrite(&(xp->e_number.num_num.numIq_int.Iq_ulong[1]),
582 sizeof (long), txtfil);
583 bwrite(&(xp->e_number.num_num.numIq_int.Iq_ulong[0]),
584 sizeof (long), txtfil);
585 break;
586 case TYPD:
587 bwrite(&(xp->e_number.num_num.numFd_float.Fd_ulong[0]),
588 sizeof (long), txtfil);
589 bwrite(&(xp->e_number.num_num.numFd_float.Fd_ulong[1]),
590 sizeof (long), txtfil);
591 break;
592 case TYPF:
593 bwrite(&(xp->e_number.num_num.numFf_float.Ff_ulong[0]),
594 sizeof (long), txtfil);
595 break;
596
597 case TYPB:
598 bwrite(((char *)&(xp->e_xvalue))+3, ty_nbyte[reloc_how], txtfil);
599 break;
600 case TYPW:
601 bwrite(((char *)&(xp->e_xvalue))+2, ty_nbyte[reloc_how], txtfil);
602 break;
603 case TYPL:
604 bwrite ((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
605 break;
606 }
607 if (liston && (passno == 2))
608 switch (reloc_how)
609 {
610 case TYPQ:
611 long_out(xp->e_number.num_num.numIq_int.Iq_ulong[1]);
612 long_out(xp->e_number.num_num.numIq_int.Iq_ulong[0]);
613 case TYPD:
614 long_out(xp->e_number.num_num.numIq_int.Iq_ulong[0]);
615 long_out(xp->e_number.num_num.numIq_int.Iq_ulong[1]);
616 break;
617 case TYPF:
618 long_out(xp->e_number.num_num.numFf_float.Ff_ulong[0]);
619 break;
620
621 case TYPB:
622 byte_out(xp->e_xvalue);
623 break;
624 case TYPW:
625 word_out(xp->e_xvalue);
626 break;
627 case TYPL:
628 long_out(xp->e_xvalue);
629 break;
630 }
631}
632/*
633 * Flush out all of the relocation information.
634 * Note that the individual lists of buffers are in
635 * reverse order, so we must reverse them
636 */
637off_t closeoutrel(relocfile)
638 BFILE *relocfile;
639{
640 int locindex;
641 u_long Closeoutrel();
642
643 trsize = 0;
644 for (locindex = 0; locindex < NLOC; locindex++){
645 trsize += Closeoutrel(rusefile[locindex], relocfile);
646 }
647 drsize = 0;
648 for (locindex = 0; locindex < NLOC; locindex++){
649 drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
650 }
651 return(trsize + drsize);
652}
653
654u_long Closeoutrel(relfil, relocfile)
655 struct relbufdesc *relfil;
656 BFILE *relocfile;
657{
658 u_long tail;
659 if (relfil == 0)
660 return(0L);
661 tail = Closeoutrel(relfil->rel_next, relocfile);
662 bwrite((char *)&relfil->rel_reloc[0],
663 relfil->rel_count * sizeof (struct relocation_info),
664 relocfile);
665 return(tail + relfil->rel_count * sizeof (struct relocation_info));
666}
667
668#define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
669int sizesymtab()
670{
671 return (sizeof (struct nlist) * NOUTSYMS);
672}
673/*
674 * Write out n symbols to file f, beginning at p
675 * ignoring symbols that are obsolete, jxxx instructions, and
676 * possibly, labels
677 */
678int symwrite(symfile)
679 BFILE *symfile;
680{
681 int symsout; /*those actually written*/
682 int symsdesired = NOUTSYMS;
683 reg struct symtab *sp, *ub;
684 char *name; /* temp to save the name */
685 int totalstr;
686 /*
687 * We use sp->s_index to hold the length of the
688 * name; it isn't used for anything else
689 */
690 register struct allocbox *allocwalk;
691
692 symsout = 0;
693 totalstr = sizeof(totalstr);
694 DECLITERATE(allocwalk, sp, ub) {
695 if (sp->s_tag >= IGNOREBOUND)
696 continue;
697 if (ISLABEL(sp))
698 continue;
699 symsout++;
700 name = sp->s_name; /* save pointer */
701 /*
702 * the length of the symbol table string
703 * always includes the trailing null;
704 * blast the pointer to its a.out value.
705 */
706 if (sp->s_name && (sp->s_index = STRLEN(sp))){
707 sp->s_nmx = totalstr;
708 totalstr += sp->s_index;
709 } else {
710 sp->s_nmx = 0;
711 }
712 if (sp->s_ptype != 0)
713 sp->s_type = sp->s_ptype;
714 else
715 sp->s_type = (sp->s_type & (~XFORW));
716 if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
717 sp->s_type = N_TEXT | (sp->s_type & N_EXT);
718 bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile);
719 sp->s_name = name; /* restore pointer */
720 }
721 if (symsout != symsdesired)
722 yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
723 symsout, symsdesired);
724 /*
725 * Construct the string pool from the symbols that were written,
726 * possibly fetching from the string file if the string
727 * is not core resident.
728 */
729 bwrite(&totalstr, sizeof(totalstr), symfile);
730 symsout = 0;
731 DECLITERATE(allocwalk, sp, ub) {
732 if (sp->s_tag >= IGNOREBOUND)
733 continue;
734 if (ISLABEL(sp))
735 continue;
736 symsout++;
737 if (sp->s_name && STRLEN(sp) > 0){
738 if (STRPLACE(sp) & STR_CORE){
739 bwrite(FETCHNAME(sp), STRLEN(sp), symfile);
740 } else if (STRPLACE(sp) & STR_FILE){
741 char rbuf[2048];
742 int left, nread;
743 fseek(strfile, STROFF(sp), 0);
744 for (left = STRLEN(sp); left > 0; left -= nread){
745 nread = fread(rbuf, sizeof(char),
746 min(sizeof(rbuf), left), strfile);
747 if (nread == 0)
748 break;
749 bwrite(rbuf, nread, symfile);
750 }
751 }
752 }
753 }
754 if (symsout != symsdesired)
755 yyerror("INTERNAL ERROR: Wrote %d strings, wanted %d\n",
756 symsout, symsdesired);
757}