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