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 }