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

Defined functions

addtag defined in line 1101; used 1 times
consDynarray defined in line 882; used 1 times
consEnum defined in line 941; used 1 times
consImpType defined in line 1007; used 1 times
consOpaqType defined in line 1036; used 1 times
consParamlist defined in line 978; used 2 times
consRecord defined in line 896; used 2 times
consSubrange defined in line 827; used 1 times
constName defined in line 260; used 1 times
constype defined in line 683; used 18 times
enterNestedBlock defined in line 615; used 1 times
enterRoutine defined in line 497; used 2 times
entersym defined in line 148; used 1 times
extVar defined in line 531; used 1 times
findBlock defined in line 590; used 2 times
getExtRef defined in line 559; used 4 times
getRangeBoundType defined in line 851; used 3 times
getType defined in line 668; used 7 times
getint defined in line 1073; used 19 times
initTypeTable defined in line 84; used 1 times
ownVariable defined in line 647; used 1 times
privateRoutine defined in line 458; used 2 times
publicRoutine defined in line 411; used 5 times
tagName defined in line 381; used 1 times
typeName defined in line 338; used 1 times

Defined variables

curchar defined in line 98; used 88 times
private defined in line 1101; never used
rcsid defined in line 11; never used
sccsid defined in line 8; never used

Defined macros

CONSTNAME defined in line 37; never used
EXTFUNCTION defined in line 44; never used
EXTPROCEDURE defined in line 41; never used
EXTVAR defined in line 47; never used
INTFUNCTION defined in line 46; never used
INTPROCEDURE defined in line 43; never used
LOCALVAR defined in line 53; never used
MODULEBEGIN defined in line 40; never used
MODULEVAR defined in line 48; never used
NTYPES defined in line 80; used 4 times
OWNVAR defined in line 49; never used
PRIVFUNCTION defined in line 45; never used
PRIVPROCEDURE defined in line 42; never used
REGVAR defined in line 50; never used
TAGNAME defined in line 39; never used
TYPENAME defined in line 38; never used
T_ARRAY defined in line 60; never used
T_DYNARRAY defined in line 63; never used
T_ENUM defined in line 67; never used
T_FILE defined in line 74; never used
T_FUNCVAR defined in line 69; never used
T_IMPORTED defined in line 71; never used
T_OLDOPENARRAY defined in line 61; never used
T_OPAQUE defined in line 73; never used
T_OPENARRAY defined in line 62; never used
T_PROCVAR defined in line 70; never used
T_PTR defined in line 68; never used
T_RECORD defined in line 65; never used
T_SET defined in line 72; never used
T_SUBARRAY defined in line 64; never used
T_SUBRANGE defined in line 59; never used
T_UNION defined in line 66; never used
VALUEPARAM defined in line 51; never used
VARIABLEPARAM defined in line 52; never used
chkcont defined in line 115; used 6 times
makeParameter defined in line 138; used 2 times
makeVariable defined in line 130; used 5 times
newSym defined in line 122; used 5 times
optchar defined in line 108; never used
skipchar defined in line 100; used 22 times
Last modified: 1985-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4033
Valid CSS Valid XHTML 1.0 Strict