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