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