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