1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)c.c 1.2 12/15/82"; 4 5 /* 6 * C-dependent symbol routines. 7 */ 8 9 #include "defs.h" 10 #include "symbols.h" 11 #include "printsym.h" 12 #include "languages.h" 13 #include "c.h" 14 #include "tree.h" 15 #include "eval.h" 16 #include "operators.h" 17 #include "mappings.h" 18 #include "process.h" 19 #include "runtime.h" 20 #include "machine.h" 21 22 #define isdouble(range) ( \ 23 range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \ 24 ) 25 26 #define isrange(t, name) (t->class == RANGE and istypename(t->type, name)) 27 28 /* 29 * Initialize C language information. 30 */ 31 32 public c_init() 33 { 34 Language lang; 35 36 lang = language_define("c", ".c"); 37 language_setop(lang, L_PRINTDECL, c_printdecl); 38 language_setop(lang, L_PRINTVAL, c_printval); 39 language_setop(lang, L_TYPEMATCH, c_typematch); 40 } 41 42 /* 43 * Test if two types are compatible. 44 * 45 * Integers and reals are not compatible since they cannot always be mixed. 46 */ 47 48 public Boolean c_typematch(type1, type2) 49 Symbol type1, type2; 50 { 51 Boolean b; 52 register Symbol t1, t2, tmp; 53 54 t1 = type1; 55 t2 = type2; 56 if (t1 == t2) { 57 b = true; 58 } else { 59 t1 = rtype(t1); 60 t2 = rtype(t2); 61 if (t1->type == t_int or t1->type == t_char) { 62 tmp = t1; 63 t1 = t2; 64 t2 = tmp; 65 } 66 b = (Boolean) ( 67 ( 68 isrange(t1, "int") and 69 (t2->type == t_int or t2->type == t_char) 70 ) or ( 71 isrange(t1, "char") and 72 (t2->type == t_char or t2->type == t_int) 73 ) or ( 74 t1->type == t2->type and ( 75 (t1->class == t2->class) or 76 (t1->class == SCAL and t2->class == CONST) or 77 (t1->class == CONST and t2->class == SCAL) 78 ) 79 ) 80 ); 81 } 82 return b; 83 } 84 85 /* 86 * Decide if a field is a bit field. 87 */ 88 89 private Boolean isbitfield(s) 90 register Symbol s; 91 { 92 Boolean b; 93 register Integer off, len; 94 register Symbol t; 95 96 off = s->symvalue.field.offset; 97 len = s->symvalue.field.length; 98 if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { 99 b = true; 100 } else { 101 t = rtype(s->type); 102 b = (Boolean) 103 (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE) or 104 len != (size(t)*BITSPERBYTE) 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, ord %ld)", 139 s->symvalue.iconval); 140 } else { 141 printf("const %s = ", symname(s)); 142 printval(s); 143 } 144 break; 145 146 case TYPE: 147 case VAR: 148 if (s->class != TYPE) { 149 if (s->level == 2) { 150 printf("static "); 151 } else if (s->level < 0) { 152 printf("register "); 153 } 154 } 155 if (s->type->class == ARRAY) { 156 printtype(s->type, s->type->type, indent); 157 t = rtype(s->type->chain); 158 assert(t->class == RANGE); 159 printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); 160 } else { 161 printtype(s, s->type, indent); 162 if (s->type->class != PTR) { 163 printf(" "); 164 } 165 printf("%s", symname(s)); 166 } 167 break; 168 169 case FIELD: 170 if (s->type->class == ARRAY) { 171 printtype(s->type, s->type->type, indent); 172 t = rtype(s->type->chain); 173 assert(t->class == RANGE); 174 printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); 175 } else { 176 printtype(s, s->type, indent); 177 if (s->type->class != PTR) { 178 printf(" "); 179 } 180 printf("%s", symname(s)); 181 } 182 if (isbitfield(s)) { 183 printf(" : %d", s->symvalue.field.length); 184 } 185 break; 186 187 case TAG: 188 if (s->type == nil) { 189 findtype(s); 190 if (s->type == nil) { 191 error("unexpected missing type information"); 192 } 193 } 194 printtype(s, s->type, indent); 195 break; 196 197 case RANGE: 198 case ARRAY: 199 case RECORD: 200 case VARNT: 201 case PTR: 202 semicolon = false; 203 printtype(s, s, indent); 204 break; 205 206 case PROC: 207 semicolon = false; 208 printf("%s", symname(s)); 209 c_listparams(s); 210 newline = false; 211 break; 212 213 case FUNC: 214 semicolon = false; 215 if (not istypename(s->type, "void")) { 216 printtype(s, s->type, indent); 217 printf(" "); 218 } 219 printf("%s", symname(s)); 220 c_listparams(s); 221 newline = false; 222 break; 223 224 case MODULE: 225 semicolon = false; 226 printf("source file \"%s.c\"", symname(s)); 227 break; 228 229 case PROG: 230 semicolon = false; 231 printf("executable file \"%s\"", symname(s)); 232 break; 233 234 default: 235 error("class %s in c_printdecl", classname(s)); 236 } 237 if (semicolon) { 238 putchar(';'); 239 } 240 if (newline) { 241 putchar('\n'); 242 } 243 } 244 245 /* 246 * Recursive whiz-bang procedure to print the type portion 247 * of a declaration. 248 * 249 * The symbol associated with the type is passed to allow 250 * searching for type names without getting "type blah = blah". 251 */ 252 253 private printtype(s, t, indent) 254 Symbol s; 255 Symbol t; 256 Integer indent; 257 { 258 register Symbol i; 259 long r0, r1; 260 register String p; 261 262 checkref(s); 263 checkref(t); 264 switch (t->class) { 265 case VAR: 266 case CONST: 267 case PROC: 268 panic("printtype: class %s", classname(t)); 269 break; 270 271 case ARRAY: 272 printf("array["); 273 i = t->chain; 274 if (i != nil) { 275 for (;;) { 276 printtype(i, i, indent); 277 i = i->chain; 278 if (i == nil) { 279 break; 280 } 281 printf(", "); 282 } 283 } 284 printf("] of "); 285 printtype(t, t->type, indent); 286 break; 287 288 case RECORD: 289 case VARNT: 290 printf("%s ", c_classname(t)); 291 if (s->name != nil and s->class == TAG) { 292 p = symname(s); 293 if (p[0] == '$' and p[1] == '$') { 294 printf("%s ", &p[2]); 295 } else { 296 printf("%s ", p); 297 } 298 } 299 printf("{\n", t->class == RECORD ? "struct" : "union"); 300 for (i = t->chain; i != nil; i = i->chain) { 301 assert(i->class == FIELD); 302 printdecl(i, indent+4); 303 } 304 if (indent > 0) { 305 printf("%*c", indent, ' '); 306 } 307 printf("}"); 308 break; 309 310 case RANGE: 311 r0 = t->symvalue.rangev.lower; 312 r1 = t->symvalue.rangev.upper; 313 if (istypename(t->type, "char")) { 314 if (r0 < 0x20 or r0 > 0x7e) { 315 printf("%ld..", r0); 316 } else { 317 printf("'%c'..", (char) r0); 318 } 319 if (r1 < 0x20 or r1 > 0x7e) { 320 printf("\\%lo", r1); 321 } else { 322 printf("'%c'", (char) r1); 323 } 324 } else if (r0 > 0 and r1 == 0) { 325 printf("%ld byte real", r0); 326 } else if (r0 >= 0) { 327 printf("%lu..%lu", r0, r1); 328 } else { 329 printf("%ld..%ld", r0, r1); 330 } 331 break; 332 333 case PTR: 334 printtype(t, t->type, indent); 335 if (t->type->class != PTR) { 336 printf(" "); 337 } 338 printf("*"); 339 break; 340 341 case FUNC: 342 printtype(t, t->type, indent); 343 printf("()"); 344 break; 345 346 case TYPE: 347 if (t->name != nil) { 348 printname(stdout, t); 349 } else { 350 printtype(t, t->type, indent); 351 } 352 break; 353 354 case TYPEREF: 355 printf("@%s", symname(t)); 356 break; 357 358 case SCAL: 359 printf("enum "); 360 if (s->name != nil and s->class == TAG) { 361 printf("%s ", symname(s)); 362 } 363 printf("{ "); 364 i = t->chain; 365 if (i != nil) { 366 for (;;) { 367 printf("%s", symname(i)); 368 i = i->chain; 369 if (i == nil) break; 370 printf(", "); 371 } 372 } 373 printf(" }"); 374 break; 375 376 case TAG: 377 if (t->type == nil) { 378 printf("unresolved tag %s", symname(t)); 379 } else { 380 i = rtype(t->type); 381 printf("%s %s", c_classname(i), symname(t)); 382 } 383 break; 384 385 default: 386 printf("(class %d)", t->class); 387 break; 388 } 389 } 390 391 /* 392 * List the parameters of a procedure or function. 393 * No attempt is made to combine like types. 394 */ 395 396 public c_listparams(s) 397 Symbol s; 398 { 399 register Symbol t; 400 401 putchar('('); 402 for (t = s->chain; t != nil; t = t->chain) { 403 printf("%s", symname(t)); 404 if (t->chain != nil) { 405 printf(", "); 406 } 407 } 408 putchar(')'); 409 if (s->chain != nil) { 410 printf("\n"); 411 for (t = s->chain; t != nil; t = t->chain) { 412 if (t->class != VAR) { 413 panic("unexpected class %d for parameter", t->class); 414 } 415 printdecl(t, 0); 416 } 417 } else { 418 putchar('\n'); 419 } 420 } 421 422 /* 423 * Print out the value on the top of the expression stack 424 * in the format for the type of the given symbol. 425 */ 426 427 public c_printval(s) 428 Symbol s; 429 { 430 register Symbol t; 431 register Address a; 432 register int i, len; 433 434 switch (s->class) { 435 case CONST: 436 case TYPE: 437 case VAR: 438 case REF: 439 case FVAR: 440 case TAG: 441 c_printval(s->type); 442 break; 443 444 case FIELD: 445 if (isbitfield(s)) { 446 len = s->symvalue.field.length; 447 if (len <= BITSPERBYTE) { 448 i = pop(char); 449 } else if (len <= sizeof(short)*BITSPERBYTE) { 450 i = pop(short); 451 } else { 452 i = pop(long); 453 } 454 i >>= (s->symvalue.field.offset mod BITSPERBYTE); 455 i &= ((1 << len) - 1); 456 t = rtype(s->type); 457 if (t->class == SCAL) { 458 printenum(i, t); 459 } else { 460 printrange(i, t); 461 } 462 } else { 463 c_printval(s->type); 464 } 465 break; 466 467 case ARRAY: 468 t = rtype(s->type); 469 if (t->class == RANGE and istypename(t->type, "char")) { 470 len = size(s); 471 sp -= len; 472 printf("\"%.*s\"", len, sp); 473 } else { 474 printarray(s); 475 } 476 break; 477 478 case RECORD: 479 case VARNT: 480 c_printstruct(s); 481 break; 482 483 case RANGE: 484 if (istypename(s->type, "boolean")) { 485 printrange(popsmall(s), s); 486 } else if (istypename(s->type, "char")) { 487 printrange(pop(char), s); 488 } else if (isdouble(s)) { 489 switch (s->symvalue.rangev.lower) { 490 case sizeof(float): 491 prtreal(pop(float)); 492 break; 493 494 case sizeof(double): 495 prtreal(pop(double)); 496 break; 497 498 default: 499 panic("bad real size %d", t->symvalue.rangev.lower); 500 break; 501 } 502 } else { 503 printrange(popsmall(s), s); 504 } 505 break; 506 507 case PTR: 508 t = rtype(s->type); 509 a = pop(Address); 510 if (a == 0) { 511 printf("(nil)"); 512 } else if (t->class == RANGE and istypename(t->type, "char")) { 513 printstring(a); 514 } else { 515 printf("0x%x", a); 516 } 517 break; 518 519 case SCAL: 520 i = pop(Integer); 521 printenum(i, s); 522 break; 523 524 default: 525 if (ord(s->class) > ord(TYPEREF)) { 526 panic("printval: bad class %d", ord(s->class)); 527 } 528 error("don't know how to print a %s", c_classname(s)); 529 /* NOTREACHED */ 530 } 531 } 532 533 /* 534 * Print out a C structure. 535 */ 536 537 private c_printstruct(s) 538 Symbol s; 539 { 540 register Symbol f; 541 register Stack *savesp; 542 register Integer n, off, len; 543 544 sp -= size(s); 545 savesp = sp; 546 printf("("); 547 f = s->chain; 548 for (;;) { 549 off = f->symvalue.field.offset; 550 len = f->symvalue.field.length; 551 n = (off + len + 7) div BITSPERBYTE; 552 sp += n; 553 printf("%s = ", symname(f)); 554 c_printval(f); 555 sp = savesp; 556 f = f->chain; 557 if (f == nil) break; 558 printf(", "); 559 } 560 printf(")"); 561 } 562 563 /* 564 * Print out a range type (integer, char, or boolean). 565 */ 566 567 private printrange(i, t) 568 Integer i; 569 register Symbol t; 570 { 571 if (istypename(t->type, "boolean")) { 572 printf(((Boolean) i) == true ? "true" : "false"); 573 } else if (istypename(t->type, "char")) { 574 putchar('\''); 575 printchar(i); 576 putchar('\''); 577 } else if (t->symvalue.rangev.lower >= 0) { 578 printf("%lu", i); 579 } else { 580 printf("%ld", i); 581 } 582 } 583 584 /* 585 * Print out a null-terminated string (pointer to char) 586 * starting at the given address. 587 */ 588 589 private printstring(addr) 590 Address addr; 591 { 592 register Address a; 593 register Integer i, len; 594 register Boolean endofstring; 595 union { 596 char ch[sizeof(Word)]; 597 int word; 598 } u; 599 600 putchar('"'); 601 a = addr; 602 endofstring = false; 603 while (not endofstring) { 604 dread(&u, a, sizeof(u)); 605 i = 0; 606 do { 607 if (u.ch[i] == '\0') { 608 endofstring = true; 609 } else { 610 printchar(u.ch[i]); 611 } 612 ++i; 613 } while (i < sizeof(Word) and not endofstring); 614 a += sizeof(Word); 615 } 616 putchar('"'); 617 } 618 619 /* 620 * Print out an enumerated value by finding the corresponding 621 * name in the enumeration list. 622 */ 623 624 private printenum(i, t) 625 Integer i; 626 Symbol t; 627 { 628 register Symbol e; 629 630 e = t->chain; 631 while (e != nil and e->symvalue.iconval != i) { 632 e = e->chain; 633 } 634 if (e != nil) { 635 printf("%s", symname(e)); 636 } else { 637 printf("%d", i); 638 } 639 } 640 641 /* 642 * Return the C name for the particular class of a symbol. 643 */ 644 645 public String c_classname(s) 646 Symbol s; 647 { 648 String str; 649 650 switch (s->class) { 651 case RECORD: 652 str = "struct"; 653 break; 654 655 case VARNT: 656 str = "union"; 657 break; 658 659 case SCAL: 660 str = "enum"; 661 break; 662 663 default: 664 str = classname(s); 665 } 666 return str; 667 } 668