fmt.c - vx32 - Local 9vx git repository for patches.
(HTM) git clone git://r-36.net/vx32
(DIR) Log
(DIR) Files
(DIR) Refs
---
fmt.c (65393B)
---
1 /*
2 * The authors of this software are Rob Pike and Ken Thompson,
3 * with contributions from Mike Burrows and Sean Dorward.
4 *
5 * Copyright (c) 2002-2006 by Lucent Technologies.
6 * Portions Copyright (c) 2004 Google Inc.
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose without fee is hereby granted, provided that this entire notice
10 * is included in all copies of any software which is or includes a copy
11 * or modification of this software and in all copies of the supporting
12 * documentation for such software.
13 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
14 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES
15 * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING
16 * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
17 */
18 #include <stdio.h>
19 #include <math.h>
20 #include <float.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <stdarg.h>
25 #include <assert.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include "u.h"
29 #include "utf.h"
30 #include "fmt.h"
31
32 #define PLAN9PORT /* Get Plan 9 verbs */
33
34 /*
35 * compiler directive on Plan 9
36 */
37 #ifndef USED
38 #define USED(x) if(x);else
39 #endif
40
41 /*
42 * nil cannot be ((void*)0) on ANSI C,
43 * because it is used for function pointers
44 */
45 #undef nil
46 #define nil 0
47
48 #undef nelem
49 #define nelem(x) (sizeof (x)/sizeof (x)[0])
50
51 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
52
53 /*
54 * dofmt -- format to a buffer
55 * the number of characters formatted is returned,
56 * or -1 if there was an error.
57 * if the buffer is ever filled, flush is called.
58 * it should reset the buffer and return whether formatting should continue.
59 */
60
61 typedef int (*Fmts)(Fmt*);
62
63 typedef struct Quoteinfo Quoteinfo;
64 struct Quoteinfo
65 {
66 int quoted; /* if set, string must be quoted */
67 int nrunesin; /* number of input runes that can be accepted */
68 int nbytesin; /* number of input bytes that can be accepted */
69 int nrunesout; /* number of runes that will be generated */
70 int nbytesout; /* number of bytes that will be generated */
71 };
72
73 /* Edit .+1,/^$/ |cfn |grep -v static | grep __ */
74 double __Inf(int sign);
75 double __NaN(void);
76 int __badfmt(Fmt *f);
77 int __charfmt(Fmt *f);
78 int __countfmt(Fmt *f);
79 int __efgfmt(Fmt *fmt);
80 int __errfmt(Fmt *f);
81 int __flagfmt(Fmt *f);
82 int __fmtFdFlush(Fmt *f);
83 int __fmtcpy(Fmt *f, const void *vm, int n, int sz);
84 void* __fmtdispatch(Fmt *f, void *fmt, int isrunes);
85 void * __fmtflush(Fmt *f, void *t, int len);
86 void __fmtlock(void);
87 int __fmtpad(Fmt *f, int n);
88 double __fmtpow10(int n);
89 int __fmtrcpy(Fmt *f, const void *vm, int n);
90 void __fmtunlock(void);
91 int __ifmt(Fmt *f);
92 int __isInf(double d, int sign);
93 int __isNaN(double d);
94 int __needsep(int*, char**);
95 int __needsquotes(char *s, int *quotelenp);
96 int __percentfmt(Fmt *f);
97 void __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout);
98 int __quotestrfmt(int runesin, Fmt *f);
99 int __rfmtpad(Fmt *f, int n);
100 int __runefmt(Fmt *f);
101 int __runeneedsquotes(Rune *r, int *quotelenp);
102 int __runesfmt(Fmt *f);
103 int __strfmt(Fmt *f);
104
105 #define FMTCHAR(f, t, s, c)\
106 do{\
107 if(t + 1 > (char*)s){\
108 t = (char*)__fmtflush(f, t, 1);\
109 if(t != nil)\
110 s = (char*)f->stop;\
111 else\
112 return -1;\
113 }\
114 *t++ = c;\
115 }while(0)
116
117 #define FMTRCHAR(f, t, s, c)\
118 do{\
119 if(t + 1 > (Rune*)s){\
120 t = (Rune*)__fmtflush(f, t, sizeof(Rune));\
121 if(t != nil)\
122 s = (Rune*)f->stop;\
123 else\
124 return -1;\
125 }\
126 *t++ = c;\
127 }while(0)
128
129 #define FMTRUNE(f, t, s, r)\
130 do{\
131 Rune _rune;\
132 int _runelen;\
133 if(t + UTFmax > (char*)s && t + (_runelen = runelen(r)) > (char*)s){\
134 t = (char*)__fmtflush(f, t, _runelen);\
135 if(t != nil)\
136 s = (char*)f->stop;\
137 else\
138 return -1;\
139 }\
140 if(r < Runeself)\
141 *t++ = r;\
142 else{\
143 _rune = r;\
144 t += runetochar(t, &_rune);\
145 }\
146 }while(0)
147
148 #ifdef va_copy
149 # define VA_COPY(a,b) va_copy(a,b)
150 # define VA_END(a) va_end(a)
151 #else
152 # define VA_COPY(a,b) (a) = (b)
153 # define VA_END(a)
154 #endif
155
156
157 /* ---------- end preamble -------- */
158
159 /* -------------- charstod.c --------------- */
160 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
161 // #include <stdarg.h>
162 // #include <string.h>
163 // #include "plan9.h"
164 // #include "fmt.h"
165 // #include "fmtdef.h"
166
167 /*
168 * Reads a floating-point number by interpreting successive characters
169 * returned by (*f)(vp). The last call it makes to f terminates the
170 * scan, so is not a character in the number. It may therefore be
171 * necessary to back up the input stream up one byte after calling charstod.
172 */
173
174 double
175 fmtcharstod(int(*f)(void*), void *vp)
176 {
177 double num, dem;
178 int neg, eneg, dig, exp, c;
179
180 num = 0;
181 neg = 0;
182 dig = 0;
183 exp = 0;
184 eneg = 0;
185
186 c = (*f)(vp);
187 while(c == ' ' || c == '\t')
188 c = (*f)(vp);
189 if(c == '-' || c == '+'){
190 if(c == '-')
191 neg = 1;
192 c = (*f)(vp);
193 }
194 while(c >= '0' && c <= '9'){
195 num = num*10 + c-'0';
196 c = (*f)(vp);
197 }
198 if(c == '.')
199 c = (*f)(vp);
200 while(c >= '0' && c <= '9'){
201 num = num*10 + c-'0';
202 dig++;
203 c = (*f)(vp);
204 }
205 if(c == 'e' || c == 'E'){
206 c = (*f)(vp);
207 if(c == '-' || c == '+'){
208 if(c == '-'){
209 dig = -dig;
210 eneg = 1;
211 }
212 c = (*f)(vp);
213 }
214 while(c >= '0' && c <= '9'){
215 exp = exp*10 + c-'0';
216 c = (*f)(vp);
217 }
218 }
219 exp -= dig;
220 if(exp < 0){
221 exp = -exp;
222 eneg = !eneg;
223 }
224 dem = __fmtpow10(exp);
225 if(eneg)
226 num /= dem;
227 else
228 num *= dem;
229 if(neg)
230 return -num;
231 return num;
232 }
233 /* -------------- dofmt.c --------------- */
234 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
235 /* Copyright (c) 2004 Google Inc.; see LICENSE */
236
237 // #include <stdarg.h>
238 // #include <string.h>
239 // #include "plan9.h"
240 // #include "fmt.h"
241 // #include "fmtdef.h"
242
243 /* format the output into f->to and return the number of characters fmted */
244 int
245 dofmt(Fmt *f, char *fmt)
246 {
247 Rune rune, *rt, *rs;
248 int r;
249 char *t, *s;
250 int n, nfmt;
251
252 nfmt = f->nfmt;
253 for(;;){
254 if(f->runes){
255 rt = (Rune*)f->to;
256 rs = (Rune*)f->stop;
257 while((r = *(uchar*)fmt) && r != '%'){
258 if(r < Runeself)
259 fmt++;
260 else{
261 fmt += chartorune(&rune, fmt);
262 r = rune;
263 }
264 FMTRCHAR(f, rt, rs, r);
265 }
266 fmt++;
267 f->nfmt += rt - (Rune *)f->to;
268 f->to = rt;
269 if(!r)
270 return f->nfmt - nfmt;
271 f->stop = rs;
272 }else{
273 t = (char*)f->to;
274 s = (char*)f->stop;
275 while((r = *(uchar*)fmt) && r != '%'){
276 if(r < Runeself){
277 FMTCHAR(f, t, s, r);
278 fmt++;
279 }else{
280 n = chartorune(&rune, fmt);
281 if(t + n > s){
282 t = (char*)__fmtflush(f, t, n);
283 if(t != nil)
284 s = (char*)f->stop;
285 else
286 return -1;
287 }
288 while(n--)
289 *t++ = *fmt++;
290 }
291 }
292 fmt++;
293 f->nfmt += t - (char *)f->to;
294 f->to = t;
295 if(!r)
296 return f->nfmt - nfmt;
297 f->stop = s;
298 }
299
300 fmt = (char*)__fmtdispatch(f, fmt, 0);
301 if(fmt == nil)
302 return -1;
303 }
304 }
305
306 void *
307 __fmtflush(Fmt *f, void *t, int len)
308 {
309 if(f->runes)
310 f->nfmt += (Rune*)t - (Rune*)f->to;
311 else
312 f->nfmt += (char*)t - (char *)f->to;
313 f->to = t;
314 if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
315 f->stop = f->to;
316 return nil;
317 }
318 return f->to;
319 }
320
321 /*
322 * put a formatted block of memory sz bytes long of n runes into the output buffer,
323 * left/right justified in a field of at least f->width characters (if FmtWidth is set)
324 */
325 int
326 __fmtpad(Fmt *f, int n)
327 {
328 char *t, *s;
329 int i;
330
331 t = (char*)f->to;
332 s = (char*)f->stop;
333 for(i = 0; i < n; i++)
334 FMTCHAR(f, t, s, ' ');
335 f->nfmt += t - (char *)f->to;
336 f->to = t;
337 return 0;
338 }
339
340 int
341 __rfmtpad(Fmt *f, int n)
342 {
343 Rune *t, *s;
344 int i;
345
346 t = (Rune*)f->to;
347 s = (Rune*)f->stop;
348 for(i = 0; i < n; i++)
349 FMTRCHAR(f, t, s, ' ');
350 f->nfmt += t - (Rune *)f->to;
351 f->to = t;
352 return 0;
353 }
354
355 int
356 __fmtcpy(Fmt *f, const void *vm, int n, int sz)
357 {
358 Rune *rt, *rs, r;
359 char *t, *s, *m, *me;
360 ulong fl;
361 int nc, w;
362
363 m = (char*)vm;
364 me = m + sz;
365 fl = f->flags;
366 w = 0;
367 if(fl & FmtWidth)
368 w = f->width;
369 if((fl & FmtPrec) && n > f->prec)
370 n = f->prec;
371 if(f->runes){
372 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
373 return -1;
374 rt = (Rune*)f->to;
375 rs = (Rune*)f->stop;
376 for(nc = n; nc > 0; nc--){
377 r = *(uchar*)m;
378 if(r < Runeself)
379 m++;
380 else if((me - m) >= UTFmax || fullrune(m, me-m))
381 m += chartorune(&r, m);
382 else
383 break;
384 FMTRCHAR(f, rt, rs, r);
385 }
386 f->nfmt += rt - (Rune *)f->to;
387 f->to = rt;
388 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
389 return -1;
390 }else{
391 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
392 return -1;
393 t = (char*)f->to;
394 s = (char*)f->stop;
395 for(nc = n; nc > 0; nc--){
396 r = *(uchar*)m;
397 if(r < Runeself)
398 m++;
399 else if((me - m) >= UTFmax || fullrune(m, me-m))
400 m += chartorune(&r, m);
401 else
402 break;
403 FMTRUNE(f, t, s, r);
404 }
405 f->nfmt += t - (char *)f->to;
406 f->to = t;
407 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
408 return -1;
409 }
410 return 0;
411 }
412
413 int
414 __fmtrcpy(Fmt *f, const void *vm, int n)
415 {
416 Rune r, *m, *me, *rt, *rs;
417 char *t, *s;
418 ulong fl;
419 int w;
420
421 m = (Rune*)vm;
422 fl = f->flags;
423 w = 0;
424 if(fl & FmtWidth)
425 w = f->width;
426 if((fl & FmtPrec) && n > f->prec)
427 n = f->prec;
428 if(f->runes){
429 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
430 return -1;
431 rt = (Rune*)f->to;
432 rs = (Rune*)f->stop;
433 for(me = m + n; m < me; m++)
434 FMTRCHAR(f, rt, rs, *m);
435 f->nfmt += rt - (Rune *)f->to;
436 f->to = rt;
437 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
438 return -1;
439 }else{
440 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
441 return -1;
442 t = (char*)f->to;
443 s = (char*)f->stop;
444 for(me = m + n; m < me; m++){
445 r = *m;
446 FMTRUNE(f, t, s, r);
447 }
448 f->nfmt += t - (char *)f->to;
449 f->to = t;
450 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
451 return -1;
452 }
453 return 0;
454 }
455
456 /* fmt out one character */
457 int
458 __charfmt(Fmt *f)
459 {
460 char x[1];
461
462 x[0] = va_arg(f->args, int);
463 f->prec = 1;
464 return __fmtcpy(f, (const char*)x, 1, 1);
465 }
466
467 /* fmt out one rune */
468 int
469 __runefmt(Fmt *f)
470 {
471 Rune x[1];
472
473 x[0] = va_arg(f->args, int);
474 return __fmtrcpy(f, (const void*)x, 1);
475 }
476
477 /* public helper routine: fmt out a null terminated string already in hand */
478 int
479 fmtstrcpy(Fmt *f, char *s)
480 {
481 int i, j;
482
483 if(!s)
484 return __fmtcpy(f, "<nil>", 5, 5);
485 /* if precision is specified, make sure we don't wander off the end */
486 if(f->flags & FmtPrec){
487 #ifdef PLAN9PORT
488 Rune r;
489 i = 0;
490 for(j=0; j<f->prec && s[i]; j++)
491 i += chartorune(&r, s+i);
492 #else
493 /* ANSI requires precision in bytes, not Runes */
494 for(i=0; i<f->prec; i++)
495 if(s[i] == 0)
496 break;
497 j = utfnlen(s, i); /* won't print partial at end */
498 #endif
499 return __fmtcpy(f, s, j, i);
500 }
501 return __fmtcpy(f, s, utflen(s), strlen(s));
502 }
503
504 /* fmt out a null terminated utf string */
505 int
506 __strfmt(Fmt *f)
507 {
508 char *s;
509
510 s = va_arg(f->args, char *);
511 return fmtstrcpy(f, s);
512 }
513
514 /* public helper routine: fmt out a null terminated rune string already in hand */
515 int
516 fmtrunestrcpy(Fmt *f, Rune *s)
517 {
518 Rune *e;
519 int n, p;
520
521 if(!s)
522 return __fmtcpy(f, "<nil>", 5, 5);
523 /* if precision is specified, make sure we don't wander off the end */
524 if(f->flags & FmtPrec){
525 p = f->prec;
526 for(n = 0; n < p; n++)
527 if(s[n] == 0)
528 break;
529 }else{
530 for(e = s; *e; e++)
531 ;
532 n = e - s;
533 }
534 return __fmtrcpy(f, s, n);
535 }
536
537 /* fmt out a null terminated rune string */
538 int
539 __runesfmt(Fmt *f)
540 {
541 Rune *s;
542
543 s = va_arg(f->args, Rune *);
544 return fmtrunestrcpy(f, s);
545 }
546
547 /* fmt a % */
548 int
549 __percentfmt(Fmt *f)
550 {
551 Rune x[1];
552
553 x[0] = f->r;
554 f->prec = 1;
555 return __fmtrcpy(f, (const void*)x, 1);
556 }
557
558 /* fmt an integer */
559 int
560 __ifmt(Fmt *f)
561 {
562 char buf[140], *p, *conv;
563 /* 140: for 64 bits of binary + 3-byte sep every 4 digits */
564 uvlong vu;
565 ulong u;
566 int neg, base, i, n, fl, w, isv;
567 int ndig, len, excess, bytelen;
568 char *grouping;
569 char *thousands;
570
571 neg = 0;
572 fl = f->flags;
573 isv = 0;
574 vu = 0;
575 u = 0;
576 #ifndef PLAN9PORT
577 /*
578 * Unsigned verbs for ANSI C
579 */
580 switch(f->r){
581 case 'o':
582 case 'p':
583 case 'u':
584 case 'x':
585 case 'X':
586 fl |= FmtUnsigned;
587 fl &= ~(FmtSign|FmtSpace);
588 break;
589 }
590 #endif
591 if(f->r == 'p'){
592 u = (ulong)va_arg(f->args, void*);
593 f->r = 'x';
594 fl |= FmtUnsigned;
595 }else if(fl & FmtVLong){
596 isv = 1;
597 if(fl & FmtUnsigned)
598 vu = va_arg(f->args, uvlong);
599 else
600 vu = va_arg(f->args, vlong);
601 }else if(fl & FmtLong){
602 if(fl & FmtUnsigned)
603 u = va_arg(f->args, ulong);
604 else
605 u = va_arg(f->args, long);
606 }else if(fl & FmtByte){
607 if(fl & FmtUnsigned)
608 u = (uchar)va_arg(f->args, int);
609 else
610 u = (char)va_arg(f->args, int);
611 }else if(fl & FmtShort){
612 if(fl & FmtUnsigned)
613 u = (ushort)va_arg(f->args, int);
614 else
615 u = (short)va_arg(f->args, int);
616 }else{
617 if(fl & FmtUnsigned)
618 u = va_arg(f->args, uint);
619 else
620 u = va_arg(f->args, int);
621 }
622 conv = "0123456789abcdef";
623 grouping = "\4"; /* for hex, octal etc. (undefined by spec but nice) */
624 thousands = f->thousands;
625 switch(f->r){
626 case 'd':
627 case 'i':
628 case 'u':
629 base = 10;
630 grouping = f->grouping;
631 break;
632 case 'X':
633 conv = "0123456789ABCDEF";
634 /* fall through */
635 case 'x':
636 base = 16;
637 thousands = ":";
638 break;
639 case 'b':
640 base = 2;
641 thousands = ":";
642 break;
643 case 'o':
644 base = 8;
645 break;
646 default:
647 return -1;
648 }
649 if(!(fl & FmtUnsigned)){
650 if(isv && (vlong)vu < 0){
651 vu = -(vlong)vu;
652 neg = 1;
653 }else if(!isv && (long)u < 0){
654 u = -(long)u;
655 neg = 1;
656 }
657 }
658 p = buf + sizeof buf - 1;
659 n = 0; /* in runes */
660 excess = 0; /* number of bytes > number runes */
661 ndig = 0;
662 len = utflen(thousands);
663 bytelen = strlen(thousands);
664 if(isv){
665 while(vu){
666 i = vu % base;
667 vu /= base;
668 if((fl & FmtComma) && n % 4 == 3){
669 *p-- = ',';
670 n++;
671 }
672 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
673 n += len;
674 excess += bytelen - len;
675 p -= bytelen;
676 memmove(p+1, thousands, bytelen);
677 }
678 *p-- = conv[i];
679 n++;
680 }
681 }else{
682 while(u){
683 i = u % base;
684 u /= base;
685 if((fl & FmtComma) && n % 4 == 3){
686 *p-- = ',';
687 n++;
688 }
689 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
690 n += len;
691 excess += bytelen - len;
692 p -= bytelen;
693 memmove(p+1, thousands, bytelen);
694 }
695 *p-- = conv[i];
696 n++;
697 }
698 }
699 if(n == 0){
700 /*
701 * "The result of converting a zero value with
702 * a precision of zero is no characters." - ANSI
703 *
704 * "For o conversion, # increases the precision, if and only if
705 * necessary, to force the first digit of the result to be a zero
706 * (if the value and precision are both 0, a single 0 is printed)." - ANSI
707 */
708 if(!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (fl & FmtSharp))){
709 *p-- = '0';
710 n = 1;
711 if(fl & FmtApost)
712 __needsep(&ndig, &grouping);
713 }
714
715 /*
716 * Zero values don't get 0x.
717 */
718 if(f->r == 'x' || f->r == 'X')
719 fl &= ~FmtSharp;
720 }
721 for(w = f->prec; n < w && p > buf+3; n++){
722 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
723 n += len;
724 excess += bytelen - len;
725 p -= bytelen;
726 memmove(p+1, thousands, bytelen);
727 }
728 *p-- = '0';
729 }
730 if(neg || (fl & (FmtSign|FmtSpace)))
731 n++;
732 if(fl & FmtSharp){
733 if(base == 16)
734 n += 2;
735 else if(base == 8){
736 if(p[1] == '0')
737 fl &= ~FmtSharp;
738 else
739 n++;
740 }
741 }
742 if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
743 w = 0;
744 if(fl & FmtWidth)
745 w = f->width;
746 for(; n < w && p > buf+3; n++){
747 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
748 n += len;
749 excess += bytelen - len;
750 p -= bytelen;
751 memmove(p+1, thousands, bytelen);
752 }
753 *p-- = '0';
754 }
755 f->flags &= ~FmtWidth;
756 }
757 if(fl & FmtSharp){
758 if(base == 16)
759 *p-- = f->r;
760 if(base == 16 || base == 8)
761 *p-- = '0';
762 }
763 if(neg)
764 *p-- = '-';
765 else if(fl & FmtSign)
766 *p-- = '+';
767 else if(fl & FmtSpace)
768 *p-- = ' ';
769 f->flags &= ~FmtPrec;
770 return __fmtcpy(f, p + 1, n, n + excess);
771 }
772
773 int
774 __countfmt(Fmt *f)
775 {
776 void *p;
777 ulong fl;
778
779 fl = f->flags;
780 p = va_arg(f->args, void*);
781 if(fl & FmtVLong){
782 *(vlong*)p = f->nfmt;
783 }else if(fl & FmtLong){
784 *(long*)p = f->nfmt;
785 }else if(fl & FmtByte){
786 *(char*)p = f->nfmt;
787 }else if(fl & FmtShort){
788 *(short*)p = f->nfmt;
789 }else{
790 *(int*)p = f->nfmt;
791 }
792 return 0;
793 }
794
795 int
796 __flagfmt(Fmt *f)
797 {
798 switch(f->r){
799 case ',':
800 f->flags |= FmtComma;
801 break;
802 case '-':
803 f->flags |= FmtLeft;
804 break;
805 case '+':
806 f->flags |= FmtSign;
807 break;
808 case '#':
809 f->flags |= FmtSharp;
810 break;
811 case '\'':
812 f->flags |= FmtApost;
813 break;
814 case ' ':
815 f->flags |= FmtSpace;
816 break;
817 case 'u':
818 f->flags |= FmtUnsigned;
819 break;
820 case 'h':
821 if(f->flags & FmtShort)
822 f->flags |= FmtByte;
823 f->flags |= FmtShort;
824 break;
825 case 'L':
826 f->flags |= FmtLDouble;
827 break;
828 case 'l':
829 if(f->flags & FmtLong)
830 f->flags |= FmtVLong;
831 f->flags |= FmtLong;
832 break;
833 }
834 return 1;
835 }
836
837 /* default error format */
838 int
839 __badfmt(Fmt *f)
840 {
841 char x[3];
842
843 x[0] = '%';
844 x[1] = f->r;
845 x[2] = '%';
846 f->prec = 3;
847 __fmtcpy(f, (const void*)x, 3, 3);
848 return 0;
849 }
850 /* -------------- fltfmt.c --------------- */
851 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
852 // #include <stdio.h>
853 // #include <math.h>
854 // #include <float.h>
855 // #include <string.h>
856 // #include <stdlib.h>
857 // #include <errno.h>
858 // #include <stdarg.h>
859 // #include <fmt.h>
860 // #include <assert.h>
861 // #include "plan9.h"
862 // #include "fmt.h"
863 // #include "fmtdef.h"
864 // #include "nan.h"
865
866 enum
867 {
868 FDIGIT = 30,
869 FDEFLT = 6,
870 NSIGNIF = 17
871 };
872
873 /*
874 * first few powers of 10, enough for about 1/2 of the
875 * total space for doubles.
876 */
877 static double pows10[] =
878 {
879 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
880 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
881 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
882 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
883 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
884 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
885 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
886 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
887 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89,
888 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99,
889 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
890 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
891 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
892 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
893 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
894 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
895 };
896 #define npows10 ((int)(sizeof(pows10)/sizeof(pows10[0])))
897 #define pow10(x) fmtpow10(x)
898
899 static double
900 pow10(int n)
901 {
902 double d;
903 int neg;
904
905 neg = 0;
906 if(n < 0){
907 if(n < DBL_MIN_10_EXP)
908 return 0.;
909 neg = 1;
910 n = -n;
911 }else if(n > DBL_MAX_10_EXP)
912 return HUGE_VAL;
913
914 if(n < npows10)
915 d = pows10[n];
916 else{
917 d = pows10[npows10-1];
918 for(;;){
919 n -= npows10 - 1;
920 if(n < npows10){
921 d *= pows10[n];
922 break;
923 }
924 d *= pows10[npows10 - 1];
925 }
926 }
927 if(neg)
928 return 1./d;
929 return d;
930 }
931
932 /*
933 * add 1 to the decimal integer string a of length n.
934 * if 99999 overflows into 10000, return 1 to tell caller
935 * to move the virtual decimal point.
936 */
937 static int
938 xadd1(char *a, int n)
939 {
940 char *b;
941 int c;
942
943 if(n < 0 || n > NSIGNIF)
944 return 0;
945 for(b = a+n-1; b >= a; b--) {
946 c = *b + 1;
947 if(c <= '9') {
948 *b = c;
949 return 0;
950 }
951 *b = '0';
952 }
953 /*
954 * need to overflow adding digit.
955 * shift number down and insert 1 at beginning.
956 * decimal is known to be 0s or we wouldn't
957 * have gotten this far. (e.g., 99999+1 => 00000)
958 */
959 a[0] = '1';
960 return 1;
961 }
962
963 /*
964 * subtract 1 from the decimal integer string a.
965 * if 10000 underflows into 09999, make it 99999
966 * and return 1 to tell caller to move the virtual
967 * decimal point. this way, xsub1 is inverse of xadd1.
968 */
969 static int
970 xsub1(char *a, int n)
971 {
972 char *b;
973 int c;
974
975 if(n < 0 || n > NSIGNIF)
976 return 0;
977 for(b = a+n-1; b >= a; b--) {
978 c = *b - 1;
979 if(c >= '0') {
980 if(c == '0' && b == a) {
981 /*
982 * just zeroed the top digit; shift everyone up.
983 * decimal is known to be 9s or we wouldn't
984 * have gotten this far. (e.g., 10000-1 => 09999)
985 */
986 *b = '9';
987 return 1;
988 }
989 *b = c;
990 return 0;
991 }
992 *b = '9';
993 }
994 /*
995 * can't get here. the number a is always normalized
996 * so that it has a nonzero first digit.
997 */
998 abort();
999 }
1000
1001 /*
1002 * format exponent like sprintf(p, "e%+02d", e)
1003 */
1004 static void
1005 xfmtexp(char *p, int e, int ucase)
1006 {
1007 char se[9];
1008 int i;
1009
1010 *p++ = ucase ? 'E' : 'e';
1011 if(e < 0) {
1012 *p++ = '-';
1013 e = -e;
1014 } else
1015 *p++ = '+';
1016 i = 0;
1017 while(e) {
1018 se[i++] = e % 10 + '0';
1019 e /= 10;
1020 }
1021 while(i < 2)
1022 se[i++] = '0';
1023 while(i > 0)
1024 *p++ = se[--i];
1025 *p++ = '\0';
1026 }
1027
1028 /*
1029 * compute decimal integer m, exp such that:
1030 * f = m*10^exp
1031 * m is as short as possible with losing exactness
1032 * assumes special cases (NaN, +Inf, -Inf) have been handled.
1033 */
1034 static void
1035 xdtoa(double f, char *s, int *exp, int *neg, int *ns)
1036 {
1037 int c, d, e2, e, ee, i, ndigit, oerrno;
1038 char tmp[NSIGNIF+10];
1039 double g;
1040
1041 oerrno = errno; /* in case strtod smashes errno */
1042
1043 /*
1044 * make f non-negative.
1045 */
1046 *neg = 0;
1047 if(f < 0) {
1048 f = -f;
1049 *neg = 1;
1050 }
1051
1052 /*
1053 * must handle zero specially.
1054 */
1055 if(f == 0){
1056 *exp = 0;
1057 s[0] = '0';
1058 s[1] = '\0';
1059 *ns = 1;
1060 return;
1061 }
1062
1063 /*
1064 * find g,e such that f = g*10^e.
1065 * guess 10-exponent using 2-exponent, then fine tune.
1066 */
1067 frexp(f, &e2);
1068 e = (int)(e2 * .301029995664);
1069 g = f * pow10(-e);
1070 while(g < 1) {
1071 e--;
1072 g = f * pow10(-e);
1073 }
1074 while(g >= 10) {
1075 e++;
1076 g = f * pow10(-e);
1077 }
1078
1079 /*
1080 * convert NSIGNIF digits as a first approximation.
1081 */
1082 for(i=0; i<NSIGNIF; i++) {
1083 d = (int)g;
1084 s[i] = d+'0';
1085 g = (g-d) * 10;
1086 }
1087 s[i] = 0;
1088
1089 /*
1090 * adjust e because s is 314159... not 3.14159...
1091 */
1092 e -= NSIGNIF-1;
1093 xfmtexp(s+NSIGNIF, e, 0);
1094
1095 /*
1096 * adjust conversion until strtod(s) == f exactly.
1097 */
1098 for(i=0; i<10; i++) {
1099 g = strtod(s, nil);
1100 if(f > g) {
1101 if(xadd1(s, NSIGNIF)) {
1102 /* gained a digit */
1103 e--;
1104 xfmtexp(s+NSIGNIF, e, 0);
1105 }
1106 continue;
1107 }
1108 if(f < g) {
1109 if(xsub1(s, NSIGNIF)) {
1110 /* lost a digit */
1111 e++;
1112 xfmtexp(s+NSIGNIF, e, 0);
1113 }
1114 continue;
1115 }
1116 break;
1117 }
1118
1119 /*
1120 * play with the decimal to try to simplify.
1121 */
1122
1123 /*
1124 * bump last few digits up to 9 if we can
1125 */
1126 for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
1127 c = s[i];
1128 if(c != '9') {
1129 s[i] = '9';
1130 g = strtod(s, nil);
1131 if(g != f) {
1132 s[i] = c;
1133 break;
1134 }
1135 }
1136 }
1137
1138 /*
1139 * add 1 in hopes of turning 9s to 0s
1140 */
1141 if(s[NSIGNIF-1] == '9') {
1142 strcpy(tmp, s);
1143 ee = e;
1144 if(xadd1(tmp, NSIGNIF)) {
1145 ee--;
1146 xfmtexp(tmp+NSIGNIF, ee, 0);
1147 }
1148 g = strtod(tmp, nil);
1149 if(g == f) {
1150 strcpy(s, tmp);
1151 e = ee;
1152 }
1153 }
1154
1155 /*
1156 * bump last few digits down to 0 as we can.
1157 */
1158 for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
1159 c = s[i];
1160 if(c != '0') {
1161 s[i] = '0';
1162 g = strtod(s, nil);
1163 if(g != f) {
1164 s[i] = c;
1165 break;
1166 }
1167 }
1168 }
1169
1170 /*
1171 * remove trailing zeros.
1172 */
1173 ndigit = NSIGNIF;
1174 while(ndigit > 1 && s[ndigit-1] == '0'){
1175 e++;
1176 --ndigit;
1177 }
1178 s[ndigit] = 0;
1179 *exp = e;
1180 *ns = ndigit;
1181 errno = oerrno;
1182 }
1183
1184 #ifdef PLAN9PORT
1185 static char *special[] = { "NaN", "NaN", "+Inf", "+Inf", "-Inf", "-Inf" };
1186 #else
1187 static char *special[] = { "nan", "NAN", "inf", "INF", "-inf", "-INF" };
1188 #endif
1189
1190 int
1191 __efgfmt(Fmt *fmt)
1192 {
1193 char buf[NSIGNIF+10], *dot, *digits, *p, *s, suf[10], *t;
1194 double f;
1195 int c, chr, dotwid, e, exp, fl, ndigits, neg, newndigits;
1196 int pad, point, prec, realchr, sign, sufwid, ucase, wid, z1, z2;
1197 Rune r, *rs, *rt;
1198
1199 f = va_arg(fmt->args, double);
1200
1201 /*
1202 * extract formatting flags
1203 */
1204 fl = fmt->flags;
1205 fmt->flags = 0;
1206 prec = FDEFLT;
1207 if(fl & FmtPrec)
1208 prec = fmt->prec;
1209 chr = fmt->r;
1210 ucase = 0;
1211 switch(chr) {
1212 case 'A':
1213 case 'E':
1214 case 'F':
1215 case 'G':
1216 chr += 'a'-'A';
1217 ucase = 1;
1218 break;
1219 }
1220
1221 /*
1222 * pick off special numbers.
1223 */
1224 if(__isNaN(f)) {
1225 s = special[0+ucase];
1226 special:
1227 fmt->flags = fl & (FmtWidth|FmtLeft);
1228 return __fmtcpy(fmt, s, strlen(s), strlen(s));
1229 }
1230 if(__isInf(f, 1)) {
1231 s = special[2+ucase];
1232 goto special;
1233 }
1234 if(__isInf(f, -1)) {
1235 s = special[4+ucase];
1236 goto special;
1237 }
1238
1239 /*
1240 * get exact representation.
1241 */
1242 digits = buf;
1243 xdtoa(f, digits, &exp, &neg, &ndigits);
1244
1245 /*
1246 * get locale's decimal point.
1247 */
1248 dot = fmt->decimal;
1249 if(dot == nil)
1250 dot = ".";
1251 dotwid = utflen(dot);
1252
1253 /*
1254 * now the formatting fun begins.
1255 * compute parameters for actual fmt:
1256 *
1257 * pad: number of spaces to insert before/after field.
1258 * z1: number of zeros to insert before digits
1259 * z2: number of zeros to insert after digits
1260 * point: number of digits to print before decimal point
1261 * ndigits: number of digits to use from digits[]
1262 * suf: trailing suffix, like "e-5"
1263 */
1264 realchr = chr;
1265 switch(chr){
1266 case 'g':
1267 /*
1268 * convert to at most prec significant digits. (prec=0 means 1)
1269 */
1270 if(prec == 0)
1271 prec = 1;
1272 if(ndigits > prec) {
1273 if(digits[prec] >= '5' && xadd1(digits, prec))
1274 exp++;
1275 exp += ndigits-prec;
1276 ndigits = prec;
1277 }
1278
1279 /*
1280 * extra rules for %g (implemented below):
1281 * trailing zeros removed after decimal unless FmtSharp.
1282 * decimal point only if digit follows.
1283 */
1284
1285 /* fall through to %e */
1286 default:
1287 case 'e':
1288 /*
1289 * one significant digit before decimal, no leading zeros.
1290 */
1291 point = 1;
1292 z1 = 0;
1293
1294 /*
1295 * decimal point is after ndigits digits right now.
1296 * slide to be after first.
1297 */
1298 e = exp + (ndigits-1);
1299
1300 /*
1301 * if this is %g, check exponent and convert prec
1302 */
1303 if(realchr == 'g') {
1304 if(-4 <= e && e < prec)
1305 goto casef;
1306 prec--; /* one digit before decimal; rest after */
1307 }
1308
1309 /*
1310 * compute trailing zero padding or truncate digits.
1311 */
1312 if(1+prec >= ndigits)
1313 z2 = 1+prec - ndigits;
1314 else {
1315 /*
1316 * truncate digits
1317 */
1318 assert(realchr != 'g');
1319 newndigits = 1+prec;
1320 if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {
1321 /*
1322 * had 999e4, now have 100e5
1323 */
1324 e++;
1325 }
1326 ndigits = newndigits;
1327 z2 = 0;
1328 }
1329 xfmtexp(suf, e, ucase);
1330 sufwid = strlen(suf);
1331 break;
1332
1333 casef:
1334 case 'f':
1335 /*
1336 * determine where digits go with respect to decimal point
1337 */
1338 if(ndigits+exp > 0) {
1339 point = ndigits+exp;
1340 z1 = 0;
1341 } else {
1342 point = 1;
1343 z1 = 1 + -(ndigits+exp);
1344 }
1345
1346 /*
1347 * %g specifies prec = number of significant digits
1348 * convert to number of digits after decimal point
1349 */
1350 if(realchr == 'g')
1351 prec += z1 - point;
1352
1353 /*
1354 * compute trailing zero padding or truncate digits.
1355 */
1356 if(point+prec >= z1+ndigits)
1357 z2 = point+prec - (z1+ndigits);
1358 else {
1359 /*
1360 * truncate digits
1361 */
1362 assert(realchr != 'g');
1363 newndigits = point+prec - z1;
1364 if(newndigits < 0) {
1365 z1 += newndigits;
1366 newndigits = 0;
1367 } else if(newndigits == 0) {
1368 /* perhaps round up */
1369 if(digits[0] >= '5'){
1370 digits[0] = '1';
1371 newndigits = 1;
1372 goto newdigit;
1373 }
1374 } else if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {
1375 /*
1376 * digits was 999, is now 100; make it 1000
1377 */
1378 digits[newndigits++] = '0';
1379 newdigit:
1380 /*
1381 * account for new digit
1382 */
1383 if(z1) /* 0.099 => 0.100 or 0.99 => 1.00*/
1384 z1--;
1385 else /* 9.99 => 10.00 */
1386 point++;
1387 }
1388 z2 = 0;
1389 ndigits = newndigits;
1390 }
1391 sufwid = 0;
1392 break;
1393 }
1394
1395 /*
1396 * if %g is given without FmtSharp, remove trailing zeros.
1397 * must do after truncation, so that e.g. print %.3g 1.001
1398 * produces 1, not 1.00. sorry, but them's the rules.
1399 */
1400 if(realchr == 'g' && !(fl & FmtSharp)) {
1401 if(z1+ndigits+z2 >= point) {
1402 if(z1+ndigits < point)
1403 z2 = point - (z1+ndigits);
1404 else{
1405 z2 = 0;
1406 while(z1+ndigits > point && digits[ndigits-1] == '0')
1407 ndigits--;
1408 }
1409 }
1410 }
1411
1412 /*
1413 * compute width of all digits and decimal point and suffix if any
1414 */
1415 wid = z1+ndigits+z2;
1416 if(wid > point)
1417 wid += dotwid;
1418 else if(wid == point){
1419 if(fl & FmtSharp)
1420 wid += dotwid;
1421 else
1422 point++; /* do not print any decimal point */
1423 }
1424 wid += sufwid;
1425
1426 /*
1427 * determine sign
1428 */
1429 sign = 0;
1430 if(neg)
1431 sign = '-';
1432 else if(fl & FmtSign)
1433 sign = '+';
1434 else if(fl & FmtSpace)
1435 sign = ' ';
1436 if(sign)
1437 wid++;
1438
1439 /*
1440 * compute padding
1441 */
1442 pad = 0;
1443 if((fl & FmtWidth) && fmt->width > wid)
1444 pad = fmt->width - wid;
1445 if(pad && !(fl & FmtLeft) && (fl & FmtZero)){
1446 z1 += pad;
1447 point += pad;
1448 pad = 0;
1449 }
1450
1451 /*
1452 * format the actual field. too bad about doing this twice.
1453 */
1454 if(fmt->runes){
1455 if(pad && !(fl & FmtLeft) && __rfmtpad(fmt, pad) < 0)
1456 return -1;
1457 rt = (Rune*)fmt->to;
1458 rs = (Rune*)fmt->stop;
1459 if(sign)
1460 FMTRCHAR(fmt, rt, rs, sign);
1461 while(z1>0 || ndigits>0 || z2>0) {
1462 if(z1 > 0){
1463 z1--;
1464 c = '0';
1465 }else if(ndigits > 0){
1466 ndigits--;
1467 c = *digits++;
1468 }else{
1469 z2--;
1470 c = '0';
1471 }
1472 FMTRCHAR(fmt, rt, rs, c);
1473 if(--point == 0) {
1474 for(p = dot; *p; ){
1475 p += chartorune(&r, p);
1476 FMTRCHAR(fmt, rt, rs, r);
1477 }
1478 }
1479 }
1480 fmt->nfmt += rt - (Rune*)fmt->to;
1481 fmt->to = rt;
1482 if(sufwid && __fmtcpy(fmt, suf, sufwid, sufwid) < 0)
1483 return -1;
1484 if(pad && (fl & FmtLeft) && __rfmtpad(fmt, pad) < 0)
1485 return -1;
1486 }else{
1487 if(pad && !(fl & FmtLeft) && __fmtpad(fmt, pad) < 0)
1488 return -1;
1489 t = (char*)fmt->to;
1490 s = (char*)fmt->stop;
1491 if(sign)
1492 FMTCHAR(fmt, t, s, sign);
1493 while(z1>0 || ndigits>0 || z2>0) {
1494 if(z1 > 0){
1495 z1--;
1496 c = '0';
1497 }else if(ndigits > 0){
1498 ndigits--;
1499 c = *digits++;
1500 }else{
1501 z2--;
1502 c = '0';
1503 }
1504 FMTCHAR(fmt, t, s, c);
1505 if(--point == 0)
1506 for(p=dot; *p; p++)
1507 FMTCHAR(fmt, t, s, *p);
1508 }
1509 fmt->nfmt += t - (char*)fmt->to;
1510 fmt->to = t;
1511 if(sufwid && __fmtcpy(fmt, suf, sufwid, sufwid) < 0)
1512 return -1;
1513 if(pad && (fl & FmtLeft) && __fmtpad(fmt, pad) < 0)
1514 return -1;
1515 }
1516 return 0;
1517 }
1518
1519 /* -------------- fmt.c --------------- */
1520 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
1521 // #include <stdarg.h>
1522 // #include <string.h>
1523 // #include "plan9.h"
1524 // #include "fmt.h"
1525 // #include "fmtdef.h"
1526
1527 enum
1528 {
1529 Maxfmt = 64
1530 };
1531
1532 typedef struct Convfmt Convfmt;
1533 struct Convfmt
1534 {
1535 int c;
1536 volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */
1537 };
1538
1539 static struct
1540 {
1541 /* lock by calling __fmtlock, __fmtunlock */
1542 int nfmt;
1543 Convfmt fmt[Maxfmt];
1544 } fmtalloc;
1545
1546 static Convfmt knownfmt[] = {
1547 { ' ', __flagfmt },
1548 { '#', __flagfmt },
1549 { '%', __percentfmt },
1550 { '\'', __flagfmt },
1551 { '+', __flagfmt },
1552 { ',', __flagfmt },
1553 { '-', __flagfmt },
1554 { 'C', __runefmt }, /* Plan 9 addition */
1555 { 'E', __efgfmt },
1556 #ifndef PLAN9PORT
1557 { 'F', __efgfmt }, /* ANSI only */
1558 #endif
1559 { 'G', __efgfmt },
1560 #ifndef PLAN9PORT
1561 { 'L', __flagfmt }, /* ANSI only */
1562 #endif
1563 { 'S', __runesfmt }, /* Plan 9 addition */
1564 { 'X', __ifmt },
1565 { 'b', __ifmt }, /* Plan 9 addition */
1566 { 'c', __charfmt },
1567 { 'd', __ifmt },
1568 { 'e', __efgfmt },
1569 { 'f', __efgfmt },
1570 { 'g', __efgfmt },
1571 { 'h', __flagfmt },
1572 #ifndef PLAN9PORT
1573 { 'i', __ifmt }, /* ANSI only */
1574 #endif
1575 { 'l', __flagfmt },
1576 { 'n', __countfmt },
1577 { 'o', __ifmt },
1578 { 'p', __ifmt },
1579 { 'r', __errfmt },
1580 { 's', __strfmt },
1581 #ifdef PLAN9PORT
1582 { 'u', __flagfmt },
1583 #else
1584 { 'u', __ifmt },
1585 #endif
1586 { 'x', __ifmt },
1587 { 0, nil }
1588 };
1589
1590
1591 int (*fmtdoquote)(int);
1592
1593 /*
1594 * __fmtlock() must be set
1595 */
1596 static int
1597 __fmtinstall(int c, Fmts f)
1598 {
1599 Convfmt *p, *ep;
1600
1601 if(c<=0 || c>=65536)
1602 return -1;
1603 if(!f)
1604 f = __badfmt;
1605
1606 ep = &fmtalloc.fmt[fmtalloc.nfmt];
1607 for(p=fmtalloc.fmt; p<ep; p++)
1608 if(p->c == c)
1609 break;
1610
1611 if(p == &fmtalloc.fmt[Maxfmt])
1612 return -1;
1613
1614 p->fmt = f;
1615 if(p == ep){ /* installing a new format character */
1616 fmtalloc.nfmt++;
1617 p->c = c;
1618 }
1619
1620 return 0;
1621 }
1622
1623 int
1624 fmtinstall(int c, int (*f)(Fmt*))
1625 {
1626 int ret;
1627
1628 __fmtlock();
1629 ret = __fmtinstall(c, f);
1630 __fmtunlock();
1631 return ret;
1632 }
1633
1634 static Fmts
1635 fmtfmt(int c)
1636 {
1637 Convfmt *p, *ep;
1638
1639 ep = &fmtalloc.fmt[fmtalloc.nfmt];
1640 for(p=fmtalloc.fmt; p<ep; p++)
1641 if(p->c == c){
1642 while(p->fmt == nil) /* loop until value is updated */
1643 ;
1644 return p->fmt;
1645 }
1646
1647 /* is this a predefined format char? */
1648 __fmtlock();
1649 for(p=knownfmt; p->c; p++)
1650 if(p->c == c){
1651 __fmtinstall(p->c, p->fmt);
1652 __fmtunlock();
1653 return p->fmt;
1654 }
1655 __fmtunlock();
1656
1657 return __badfmt;
1658 }
1659
1660 void*
1661 __fmtdispatch(Fmt *f, void *fmt, int isrunes)
1662 {
1663 Rune rune, r;
1664 int i, n;
1665
1666 f->flags = 0;
1667 f->width = f->prec = 0;
1668
1669 for(;;){
1670 if(isrunes){
1671 r = *(Rune*)fmt;
1672 fmt = (Rune*)fmt + 1;
1673 }else{
1674 fmt = (char*)fmt + chartorune(&rune, (char*)fmt);
1675 r = rune;
1676 }
1677 f->r = r;
1678 switch(r){
1679 case '\0':
1680 return nil;
1681 case '.':
1682 f->flags |= FmtWidth|FmtPrec;
1683 continue;
1684 case '0':
1685 if(!(f->flags & FmtWidth)){
1686 f->flags |= FmtZero;
1687 continue;
1688 }
1689 /* fall through */
1690 case '1': case '2': case '3': case '4':
1691 case '5': case '6': case '7': case '8': case '9':
1692 i = 0;
1693 while(r >= '0' && r <= '9'){
1694 i = i * 10 + r - '0';
1695 if(isrunes){
1696 r = *(Rune*)fmt;
1697 fmt = (Rune*)fmt + 1;
1698 }else{
1699 r = *(char*)fmt;
1700 fmt = (char*)fmt + 1;
1701 }
1702 }
1703 if(isrunes)
1704 fmt = (Rune*)fmt - 1;
1705 else
1706 fmt = (char*)fmt - 1;
1707 numflag:
1708 if(f->flags & FmtWidth){
1709 f->flags |= FmtPrec;
1710 f->prec = i;
1711 }else{
1712 f->flags |= FmtWidth;
1713 f->width = i;
1714 }
1715 continue;
1716 case '*':
1717 i = va_arg(f->args, int);
1718 if(i < 0){
1719 /*
1720 * negative precision =>
1721 * ignore the precision.
1722 */
1723 if(f->flags & FmtPrec){
1724 f->flags &= ~FmtPrec;
1725 f->prec = 0;
1726 continue;
1727 }
1728 i = -i;
1729 f->flags |= FmtLeft;
1730 }
1731 goto numflag;
1732 }
1733 n = (*fmtfmt(r))(f);
1734 if(n < 0)
1735 return nil;
1736 if(n == 0)
1737 return fmt;
1738 }
1739 }
1740 /* -------------- fmtfd.c --------------- */
1741 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
1742 // #include <stdarg.h>
1743 // #include <string.h>
1744 // #include "plan9.h"
1745 // #include "fmt.h"
1746 // #include "fmtdef.h"
1747
1748 /*
1749 * public routine for final flush of a formatting buffer
1750 * to a file descriptor; returns total char count.
1751 */
1752 int
1753 fmtfdflush(Fmt *f)
1754 {
1755 if(__fmtFdFlush(f) <= 0)
1756 return -1;
1757 return f->nfmt;
1758 }
1759
1760 /*
1761 * initialize an output buffer for buffered printing
1762 */
1763 int
1764 fmtfdinit(Fmt *f, int fd, char *buf, int size)
1765 {
1766 f->runes = 0;
1767 f->start = buf;
1768 f->to = buf;
1769 f->stop = buf + size;
1770 f->flush = __fmtFdFlush;
1771 f->farg = (void*)(uintptr_t)fd;
1772 f->flags = 0;
1773 f->nfmt = 0;
1774 fmtlocaleinit(f, nil, nil, nil);
1775 return 0;
1776 }
1777 /* -------------- fmtfdflush.c --------------- */
1778 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
1779 // #include <stdarg.h>
1780 // #include <unistd.h>
1781 // #include "plan9.h"
1782 // #include "fmt.h"
1783 // #include "fmtdef.h"
1784
1785 /*
1786 * generic routine for flushing a formatting buffer
1787 * to a file descriptor
1788 */
1789 int
1790 __fmtFdFlush(Fmt *f)
1791 {
1792 int n;
1793
1794 n = (char*)f->to - (char*)f->start;
1795 if(n && write((uintptr)f->farg, f->start, n) != n)
1796 return 0;
1797 f->to = f->start;
1798 return 1;
1799 }
1800 /* -------------- fmtlocale.c --------------- */
1801 /* Copyright (c) 2004 Google Inc.; see LICENSE */
1802
1803 // #include <stdarg.h>
1804 // #include <string.h>
1805 // #include "plan9.h"
1806 // #include "fmt.h"
1807 // #include "fmtdef.h"
1808
1809 /*
1810 * Fill in the internationalization stuff in the State structure.
1811 * For nil arguments, provide the sensible defaults:
1812 * decimal is a period
1813 * thousands separator is a comma
1814 * thousands are marked every three digits
1815 */
1816 void
1817 fmtlocaleinit(Fmt *f, char *decimal, char *thousands, char *grouping)
1818 {
1819 if(decimal == nil || decimal[0] == '\0')
1820 decimal = ".";
1821 if(thousands == nil)
1822 thousands = ",";
1823 if(grouping == nil)
1824 grouping = "\3";
1825 f->decimal = decimal;
1826 f->thousands = thousands;
1827 f->grouping = grouping;
1828 }
1829
1830 /*
1831 * We are about to emit a digit in e.g. %'d. If that digit would
1832 * overflow a thousands (e.g.) grouping, tell the caller to emit
1833 * the thousands separator. Always advance the digit counter
1834 * and pointer into the grouping descriptor.
1835 */
1836 int
1837 __needsep(int *ndig, char **grouping)
1838 {
1839 int group;
1840
1841 (*ndig)++;
1842 group = *(unsigned char*)*grouping;
1843 /* CHAR_MAX means no further grouping. \0 means we got the empty string */
1844 if(group == 0xFF || group == 0x7f || group == 0x00)
1845 return 0;
1846 if(*ndig > group){
1847 /* if we're at end of string, continue with this grouping; else advance */
1848 if((*grouping)[1] != '\0')
1849 (*grouping)++;
1850 *ndig = 1;
1851 return 1;
1852 }
1853 return 0;
1854 }
1855
1856 /* -------------- fmtlock.c --------------- */
1857 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
1858 // #include <stdarg.h>
1859 // #include "plan9.h"
1860 // #include "fmt.h"
1861 // #include "fmtdef.h"
1862
1863 void
1864 __fmtlock(void)
1865 {
1866 }
1867
1868 void
1869 __fmtunlock(void)
1870 {
1871 }
1872 /* -------------- fmtnull.c --------------- */
1873 /* Copyright (c) 2004 Google Inc.; see LICENSE */
1874 // #include <stdarg.h>
1875 // #include <string.h>
1876 // #include "plan9.h"
1877 // #include "fmt.h"
1878 // #include "fmtdef.h"
1879
1880 /*
1881 * Absorb output without using resources.
1882 */
1883 static Rune nullbuf[32];
1884
1885 static int
1886 __fmtnullflush(Fmt *f)
1887 {
1888 f->to = nullbuf;
1889 f->nfmt = 0;
1890 return 0;
1891 }
1892
1893 int
1894 fmtnullinit(Fmt *f)
1895 {
1896 memset(f, 0, sizeof *f);
1897 f->runes = 1;
1898 f->start = nullbuf;
1899 f->to = nullbuf;
1900 f->stop = nullbuf+nelem(nullbuf);
1901 f->flush = __fmtnullflush;
1902 fmtlocaleinit(f, nil, nil, nil);
1903 return 0;
1904 }
1905
1906 /* -------------- fmtprint.c --------------- */
1907 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
1908 // #include <stdarg.h>
1909 // #include <string.h>
1910 // #include "plan9.h"
1911 // #include "fmt.h"
1912 // #include "fmtdef.h"
1913
1914 /*
1915 * format a string into the output buffer
1916 * designed for formats which themselves call fmt,
1917 * but ignore any width flags
1918 */
1919 int
1920 fmtprint(Fmt *f, char *fmt, ...)
1921 {
1922 va_list va;
1923 int n;
1924
1925 f->flags = 0;
1926 f->width = 0;
1927 f->prec = 0;
1928 VA_COPY(va, f->args);
1929 VA_END(f->args);
1930 va_start(f->args, fmt);
1931 n = dofmt(f, fmt);
1932 va_end(f->args);
1933 f->flags = 0;
1934 f->width = 0;
1935 f->prec = 0;
1936 VA_COPY(f->args,va);
1937 VA_END(va);
1938 if(n >= 0)
1939 return 0;
1940 return n;
1941 }
1942
1943 /* -------------- fmtquote.c --------------- */
1944 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
1945 // #include <stdarg.h>
1946 // #include <string.h>
1947 // #include "plan9.h"
1948 // #include "fmt.h"
1949 // #include "fmtdef.h"
1950
1951 /*
1952 * How many bytes of output UTF will be produced by quoting (if necessary) this string?
1953 * How many runes? How much of the input will be consumed?
1954 * The parameter q is filled in by __quotesetup.
1955 * The string may be UTF or Runes (s or r).
1956 * Return count does not include NUL.
1957 * Terminate the scan at the first of:
1958 * NUL in input
1959 * count exceeded in input
1960 * count exceeded on output
1961 * *ninp is set to number of input bytes accepted.
1962 * nin may be <0 initially, to avoid checking input by count.
1963 */
1964 void
1965 __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout)
1966 {
1967 int w;
1968 Rune c;
1969
1970 q->quoted = 0;
1971 q->nbytesout = 0;
1972 q->nrunesout = 0;
1973 q->nbytesin = 0;
1974 q->nrunesin = 0;
1975 if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){
1976 if(nout < 2)
1977 return;
1978 q->quoted = 1;
1979 q->nbytesout = 2;
1980 q->nrunesout = 2;
1981 }
1982 for(; nin!=0; nin--){
1983 if(s)
1984 w = chartorune(&c, s);
1985 else{
1986 c = *r;
1987 w = runelen(c);
1988 }
1989
1990 if(c == '\0')
1991 break;
1992 if(runesout){
1993 if(q->nrunesout+1 > nout)
1994 break;
1995 }else{
1996 if(q->nbytesout+w > nout)
1997 break;
1998 }
1999
2000 if((c <= L' ') || (c == L'\'') || (fmtdoquote!=nil && fmtdoquote(c))){
2001 if(!q->quoted){
2002 if(runesout){
2003 if(1+q->nrunesout+1+1 > nout) /* no room for quotes */
2004 break;
2005 }else{
2006 if(1+q->nbytesout+w+1 > nout) /* no room for quotes */
2007 break;
2008 }
2009 q->nrunesout += 2; /* include quotes */
2010 q->nbytesout += 2; /* include quotes */
2011 q->quoted = 1;
2012 }
2013 if(c == '\'') {
2014 if(runesout){
2015 if(1+q->nrunesout+1 > nout) /* no room for quotes */
2016 break;
2017 }else{
2018 if(1+q->nbytesout+w > nout) /* no room for quotes */
2019 break;
2020 }
2021 q->nbytesout++;
2022 q->nrunesout++; /* quotes reproduce as two characters */
2023 }
2024 }
2025
2026 /* advance input */
2027 if(s)
2028 s += w;
2029 else
2030 r++;
2031 q->nbytesin += w;
2032 q->nrunesin++;
2033
2034 /* advance output */
2035 q->nbytesout += w;
2036 q->nrunesout++;
2037
2038 #ifndef PLAN9PORT
2039 /* ANSI requires precision in bytes, not Runes. */
2040 nin-= w-1; /* and then n-- in the loop */
2041 #endif
2042 }
2043 }
2044
2045 static int
2046 qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f)
2047 {
2048 Rune r, *rm, *rme;
2049 char *t, *s, *m, *me;
2050 Rune *rt, *rs;
2051 ulong fl;
2052 int nc, w;
2053
2054 m = sin;
2055 me = m + q->nbytesin;
2056 rm = rin;
2057 rme = rm + q->nrunesin;
2058
2059 fl = f->flags;
2060 w = 0;
2061 if(fl & FmtWidth)
2062 w = f->width;
2063 if(f->runes){
2064 if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0)
2065 return -1;
2066 }else{
2067 if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0)
2068 return -1;
2069 }
2070 t = (char*)f->to;
2071 s = (char*)f->stop;
2072 rt = (Rune*)f->to;
2073 rs = (Rune*)f->stop;
2074 if(f->runes)
2075 FMTRCHAR(f, rt, rs, '\'');
2076 else
2077 FMTRUNE(f, t, s, '\'');
2078 for(nc = q->nrunesin; nc > 0; nc--){
2079 if(sin){
2080 r = *(uchar*)m;
2081 if(r < Runeself)
2082 m++;
2083 else if((me - m) >= UTFmax || fullrune(m, me-m))
2084 m += chartorune(&r, m);
2085 else
2086 break;
2087 }else{
2088 if(rm >= rme)
2089 break;
2090 r = *(uchar*)rm++;
2091 }
2092 if(f->runes){
2093 FMTRCHAR(f, rt, rs, r);
2094 if(r == '\'')
2095 FMTRCHAR(f, rt, rs, r);
2096 }else{
2097 FMTRUNE(f, t, s, r);
2098 if(r == '\'')
2099 FMTRUNE(f, t, s, r);
2100 }
2101 }
2102
2103 if(f->runes){
2104 FMTRCHAR(f, rt, rs, '\'');
2105 USED(rs);
2106 f->nfmt += rt - (Rune *)f->to;
2107 f->to = rt;
2108 if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0)
2109 return -1;
2110 }else{
2111 FMTRUNE(f, t, s, '\'');
2112 USED(s);
2113 f->nfmt += t - (char *)f->to;
2114 f->to = t;
2115 if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0)
2116 return -1;
2117 }
2118 return 0;
2119 }
2120
2121 int
2122 __quotestrfmt(int runesin, Fmt *f)
2123 {
2124 int nin, outlen;
2125 Rune *r;
2126 char *s;
2127 Quoteinfo q;
2128
2129 nin = -1;
2130 if(f->flags&FmtPrec)
2131 nin = f->prec;
2132 if(runesin){
2133 r = va_arg(f->args, Rune *);
2134 s = nil;
2135 }else{
2136 s = va_arg(f->args, char *);
2137 r = nil;
2138 }
2139 if(!s && !r)
2140 return __fmtcpy(f, (void*)"<nil>", 5, 5);
2141
2142 if(f->flush)
2143 outlen = 0x7FFFFFFF; /* if we can flush, no output limit */
2144 else if(f->runes)
2145 outlen = (Rune*)f->stop - (Rune*)f->to;
2146 else
2147 outlen = (char*)f->stop - (char*)f->to;
2148
2149 __quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes);
2150 /*print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); */
2151
2152 if(runesin){
2153 if(!q.quoted)
2154 return __fmtrcpy(f, r, q.nrunesin);
2155 return qstrfmt(nil, r, &q, f);
2156 }
2157
2158 if(!q.quoted)
2159 return __fmtcpy(f, s, q.nrunesin, q.nbytesin);
2160 return qstrfmt(s, nil, &q, f);
2161 }
2162
2163 int
2164 quotestrfmt(Fmt *f)
2165 {
2166 return __quotestrfmt(0, f);
2167 }
2168
2169 int
2170 quoterunestrfmt(Fmt *f)
2171 {
2172 return __quotestrfmt(1, f);
2173 }
2174
2175 void
2176 quotefmtinstall(void)
2177 {
2178 fmtinstall('q', quotestrfmt);
2179 fmtinstall('Q', quoterunestrfmt);
2180 }
2181
2182 int
2183 __needsquotes(char *s, int *quotelenp)
2184 {
2185 Quoteinfo q;
2186
2187 __quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0);
2188 *quotelenp = q.nbytesout;
2189
2190 return q.quoted;
2191 }
2192
2193 int
2194 __runeneedsquotes(Rune *r, int *quotelenp)
2195 {
2196 Quoteinfo q;
2197
2198 __quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0);
2199 *quotelenp = q.nrunesout;
2200
2201 return q.quoted;
2202 }
2203 /* -------------- fmtrune.c --------------- */
2204 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2205 // #include <stdarg.h>
2206 // #include <string.h>
2207 // #include "plan9.h"
2208 // #include "fmt.h"
2209 // #include "fmtdef.h"
2210
2211 int
2212 fmtrune(Fmt *f, int r)
2213 {
2214 Rune *rt;
2215 char *t;
2216 int n;
2217
2218 if(f->runes){
2219 rt = (Rune*)f->to;
2220 FMTRCHAR(f, rt, f->stop, r);
2221 f->to = rt;
2222 n = 1;
2223 }else{
2224 t = (char*)f->to;
2225 FMTRUNE(f, t, f->stop, r);
2226 n = t - (char*)f->to;
2227 f->to = t;
2228 }
2229 f->nfmt += n;
2230 return 0;
2231 }
2232 /* -------------- fmtstr.c --------------- */
2233 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2234 // #include <stdlib.h>
2235 // #include <stdarg.h>
2236 // #include "plan9.h"
2237 // #include "fmt.h"
2238 // #include "fmtdef.h"
2239
2240 char*
2241 fmtstrflush(Fmt *f)
2242 {
2243 if(f->start == nil)
2244 return nil;
2245 *(char*)f->to = '\0';
2246 f->to = f->start;
2247 return (char*)f->start;
2248 }
2249 /* -------------- fmtvprint.c --------------- */
2250 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2251 // #include <stdarg.h>
2252 // #include <string.h>
2253 // #include "plan9.h"
2254 // #include "fmt.h"
2255 // #include "fmtdef.h"
2256
2257
2258 /*
2259 * format a string into the output buffer
2260 * designed for formats which themselves call fmt,
2261 * but ignore any width flags
2262 */
2263 int
2264 fmtvprint(Fmt *f, char *fmt, va_list args)
2265 {
2266 va_list va;
2267 int n;
2268
2269 f->flags = 0;
2270 f->width = 0;
2271 f->prec = 0;
2272 VA_COPY(va,f->args);
2273 VA_END(f->args);
2274 VA_COPY(f->args,args);
2275 n = dofmt(f, fmt);
2276 f->flags = 0;
2277 f->width = 0;
2278 f->prec = 0;
2279 VA_END(f->args);
2280 VA_COPY(f->args,va);
2281 VA_END(va);
2282 if(n >= 0)
2283 return 0;
2284 return n;
2285 }
2286
2287 /* -------------- fprint.c --------------- */
2288 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2289 // #include <stdarg.h>
2290 // #include "plan9.h"
2291 // #include "fmt.h"
2292 // #include "fmtdef.h"
2293
2294 int
2295 fprint(int fd, char *fmt, ...)
2296 {
2297 int n;
2298 va_list args;
2299
2300 va_start(args, fmt);
2301 n = vfprint(fd, fmt, args);
2302 va_end(args);
2303 return n;
2304 }
2305 /* -------------- nan64.c --------------- */
2306 /*
2307 * 64-bit IEEE not-a-number routines.
2308 * This is big/little-endian portable assuming that
2309 * the 64-bit doubles and 64-bit integers have the
2310 * same byte ordering.
2311 */
2312
2313 // #include "plan9.h"
2314 // #include "fmt.h"
2315 // #include "fmtdef.h"
2316
2317 #if defined (__APPLE__) || (__powerpc__)
2318 #define _NEEDLL
2319 #endif
2320
2321 static uvlong uvnan = ((uvlong)0x7FF00000<<32)|0x00000001;
2322 static uvlong uvinf = ((uvlong)0x7FF00000<<32)|0x00000000;
2323 static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000;
2324
2325 double
2326 __NaN(void)
2327 {
2328 uvlong *p;
2329
2330 /* gcc complains about "return *(double*)&uvnan;" */
2331 p = &uvnan;
2332 return *(double*)p;
2333 }
2334
2335 int
2336 __isNaN(double d)
2337 {
2338 uvlong x;
2339 double *p;
2340
2341 p = &d;
2342 x = *(uvlong*)p;
2343 return (ulong)(x>>32)==0x7FF00000 && !__isInf(d, 0);
2344 }
2345
2346 double
2347 __Inf(int sign)
2348 {
2349 uvlong *p;
2350
2351 if(sign < 0)
2352 p = &uvinf;
2353 else
2354 p = &uvneginf;
2355 return *(double*)p;
2356 }
2357
2358 int
2359 __isInf(double d, int sign)
2360 {
2361 uvlong x;
2362 double *p;
2363
2364 p = &d;
2365 x = *(uvlong*)p;
2366 if(sign == 0)
2367 return x==uvinf || x==uvneginf;
2368 else if(sign > 0)
2369 return x==uvinf;
2370 else
2371 return x==uvneginf;
2372 }
2373 /* -------------- pow10.c --------------- */
2374 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2375 // #include <stdarg.h>
2376 // #include <string.h>
2377 // #include "plan9.h"
2378 // #include "fmt.h"
2379 // #include "fmtdef.h"
2380
2381 /*
2382 * this table might overflow 127-bit exponent representations.
2383 * in that case, truncate it after 1.0e38.
2384 * it is important to get all one can from this
2385 * routine since it is used in atof to scale numbers.
2386 * the presumption is that C converts fp numbers better
2387 * than multipication of lower powers of 10.
2388 */
2389
2390 static
2391 double tab[] =
2392 {
2393 1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9,
2394 1.0e10,1.0e11,1.0e12,1.0e13,1.0e14,1.0e15,1.0e16,1.0e17,1.0e18,1.0e19,
2395 1.0e20,1.0e21,1.0e22,1.0e23,1.0e24,1.0e25,1.0e26,1.0e27,1.0e28,1.0e29,
2396 1.0e30,1.0e31,1.0e32,1.0e33,1.0e34,1.0e35,1.0e36,1.0e37,1.0e38,1.0e39,
2397 1.0e40,1.0e41,1.0e42,1.0e43,1.0e44,1.0e45,1.0e46,1.0e47,1.0e48,1.0e49,
2398 1.0e50,1.0e51,1.0e52,1.0e53,1.0e54,1.0e55,1.0e56,1.0e57,1.0e58,1.0e59,
2399 1.0e60,1.0e61,1.0e62,1.0e63,1.0e64,1.0e65,1.0e66,1.0e67,1.0e68,1.0e69,
2400 };
2401
2402 double
2403 __fmtpow10(int n)
2404 {
2405 int m;
2406
2407 if(n < 0) {
2408 n = -n;
2409 if(n < (int)(sizeof(tab)/sizeof(tab[0])))
2410 return 1/tab[n];
2411 m = n/2;
2412 return __fmtpow10(-m) * __fmtpow10(m-n);
2413 }
2414 if(n < (int)(sizeof(tab)/sizeof(tab[0])))
2415 return tab[n];
2416 m = n/2;
2417 return __fmtpow10(m) * __fmtpow10(n-m);
2418 }
2419 /* -------------- print.c --------------- */
2420 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2421 // #include <stdarg.h>
2422 // #include "plan9.h"
2423 // #include "fmt.h"
2424 // #include "fmtdef.h"
2425
2426 /*
2427 int
2428 print(char *fmt, ...)
2429 {
2430 int n;
2431 va_list args;
2432
2433 va_start(args, fmt);
2434 n = vfprint(1, fmt, args);
2435 va_end(args);
2436 return n;
2437 }
2438 */
2439
2440 /* -------------- runefmtstr.c --------------- */
2441 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2442 // #include <stdarg.h>
2443 // #include <stdlib.h>
2444 // #include "plan9.h"
2445 // #include "fmt.h"
2446 // #include "fmtdef.h"
2447
2448 Rune*
2449 runefmtstrflush(Fmt *f)
2450 {
2451 if(f->start == nil)
2452 return nil;
2453 *(Rune*)f->to = '\0';
2454 f->to = f->start;
2455 return f->start;
2456 }
2457 /* -------------- runeseprint.c --------------- */
2458 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2459 // #include <stdarg.h>
2460 // #include <string.h>
2461 // #include "plan9.h"
2462 // #include "fmt.h"
2463 // #include "fmtdef.h"
2464
2465 Rune*
2466 runeseprint(Rune *buf, Rune *e, char *fmt, ...)
2467 {
2468 Rune *p;
2469 va_list args;
2470
2471 va_start(args, fmt);
2472 p = runevseprint(buf, e, fmt, args);
2473 va_end(args);
2474 return p;
2475 }
2476 /* -------------- runesmprint.c --------------- */
2477 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2478 // #include <stdarg.h>
2479 // #include <string.h>
2480 // #include "plan9.h"
2481 // #include "fmt.h"
2482 // #include "fmtdef.h"
2483
2484 Rune*
2485 runesmprint(char *fmt, ...)
2486 {
2487 va_list args;
2488 Rune *p;
2489
2490 va_start(args, fmt);
2491 p = runevsmprint(fmt, args);
2492 va_end(args);
2493 return p;
2494 }
2495 /* -------------- runesnprint.c --------------- */
2496 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2497 // #include <stdarg.h>
2498 // #include <string.h>
2499 // #include "plan9.h"
2500 // #include "fmt.h"
2501 // #include "fmtdef.h"
2502
2503 int
2504 runesnprint(Rune *buf, int len, char *fmt, ...)
2505 {
2506 int n;
2507 va_list args;
2508
2509 va_start(args, fmt);
2510 n = runevsnprint(buf, len, fmt, args);
2511 va_end(args);
2512 return n;
2513 }
2514
2515 /* -------------- runesprint.c --------------- */
2516 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2517 // #include <stdarg.h>
2518 // #include <string.h>
2519 // #include "plan9.h"
2520 // #include "fmt.h"
2521 // #include "fmtdef.h"
2522
2523 int
2524 runesprint(Rune *buf, char *fmt, ...)
2525 {
2526 int n;
2527 va_list args;
2528
2529 va_start(args, fmt);
2530 n = runevsnprint(buf, 256, fmt, args);
2531 va_end(args);
2532 return n;
2533 }
2534 /* -------------- runevseprint.c --------------- */
2535 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2536 // #include <stdarg.h>
2537 // #include <string.h>
2538 // #include "plan9.h"
2539 // #include "fmt.h"
2540 // #include "fmtdef.h"
2541
2542 Rune*
2543 runevseprint(Rune *buf, Rune *e, char *fmt, va_list args)
2544 {
2545 Fmt f;
2546
2547 if(e <= buf)
2548 return nil;
2549 f.runes = 1;
2550 f.start = buf;
2551 f.to = buf;
2552 f.stop = e - 1;
2553 f.flush = nil;
2554 f.farg = nil;
2555 f.nfmt = 0;
2556 VA_COPY(f.args,args);
2557 fmtlocaleinit(&f, nil, nil, nil);
2558 dofmt(&f, fmt);
2559 VA_END(f.args);
2560 *(Rune*)f.to = '\0';
2561 return (Rune*)f.to;
2562 }
2563
2564 /* -------------- runevsmprint.c --------------- */
2565 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2566 /*
2567 * Plan 9 port version must include libc.h in order to
2568 * get Plan 9 debugging malloc, which sometimes returns
2569 * different pointers than the standard malloc.
2570 */
2571 #ifdef PLAN9PORT
2572 // #include <u.h>
2573 // #include <libc.h>
2574 // #include "fmtdef.h"
2575 #else
2576 // #include <stdlib.h>
2577 // #include <string.h>
2578 // #include "plan9.h"
2579 // #include "fmt.h"
2580 // #include "fmtdef.h"
2581 #endif
2582
2583 static int
2584 runeFmtStrFlush(Fmt *f)
2585 {
2586 Rune *s;
2587 int n;
2588
2589 if(f->start == nil)
2590 return 0;
2591 n = (uintptr)f->farg;
2592 n *= 2;
2593 s = (Rune*)f->start;
2594 f->start = realloc(s, sizeof(Rune)*n);
2595 if(f->start == nil){
2596 f->farg = nil;
2597 f->to = nil;
2598 f->stop = nil;
2599 free(s);
2600 return 0;
2601 }
2602 f->farg = (void*)(uintptr)n;
2603 f->to = (Rune*)f->start + ((Rune*)f->to - s);
2604 f->stop = (Rune*)f->start + n - 1;
2605 return 1;
2606 }
2607
2608 int
2609 runefmtstrinit(Fmt *f)
2610 {
2611 int n;
2612
2613 memset(f, 0, sizeof *f);
2614 f->runes = 1;
2615 n = 32;
2616 f->start = malloc(sizeof(Rune)*n);
2617 if(f->start == nil)
2618 return -1;
2619 f->to = f->start;
2620 f->stop = (Rune*)f->start + n - 1;
2621 f->flush = runeFmtStrFlush;
2622 f->farg = (void*)(uintptr)n;
2623 f->nfmt = 0;
2624 fmtlocaleinit(f, nil, nil, nil);
2625 return 0;
2626 }
2627
2628 /*
2629 * print into an allocated string buffer
2630 */
2631 Rune*
2632 runevsmprint(char *fmt, va_list args)
2633 {
2634 Fmt f;
2635 int n;
2636
2637 if(runefmtstrinit(&f) < 0)
2638 return nil;
2639 VA_COPY(f.args,args);
2640 n = dofmt(&f, fmt);
2641 VA_END(f.args);
2642 if(f.start == nil)
2643 return nil;
2644 if(n < 0){
2645 free(f.start);
2646 return nil;
2647 }
2648 *(Rune*)f.to = '\0';
2649 return (Rune*)f.start;
2650 }
2651 /* -------------- runevsnprint.c --------------- */
2652 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2653 // #include <stdarg.h>
2654 // #include <string.h>
2655 // #include "plan9.h"
2656 // #include "fmt.h"
2657 // #include "fmtdef.h"
2658
2659 int
2660 runevsnprint(Rune *buf, int len, char *fmt, va_list args)
2661 {
2662 Fmt f;
2663
2664 if(len <= 0)
2665 return -1;
2666 f.runes = 1;
2667 f.start = buf;
2668 f.to = buf;
2669 f.stop = buf + len - 1;
2670 f.flush = nil;
2671 f.farg = nil;
2672 f.nfmt = 0;
2673 VA_COPY(f.args,args);
2674 fmtlocaleinit(&f, nil, nil, nil);
2675 dofmt(&f, fmt);
2676 VA_END(f.args);
2677 *(Rune*)f.to = '\0';
2678 return (Rune*)f.to - buf;
2679 }
2680 /* -------------- seprint.c --------------- */
2681 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2682 // #include <stdarg.h>
2683 // #include "plan9.h"
2684 // #include "fmt.h"
2685 // #include "fmtdef.h"
2686
2687 char*
2688 seprint(char *buf, char *e, char *fmt, ...)
2689 {
2690 char *p;
2691 va_list args;
2692
2693 va_start(args, fmt);
2694 p = vseprint(buf, e, fmt, args);
2695 va_end(args);
2696 return p;
2697 }
2698 /* -------------- smprint.c --------------- */
2699 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2700 // #include <stdarg.h>
2701 // #include "plan9.h"
2702 // #include "fmt.h"
2703 // #include "fmtdef.h"
2704
2705 char*
2706 smprint(char *fmt, ...)
2707 {
2708 va_list args;
2709 char *p;
2710
2711 va_start(args, fmt);
2712 p = vsmprint(fmt, args);
2713 va_end(args);
2714 return p;
2715 }
2716 /* -------------- snprint.c --------------- */
2717 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2718 // #include <stdarg.h>
2719 // #include "plan9.h"
2720 // #include "fmt.h"
2721 // #include "fmtdef.h"
2722
2723 int
2724 snprint(char *buf, int len, char *fmt, ...)
2725 {
2726 int n;
2727 va_list args;
2728
2729 va_start(args, fmt);
2730 n = vsnprint(buf, len, fmt, args);
2731 va_end(args);
2732 return n;
2733 }
2734
2735 /* -------------- sprint.c --------------- */
2736 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2737 // #include <stdarg.h>
2738 // #include <fmt.h>
2739 // #include "plan9.h"
2740 // #include "fmt.h"
2741 // #include "fmtdef.h"
2742
2743 int
2744 sprint(char *buf, char *fmt, ...)
2745 {
2746 int n;
2747 va_list args;
2748
2749 va_start(args, fmt);
2750 n = vsnprint(buf, 65536, fmt, args);
2751 va_end(args);
2752 return n;
2753 }
2754 /* -------------- strtod.c --------------- */
2755 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2756 // #include <stdlib.h>
2757 // #include <math.h>
2758 // #include <ctype.h>
2759 // #include <stdlib.h>
2760 // #include <string.h>
2761 // #include <errno.h>
2762 // #include "plan9.h"
2763 // #include "fmt.h"
2764 // #include "fmtdef.h"
2765
2766 static ulong
2767 umuldiv(ulong a, ulong b, ulong c)
2768 {
2769 double d;
2770
2771 d = ((double)a * (double)b) / (double)c;
2772 if(d >= 4294967295.)
2773 d = 4294967295.;
2774 return (ulong)d;
2775 }
2776
2777 /*
2778 * This routine will convert to arbitrary precision
2779 * floating point entirely in multi-precision fixed.
2780 * The answer is the closest floating point number to
2781 * the given decimal number. Exactly half way are
2782 * rounded ala ieee rules.
2783 * Method is to scale input decimal between .500 and .999...
2784 * with external power of 2, then binary search for the
2785 * closest mantissa to this decimal number.
2786 * Nmant is is the required precision. (53 for ieee dp)
2787 * Nbits is the max number of bits/word. (must be <= 28)
2788 * Prec is calculated - the number of words of fixed mantissa.
2789 */
2790 enum
2791 {
2792 Nbits = 28, /* bits safely represented in a ulong */
2793 Nmant = 53, /* bits of precision required */
2794 Prec = (Nmant+Nbits+1)/Nbits, /* words of Nbits each to represent mantissa */
2795 Sigbit = 1<<(Prec*Nbits-Nmant), /* first significant bit of Prec-th word */
2796 Ndig = 1500,
2797 One = (ulong)(1<<Nbits),
2798 Half = (ulong)(One>>1),
2799 Maxe = 310,
2800
2801 Fsign = 1<<0, /* found - */
2802 Fesign = 1<<1, /* found e- */
2803 Fdpoint = 1<<2, /* found . */
2804
2805 S0 = 0, /* _ _S0 +S1 #S2 .S3 */
2806 S1, /* _+ #S2 .S3 */
2807 S2, /* _+# #S2 .S4 eS5 */
2808 S3, /* _+. #S4 */
2809 S4, /* _+#.# #S4 eS5 */
2810 S5, /* _+#.#e +S6 #S7 */
2811 S6, /* _+#.#e+ #S7 */
2812 S7 /* _+#.#e+# #S7 */
2813 };
2814
2815 static int xcmp(char*, char*);
2816 static int fpcmp(char*, ulong*);
2817 static void frnorm(ulong*);
2818 static void divascii(char*, int*, int*, int*);
2819 static void mulascii(char*, int*, int*, int*);
2820
2821 typedef struct Tab Tab;
2822 struct Tab
2823 {
2824 int bp;
2825 int siz;
2826 char* cmp;
2827 };
2828
2829 double
2830 fmtstrtod(const char *as, char **aas)
2831 {
2832 int na, ex, dp, bp, c, i, flag, state;
2833 ulong low[Prec], hig[Prec], mid[Prec];
2834 double d;
2835 char *s, a[Ndig];
2836
2837 flag = 0; /* Fsign, Fesign, Fdpoint */
2838 na = 0; /* number of digits of a[] */
2839 dp = 0; /* na of decimal point */
2840 ex = 0; /* exonent */
2841
2842 state = S0;
2843 for(s=(char*)as;; s++) {
2844 c = *s;
2845 if(c >= '0' && c <= '9') {
2846 switch(state) {
2847 case S0:
2848 case S1:
2849 case S2:
2850 state = S2;
2851 break;
2852 case S3:
2853 case S4:
2854 state = S4;
2855 break;
2856
2857 case S5:
2858 case S6:
2859 case S7:
2860 state = S7;
2861 ex = ex*10 + (c-'0');
2862 continue;
2863 }
2864 if(na == 0 && c == '0') {
2865 dp--;
2866 continue;
2867 }
2868 if(na < Ndig-50)
2869 a[na++] = c;
2870 continue;
2871 }
2872 switch(c) {
2873 case '\t':
2874 case '\n':
2875 case '\v':
2876 case '\f':
2877 case '\r':
2878 case ' ':
2879 if(state == S0)
2880 continue;
2881 break;
2882 case '-':
2883 if(state == S0)
2884 flag |= Fsign;
2885 else
2886 flag |= Fesign;
2887 case '+':
2888 if(state == S0)
2889 state = S1;
2890 else
2891 if(state == S5)
2892 state = S6;
2893 else
2894 break; /* syntax */
2895 continue;
2896 case '.':
2897 flag |= Fdpoint;
2898 dp = na;
2899 if(state == S0 || state == S1) {
2900 state = S3;
2901 continue;
2902 }
2903 if(state == S2) {
2904 state = S4;
2905 continue;
2906 }
2907 break;
2908 case 'e':
2909 case 'E':
2910 if(state == S2 || state == S4) {
2911 state = S5;
2912 continue;
2913 }
2914 break;
2915 }
2916 break;
2917 }
2918
2919 /*
2920 * clean up return char-pointer
2921 */
2922 switch(state) {
2923 case S0:
2924 if(xcmp(s, "nan") == 0) {
2925 if(aas != nil)
2926 *aas = s+3;
2927 goto retnan;
2928 }
2929 case S1:
2930 if(xcmp(s, "infinity") == 0) {
2931 if(aas != nil)
2932 *aas = s+8;
2933 goto retinf;
2934 }
2935 if(xcmp(s, "inf") == 0) {
2936 if(aas != nil)
2937 *aas = s+3;
2938 goto retinf;
2939 }
2940 case S3:
2941 if(aas != nil)
2942 *aas = (char*)as;
2943 goto ret0; /* no digits found */
2944 case S6:
2945 s--; /* back over +- */
2946 case S5:
2947 s--; /* back over e */
2948 break;
2949 }
2950 if(aas != nil)
2951 *aas = s;
2952
2953 if(flag & Fdpoint)
2954 while(na > 0 && a[na-1] == '0')
2955 na--;
2956 if(na == 0)
2957 goto ret0; /* zero */
2958 a[na] = 0;
2959 if(!(flag & Fdpoint))
2960 dp = na;
2961 if(flag & Fesign)
2962 ex = -ex;
2963 dp += ex;
2964 if(dp < -Maxe){
2965 errno = ERANGE;
2966 goto ret0; /* underflow by exp */
2967 } else
2968 if(dp > +Maxe)
2969 goto retinf; /* overflow by exp */
2970
2971 /*
2972 * normalize the decimal ascii number
2973 * to range .[5-9][0-9]* e0
2974 */
2975 bp = 0; /* binary exponent */
2976 while(dp > 0)
2977 divascii(a, &na, &dp, &bp);
2978 while(dp < 0 || a[0] < '5')
2979 mulascii(a, &na, &dp, &bp);
2980
2981 /* close approx by naive conversion */
2982 mid[0] = 0;
2983 mid[1] = 1;
2984 for(i=0; (c=a[i]) != '\0'; i++) {
2985 mid[0] = mid[0]*10 + (c-'0');
2986 mid[1] = mid[1]*10;
2987 if(i >= 8)
2988 break;
2989 }
2990 low[0] = umuldiv(mid[0], One, mid[1]);
2991 hig[0] = umuldiv(mid[0]+1, One, mid[1]);
2992 for(i=1; i<Prec; i++) {
2993 low[i] = 0;
2994 hig[i] = One-1;
2995 }
2996
2997 /* binary search for closest mantissa */
2998 for(;;) {
2999 /* mid = (hig + low) / 2 */
3000 c = 0;
3001 for(i=0; i<Prec; i++) {
3002 mid[i] = hig[i] + low[i];
3003 if(c)
3004 mid[i] += One;
3005 c = mid[i] & 1;
3006 mid[i] >>= 1;
3007 }
3008 frnorm(mid);
3009
3010 /* compare */
3011 c = fpcmp(a, mid);
3012 if(c > 0) {
3013 c = 1;
3014 for(i=0; i<Prec; i++)
3015 if(low[i] != mid[i]) {
3016 c = 0;
3017 low[i] = mid[i];
3018 }
3019 if(c)
3020 break; /* between mid and hig */
3021 continue;
3022 }
3023 if(c < 0) {
3024 for(i=0; i<Prec; i++)
3025 hig[i] = mid[i];
3026 continue;
3027 }
3028
3029 /* only hard part is if even/odd roundings wants to go up */
3030 c = mid[Prec-1] & (Sigbit-1);
3031 if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0)
3032 mid[Prec-1] -= c;
3033 break; /* exactly mid */
3034 }
3035
3036 /* normal rounding applies */
3037 c = mid[Prec-1] & (Sigbit-1);
3038 mid[Prec-1] -= c;
3039 if(c >= Sigbit/2) {
3040 mid[Prec-1] += Sigbit;
3041 frnorm(mid);
3042 }
3043 goto out;
3044
3045 ret0:
3046 return 0;
3047
3048 retnan:
3049 return __NaN();
3050
3051 retinf:
3052 /*
3053 * Unix strtod requires these. Plan 9 would return Inf(0) or Inf(-1). */
3054 errno = ERANGE;
3055 if(flag & Fsign)
3056 return -HUGE_VAL;
3057 return HUGE_VAL;
3058
3059 out:
3060 d = 0;
3061 for(i=0; i<Prec; i++)
3062 d = d*One + mid[i];
3063 if(flag & Fsign)
3064 d = -d;
3065 d = ldexp(d, bp - Prec*Nbits);
3066 if(d == 0){ /* underflow */
3067 errno = ERANGE;
3068 }
3069 return d;
3070 }
3071
3072 static void
3073 frnorm(ulong *f)
3074 {
3075 int i, c;
3076
3077 c = 0;
3078 for(i=Prec-1; i>0; i--) {
3079 f[i] += c;
3080 c = f[i] >> Nbits;
3081 f[i] &= One-1;
3082 }
3083 f[0] += c;
3084 }
3085
3086 static int
3087 fpcmp(char *a, ulong* f)
3088 {
3089 ulong tf[Prec];
3090 int i, d, c;
3091
3092 for(i=0; i<Prec; i++)
3093 tf[i] = f[i];
3094
3095 for(;;) {
3096 /* tf *= 10 */
3097 for(i=0; i<Prec; i++)
3098 tf[i] = tf[i]*10;
3099 frnorm(tf);
3100 d = (tf[0] >> Nbits) + '0';
3101 tf[0] &= One-1;
3102
3103 /* compare next digit */
3104 c = *a;
3105 if(c == 0) {
3106 if('0' < d)
3107 return -1;
3108 if(tf[0] != 0)
3109 goto cont;
3110 for(i=1; i<Prec; i++)
3111 if(tf[i] != 0)
3112 goto cont;
3113 return 0;
3114 }
3115 if(c > d)
3116 return +1;
3117 if(c < d)
3118 return -1;
3119 a++;
3120 cont:;
3121 }
3122 }
3123
3124 static void
3125 divby(char *a, int *na, int b)
3126 {
3127 int n, c;
3128 char *p;
3129
3130 p = a;
3131 n = 0;
3132 while(n>>b == 0) {
3133 c = *a++;
3134 if(c == 0) {
3135 while(n) {
3136 c = n*10;
3137 if(c>>b)
3138 break;
3139 n = c;
3140 }
3141 goto xx;
3142 }
3143 n = n*10 + c-'0';
3144 (*na)--;
3145 }
3146 for(;;) {
3147 c = n>>b;
3148 n -= c<<b;
3149 *p++ = c + '0';
3150 c = *a++;
3151 if(c == 0)
3152 break;
3153 n = n*10 + c-'0';
3154 }
3155 (*na)++;
3156 xx:
3157 while(n) {
3158 n = n*10;
3159 c = n>>b;
3160 n -= c<<b;
3161 *p++ = c + '0';
3162 (*na)++;
3163 }
3164 *p = 0;
3165 }
3166
3167 static Tab tab1[] =
3168 {
3169 { 1, 0, "" },
3170 { 3, 1, "7" },
3171 { 6, 2, "63" },
3172 { 9, 3, "511" },
3173 { 13, 4, "8191" },
3174 { 16, 5, "65535" },
3175 { 19, 6, "524287" },
3176 { 23, 7, "8388607" },
3177 { 26, 8, "67108863" },
3178 { 27, 9, "134217727" },
3179 };
3180
3181 static void
3182 divascii(char *a, int *na, int *dp, int *bp)
3183 {
3184 int b, d;
3185 Tab *t;
3186
3187 d = *dp;
3188 if(d >= (int)(nelem(tab1)))
3189 d = (int)(nelem(tab1))-1;
3190 t = tab1 + d;
3191 b = t->bp;
3192 if(memcmp(a, t->cmp, t->siz) > 0)
3193 d--;
3194 *dp -= d;
3195 *bp += b;
3196 divby(a, na, b);
3197 }
3198
3199 static void
3200 mulby(char *a, char *p, char *q, int b)
3201 {
3202 int n, c;
3203
3204 n = 0;
3205 *p = 0;
3206 for(;;) {
3207 q--;
3208 if(q < a)
3209 break;
3210 c = *q - '0';
3211 c = (c<<b) + n;
3212 n = c/10;
3213 c -= n*10;
3214 p--;
3215 *p = c + '0';
3216 }
3217 while(n) {
3218 c = n;
3219 n = c/10;
3220 c -= n*10;
3221 p--;
3222 *p = c + '0';
3223 }
3224 }
3225
3226 static Tab tab2[] =
3227 {
3228 { 1, 1, "" }, /* dp = 0-0 */
3229 { 3, 3, "125" },
3230 { 6, 5, "15625" },
3231 { 9, 7, "1953125" },
3232 { 13, 10, "1220703125" },
3233 { 16, 12, "152587890625" },
3234 { 19, 14, "19073486328125" },
3235 { 23, 17, "11920928955078125" },
3236 { 26, 19, "1490116119384765625" },
3237 { 27, 19, "7450580596923828125" }, /* dp 8-9 */
3238 };
3239
3240 static void
3241 mulascii(char *a, int *na, int *dp, int *bp)
3242 {
3243 char *p;
3244 int d, b;
3245 Tab *t;
3246
3247 d = -*dp;
3248 if(d >= (int)(nelem(tab2)))
3249 d = (int)(nelem(tab2))-1;
3250 t = tab2 + d;
3251 b = t->bp;
3252 if(memcmp(a, t->cmp, t->siz) < 0)
3253 d--;
3254 p = a + *na;
3255 *bp -= b;
3256 *dp += d;
3257 *na += d;
3258 mulby(a, p+d, p, b);
3259 }
3260
3261 static int
3262 xcmp(char *a, char *b)
3263 {
3264 int c1, c2;
3265
3266 while((c1 = *b++) != '\0') {
3267 c2 = *a++;
3268 if(isupper(c2))
3269 c2 = tolower(c2);
3270 if(c1 != c2)
3271 return 1;
3272 }
3273 return 0;
3274 }
3275 /* -------------- vfprint.c --------------- */
3276 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
3277 // #include <stdarg.h>
3278 // #include "plan9.h"
3279 // #include "fmt.h"
3280 // #include "fmtdef.h"
3281
3282 int
3283 vfprint(int fd, char *fmt, va_list args)
3284 {
3285 Fmt f;
3286 char buf[256];
3287 int n;
3288
3289 fmtfdinit(&f, fd, buf, sizeof(buf));
3290 VA_COPY(f.args,args);
3291 n = dofmt(&f, fmt);
3292 VA_END(f.args);
3293 if(n > 0 && __fmtFdFlush(&f) == 0)
3294 return -1;
3295 return n;
3296 }
3297 /* -------------- vseprint.c --------------- */
3298 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
3299 // #include <stdarg.h>
3300 // #include "plan9.h"
3301 // #include "fmt.h"
3302 // #include "fmtdef.h"
3303
3304 char*
3305 vseprint(char *buf, char *e, char *fmt, va_list args)
3306 {
3307 Fmt f;
3308
3309 if(e <= buf)
3310 return nil;
3311 f.runes = 0;
3312 f.start = buf;
3313 f.to = buf;
3314 f.stop = e - 1;
3315 f.flush = 0;
3316 f.farg = nil;
3317 f.nfmt = 0;
3318 VA_COPY(f.args,args);
3319 fmtlocaleinit(&f, nil, nil, nil);
3320 dofmt(&f, fmt);
3321 VA_END(f.args);
3322 *(char*)f.to = '\0';
3323 return (char*)f.to;
3324 }
3325
3326 /* -------------- vsmprint.c --------------- */
3327 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
3328 /*
3329 * Plan 9 port version must include libc.h in order to
3330 * get Plan 9 debugging malloc, which sometimes returns
3331 * different pointers than the standard malloc.
3332 */
3333 #ifdef PLAN9PORT
3334 // #include <u.h>
3335 // #include <libc.h>
3336 // #include "fmtdef.h"
3337 #else
3338 // #include <stdlib.h>
3339 // #include <string.h>
3340 // #include "plan9.h"
3341 // #include "fmt.h"
3342 // #include "fmtdef.h"
3343 #endif
3344
3345 static int
3346 fmtStrFlush(Fmt *f)
3347 {
3348 char *s;
3349 int n;
3350
3351 if(f->start == nil)
3352 return 0;
3353 n = (uintptr)f->farg;
3354 n *= 2;
3355 s = (char*)f->start;
3356 f->start = realloc(s, n);
3357 if(f->start == nil){
3358 f->farg = nil;
3359 f->to = nil;
3360 f->stop = nil;
3361 free(s);
3362 return 0;
3363 }
3364 f->farg = (void*)(uintptr)n;
3365 f->to = (char*)f->start + ((char*)f->to - s);
3366 f->stop = (char*)f->start + n - 1;
3367 return 1;
3368 }
3369
3370 int
3371 fmtstrinit(Fmt *f)
3372 {
3373 int n;
3374
3375 memset(f, 0, sizeof *f);
3376 f->runes = 0;
3377 n = 32;
3378 f->start = malloc(n);
3379 if(f->start == nil)
3380 return -1;
3381 f->to = f->start;
3382 f->stop = (char*)f->start + n - 1;
3383 f->flush = fmtStrFlush;
3384 f->farg = (void*)(uintptr)n;
3385 f->nfmt = 0;
3386 fmtlocaleinit(f, nil, nil, nil);
3387 return 0;
3388 }
3389
3390 /*
3391 * print into an allocated string buffer
3392 */
3393 char*
3394 vsmprint(char *fmt, va_list args)
3395 {
3396 Fmt f;
3397 int n;
3398
3399 if(fmtstrinit(&f) < 0)
3400 return nil;
3401 VA_COPY(f.args,args);
3402 n = dofmt(&f, fmt);
3403 VA_END(f.args);
3404 if(n < 0){
3405 free(f.start);
3406 return nil;
3407 }
3408 return fmtstrflush(&f);
3409 }
3410 /* -------------- vsnprint.c --------------- */
3411 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
3412 // #include <stdlib.h>
3413 // #include <stdarg.h>
3414 // #include "plan9.h"
3415 // #include "fmt.h"
3416 // #include "fmtdef.h"
3417
3418 int
3419 vsnprint(char *buf, int len, char *fmt, va_list args)
3420 {
3421 Fmt f;
3422
3423 if(len <= 0)
3424 return -1;
3425 f.runes = 0;
3426 f.start = buf;
3427 f.to = buf;
3428 f.stop = buf + len - 1;
3429 f.flush = 0;
3430 f.farg = nil;
3431 f.nfmt = 0;
3432 VA_COPY(f.args,args);
3433 fmtlocaleinit(&f, nil, nil, nil);
3434 dofmt(&f, fmt);
3435 VA_END(f.args);
3436 *(char*)f.to = '\0';
3437 return (char*)f.to - buf;
3438 }
3439
3440 int
3441 __errfmt(Fmt *f)
3442 {
3443 char *s;
3444
3445 s = strerror(errno);
3446 return fmtstrcpy(f, s);
3447 }