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