|
|
1.1 ! root 1: /* Copyright (c) 1982 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)c.c 1.7 8/16/83"; ! 4: ! 5: /* ! 6: * C-dependent symbol routines. ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: #include "symbols.h" ! 11: #include "printsym.h" ! 12: #include "languages.h" ! 13: #include "c.h" ! 14: #include "tree.h" ! 15: #include "eval.h" ! 16: #include "operators.h" ! 17: #include "mappings.h" ! 18: #include "process.h" ! 19: #include "runtime.h" ! 20: #include "machine.h" ! 21: ! 22: #ifndef public ! 23: # include "tree.h" ! 24: #endif ! 25: ! 26: #define isdouble(range) ( \ ! 27: range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \ ! 28: ) ! 29: ! 30: #define isrange(t, name) (t->class == RANGE and istypename(t->type, name)) ! 31: ! 32: /* ! 33: * Initialize C language information. ! 34: */ ! 35: ! 36: public c_init() ! 37: { ! 38: Language lang; ! 39: ! 40: lang = language_define("c", ".c"); ! 41: language_setop(lang, L_PRINTDECL, c_printdecl); ! 42: language_setop(lang, L_PRINTVAL, c_printval); ! 43: language_setop(lang, L_TYPEMATCH, c_typematch); ! 44: language_setop(lang, L_BUILDAREF, c_buildaref); ! 45: language_setop(lang, L_EVALAREF, c_evalaref); ! 46: } ! 47: ! 48: /* ! 49: * Test if two types are compatible. ! 50: */ ! 51: ! 52: public Boolean c_typematch(type1, type2) ! 53: Symbol type1, type2; ! 54: { ! 55: Boolean b; ! 56: register Symbol t1, t2, tmp; ! 57: ! 58: t1 = type1; ! 59: t2 = type2; ! 60: if (t1 == t2) { ! 61: b = true; ! 62: } else { ! 63: t1 = rtype(t1); ! 64: t2 = rtype(t2); ! 65: if (t1->type == t_char or t1->type == t_int or t1->type == t_real) { ! 66: tmp = t1; ! 67: t1 = t2; ! 68: t2 = tmp; ! 69: } ! 70: b = (Boolean) ( ! 71: ( ! 72: isrange(t1, "int") and ! 73: (t2->type == t_int or t2->type == t_char) ! 74: ) or ( ! 75: isrange(t1, "char") and ! 76: (t2->type == t_char or t2->type == t_int) ! 77: ) or ( ! 78: t1->class == RANGE and isdouble(t1) and t2->type == t_real ! 79: ) or ( ! 80: t1->type == t2->type and ( ! 81: (t1->class == t2->class) or ! 82: (t1->class == SCAL and t2->class == CONST) or ! 83: (t1->class == CONST and t2->class == SCAL) ! 84: ) ! 85: ) ! 86: ); ! 87: } ! 88: return b; ! 89: } ! 90: ! 91: /* ! 92: * Decide if a field is a bit field. ! 93: */ ! 94: ! 95: private Boolean isbitfield(s) ! 96: register Symbol s; ! 97: { ! 98: Boolean b; ! 99: register Integer off, len; ! 100: register Symbol t; ! 101: ! 102: off = s->symvalue.field.offset; ! 103: len = s->symvalue.field.length; ! 104: if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { ! 105: b = true; ! 106: } else { ! 107: t = rtype(s->type); ! 108: b = (Boolean) ! 109: (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE) or ! 110: len != (size(t)*BITSPERBYTE) ! 111: ); ! 112: } ! 113: return b; ! 114: } ! 115: ! 116: /* ! 117: * Print out the declaration of a C variable. ! 118: */ ! 119: ! 120: public c_printdecl(s) ! 121: Symbol s; ! 122: { ! 123: printdecl(s, 0); ! 124: } ! 125: ! 126: private printdecl(s, indent) ! 127: register Symbol s; ! 128: Integer indent; ! 129: { ! 130: register Symbol t; ! 131: Boolean semicolon, newline; ! 132: ! 133: semicolon = true; ! 134: newline = true; ! 135: if (indent > 0) { ! 136: printf("%*c", indent, ' '); ! 137: } ! 138: if (s->class == TYPE) { ! 139: printf("typedef "); ! 140: } ! 141: switch (s->class) { ! 142: case CONST: ! 143: if (s->type->class == SCAL) { ! 144: printf("(enumeration constant, ord %ld)", ! 145: s->symvalue.iconval); ! 146: } else { ! 147: printf("const %s = ", symname(s)); ! 148: printval(s); ! 149: } ! 150: break; ! 151: ! 152: case TYPE: ! 153: case VAR: ! 154: if (s->class != TYPE) { ! 155: if (s->level == 2) { ! 156: printf("static "); ! 157: } else if (s->level < 0) { ! 158: printf("register "); ! 159: } ! 160: } ! 161: if (s->type->class == ARRAY) { ! 162: printtype(s->type, s->type->type, indent); ! 163: t = rtype(s->type->chain); ! 164: assert(t->class == RANGE); ! 165: printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); ! 166: } else { ! 167: printtype(s, s->type, indent); ! 168: if (s->type->class != PTR) { ! 169: printf(" "); ! 170: } ! 171: printf("%s", symname(s)); ! 172: } ! 173: break; ! 174: ! 175: case FIELD: ! 176: if (s->type->class == ARRAY) { ! 177: printtype(s->type, s->type->type, indent); ! 178: t = rtype(s->type->chain); ! 179: assert(t->class == RANGE); ! 180: printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); ! 181: } else { ! 182: printtype(s, s->type, indent); ! 183: if (s->type->class != PTR) { ! 184: printf(" "); ! 185: } ! 186: printf("%s", symname(s)); ! 187: } ! 188: if (isbitfield(s)) { ! 189: printf(" : %d", s->symvalue.field.length); ! 190: } ! 191: break; ! 192: ! 193: case TAG: ! 194: if (s->type == nil) { ! 195: findtype(s); ! 196: if (s->type == nil) { ! 197: error("unexpected missing type information"); ! 198: } ! 199: } ! 200: printtype(s, s->type, indent); ! 201: break; ! 202: ! 203: case RANGE: ! 204: case ARRAY: ! 205: case RECORD: ! 206: case VARNT: ! 207: case PTR: ! 208: semicolon = false; ! 209: printtype(s, s, indent); ! 210: break; ! 211: ! 212: case PROC: ! 213: semicolon = false; ! 214: printf("%s", symname(s)); ! 215: c_listparams(s); ! 216: newline = false; ! 217: break; ! 218: ! 219: case FUNC: ! 220: semicolon = false; ! 221: if (not istypename(s->type, "void")) { ! 222: printtype(s, s->type, indent); ! 223: printf(" "); ! 224: } ! 225: printf("%s", symname(s)); ! 226: c_listparams(s); ! 227: newline = false; ! 228: break; ! 229: ! 230: case MODULE: ! 231: semicolon = false; ! 232: printf("source file \"%s.c\"", symname(s)); ! 233: break; ! 234: ! 235: case PROG: ! 236: semicolon = false; ! 237: printf("executable file \"%s\"", symname(s)); ! 238: break; ! 239: ! 240: default: ! 241: error("class %s in c_printdecl", classname(s)); ! 242: } ! 243: if (semicolon) { ! 244: putchar(';'); ! 245: } ! 246: if (newline) { ! 247: putchar('\n'); ! 248: } ! 249: } ! 250: ! 251: /* ! 252: * Recursive whiz-bang procedure to print the type portion ! 253: * of a declaration. ! 254: * ! 255: * The symbol associated with the type is passed to allow ! 256: * searching for type names without getting "type blah = blah". ! 257: */ ! 258: ! 259: private printtype(s, t, indent) ! 260: Symbol s; ! 261: Symbol t; ! 262: Integer indent; ! 263: { ! 264: register Symbol i; ! 265: long r0, r1; ! 266: register String p; ! 267: ! 268: checkref(s); ! 269: checkref(t); ! 270: switch (t->class) { ! 271: case VAR: ! 272: case CONST: ! 273: case PROC: ! 274: panic("printtype: class %s", classname(t)); ! 275: break; ! 276: ! 277: case ARRAY: ! 278: printf("array["); ! 279: i = t->chain; ! 280: if (i != nil) { ! 281: for (;;) { ! 282: printtype(i, i, indent); ! 283: i = i->chain; ! 284: if (i == nil) { ! 285: break; ! 286: } ! 287: printf(", "); ! 288: } ! 289: } ! 290: printf("] of "); ! 291: printtype(t, t->type, indent); ! 292: break; ! 293: ! 294: case RECORD: ! 295: case VARNT: ! 296: printf("%s ", c_classname(t)); ! 297: if (s->name != nil and s->class == TAG) { ! 298: p = symname(s); ! 299: if (p[0] == '$' and p[1] == '$') { ! 300: printf("%s ", &p[2]); ! 301: } else { ! 302: printf("%s ", p); ! 303: } ! 304: } ! 305: printf("{\n", t->class == RECORD ? "struct" : "union"); ! 306: for (i = t->chain; i != nil; i = i->chain) { ! 307: assert(i->class == FIELD); ! 308: printdecl(i, indent+4); ! 309: } ! 310: if (indent > 0) { ! 311: printf("%*c", indent, ' '); ! 312: } ! 313: printf("}"); ! 314: break; ! 315: ! 316: case RANGE: ! 317: r0 = t->symvalue.rangev.lower; ! 318: r1 = t->symvalue.rangev.upper; ! 319: if (istypename(t->type, "char")) { ! 320: if (r0 < 0x20 or r0 > 0x7e) { ! 321: printf("%ld..", r0); ! 322: } else { ! 323: printf("'%c'..", (char) r0); ! 324: } ! 325: if (r1 < 0x20 or r1 > 0x7e) { ! 326: printf("\\%lo", r1); ! 327: } else { ! 328: printf("'%c'", (char) r1); ! 329: } ! 330: } else if (r0 > 0 and r1 == 0) { ! 331: printf("%ld byte real", r0); ! 332: } else if (r0 >= 0) { ! 333: printf("%lu..%lu", r0, r1); ! 334: } else { ! 335: printf("%ld..%ld", r0, r1); ! 336: } ! 337: break; ! 338: ! 339: case PTR: ! 340: printtype(t, t->type, indent); ! 341: if (t->type->class != PTR) { ! 342: printf(" "); ! 343: } ! 344: printf("*"); ! 345: break; ! 346: ! 347: case FUNC: ! 348: printtype(t, t->type, indent); ! 349: printf("()"); ! 350: break; ! 351: ! 352: case TYPE: ! 353: if (t->name != nil) { ! 354: printf("%s", symname(t)); ! 355: } else { ! 356: printtype(t, t->type, indent); ! 357: } ! 358: break; ! 359: ! 360: case TYPEREF: ! 361: printf("@%s", symname(t)); ! 362: break; ! 363: ! 364: case SCAL: ! 365: printf("enum "); ! 366: if (s->name != nil and s->class == TAG) { ! 367: printf("%s ", symname(s)); ! 368: } ! 369: printf("{ "); ! 370: i = t->chain; ! 371: if (i != nil) { ! 372: for (;;) { ! 373: printf("%s", symname(i)); ! 374: i = i->chain; ! 375: if (i == nil) break; ! 376: printf(", "); ! 377: } ! 378: } ! 379: printf(" }"); ! 380: break; ! 381: ! 382: case TAG: ! 383: if (t->type == nil) { ! 384: printf("unresolved tag %s", symname(t)); ! 385: } else { ! 386: i = rtype(t->type); ! 387: printf("%s %s", c_classname(i), symname(t)); ! 388: } ! 389: break; ! 390: ! 391: default: ! 392: printf("(class %d)", t->class); ! 393: break; ! 394: } ! 395: } ! 396: ! 397: /* ! 398: * List the parameters of a procedure or function. ! 399: * No attempt is made to combine like types. ! 400: */ ! 401: ! 402: public c_listparams(s) ! 403: Symbol s; ! 404: { ! 405: register Symbol t; ! 406: ! 407: putchar('('); ! 408: for (t = s->chain; t != nil; t = t->chain) { ! 409: printf("%s", symname(t)); ! 410: if (t->chain != nil) { ! 411: printf(", "); ! 412: } ! 413: } ! 414: putchar(')'); ! 415: if (s->chain != nil) { ! 416: printf("\n"); ! 417: for (t = s->chain; t != nil; t = t->chain) { ! 418: if (t->class != VAR) { ! 419: panic("unexpected class %d for parameter", t->class); ! 420: } ! 421: printdecl(t, 0); ! 422: } ! 423: } else { ! 424: putchar('\n'); ! 425: } ! 426: } ! 427: ! 428: /* ! 429: * Print out the value on the top of the expression stack ! 430: * in the format for the type of the given symbol. ! 431: */ ! 432: ! 433: public c_printval(s) ! 434: Symbol s; ! 435: { ! 436: register Symbol t; ! 437: register Address a; ! 438: register int i, len; ! 439: ! 440: switch (s->class) { ! 441: case CONST: ! 442: case TYPE: ! 443: case VAR: ! 444: case REF: ! 445: case FVAR: ! 446: case TAG: ! 447: c_printval(s->type); ! 448: break; ! 449: ! 450: case FIELD: ! 451: if (isbitfield(s)) { ! 452: len = s->symvalue.field.length; ! 453: if (len <= BITSPERBYTE) { ! 454: i = pop(char); ! 455: } else if (len <= sizeof(short)*BITSPERBYTE) { ! 456: i = pop(short); ! 457: } else { ! 458: i = pop(long); ! 459: } ! 460: i >>= (s->symvalue.field.offset mod BITSPERBYTE); ! 461: i &= ((1 << len) - 1); ! 462: t = rtype(s->type); ! 463: if (t->class == SCAL) { ! 464: printenum(i, t); ! 465: } else { ! 466: printrange(i, t); ! 467: } ! 468: } else { ! 469: c_printval(s->type); ! 470: } ! 471: break; ! 472: ! 473: case ARRAY: ! 474: t = rtype(s->type); ! 475: if (t->class == RANGE and istypename(t->type, "char")) { ! 476: len = size(s); ! 477: sp -= len; ! 478: printf("\"%.*s\"", len, sp); ! 479: } else { ! 480: printarray(s); ! 481: } ! 482: break; ! 483: ! 484: case RECORD: ! 485: c_printstruct(s); ! 486: break; ! 487: ! 488: case RANGE: ! 489: if (istypename(s->type, "boolean")) { ! 490: printrange(popsmall(s), s); ! 491: } else if (istypename(s->type, "char")) { ! 492: printrange(pop(char), s); ! 493: } else if (isdouble(s)) { ! 494: switch (s->symvalue.rangev.lower) { ! 495: case sizeof(float): ! 496: prtreal(pop(float)); ! 497: break; ! 498: ! 499: case sizeof(double): ! 500: prtreal(pop(double)); ! 501: break; ! 502: ! 503: default: ! 504: panic("bad real size %d", t->symvalue.rangev.lower); ! 505: break; ! 506: } ! 507: } else { ! 508: printrange(popsmall(s), s); ! 509: } ! 510: break; ! 511: ! 512: case PTR: ! 513: t = rtype(s->type); ! 514: a = pop(Address); ! 515: if (a == 0) { ! 516: printf("(nil)"); ! 517: } else if (t->class == RANGE and istypename(t->type, "char")) { ! 518: printstring(a); ! 519: } else { ! 520: printf("0x%x", a); ! 521: } ! 522: break; ! 523: ! 524: case SCAL: ! 525: i = pop(Integer); ! 526: printenum(i, s); ! 527: break; ! 528: ! 529: default: ! 530: if (ord(s->class) > ord(TYPEREF)) { ! 531: panic("printval: bad class %d", ord(s->class)); ! 532: } ! 533: sp -= size(s); ! 534: printf("<%s>", c_classname(s)); ! 535: break; ! 536: } ! 537: } ! 538: ! 539: /* ! 540: * Print out a C structure. ! 541: */ ! 542: ! 543: private c_printstruct(s) ! 544: Symbol s; ! 545: { ! 546: register Symbol f; ! 547: register Stack *savesp; ! 548: register Integer n, off, len; ! 549: ! 550: sp -= size(s); ! 551: savesp = sp; ! 552: printf("("); ! 553: f = s->chain; ! 554: for (;;) { ! 555: off = f->symvalue.field.offset; ! 556: len = f->symvalue.field.length; ! 557: n = (off + len + 7) div BITSPERBYTE; ! 558: sp += n; ! 559: printf("%s = ", symname(f)); ! 560: c_printval(f); ! 561: sp = savesp; ! 562: f = f->chain; ! 563: if (f == nil) break; ! 564: printf(", "); ! 565: } ! 566: printf(")"); ! 567: } ! 568: ! 569: /* ! 570: * Print out a range type (integer, char, or boolean). ! 571: */ ! 572: ! 573: private printrange(i, t) ! 574: Integer i; ! 575: register Symbol t; ! 576: { ! 577: if (istypename(t->type, "boolean")) { ! 578: printf(((Boolean) i) == true ? "true" : "false"); ! 579: } else if (istypename(t->type, "char")) { ! 580: putchar('\''); ! 581: printchar(i); ! 582: putchar('\''); ! 583: } else if (t->symvalue.rangev.lower >= 0) { ! 584: printf("%lu", i); ! 585: } else { ! 586: printf("%ld", i); ! 587: } ! 588: } ! 589: ! 590: /* ! 591: * Print out a null-terminated string (pointer to char) ! 592: * starting at the given address. ! 593: */ ! 594: ! 595: private printstring(addr) ! 596: Address addr; ! 597: { ! 598: register Address a; ! 599: register Integer i, len; ! 600: register Boolean endofstring; ! 601: union { ! 602: char ch[sizeof(Word)]; ! 603: int word; ! 604: } u; ! 605: ! 606: putchar('"'); ! 607: a = addr; ! 608: endofstring = false; ! 609: while (not endofstring) { ! 610: dread(&u, a, sizeof(u)); ! 611: i = 0; ! 612: do { ! 613: if (u.ch[i] == '\0') { ! 614: endofstring = true; ! 615: } else { ! 616: printchar(u.ch[i]); ! 617: } ! 618: ++i; ! 619: } while (i < sizeof(Word) and not endofstring); ! 620: a += sizeof(Word); ! 621: } ! 622: putchar('"'); ! 623: } ! 624: ! 625: /* ! 626: * Print out an enumerated value by finding the corresponding ! 627: * name in the enumeration list. ! 628: */ ! 629: ! 630: private printenum(i, t) ! 631: Integer i; ! 632: Symbol t; ! 633: { ! 634: register Symbol e; ! 635: ! 636: e = t->chain; ! 637: while (e != nil and e->symvalue.iconval != i) { ! 638: e = e->chain; ! 639: } ! 640: if (e != nil) { ! 641: printf("%s", symname(e)); ! 642: } else { ! 643: printf("%d", i); ! 644: } ! 645: } ! 646: ! 647: /* ! 648: * Return the C name for the particular class of a symbol. ! 649: */ ! 650: ! 651: public String c_classname(s) ! 652: Symbol s; ! 653: { ! 654: String str; ! 655: ! 656: switch (s->class) { ! 657: case RECORD: ! 658: str = "struct"; ! 659: break; ! 660: ! 661: case VARNT: ! 662: str = "union"; ! 663: break; ! 664: ! 665: case SCAL: ! 666: str = "enum"; ! 667: break; ! 668: ! 669: default: ! 670: str = classname(s); ! 671: } ! 672: return str; ! 673: } ! 674: public Node c_buildaref(a, slist) ! 675: Node a, slist; ! 676: { ! 677: register Symbol t; ! 678: register Node p; ! 679: Symbol etype, atype, eltype; ! 680: Node esub, r; ! 681: ! 682: r = a; ! 683: t = rtype(a->nodetype); ! 684: eltype = t->type; ! 685: if (t->class == PTR) { ! 686: p = slist->value.arg[0]; ! 687: if (not compatible(p->nodetype, t_int)) { ! 688: beginerrmsg(); ! 689: fprintf(stderr, "bad type for subscript of "); ! 690: prtree(stderr, a); ! 691: enderrmsg(); ! 692: } ! 693: r = build(O_MUL, p, build(O_LCON, (long) size(eltype))); ! 694: r = build(O_ADD, build(O_RVAL, a), r); ! 695: r->nodetype = eltype; ! 696: } else if (t->class != ARRAY) { ! 697: beginerrmsg(); ! 698: prtree(stderr, a); ! 699: fprintf(stderr, " is not an array"); ! 700: enderrmsg(); ! 701: } else { ! 702: p = slist; ! 703: t = t->chain; ! 704: for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { ! 705: esub = p->value.arg[0]; ! 706: etype = rtype(esub->nodetype); ! 707: atype = rtype(t); ! 708: if (not compatible(atype, etype)) { ! 709: beginerrmsg(); ! 710: fprintf(stderr, "subscript "); ! 711: prtree(stderr, esub); ! 712: fprintf(stderr, " is the wrong type"); ! 713: enderrmsg(); ! 714: } ! 715: r = build(O_INDEX, r, esub); ! 716: r->nodetype = eltype; ! 717: } ! 718: if (p != nil or t != nil) { ! 719: beginerrmsg(); ! 720: if (p != nil) { ! 721: fprintf(stderr, "too many subscripts for "); ! 722: } else { ! 723: fprintf(stderr, "not enough subscripts for "); ! 724: } ! 725: prtree(stderr, a); ! 726: enderrmsg(); ! 727: } ! 728: } ! 729: return r; ! 730: } ! 731: ! 732: /* ! 733: * Evaluate a subscript index. ! 734: */ ! 735: ! 736: public int c_evalaref(s, i) ! 737: Symbol s; ! 738: long i; ! 739: { ! 740: long lb, ub; ! 741: ! 742: s = rtype(s)->chain; ! 743: lb = s->symvalue.rangev.lower; ! 744: ub = s->symvalue.rangev.upper; ! 745: if (i < lb or i > ub) { ! 746: error("subscript out of range"); ! 747: } ! 748: return (i - lb); ! 749: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.