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