Introduction
Introduction Statistics Contact Development Disclaimer Help
dofmt.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
dofmt.c (11231B)
---
1 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2 /* Copyright (c) 2004 Google Inc.; see LICENSE */
3
4 #include <stdarg.h>
5 #include <string.h>
6 #include "plan9.h"
7 #include "fmt.h"
8 #include "fmtdef.h"
9
10 /* format the output into f->to and return the number of characters fmte…
11 int
12 dofmt(Fmt *f, char *fmt)
13 {
14 Rune rune, *rt, *rs;
15 int r;
16 char *t, *s;
17 int n, nfmt;
18
19 nfmt = f->nfmt;
20 for(;;){
21 if(f->runes){
22 rt = (Rune*)f->to;
23 rs = (Rune*)f->stop;
24 while((r = *(uchar*)fmt) && r != '%'){
25 if(r < Runeself)
26 fmt++;
27 else{
28 fmt += chartorune(&rune, fmt);
29 r = rune;
30 }
31 FMTRCHAR(f, rt, rs, r);
32 }
33 fmt++;
34 f->nfmt += rt - (Rune *)f->to;
35 f->to = rt;
36 if(!r)
37 return f->nfmt - nfmt;
38 f->stop = rs;
39 }else{
40 t = (char*)f->to;
41 s = (char*)f->stop;
42 while((r = *(uchar*)fmt) && r != '%'){
43 if(r < Runeself){
44 FMTCHAR(f, t, s, r);
45 fmt++;
46 }else{
47 n = chartorune(&rune, fmt);
48 if(t + n > s){
49 t = (char*)__fmtflush(f,…
50 if(t != nil)
51 s = (char*)f->st…
52 else
53 return -1;
54 }
55 while(n--)
56 *t++ = *fmt++;
57 }
58 }
59 fmt++;
60 f->nfmt += t - (char *)f->to;
61 f->to = t;
62 if(!r)
63 return f->nfmt - nfmt;
64 f->stop = s;
65 }
66
67 fmt = (char*)__fmtdispatch(f, fmt, 0);
68 if(fmt == nil)
69 return -1;
70 }
71 }
72
73 void *
74 __fmtflush(Fmt *f, void *t, int len)
75 {
76 if(f->runes)
77 f->nfmt += (Rune*)t - (Rune*)f->to;
78 else
79 f->nfmt += (char*)t - (char *)f->to;
80 f->to = t;
81 if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > …
82 f->stop = f->to;
83 return nil;
84 }
85 return f->to;
86 }
87
88 /*
89 * put a formatted block of memory sz bytes long of n runes into the out…
90 * left/right justified in a field of at least f->width characters (if F…
91 */
92 int
93 __fmtpad(Fmt *f, int n)
94 {
95 char *t, *s;
96 int i;
97
98 t = (char*)f->to;
99 s = (char*)f->stop;
100 for(i = 0; i < n; i++)
101 FMTCHAR(f, t, s, ' ');
102 f->nfmt += t - (char *)f->to;
103 f->to = t;
104 return 0;
105 }
106
107 int
108 __rfmtpad(Fmt *f, int n)
109 {
110 Rune *t, *s;
111 int i;
112
113 t = (Rune*)f->to;
114 s = (Rune*)f->stop;
115 for(i = 0; i < n; i++)
116 FMTRCHAR(f, t, s, ' ');
117 f->nfmt += t - (Rune *)f->to;
118 f->to = t;
119 return 0;
120 }
121
122 int
123 __fmtcpy(Fmt *f, const void *vm, int n, int sz)
124 {
125 Rune *rt, *rs, r;
126 char *t, *s, *m, *me;
127 ulong fl;
128 int nc, w;
129
130 m = (char*)vm;
131 me = m + sz;
132 fl = f->flags;
133 w = 0;
134 if(fl & FmtWidth)
135 w = f->width;
136 if((fl & FmtPrec) && n > f->prec)
137 n = f->prec;
138 if(f->runes){
139 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
140 return -1;
141 rt = (Rune*)f->to;
142 rs = (Rune*)f->stop;
143 for(nc = n; nc > 0; nc--){
144 r = *(uchar*)m;
145 if(r < Runeself)
146 m++;
147 else if((me - m) >= UTFmax || fullrune(m, me-m))
148 m += chartorune(&r, m);
149 else
150 break;
151 FMTRCHAR(f, rt, rs, r);
152 }
153 f->nfmt += rt - (Rune *)f->to;
154 f->to = rt;
155 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
156 return -1;
157 }else{
158 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
159 return -1;
160 t = (char*)f->to;
161 s = (char*)f->stop;
162 for(nc = n; nc > 0; nc--){
163 r = *(uchar*)m;
164 if(r < Runeself)
165 m++;
166 else if((me - m) >= UTFmax || fullrune(m, me-m))
167 m += chartorune(&r, m);
168 else
169 break;
170 FMTRUNE(f, t, s, r);
171 }
172 f->nfmt += t - (char *)f->to;
173 f->to = t;
174 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
175 return -1;
176 }
177 return 0;
178 }
179
180 int
181 __fmtrcpy(Fmt *f, const void *vm, int n)
182 {
183 Rune r, *m, *me, *rt, *rs;
184 char *t, *s;
185 ulong fl;
186 int w;
187
188 m = (Rune*)vm;
189 fl = f->flags;
190 w = 0;
191 if(fl & FmtWidth)
192 w = f->width;
193 if((fl & FmtPrec) && n > f->prec)
194 n = f->prec;
195 if(f->runes){
196 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
197 return -1;
198 rt = (Rune*)f->to;
199 rs = (Rune*)f->stop;
200 for(me = m + n; m < me; m++)
201 FMTRCHAR(f, rt, rs, *m);
202 f->nfmt += rt - (Rune *)f->to;
203 f->to = rt;
204 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
205 return -1;
206 }else{
207 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
208 return -1;
209 t = (char*)f->to;
210 s = (char*)f->stop;
211 for(me = m + n; m < me; m++){
212 r = *m;
213 FMTRUNE(f, t, s, r);
214 }
215 f->nfmt += t - (char *)f->to;
216 f->to = t;
217 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
218 return -1;
219 }
220 return 0;
221 }
222
223 /* fmt out one character */
224 int
225 __charfmt(Fmt *f)
226 {
227 char x[1];
228
229 x[0] = va_arg(f->args, int);
230 f->prec = 1;
231 return __fmtcpy(f, (const char*)x, 1, 1);
232 }
233
234 /* fmt out one rune */
235 int
236 __runefmt(Fmt *f)
237 {
238 Rune x[1];
239
240 x[0] = va_arg(f->args, int);
241 return __fmtrcpy(f, (const void*)x, 1);
242 }
243
244 /* public helper routine: fmt out a null terminated string already in ha…
245 int
246 fmtstrcpy(Fmt *f, char *s)
247 {
248 int i, j;
249
250 if(!s)
251 return __fmtcpy(f, "<nil>", 5, 5);
252 /* if precision is specified, make sure we don't wander off the …
253 if(f->flags & FmtPrec){
254 #ifdef PLAN9PORT
255 Rune r;
256 i = 0;
257 for(j=0; j<f->prec && s[i]; j++)
258 i += chartorune(&r, s+i);
259 #else
260 /* ANSI requires precision in bytes, not Runes */
261 for(i=0; i<f->prec; i++)
262 if(s[i] == 0)
263 break;
264 j = utfnlen(s, i); /* won't print partial at end …
265 #endif
266 return __fmtcpy(f, s, j, i);
267 }
268 return __fmtcpy(f, s, utflen(s), strlen(s));
269 }
270
271 /* fmt out a null terminated utf string */
272 int
273 __strfmt(Fmt *f)
274 {
275 char *s;
276
277 s = va_arg(f->args, char *);
278 return fmtstrcpy(f, s);
279 }
280
281 /* public helper routine: fmt out a null terminated rune string already …
282 int
283 fmtrunestrcpy(Fmt *f, Rune *s)
284 {
285 Rune *e;
286 int n, p;
287
288 if(!s)
289 return __fmtcpy(f, "<nil>", 5, 5);
290 /* if precision is specified, make sure we don't wander off the …
291 if(f->flags & FmtPrec){
292 p = f->prec;
293 for(n = 0; n < p; n++)
294 if(s[n] == 0)
295 break;
296 }else{
297 for(e = s; *e; e++)
298 ;
299 n = e - s;
300 }
301 return __fmtrcpy(f, s, n);
302 }
303
304 /* fmt out a null terminated rune string */
305 int
306 __runesfmt(Fmt *f)
307 {
308 Rune *s;
309
310 s = va_arg(f->args, Rune *);
311 return fmtrunestrcpy(f, s);
312 }
313
314 /* fmt a % */
315 int
316 __percentfmt(Fmt *f)
317 {
318 Rune x[1];
319
320 x[0] = f->r;
321 f->prec = 1;
322 return __fmtrcpy(f, (const void*)x, 1);
323 }
324
325 /* fmt an integer */
326 int
327 __ifmt(Fmt *f)
328 {
329 char buf[140], *p, *conv;
330 /* 140: for 64 bits of binary + 3-byte sep every 4 digits */
331 uvlong vu;
332 ulong u;
333 int neg, base, i, n, fl, w, isv;
334 int ndig, len, excess, bytelen;
335 char *grouping;
336 char *thousands;
337
338 neg = 0;
339 fl = f->flags;
340 isv = 0;
341 vu = 0;
342 u = 0;
343 #ifndef PLAN9PORT
344 /*
345 * Unsigned verbs for ANSI C
346 */
347 switch(f->r){
348 case 'o':
349 case 'p':
350 case 'u':
351 case 'x':
352 case 'X':
353 fl |= FmtUnsigned;
354 fl &= ~(FmtSign|FmtSpace);
355 break;
356 }
357 #endif
358 if(f->r == 'p'){
359 u = (ulong)va_arg(f->args, void*);
360 f->r = 'x';
361 fl |= FmtUnsigned;
362 }else if(fl & FmtVLong){
363 isv = 1;
364 if(fl & FmtUnsigned)
365 vu = va_arg(f->args, uvlong);
366 else
367 vu = va_arg(f->args, vlong);
368 }else if(fl & FmtLong){
369 if(fl & FmtUnsigned)
370 u = va_arg(f->args, ulong);
371 else
372 u = va_arg(f->args, long);
373 }else if(fl & FmtByte){
374 if(fl & FmtUnsigned)
375 u = (uchar)va_arg(f->args, int);
376 else
377 u = (char)va_arg(f->args, int);
378 }else if(fl & FmtShort){
379 if(fl & FmtUnsigned)
380 u = (ushort)va_arg(f->args, int);
381 else
382 u = (short)va_arg(f->args, int);
383 }else{
384 if(fl & FmtUnsigned)
385 u = va_arg(f->args, uint);
386 else
387 u = va_arg(f->args, int);
388 }
389 conv = "0123456789abcdef";
390 grouping = "\4"; /* for hex, octal etc. (undefined by spe…
391 thousands = f->thousands;
392 switch(f->r){
393 case 'd':
394 case 'i':
395 case 'u':
396 base = 10;
397 grouping = f->grouping;
398 break;
399 case 'X':
400 conv = "0123456789ABCDEF";
401 /* fall through */
402 case 'x':
403 base = 16;
404 thousands = ":";
405 break;
406 case 'b':
407 base = 2;
408 thousands = ":";
409 break;
410 case 'o':
411 base = 8;
412 break;
413 default:
414 return -1;
415 }
416 if(!(fl & FmtUnsigned)){
417 if(isv && (vlong)vu < 0){
418 vu = -(vlong)vu;
419 neg = 1;
420 }else if(!isv && (long)u < 0){
421 u = -(long)u;
422 neg = 1;
423 }
424 }
425 p = buf + sizeof buf - 1;
426 n = 0; /* in runes */
427 excess = 0; /* number of bytes > number runes */
428 ndig = 0;
429 len = utflen(thousands);
430 bytelen = strlen(thousands);
431 if(isv){
432 while(vu){
433 i = vu % base;
434 vu /= base;
435 if((fl & FmtComma) && n % 4 == 3){
436 *p-- = ',';
437 n++;
438 }
439 if((fl & FmtApost) && __needsep(&ndig, &grouping…
440 n += len;
441 excess += bytelen - len;
442 p -= bytelen;
443 memmove(p+1, thousands, bytelen);
444 }
445 *p-- = conv[i];
446 n++;
447 }
448 }else{
449 while(u){
450 i = u % base;
451 u /= base;
452 if((fl & FmtComma) && n % 4 == 3){
453 *p-- = ',';
454 n++;
455 }
456 if((fl & FmtApost) && __needsep(&ndig, &grouping…
457 n += len;
458 excess += bytelen - len;
459 p -= bytelen;
460 memmove(p+1, thousands, bytelen);
461 }
462 *p-- = conv[i];
463 n++;
464 }
465 }
466 if(n == 0){
467 /*
468 * "The result of converting a zero value with
469 * a precision of zero is no characters." - ANSI
470 *
471 * "For o conversion, # increases the precision, if and …
472 * necessary, to force the first digit of the result to …
473 * (if the value and precision are both 0, a single 0 is…
474 */
475 if(!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (f…
476 *p-- = '0';
477 n = 1;
478 if(fl & FmtApost)
479 __needsep(&ndig, &grouping);
480 }
481
482 /*
483 * Zero values don't get 0x.
484 */
485 if(f->r == 'x' || f->r == 'X')
486 fl &= ~FmtSharp;
487 }
488 for(w = f->prec; n < w && p > buf+3; n++){
489 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
490 n += len;
491 excess += bytelen - len;
492 p -= bytelen;
493 memmove(p+1, thousands, bytelen);
494 }
495 *p-- = '0';
496 }
497 if(neg || (fl & (FmtSign|FmtSpace)))
498 n++;
499 if(fl & FmtSharp){
500 if(base == 16)
501 n += 2;
502 else if(base == 8){
503 if(p[1] == '0')
504 fl &= ~FmtSharp;
505 else
506 n++;
507 }
508 }
509 if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
510 w = 0;
511 if(fl & FmtWidth)
512 w = f->width;
513 for(; n < w && p > buf+3; n++){
514 if((fl & FmtApost) && __needsep(&ndig, &grouping…
515 n += len;
516 excess += bytelen - len;
517 p -= bytelen;
518 memmove(p+1, thousands, bytelen);
519 }
520 *p-- = '0';
521 }
522 f->flags &= ~FmtWidth;
523 }
524 if(fl & FmtSharp){
525 if(base == 16)
526 *p-- = f->r;
527 if(base == 16 || base == 8)
528 *p-- = '0';
529 }
530 if(neg)
531 *p-- = '-';
532 else if(fl & FmtSign)
533 *p-- = '+';
534 else if(fl & FmtSpace)
535 *p-- = ' ';
536 f->flags &= ~FmtPrec;
537 return __fmtcpy(f, p + 1, n, n + excess);
538 }
539
540 int
541 __countfmt(Fmt *f)
542 {
543 void *p;
544 ulong fl;
545
546 fl = f->flags;
547 p = va_arg(f->args, void*);
548 if(fl & FmtVLong){
549 *(vlong*)p = f->nfmt;
550 }else if(fl & FmtLong){
551 *(long*)p = f->nfmt;
552 }else if(fl & FmtByte){
553 *(char*)p = f->nfmt;
554 }else if(fl & FmtShort){
555 *(short*)p = f->nfmt;
556 }else{
557 *(int*)p = f->nfmt;
558 }
559 return 0;
560 }
561
562 int
563 __flagfmt(Fmt *f)
564 {
565 switch(f->r){
566 case ',':
567 f->flags |= FmtComma;
568 break;
569 case '-':
570 f->flags |= FmtLeft;
571 break;
572 case '+':
573 f->flags |= FmtSign;
574 break;
575 case '#':
576 f->flags |= FmtSharp;
577 break;
578 case '\'':
579 f->flags |= FmtApost;
580 break;
581 case ' ':
582 f->flags |= FmtSpace;
583 break;
584 case 'u':
585 f->flags |= FmtUnsigned;
586 break;
587 case 'h':
588 if(f->flags & FmtShort)
589 f->flags |= FmtByte;
590 f->flags |= FmtShort;
591 break;
592 case 'L':
593 f->flags |= FmtLDouble;
594 break;
595 case 'l':
596 if(f->flags & FmtLong)
597 f->flags |= FmtVLong;
598 f->flags |= FmtLong;
599 break;
600 }
601 return 1;
602 }
603
604 /* default error format */
605 int
606 __badfmt(Fmt *f)
607 {
608 char x[2+UTFmax];
609 int n;
610
611 x[0] = '%';
612 n = 1 + runetochar(x+1, &f->r);
613 x[n++] = '%';
614 f->prec = n;
615 __fmtcpy(f, (const void*)x, n, n);
616 return 0;
617 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.