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