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