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