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