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