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