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
addcreate(char * s)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
created(char * s)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
dolog(void)71 dolog(void)
72 {
73 if(justcode)
74 return 0;
75 return domod || !doinc || inmain;
76 }
77
78 static char*
curf(void)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*
curm(void)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
setmod(Sym * s)101 setmod(Sym *s)
102 {
103 if(domod && s->mod == nil && ism() && !(doloc && !isloc()))
104 s->mod = curm();
105 }
106
107 char *
outmod(char * buf,int up)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
ism(void)127 ism(void)
128 {
129 return !isb();
130 }
131
132 int
isb(void)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
isloc(void)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*
pushf(void)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
popf(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
setf(File * f,char * s)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
outpush0(char * s,Node * n)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
outpop0(int lno)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
outpush2(char * s,Node * n)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
outpop2(int lno)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
xprint(char * s)328 xprint(char *s)
329 {
330 if(nerrors == 0)
331 print(s);
332 }
333
334 static int tot = 0;
335
336 static void
doindent(int d)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
incind(void)348 incind(void)
349 {
350 indent += INCREMENT;
351 }
352
353 void
decind(void)354 decind(void)
355 {
356 indent -= INCREMENT;
357 }
358
359 int
zeroind(void)360 zeroind(void)
361 {
362 int i = indent;
363
364 indent = 0;
365 return i;
366 }
367
368 void
restoreind(int i)369 restoreind(int i)
370 {
371 indent = i;
372 }
373
374 void
newline0(void)375 newline0(void)
376 {
377 xprint("\n");
378 tot = 0;
379 mylineno++;
380 }
381
382 void
newline(void)383 newline(void)
384 {
385 if(!outcom(1)){
386 xprint("\n");
387 mylineno++;
388 }
389 tot = 0;
390 }
391
392 static void
lprint(char * s)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
prline(char * s)404 prline(char *s)
405 {
406 xprint(s);
407 xprint("\n");
408 mylineno++;
409 }
410
411 void
prdelim(char * s)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
prkeywd(char * kw)425 prkeywd(char *kw)
426 {
427 lprint(kw);
428 }
429
430 void
prid(char * s)431 prid(char *s)
432 {
433 lprint(s);
434 }
435
436 static void
priddol(char * s,int dol)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
prsym(Sym * s,int mod)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
arrow(Sym * s)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
prsym0(Sym * s)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
isprintable(int c)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
hex(int c)526 hex(int c)
527 {
528 if(c < 10)
529 return c+'0';
530 return c+'a'-10;
531 }
532
533 void
prchar0(vlong x,int quote)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
prchar(vlong x)581 prchar(vlong x)
582 {
583 prchar0(x, 1);
584 }
585
586 void
prstr(char * s)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
prlstr(Rune * s)606 prlstr(Rune *s)
607 {
608 lprint("\"");
609 while(*s != 0)
610 prchar0(*s++, 0);
611 lprint("\"");
612 }
613
614 void
prreal(double x,char * s,int b)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
prnum(vlong x,int b,Type * t)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
outcom0(Com * c)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
outcom(int f)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
startcom(int lno)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
addcom(int rr)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
endcom(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
linit()778 linit()
779 {
780 csz = 32;
781 cb = malloc(csz);
782 sysinit();
783 }
784
785 static void
genmsg(void)786 genmsg(void)
787 {
788 prline("#");
789 prline("# initially generated by c2l");
790 prline("#");
791 prline("");
792 }
793
794 void
prcom(char * s,Node * n)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
output(long lno,int com)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
exists(char * f)818 exists(char *f)
819 {
820 int fd;
821
822 fd = open(f, OREAD);
823 close(fd);
824 return fd >= 0;
825 }
826