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