1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)c.c 5.10 (Berkeley) 06/01/90"; 10 #endif /* not lint */ 11 12 /* 13 * C-dependent symbol routines. 14 */ 15 16 #include "defs.h" 17 #include "symbols.h" 18 #include "printsym.h" 19 #include "languages.h" 20 #include "c.h" 21 #include "tree.h" 22 #include "eval.h" 23 #include "operators.h" 24 #include "mappings.h" 25 #include "process.h" 26 #include "runtime.h" 27 #include "machine.h" 28 29 #ifndef public 30 # include "tree.h" 31 #endif 32 33 #define isdouble(range) ( \ 34 range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \ 35 ) 36 37 #define isrange(t, name) (t->class == RANGE and istypename(t->type, name)) 38 39 private Language langC; 40 private Language langCplpl; 41 42 /* 43 * Initialize C language information. 44 */ 45 46 public c_init() 47 { 48 langC = language_define("c", ".c"); 49 language_setop(langC, L_PRINTDECL, c_printdecl); 50 language_setop(langC, L_PRINTVAL, c_printval); 51 language_setop(langC, L_TYPEMATCH, c_typematch); 52 language_setop(langC, L_BUILDAREF, c_buildaref); 53 language_setop(langC, L_EVALAREF, c_evalaref); 54 language_setop(langC, L_MODINIT, c_modinit); 55 language_setop(langC, L_HASMODULES, c_hasmodules); 56 language_setop(langC, L_PASSADDR, c_passaddr); 57 58 langCplpl = language_define("c++", "..c"); 59 language_setop(langCplpl, L_PRINTDECL, c_printdecl); 60 language_setop(langCplpl, L_PRINTVAL, c_printval); 61 language_setop(langCplpl, L_TYPEMATCH, c_typematch); 62 language_setop(langCplpl, L_BUILDAREF, c_buildaref); 63 language_setop(langCplpl, L_EVALAREF, c_evalaref); 64 language_setop(langCplpl, L_MODINIT, c_modinit); 65 language_setop(langCplpl, L_HASMODULES, c_hasmodules); 66 language_setop(langCplpl, L_PASSADDR, c_passaddr); 67 } 68 69 /* 70 * Test if two types are compatible. 71 */ 72 73 public Boolean c_typematch(type1, type2) 74 Symbol type1, type2; 75 { 76 Boolean b; 77 register Symbol t1, t2, tmp; 78 79 t1 = type1; 80 t2 = type2; 81 if (t1 == t2) { 82 b = true; 83 } else { 84 t1 = rtype(t1); 85 t2 = rtype(t2); 86 if (t1 == t_char->type or t1 == t_int->type or t1 == t_real->type) { 87 tmp = t1; 88 t1 = t2; 89 t2 = tmp; 90 } 91 b = (Boolean) ( 92 ( 93 isrange(t1, "int") and !isdouble(t1) /* sigh */ and 94 (t2 == t_int->type or t2 == t_char->type) 95 ) or ( 96 isrange(t1, "char") and 97 (t2 == t_char->type or t2 == t_int->type) 98 ) or ( 99 t1->class == RANGE and isdouble(t1) and t2 == t_real->type 100 ) or ( 101 t1->class == RANGE and t2->class == RANGE and 102 t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 103 t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 104 ) or ( 105 t1->class != RANGE and t1->type == t2->type and ( 106 (t1->class == t2->class) or 107 (t1->class == SCAL and t2->class == CONST) or 108 (t1->class == CONST and t2->class == SCAL) 109 ) 110 ) or ( 111 t1->class == PTR and c_typematch(t1->type, t_char) and 112 t2->class == ARRAY and c_typematch(t2->type, t_char) and 113 t2->language == primlang 114 ) 115 ); 116 } 117 return b; 118 } 119 120 /* 121 * Print out the declaration of a C variable. 122 */ 123 124 public c_printdecl(s) 125 Symbol s; 126 { 127 printdecl(s, 0); 128 } 129 130 private printdecl(s, indent) 131 register Symbol s; 132 Integer indent; 133 { 134 register Symbol t; 135 Boolean semicolon, newline; 136 137 semicolon = true; 138 newline = true; 139 if (indent > 0) { 140 printf("%*c", indent, ' '); 141 } 142 if (s->class == TYPE) { 143 printf("typedef "); 144 } 145 switch (s->class) { 146 case CONST: 147 if (s->type->class == SCAL) { 148 printf("enumeration constant with value "); 149 eval(s->symvalue.constval); 150 c_printval(s); 151 } else { 152 printf("const %s = ", symname(s)); 153 printval(s); 154 } 155 break; 156 157 case TYPE: 158 case VAR: 159 if (s->class != TYPE and s->storage == INREG) { 160 printf("register "); 161 } 162 if (s->type->class == ARRAY) { 163 printtype(s->type, s->type->type, indent); 164 t = rtype(s->type->chain); 165 assert(t->class == RANGE); 166 printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); 167 } else { 168 printtype(s, s->type, indent); 169 if (s->type->class != PTR) { 170 printf(" "); 171 } 172 printf("%s", symname(s)); 173 } 174 break; 175 176 case FIELD: 177 if (s->type->class == ARRAY) { 178 printtype(s->type, s->type->type, indent); 179 t = rtype(s->type->chain); 180 assert(t->class == RANGE); 181 printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); 182 } else { 183 printtype(s, s->type, indent); 184 if (s->type->class != PTR) { 185 printf(" "); 186 } 187 printf("%s", symname(s)); 188 } 189 if (isbitfield(s)) { 190 printf(" : %d", s->symvalue.field.length); 191 } 192 break; 193 194 case TAG: 195 if (s->type == nil) { 196 findtype(s); 197 if (s->type == nil) { 198 error("unexpected missing type information"); 199 } 200 } 201 printtype(s, s->type, indent); 202 break; 203 204 case RANGE: 205 case ARRAY: 206 case RECORD: 207 case VARNT: 208 case PTR: 209 case FFUNC: 210 semicolon = false; 211 printtype(s, s, indent); 212 break; 213 214 case SCAL: 215 printf("(enumeration constant, value %d)", s->symvalue.iconval); 216 break; 217 218 case PROC: 219 semicolon = false; 220 printf("%s", symname(s)); 221 c_listparams(s); 222 newline = false; 223 break; 224 225 case FUNC: 226 semicolon = false; 227 if (not istypename(s->type, "void")) { 228 printtype(s, s->type, indent); 229 printf(" "); 230 } 231 printf("%s", symname(s)); 232 c_listparams(s); 233 newline = false; 234 break; 235 236 case MODULE: 237 semicolon = false; 238 printf("source file \"%s.c\"", symname(s)); 239 break; 240 241 case PROG: 242 semicolon = false; 243 printf("executable file \"%s\"", symname(s)); 244 break; 245 246 default: 247 printf("[%s]", classname(s)); 248 break; 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"); 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 register String str; 448 449 switch (s->class) { 450 case CONST: 451 case TYPE: 452 case VAR: 453 case REF: 454 case FVAR: 455 case TAG: 456 c_printval(s->type); 457 break; 458 459 case FIELD: 460 if (isbitfield(s)) { 461 i = extractField(s); 462 t = rtype(s->type); 463 if (t->class == SCAL) { 464 printEnum(i, t); 465 } else { 466 printRangeVal(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")) or 476 t == t_char->type 477 ) { 478 len = size(s); 479 str = (String) (sp -= len); 480 if (s->language != primlang) { 481 putchar('"'); 482 } 483 while (--len > 0 and *str != '\0') { 484 printchar(*str++); 485 } 486 if (*str != '\0') { /* XXX - pitch trailing null */ 487 printchar(*str); 488 } 489 if (s->language != primlang) { 490 putchar('"'); 491 } 492 } else { 493 printarray(s); 494 } 495 break; 496 497 case RECORD: 498 c_printstruct(s); 499 break; 500 501 case RANGE: 502 if (s == t_boolean->type or istypename(s->type, "boolean")) { 503 printRangeVal(popsmall(s), s); 504 } else if (s == t_char->type or istypename(s->type, "char")) { 505 printRangeVal(pop(char), s); 506 } else if (s == t_real->type or isdouble(s)) { 507 switch (s->symvalue.rangev.lower) { 508 case sizeof(float): 509 prtreal((double) (pop(float))); 510 break; 511 512 case sizeof(double): 513 prtreal(pop(double)); 514 break; 515 516 default: 517 panic("bad real size %d", t->symvalue.rangev.lower); 518 break; 519 } 520 } else { 521 printRangeVal(popsmall(s), s); 522 } 523 break; 524 525 case PTR: 526 t = rtype(s->type); 527 a = pop(Address); 528 if (a == 0) { 529 printf("(nil)"); 530 } else if (t->class == RANGE and istypename(t->type, "char")) { 531 printString(a, (boolean) (s->language != primlang)); 532 } else { 533 printf("0x%x", a); 534 } 535 break; 536 537 case SCAL: 538 i = pop(Integer); 539 printEnum(i, s); 540 break; 541 542 /* 543 * Unresolved structure pointers? 544 */ 545 case BADUSE: 546 a = pop(Address); 547 printf("@%x", a); 548 break; 549 550 default: 551 if (ord(s->class) > ord(TYPEREF)) { 552 panic("printval: bad class %d", ord(s->class)); 553 } 554 sp -= size(s); 555 printf("[%s]", c_classname(s)); 556 break; 557 } 558 } 559 560 /* 561 * Print out a C structure. 562 */ 563 564 private c_printstruct (s) 565 Symbol s; 566 { 567 Symbol f; 568 Stack *savesp; 569 integer n, off, len; 570 571 sp -= size(s); 572 savesp = sp; 573 printf("("); 574 f = s->chain; 575 for (;;) { 576 off = f->symvalue.field.offset; 577 len = f->symvalue.field.length; 578 n = (off + len + BITSPERBYTE - 1) div BITSPERBYTE; 579 sp += n; 580 printf("%s = ", symname(f)); 581 c_printval(f); 582 sp = savesp; 583 f = f->chain; 584 if (f == nil) break; 585 printf(", "); 586 } 587 printf(")"); 588 } 589 590 /* 591 * Return the C name for the particular class of a symbol. 592 */ 593 594 public String c_classname(s) 595 Symbol s; 596 { 597 String str; 598 599 switch (s->class) { 600 case RECORD: 601 str = "struct"; 602 break; 603 604 case VARNT: 605 str = "union"; 606 break; 607 608 case SCAL: 609 str = "enum"; 610 break; 611 612 default: 613 str = classname(s); 614 } 615 return str; 616 } 617 618 public Node c_buildaref(a, slist) 619 Node a, slist; 620 { 621 register Symbol t; 622 register Node p; 623 Symbol etype, atype, eltype; 624 Node r, esub; 625 626 t = rtype(a->nodetype); 627 eltype = t->type; 628 if (t->class == PTR) { 629 p = slist->value.arg[0]; 630 if (not compatible(p->nodetype, t_int)) { 631 beginerrmsg(); 632 fprintf(stderr, "subscript must be integer-compatible"); 633 enderrmsg(); 634 } 635 r = build(O_MUL, p, build(O_LCON, (long) size(eltype))); 636 r = build(O_ADD, build(O_RVAL, a), r); 637 r->nodetype = eltype; 638 } else if (t->class != ARRAY) { 639 beginerrmsg(); 640 fprintf(stderr, "\""); 641 prtree(stderr, a); 642 fprintf(stderr, "\" is not an array"); 643 enderrmsg(); 644 } else { 645 r = a; 646 p = slist; 647 t = t->chain; 648 for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { 649 esub = p->value.arg[0]; 650 etype = rtype(esub->nodetype); 651 atype = rtype(t); 652 if (not compatible(atype, etype)) { 653 beginerrmsg(); 654 fprintf(stderr, "subscript \""); 655 prtree(stderr, esub); 656 fprintf(stderr, "\" is the wrong type"); 657 enderrmsg(); 658 } 659 r = build(O_INDEX, r, esub); 660 r->nodetype = eltype; 661 } 662 if (p != nil or t != nil) { 663 beginerrmsg(); 664 if (p != nil) { 665 fprintf(stderr, "too many subscripts for \""); 666 } else { 667 fprintf(stderr, "not enough subscripts for \""); 668 } 669 prtree(stderr, a); 670 fprintf(stderr, "\""); 671 enderrmsg(); 672 } 673 } 674 return r; 675 } 676 677 /* 678 * Evaluate a subscript index. 679 */ 680 681 public c_evalaref(s, base, i) 682 Symbol s; 683 Address base; 684 long i; 685 { 686 Symbol t; 687 long lb, ub; 688 689 t = rtype(s); 690 s = t->chain; 691 lb = s->symvalue.rangev.lower; 692 ub = s->symvalue.rangev.upper; 693 if (i < lb or i > ub) { 694 warning("subscript out of range"); 695 } 696 push(long, base + (i - lb) * size(t->type)); 697 } 698 699 /* 700 * Initialize typetable information. 701 */ 702 703 public c_modinit (typetable) 704 Symbol typetable[]; 705 { 706 /* nothing right now */ 707 } 708 709 public boolean c_hasmodules () 710 { 711 return false; 712 } 713 714 public boolean c_passaddr (param, exprtype) 715 Symbol param, exprtype; 716 { 717 boolean b; 718 Symbol t; 719 720 t = rtype(exprtype); 721 b = (boolean) (t->class == ARRAY); 722 return b; 723 } 724