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