1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)c.c 1.9 (Berkeley) 03/01/85"; 4 5 static char rcsid[] = "$Header: c.c,v 1.5 84/12/26 10:38:23 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->class == RANGE and t2->class == RANGE and 86 t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 87 t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 88 ) or ( 89 t1->type == t2->type and ( 90 (t1->class == t2->class) or 91 (t1->class == SCAL and t2->class == CONST) or 92 (t1->class == CONST and t2->class == SCAL) 93 ) 94 ) or ( 95 t1->class == PTR and c_typematch(t1->type, t_char) and 96 t2->class == ARRAY and c_typematch(t2->type, t_char) and 97 t2->language == primlang 98 ) 99 ); 100 } 101 return b; 102 } 103 104 /* 105 * Print out the declaration of a C variable. 106 */ 107 108 public c_printdecl(s) 109 Symbol s; 110 { 111 printdecl(s, 0); 112 } 113 114 private printdecl(s, indent) 115 register Symbol s; 116 Integer indent; 117 { 118 register Symbol t; 119 Boolean semicolon, newline; 120 121 semicolon = true; 122 newline = true; 123 if (indent > 0) { 124 printf("%*c", indent, ' '); 125 } 126 if (s->class == TYPE) { 127 printf("typedef "); 128 } 129 switch (s->class) { 130 case CONST: 131 if (s->type->class == SCAL) { 132 printf("enumeration constant with value "); 133 eval(s->symvalue.constval); 134 c_printval(s); 135 } else { 136 printf("const %s = ", symname(s)); 137 printval(s); 138 } 139 break; 140 141 case TYPE: 142 case VAR: 143 if (s->class != TYPE and s->level < 0) { 144 printf("register "); 145 } 146 if (s->type->class == ARRAY) { 147 printtype(s->type, s->type->type, indent); 148 t = rtype(s->type->chain); 149 assert(t->class == RANGE); 150 printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); 151 } else { 152 printtype(s, s->type, indent); 153 if (s->type->class != PTR) { 154 printf(" "); 155 } 156 printf("%s", symname(s)); 157 } 158 break; 159 160 case FIELD: 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 if (isbitfield(s)) { 174 printf(" : %d", s->symvalue.field.length); 175 } 176 break; 177 178 case TAG: 179 if (s->type == nil) { 180 findtype(s); 181 if (s->type == nil) { 182 error("unexpected missing type information"); 183 } 184 } 185 printtype(s, s->type, indent); 186 break; 187 188 case RANGE: 189 case ARRAY: 190 case RECORD: 191 case VARNT: 192 case PTR: 193 case FFUNC: 194 semicolon = false; 195 printtype(s, s, indent); 196 break; 197 198 case SCAL: 199 printf("(enumeration constant, value %d)", s->symvalue.iconval); 200 break; 201 202 case PROC: 203 semicolon = false; 204 printf("%s", symname(s)); 205 c_listparams(s); 206 newline = false; 207 break; 208 209 case FUNC: 210 semicolon = false; 211 if (not istypename(s->type, "void")) { 212 printtype(s, s->type, indent); 213 printf(" "); 214 } 215 printf("%s", symname(s)); 216 c_listparams(s); 217 newline = false; 218 break; 219 220 case MODULE: 221 semicolon = false; 222 printf("source file \"%s.c\"", symname(s)); 223 break; 224 225 case PROG: 226 semicolon = false; 227 printf("executable file \"%s\"", symname(s)); 228 break; 229 230 default: 231 printf("[%s]", classname(s)); 232 break; 233 } 234 if (semicolon) { 235 putchar(';'); 236 } 237 if (newline) { 238 putchar('\n'); 239 } 240 } 241 242 /* 243 * Recursive whiz-bang procedure to print the type portion 244 * of a declaration. 245 * 246 * The symbol associated with the type is passed to allow 247 * searching for type names without getting "type blah = blah". 248 */ 249 250 private printtype(s, t, indent) 251 Symbol s; 252 Symbol t; 253 Integer indent; 254 { 255 register Symbol i; 256 long r0, r1; 257 register String p; 258 259 checkref(s); 260 checkref(t); 261 switch (t->class) { 262 case VAR: 263 case CONST: 264 case PROC: 265 panic("printtype: class %s", classname(t)); 266 break; 267 268 case ARRAY: 269 printf("array["); 270 i = t->chain; 271 if (i != nil) { 272 for (;;) { 273 printtype(i, i, indent); 274 i = i->chain; 275 if (i == nil) { 276 break; 277 } 278 printf(", "); 279 } 280 } 281 printf("] of "); 282 printtype(t, t->type, indent); 283 break; 284 285 case RECORD: 286 case VARNT: 287 printf("%s ", c_classname(t)); 288 if (s->name != nil and s->class == TAG) { 289 p = symname(s); 290 if (p[0] == '$' and p[1] == '$') { 291 printf("%s ", &p[2]); 292 } else { 293 printf("%s ", p); 294 } 295 } 296 printf("{\n", t->class == RECORD ? "struct" : "union"); 297 for (i = t->chain; i != nil; i = i->chain) { 298 assert(i->class == FIELD); 299 printdecl(i, indent+4); 300 } 301 if (indent > 0) { 302 printf("%*c", indent, ' '); 303 } 304 printf("}"); 305 break; 306 307 case RANGE: 308 r0 = t->symvalue.rangev.lower; 309 r1 = t->symvalue.rangev.upper; 310 if (istypename(t->type, "char")) { 311 if (r0 < 0x20 or r0 > 0x7e) { 312 printf("%ld..", r0); 313 } else { 314 printf("'%c'..", (char) r0); 315 } 316 if (r1 < 0x20 or r1 > 0x7e) { 317 printf("\\%lo", r1); 318 } else { 319 printf("'%c'", (char) r1); 320 } 321 } else if (r0 > 0 and r1 == 0) { 322 printf("%ld byte real", r0); 323 } else if (r0 >= 0) { 324 printf("%lu..%lu", r0, r1); 325 } else { 326 printf("%ld..%ld", r0, r1); 327 } 328 break; 329 330 case PTR: 331 printtype(t, t->type, indent); 332 if (t->type->class != PTR) { 333 printf(" "); 334 } 335 printf("*"); 336 break; 337 338 case FUNC: 339 case FFUNC: 340 printtype(t, t->type, indent); 341 printf("()"); 342 break; 343 344 case TYPE: 345 if (t->name != nil) { 346 printname(stdout, t); 347 } else { 348 printtype(t, t->type, indent); 349 } 350 break; 351 352 case TYPEREF: 353 printf("@%s", symname(t)); 354 break; 355 356 case SCAL: 357 printf("enum "); 358 if (s->name != nil and s->class == TAG) { 359 printf("%s ", symname(s)); 360 } 361 printf("{ "); 362 i = t->chain; 363 if (i != nil) { 364 for (;;) { 365 printf("%s", symname(i)); 366 i = i->chain; 367 if (i == nil) break; 368 printf(", "); 369 } 370 } 371 printf(" }"); 372 break; 373 374 case TAG: 375 if (t->type == nil) { 376 printf("unresolved tag %s", symname(t)); 377 } else { 378 i = rtype(t->type); 379 printf("%s %s", c_classname(i), symname(t)); 380 } 381 break; 382 383 default: 384 printf("(class %d)", t->class); 385 break; 386 } 387 } 388 389 /* 390 * List the parameters of a procedure or function. 391 * No attempt is made to combine like types. 392 */ 393 394 public c_listparams(s) 395 Symbol s; 396 { 397 register Symbol t; 398 399 putchar('('); 400 for (t = s->chain; t != nil; t = t->chain) { 401 printf("%s", symname(t)); 402 if (t->chain != nil) { 403 printf(", "); 404 } 405 } 406 putchar(')'); 407 if (s->chain != nil) { 408 printf("\n"); 409 for (t = s->chain; t != nil; t = t->chain) { 410 if (t->class != VAR) { 411 panic("unexpected class %d for parameter", t->class); 412 } 413 printdecl(t, 0); 414 } 415 } else { 416 putchar('\n'); 417 } 418 } 419 420 /* 421 * Print out the value on the top of the expression stack 422 * in the format for the type of the given symbol. 423 */ 424 425 public c_printval(s) 426 Symbol s; 427 { 428 register Symbol t; 429 register Address a; 430 integer i, len; 431 432 switch (s->class) { 433 case CONST: 434 case TYPE: 435 case VAR: 436 case REF: 437 case FVAR: 438 case TAG: 439 c_printval(s->type); 440 break; 441 442 case FIELD: 443 if (isbitfield(s)) { 444 i = 0; 445 popn(size(s), &i); 446 i >>= (s->symvalue.field.offset mod BITSPERBYTE); 447 i &= ((1 << s->symvalue.field.length) - 1); 448 t = rtype(s->type); 449 if (t->class == SCAL) { 450 printEnum(i, t); 451 } else { 452 printRangeVal(i, t); 453 } 454 } else { 455 c_printval(s->type); 456 } 457 break; 458 459 case ARRAY: 460 t = rtype(s->type); 461 if ((t->class == RANGE and istypename(t->type, "char")) or 462 t == t_char->type 463 ) { 464 len = size(s); 465 sp -= len; 466 if (s->language == primlang) { 467 printf("%.*s", len, sp); 468 } else { 469 printf("\"%.*s\"", len, sp); 470 } 471 } else { 472 printarray(s); 473 } 474 break; 475 476 case RECORD: 477 c_printstruct(s); 478 break; 479 480 case RANGE: 481 if (s == t_boolean->type or istypename(s->type, "boolean")) { 482 printRangeVal(popsmall(s), s); 483 } else if (s == t_char->type or istypename(s->type, "char")) { 484 printRangeVal(pop(char), s); 485 } else if (s == t_real->type or isdouble(s)) { 486 switch (s->symvalue.rangev.lower) { 487 case sizeof(float): 488 prtreal(pop(float)); 489 break; 490 491 case sizeof(double): 492 prtreal(pop(double)); 493 break; 494 495 default: 496 panic("bad real size %d", t->symvalue.rangev.lower); 497 break; 498 } 499 } else { 500 printRangeVal(popsmall(s), s); 501 } 502 break; 503 504 case PTR: 505 t = rtype(s->type); 506 a = pop(Address); 507 if (a == 0) { 508 printf("(nil)"); 509 } else if (t->class == RANGE and istypename(t->type, "char")) { 510 printString(a, (boolean) (s->language != primlang)); 511 } else { 512 printf("0x%x", a); 513 } 514 break; 515 516 case SCAL: 517 i = pop(Integer); 518 printEnum(i, s); 519 break; 520 521 /* 522 * Unresolved structure pointers? 523 */ 524 case BADUSE: 525 a = pop(Address); 526 printf("@%x", a); 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 Symbol f; 547 Stack *savesp; 548 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 + BITSPERBYTE - 1) 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 * Return the C name for the particular class of a symbol. 571 */ 572 573 public String c_classname(s) 574 Symbol s; 575 { 576 String str; 577 578 switch (s->class) { 579 case RECORD: 580 str = "struct"; 581 break; 582 583 case VARNT: 584 str = "union"; 585 break; 586 587 case SCAL: 588 str = "enum"; 589 break; 590 591 default: 592 str = classname(s); 593 } 594 return str; 595 } 596 597 public Node c_buildaref(a, slist) 598 Node a, slist; 599 { 600 register Symbol t; 601 register Node p; 602 Symbol etype, atype, eltype; 603 Node r, esub; 604 605 t = rtype(a->nodetype); 606 eltype = t->type; 607 if (t->class == PTR) { 608 p = slist->value.arg[0]; 609 if (not compatible(p->nodetype, t_int)) { 610 beginerrmsg(); 611 fprintf(stderr, "subscript must be integer-compatible"); 612 enderrmsg(); 613 } 614 r = build(O_MUL, p, build(O_LCON, (long) size(eltype))); 615 r = build(O_ADD, build(O_RVAL, a), r); 616 r->nodetype = eltype; 617 } else if (t->class != ARRAY) { 618 beginerrmsg(); 619 fprintf(stderr, "\""); 620 prtree(stderr, a); 621 fprintf(stderr, "\" is not an array"); 622 enderrmsg(); 623 } else { 624 r = a; 625 p = slist; 626 t = t->chain; 627 for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { 628 esub = p->value.arg[0]; 629 etype = rtype(esub->nodetype); 630 atype = rtype(t); 631 if (not compatible(atype, etype)) { 632 beginerrmsg(); 633 fprintf(stderr, "subscript \""); 634 prtree(stderr, esub); 635 fprintf(stderr, "\" is the wrong type"); 636 enderrmsg(); 637 } 638 r = build(O_INDEX, r, esub); 639 r->nodetype = eltype; 640 } 641 if (p != nil or t != nil) { 642 beginerrmsg(); 643 if (p != nil) { 644 fprintf(stderr, "too many subscripts for \""); 645 } else { 646 fprintf(stderr, "not enough subscripts for \""); 647 } 648 prtree(stderr, a); 649 fprintf(stderr, "\""); 650 enderrmsg(); 651 } 652 } 653 return r; 654 } 655 656 /* 657 * Evaluate a subscript index. 658 */ 659 660 public c_evalaref(s, base, i) 661 Symbol s; 662 Address base; 663 long i; 664 { 665 Symbol t; 666 long lb, ub; 667 668 t = rtype(s); 669 s = t->chain; 670 lb = s->symvalue.rangev.lower; 671 ub = s->symvalue.rangev.upper; 672 if (i < lb or i > ub) { 673 error("subscript out of range"); 674 } 675 push(long, base + (i - lb) * size(t->type)); 676 } 677 678 /* 679 * Initialize typetable information. 680 */ 681 682 public c_modinit (typetable) 683 Symbol typetable[]; 684 { 685 /* nothing right now */ 686 } 687 688 public boolean c_hasmodules () 689 { 690 return false; 691 } 692 693 public boolean c_passaddr (param, exprtype) 694 Symbol param, exprtype; 695 { 696 boolean b; 697 Symbol t; 698 699 t = rtype(exprtype); 700 b = (boolean) (t->class == ARRAY); 701 return b; 702 } 703