bye bye VMS: UNIX only. All the preceeding changes to the symbol
[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
ec43bca4 5static char sccsid[] = "@(#)assyms.c 4.11 %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
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 */
101extern struct exec hdr;
102
103freezesymtab()
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 {
451260e7 113 if (sp->s_tag >= IGNOREBOUND)
5178805d
BJ
114 continue; /*totally ignore jxxx entries */
115 /*
116 * Ignore stabs, but give them a symbol table index
117 */
451260e7 118 if (sp->s_type & STABFLAG)
5178805d 119 goto assignindex;
451260e7
RH
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;
5178805d
BJ
129 hdr.a_bss += bs;
130 }
131 assignindex:
ec43bca4 132 if ( (FETCHNAME(sp)[0] != 'L')
451260e7 133 || (sp->s_tag != LABELID)
5178805d
BJ
134 || savelabels
135 ) /*then, we will write it later on*/
451260e7 136 sp->s_index = relpos++;
5178805d
BJ
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 */
ac73cea0
AF
149
150stabfix()
151{
5178805d
BJ
152 register struct symtab *sp, **cosp;
153 register struct symtab *p;
154
155 SYMITERATE(cosp, sp){
451260e7
RH
156 if(sp->s_ptype && (sp->s_type & STABFLAG)) {
157 p = sp->s_dest;
ac73cea0
AF
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;
451260e7
RH
166 sp->s_index = p->s_index;
167 sp->s_type = p->s_type;
ac73cea0
AF
168
169
5178805d
BJ
170 }
171 }
172}
173
174char *Calloc(number, size)
175 int number, size;
176{
177 register char *newstuff;
f70ab843
RH
178 char *sbrk();
179 newstuff = sbrk(number*size);
5178805d
BJ
180 if ((int)newstuff == -1){
181 yyerror("Ran out of Memory");
182 delexit();
183 }
184 return(newstuff);
185}
186
187char *ClearCalloc(number, size)
188 int number, size;
189{
190 register char *newstuff; /* r11 */
191 register int length = number * size; /* r10 */
f70ab843
RH
192#ifdef lint
193 length = length;
194#endif length
5178805d
BJ
195 newstuff = Calloc(number, size);
196 asm("movc5 $0, (r0), $0, r10, (r11)");
197 return(newstuff);
198}
199
200struct symtab *symalloc()
201{
202 if (symsleft == 0){
203 newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
204 symsleft = SYMDALLOP;
205 nextsym = &newbox->symslots[0];
5178805d
BJ
206 if (alloctail == 0){
207 allochead = alloctail = newbox;
208 } else {
209 alloctail->nextalloc = newbox;
210 alloctail = newbox;
211 }
212 }
213 --symsleft;
214 ++nsyms;
5178805d
BJ
215 return(nextsym++);
216}
217
5178805d
BJ
218strpoolalloc()
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}
5178805d
BJ
227
228symcmp(Pptr, Qptr)
229 struct symtab **Pptr, **Qptr;
230{
231 register struct symtab *p = *Pptr;
232 register struct symtab *q = *Qptr;
451260e7 233 if (p->s_index < q->s_index)
5178805d 234 return(-1);
451260e7 235 if (p->s_index > q->s_index)
5178805d 236 return(1);
451260e7 237 if (p->s_value < q->s_value)
5178805d 238 return(-1);
451260e7 239 if (p->s_value > q->s_value)
5178805d
BJ
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 */
451260e7 246 if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/
5178805d 247 return(-1);
451260e7 248 if (q->s_tag >= IGNOREBOUND)
5178805d
BJ
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
267sortsymtab()
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) {
451260e7
RH
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;
5178805d
BJ
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++){
451260e7 305 for (; sp && sp->s_index == segno; sp = *++cowalk);
5178805d
BJ
306 symdelim[slotno] = cowalk; /*forms the ub delimeter*/
307 }
308} /*end of sortsymtab*/
309
310#ifdef DEBUG
311dumpsymtab()
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",
ec43bca4 323 segno, FETCHNAME(sp),
451260e7
RH
324 sp->s_value, sp->s_index,
325 tagstring(sp->s_tag));
5178805d
BJ
326#else not FLEXNAMES
327 printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n",
ec43bca4 328 segno, NCPName, NCPName, FETCHNAME(sp),
451260e7
RH
329 sp->s_value, sp->s_index,
330 tagstring(sp->s_tag));
5178805d
BJ
331#endif not FLEXNAMES
332 printf("\t\ttype: %d jxbump %d jxfear: %d\n",
451260e7 333 sp->s_type, sp->s_jxbump, sp->s_jxfear);
5178805d
BJ
334 }
335 printf("\n\n");
336 }
337}
338
339static char tagbuff[4];
340
341char *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
365htaballoc()
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 */
390struct 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;
ec43bca4
RH
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;
5178805d
BJ
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;
ec43bca4 426 to = FETCHNAME(*hp);
5178805d 427#ifndef FLEXNAMES
abcba8d5 428 for (len = 0; (len<NCPName) && *from; len++)
5178805d
BJ
429 if (*from++ != *to++)
430 goto nextprobe;
abcba8d5 431 if (len >= NCPName) /*both are maximal length*/
5178805d
BJ
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
ec43bca4 463 strncpy(FETCHNAME(*hp), yytext, NCPName);
5178805d 464#else FLEXNAMES
ad67d5e5 465 for (from = yytext, len = 0; *from++; len++)
5178805d 466 continue;
ad67d5e5 467 /*
ec43bca4
RH
468 * save string and trailing null, both
469 * internally, and in the string temporary file
ad67d5e5 470 */
ec43bca4
RH
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);
5178805d
BJ
478#endif FLEXNAMES
479 }
480 return(hp);
481} /*end of lookup*/
ad67d5e5 482/*
ec43bca4 483 * save a string str, descriptor strdp, in the string pool
ad67d5e5 484 */
ec43bca4 485struct strdesc *savestr(str, strdp)
ad67d5e5 486 char *str;
ec43bca4 487 struct strdesc *strdp;
5178805d 488{
ec43bca4
RH
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;
5178805d 495
ec43bca4 496 if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc))
5178805d 497 strpoolalloc();
ec43bca4
RH
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;
ad67d5e5 503 return(res);
5178805d
BJ
504}
505
5178805d
BJ
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
518struct relbufdesc{
519 int rel_count;
520 struct relbufdesc *rel_next;
521 struct relocation_info rel_reloc[NRELOC];
522};
523extern struct relbufdesc *tok_free;
524#define rel_free tok_free
525static struct relbufdesc *rel_temp;
451260e7
RH
526struct relocation_info r_can_1PC;
527struct relocation_info r_can_0PC;
5178805d
BJ
528
529initoutrel()
530{
451260e7
RH
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;
5178805d
BJ
538 r_can_1PC.r_pcrel = 1;
539}
540
5b3c350a
RH
541outrel(xp, reloc_how)
542 register struct exp *xp;
f70ab843 543 int reloc_how; /* TYPB..TYPH + (possibly)RELOC_PCREL */
5178805d 544{
5b3c350a
RH
545 struct relocation_info reloc;
546 register int x_type_mask;
ad67d5e5 547 int pcrel;
5178805d 548
5b3c350a
RH
549 x_type_mask = xp->e_xtype & ~XFORW;
550 pcrel = reloc_how & RELOC_PCREL;
551 reloc_how &= ~RELOC_PCREL;
552
5178805d
BJ
553 if (bitoff&07)
554 yyerror("Padding error");
5b3c350a 555 if (x_type_mask == XUNDEF)
5178805d
BJ
556 yyerror("Undefined reference");
557
5b3c350a
RH
558 if ( (x_type_mask != XABS) || pcrel ) {
559 if (ty_NORELOC[reloc_how])
f70ab843 560 yyerror("Illegal Relocation of floating or large int number.");
5b3c350a 561 reloc = pcrel ? r_can_1PC : r_can_0PC;
451260e7 562 reloc.r_address = dotp->e_xvalue -
030352e9 563 ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
5b3c350a
RH
564 reloc.r_length = ty_nlg[reloc_how];
565 switch(x_type_mask){
5178805d 566 case XXTRN | XUNDEF:
5b3c350a 567 reloc.r_symbolnum = xp->e_xname->s_index;
5178805d
BJ
568 reloc.r_extern = 1;
569 break;
570 default:
5b3c350a
RH
571 if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
572 x_type_mask = XTEXT | (x_type_mask&XXTRN);
573 reloc.r_symbolnum = x_type_mask;
5178805d
BJ
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 */
5b3c350a
RH
593 dotp->e_xvalue += ty_nbyte[reloc_how];
594 if (pcrel)
595 xp->e_xvalue -= dotp->e_xvalue;
f70ab843
RH
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 }
5178805d
BJ
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 */
617off_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
634u_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
451260e7 648#define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
5178805d
BJ
649int sizesymtab()
650{
451260e7 651 return (sizeof (struct nlist) * NOUTSYMS);
5178805d
BJ
652}
653
654#ifdef FLEXNAMES
655/*
656 * We write out the flexible length character strings for names
657 * in two stages.
ad67d5e5 658 * 1) We always! maintain a fixed sized name list entry;
5178805d
BJ
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
675int symwrite(symfile)
676 BFILE *symfile;
677{
ec43bca4
RH
678 int symsout; /*those actually written*/
679 int symsdesired = NOUTSYMS;
680 reg struct symtab *sp, *ub;
5178805d 681#ifdef FLEXNAMES
ec43bca4
RH
682 char *name; /* temp to save the name */
683 int nread;
684 char rbuf[2048];
685 int i;
451260e7
RH
686 /*
687 * We use sp->s_index to hold the length of the
688 * name; it isn't used for anything else
689 */
5178805d
BJ
690#endif FLEXNAMES
691
692 register struct allocbox *allocwalk;
693
694 symsout = 0;
695 DECLITERATE(allocwalk, sp, ub)
696 {
451260e7 697 if (sp->s_tag >= IGNOREBOUND)
5178805d 698 continue;
ec43bca4 699 if ((FETCHNAME(sp)[0] == 'L') && (sp->s_tag == LABELID) && !savelabels)
5178805d
BJ
700 continue;
701 symsout++;
451260e7
RH
702
703#ifdef FLEXNAMES
704 name = sp->s_name; /* save pointer */
ad67d5e5
RH
705 /*
706 * the length of the symbol table string
707 * always includes the trailing null
708 */
ec43bca4
RH
709 if (sp->s_name && (sp->s_index = STRLEN(sp))){
710 sp->s_nmx = STROFF(sp); /* clobber */
451260e7 711 } else {
ad67d5e5 712 sp->s_nmx = 0;
451260e7 713 }
ec43bca4
RH
714#ifdef DEBUG
715 printf("symbol %d: nmx == %d\n", symsout, sp->s_nmx);
716#endif DEBUG
717#endif FLEXNAMES
451260e7 718 sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW));
030352e9
BJ
719 if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
720 sp->s_type = N_TEXT | (sp->s_type & N_EXT);
f70ab843 721 bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile);
451260e7
RH
722#ifdef FLEXNAMES
723 sp->s_name = name; /* restore pointer */
5178805d 724#endif FLEXNAMES
5178805d
BJ
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 /*
ec43bca4
RH
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.
5178805d 735 */
ec43bca4
RH
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;
ad67d5e5 743 }
ec43bca4
RH
744 bwrite(rbuf, nread, symfile);
745 i++;
5178805d
BJ
746 }
747#endif FLEXNAMES
748}