1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)stabstring.c 5.6 (Berkeley) 03/05/91"; 10 #endif /* not lint */ 11 12 /* 13 * String information interpretation 14 * 15 * The string part of a stab entry is broken up into name and type information. 16 */ 17 18 #include "defs.h" 19 #include "stabstring.h" 20 #include "object.h" 21 #include "main.h" 22 #include "symbols.h" 23 #include "names.h" 24 #include "languages.h" 25 #include "tree.h" 26 #include <a.out.h> 27 #include <ctype.h> 28 29 #ifndef public 30 #endif 31 32 /* 33 * Special characters in symbol table information. 34 */ 35 36 #define CONSTNAME 'c' 37 #define TYPENAME 't' 38 #define TAGNAME 'T' 39 #define MODULEBEGIN 'm' 40 #define EXTPROCEDURE 'P' 41 #define PRIVPROCEDURE 'Q' 42 #define INTPROCEDURE 'I' 43 #define EXTFUNCTION 'F' 44 #define PRIVFUNCTION 'f' 45 #define INTFUNCTION 'J' 46 #define EXTVAR 'G' 47 #define MODULEVAR 'S' 48 #define OWNVAR 'V' 49 #define REGVAR 'r' 50 #define VALUEPARAM 'p' 51 #define VARIABLEPARAM 'v' 52 #define LOCALVAR /* default */ 53 54 /* 55 * Type information special characters. 56 */ 57 58 #define T_SUBRANGE 'r' 59 #define T_ARRAY 'a' 60 #define T_OLDOPENARRAY 'A' 61 #define T_OPENARRAY 'O' 62 #define T_DYNARRAY 'D' 63 #define T_SUBARRAY 'E' 64 #define T_RECORD 's' 65 #define T_UNION 'u' 66 #define T_ENUM 'e' 67 #define T_PTR '*' 68 #define T_FUNCVAR 'f' 69 #define T_PROCVAR 'p' 70 #define T_IMPORTED 'i' 71 #define T_SET 'S' 72 #define T_OPAQUE 'o' 73 #define T_FILE 'd' 74 75 /* 76 * Table of types indexed by per-file unique identification number. 77 */ 78 79 #define NTYPES 1000 80 81 private Symbol typetable[NTYPES]; 82 83 public initTypeTable () 84 { 85 bzero(typetable, sizeof(typetable)); 86 (*language_op(curlang, L_MODINIT))(typetable); 87 } 88 89 /* 90 * Put an nlist entry into the symbol table. 91 * If it's already there just add the associated information. 92 * 93 * Type information is encoded in the name following a ":". 94 */ 95 96 private Symbol constype(); 97 private Char *curchar; 98 99 #define skipchar(ptr, ch) \ 100 { \ 101 if (*ptr != ch) { \ 102 panic("expected char '%c', found '%s'", ch, ptr); \ 103 } \ 104 ++ptr; \ 105 } 106 107 #define optchar(ptr, ch) \ 108 { \ 109 if (*ptr == ch) { \ 110 ++ptr; \ 111 } \ 112 } 113 114 #ifdef sun 115 # define chkcont(ptr) \ 116 { \ 117 if (*ptr == '\\' or *ptr == '?') { \ 118 ptr = getcont(); \ 119 } \ 120 } 121 #else if notsun 122 # define chkcont(ptr) \ 123 { \ 124 if (*ptr == '?') { \ 125 ptr = getcont(); \ 126 } \ 127 } 128 #endif 129 130 #define newSym(s, n) \ 131 { \ 132 s = insert(n); \ 133 s->level = curblock->level + 1; \ 134 s->language = curlang; \ 135 s->block = curblock; \ 136 } 137 138 #define makeVariable(s, n, off) \ 139 { \ 140 newSym(s, n); \ 141 s->class = VAR; \ 142 s->symvalue.offset = off; \ 143 getType(s); \ 144 } 145 146 #define makeParameter(s, n, cl, off) \ 147 { \ 148 if ((s = lookup(n)) == nil or s->block != curblock) { \ 149 newSym(s, n); \ 150 s->storage = STK; \ 151 s->class = cl; \ 152 s->symvalue.offset = off; \ 153 getType(s); \ 154 } \ 155 curparam->chain = s; \ 156 curparam = s; \ 157 } 158 159 public entersym (name, np) 160 String name; 161 struct nlist *np; 162 { 163 Symbol s; 164 register char *p, *q, *r; 165 register Name n; 166 char c; 167 168 p = index(name, ':'); 169 *p = '\0'; 170 c = *(p+1); 171 if (autostrip and streq(language_name(curlang), "c++")) { 172 /* 173 * Strip off redundant prefixes from C++ names. 174 * Static variables are prefixed with _static_. 175 * Formal arguments of functions are prefixed with _au0_. 176 * Automatic variables are prefixed with _au[1-9][0-9]*_. 177 * Class members are prefixed with _T_, where T is a class tag. 178 */ 179 if (strncmp("_static_", name, 8) == 0 and name[8] != '\0') { 180 name += 8; 181 } 182 q = name; 183 if (*q++ == '_' and *q++ == 'a' and *q++ == 'u' and isdigit(*q++)) { 184 while (isdigit(*q)) 185 ++q; 186 if (*q++ == '_' and *q != '\0') 187 name = q; 188 } 189 q = name; 190 if (*q++ == '_' and c == EXTFUNCTION) { 191 /* 192 * Punt on static class members, for speed. 193 */ 194 for (r = q; (r = index(r, '_')) != nil; ++r) { 195 if (r == q) { 196 continue; 197 } 198 *r = '\0'; 199 s = lookup(identname(q, true)); 200 if (s != nil and s->class == TYPE) { 201 char *newname = r + 1; 202 if (*newname != '\0') { 203 name = newname; 204 break; 205 } 206 } 207 *r = '_'; 208 } 209 } 210 } 211 n = identname(name, true); 212 chkUnnamedBlock(); 213 curchar = p + 2; 214 switch (c) { 215 case CONSTNAME: 216 newSym(s, n); 217 constName(s); 218 break; 219 220 case TYPENAME: 221 newSym(s, n); 222 typeName(s); 223 break; 224 225 case TAGNAME: 226 s = symbol_alloc(); 227 s->name = n; 228 s->level = curblock->level + 1; 229 s->language = curlang; 230 s->block = curblock; 231 tagName(s); 232 break; 233 234 case MODULEBEGIN: 235 publicRoutine(&s, n, MODULE, np->n_value, false); 236 curmodule = s; 237 break; 238 239 case EXTPROCEDURE: 240 publicRoutine(&s, n, PROC, np->n_value, false); 241 break; 242 243 case PRIVPROCEDURE: 244 privateRoutine(&s, n, PROC, np->n_value); 245 break; 246 247 case INTPROCEDURE: 248 publicRoutine(&s, n, PROC, np->n_value, true); 249 break; 250 251 case EXTFUNCTION: 252 publicRoutine(&s, n, FUNC, np->n_value, false); 253 break; 254 255 case PRIVFUNCTION: 256 privateRoutine(&s, n, FUNC, np->n_value); 257 break; 258 259 case INTFUNCTION: 260 publicRoutine(&s, n, FUNC, np->n_value, true); 261 break; 262 263 case EXTVAR: 264 extVar(&s, n, np->n_value); 265 break; 266 267 case MODULEVAR: 268 if (curblock->class != MODULE) { 269 exitblock(); 270 } 271 makeVariable(s, n, np->n_value); 272 s->storage = EXT; 273 s->level = program->level; 274 s->block = curmodule; 275 getExtRef(s); 276 break; 277 278 case OWNVAR: 279 makeVariable(s, n, np->n_value); 280 ownVariable(s, np->n_value); 281 getExtRef(s); 282 break; 283 284 case REGVAR: 285 makeVariable(s, n, np->n_value); 286 s->storage = INREG; 287 break; 288 289 case VALUEPARAM: 290 makeParameter(s, n, VAR, np->n_value); 291 # ifdef IRIS 292 /* 293 * Bug in SGI C compiler -- generates stab offset 294 * for parameters with size added in. 295 */ 296 if (s->storage == STK and curlang == findlanguage(".c")) { 297 s->symvalue.offset -= size(s); 298 } 299 # endif 300 break; 301 302 case VARIABLEPARAM: 303 makeParameter(s, n, REF, np->n_value); 304 break; 305 306 default: /* local variable */ 307 --curchar; 308 makeVariable(s, n, np->n_value); 309 s->storage = STK; 310 break; 311 } 312 if (tracesyms) { 313 printdecl(s); 314 fflush(stdout); 315 } 316 } 317 318 /* 319 * Enter a named constant. 320 */ 321 322 private constName (s) 323 Symbol s; 324 { 325 integer i; 326 double d; 327 char *p, buf[1000]; 328 329 s->class = CONST; 330 skipchar(curchar, '='); 331 p = curchar; 332 ++curchar; 333 switch (*p) { 334 case 'b': 335 s->type = t_boolean; 336 s->symvalue.constval = build(O_LCON, getint()); 337 break; 338 339 case 'c': 340 s->type = t_char; 341 s->symvalue.constval = build(O_LCON, getint()); 342 break; 343 344 case 'i': 345 s->type = t_int; 346 s->symvalue.constval = build(O_LCON, getint()); 347 break; 348 349 case 'r': 350 sscanf(curchar, "%lf", &d); 351 while (*curchar != '\0' and *curchar != ';') { 352 ++curchar; 353 } 354 --curchar; 355 s->type = t_real; 356 s->symvalue.constval = build(O_FCON, d); 357 break; 358 359 case 's': 360 p = &buf[0]; 361 skipchar(curchar, '\''); 362 while (*curchar != '\'') { 363 *p = *curchar; 364 ++p; 365 ++curchar; 366 } 367 *p = '\0'; 368 s->symvalue.constval = build(O_SCON, strdup(buf)); 369 s->type = s->symvalue.constval->nodetype; 370 break; 371 372 case 'e': 373 getType(s); 374 skipchar(curchar, ','); 375 s->symvalue.constval = build(O_LCON, getint()); 376 break; 377 378 case 'S': 379 getType(s); 380 skipchar(curchar, ','); 381 i = getint(); /* set size */ 382 skipchar(curchar, ','); 383 i = getint(); /* number of bits in constant */ 384 s->symvalue.constval = build(O_LCON, 0); 385 break; 386 387 default: 388 s->type = t_int; 389 s->symvalue.constval = build(O_LCON, 0); 390 printf("[internal error: unknown constant type '%c']", *p); 391 break; 392 } 393 s->symvalue.constval->nodetype = s->type; 394 } 395 396 /* 397 * Enter a type name. 398 */ 399 400 private typeName (s) 401 Symbol s; 402 { 403 register integer i; 404 405 s->class = TYPE; 406 s->language = curlang; 407 s->block = curblock; 408 s->level = curblock->level + 1; 409 i = getint(); 410 if (i == 0) { 411 panic("bad input on type \"%s\" at \"%s\"", symname(s), curchar); 412 } else if (i >= NTYPES) { 413 panic("too many types in file \"%s\"", curfilename()); 414 } 415 /* 416 * A hack for C typedefs that don't create new types, 417 * e.g. typedef unsigned int Hashvalue; 418 * or typedef struct blah BLAH; 419 */ 420 if (*curchar != '=') { 421 s->type = typetable[i]; 422 if (s->type == nil) { 423 s->type = symbol_alloc(); 424 typetable[i] = s->type; 425 } 426 } else { 427 if (typetable[i] != nil) { 428 typetable[i]->language = curlang; 429 typetable[i]->class = TYPE; 430 typetable[i]->type = s; 431 } else { 432 typetable[i] = s; 433 } 434 skipchar(curchar, '='); 435 getType(s); 436 } 437 } 438 439 /* 440 * Enter a tag name. 441 */ 442 443 private tagName (s) 444 Symbol s; 445 { 446 register integer i; 447 448 s->class = TAG; 449 i = getint(); 450 if (i == 0) { 451 panic("bad input on tag \"%s\" at \"%s\"", symname(s), curchar); 452 } else if (i >= NTYPES) { 453 panic("too many types in file \"%s\"", curfilename()); 454 } 455 if (typetable[i] != nil) { 456 typetable[i]->language = curlang; 457 typetable[i]->class = TYPE; 458 typetable[i]->type = s; 459 } else { 460 typetable[i] = s; 461 } 462 skipchar(curchar, '='); 463 getType(s); 464 } 465 466 /* 467 * Setup a symbol entry for a public procedure or function. 468 * 469 * If it contains nested procedures, then it may already be defined 470 * in the current block as a MODULE. 471 */ 472 473 private publicRoutine (s, n, class, addr, isinternal) 474 Symbol *s; 475 Name n; 476 Symclass class; 477 Address addr; 478 boolean isinternal; 479 { 480 Symbol nt, t; 481 482 newSym(nt, n); 483 if (isinternal) { 484 markInternal(nt); 485 } 486 enterRoutine(nt, class); 487 find(t, n) where 488 t != nt and t->class == MODULE and t->block == nt->block 489 endfind(t); 490 if (t == nil) { 491 t = nt; 492 } else { 493 t->language = nt->language; 494 t->class = nt->class; 495 t->type = nt->type; 496 t->chain = nt->chain; 497 t->symvalue = nt->symvalue; 498 nt->class = EXTREF; 499 nt->symvalue.extref = t; 500 delete(nt); 501 curparam = t; 502 changeBlock(t); 503 } 504 if (t->block == program) { 505 t->level = program->level; 506 } else if (t->class == MODULE) { 507 t->level = t->block->level; 508 } else if (t->block->class == MODULE) { 509 t->level = t->block->block->level; 510 } else { 511 t->level = t->block->level + 1; 512 } 513 *s = t; 514 } 515 516 /* 517 * Setup a symbol entry for a private procedure or function. 518 */ 519 520 private privateRoutine (s, n, class, addr) 521 Symbol *s; 522 Name n; 523 Symclass class; 524 Address addr; 525 { 526 Symbol t; 527 boolean isnew; 528 529 find(t, n) where 530 t->level == curmodule->level and t->class == class 531 endfind(t); 532 if (t == nil) { 533 isnew = true; 534 t = insert(n); 535 } else { 536 isnew = false; 537 } 538 t->language = curlang; 539 enterRoutine(t, class); 540 if (isnew) { 541 t->symvalue.funcv.src = false; 542 t->symvalue.funcv.inlne = false; 543 t->symvalue.funcv.beginaddr = addr; 544 newfunc(t, codeloc(t)); 545 findbeginning(t); 546 } 547 *s = t; 548 } 549 550 /* 551 * Set up for beginning a new procedure, function, or module. 552 * If it's a function, then read the type. 553 * 554 * If the next character is a ",", then read the name of the enclosing block. 555 * Otherwise assume the previous function, if any, is over, and the current 556 * routine is at the same level. 557 */ 558 559 private enterRoutine (s, class) 560 Symbol s; 561 Symclass class; 562 { 563 s->class = class; 564 if (class == FUNC) { 565 getType(s); 566 } 567 if (s->class != MODULE) { 568 getExtRef(s); 569 } else if (*curchar == ',') { 570 ++curchar; 571 } 572 if (*curchar != '\0') { 573 exitblock(); 574 enterNestedBlock(s); 575 } else { 576 if (curblock->class == FUNC or curblock->class == PROC) { 577 exitblock(); 578 } 579 if (class == MODULE) { 580 exitblock(); 581 } 582 enterblock(s); 583 } 584 curparam = s; 585 } 586 587 /* 588 * Handling an external variable is tricky, since we might already 589 * know it but need to define it's type for other type information 590 * in the file. So just in case we read the type information anyway. 591 */ 592 593 private extVar (symp, n, off) 594 Symbol *symp; 595 Name n; 596 integer off; 597 { 598 Symbol s, t; 599 600 find(s, n) where 601 s->level == program->level and s->class == VAR 602 endfind(s); 603 if (s == nil) { 604 makeVariable(s, n, off); 605 s->storage = EXT; 606 s->level = program->level; 607 s->block = curmodule; 608 getExtRef(s); 609 } else { 610 t = constype(nil); 611 } 612 *symp = s; 613 } 614 615 /* 616 * Check to see if the stab string contains the name of the external 617 * reference. If so, we create a symbol with that name and class EXTREF, and 618 * connect it to the given symbol. This link is created so that when 619 * we see the linker symbol we can resolve it to the given symbol. 620 */ 621 622 private getExtRef (s) 623 Symbol s; 624 { 625 char *p; 626 Name n; 627 Symbol t; 628 629 if (*curchar == ',' and *(curchar + 1) != '\0') { 630 p = index(curchar + 1, ','); 631 *curchar = '\0'; 632 if (p != nil) { 633 *p = '\0'; 634 n = identname(curchar + 1, false); 635 curchar = p + 1; 636 } else { 637 n = identname(curchar + 1, true); 638 } 639 t = insert(n); 640 t->language = s->language; 641 t->class = EXTREF; 642 t->block = program; 643 t->level = program->level; 644 t->symvalue.extref = s; 645 } 646 } 647 648 /* 649 * Find a block with the given identifier in the given outer block. 650 * If not there, then create it. 651 */ 652 653 private Symbol findBlock (id, m) 654 String id; 655 Symbol m; 656 { 657 Name n; 658 Symbol s; 659 660 n = identname(id, true); 661 find(s, n) where s->block == m and isblock(s) endfind(s); 662 if (s == nil) { 663 s = insert(n); 664 s->block = m; 665 s->language = curlang; 666 s->class = MODULE; 667 s->level = m->level + 1; 668 } 669 return s; 670 } 671 672 /* 673 * Enter a nested block. 674 * The block within which it is nested is described 675 * by "module{:module}[:proc]". 676 */ 677 678 private enterNestedBlock (b) 679 Symbol b; 680 { 681 register char *p, *q; 682 Symbol m, s; 683 Name n; 684 685 q = curchar; 686 p = index(q, ':'); 687 m = program; 688 while (p != nil) { 689 *p = '\0'; 690 m = findBlock(q, m); 691 q = p + 1; 692 p = index(q, ':'); 693 } 694 if (*q != '\0') { 695 m = findBlock(q, m); 696 } 697 b->level = m->level + 1; 698 b->block = m; 699 pushBlock(b); 700 } 701 702 /* 703 * Enter a statically-allocated variable defined within a routine. 704 * 705 * Global BSS variables are chained together so we can resolve them 706 * when the start of common is determined. The list is kept in order 707 * so that f77 can display all vars in a COMMON. 708 */ 709 710 private ownVariable (s, addr) 711 Symbol s; 712 Address addr; 713 { 714 s->storage = EXT; 715 /* s->level = 1; */ 716 if (curcomm) { 717 if (commchain != nil) { 718 commchain->symvalue.common.chain = s; 719 } else { 720 curcomm->symvalue.common.offset = (integer) s; 721 } 722 commchain = s; 723 s->symvalue.common.offset = addr; 724 s->symvalue.common.chain = nil; 725 } 726 } 727 728 /* 729 * Get a type from the current stab string for the given symbol. 730 */ 731 732 private getType (s) 733 Symbol s; 734 { 735 Symbol t, addtag(); 736 737 if (s->class == TAG) { 738 t = addtag(s); 739 t->type = constype(nil); 740 s->type = t->type; 741 } else { 742 s->type = constype(nil); 743 } 744 } 745 746 /* 747 * Construct a type out of a string encoding. 748 */ 749 750 private Rangetype getRangeBoundType(); 751 752 private Symbol constype (type) 753 Symbol type; 754 { 755 register Symbol t; 756 register integer n; 757 char class; 758 char *p; 759 760 while (*curchar == '@') { 761 p = index(curchar, ';'); 762 if (p == nil) { 763 fflush(stdout); 764 fprintf(stderr, "missing ';' after type attributes"); 765 } else { 766 curchar = p + 1; 767 } 768 } 769 if (isdigit(*curchar)) { 770 n = getint(); 771 if (n >= NTYPES) { 772 panic("too many types in file \"%s\"", curfilename()); 773 } 774 if (*curchar == '=') { 775 if (typetable[n] != nil) { 776 t = typetable[n]; 777 } else { 778 t = symbol_alloc(); 779 typetable[n] = t; 780 } 781 ++curchar; 782 constype(t); 783 } else { 784 t = typetable[n]; 785 if (t == nil) { 786 t = symbol_alloc(); 787 typetable[n] = t; 788 } 789 } 790 } else { 791 if (type == nil) { 792 t = symbol_alloc(); 793 } else { 794 t = type; 795 } 796 t->language = curlang; 797 t->level = curblock->level + 1; 798 t->block = curblock; 799 class = *curchar++; 800 switch (class) { 801 case T_SUBRANGE: 802 consSubrange(t); 803 break; 804 805 case T_ARRAY: 806 t->class = ARRAY; 807 t->chain = constype(nil); 808 skipchar(curchar, ';'); 809 chkcont(curchar); 810 t->type = constype(nil); 811 break; 812 813 case T_OLDOPENARRAY: 814 t->class = DYNARRAY; 815 t->symvalue.ndims = 1; 816 t->type = constype(nil); 817 t->chain = t_int; 818 break; 819 820 case T_OPENARRAY: 821 consDynarray(t, OPENARRAY); 822 break; 823 824 case T_DYNARRAY: 825 consDynarray(t, DYNARRAY); 826 break; 827 828 case T_SUBARRAY: 829 t->class = SUBARRAY; 830 t->symvalue.ndims = getint(); 831 skipchar(curchar, ','); 832 t->type = constype(nil); 833 t->chain = t_int; 834 break; 835 836 case T_RECORD: 837 consRecord(t, RECORD); 838 break; 839 840 case T_UNION: 841 consRecord(t, VARNT); 842 break; 843 844 case T_ENUM: 845 consEnum(t); 846 break; 847 848 case T_PTR: 849 t->class = PTR; 850 t->type = constype(nil); 851 break; 852 853 /* 854 * C function variables are different from Modula-2's. 855 */ 856 case T_FUNCVAR: 857 t->class = FFUNC; 858 t->type = constype(nil); 859 if (streq(language_name(curlang), "modula-2")) { 860 skipchar(curchar, ','); 861 consParamlist(t); 862 } 863 break; 864 865 case T_PROCVAR: 866 t->class = FPROC; 867 consParamlist(t); 868 break; 869 870 case T_IMPORTED: 871 consImpType(t); 872 break; 873 874 case T_SET: 875 t->class = SET; 876 t->type = constype(nil); 877 break; 878 879 case T_OPAQUE: 880 consOpaqType(t); 881 break; 882 883 case T_FILE: 884 t->class = FILET; 885 t->type = constype(nil); 886 break; 887 888 default: 889 badcaseval(class); 890 } 891 } 892 return t; 893 } 894 895 /* 896 * Construct a subrange type. 897 */ 898 899 private consSubrange (t) 900 Symbol t; 901 { 902 t->class = RANGE; 903 t->type = constype(nil); 904 skipchar(curchar, ';'); 905 chkcont(curchar); 906 t->symvalue.rangev.lowertype = getRangeBoundType(); 907 t->symvalue.rangev.lower = getint(); 908 skipchar(curchar, ';'); 909 chkcont(curchar); 910 t->symvalue.rangev.uppertype = getRangeBoundType(); 911 t->symvalue.rangev.upper = getint(); 912 } 913 914 /* 915 * Figure out the bound type of a range. 916 * 917 * Some letters indicate a dynamic bound, ie what follows 918 * is the offset from the fp which contains the bound; this will 919 * need a different encoding when pc a['A'..'Z'] is 920 * added; J is a special flag to handle fortran a(*) bounds 921 */ 922 923 private Rangetype getRangeBoundType () 924 { 925 Rangetype r; 926 927 switch (*curchar) { 928 case 'A': 929 r = R_ARG; 930 curchar++; 931 break; 932 933 case 'T': 934 r = R_TEMP; 935 curchar++; 936 break; 937 938 case 'J': 939 r = R_ADJUST; 940 curchar++; 941 break; 942 943 default: 944 r = R_CONST; 945 break; 946 } 947 return r; 948 } 949 950 /* 951 * Construct a dynamic array descriptor. 952 */ 953 954 private consDynarray (t, c) 955 register Symbol t; 956 Symclass c; 957 { 958 t->class = c; 959 t->symvalue.ndims = getint(); 960 skipchar(curchar, ','); 961 t->type = constype(nil); 962 t->chain = t_int; 963 } 964 965 /* 966 * Construct a record or union type. 967 */ 968 969 private consRecord (t, class) 970 Symbol t; 971 Symclass class; 972 { 973 register Symbol u; 974 register char *cur, *p; 975 Name name; 976 integer d; 977 978 t->class = class; 979 t->symvalue.offset = getint(); 980 d = curblock->level + 1; 981 u = t; 982 chkcont(curchar); 983 cur = curchar; 984 while (*cur != ';' and *cur != '\0') { 985 p = index(cur, ':'); 986 if (p == nil) { 987 panic("index(\"%s\", ':') failed", curchar); 988 } 989 *p = '\0'; 990 if ( 991 autostrip and 992 *cur == '_' and 993 streq(language_name(curlang), "c++") 994 ) { 995 /* 996 * Strip off redundant prefixes from C++ names. 997 * Class members are prefixed with _T_, where T is a class tag. 998 */ 999 register char *q, *r; 1000 Symbol s; 1001 1002 /* 1003 * The slow way... Check for members defined in the base class. 1004 */ 1005 for (q = cur + 1, r = q; (r = index(r, '_')) != nil; ++r) { 1006 if (r == q) { 1007 continue; 1008 } 1009 *r = '\0'; 1010 s = lookup(identname(q, true)); 1011 if (s != nil and s->class == TYPE) { 1012 char *newcur = r + 1; 1013 if (*newcur != '\0') { 1014 cur = newcur; 1015 break; 1016 } 1017 } 1018 *r = '_'; 1019 } 1020 } 1021 name = identname(cur, true); 1022 u->chain = newSymbol(name, d, FIELD, nil, nil); 1023 cur = p + 1; 1024 u = u->chain; 1025 u->language = curlang; 1026 curchar = cur; 1027 u->type = constype(nil); 1028 skipchar(curchar, ','); 1029 u->symvalue.field.offset = getint(); 1030 skipchar(curchar, ','); 1031 u->symvalue.field.length = getint(); 1032 skipchar(curchar, ';'); 1033 chkcont(curchar); 1034 cur = curchar; 1035 } 1036 if (*cur == ';') { 1037 ++cur; 1038 } 1039 curchar = cur; 1040 } 1041 1042 /* 1043 * Construct an enumeration type. 1044 */ 1045 1046 private consEnum (t) 1047 Symbol t; 1048 { 1049 register Symbol u; 1050 register char *p; 1051 register integer count; 1052 1053 t->class = SCAL; 1054 count = 0; 1055 u = t; 1056 while (*curchar != ';' and *curchar != '\0' and *curchar != ',') { 1057 p = index(curchar, ':'); 1058 assert(p != nil); 1059 *p = '\0'; 1060 u->chain = insert(identname(curchar, true)); 1061 curchar = p + 1; 1062 u = u->chain; 1063 u->language = curlang; 1064 u->class = CONST; 1065 u->level = curblock->level + 1; 1066 u->block = curblock; 1067 u->type = t; 1068 u->symvalue.constval = build(O_LCON, (long) getint()); 1069 ++count; 1070 skipchar(curchar, ','); 1071 chkcont(curchar); 1072 } 1073 if (*curchar == ';') { 1074 ++curchar; 1075 } 1076 t->symvalue.iconval = count; 1077 } 1078 1079 /* 1080 * Construct a parameter list for a function or procedure variable. 1081 */ 1082 1083 private consParamlist (t) 1084 Symbol t; 1085 { 1086 Symbol p; 1087 integer i, d, n, paramclass; 1088 1089 n = getint(); 1090 skipchar(curchar, ';'); 1091 p = t; 1092 d = curblock->level + 1; 1093 for (i = 0; i < n; i++) { 1094 p->chain = newSymbol(nil, d, VAR, nil, nil); 1095 p = p->chain; 1096 p->type = constype(nil); 1097 skipchar(curchar, ','); 1098 paramclass = getint(); 1099 if (paramclass == 0) { 1100 p->class = REF; 1101 } 1102 skipchar(curchar, ';'); 1103 chkcont(curchar); 1104 } 1105 } 1106 1107 /* 1108 * Construct an imported type. 1109 * Add it to a list of symbols to get fixed up. 1110 */ 1111 1112 private consImpType (t) 1113 Symbol t; 1114 { 1115 register char *p; 1116 Symbol tmp; 1117 1118 p = curchar; 1119 while (*p != ',' and *p != ';' and *p != '\0') { 1120 ++p; 1121 } 1122 if (*p == '\0') { 1123 panic("bad import symbol entry '%s'", curchar); 1124 } 1125 t->class = TYPEREF; 1126 t->symvalue.typeref = curchar; 1127 if (*p == ',') { 1128 curchar = p + 1; 1129 tmp = constype(nil); 1130 } else { 1131 curchar = p; 1132 } 1133 skipchar(curchar, ';'); 1134 *p = '\0'; 1135 } 1136 1137 /* 1138 * Construct an opaque type entry. 1139 */ 1140 1141 private consOpaqType (t) 1142 Symbol t; 1143 { 1144 register char *p; 1145 register Symbol s; 1146 register Name n; 1147 boolean def; 1148 1149 p = curchar; 1150 while (*p != ';' and *p != ',') { 1151 if (*p == '\0') { 1152 panic("bad opaque symbol entry '%s'", curchar); 1153 } 1154 ++p; 1155 } 1156 def = (Boolean) (*p == ','); 1157 *p = '\0'; 1158 n = identname(curchar, true); 1159 find(s, n) where s->class == TYPEREF endfind(s); 1160 if (s == nil) { 1161 s = insert(n); 1162 s->class = TYPEREF; 1163 s->type = nil; 1164 } 1165 curchar = p + 1; 1166 if (def) { 1167 s->type = constype(nil); 1168 skipchar(curchar, ';'); 1169 } 1170 t->class = TYPE; 1171 t->type = s; 1172 } 1173 1174 /* 1175 * Read an integer from the current position in the type string. 1176 */ 1177 1178 private integer getint () 1179 { 1180 register integer n; 1181 register char *p; 1182 register Boolean isneg; 1183 1184 n = 0; 1185 p = curchar; 1186 if (*p == '-') { 1187 isneg = true; 1188 ++p; 1189 } else { 1190 isneg = false; 1191 } 1192 while (isdigit(*p)) { 1193 n = 10*n + (*p - '0'); 1194 ++p; 1195 } 1196 curchar = p; 1197 return isneg ? (-n) : n; 1198 } 1199 1200 /* 1201 * Add a tag name. This is a kludge to be able to refer 1202 * to tags that have the same name as some other symbol 1203 * in the same block. 1204 */ 1205 1206 private Symbol addtag (s) 1207 register Symbol s; 1208 { 1209 register Symbol t; 1210 char buf[100]; 1211 1212 if (streq(language_name(curlang), "c++")) { 1213 t = insert(s->name); 1214 t->class = TYPE; 1215 } else { 1216 sprintf(buf, "$$%.90s", ident(s->name)); 1217 t = insert(identname(buf, false)); 1218 t->class = TAG; 1219 } 1220 t->language = s->language; 1221 t->block = s->block; 1222 return t; 1223 } 1224