xref: /plan9/sys/src/cmd/disk/kfs/print.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1 #include	"all.h"
2 
3 #define	PTR	sizeof(char*)
4 #define	SHORT	sizeof(int)
5 #define	INT	sizeof(int)
6 #define	LONG	sizeof(long)
7 #define	IDIGIT	30
8 #define	MAXCON	30
9 
10 static	int	convcount  = { 10 };
11 
12 #define	PUT(o, c)	if((o)->p < (o)->ep) *(o)->p++ = c
13 
14 static	int	noconv(Op*);
15 static	int	cconv(Op*);
16 static	int	dconv(Op*);
17 static	int	hconv(Op*);
18 static	int	lconv(Op*);
19 static	int	oconv(Op*);
20 static	int	sconv(Op*);
21 static	int	uconv(Op*);
22 static	int	xconv(Op*);
23 static	int	percent(Op*);
24 
25 static
26 int	(*fmtconv[MAXCON])(Op*) =
27 {
28 	noconv,
29 	cconv, dconv, hconv, lconv,
30 	oconv, sconv, uconv, xconv,
31 	percent,
32 };
33 static
34 char	fmtindex[128] =
35 {
36 	['c'] 1,
37 	['d'] 2,
38 	['h'] 3,
39 	['l'] 4,
40 	['o'] 5,
41 	['s'] 6,
42 	['u'] 7,
43 	['x'] 8,
44 	['%'] 9,
45 };
46 
47 int
fmtinstall(char c,int (* f)(Op *))48 fmtinstall(char c, int (*f)(Op*))
49 {
50 
51 	c &= 0177;
52 	if(fmtindex[c] == 0) {
53 		if(convcount >= MAXCON)
54 			return 1;
55 		fmtindex[c] = convcount++;
56 	}
57 	fmtconv[fmtindex[c]] = f;
58 	return 0;
59 }
60 
61 char*
doprint(char * p,char * ep,char * fmt,void * argp)62 doprint(char *p, char *ep, char *fmt, void *argp)
63 {
64 	int sf1, c;
65 	Op o;
66 
67 	o.p = p;
68 	o.ep = ep;
69 	o.argp = argp;
70 
71 loop:
72 	c = *fmt++;
73 	if(c != '%') {
74 		if(c == 0) {
75 			if(o.p < o.ep)
76 				*o.p = 0;
77 			return o.p;
78 		}
79 		PUT(&o, c);
80 		goto loop;
81 	}
82 	o.f1 = 0;
83 	o.f2 = -1;
84 	o.f3 = 0;
85 	c = *fmt++;
86 	sf1 = 0;
87 	if(c == '-') {
88 		sf1 = 1;
89 		c = *fmt++;
90 	}
91 	while(c >= '0' && c <= '9') {
92 		o.f1 = o.f1*10 + c-'0';
93 		c = *fmt++;
94 	}
95 	if(sf1)
96 		o.f1 = -o.f1;
97 	if(c != '.')
98 		goto l1;
99 	c = *fmt++;
100 	while(c >= '0' && c <= '9') {
101 		if(o.f2 < 0)
102 			o.f2 = 0;
103 		o.f2 = o.f2*10 + c-'0';
104 		c = *fmt++;
105 	}
106 l1:
107 	if(c == 0)
108 		fmt--;
109 	c = (*fmtconv[fmtindex[c&0177]])(&o);
110 	if(c < 0) {
111 		o.f3 |= -c;
112 		c = *fmt++;
113 		goto l1;
114 	}
115 	o.argp = (char*)o.argp + c;
116 	goto loop;
117 }
118 
119 int
numbconv(Op * op,int base)120 numbconv(Op *op, int base)
121 {
122 	char b[IDIGIT];
123 	int i, f, n, r;
124 	long v;
125 	short h;
126 
127 	f = 0;
128 	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
129 	case FLONG:
130 		v = *(long*)op->argp;
131 		r = LONG;
132 		break;
133 
134 	case FUNSIGN|FLONG:
135 		v = *(ulong*)op->argp;
136 		r = LONG;
137 		break;
138 
139 	case FSHORT:
140 		h = *(int*)op->argp;
141 		v = h;
142 		r = SHORT;
143 		break;
144 
145 	case FUNSIGN|FSHORT:
146 		h = *(int*)op->argp;
147 		v = (ushort)h;
148 		r = SHORT;
149 		break;
150 
151 	default:
152 		v = *(int*)op->argp;
153 		r = INT;
154 		break;
155 
156 	case FUNSIGN:
157 		v = *(unsigned*)op->argp;
158 		r = INT;
159 		break;
160 	}
161 	if(!(op->f3 & FUNSIGN) && v < 0) {
162 		v = -v;
163 		f = 1;
164 	}
165 	b[IDIGIT-1] = 0;
166 	for(i = IDIGIT-2;; i--) {
167 		n = (ulong)v % base;
168 		n += '0';
169 		if(n > '9')
170 			n += 'a' - ('9'+1);
171 		b[i] = n;
172 		if(i < 2)
173 			break;
174 		v = (ulong)v / base;
175 		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
176 			continue;
177 		if(v <= 0)
178 			break;
179 	}
180 sout:
181 	if(f)
182 		b[--i] = '-';
183 	strconv(b+i, op, op->f1, -1);
184 	return r;
185 }
186 
187 void
strconv(char * o,Op * op,int f1,int f2)188 strconv(char *o, Op *op, int f1, int f2)
189 {
190 	int n, c;
191 	char *p;
192 
193 	n = strlen(o);
194 	if(f1 >= 0)
195 		while(n < f1) {
196 			PUT(op, ' ');
197 			n++;
198 		}
199 	for(p=o; c = *p++;)
200 		if(f2 != 0) {
201 			PUT(op, c);
202 			f2--;
203 		}
204 	if(f1 < 0) {
205 		f1 = -f1;
206 		while(n < f1) {
207 			PUT(op, ' ');
208 			n++;
209 		}
210 	}
211 }
212 
213 static	int
noconv(Op * op)214 noconv(Op *op)
215 {
216 
217 	strconv("***", op, 0, -1);
218 	return 0;
219 }
220 
221 static	int
cconv(Op * op)222 cconv(Op *op)
223 {
224 	char b[2];
225 
226 	b[0] = *(int*)op->argp;
227 	b[1] = 0;
228 	strconv(b, op, op->f1, -1);
229 	return INT;
230 }
231 
232 static	int
dconv(Op * op)233 dconv(Op *op)
234 {
235 
236 	return numbconv(op, 10);
237 }
238 
239 static	int
hconv(Op * op)240 hconv(Op *op)
241 {
242 	USED(op);
243 	return -FSHORT;
244 }
245 
246 static	int
lconv(Op * op)247 lconv(Op *op)
248 {
249 	USED(op);
250 	return -FLONG;
251 }
252 
253 static	int
oconv(Op * op)254 oconv(Op *op)
255 {
256 	USED(op);
257 	return numbconv(op, 8);
258 }
259 
260 static	int
sconv(Op * op)261 sconv(Op *op)
262 {
263 
264 	strconv(*(char**)op->argp, op, op->f1, op->f2);
265 	return PTR;
266 }
267 
268 static	int
uconv(Op * op)269 uconv(Op *op)
270 {
271 	USED(op);
272 	return -FUNSIGN;
273 }
274 
275 static	int
xconv(Op * op)276 xconv(Op *op)
277 {
278 
279 	return numbconv(op, 16);
280 }
281 
282 static	int
percent(Op * op)283 percent(Op *op)
284 {
285 
286 	PUT(op, '%');
287 	return 0;
288 }
289