|
|
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.3 (Berkeley) 5/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.