1/**************************************************************** 2Copyright (C) 1997, 1999, 2001 Lucent Technologies 3All Rights Reserved 4 5Permission to use, copy, modify, and distribute this software and 6its documentation for any purpose and without fee is hereby 7granted, provided that the above copyright notice appear in all 8copies and that both that the copyright notice and this 9permission notice and warranty disclaimer appear in supporting 10documentation, and that the name of Lucent or any of its entities 11not be used in advertising or publicity pertaining to 12distribution of the software without specific, written prior 13permission. 14 15LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 17IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 18SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 20IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 22THIS SOFTWARE. 23****************************************************************/ 24 25/* This implements most of ANSI C's printf, fprintf, and sprintf, 26 * omitting L, with %.0g and %.0G giving the shortest decimal string 27 * that rounds to the number being converted, and with negative 28 * precisions allowed for %f. 29 */ 30 31#ifdef KR_headers 32#include "varargs.h" 33#else 34#include "stddef.h" 35#include "stdarg.h" 36#include "stdlib.h" 37#endif 38 39#ifdef Use_GDTOA_for_i386_long_double /*{{*/ 40#include "gdtoa.h" 41#else /*}{*/ 42#ifndef NO_PRINTF_A_FMT /*{*/ 43#include "gdtoa.h" 44#endif /*}*/ 45#endif /*}}*/ 46 47#ifdef __i386 48#define NO_GDTOA_i386_Quad 49#endif 50 51#ifdef Use_GDTOA_for_i386_long_double /*{*/ 52#ifndef NO_GDTOA_i386_Quad /*{*/ 53#define GDTOA_both 54#define Use_GDTOA_Qtype 55#ifdef __ICC__ /* or __INTEL_COMPILER__ or __INTEL_COMPILER ?? */ 56#define GDTOA_Qtype _Quad 57#else 58#define GDTOA_Qtype __float128 59#endif 60#endif /*} NO_GDTOA_i386_Quad */ 61#endif /*} Use_GDTOA_for_i386_long_double */ 62 63#ifdef Use_GDTOA_Qtype /*{*/ 64#ifndef GDTOA_H_INCLUDED 65#include "gdtoa.h" 66#endif 67#ifndef GDTOA_Qtype 68#define GDTOA_Qtype long double 69#endif 70#endif /*}*/ 71 72#ifndef GDTOA_H_INCLUDED /*{*/ 73 74 enum { /* return values from strtodg */ 75 STRTOG_Zero = 0, 76 STRTOG_Normal = 1, 77 STRTOG_Denormal = 2, 78 STRTOG_Infinite = 3, 79 STRTOG_NaN = 4, 80 STRTOG_NaNbits = 5, 81 STRTOG_NoNumber = 6, 82 STRTOG_Retmask = 7}; 83 84 typedef struct 85FPI { 86 int nbits; 87 int emin; 88 int emax; 89 int rounding; 90 int sudden_underflow; 91 } FPI; 92 93enum { /* FPI.rounding values: same as FLT_ROUNDS */ 94 FPI_Round_zero = 0, 95 FPI_Round_near = 1, 96 FPI_Round_up = 2, 97 FPI_Round_down = 3 98 }; 99#endif /*}*/ 100 101#ifdef NO_PRINTF_A_FMT /*{{*/ 102#define WANT_A_FMT(x) /*nothing*/ 103#else /*}{*/ 104#define WANT_A_FMT(x) x 105#endif /*}}*/ 106 107#include "stdio1.h" 108#include "string.h" 109#include "errno.h" 110 111 typedef struct 112Finfo { 113 union { FILE *cf; char *sf; } u; 114 char *ob0, *obe1; 115 size_t lastlen; 116 } Finfo; 117 118 typedef char *(*pgdtoa) ANSI((FPI*, int be, ULong *bits, int *kind, int mode, int ndigits, int *decpt, char **rve)); 119 120 typedef struct 121FPBits { 122 ULong bits[4]; /* sufficient for quad; modify if considering wider types */ 123 FPI *fpi; 124 pgdtoa gdtoa; 125 int sign; 126 int ex; /* exponent */ 127 int kind; 128 } FPBits; 129 130 typedef union U 131{ 132 double d; 133 long double ld; 134#ifdef GDTOA_Qtype 135 GDTOA_Qtype Qd; 136#endif 137 unsigned int ui[4]; 138 unsigned short us[5]; 139 } U; 140 141 typedef char *(*Putfunc) ANSI((Finfo*, int*)); 142 typedef void (*Fpbits) ANSI((U*, FPBits*)); 143 144/* Would have preferred typedef void (*Fpbits)(va_list*, FPBits*) 145 * but gcc is buggy in this regard. 146 */ 147 148#ifdef Use_GDTOA_for_i386_long_double /*{*/ 149 150#ifdef IEEE_MC68k 151#define _0 0 152#define _1 1 153#define _2 2 154#define _3 3 155#define _4 4 156#endif 157#ifdef IEEE_8087 158#define _0 4 159#define _1 3 160#define _2 2 161#define _3 1 162#define _4 0 163#endif 164 165 static void 166xfpbits(U *u, FPBits *b) 167{ 168 ULong *bits; 169 int ex, i; 170 static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; 171 172 b->fpi = &fpi0; 173 b->gdtoa = gdtoa; 174 b->sign = u->us[_0] & 0x8000; 175 bits = b->bits; 176 bits[1] = (u->us[_1] << 16) | u->us[_2]; 177 bits[0] = (u->us[_3] << 16) | u->us[_4]; 178 if ( (ex = u->us[_0] & 0x7fff) !=0) { 179 i = STRTOG_Normal; 180 if (ex == 0x7fff) 181 /* Infinity or NaN */ 182 i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite; 183 } 184 else if (bits[0] | bits[1]) { 185 i = STRTOG_Denormal; 186 ex = 1; 187 } 188 else 189 i = STRTOG_Zero; 190 b->kind = i; 191 b->ex = ex - (0x3fff + 63); 192 } 193 194#undef _0 195#undef _1 196#undef _2 197#undef _3 198#undef _4 199#define GDTOA_LD_fpbits xfpbits 200#endif /*} Use_GDTOA_for_i386_long_double */ 201 202#ifdef Use_GDTOA_Qtype /*{*/ 203#include "gdtoa.h" 204#ifndef GDTOA_Qtype 205#define GDTOA_Qtype long double 206#endif 207#ifdef GDTOA_LD_fpbits 208#define GDTOA_Q_fpbits Qfpbits 209#else 210#define GDTOA_LD_fpbits Qfpbits 211#endif 212 213#ifdef IEEE_MC68k 214#define _0 0 215#define _1 1 216#define _2 2 217#define _3 3 218#endif 219#ifdef IEEE_8087 220#define _0 3 221#define _1 2 222#define _2 1 223#define _3 0 224#endif 225 226 static void 227Qfpbits(U *u, FPBits *b) 228{ 229 ULong *bits; 230 int ex, i; 231 static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 }; 232 233 b->fpi = &fpi0; 234 b->gdtoa = gdtoa; 235 b->sign = u->ui[_0] & 0x80000000L; 236 bits = b->bits; 237 bits[3] = u->ui[_0] & 0xffff; 238 bits[2] = u->ui[_1]; 239 bits[1] = u->ui[_2]; 240 bits[0] = u->ui[_3]; 241 if ( (ex = (u->ui[_0] & 0x7fff0000L) >> 16) !=0) { 242 if (ex == 0x7fff) { 243 /* Infinity or NaN */ 244 i = bits[0] | bits[1] | bits[2] | bits[3] 245 ? STRTOG_NaN : STRTOG_Infinite; 246 } 247 else { 248 i = STRTOG_Normal; 249 bits[3] |= 0x10000; 250 } 251 } 252 else if (bits[0] | bits[1] | bits[2] | bits[3]) { 253 i = STRTOG_Denormal; 254 ex = 1; 255 } 256 else 257 i = STRTOG_Zero; 258 b->kind = i; 259 b->ex = ex - (0x3fff + 112); 260 } 261 262#undef _0 263#undef _1 264#undef _2 265#undef _3 266#endif /*} GDTOA_Qtype */ 267 268#ifdef KR_headers 269#define Const /* const */ 270#define Voidptr char* 271#ifndef size_t__ 272#define size_t int 273#define size_t__ 274#endif 275 276#else 277 278#define Const const 279#define Voidptr void* 280 281#endif 282 283#undef MESS 284#ifndef Stderr 285#define Stderr stderr 286#endif 287 288#ifdef _windows_ 289#undef PF_BUF 290#define MESS 291#include "mux0.h" 292#define stdout_or_err(f) (f == stdout) 293#else 294#define stdout_or_err(f) (f == Stderr || f == stdout) 295#endif 296 297#ifdef __cplusplus 298extern "C" { 299#endif 300 301 extern char *dtoa ANSI((double, int, int, int*, int*, char **)); 302 extern void freedtoa ANSI((char*)); 303 304 305 306#ifdef USE_ULDIV 307/* This is for avoiding 64-bit divisions on the DEC Alpha, since */ 308/* they are not portable among variants of OSF1 (DEC's Unix). */ 309 310#define ULDIV(a,b) uldiv_ASL(a,(unsigned long)(b)) 311 312#ifndef LLBITS 313#define LLBITS 6 314#endif 315#ifndef ULONG 316#define ULONG unsigned long 317#endif 318 319 static int 320klog(ULONG x) 321{ 322 int k, rv = 0; 323 324 if (x > 1L) 325 for(k = 1 << LLBITS-1;;) { 326 if (x >= (1L << k)) { 327 rv |= k; 328 x >>= k; 329 } 330 if (!(k >>= 1)) 331 break; 332 } 333 return rv; 334 } 335 336 ULONG 337uldiv_ASL(ULONG a, ULONG b) 338{ 339 int ka; 340 ULONG c, k; 341 static ULONG b0; 342 static int kb; 343 344 if (a < b) 345 return 0; 346 if (b != b0) { 347 b0 = b; 348 kb = klog(b); 349 } 350 k = 1; 351 if ((ka = klog(a) - kb) > 0) { 352 k <<= ka; 353 b <<= ka; 354 } 355 c = 0; 356 for(;;) { 357 if (a >= b) { 358 a -= b; 359 c |= k; 360 } 361 if (!(k >>= 1)) 362 break; 363 a <<= 1; 364 } 365 return c; 366 } 367 368#else 369#define ULDIV(a,b) a / b 370#endif /* USE_ULDIV */ 371 372#ifdef PF_BUF 373FILE *stderr_ASL = (FILE*)&stderr_ASL; 374void (*pfbuf_print_ASL) ANSI((char*)); 375char *pfbuf_ASL; 376static char *pfbuf_next; 377static size_t pfbuf_len; 378extern Char *mymalloc_ASL ANSI((size_t)); 379extern Char *myralloc_ASL ANSI((void *, size_t)); 380 381#undef fflush 382#ifdef old_fflush_ASL 383#define fflush old_fflush_ASL 384#endif 385 386 void 387fflush_ASL(FILE *f) 388{ 389 if (f == stderr_ASL) { 390 if (pfbuf_ASL && pfbuf_print_ASL) { 391 (*pfbuf_print_ASL)(pfbuf_ASL); 392 free(pfbuf_ASL); 393 pfbuf_ASL = 0; 394 } 395 } 396 else 397 fflush(f); 398 } 399 400 static void 401pf_put(char *buf, int len) 402{ 403 size_t x, y; 404 if (!pfbuf_ASL) { 405 x = len + 256; 406 if (x < 512) 407 x = 512; 408 pfbuf_ASL = pfbuf_next = (char*)mymalloc_ASL(pfbuf_len = x); 409 } 410 else if ((y = (pfbuf_next - pfbuf_ASL) + len) >= pfbuf_len) { 411 x = pfbuf_len; 412 while((x <<= 1) <= y); 413 y = pfbuf_next - pfbuf_ASL; 414 pfbuf_ASL = (char*)myralloc_ASL(pfbuf_ASL, x); 415 pfbuf_next = pfbuf_ASL + y; 416 pfbuf_len = x; 417 } 418 memcpy(pfbuf_next, buf, len); 419 pfbuf_next += len; 420 *pfbuf_next = 0; 421 } 422 423 static char * 424pfput(Finfo *f, int *rvp) 425{ 426 int n; 427 char *ob0 = f->ob0; 428 *rvp += n = (int)(f->obe1 - ob0); 429 pf_put(ob0, n); 430 return ob0; 431 } 432#endif /* PF_BUF */ 433 434 static char * 435Fput 436#ifdef KR_headers 437 (f, rvp) Finfo *f; int *rvp; 438#else 439 (Finfo *f, int *rvp) 440#endif 441{ 442 char *ob0 = f->ob0; 443 444 *rvp += f->obe1 - ob0; 445 *f->obe1 = 0; 446 fputs(ob0, f->u.cf); 447 return ob0; 448 } 449 450 451#ifdef _windows_ 452int stdout_fileno_ASL = 1; 453 454 static char * 455Wput 456#ifdef KR_headers 457 (f, rvp) Finfo *f; int *rvp; 458#else 459 (Finfo *f, int *rvp) 460#endif 461{ 462 char *ob0 = f->ob0; 463 464 *rvp += f->obe1 - ob0; 465 *f->obe1 = 0; 466 mwrite(ob0, f->obe1 - ob0); 467 return ob0; 468 } 469#endif /*_windows_*/ 470 471 472#ifdef IEEE_MC68k 473#define _0 0 474#define _1 1 475#endif 476#ifdef IEEE_8087 477#define _0 1 478#define _1 0 479#endif 480 481 static void 482dfpbits(U *u, FPBits *b) 483{ 484 ULong *bits; 485 int ex, i; 486 static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 }; 487 488 b->fpi = &fpi0; 489 b->gdtoa = gdtoa; 490 b->sign = u->ui[_0] & 0x80000000L; 491 bits = b->bits; 492 bits[1] = u->ui[_0] & 0xfffff; 493 bits[0] = u->ui[_1]; 494 if ( (ex = (u->ui[_0] & 0x7ff00000L) >> 20) !=0) { 495 if (ex == 0x7ff) { 496 /* Infinity or NaN */ 497 i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite; 498 } 499 else { 500 i = STRTOG_Normal; 501 bits[1] |= 0x100000; 502 } 503 } 504 else if (bits[0] | bits[1]) { 505 i = STRTOG_Denormal; 506 ex = 1; 507 } 508 else 509 i = STRTOG_Zero; 510 b->kind = i; 511 b->ex = ex - (0x3ff + 52); 512 } 513 514#undef _0 515#undef _1 516 517#ifdef Honor_FLT_ROUNDS /*{{*/ 518#ifdef Trust_FLT_ROUNDS /*{{*/ 519#define RoundCheck if (Rounding == -1) Rounding = Flt_Rounds; if (Rounding != 1){\ 520 fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;} 521#else /*}{*/ 522#define RoundCheck if (Rounding == -1) { Rounding = 1; switch((fegetround()) {\ 523 case FE_TOWARDZERO: Rounding = 0; break;\ 524 case FE_UPWARD: Rounding = 2; break;\ 525 case FE_DOWNWARD: Rounding = 3; }}\ 526 if (Rounding != 1){\ 527 fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;} 528#endif /*}}*/ 529#else /*}{*/ 530#define RoundCheck /*nothing*/ 531#endif /*}}*/ 532 533#ifndef NO_PRINTF_A_FMT /*{*/ 534 static int 535fpiprec(FPBits *b) /* return number of hex digits minus 1, or 0 for zero */ 536{ 537 FPI *fpi; 538 ULong *bits; 539 int i, j, k, m; 540 541 if (b->kind == STRTOG_Zero) 542 return b->ex = 0; 543 fpi = b->fpi; 544 bits = b->bits; 545 for(k = (fpi->nbits - 1) >> 2; k > 0; --k) 546 if ((bits[k >> 3] >> 4*(k & 7)) & 0xf) { 547 m = k >> 3; 548 for(i = 0; i <= m; ++i) 549 if (bits[i]) { 550 if (i > 0) { 551 k -= 8*i; 552 b->ex += 32*i; 553 for(j = i; j <= m; ++j) 554 bits[j-i] = bits[j]; 555 } 556 break; 557 } 558 for(i = 0; i < 28 && !((bits[0] >> i) & 0xf); i += 4); 559 if (i) { 560 b->ex += i; 561 m = k >> 3; 562 k -= (i >> 2); 563 for(j = 0;;++j) { 564 bits[j] >>= i; 565 if (j == m) 566 break; 567 bits[j] |= bits[j+1] << (32 - i); 568 } 569 } 570 break; 571 } 572 return k; 573 } 574 575 static int 576bround(FPBits *b, int prec, int prec1) /* round to prec hex digits after the "." */ 577{ /* prec1 = incoming precision (after ".") */ 578 FPI *fpi = b->fpi; 579 ULong *bits, t; 580 int i, inc, j, k, m, n; 581#ifdef Honor_FLT_ROUNDS 582 int rounding = fpi->rounding; 583 584 if (rounding > FPI_Round_near && b->sign) 585 rounding = FPI_Round_up + FPI_Round_down - rounding; 586 if (rounding == FPI_Round_down) 587 rounding = FPI_Round_zero; 588#endif 589 m = prec1 - prec; 590 bits = b->bits; 591 inc = 0; 592#ifdef Honor_FLT_ROUNDS 593 switch(rounding) { 594 case FPI_Round_up: 595 for(i = 0; i < m; i += 8) 596 if (bits[i>>3]) 597 goto inc1; 598 if ((j = i - m) > 0 && bits[(i-8)>>3] << j*4) 599 goto inc1; 600 break; 601 case FPI_Round_near: 602#endif 603 k = m - 1; 604 if ((t = bits[k >> 3] >> (j = (k&7)*4)) & 8) { 605 if (t & 7) 606 goto inc1; 607 if (j && bits[k >> 3] << (32 - j)) 608 goto inc1; 609 while(k >= 8) { 610 k -= 8; 611 if (bits[k>>3]) { 612 inc1: 613 inc = 1; 614 goto haveinc; 615 } 616 } 617 } 618#ifdef Honor_FLT_ROUNDS 619 } 620#endif 621 haveinc: 622 b->ex += m*4; 623 i = m >> 3; 624 k = prec1 >> 3; 625 j = i; 626 if ((n = 4*(m & 7))) 627 for(;; ++j) { 628 bits[j-i] = bits[j] >> n; 629 if (j == k) 630 break; 631 bits[j-i] |= bits[j+1] << (32-n); 632 } 633 else 634 for(;; ++j) { 635 bits[j-i] = bits[j]; 636 if (j == k) 637 break; 638 } 639 k = prec >> 3; 640 if (inc) { 641 for(j = 0; !(++bits[j] & 0xffffffff); ++j); 642 if (j > k) { 643 onebit: 644 bits[0] = 1; 645 b->ex += 4*prec; 646 return 1; 647 } 648 if ((j = prec & 7) < 7 && bits[k] >> (j+1)*4) 649 goto onebit; 650 } 651 for(i = 0; !(bits[i >> 3] & (0xf << 4*(i&7))); ++i); 652 if (i) { 653 b->ex += 4*i; 654 prec -= i; 655 j = i >> 3; 656 i &= 7; 657 i *= 4; 658 for(m = j; ; ++m) { 659 bits[m-j] = bits[m] >> i; 660 if (m == k) 661 break; 662 bits[m-j] |= bits[m+1] << (32 - i); 663 } 664 } 665 return prec; 666 } 667#endif /*}NO_PRINTF_A_FMT*/ 668 669#define put(x) { *outbuf++ = x; if (outbuf == obe) outbuf = (*fput)(f,&rv); } 670 671 static int 672x_sprintf 673#ifdef KR_headers 674 (obe, fput, f, fmt, ap) 675 char *obe, *fmt; Finfo *f; Putfunc fput; va_list ap; 676#else 677 (char *obe, Putfunc fput, Finfo *f, const char *fmt, va_list ap) 678#endif 679{ 680 FPBits fpb; 681 Fpbits fpbits; 682 U u; 683 char *digits, *ob0, *outbuf, *s, *s0, *se; 684 Const char *fmt0; 685 char buf[32]; 686 long i; 687 unsigned long j, ul; 688 double x; 689 int alt, base, c, decpt, dot, conv, i1, k, lead0, left, 690 len, prec, prec1, psign, rv, sign, width; 691 long Ltmp, *ip; 692 short sh; 693 unsigned short us; 694 unsigned int ui; 695#ifdef Honor_FLT_ROUNDS 696 FPI fpi1; 697 int Rounding = -1; 698#endif 699#ifndef NO_PRINTF_A_FMT /*{*/ 700 int bex, bw; 701#endif /*} NO_PRINTF_A_FMT */ 702 static char hex[] = "0123456789abcdefpx"; 703 static char Hex[] = "0123456789ABCDEFPX"; 704 705 ob0 = outbuf = f->ob0; 706 rv = 0; 707 for(;;) { 708 for(;;) { 709 switch(c = *fmt++) { 710 case 0: 711 goto done; 712 case '%': 713 break; 714 default: 715 put(c) 716 continue; 717 } 718 break; 719 } 720 alt=dot=lead0=left=len=prec=psign=sign=width=0; 721 fpbits = dfpbits; 722 fmt0 = fmt; 723 fmtloop: 724 switch(conv = *fmt++) { 725 case ' ': 726 case '+': 727 sign = conv; 728 goto fmtloop; 729 case '-': 730 if (dot) 731 psign = 1; 732 else 733 left = 1; 734 goto fmtloop; 735 case '#': 736 alt = 1; 737 goto fmtloop; 738 case '0': 739 if (!lead0 && !dot) { 740 lead0 = 1; 741 goto fmtloop; 742 } 743 case '1': 744 case '2': 745 case '3': 746 case '4': 747 case '5': 748 case '6': 749 case '7': 750 case '8': 751 case '9': 752 k = conv - '0'; 753 while((c = *fmt) >= '0' && c <= '9') { 754 k = 10*k + c - '0'; 755 fmt++; 756 } 757 if (dot) 758 prec = psign ? -k : k; 759 else 760 width = k; 761 goto fmtloop; 762 case 'h': 763 len = 2; 764 goto fmtloop; 765 case 'L': 766#ifdef GDTOA_LD_fpbits /*{*/ 767 fpbits = GDTOA_LD_fpbits; 768#ifdef GDTOA_Q_fpbits 769 if (*fmt == 'q') { 770 ++fmt; 771 fpbits = Qfpbits; 772 } 773#endif 774#endif /*}*/ 775 goto fmtloop; 776 case 'l': 777 len = 1; 778 goto fmtloop; 779 case '.': 780 dot = 1; 781 goto fmtloop; 782 case '*': 783 k = va_arg(ap, int); 784 if (dot) 785 prec = k; 786 else { 787 if (k < 0) { 788 sign = '-'; 789 k = -k; 790 } 791 width = k; 792 } 793 goto fmtloop; 794 case 'c': 795 c = va_arg(ap, int); 796 put(c) 797 continue; 798 case '%': 799 put(conv) 800 continue; 801 case 'u': 802 switch(len) { 803 case 0: 804 ui = va_arg(ap, int); 805 i = ui; 806 break; 807 case 1: 808 i = va_arg(ap, long); 809 break; 810 case 2: 811 us = va_arg(ap, int); 812 i = us; 813 } 814 sign = 0; 815 goto have_i; 816 case 'i': 817 case 'd': 818 switch(len) { 819 case 0: 820 k = va_arg(ap, int); 821 i = k; 822 break; 823 case 1: 824 i = va_arg(ap, long); 825 break; 826 case 2: 827 sh = va_arg(ap, int); 828 i = sh; 829 } 830 if (i < 0) { 831 sign = '-'; 832 i = -i; 833 } 834 have_i: 835 base = 10; 836 ul = i; 837 digits = hex; 838 baseloop: 839 if (dot) 840 lead0 = 0; 841 s = buf; 842 if (!ul) 843 alt = 0; 844 do { 845 j = ULDIV(ul, base); 846 *s++ = digits[ul - base*j]; 847 } 848 while((ul = j)); 849 prec -= c = s - buf; 850 if (alt && conv == 'o' && prec <= 0) 851 prec = 1; 852 if ((width -= c) > 0) { 853 if (prec > 0) 854 width -= prec; 855 if (sign) 856 width--; 857 if (alt == 2) 858 width--; 859 } 860 if (left) { 861 if (alt == 2) 862 put('0') /* for 0x */ 863 if (sign) 864 put(sign) 865 while(--prec >= 0) 866 put('0') 867 do put(*--s) 868 while(s > buf); 869 while(--width >= 0) 870 put(' ') 871 continue; 872 } 873 if (width > 0) { 874 if (lead0) { 875 if (alt == 2) 876 put('0') 877 if (sign) 878 put(sign) 879 while(--width >= 0) 880 put('0') 881 goto s_loop; 882 } 883 else 884 while(--width >= 0) 885 put(' ') 886 } 887 if (alt == 2) 888 put('0') 889 if (sign) 890 put(sign) 891 s_loop: 892 while(--prec >= 0) 893 put('0') 894 do put(*--s) 895 while(s > buf); 896 continue; 897 case 'n': 898 ip = va_arg(ap, long*); 899 if (!ip) 900 ip = &Ltmp; 901 c = outbuf - ob0 + rv; 902 switch(len) { 903 case 0: 904 *(int*)ip = c; 905 break; 906 case 1: 907 *ip = c; 908 break; 909 case 2: 910 *(short*)ip = c; 911 } 912 break; 913 case 'p': 914 len = alt = 1; 915 /* no break */ 916 case 'x': 917 digits = hex; 918 goto more_x; 919 case 'X': 920 digits = Hex; 921 more_x: 922 if (alt) { 923 alt = 2; 924 sign = conv; 925 } 926 else 927 sign = 0; 928 base = 16; 929 get_u: 930 switch(len) { 931 case 0: 932 ui = va_arg(ap, int); 933 ul = ui; 934 break; 935 case 1: 936 ul = va_arg(ap, long); 937 break; 938 case 2: 939 us = va_arg(ap, int); 940 ul = us; 941 } 942 if (!ul) 943 sign = alt = 0; 944 goto baseloop; 945 case 'o': 946 base = 8; 947 digits = hex; 948 goto get_u; 949 case 's': 950 s0 = 0; 951 s = va_arg(ap, char*); 952 if (!s) 953 s = "<NULL>"; 954 if (prec < 0) 955 prec = 0; 956 have_s: 957 if (dot) { 958 for(c = 0; c < prec; c++) 959 if (!s[c]) 960 break; 961 prec = c; 962 } 963 else 964 prec = strlen(s); 965 width -= prec; 966 if (!left) 967 while(--width >= 0) 968 put(' ') 969 while(--prec >= 0) 970 put(*s++) 971 while(--width >= 0) 972 put(' ') 973 if (s0) 974 freedtoa(s0); 975 continue; 976 case 'f': 977 if (!dot) 978 prec = 6; 979#ifdef GDTOA_H_INCLUDED 980 if (fpbits == dfpbits) { 981#endif 982 x = va_arg(ap, double); 983 s = s0 = dtoa(x, 3, prec, &decpt, &fpb.sign, &se); 984#ifdef GDTOA_H_INCLUDED 985 } 986 else { 987#ifdef GDTOA_both 988 if (fpbits == GDTOA_LD_fpbits) 989 u.ld = va_arg(ap, long double); 990 else 991 u.Qd = va_arg(ap, GDTOA_Qtype); 992#else 993 u.ld = va_arg(ap, long double); 994#endif 995 fpbits(&u, &fpb); 996 RoundCheck 997 s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits, 998 &fpb.kind, 3, prec, &decpt, &se); 999 } 1000#endif 1001 if (decpt == 9999) { 1002 fmt9999: 1003 dot = prec = alt = 0; 1004 if (*s == 'N') 1005 goto have_s; 1006 decpt = strlen(s); 1007 } 1008 f_fmt: 1009 if (fpb.sign && (x||sign)) 1010 sign = '-'; 1011 if (prec > 0) 1012 width -= prec; 1013 if (width > 0) { 1014 if (sign) 1015 --width; 1016 if (decpt <= 0) { 1017 --width; 1018 if (prec > 0) 1019 --width; 1020 } 1021 else { 1022 if (s == se) 1023 decpt = 1; 1024 width -= decpt; 1025 if (prec > 0 || alt) 1026 --width; 1027 } 1028 } 1029 if (width > 0 && !left) { 1030 if (lead0) { 1031 if (sign) 1032 put(sign) 1033 sign = 0; 1034 do put('0') 1035 while(--width > 0); 1036 } 1037 else do put(' ') 1038 while(--width > 0); 1039 } 1040 if (sign) 1041 put(sign) 1042 if (decpt <= 0) { 1043 put('0') 1044 if (prec > 0 || alt) 1045 put('.') 1046 while(decpt < 0) { 1047 put('0') 1048 prec--; 1049 decpt++; 1050 } 1051 } 1052 else { 1053 do { 1054 if ((c = *s)) 1055 s++; 1056 else 1057 c = '0'; 1058 put(c) 1059 } 1060 while(--decpt > 0); 1061 if (prec > 0 || alt) 1062 put('.') 1063 } 1064 while(--prec >= 0) { 1065 if ((c = *s)) 1066 s++; 1067 else 1068 c = '0'; 1069 put(c) 1070 } 1071 while(--width >= 0) 1072 put(' ') 1073 if (s0) 1074 freedtoa(s0); 1075 continue; 1076 case 'G': 1077 case 'g': 1078 if (!dot) 1079 prec = 6; 1080 if (prec < 0) 1081 prec = 0; 1082#ifdef GDTOA_H_INCLUDED 1083 if (fpbits == dfpbits) { 1084#endif 1085 x = va_arg(ap, double); 1086 s = s0 = dtoa(x, prec ? 2 : 0, prec, &decpt, 1087 &fpb.sign, &se); 1088#ifdef GDTOA_H_INCLUDED 1089 } 1090 else { 1091#ifdef GDTOA_both 1092 if (fpbits == GDTOA_LD_fpbits) 1093 u.ld = va_arg(ap, long double); 1094 else 1095 u.Qd = va_arg(ap, GDTOA_Qtype); 1096#else 1097 u.ld = va_arg(ap, long double); 1098#endif 1099 fpbits(&u, &fpb); 1100 RoundCheck 1101 s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits, 1102 &fpb.kind, prec ? 2 : 0, prec, &decpt, &se); 1103 } 1104#endif 1105 if (decpt == 9999) 1106 goto fmt9999; 1107 c = se - s; 1108 prec1 = prec; 1109 if (!prec) { 1110 prec = c; 1111 prec1 = c + (s[1] || alt ? 5 : 4); 1112 /* %.0g gives 10 rather than 1e1 */ 1113 } 1114 if (decpt > -4 && decpt <= prec1) { 1115 if (alt) 1116 prec -= decpt; 1117 else 1118 prec = c - decpt; 1119 if (prec < 0) 1120 prec = 0; 1121 goto f_fmt; 1122 } 1123 conv -= 2; 1124 if (!alt && prec > c) 1125 prec = c; 1126 --prec; 1127 goto e_fmt; 1128 case 'e': 1129 case 'E': 1130 if (!dot) 1131 prec = 6; 1132 if (prec < 0) 1133 prec = 0; 1134#ifdef GDTOA_H_INCLUDED 1135 if (fpbits == dfpbits) { 1136#endif 1137 x = va_arg(ap, double); 1138 s = s0 = dtoa(x, prec ? 2 : 0, prec+1, &decpt, 1139 &fpb.sign, &se); 1140#ifdef GDTOA_H_INCLUDED 1141 } 1142 else { 1143#ifdef GDTOA_both 1144 if (fpbits == GDTOA_LD_fpbits) 1145 u.ld = va_arg(ap, long double); 1146 else 1147 u.Qd = va_arg(ap, GDTOA_Qtype); 1148#else 1149 u.ld = va_arg(ap, long double); 1150#endif 1151 fpbits(&u, &fpb); 1152 RoundCheck 1153 s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits, 1154 &fpb.kind, prec ? 2 : 0, prec, &decpt, &se); 1155 } 1156#endif 1157 if (decpt == 9999) 1158 goto fmt9999; 1159 e_fmt: 1160 if (fpb.sign && (x||sign)) 1161 sign = '-'; 1162 if ((width -= prec + 5) > 0) { 1163 if (sign) 1164 --width; 1165 if (prec || alt) 1166 --width; 1167 } 1168 if ((c = --decpt) < 0) 1169 c = -c; 1170 while(c >= 100) { 1171 --width; 1172 c /= 10; 1173 } 1174 if (width > 0 && !left) { 1175 if (lead0) { 1176 if (sign) 1177 put(sign) 1178 sign = 0; 1179 do put('0') 1180 while(--width > 0); 1181 } 1182 else do put(' ') 1183 while(--width > 0); 1184 } 1185 if (sign) 1186 put(sign) 1187 put(*s++) 1188 if (prec || alt) 1189 put('.') 1190 while(--prec >= 0) { 1191 if ((c = *s)) 1192 s++; 1193 else 1194 c = '0'; 1195 put(c) 1196 } 1197 put(conv) 1198 if (decpt < 0) { 1199 put('-') 1200 decpt = -decpt; 1201 } 1202 else 1203 put('+') 1204 for(c = 2, k = 10; 10*k <= decpt; c++, k *= 10); 1205 for(;;) { 1206 i1 = decpt / k; 1207 put(i1 + '0') 1208 if (--c <= 0) 1209 break; 1210 decpt -= i1*k; 1211 decpt *= 10; 1212 } 1213 while(--width >= 0) 1214 put(' ') 1215 freedtoa(s0); 1216 continue; 1217#ifndef NO_PRINTF_A_FMT 1218 case 'a': 1219 digits = hex; 1220 goto more_a; 1221 case 'A': 1222 digits = Hex; 1223 more_a: 1224#ifdef GDTOA_H_INCLUDED /*{{*/ 1225 if (fpbits == dfpbits) 1226 u.d = va_arg(ap, double); 1227#ifdef GDTOA_both /*{*/ 1228 else if (fpbits == GDTOA_LD_fpbits) 1229 u.ld = va_arg(ap, long double); 1230 else 1231 u.Qd = va_arg(ap, GDTOA_Qtype); 1232#else 1233 else 1234 u.ld = va_arg(ap, long double); 1235#endif /*}*/ 1236#else /*}{*/ 1237 u.d = va_arg(ap, double); 1238#endif /*}}*/ 1239 fpbits(&u, &fpb); 1240 if (fpb.kind == STRTOG_Infinite) { 1241 s = "Infinity"; 1242 s0 = 0; 1243 goto fmt9999; 1244 } 1245 if (fpb.kind == STRTOG_NaN) { 1246 s = "NaN"; 1247 s0 = 0; 1248 goto fmt9999; 1249 } 1250 prec1 = fpiprec(&fpb); 1251 if (dot && prec < prec1) 1252 prec1 = bround(&fpb, prec, prec1); 1253 bw = 1; 1254 bex = fpb.ex + 4*prec1; 1255 if (bex) { 1256 if ((i1 = bex) < 0) 1257 i1 = -i1; 1258 while(i1 >= 10) { 1259 ++bw; 1260 i1 /= 10; 1261 } 1262 } 1263 if (fpb.sign && (sign || fpb.kind != STRTOG_Zero)) 1264 sign = '-'; 1265 if ((width -= bw + 5) > 0) { 1266 if (sign) 1267 --width; 1268 if (prec1 || alt) 1269 --width; 1270 } 1271 if ((width -= prec1) > 0 && !left && !lead0) { 1272 do put(' ') 1273 while(--width > 0); 1274 } 1275 if (sign) 1276 put(sign) 1277 put('0') 1278 put(digits[17]) 1279 if (lead0 && width > 0 && !left) { 1280 do put('0') 1281 while(--width > 0); 1282 } 1283 i1 = prec1 & 7; 1284 k = prec1 >> 3; 1285 put(digits[(fpb.bits[k] >> 4*i1) & 0xf]) 1286 if (prec1 > 0 || alt) 1287 put('.') 1288 if (prec1 > 0) { 1289 prec -= prec1; 1290 while(prec1 > 0) { 1291 if (--i1 < 0) { 1292 if (--k < 0) 1293 break; 1294 i1 = 7; 1295 } 1296 put(digits[(fpb.bits[k] >> 4*i1) & 0xf]) 1297 --prec1; 1298 } 1299 if (alt && prec > 0) 1300 do put(0) 1301 while(--prec > 0); 1302 } 1303 put(digits[16]) 1304 if (bex < 0) { 1305 put('-') 1306 bex = -bex; 1307 } 1308 else 1309 put('+') 1310 for(c = 1; 10*c <= bex; c *= 10); 1311 for(;;) { 1312 i1 = bex / c; 1313 put('0' + i1) 1314 if (!--bw) 1315 break; 1316 bex -= i1 * c; 1317 bex *= 10; 1318 } 1319 while(--width >= 0) 1320 put(' ') 1321 continue; 1322#endif /* NO_PRINTF_A_FMT */ 1323 default: 1324 put('%') 1325 while(fmt0 < fmt) 1326 put(*fmt0++) 1327 continue; 1328 } 1329 } 1330 done: 1331 *outbuf = 0; 1332 return (f->lastlen = outbuf - ob0) + rv; 1333 } 1334 1335#define Bsize 256 1336 1337 int 1338Printf 1339#ifdef KR_headers 1340 (va_alist) 1341 va_dcl 1342{ 1343 char *fmt; 1344 1345 va_list ap; 1346 int rv; 1347 Finfo f; 1348 char buf[Bsize]; 1349 1350 va_start(ap); 1351 fmt = va_arg(ap, char*); 1352 /*}*/ 1353#else 1354 (const char *fmt, ...) 1355{ 1356 va_list ap; 1357 int rv; 1358 Finfo f; 1359 char buf[Bsize]; 1360 1361 va_start(ap, fmt); 1362#endif 1363 f.u.cf = stdout; 1364 f.ob0 = buf; 1365 f.obe1 = buf + Bsize - 1; 1366#ifdef _windows_ 1367 if (fileno(stdout) == stdout_fileno_ASL) { 1368 rv = x_sprintf(f.obe1, Wput, &f, fmt, ap); 1369 mwrite(buf, f.lastlen); 1370 } 1371 else 1372#endif 1373#ifdef PF_BUF 1374 if (stdout == stderr_ASL) { 1375 rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1376 pf_put(buf, f.lastlen); 1377 } 1378 else 1379#endif 1380 { 1381 rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1382 fputs(buf, stdout); 1383 } 1384 va_end(ap); 1385 return rv; 1386 } 1387 1388 static char * 1389Sput 1390#ifdef KR_headers 1391 (f, rvp) Finfo *f; int *rvp; 1392#else 1393 (Finfo *f, int *rvp) 1394#endif 1395{ 1396 if (Printf("\nBUG! Sput called!\n", f, rvp)) 1397 /* pass vp, rvp and return 0 to shut diagnostics off */ 1398 exit(250); 1399 return 0; 1400 } 1401 1402 int 1403Sprintf 1404#ifdef KR_headers 1405 (va_alist) 1406 va_dcl 1407{ 1408 char *s, *fmt; 1409 va_list ap; 1410 int rv; 1411 Finfo f; 1412 1413 va_start(ap); 1414 s = va_arg(ap, char*); 1415 fmt = va_arg(ap, char*); 1416 /*}*/ 1417#else 1418 (char *s, const char *fmt, ...) 1419{ 1420 va_list ap; 1421 int rv; 1422 Finfo f; 1423 1424 va_start(ap, fmt); 1425#endif 1426 f.ob0 = s; 1427 rv = x_sprintf(s, Sput, &f, fmt, ap); 1428 va_end(ap); 1429 return rv; 1430 } 1431 1432 int 1433Fprintf 1434#ifdef KR_headers 1435 (va_alist) 1436 va_dcl 1437{ 1438 FILE *F; 1439 char *s, *fmt; 1440 va_list ap; 1441 int rv; 1442 Finfo f; 1443 char buf[Bsize]; 1444 1445 va_start(ap); 1446 F = va_arg(ap, FILE*); 1447 fmt = va_arg(ap, char*); 1448 /*}*/ 1449#else 1450 (FILE *F, const char *fmt, ...) 1451{ 1452 va_list ap; 1453 int rv; 1454 Finfo f; 1455 char buf[Bsize]; 1456 1457 va_start(ap, fmt); 1458#endif 1459 f.u.cf = F; 1460 f.ob0 = buf; 1461 f.obe1 = buf + Bsize - 1; 1462#ifdef MESS 1463 if (stdout_or_err(F)) { 1464#ifdef _windows_ 1465 if (fileno(stdout) == stdout_fileno_ASL) { 1466 rv = x_sprintf(f.obe1, Wput, &f, fmt, ap); 1467 mwrite(buf, f.lastlen); 1468 } 1469 else 1470#endif 1471#ifdef PF_BUF 1472 if (F == stderr_ASL) { 1473 rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1474 pf_put(buf, f.lastlen); 1475 } 1476 else 1477#endif 1478 { 1479 rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1480 fputs(buf, F); 1481 } 1482 } 1483 else 1484#endif /*MESS*/ 1485 { 1486#ifdef PF_BUF 1487 if (F == stderr_ASL) { 1488 rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1489 pf_put(buf, f.lastlen); 1490 } 1491 else 1492#endif 1493 { 1494 rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1495 fputs(buf, F); 1496 } 1497 } 1498 va_end(ap); 1499 return rv; 1500 } 1501 1502 int 1503Vsprintf 1504#ifdef KR_headers 1505 (s, fmt, ap) char *s, *fmt; va_list ap; 1506#else 1507 (char *s, const char *fmt, va_list ap) 1508#endif 1509{ 1510 Finfo f; 1511 return x_sprintf(f.ob0 = s, Sput, &f, fmt, ap); 1512 } 1513 1514 int 1515Vfprintf 1516#ifdef KR_headers 1517 (F, fmt, ap) FILE *F; char *fmt; va_list ap; 1518#else 1519 (FILE *F, const char *fmt, va_list ap) 1520#endif 1521{ 1522 char buf[Bsize]; 1523 int rv; 1524 Finfo f; 1525 1526 f.u.cf = F; 1527 f.ob0 = buf; 1528 f.obe1 = buf + Bsize - 1; 1529#ifdef MESS 1530 if (stdout_or_err(F)) { 1531#ifdef _windows_ 1532 if (fileno(stdout) == stdout_fileno_ASL) { 1533 rv = x_sprintf(f.obe1, Wput, &f, fmt, ap); 1534 mwrite(buf, f.lastlen); 1535 } 1536 else 1537#endif 1538#ifdef PF_BUF 1539 if (F == stderr_ASL) { 1540 rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1541 pf_put(buf, f.lastlen); 1542 } 1543 else 1544#endif 1545 { 1546 rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1547 fputs(buf, F); 1548 } 1549 } 1550 else 1551#endif /*MESS*/ 1552 { 1553#ifdef PF_BUF 1554 if (F == stderr_ASL) { 1555 rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1556 pf_put(buf, f.lastlen); 1557 } 1558 else 1559#endif 1560 { 1561 rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1562 fputs(buf, F); 1563 } 1564 } 1565 va_end(ap); 1566 return rv; 1567 } 1568 1569 void 1570Perror 1571#ifdef KR_headers 1572 (s) char *s; 1573#else 1574 (const char *s) 1575#endif 1576{ 1577 if (s && *s) 1578 Fprintf(Stderr, "%s: ", s); 1579 Fprintf(Stderr, "%s\n", strerror(errno)); 1580 } 1581 1582 static char * 1583Snput 1584#ifdef KR_headers 1585 (f, rvp) Finfo *f; int *rvp; 1586#else 1587 (Finfo *f, int *rvp) 1588#endif 1589{ 1590 char *s, *s0; 1591 size_t L; 1592 1593 *rvp += Bsize; 1594 s0 = f->ob0; 1595 s = f->u.sf; 1596 if ((L = f->obe1 - s) > Bsize) { 1597 L = Bsize; 1598 goto copy; 1599 } 1600 if (L > 0) { 1601 copy: 1602 memcpy(s, s0, L); 1603 f->u.sf = s + L; 1604 } 1605 return s0; 1606 } 1607 1608 int 1609Vsnprintf 1610#ifdef KR_headers 1611 (s, n, fmt, ap) char *s; size_t n; char *fmt; va_list ap; 1612#else 1613 (char *s, size_t n, const char *fmt, va_list ap) 1614#endif 1615{ 1616 Finfo f; 1617 char buf[Bsize]; 1618 int L, rv; 1619 1620 if (n <= 0 || !s) { 1621 n = 1; 1622 s = buf; 1623 } 1624 f.u.sf = s; 1625 f.ob0 = buf; 1626 f.obe1 = s + n - 1; 1627 rv = x_sprintf(buf + Bsize, Snput, &f, fmt, ap); 1628 if (f.lastlen > (L = f.obe1 - f.u.sf)) 1629 f.lastlen = L; 1630 if (f.lastlen > 0) { 1631 memcpy(f.u.sf, buf, f.lastlen); 1632 f.u.sf += f.lastlen; 1633 } 1634 *f.u.sf = 0; 1635 return rv; 1636 } 1637 int 1638Snprintf 1639#ifdef KR_headers 1640 (va_alist) 1641 va_dcl 1642{ 1643 char *s, *fmt; 1644 int rv; 1645 size_t n; 1646 va_list ap; 1647 1648 va_start(ap); 1649 s = va_arg(ap, char*); 1650 n = va_arg(ap, size_t); 1651 fmt = va_arg(ap, char*); 1652 /*}*/ 1653#else 1654 (char *s, size_t n, const char *fmt, ...) 1655{ 1656 int rv; 1657 va_list ap; 1658 1659 va_start(ap, fmt); 1660#endif 1661 rv = Vsnprintf(s, n, fmt, ap); 1662 va_end(ap); 1663 return rv; 1664 } 1665 1666 1667#ifdef __cplusplus 1668} 1669#endif 1670