|
|
1.1 root 1: /*
2: * Copyright (c) 1982 Regents of the University of California
3: */
4: #ifndef lint
5: static 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: */
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)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: */
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 (!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:
142: stabfix()
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:
166: char *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:
179: char *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:
192: struct 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:
210: strpoolalloc()
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:
220: symcmp(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:
259: sortsymtab()
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
303: dumpsymtab()
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:
324: static char tagbuff[4];
325:
326: char *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");
344: default: (void)sprintf(tagbuff,"%d", tag);
345: return(tagbuff);
346: }
347: }
348: #endif DEBUG
349:
350: htaballoc()
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: */
375: struct 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: */
444: struct 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:
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(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: */
637: off_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:
654: u_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))
669: int 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: */
678: int 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.