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