1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)c.c 1.6 08/05/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 printname(stdout, 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 } 750