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: }