1 #include "c.h"
2 
3 
outs(const char * str,FILE * f,char * bp)4 static char *outs(const char *str, FILE *f, char *bp) {
5 	if (f)
6 		fputs(str, f);
7 	else
8 		while ((*bp = *str++))
9 			bp++;
10 	return bp;
11 }
12 
outd(long n,FILE * f,char * bp)13 static char *outd(long n, FILE *f, char *bp) {
14 	unsigned long m;
15 	char buf[25], *s = buf + sizeof buf;
16 
17 	*--s = '\0';
18 	if (n < 0)
19 		m = -n;
20 	else
21 		m = n;
22 	do
23 		*--s = m%10 + '0';
24 	while ((m /= 10) != 0);
25 	if (n < 0)
26 		*--s = '-';
27 	return outs(s, f, bp);
28 }
29 
outu(unsigned long n,int base,FILE * f,char * bp)30 static char *outu(unsigned long n, int base, FILE *f, char *bp) {
31 	char buf[25], *s = buf + sizeof buf;
32 
33 	*--s = '\0';
34 	do
35 		*--s = "0123456789abcdef"[n%base];
36 	while ((n /= base) != 0);
37 	return outs(s, f, bp);
38 }
print(const char * fmt,...)39 void print(const char *fmt, ...) {
40 	va_list ap;
41 
42 	va_start(ap, fmt);
43 	vfprint(stdout, NULL, fmt, ap);
44 	va_end(ap);
45 }
46 /* fprint - formatted output to  f */
fprint(FILE * f,const char * fmt,...)47 void fprint(FILE *f, const char *fmt, ...) {
48 	va_list ap;
49 
50 	va_start(ap, fmt);
51 	vfprint(f, NULL, fmt, ap);
52 	va_end(ap);
53 }
54 
55 /* stringf - formatted output to a saved string */
stringf(const char * fmt,...)56 char *stringf(const char *fmt, ...) {
57 	char buf[1024];
58 	va_list ap;
59 
60 	va_start(ap, fmt);
61 	vfprint(NULL, buf, fmt, ap);
62 	va_end(ap);
63 	return string(buf);
64 }
65 
66 /* vfprint - formatted output to f or string bp */
vfprint(FILE * f,char * bp,const char * fmt,va_list ap)67 void vfprint(FILE *f, char *bp, const char *fmt, va_list ap) {
68 	for (; *fmt; fmt++)
69 		if (*fmt == '%')
70 			switch (*++fmt) {
71 			case 'd': bp = outd(va_arg(ap, int), f, bp); break;
72 			case 'D': bp = outd(va_arg(ap, long), f, bp); break;
73 			case 'U': bp = outu(va_arg(ap, unsigned long), 10, f, bp); break;
74 			case 'u': bp = outu(va_arg(ap, unsigned), 10, f, bp); break;
75 			case 'o': bp = outu(va_arg(ap, unsigned), 8, f, bp); break;
76 			case 'X': bp = outu(va_arg(ap, unsigned long), 16, f, bp); break;
77 			case 'x': bp = outu(va_arg(ap, unsigned), 16, f, bp); break;
78 			case 'f': case 'e':
79 			case 'g': {
80 				  	static char format[] = "%f";
81 				  	char buf[128];
82 				  	format[1] = *fmt;
83 				  	sprintf(buf, format, va_arg(ap, double));
84 				  	bp = outs(buf, f, bp);
85 				  }
86 ; break;
87 			case 's': bp = outs(va_arg(ap, char *), f, bp); break;
88 			case 'p': {
89 				void *p = va_arg(ap, void *);
90 				if (p)
91 					bp = outs("0x", f, bp);
92 				bp = outu((unsigned long)p, 16, f, bp);
93 				break;
94 				  }
95 			case 'c': if (f) fputc(va_arg(ap, int), f); else *bp++ = va_arg(ap, int); break;
96 			case 'S': { char *s = va_arg(ap, char *);
97 				    int n = va_arg(ap, int);
98 				    if (s) {
99 				    	for ( ; n-- > 0; s++)
100 				    		if (f) (void)putc(*s, f); else *bp++ = *s;
101 				    }
102  } break;
103 			case 'k': { int t = va_arg(ap, int);
104 				    static char *tokens[] = {
105 #define xx(a,b,c,d,e,f,g) g,
106 #define yy(a,b,c,d,e,f,g) g,
107 #include "token.h"
108 				    };
109 				    assert(tokens[t&0177]);
110 				    bp = outs(tokens[t&0177], f, bp);
111  } break;
112 			case 't': { Type ty = va_arg(ap, Type);
113 				    assert(f);
114 				    outtype(ty ? ty : voidtype, f);
115  } break;
116 			case 'w': { Coordinate *p = va_arg(ap, Coordinate *);
117 				    if (p->file && *p->file) {
118 				    	bp = outs(p->file, f, bp);
119 				    	bp = outs(":", f, bp);
120 				    }
121 				    bp = outd(p->y, f, bp);
122  } break;
123 			case 'I': { int n = va_arg(ap, int);
124 				    while (--n >= 0)
125 				    	if (f) (void)putc(' ', f); else *bp++ = ' ';
126  } break;
127 			default:  if (f) (void)putc(*fmt, f); else *bp++ = *fmt; break;
128 			}
129 		else if (f)
130 			(void)putc(*fmt, f);
131 		else
132 			*bp++ = *fmt;
133 	if (!f)
134 		*bp = '\0';
135 }
136