1 #include "cc.h" 2 3 #define INCREMENT 8 4 #define DEVNULL "/dev/null" 5 6 static int indent = 0; 7 static int fd = -1; 8 static int nf = 0; 9 static int mylineno = 1; 10 11 typedef struct Com{ 12 int lno; 13 char *s; 14 Node *n; 15 int tba; 16 struct Com *nxt; 17 } Com; 18 19 Com *hdc, *curc; 20 21 typedef struct File{ 22 char *s; 23 char *f; 24 char *m; 25 int b; 26 int loc; 27 int in; 28 int tg; 29 Node *n; 30 Com *c; 31 struct File *nxt; 32 } File; 33 34 typedef struct Create{ 35 char *s; 36 struct Create *nxt; 37 } Create; 38 39 File *fs; 40 Create *cs; 41 42 static void genmsg(void); 43 static int isloc(void); 44 45 static void 46 addcreate(char *s) 47 { 48 Create *c; 49 50 if(strcmp(s, DEVNULL) == 0) 51 return; 52 c = (Create*)malloc(sizeof(Create)); 53 c->s = malloc(strlen(s)+1); 54 strcpy(c->s, s); 55 c->nxt = cs; 56 cs = c; 57 } 58 59 static int 60 created(char *s) 61 { 62 Create *c; 63 64 for(c = cs; c != nil; c = c->nxt) 65 if(strcmp(s, c->s) == 0) 66 return 1; 67 return 0; 68 } 69 70 int 71 dolog(void) 72 { 73 if(justcode) 74 return 0; 75 return domod || !doinc || inmain; 76 } 77 78 static char* 79 curf(void) 80 { 81 File *f; 82 83 for(f = fs; f != nil; f = f->nxt) 84 if(f->f != nil) 85 return f->s; 86 return nil; 87 } 88 89 static char* 90 curm(void) 91 { 92 File *f; 93 94 for(f = fs; f != nil; f = f->nxt) 95 if(f->f != nil) 96 return f->m; 97 return nil; 98 } 99 100 void 101 setmod(Sym *s) 102 { 103 if(domod && s->mod == nil && ism() && !(doloc && !isloc())) 104 s->mod = curm(); 105 } 106 107 char * 108 outmod(char *buf, int up) 109 { 110 char *s, *t; 111 112 s = curf(); 113 if(s == nil) 114 return ""; 115 t = strchr(s, '.'); 116 if(t != nil) 117 *t = '\0'; 118 strcpy(buf, s); 119 if(t != nil) 120 *t = '.'; 121 if(up == 1 || (up < 0 && ism())) 122 buf[0] = toupper(buf[0]); 123 return buf; 124 } 125 126 int 127 ism(void) 128 { 129 return !isb(); 130 } 131 132 int 133 isb(void) 134 { 135 File *f; 136 137 for(f = fs; f != nil; f = f->nxt) 138 if(f->f != nil) 139 return f->b; 140 return 0; 141 } 142 143 static int 144 isloc(void) 145 { 146 File *f; 147 148 for(f = fs; f != nil; f = f->nxt) 149 if(f->f != nil) 150 return f->loc; 151 return 0; 152 } 153 154 static File* 155 pushf(void) 156 { 157 static File zfile; 158 File *f; 159 160 f = (File*)malloc(sizeof(File)); 161 *f = zfile; 162 f->s = nil; 163 f->f = nil; 164 f->m = nil; 165 f->nxt = fs; 166 fs = f; 167 return f; 168 } 169 170 static void 171 popf(void) 172 { 173 File *f; 174 175 f = fs; 176 fs = fs->nxt; 177 if(f->s != nil) 178 free(f->s); 179 free(f); 180 } 181 182 static void 183 setf(File *f, char *s) 184 { 185 int n; 186 char *t; 187 188 if(s != nil){ 189 t = strrchr(s, '/'); 190 f->loc = t == nil; 191 if(t != nil) 192 s = t+1; 193 n = strlen(s); 194 f->s = malloc(n+1); 195 strcpy(f->s, s); 196 s = f->s; 197 if(n > 2 && s[n-2] == '.'){ 198 f->m = malloc(n-1); 199 strncpy(f->m, s, n-2); 200 if(s[n-1] == 'h') 201 s[n-1] = 'm'; 202 else if(s[n-1] == 'c'){ 203 s[n-1] = 'b'; 204 f->b = 1; 205 } 206 else 207 s = nil; 208 } 209 else 210 s = nil; 211 if(s == nil){ 212 free(f->s); 213 if(f->m != nil) 214 free(f->m); 215 f->s = nil; 216 f->m = nil; 217 } 218 } 219 f->f = f->s; 220 if(f->s != nil && nf > 0){ 221 if(doinc || doloc && !f->loc) 222 f->f = DEVNULL; 223 else if(!domod) 224 f->f = nil; 225 } 226 } 227 228 void 229 outpush0(char *s, Node *n) 230 { 231 File *f; 232 233 f = pushf(); 234 setf(f, s); 235 if(f->f != nil){ 236 nf++; 237 f->tg = taggen; 238 taggen = 0; 239 f->n = n; 240 f->c = hdc; 241 hdc = nil; 242 } 243 } 244 245 void 246 outpop0(int lno) 247 { 248 File *f; 249 250 USED(lno); 251 f = fs; 252 if(f->f != nil){ 253 nf--; 254 taggen = f->tg; 255 f->n->left = (void*)hdc; 256 hdc = f->c; 257 } 258 popf(); 259 } 260 261 void 262 outpush2(char *s, Node *n) 263 { 264 File *f; 265 266 f = pushf(); 267 setf(f, s); 268 if(f->f != nil){ 269 if(fd >= 0){ 270 newsec(0); 271 close(fd); 272 close(1); 273 fd = -1; 274 } 275 if(created(f->f)) 276 f->f = DEVNULL; /* don't overwrite original if included again */ 277 fd = create(f->f, OWRITE, 0664); 278 if(fd >= 0) 279 addcreate(f->f); 280 mydup(fd, 1); 281 nf++; 282 f->tg = taggen; 283 taggen = 0; 284 f->c = hdc; 285 if(n != Z) 286 hdc = (void*)n->left; 287 else 288 hdc = nil; 289 f->in = indent; 290 indent = 0; 291 genmsg(); 292 pgen(f->b); 293 } 294 } 295 296 void 297 outpop2(int lno) 298 { 299 File *f, *g; 300 301 f = fs; 302 if(f->f != nil){ 303 if(fd >= 0){ 304 newsec(0); 305 output(lno, 1); 306 epgen(f->b); 307 close(fd); 308 close(1); 309 fd = -1; 310 } 311 for(g = fs->nxt; g != nil; g = g->nxt){ 312 if(g->f != nil){ 313 fd = open(g->f, OWRITE); 314 seek(fd, 0, 2); 315 mydup(fd, 1); 316 break; 317 } 318 } 319 nf--; 320 taggen = f->tg; 321 hdc = f->c; 322 indent = f->in; 323 } 324 popf(); 325 } 326 327 static void 328 xprint(char *s) 329 { 330 if(nerrors == 0) 331 print(s); 332 } 333 334 static int tot = 0; 335 336 static void 337 doindent(int d) 338 { 339 int i; 340 341 for(i = 0; i < d/8; i++) 342 xprint("\t"); 343 for(i = 0; i < d%8; i++) 344 xprint(" "); 345 } 346 347 void 348 incind(void) 349 { 350 indent += INCREMENT; 351 } 352 353 void 354 decind(void) 355 { 356 indent -= INCREMENT; 357 } 358 359 int 360 zeroind(void) 361 { 362 int i = indent; 363 364 indent = 0; 365 return i; 366 } 367 368 void 369 restoreind(int i) 370 { 371 indent = i; 372 } 373 374 void 375 newline0(void) 376 { 377 xprint("\n"); 378 tot = 0; 379 mylineno++; 380 } 381 382 void 383 newline(void) 384 { 385 if(!outcom(1)){ 386 xprint("\n"); 387 mylineno++; 388 } 389 tot = 0; 390 } 391 392 static void 393 lprint(char *s) 394 { 395 if(tot == 0) { 396 doindent(indent); 397 tot += indent; 398 } 399 xprint(s); 400 tot += strlen(s); 401 } 402 403 void 404 prline(char *s) 405 { 406 xprint(s); 407 xprint("\n"); 408 mylineno++; 409 } 410 411 void 412 prdelim(char *s) 413 { 414 if(*s == '%'){ 415 if(*++s == '=') 416 lprint("%%="); 417 else 418 lprint("%%"); 419 return; 420 } 421 lprint(s); 422 } 423 424 void 425 prkeywd(char *kw) 426 { 427 lprint(kw); 428 } 429 430 void 431 prid(char *s) 432 { 433 lprint(s); 434 } 435 436 static void 437 priddol(char *s, int dol) 438 { 439 char *t; 440 char buf[128]; 441 442 if(dol){ 443 t = strchr(s, '$'); 444 if(t != nil) 445 *t = '_'; 446 lprint(s); 447 if(t != nil){ 448 strcpy(buf, s); 449 while(slookup(buf)->type != T){ 450 strcat(buf, "x"); 451 lprint("x"); 452 } 453 *t = '$'; 454 } 455 } 456 else 457 lprint(s); 458 } 459 460 void 461 prsym(Sym *s, int mod) 462 { 463 char buf[128]; 464 int c; 465 466 if(mod && s->mod && strcmp(s->mod, curm()) != 0 && (!s->limbo || s->class == CEXTERN)){ 467 c = isconsym(s); 468 if(c >= 0){ 469 if(c){ 470 s->mod[0] = toupper(s->mod[0]); 471 lprint(s->mod); 472 s->mod[0] = tolower(s->mod[0]); 473 } 474 else 475 lprint(s->mod); 476 lprint("->"); 477 usemod(s, !c); 478 } 479 } 480 if(s->lname) 481 prid(s->lname); 482 else{ 483 priddol(s->name, s->class == CSTATIC); 484 if(s->lkw){ 485 strcpy(buf, s->name); 486 for(;;){ 487 strcat(buf, "x"); 488 lprint("x"); 489 s = slookup(buf); 490 if(s->type == T) 491 break; 492 } 493 } 494 } 495 } 496 497 int 498 arrow(Sym *s) 499 { 500 if(s->mod && strcmp(s->mod, curm()) != 0) 501 return isconsym(s) >= 0; 502 return 0; 503 } 504 505 void 506 prsym0(Sym *s) 507 { 508 int c; 509 510 if(s->mod && strcmp(s->mod, curm()) != 0){ 511 c = isconsym(s); 512 if(c >= 0) 513 usemod(s, !c); 514 } 515 } 516 517 static int 518 isprintable(int c) 519 { 520 if(c >= 0x20 && c <= 0x7e) 521 return 1; 522 return c == '\0' || c == '\n' || c == '\t' || c == '\b' || c == '\r' || c == '\f' || c == '\a' || c == '\v'; 523 } 524 525 static int 526 hex(int c) 527 { 528 if(c < 10) 529 return c+'0'; 530 return c+'a'-10; 531 } 532 533 void 534 prchar0(vlong x, int quote) 535 { 536 int c, e, i = 0; 537 static char buf[16]; 538 539 if(quote) 540 buf[i++] = '\''; 541 c = x; 542 if(c < 0 || c > 255 || !isprintable(c)){ 543 if(c&0xffff0000) 544 diag(Z, "character too big"); 545 buf[i++] = '\\'; 546 buf[i++] = 'u'; 547 buf[i++] = hex((c>>12)&0xf); 548 buf[i++] = hex((c>>8)&0xf); 549 buf[i++] = hex((c>>4)&0xf); 550 buf[i++] = hex((c>>0)&0xf); 551 } 552 else{ 553 e = 0; 554 switch(c){ 555 case '\n': e = 'n'; break; 556 case '\t': e = 't'; break; 557 case '\b': e = 'b'; break; 558 case '\r': e = 'r'; break; 559 case '\f': e = 'f'; break; 560 case '\a': e = 'a'; break; 561 case '\v': e = 'v'; break; 562 case '"': if(!quote) e = '"'; break; 563 case '\'': if(quote) e = '\''; break; 564 case '\\': e = '\\'; break; 565 case '%': buf[i++] = c; break; 566 case 0: e = '0'; if(strings) prcom("nul byte in string ?", Z); break; 567 } 568 if(e != 0){ 569 buf[i++] = '\\'; 570 c = e; 571 } 572 buf[i++] = c; 573 } 574 if(quote) 575 buf[i++] = '\''; 576 buf[i] = '\0'; 577 lprint(buf); 578 } 579 580 void 581 prchar(vlong x) 582 { 583 prchar0(x, 1); 584 } 585 586 void 587 prstr(char *s) 588 { 589 uchar *t; 590 Rune r; 591 592 t = (uchar*)s; 593 lprint("\""); 594 while(*t != 0){ 595 if(*t & 0x80){ 596 t += chartorune(&r, (char*)t); 597 prchar0(r, 0); 598 } 599 else 600 prchar0(*t++, 0); 601 } 602 lprint("\""); 603 } 604 605 void 606 prlstr(Rune *s) 607 { 608 lprint("\""); 609 while(*s != 0) 610 prchar0(*s++, 0); 611 lprint("\""); 612 } 613 614 void 615 prreal(double x, char *s, int b) 616 { 617 static char buf[128]; 618 619 if(b != KDEC) 620 diag(Z, "not base 10 in prreal"); 621 if(s != nil) 622 lprint(s); 623 else{ 624 sprint(buf, "%f", x); 625 lprint(buf); 626 } 627 } 628 629 void 630 prnum(vlong x, int b, Type *t) 631 { 632 static char buf[128]; 633 int w; 634 vlong m; 635 636 w = 4; 637 if(t != T) 638 w = ewidth[t->etype]; 639 m = MASK(8*w); 640 if(b == KHEX) 641 sprint(buf, "16r%llux", x&m); 642 else if(b == KOCT) 643 sprint(buf, "8r%lluo", x&m); 644 else 645 sprint(buf, "%lld", x); 646 lprint(buf); 647 } 648 649 char *cb; 650 int cn, csz; 651 652 static void 653 outcom0(Com *c) 654 { 655 Node *n; 656 char *s, *t, *u; 657 658 s = c->s; 659 n = c->n; 660 if(comm && c->tba){ 661 t = strchr(s, '\n'); 662 *t = '\0'; 663 fprint(2, "%s:%d: %s", curf(), mylineno, s); 664 *t = '\n'; 665 if(n != Z){ 666 mydup(2, 1); 667 expgen(n); 668 mydup(fd, 1); 669 } 670 fprint(2, "\n"); 671 } 672 while(*s != '\0'){ 673 t = strchr(s, '\n'); 674 *t = '\0'; 675 if(tot != 0) 676 prdelim("\t"); 677 prdelim("# "); 678 while((u = strchr(s, '%')) != nil){ 679 /* do not let print interpret % ! */ 680 *u = 0; 681 lprint(s); 682 *u = '%'; 683 lprint("%%"); 684 s = u+1; 685 } 686 lprint(s); 687 if(n == Z) 688 newline0(); 689 *t = '\n'; 690 s = t+1; 691 } 692 if(n != Z){ 693 expgen(n); 694 newline0(); 695 } 696 } 697 698 int 699 outcom(int f) 700 { 701 int lno, nl; 702 Com *c; 703 704 nl = 0; 705 lno = pline+f; 706 c = hdc; 707 while(c != nil && c->lno < lno){ 708 /* print("outcom: %d < %d (f=%d)\n", c->lno, lno, f); */ 709 nl = 1; 710 outcom0(c); 711 hdc = hdc->nxt; 712 free(c->s); 713 free(c); 714 c = hdc; 715 } 716 return nl; 717 } 718 719 void 720 startcom(int lno) 721 { 722 Com *c, **ac; 723 724 c = (Com *)malloc(sizeof(Com)); 725 c->lno = lno; 726 c->s = nil; 727 c->n = Z; 728 c->tba = 0; 729 c->nxt = nil; 730 for(ac = &hdc; *ac != nil && (*ac)->lno <= lno; ac = &(*ac)->nxt) 731 ; 732 c->nxt = *ac; 733 curc = *ac = c; 734 } 735 736 void 737 addcom(int rr) 738 { 739 int i, nb; 740 char *ncb; 741 char s[UTFmax]; 742 Rune r[1]; 743 744 if(rr >= Runeself){ 745 r[0] = rr; 746 nb = runetochar(s, r); 747 } 748 else{ 749 nb = 1; 750 s[0] = rr; 751 } 752 if(cn+nb-1 >= csz){ 753 csz += 32; 754 ncb = malloc(csz); 755 memcpy(ncb, cb, cn); 756 free(cb); 757 cb = ncb; 758 } 759 for(i = 0; i < nb; i++) 760 cb[cn++] = s[i]; 761 } 762 763 void 764 endcom(void) 765 { 766 char *s; 767 768 addcom('\n'); 769 addcom('\0'); 770 s = malloc(strlen(cb)+1); 771 strcpy(s, cb); 772 curc->s = s; 773 /* print("com %d %s\n", curc->lno, s); */ 774 cn = 0; 775 } 776 777 void 778 linit() 779 { 780 csz = 32; 781 cb = malloc(csz); 782 sysinit(); 783 } 784 785 static void 786 genmsg(void) 787 { 788 prline("#"); 789 prline("# initially generated by c2l"); 790 prline("#"); 791 prline(""); 792 } 793 794 void 795 prcom(char *s, Node *n) 796 { 797 Com *c; 798 799 startcom(pline); 800 c = curc; 801 sprint(cb, "TBA %s", s); 802 cn = strlen(cb); 803 c->n = n; 804 c->tba = 1; 805 endcom(); 806 } 807 808 void 809 output(long lno, int com) 810 { 811 /* print("output(%ld)\n", lno); */ 812 pline = lno; 813 if(com) 814 outcom(0); 815 } 816 817 int 818 exists(char *f) 819 { 820 int fd; 821 822 fd = open(f, OREAD); 823 close(fd); 824 return fd >= 0; 825 } 826