xref: /inferno-os/utils/c2l/out.c (revision 1981fff245dfce579ef416fa767eb69d462039e9)
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