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