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