]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/bitsy/donprint.c
merge
[plan9front.git] / sys / src / boot / bitsy / donprint.c
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
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
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*
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
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
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
254 noconv(Op *op)
255 {
256
257         strconv("***", op, 0, -1);
258         return 0;
259 }
260
261 static  int
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
273 dconv(Op *op)
274 {
275         return numbconv(op, 10);
276 }
277
278 static  int
279 hconv(Op*)
280 {
281         return -FSHORT;
282 }
283
284 static  int
285 lconv(Op*)
286 {
287         return -FLONG;
288 }
289
290 static  int
291 oconv(Op *op)
292 {
293         return numbconv(op, 8);
294 }
295
296 static  int
297 sconv(Op *op)
298 {
299         strconv(*(char**)op->argp, op, op->f1, op->f2);
300         return PTR;
301 }
302
303 static  int
304 uconv(Op*)
305 {
306         return -FUNSIGN;
307 }
308
309 static  int
310 xconv(Op *op)
311 {
312         return numbconv(op, 16);
313 }
314
315 static  int
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
327 percent(Op *op)
328 {
329
330         PUT(op, '%');
331         return 0;
332 }