1 #ifndef lint 2 static char sccsid[] = "@(#)stabstring.c 1.1 (Berkeley) 06/23/84"; /* from 1.4 84/03/27 10:24:04 linton Exp */ 3 #endif 4 5 /* 6 * String information interpretation 7 * 8 * The string part of a stab entry is broken up into name and type information. 9 */ 10 11 #include "defs.h" 12 #include "stabstring.h" 13 #include "object.h" 14 #include "main.h" 15 #include "symbols.h" 16 #include "names.h" 17 #include "languages.h" 18 #include <a.out.h> 19 #include <ctype.h> 20 21 #ifndef public 22 #endif 23 24 /* 25 * Special characters in symbol table information. 26 */ 27 28 #define TYPENAME 't' 29 #define TAGNAME 'T' 30 #define MODULEBEGIN 'm' 31 #define EXTPROCEDURE 'P' 32 #define PRIVPROCEDURE 'Q' 33 #define INTPROCEDURE 'I' 34 #define EXTFUNCTION 'F' 35 #define PRIVFUNCTION 'f' 36 #define INTFUNCTION 'J' 37 #define EXTVAR 'G' 38 #define MODULEVAR 'S' 39 #define OWNVAR 'V' 40 #define REGVAR 'r' 41 #define VALUEPARAM 'p' 42 #define VARIABLEPARAM 'v' 43 #define LOCALVAR /* default */ 44 45 /* 46 * Type information special characters. 47 */ 48 49 #define T_SUBRANGE 'r' 50 #define T_ARRAY 'a' 51 #define T_OPENARRAY 'A' 52 #define T_RECORD 's' 53 #define T_UNION 'u' 54 #define T_ENUM 'e' 55 #define T_PTR '*' 56 #define T_FUNCVAR 'f' 57 #define T_PROCVAR 'p' 58 #define T_IMPORTED 'i' 59 #define T_SET 'S' 60 #define T_OPAQUE 'o' 61 62 /* 63 * Table of types indexed by per-file unique identification number. 64 */ 65 66 #define NTYPES 1000 67 68 private Symbol typetable[NTYPES]; 69 70 public initTypeTable () 71 { 72 bzero(typetable, sizeof(typetable)); 73 (*language_op(curlang, L_MODINIT))(typetable); 74 } 75 76 /* 77 * Put an nlist entry into the symbol table. 78 * If it's already there just add the associated information. 79 * 80 * Type information is encoded in the name following a ":". 81 */ 82 83 private Symbol constype(); 84 private Char *curchar; 85 86 #define skipchar(ptr, ch) \ 87 { \ 88 if (*ptr != ch) { \ 89 panic("expected char '%c', found '%s'", ch, ptr); \ 90 } \ 91 ++ptr; \ 92 } 93 94 #define optchar(ptr, ch) \ 95 { \ 96 if (*ptr == ch) { \ 97 ++ptr; \ 98 } \ 99 } 100 101 #define chkcont(ptr) \ 102 { \ 103 if (*ptr == '?') { \ 104 ptr = getcont(); \ 105 } \ 106 } 107 108 #define newSym(s, n) \ 109 { \ 110 s = insert(n); \ 111 s->level = curblock->level + 1; \ 112 s->language = curlang; \ 113 s->block = curblock; \ 114 } 115 116 #define makeVariable(s, n, off) \ 117 { \ 118 newSym(s, n); \ 119 s->class = VAR; \ 120 s->symvalue.offset = off; \ 121 getType(s); \ 122 } 123 124 #define makeParameter(s, n, cl, off) \ 125 { \ 126 newSym(s, n); \ 127 s->class = cl; \ 128 s->symvalue.offset = off; \ 129 curparam->chain = s; \ 130 curparam = s; \ 131 getType(s); \ 132 } 133 134 public entersym (name, np) 135 String name; 136 struct nlist *np; 137 { 138 Symbol s; 139 char *p; 140 register Name n; 141 char c; 142 143 p = index(name, ':'); 144 *p = '\0'; 145 c = *(p+1); 146 n = identname(name, true); 147 chkUnnamedBlock(); 148 curchar = p + 2; 149 switch (c) { 150 case TYPENAME: 151 newSym(s, n); 152 typeName(s); 153 break; 154 155 case TAGNAME: 156 newSym(s, n); 157 tagName(s); 158 break; 159 160 case MODULEBEGIN: 161 newSym(s, n); 162 publicRoutine(s, MODULE, np->n_value); 163 curmodule = s; 164 break; 165 166 case EXTPROCEDURE: 167 newSym(s, n); 168 publicRoutine(s, PROC, np->n_value); 169 break; 170 171 case PRIVPROCEDURE: 172 privateRoutine(&s, n, PROC, np->n_value); 173 break; 174 175 case INTPROCEDURE: 176 newSym(s, n); 177 markInternal(s); 178 publicRoutine(s, PROC, np->n_value); 179 break; 180 181 case EXTFUNCTION: 182 newSym(s, n); 183 publicRoutine(s, FUNC, np->n_value); 184 break; 185 186 case PRIVFUNCTION: 187 privateRoutine(&s, n, FUNC, np->n_value); 188 break; 189 190 case INTFUNCTION: 191 newSym(s, n); 192 markInternal(s); 193 publicRoutine(s, FUNC, np->n_value); 194 break; 195 196 case EXTVAR: 197 find(s, n) where 198 s->level == program->level and s->class == VAR 199 endfind(s); 200 if (s == nil) { 201 makeVariable(s, n, np->n_value); 202 s->level = program->level; 203 s->block = program; 204 getExtRef(s); 205 } 206 break; 207 208 case MODULEVAR: 209 if (curblock->class != MODULE) { 210 exitblock(); 211 } 212 makeVariable(s, n, np->n_value); 213 s->level = program->level; 214 s->block = curmodule; 215 getExtRef(s); 216 break; 217 218 case OWNVAR: 219 makeVariable(s, n, np->n_value); 220 ownVariable(s, np->n_value); 221 getExtRef(s); 222 break; 223 224 case REGVAR: 225 makeVariable(s, n, np->n_value); 226 s->level = -(s->level); 227 break; 228 229 case VALUEPARAM: 230 makeParameter(s, n, VAR, np->n_value); 231 break; 232 233 case VARIABLEPARAM: 234 makeParameter(s, n, REF, np->n_value); 235 break; 236 237 default: /* local variable */ 238 --curchar; 239 makeVariable(s, n, np->n_value); 240 break; 241 } 242 if (tracesyms) { 243 printdecl(s); 244 fflush(stdout); 245 } 246 } 247 248 /* 249 * Enter a type name. 250 */ 251 252 private typeName (s) 253 Symbol s; 254 { 255 register integer i; 256 257 s->class = TYPE; 258 s->language = curlang; 259 s->block = curblock; 260 s->level = curblock->level + 1; 261 i = getint(); 262 if (i == 0) { 263 panic("bad input on type \"%s\" at \"%s\"", symname(s), curchar); 264 } else if (i >= NTYPES) { 265 panic("too many types in file \"%s\"", curfilename()); 266 } 267 /* 268 * A hack for C typedefs that don't create new types, 269 * e.g. typedef unsigned int Hashvalue; 270 * or typedef struct blah BLAH; 271 */ 272 if (*curchar != '=') { 273 s->type = typetable[i]; 274 if (s->type == nil) { 275 s->type = symbol_alloc(); 276 typetable[i] = s->type; 277 } 278 } else { 279 if (typetable[i] != nil) { 280 typetable[i]->language = curlang; 281 typetable[i]->class = TYPE; 282 typetable[i]->type = s; 283 } else { 284 typetable[i] = s; 285 } 286 skipchar(curchar, '='); 287 getType(s); 288 } 289 } 290 291 /* 292 * Enter a tag name. 293 */ 294 295 private tagName (s) 296 Symbol s; 297 { 298 register integer i; 299 300 s->class = TAG; 301 i = getint(); 302 if (i == 0) { 303 panic("bad input on tag \"%s\" at \"%s\"", symname(s), curchar); 304 } else if (i >= NTYPES) { 305 panic("too many types in file \"%s\"", curfilename()); 306 } 307 if (typetable[i] != nil) { 308 typetable[i]->language = curlang; 309 typetable[i]->class = TYPE; 310 typetable[i]->type = s; 311 } else { 312 typetable[i] = s; 313 } 314 skipchar(curchar, '='); 315 getType(s); 316 } 317 318 /* 319 * Setup a symbol entry for a public procedure or function. 320 */ 321 322 private publicRoutine (s, class, addr) 323 Symbol s; 324 Symclass class; 325 Address addr; 326 { 327 enterRoutine(s, class); 328 s->level = program->level; 329 } 330 331 /* 332 * Setup a symbol entry for a private procedure or function. 333 */ 334 335 private privateRoutine (s, n, class, addr) 336 Symbol *s; 337 Name n; 338 Symclass class; 339 Address addr; 340 { 341 Symbol t; 342 boolean isnew; 343 344 find(t, n) where 345 t->level == curmodule->level and t->class == class 346 endfind(t); 347 if (t == nil) { 348 isnew = true; 349 t = insert(n); 350 } else { 351 isnew = false; 352 } 353 t->language = curlang; 354 enterRoutine(t, class); 355 if (isnew) { 356 t->symvalue.funcv.src = false; 357 t->symvalue.funcv.inline = false; 358 t->symvalue.funcv.beginaddr = addr; 359 newfunc(t, codeloc(t)); 360 findbeginning(t); 361 } 362 *s = t; 363 } 364 365 /* 366 * Set up for beginning a new procedure, function, or module. 367 * If it's a function, then read the type. 368 * 369 * If the next character is a ",", then read the name of the enclosing block. 370 * Otherwise assume the previous function, if any, is over, and the current 371 * routine is at the same level. 372 */ 373 374 private enterRoutine (s, class) 375 Symbol s; 376 Symclass class; 377 { 378 s->class = class; 379 if (class == FUNC) { 380 getType(s); 381 } 382 if (s->class != MODULE) { 383 getExtRef(s); 384 } else if (*curchar == ',') { 385 ++curchar; 386 } 387 if (*curchar != '\0') { 388 exitblock(); 389 enterNestedBlock(s); 390 } else { 391 if (curblock->class == FUNC or curblock->class == PROC) { 392 exitblock(); 393 } 394 if (class == MODULE) { 395 exitblock(); 396 } 397 enterblock(s); 398 } 399 curparam = s; 400 } 401 402 /* 403 * Check to see if the stab string contains the name of the external 404 * reference. If so, we create a symbol with that name and class EXTREF, and 405 * connect it to the given symbol. This link is created so that when 406 * we see the linker symbol we can resolve it to the given symbol. 407 */ 408 409 private getExtRef (s) 410 Symbol s; 411 { 412 char *p; 413 Name n; 414 Symbol t; 415 416 if (*curchar == ',' and *(curchar + 1) != '\0') { 417 p = index(curchar + 1, ','); 418 *curchar = '\0'; 419 if (p != nil) { 420 *p = '\0'; 421 n = identname(curchar + 1, false); 422 curchar = p + 1; 423 } else { 424 n = identname(curchar + 1, true); 425 } 426 t = insert(n); 427 t->language = s->language; 428 t->class = EXTREF; 429 t->block = program; 430 t->level = program->level; 431 t->symvalue.extref = s; 432 } 433 } 434 435 /* 436 * Find a block with the given identifier in the given outer block. 437 * If not there, then create it. 438 */ 439 440 private Symbol findBlock (id, m) 441 String id; 442 Symbol m; 443 { 444 Name n; 445 Symbol s; 446 447 n = identname(id, true); 448 find(s, n) where s->block == m and isblock(s) endfind(s); 449 if (s == nil) { 450 s = insert(n); 451 s->block = m; 452 s->language = curlang; 453 s->class = MODULE; 454 s->level = m->level + 1; 455 } 456 return s; 457 } 458 459 /* 460 * Enter a nested block. 461 * The block within which it is nested is described 462 * by "module{:module}[:proc]". 463 */ 464 465 private enterNestedBlock (b) 466 Symbol b; 467 { 468 register char *p, *q; 469 Symbol m, s; 470 Name n; 471 472 q = curchar; 473 p = index(q, ':'); 474 m = program; 475 while (p != nil) { 476 *p = '\0'; 477 m = findBlock(q, m); 478 q = p + 1; 479 p = index(q, ':'); 480 } 481 if (*q != '\0') { 482 m = findBlock(q, m); 483 } 484 b->level = m->level + 1; 485 b->block = m; 486 pushBlock(b); 487 } 488 489 /* 490 * Enter a statically-allocated variable defined within a routine. 491 * 492 * Global BSS variables are chained together so we can resolve them 493 * when the start of common is determined. The list is kept in order 494 * so that f77 can display all vars in a COMMON. 495 */ 496 497 private ownVariable (s, addr) 498 Symbol s; 499 Address addr; 500 { 501 s->level = 1; 502 if (curcomm) { 503 if (commchain != nil) { 504 commchain->symvalue.common.chain = s; 505 } else { 506 curcomm->symvalue.common.offset = (integer) s; 507 } 508 commchain = s; 509 s->symvalue.common.offset = addr; 510 s->symvalue.common.chain = nil; 511 } 512 } 513 514 /* 515 * Get a type from the current stab string for the given symbol. 516 */ 517 518 private getType (s) 519 Symbol s; 520 { 521 s->type = constype(nil); 522 if (s->class == TAG) { 523 addtag(s); 524 } 525 } 526 527 /* 528 * Construct a type out of a string encoding. 529 * 530 * The forms of the string are 531 * 532 * <number> 533 * <number>=<type> 534 * r<type>;<number>;<number> -- subrange 535 * a<type>;<type> -- array[index] of element 536 * A<type> -- open array 537 * s<size>{<name>:<type>;<number>;<number>}-- record 538 * u<size>{<name>:<type>;<number>;<number>}-- union 539 * *<type> -- pointer 540 * f<type>,<integer>;<paramlist> -- function variable 541 * p<integer>;<paramlist> -- procedure variable 542 * S<type> -- set of type 543 * o<name>[,<type>] -- opaque type 544 * i<name>,<type> -- imported type 545 */ 546 547 private Rangetype getRangeBoundType(); 548 549 private Symbol constype (type) 550 Symbol type; 551 { 552 register Symbol t; 553 register integer n; 554 char class; 555 556 if (isdigit(*curchar)) { 557 n = getint(); 558 if (n >= NTYPES) { 559 panic("too many types in file \"%s\"", curfilename()); 560 } 561 if (*curchar == '=') { 562 if (typetable[n] != nil) { 563 t = typetable[n]; 564 } else { 565 t = symbol_alloc(); 566 typetable[n] = t; 567 } 568 ++curchar; 569 constype(t); 570 } else { 571 t = typetable[n]; 572 if (t == nil) { 573 t = symbol_alloc(); 574 typetable[n] = t; 575 } 576 } 577 } else { 578 if (type == nil) { 579 t = symbol_alloc(); 580 } else { 581 t = type; 582 } 583 t->language = curlang; 584 t->level = curblock->level + 1; 585 t->block = curblock; 586 class = *curchar++; 587 switch (class) { 588 case T_SUBRANGE: 589 consSubrange(t); 590 break; 591 592 case T_ARRAY: 593 t->class = ARRAY; 594 t->chain = constype(nil); 595 skipchar(curchar, ';'); 596 chkcont(curchar); 597 t->type = constype(nil); 598 break; 599 600 case T_OPENARRAY: 601 t->class = ARRAY; 602 t->chain = t_open; 603 t->type = constype(nil); 604 break; 605 606 case T_RECORD: 607 consRecord(t, RECORD); 608 break; 609 610 case T_UNION: 611 consRecord(t, VARNT); 612 break; 613 614 case T_ENUM: 615 consEnum(t); 616 break; 617 618 case T_PTR: 619 t->class = PTR; 620 t->type = constype(nil); 621 break; 622 623 /* 624 * C function variables are different from Modula-2's. 625 */ 626 case T_FUNCVAR: 627 t->class = FFUNC; 628 t->type = constype(nil); 629 if (not streq(language_name(curlang), "c")) { 630 skipchar(curchar, ','); 631 consParamlist(t); 632 } 633 break; 634 635 case T_PROCVAR: 636 t->class = FPROC; 637 consParamlist(t); 638 break; 639 640 case T_IMPORTED: 641 consImpType(t); 642 break; 643 644 case T_SET: 645 t->class = SET; 646 t->type = constype(nil); 647 break; 648 649 case T_OPAQUE: 650 consOpaqType(t); 651 break; 652 653 default: 654 badcaseval(class); 655 } 656 } 657 return t; 658 } 659 660 /* 661 * Construct a subrange type. 662 */ 663 664 private consSubrange (t) 665 Symbol t; 666 { 667 t->class = RANGE; 668 t->type = constype(nil); 669 skipchar(curchar, ';'); 670 chkcont(curchar); 671 t->symvalue.rangev.lowertype = getRangeBoundType(); 672 t->symvalue.rangev.lower = getint(); 673 skipchar(curchar, ';'); 674 chkcont(curchar); 675 t->symvalue.rangev.uppertype = getRangeBoundType(); 676 t->symvalue.rangev.upper = getint(); 677 } 678 679 /* 680 * Figure out the bound type of a range. 681 * 682 * Some letters indicate a dynamic bound, ie what follows 683 * is the offset from the fp which contains the bound; this will 684 * need a different encoding when pc a['A'..'Z'] is 685 * added; J is a special flag to handle fortran a(*) bounds 686 */ 687 688 private Rangetype getRangeBoundType () 689 { 690 Rangetype r; 691 692 switch (*curchar) { 693 case 'A': 694 r = R_ARG; 695 curchar++; 696 break; 697 698 case 'T': 699 r = R_TEMP; 700 curchar++; 701 break; 702 703 case 'J': 704 r = R_ADJUST; 705 curchar++; 706 break; 707 708 default: 709 r = R_CONST; 710 break; 711 } 712 return r; 713 } 714 715 /* 716 * Construct a record or union type. 717 */ 718 719 private consRecord (t, class) 720 Symbol t; 721 Symclass class; 722 { 723 register Symbol u; 724 register char *cur, *p; 725 Name name; 726 integer d; 727 728 t->class = class; 729 t->symvalue.offset = getint(); 730 d = curblock->level + 1; 731 u = t; 732 cur = curchar; 733 while (*cur != ';' and *cur != '\0') { 734 p = index(cur, ':'); 735 if (p == nil) { 736 panic("index(\"%s\", ':') failed", curchar); 737 } 738 *p = '\0'; 739 name = identname(cur, true); 740 u->chain = newSymbol(name, d, FIELD, nil, nil); 741 cur = p + 1; 742 u = u->chain; 743 u->language = curlang; 744 curchar = cur; 745 u->type = constype(nil); 746 skipchar(curchar, ','); 747 u->symvalue.field.offset = getint(); 748 skipchar(curchar, ','); 749 u->symvalue.field.length = getint(); 750 skipchar(curchar, ';'); 751 chkcont(curchar); 752 cur = curchar; 753 } 754 if (*cur == ';') { 755 ++cur; 756 } 757 curchar = cur; 758 } 759 760 /* 761 * Construct an enumeration type. 762 */ 763 764 private consEnum (t) 765 Symbol t; 766 { 767 register Symbol u; 768 register char *p; 769 register integer count; 770 771 t->class = SCAL; 772 count = 0; 773 u = t; 774 while (*curchar != ';' and *curchar != '\0') { 775 p = index(curchar, ':'); 776 assert(p != nil); 777 *p = '\0'; 778 u->chain = insert(identname(curchar, true)); 779 curchar = p + 1; 780 u = u->chain; 781 u->language = curlang; 782 u->class = CONST; 783 u->level = curblock->level + 1; 784 u->block = curblock; 785 u->type = t; 786 u->symvalue.iconval = getint(); 787 ++count; 788 skipchar(curchar, ','); 789 chkcont(curchar); 790 } 791 if (*curchar == ';') { 792 ++curchar; 793 } 794 t->symvalue.iconval = count; 795 } 796 797 /* 798 * Construct a parameter list for a function or procedure variable. 799 */ 800 801 private consParamlist (t) 802 Symbol t; 803 { 804 Symbol p; 805 integer i, d, n, paramclass; 806 807 n = getint(); 808 skipchar(curchar, ';'); 809 p = t; 810 d = curblock->level + 1; 811 for (i = 0; i < n; i++) { 812 p->chain = newSymbol(nil, d, VAR, nil, nil); 813 p = p->chain; 814 p->type = constype(nil); 815 skipchar(curchar, ','); 816 paramclass = getint(); 817 if (paramclass == 0) { 818 p->class = REF; 819 } 820 skipchar(curchar, ';'); 821 chkcont(curchar); 822 } 823 } 824 825 /* 826 * Construct an imported type. 827 * Add it to a list of symbols to get fixed up. 828 */ 829 830 private consImpType (t) 831 Symbol t; 832 { 833 register char *p; 834 Symbol tmp; 835 836 p = curchar; 837 while (*p != ',' and *p != ';' and *p != '\0') { 838 ++p; 839 } 840 if (*p == '\0') { 841 panic("bad import symbol entry '%s'", curchar); 842 } 843 t->class = TYPEREF; 844 t->symvalue.typeref = curchar; 845 curchar = p + 1; 846 if (*p == ',') { 847 curchar = p + 1; 848 tmp = constype(nil); 849 } 850 skipchar(curchar, ';'); 851 *p = '\0'; 852 } 853 854 /* 855 * Construct an opaque type entry. 856 */ 857 858 private consOpaqType (t) 859 Symbol t; 860 { 861 register char *p; 862 register Symbol s; 863 register Name n; 864 boolean def; 865 866 p = curchar; 867 while (*p != ';' and *p != ',') { 868 if (*p == '\0') { 869 panic("bad opaque symbol entry '%s'", curchar); 870 } 871 ++p; 872 } 873 def = (Boolean) (*p == ','); 874 *p = '\0'; 875 n = identname(curchar, true); 876 find(s, n) where s->class == TYPEREF endfind(s); 877 if (s == nil) { 878 s = insert(n); 879 s->class = TYPEREF; 880 s->type = nil; 881 } 882 curchar = p + 1; 883 if (def) { 884 s->type = constype(nil); 885 skipchar(curchar, ';'); 886 } 887 t->class = TYPE; 888 t->type = s; 889 } 890 891 /* 892 * Read an integer from the current position in the type string. 893 */ 894 895 private integer getint () 896 { 897 register integer n; 898 register char *p; 899 register Boolean isneg; 900 901 n = 0; 902 p = curchar; 903 if (*p == '-') { 904 isneg = true; 905 ++p; 906 } else { 907 isneg = false; 908 } 909 while (isdigit(*p)) { 910 n = 10*n + (*p - '0'); 911 ++p; 912 } 913 curchar = p; 914 return isneg ? (-n) : n; 915 } 916 917 /* 918 * Add a tag name. This is a kludge to be able to refer 919 * to tags that have the same name as some other symbol 920 * in the same block. 921 */ 922 923 private addtag (s) 924 register Symbol s; 925 { 926 register Symbol t; 927 char buf[100]; 928 929 sprintf(buf, "$$%.90s", ident(s->name)); 930 t = insert(identname(buf, false)); 931 t->language = s->language; 932 t->class = TAG; 933 t->type = s->type; 934 t->block = s->block; 935 } 936