1219422Sdas/**************************************************************** 2219422SdasCopyright (C) 1997, 1999, 2001 Lucent Technologies 3219422SdasAll Rights Reserved 4219422Sdas 5219422SdasPermission to use, copy, modify, and distribute this software and 6219422Sdasits documentation for any purpose and without fee is hereby 7219422Sdasgranted, provided that the above copyright notice appear in all 8219422Sdascopies and that both that the copyright notice and this 9219422Sdaspermission notice and warranty disclaimer appear in supporting 10219422Sdasdocumentation, and that the name of Lucent or any of its entities 11219422Sdasnot be used in advertising or publicity pertaining to 12219422Sdasdistribution of the software without specific, written prior 13219422Sdaspermission. 14219422Sdas 15219422SdasLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16219422SdasINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 17219422SdasIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 18219422SdasSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19219422SdasWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 20219422SdasIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21219422SdasARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 22219422SdasTHIS SOFTWARE. 23219422Sdas****************************************************************/ 24219422Sdas 25219422Sdas/* This implements most of ANSI C's printf, fprintf, and sprintf, 26219422Sdas * omitting L, with %.0g and %.0G giving the shortest decimal string 27219422Sdas * that rounds to the number being converted, and with negative 28219422Sdas * precisions allowed for %f. 29219422Sdas */ 30219422Sdas 31219422Sdas#ifdef KR_headers 32219422Sdas#include "varargs.h" 33219422Sdas#else 34219422Sdas#include "stddef.h" 35219422Sdas#include "stdarg.h" 36219422Sdas#include "stdlib.h" 37219422Sdas#endif 38219422Sdas 39219422Sdas#ifdef Use_GDTOA_for_i386_long_double /*{{*/ 40219422Sdas#include "gdtoa.h" 41219422Sdas#else /*}{*/ 42219422Sdas#ifndef NO_PRINTF_A_FMT /*{*/ 43219422Sdas#include "gdtoa.h" 44219422Sdas#endif /*}*/ 45219422Sdas#endif /*}}*/ 46219422Sdas 47219422Sdas#ifdef __i386 48219422Sdas#define NO_GDTOA_i386_Quad 49219422Sdas#endif 50219422Sdas 51219422Sdas#ifdef Use_GDTOA_for_i386_long_double /*{*/ 52219422Sdas#ifndef NO_GDTOA_i386_Quad /*{*/ 53219422Sdas#define GDTOA_both 54219422Sdas#define Use_GDTOA_Qtype 55219422Sdas#ifdef __ICC__ /* or __INTEL_COMPILER__ or __INTEL_COMPILER ?? */ 56219422Sdas#define GDTOA_Qtype _Quad 57219422Sdas#else 58219422Sdas#define GDTOA_Qtype __float128 59219422Sdas#endif 60219422Sdas#endif /*} NO_GDTOA_i386_Quad */ 61219422Sdas#endif /*} Use_GDTOA_for_i386_long_double */ 62219422Sdas 63219422Sdas#ifdef Use_GDTOA_Qtype /*{*/ 64219422Sdas#ifndef GDTOA_H_INCLUDED 65219422Sdas#include "gdtoa.h" 66219422Sdas#endif 67219422Sdas#ifndef GDTOA_Qtype 68219422Sdas#define GDTOA_Qtype long double 69219422Sdas#endif 70219422Sdas#endif /*}*/ 71219422Sdas 72219422Sdas#ifndef GDTOA_H_INCLUDED /*{*/ 73219422Sdas 74219422Sdas enum { /* return values from strtodg */ 75219422Sdas STRTOG_Zero = 0, 76219422Sdas STRTOG_Normal = 1, 77219422Sdas STRTOG_Denormal = 2, 78219422Sdas STRTOG_Infinite = 3, 79219422Sdas STRTOG_NaN = 4, 80219422Sdas STRTOG_NaNbits = 5, 81219422Sdas STRTOG_NoNumber = 6, 82219422Sdas STRTOG_Retmask = 7}; 83219422Sdas 84219422Sdas typedef struct 85219422SdasFPI { 86219422Sdas int nbits; 87219422Sdas int emin; 88219422Sdas int emax; 89219422Sdas int rounding; 90219422Sdas int sudden_underflow; 91219422Sdas } FPI; 92219422Sdas 93219422Sdasenum { /* FPI.rounding values: same as FLT_ROUNDS */ 94219422Sdas FPI_Round_zero = 0, 95219422Sdas FPI_Round_near = 1, 96219422Sdas FPI_Round_up = 2, 97219422Sdas FPI_Round_down = 3 98219422Sdas }; 99219422Sdas#endif /*}*/ 100219422Sdas 101219422Sdas#ifdef NO_PRINTF_A_FMT /*{{*/ 102219422Sdas#define WANT_A_FMT(x) /*nothing*/ 103219422Sdas#else /*}{*/ 104219422Sdas#define WANT_A_FMT(x) x 105219422Sdas#endif /*}}*/ 106219422Sdas 107219422Sdas#include "stdio1.h" 108219422Sdas#include "string.h" 109219422Sdas#include "errno.h" 110219422Sdas 111219422Sdas typedef struct 112219422SdasFinfo { 113219422Sdas union { FILE *cf; char *sf; } u; 114219422Sdas char *ob0, *obe1; 115219422Sdas size_t lastlen; 116219422Sdas } Finfo; 117219422Sdas 118219422Sdas typedef char *(*pgdtoa) ANSI((FPI*, int be, ULong *bits, int *kind, int mode, int ndigits, int *decpt, char **rve)); 119219422Sdas 120219422Sdas typedef struct 121219422SdasFPBits { 122219422Sdas ULong bits[4]; /* sufficient for quad; modify if considering wider types */ 123219422Sdas FPI *fpi; 124219422Sdas pgdtoa gdtoa; 125219422Sdas int sign; 126219422Sdas int ex; /* exponent */ 127219422Sdas int kind; 128219422Sdas } FPBits; 129219422Sdas 130219422Sdas typedef union U 131219422Sdas{ 132219422Sdas double d; 133219422Sdas long double ld; 134219422Sdas#ifdef GDTOA_Qtype 135219422Sdas GDTOA_Qtype Qd; 136219422Sdas#endif 137219422Sdas unsigned int ui[4]; 138219422Sdas unsigned short us[5]; 139219422Sdas } U; 140219422Sdas 141219422Sdas typedef char *(*Putfunc) ANSI((Finfo*, int*)); 142219422Sdas typedef void (*Fpbits) ANSI((U*, FPBits*)); 143219422Sdas 144219422Sdas/* Would have preferred typedef void (*Fpbits)(va_list*, FPBits*) 145219422Sdas * but gcc is buggy in this regard. 146219422Sdas */ 147219422Sdas 148219422Sdas#ifdef Use_GDTOA_for_i386_long_double /*{*/ 149219422Sdas 150219422Sdas#ifdef IEEE_MC68k 151219422Sdas#define _0 0 152219422Sdas#define _1 1 153219422Sdas#define _2 2 154219422Sdas#define _3 3 155219422Sdas#define _4 4 156219422Sdas#endif 157219422Sdas#ifdef IEEE_8087 158219422Sdas#define _0 4 159219422Sdas#define _1 3 160219422Sdas#define _2 2 161219422Sdas#define _3 1 162219422Sdas#define _4 0 163219422Sdas#endif 164219422Sdas 165219422Sdas static void 166219422Sdasxfpbits(U *u, FPBits *b) 167219422Sdas{ 168219422Sdas ULong *bits; 169219422Sdas int ex, i; 170219422Sdas static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; 171219422Sdas 172219422Sdas b->fpi = &fpi0; 173219422Sdas b->gdtoa = gdtoa; 174219422Sdas b->sign = u->us[_0] & 0x8000; 175219422Sdas bits = b->bits; 176219422Sdas bits[1] = (u->us[_1] << 16) | u->us[_2]; 177219422Sdas bits[0] = (u->us[_3] << 16) | u->us[_4]; 178219422Sdas if ( (ex = u->us[_0] & 0x7fff) !=0) { 179219422Sdas i = STRTOG_Normal; 180219422Sdas if (ex == 0x7fff) 181219422Sdas /* Infinity or NaN */ 182219422Sdas i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite; 183219422Sdas } 184219422Sdas else if (bits[0] | bits[1]) { 185219422Sdas i = STRTOG_Denormal; 186219422Sdas ex = 1; 187219422Sdas } 188219422Sdas else 189219422Sdas i = STRTOG_Zero; 190219422Sdas b->kind = i; 191219422Sdas b->ex = ex - (0x3fff + 63); 192219422Sdas } 193219422Sdas 194219422Sdas#undef _0 195219422Sdas#undef _1 196219422Sdas#undef _2 197219422Sdas#undef _3 198219422Sdas#undef _4 199219422Sdas#define GDTOA_LD_fpbits xfpbits 200219422Sdas#endif /*} Use_GDTOA_for_i386_long_double */ 201219422Sdas 202219422Sdas#ifdef Use_GDTOA_Qtype /*{*/ 203219422Sdas#include "gdtoa.h" 204219422Sdas#ifndef GDTOA_Qtype 205219422Sdas#define GDTOA_Qtype long double 206219422Sdas#endif 207219422Sdas#ifdef GDTOA_LD_fpbits 208219422Sdas#define GDTOA_Q_fpbits Qfpbits 209219422Sdas#else 210219422Sdas#define GDTOA_LD_fpbits Qfpbits 211219422Sdas#endif 212219422Sdas 213219422Sdas#ifdef IEEE_MC68k 214219422Sdas#define _0 0 215219422Sdas#define _1 1 216219422Sdas#define _2 2 217219422Sdas#define _3 3 218219422Sdas#endif 219219422Sdas#ifdef IEEE_8087 220219422Sdas#define _0 3 221219422Sdas#define _1 2 222219422Sdas#define _2 1 223219422Sdas#define _3 0 224219422Sdas#endif 225219422Sdas 226219422Sdas static void 227219422SdasQfpbits(U *u, FPBits *b) 228219422Sdas{ 229219422Sdas ULong *bits; 230219422Sdas int ex, i; 231219422Sdas static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 }; 232219422Sdas 233219422Sdas b->fpi = &fpi0; 234219422Sdas b->gdtoa = gdtoa; 235219422Sdas b->sign = u->ui[_0] & 0x80000000L; 236219422Sdas bits = b->bits; 237219422Sdas bits[3] = u->ui[_0] & 0xffff; 238219422Sdas bits[2] = u->ui[_1]; 239219422Sdas bits[1] = u->ui[_2]; 240219422Sdas bits[0] = u->ui[_3]; 241219422Sdas if ( (ex = (u->ui[_0] & 0x7fff0000L) >> 16) !=0) { 242219422Sdas if (ex == 0x7fff) { 243219422Sdas /* Infinity or NaN */ 244219422Sdas i = bits[0] | bits[1] | bits[2] | bits[3] 245219422Sdas ? STRTOG_NaN : STRTOG_Infinite; 246219422Sdas } 247219422Sdas else { 248219422Sdas i = STRTOG_Normal; 249219422Sdas bits[3] |= 0x10000; 250219422Sdas } 251219422Sdas } 252219422Sdas else if (bits[0] | bits[1] | bits[2] | bits[3]) { 253219422Sdas i = STRTOG_Denormal; 254219422Sdas ex = 1; 255219422Sdas } 256219422Sdas else 257219422Sdas i = STRTOG_Zero; 258219422Sdas b->kind = i; 259219422Sdas b->ex = ex - (0x3fff + 112); 260219422Sdas } 261219422Sdas 262219422Sdas#undef _0 263219422Sdas#undef _1 264219422Sdas#undef _2 265219422Sdas#undef _3 266219422Sdas#endif /*} GDTOA_Qtype */ 267219422Sdas 268219422Sdas#ifdef KR_headers 269219422Sdas#define Const /* const */ 270219422Sdas#define Voidptr char* 271219422Sdas#ifndef size_t__ 272219422Sdas#define size_t int 273219422Sdas#define size_t__ 274219422Sdas#endif 275219422Sdas 276219422Sdas#else 277219422Sdas 278219422Sdas#define Const const 279219422Sdas#define Voidptr void* 280219422Sdas 281219422Sdas#endif 282219422Sdas 283219422Sdas#undef MESS 284219422Sdas#ifndef Stderr 285219422Sdas#define Stderr stderr 286219422Sdas#endif 287219422Sdas 288219422Sdas#ifdef _windows_ 289219422Sdas#undef PF_BUF 290219422Sdas#define MESS 291219422Sdas#include "mux0.h" 292219422Sdas#define stdout_or_err(f) (f == stdout) 293219422Sdas#else 294219422Sdas#define stdout_or_err(f) (f == Stderr || f == stdout) 295219422Sdas#endif 296219422Sdas 297219422Sdas#ifdef __cplusplus 298219422Sdasextern "C" { 299219422Sdas#endif 300219422Sdas 301219422Sdas extern char *dtoa ANSI((double, int, int, int*, int*, char **)); 302219422Sdas extern void freedtoa ANSI((char*)); 303219422Sdas 304219422Sdas 305219422Sdas 306219422Sdas#ifdef USE_ULDIV 307219422Sdas/* This is for avoiding 64-bit divisions on the DEC Alpha, since */ 308219422Sdas/* they are not portable among variants of OSF1 (DEC's Unix). */ 309219422Sdas 310219422Sdas#define ULDIV(a,b) uldiv_ASL(a,(unsigned long)(b)) 311219422Sdas 312219422Sdas#ifndef LLBITS 313219422Sdas#define LLBITS 6 314219422Sdas#endif 315219422Sdas#ifndef ULONG 316219422Sdas#define ULONG unsigned long 317219422Sdas#endif 318219422Sdas 319219422Sdas static int 320219422Sdasklog(ULONG x) 321219422Sdas{ 322219422Sdas int k, rv = 0; 323219422Sdas 324219422Sdas if (x > 1L) 325219422Sdas for(k = 1 << LLBITS-1;;) { 326219422Sdas if (x >= (1L << k)) { 327219422Sdas rv |= k; 328219422Sdas x >>= k; 329219422Sdas } 330219422Sdas if (!(k >>= 1)) 331219422Sdas break; 332219422Sdas } 333219422Sdas return rv; 334219422Sdas } 335219422Sdas 336219422Sdas ULONG 337219422Sdasuldiv_ASL(ULONG a, ULONG b) 338219422Sdas{ 339219422Sdas int ka; 340219422Sdas ULONG c, k; 341219422Sdas static ULONG b0; 342219422Sdas static int kb; 343219422Sdas 344219422Sdas if (a < b) 345219422Sdas return 0; 346219422Sdas if (b != b0) { 347219422Sdas b0 = b; 348219422Sdas kb = klog(b); 349219422Sdas } 350219422Sdas k = 1; 351219422Sdas if ((ka = klog(a) - kb) > 0) { 352219422Sdas k <<= ka; 353219422Sdas b <<= ka; 354219422Sdas } 355219422Sdas c = 0; 356219422Sdas for(;;) { 357219422Sdas if (a >= b) { 358219422Sdas a -= b; 359219422Sdas c |= k; 360219422Sdas } 361219422Sdas if (!(k >>= 1)) 362219422Sdas break; 363219422Sdas a <<= 1; 364219422Sdas } 365219422Sdas return c; 366219422Sdas } 367219422Sdas 368219422Sdas#else 369219422Sdas#define ULDIV(a,b) a / b 370219422Sdas#endif /* USE_ULDIV */ 371219422Sdas 372219422Sdas#ifdef PF_BUF 373219422SdasFILE *stderr_ASL = (FILE*)&stderr_ASL; 374219422Sdasvoid (*pfbuf_print_ASL) ANSI((char*)); 375219422Sdaschar *pfbuf_ASL; 376219422Sdasstatic char *pfbuf_next; 377219422Sdasstatic size_t pfbuf_len; 378219422Sdasextern Char *mymalloc_ASL ANSI((size_t)); 379219422Sdasextern Char *myralloc_ASL ANSI((void *, size_t)); 380219422Sdas 381219422Sdas#undef fflush 382219422Sdas#ifdef old_fflush_ASL 383219422Sdas#define fflush old_fflush_ASL 384219422Sdas#endif 385219422Sdas 386219422Sdas void 387219422Sdasfflush_ASL(FILE *f) 388219422Sdas{ 389219422Sdas if (f == stderr_ASL) { 390219422Sdas if (pfbuf_ASL && pfbuf_print_ASL) { 391219422Sdas (*pfbuf_print_ASL)(pfbuf_ASL); 392219422Sdas free(pfbuf_ASL); 393219422Sdas pfbuf_ASL = 0; 394219422Sdas } 395219422Sdas } 396219422Sdas else 397219422Sdas fflush(f); 398219422Sdas } 399219422Sdas 400219422Sdas static void 401219422Sdaspf_put(char *buf, int len) 402219422Sdas{ 403219422Sdas size_t x, y; 404219422Sdas if (!pfbuf_ASL) { 405219422Sdas x = len + 256; 406219422Sdas if (x < 512) 407219422Sdas x = 512; 408219422Sdas pfbuf_ASL = pfbuf_next = (char*)mymalloc_ASL(pfbuf_len = x); 409219422Sdas } 410219422Sdas else if ((y = (pfbuf_next - pfbuf_ASL) + len) >= pfbuf_len) { 411219422Sdas x = pfbuf_len; 412219422Sdas while((x <<= 1) <= y); 413219422Sdas y = pfbuf_next - pfbuf_ASL; 414219422Sdas pfbuf_ASL = (char*)myralloc_ASL(pfbuf_ASL, x); 415219422Sdas pfbuf_next = pfbuf_ASL + y; 416219422Sdas pfbuf_len = x; 417219422Sdas } 418219422Sdas memcpy(pfbuf_next, buf, len); 419219422Sdas pfbuf_next += len; 420219422Sdas *pfbuf_next = 0; 421219422Sdas } 422219422Sdas 423219422Sdas static char * 424219422Sdaspfput(Finfo *f, int *rvp) 425219422Sdas{ 426219422Sdas int n; 427219422Sdas char *ob0 = f->ob0; 428219422Sdas *rvp += n = (int)(f->obe1 - ob0); 429219422Sdas pf_put(ob0, n); 430219422Sdas return ob0; 431219422Sdas } 432219422Sdas#endif /* PF_BUF */ 433219422Sdas 434219422Sdas static char * 435219422SdasFput 436219422Sdas#ifdef KR_headers 437219422Sdas (f, rvp) Finfo *f; int *rvp; 438219422Sdas#else 439219422Sdas (Finfo *f, int *rvp) 440219422Sdas#endif 441219422Sdas{ 442219422Sdas char *ob0 = f->ob0; 443219422Sdas 444219422Sdas *rvp += f->obe1 - ob0; 445219422Sdas *f->obe1 = 0; 446219422Sdas fputs(ob0, f->u.cf); 447219422Sdas return ob0; 448219422Sdas } 449219422Sdas 450219422Sdas 451219422Sdas#ifdef _windows_ 452219422Sdasint stdout_fileno_ASL = 1; 453219422Sdas 454219422Sdas static char * 455219422SdasWput 456219422Sdas#ifdef KR_headers 457219422Sdas (f, rvp) Finfo *f; int *rvp; 458219422Sdas#else 459219422Sdas (Finfo *f, int *rvp) 460219422Sdas#endif 461219422Sdas{ 462219422Sdas char *ob0 = f->ob0; 463219422Sdas 464219422Sdas *rvp += f->obe1 - ob0; 465219422Sdas *f->obe1 = 0; 466219422Sdas mwrite(ob0, f->obe1 - ob0); 467219422Sdas return ob0; 468219422Sdas } 469219422Sdas#endif /*_windows_*/ 470219422Sdas 471219422Sdas 472219422Sdas#ifdef IEEE_MC68k 473219422Sdas#define _0 0 474219422Sdas#define _1 1 475219422Sdas#endif 476219422Sdas#ifdef IEEE_8087 477219422Sdas#define _0 1 478219422Sdas#define _1 0 479219422Sdas#endif 480219422Sdas 481219422Sdas static void 482219422Sdasdfpbits(U *u, FPBits *b) 483219422Sdas{ 484219422Sdas ULong *bits; 485219422Sdas int ex, i; 486219422Sdas static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 }; 487219422Sdas 488219422Sdas b->fpi = &fpi0; 489219422Sdas b->gdtoa = gdtoa; 490219422Sdas b->sign = u->ui[_0] & 0x80000000L; 491219422Sdas bits = b->bits; 492219422Sdas bits[1] = u->ui[_0] & 0xfffff; 493219422Sdas bits[0] = u->ui[_1]; 494219422Sdas if ( (ex = (u->ui[_0] & 0x7ff00000L) >> 20) !=0) { 495219422Sdas if (ex == 0x7ff) { 496219422Sdas /* Infinity or NaN */ 497219422Sdas i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite; 498219422Sdas } 499219422Sdas else { 500219422Sdas i = STRTOG_Normal; 501219422Sdas bits[1] |= 0x100000; 502219422Sdas } 503219422Sdas } 504219422Sdas else if (bits[0] | bits[1]) { 505219422Sdas i = STRTOG_Denormal; 506219422Sdas ex = 1; 507219422Sdas } 508219422Sdas else 509219422Sdas i = STRTOG_Zero; 510219422Sdas b->kind = i; 511219422Sdas b->ex = ex - (0x3ff + 52); 512219422Sdas } 513219422Sdas 514219422Sdas#undef _0 515219422Sdas#undef _1 516219422Sdas 517219422Sdas#ifdef Honor_FLT_ROUNDS /*{{*/ 518219422Sdas#ifdef Trust_FLT_ROUNDS /*{{*/ 519219422Sdas#define RoundCheck if (Rounding == -1) Rounding = Flt_Rounds; if (Rounding != 1){\ 520219422Sdas fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;} 521219422Sdas#else /*}{*/ 522219422Sdas#define RoundCheck if (Rounding == -1) { Rounding = 1; switch((fegetround()) {\ 523219422Sdas case FE_TOWARDZERO: Rounding = 0; break;\ 524219422Sdas case FE_UPWARD: Rounding = 2; break;\ 525219422Sdas case FE_DOWNWARD: Rounding = 3; }}\ 526219422Sdas if (Rounding != 1){\ 527219422Sdas fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;} 528219422Sdas#endif /*}}*/ 529219422Sdas#else /*}{*/ 530219422Sdas#define RoundCheck /*nothing*/ 531219422Sdas#endif /*}}*/ 532219422Sdas 533219422Sdas#ifndef NO_PRINTF_A_FMT /*{*/ 534219422Sdas static int 535219422Sdasfpiprec(FPBits *b) /* return number of hex digits minus 1, or 0 for zero */ 536219422Sdas{ 537219422Sdas FPI *fpi; 538219422Sdas ULong *bits; 539219422Sdas int i, j, k, m; 540219422Sdas 541219422Sdas if (b->kind == STRTOG_Zero) 542219422Sdas return b->ex = 0; 543219422Sdas fpi = b->fpi; 544219422Sdas bits = b->bits; 545219422Sdas for(k = (fpi->nbits - 1) >> 2; k > 0; --k) 546219422Sdas if ((bits[k >> 3] >> 4*(k & 7)) & 0xf) { 547219422Sdas m = k >> 3; 548219422Sdas for(i = 0; i <= m; ++i) 549219422Sdas if (bits[i]) { 550219422Sdas if (i > 0) { 551219422Sdas k -= 8*i; 552219422Sdas b->ex += 32*i; 553219422Sdas for(j = i; j <= m; ++j) 554219422Sdas bits[j-i] = bits[j]; 555219422Sdas } 556219422Sdas break; 557219422Sdas } 558219422Sdas for(i = 0; i < 28 && !((bits[0] >> i) & 0xf); i += 4); 559219422Sdas if (i) { 560219422Sdas b->ex += i; 561219422Sdas m = k >> 3; 562219422Sdas k -= (i >> 2); 563219422Sdas for(j = 0;;++j) { 564219422Sdas bits[j] >>= i; 565219422Sdas if (j == m) 566219422Sdas break; 567219422Sdas bits[j] |= bits[j+1] << (32 - i); 568219422Sdas } 569219422Sdas } 570219422Sdas break; 571219422Sdas } 572219422Sdas return k; 573219422Sdas } 574219422Sdas 575219422Sdas static int 576219422Sdasbround(FPBits *b, int prec, int prec1) /* round to prec hex digits after the "." */ 577219422Sdas{ /* prec1 = incoming precision (after ".") */ 578219422Sdas FPI *fpi = b->fpi; 579219422Sdas ULong *bits, t; 580219422Sdas int i, inc, j, k, m, n; 581219422Sdas#ifdef Honor_FLT_ROUNDS 582219422Sdas int rounding = fpi->rounding; 583219422Sdas 584219422Sdas if (rounding > FPI_Round_near && b->sign) 585219422Sdas rounding = FPI_Round_up + FPI_Round_down - rounding; 586219422Sdas if (rounding == FPI_Round_down) 587219422Sdas rounding = FPI_Round_zero; 588219422Sdas#endif 589219422Sdas m = prec1 - prec; 590219422Sdas bits = b->bits; 591219422Sdas inc = 0; 592219422Sdas#ifdef Honor_FLT_ROUNDS 593219422Sdas switch(rounding) { 594219422Sdas case FPI_Round_up: 595219422Sdas for(i = 0; i < m; i += 8) 596219422Sdas if (bits[i>>3]) 597219422Sdas goto inc1; 598219422Sdas if ((j = i - m) > 0 && bits[(i-8)>>3] << j*4) 599219422Sdas goto inc1; 600219422Sdas break; 601219422Sdas case FPI_Round_near: 602219422Sdas#endif 603219422Sdas k = m - 1; 604219422Sdas if ((t = bits[k >> 3] >> (j = (k&7)*4)) & 8) { 605219422Sdas if (t & 7) 606219422Sdas goto inc1; 607219422Sdas if (j && bits[k >> 3] << (32 - j)) 608219422Sdas goto inc1; 609219422Sdas while(k >= 8) { 610219422Sdas k -= 8; 611219422Sdas if (bits[k>>3]) { 612219422Sdas inc1: 613219422Sdas inc = 1; 614219422Sdas goto haveinc; 615219422Sdas } 616219422Sdas } 617219422Sdas } 618219422Sdas#ifdef Honor_FLT_ROUNDS 619219422Sdas } 620219422Sdas#endif 621219422Sdas haveinc: 622219422Sdas b->ex += m*4; 623219422Sdas i = m >> 3; 624219422Sdas k = prec1 >> 3; 625219422Sdas j = i; 626219422Sdas if ((n = 4*(m & 7))) 627219422Sdas for(;; ++j) { 628219422Sdas bits[j-i] = bits[j] >> n; 629219422Sdas if (j == k) 630219422Sdas break; 631219422Sdas bits[j-i] |= bits[j+1] << (32-n); 632219422Sdas } 633219422Sdas else 634219422Sdas for(;; ++j) { 635219422Sdas bits[j-i] = bits[j]; 636219422Sdas if (j == k) 637219422Sdas break; 638219422Sdas } 639219422Sdas k = prec >> 3; 640219422Sdas if (inc) { 641219422Sdas for(j = 0; !(++bits[j] & 0xffffffff); ++j); 642219422Sdas if (j > k) { 643219422Sdas onebit: 644219422Sdas bits[0] = 1; 645219422Sdas b->ex += 4*prec; 646219422Sdas return 1; 647219422Sdas } 648219422Sdas if ((j = prec & 7) < 7 && bits[k] >> (j+1)*4) 649219422Sdas goto onebit; 650219422Sdas } 651219422Sdas for(i = 0; !(bits[i >> 3] & (0xf << 4*(i&7))); ++i); 652219422Sdas if (i) { 653219422Sdas b->ex += 4*i; 654219422Sdas prec -= i; 655219422Sdas j = i >> 3; 656219422Sdas i &= 7; 657219422Sdas i *= 4; 658219422Sdas for(m = j; ; ++m) { 659219422Sdas bits[m-j] = bits[m] >> i; 660219422Sdas if (m == k) 661219422Sdas break; 662219422Sdas bits[m-j] |= bits[m+1] << (32 - i); 663219422Sdas } 664219422Sdas } 665219422Sdas return prec; 666219422Sdas } 667219422Sdas#endif /*}NO_PRINTF_A_FMT*/ 668219422Sdas 669219422Sdas#define put(x) { *outbuf++ = x; if (outbuf == obe) outbuf = (*fput)(f,&rv); } 670219422Sdas 671219422Sdas static int 672219422Sdasx_sprintf 673219422Sdas#ifdef KR_headers 674219422Sdas (obe, fput, f, fmt, ap) 675219422Sdas char *obe, *fmt; Finfo *f; Putfunc fput; va_list ap; 676219422Sdas#else 677219422Sdas (char *obe, Putfunc fput, Finfo *f, const char *fmt, va_list ap) 678219422Sdas#endif 679219422Sdas{ 680219422Sdas FPBits fpb; 681219422Sdas Fpbits fpbits; 682219422Sdas U u; 683219422Sdas char *digits, *ob0, *outbuf, *s, *s0, *se; 684219422Sdas Const char *fmt0; 685219422Sdas char buf[32]; 686219422Sdas long i; 687219422Sdas unsigned long j, ul; 688219422Sdas double x; 689219422Sdas int alt, base, c, decpt, dot, conv, i1, k, lead0, left, 690219422Sdas len, prec, prec1, psign, rv, sign, width; 691219422Sdas long Ltmp, *ip; 692219422Sdas short sh; 693219422Sdas unsigned short us; 694219422Sdas unsigned int ui; 695219422Sdas#ifdef Honor_FLT_ROUNDS 696219422Sdas FPI fpi1; 697219422Sdas int Rounding = -1; 698219422Sdas#endif 699219422Sdas#ifndef NO_PRINTF_A_FMT /*{*/ 700219422Sdas int bex, bw; 701219422Sdas#endif /*} NO_PRINTF_A_FMT */ 702219422Sdas static char hex[] = "0123456789abcdefpx"; 703219422Sdas static char Hex[] = "0123456789ABCDEFPX"; 704219422Sdas 705219422Sdas ob0 = outbuf = f->ob0; 706219422Sdas rv = 0; 707219422Sdas for(;;) { 708219422Sdas for(;;) { 709219422Sdas switch(c = *fmt++) { 710219422Sdas case 0: 711219422Sdas goto done; 712219422Sdas case '%': 713219422Sdas break; 714219422Sdas default: 715219422Sdas put(c) 716219422Sdas continue; 717219422Sdas } 718219422Sdas break; 719219422Sdas } 720219422Sdas alt=dot=lead0=left=len=prec=psign=sign=width=0; 721219422Sdas fpbits = dfpbits; 722219422Sdas fmt0 = fmt; 723219422Sdas fmtloop: 724219422Sdas switch(conv = *fmt++) { 725219422Sdas case ' ': 726219422Sdas case '+': 727219422Sdas sign = conv; 728219422Sdas goto fmtloop; 729219422Sdas case '-': 730219422Sdas if (dot) 731219422Sdas psign = 1; 732219422Sdas else 733219422Sdas left = 1; 734219422Sdas goto fmtloop; 735219422Sdas case '#': 736219422Sdas alt = 1; 737219422Sdas goto fmtloop; 738219422Sdas case '0': 739219422Sdas if (!lead0 && !dot) { 740219422Sdas lead0 = 1; 741219422Sdas goto fmtloop; 742219422Sdas } 743219422Sdas case '1': 744219422Sdas case '2': 745219422Sdas case '3': 746219422Sdas case '4': 747219422Sdas case '5': 748219422Sdas case '6': 749219422Sdas case '7': 750219422Sdas case '8': 751219422Sdas case '9': 752219422Sdas k = conv - '0'; 753219422Sdas while((c = *fmt) >= '0' && c <= '9') { 754219422Sdas k = 10*k + c - '0'; 755219422Sdas fmt++; 756219422Sdas } 757219422Sdas if (dot) 758219422Sdas prec = psign ? -k : k; 759219422Sdas else 760219422Sdas width = k; 761219422Sdas goto fmtloop; 762219422Sdas case 'h': 763219422Sdas len = 2; 764219422Sdas goto fmtloop; 765219422Sdas case 'L': 766219422Sdas#ifdef GDTOA_LD_fpbits /*{*/ 767219422Sdas fpbits = GDTOA_LD_fpbits; 768219422Sdas#ifdef GDTOA_Q_fpbits 769219422Sdas if (*fmt == 'q') { 770219422Sdas ++fmt; 771219422Sdas fpbits = Qfpbits; 772219422Sdas } 773219422Sdas#endif 774219422Sdas#endif /*}*/ 775219422Sdas goto fmtloop; 776219422Sdas case 'l': 777219422Sdas len = 1; 778219422Sdas goto fmtloop; 779219422Sdas case '.': 780219422Sdas dot = 1; 781219422Sdas goto fmtloop; 782219422Sdas case '*': 783219422Sdas k = va_arg(ap, int); 784219422Sdas if (dot) 785219422Sdas prec = k; 786219422Sdas else { 787219422Sdas if (k < 0) { 788219422Sdas sign = '-'; 789219422Sdas k = -k; 790219422Sdas } 791219422Sdas width = k; 792219422Sdas } 793219422Sdas goto fmtloop; 794219422Sdas case 'c': 795219422Sdas c = va_arg(ap, int); 796219422Sdas put(c) 797219422Sdas continue; 798219422Sdas case '%': 799219422Sdas put(conv) 800219422Sdas continue; 801219422Sdas case 'u': 802219422Sdas switch(len) { 803219422Sdas case 0: 804219422Sdas ui = va_arg(ap, int); 805219422Sdas i = ui; 806219422Sdas break; 807219422Sdas case 1: 808219422Sdas i = va_arg(ap, long); 809219422Sdas break; 810219422Sdas case 2: 811219422Sdas us = va_arg(ap, int); 812219422Sdas i = us; 813219422Sdas } 814219422Sdas sign = 0; 815219422Sdas goto have_i; 816219422Sdas case 'i': 817219422Sdas case 'd': 818219422Sdas switch(len) { 819219422Sdas case 0: 820219422Sdas k = va_arg(ap, int); 821219422Sdas i = k; 822219422Sdas break; 823219422Sdas case 1: 824219422Sdas i = va_arg(ap, long); 825219422Sdas break; 826219422Sdas case 2: 827219422Sdas sh = va_arg(ap, int); 828219422Sdas i = sh; 829219422Sdas } 830219422Sdas if (i < 0) { 831219422Sdas sign = '-'; 832219422Sdas i = -i; 833219422Sdas } 834219422Sdas have_i: 835219422Sdas base = 10; 836219422Sdas ul = i; 837219422Sdas digits = hex; 838219422Sdas baseloop: 839219422Sdas if (dot) 840219422Sdas lead0 = 0; 841219422Sdas s = buf; 842219422Sdas if (!ul) 843219422Sdas alt = 0; 844219422Sdas do { 845219422Sdas j = ULDIV(ul, base); 846219422Sdas *s++ = digits[ul - base*j]; 847219422Sdas } 848219422Sdas while((ul = j)); 849219422Sdas prec -= c = s - buf; 850219422Sdas if (alt && conv == 'o' && prec <= 0) 851219422Sdas prec = 1; 852219422Sdas if ((width -= c) > 0) { 853219422Sdas if (prec > 0) 854219422Sdas width -= prec; 855219422Sdas if (sign) 856219422Sdas width--; 857219422Sdas if (alt == 2) 858219422Sdas width--; 859219422Sdas } 860219422Sdas if (left) { 861219422Sdas if (alt == 2) 862219422Sdas put('0') /* for 0x */ 863219422Sdas if (sign) 864219422Sdas put(sign) 865219422Sdas while(--prec >= 0) 866219422Sdas put('0') 867219422Sdas do put(*--s) 868219422Sdas while(s > buf); 869219422Sdas while(--width >= 0) 870219422Sdas put(' ') 871219422Sdas continue; 872219422Sdas } 873219422Sdas if (width > 0) { 874219422Sdas if (lead0) { 875219422Sdas if (alt == 2) 876219422Sdas put('0') 877219422Sdas if (sign) 878219422Sdas put(sign) 879219422Sdas while(--width >= 0) 880219422Sdas put('0') 881219422Sdas goto s_loop; 882219422Sdas } 883219422Sdas else 884219422Sdas while(--width >= 0) 885219422Sdas put(' ') 886219422Sdas } 887219422Sdas if (alt == 2) 888219422Sdas put('0') 889219422Sdas if (sign) 890219422Sdas put(sign) 891219422Sdas s_loop: 892219422Sdas while(--prec >= 0) 893219422Sdas put('0') 894219422Sdas do put(*--s) 895219422Sdas while(s > buf); 896219422Sdas continue; 897219422Sdas case 'n': 898219422Sdas ip = va_arg(ap, long*); 899219422Sdas if (!ip) 900219422Sdas ip = &Ltmp; 901219422Sdas c = outbuf - ob0 + rv; 902219422Sdas switch(len) { 903219422Sdas case 0: 904219422Sdas *(int*)ip = c; 905219422Sdas break; 906219422Sdas case 1: 907219422Sdas *ip = c; 908219422Sdas break; 909219422Sdas case 2: 910219422Sdas *(short*)ip = c; 911219422Sdas } 912219422Sdas break; 913219422Sdas case 'p': 914219422Sdas len = alt = 1; 915219422Sdas /* no break */ 916219422Sdas case 'x': 917219422Sdas digits = hex; 918219422Sdas goto more_x; 919219422Sdas case 'X': 920219422Sdas digits = Hex; 921219422Sdas more_x: 922219422Sdas if (alt) { 923219422Sdas alt = 2; 924219422Sdas sign = conv; 925219422Sdas } 926219422Sdas else 927219422Sdas sign = 0; 928219422Sdas base = 16; 929219422Sdas get_u: 930219422Sdas switch(len) { 931219422Sdas case 0: 932219422Sdas ui = va_arg(ap, int); 933219422Sdas ul = ui; 934219422Sdas break; 935219422Sdas case 1: 936219422Sdas ul = va_arg(ap, long); 937219422Sdas break; 938219422Sdas case 2: 939219422Sdas us = va_arg(ap, int); 940219422Sdas ul = us; 941219422Sdas } 942219422Sdas if (!ul) 943219422Sdas sign = alt = 0; 944219422Sdas goto baseloop; 945219422Sdas case 'o': 946219422Sdas base = 8; 947219422Sdas digits = hex; 948219422Sdas goto get_u; 949219422Sdas case 's': 950219422Sdas s0 = 0; 951219422Sdas s = va_arg(ap, char*); 952219422Sdas if (!s) 953219422Sdas s = "<NULL>"; 954219422Sdas if (prec < 0) 955219422Sdas prec = 0; 956219422Sdas have_s: 957219422Sdas if (dot) { 958219422Sdas for(c = 0; c < prec; c++) 959219422Sdas if (!s[c]) 960219422Sdas break; 961219422Sdas prec = c; 962219422Sdas } 963219422Sdas else 964219422Sdas prec = strlen(s); 965219422Sdas width -= prec; 966219422Sdas if (!left) 967219422Sdas while(--width >= 0) 968219422Sdas put(' ') 969219422Sdas while(--prec >= 0) 970219422Sdas put(*s++) 971219422Sdas while(--width >= 0) 972219422Sdas put(' ') 973219422Sdas if (s0) 974219422Sdas freedtoa(s0); 975219422Sdas continue; 976219422Sdas case 'f': 977219422Sdas if (!dot) 978219422Sdas prec = 6; 979219422Sdas#ifdef GDTOA_H_INCLUDED 980219422Sdas if (fpbits == dfpbits) { 981219422Sdas#endif 982219422Sdas x = va_arg(ap, double); 983219422Sdas s = s0 = dtoa(x, 3, prec, &decpt, &fpb.sign, &se); 984219422Sdas#ifdef GDTOA_H_INCLUDED 985219422Sdas } 986219422Sdas else { 987219422Sdas#ifdef GDTOA_both 988219422Sdas if (fpbits == GDTOA_LD_fpbits) 989219422Sdas u.ld = va_arg(ap, long double); 990219422Sdas else 991219422Sdas u.Qd = va_arg(ap, GDTOA_Qtype); 992219422Sdas#else 993219422Sdas u.ld = va_arg(ap, long double); 994219422Sdas#endif 995219422Sdas fpbits(&u, &fpb); 996219422Sdas RoundCheck 997219422Sdas s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits, 998219422Sdas &fpb.kind, 3, prec, &decpt, &se); 999219422Sdas } 1000219422Sdas#endif 1001219422Sdas if (decpt == 9999) { 1002219422Sdas fmt9999: 1003219422Sdas dot = prec = alt = 0; 1004219422Sdas if (*s == 'N') 1005219422Sdas goto have_s; 1006219422Sdas decpt = strlen(s); 1007219422Sdas } 1008219422Sdas f_fmt: 1009219422Sdas if (fpb.sign && (x||sign)) 1010219422Sdas sign = '-'; 1011219422Sdas if (prec > 0) 1012219422Sdas width -= prec; 1013219422Sdas if (width > 0) { 1014219422Sdas if (sign) 1015219422Sdas --width; 1016219422Sdas if (decpt <= 0) { 1017219422Sdas --width; 1018219422Sdas if (prec > 0) 1019219422Sdas --width; 1020219422Sdas } 1021219422Sdas else { 1022219422Sdas if (s == se) 1023219422Sdas decpt = 1; 1024219422Sdas width -= decpt; 1025219422Sdas if (prec > 0 || alt) 1026219422Sdas --width; 1027219422Sdas } 1028219422Sdas } 1029219422Sdas if (width > 0 && !left) { 1030219422Sdas if (lead0) { 1031219422Sdas if (sign) 1032219422Sdas put(sign) 1033219422Sdas sign = 0; 1034219422Sdas do put('0') 1035219422Sdas while(--width > 0); 1036219422Sdas } 1037219422Sdas else do put(' ') 1038219422Sdas while(--width > 0); 1039219422Sdas } 1040219422Sdas if (sign) 1041219422Sdas put(sign) 1042219422Sdas if (decpt <= 0) { 1043219422Sdas put('0') 1044219422Sdas if (prec > 0 || alt) 1045219422Sdas put('.') 1046219422Sdas while(decpt < 0) { 1047219422Sdas put('0') 1048219422Sdas prec--; 1049219422Sdas decpt++; 1050219422Sdas } 1051219422Sdas } 1052219422Sdas else { 1053219422Sdas do { 1054219422Sdas if ((c = *s)) 1055219422Sdas s++; 1056219422Sdas else 1057219422Sdas c = '0'; 1058219422Sdas put(c) 1059219422Sdas } 1060219422Sdas while(--decpt > 0); 1061219422Sdas if (prec > 0 || alt) 1062219422Sdas put('.') 1063219422Sdas } 1064219422Sdas while(--prec >= 0) { 1065219422Sdas if ((c = *s)) 1066219422Sdas s++; 1067219422Sdas else 1068219422Sdas c = '0'; 1069219422Sdas put(c) 1070219422Sdas } 1071219422Sdas while(--width >= 0) 1072219422Sdas put(' ') 1073219422Sdas if (s0) 1074219422Sdas freedtoa(s0); 1075219422Sdas continue; 1076219422Sdas case 'G': 1077219422Sdas case 'g': 1078219422Sdas if (!dot) 1079219422Sdas prec = 6; 1080219422Sdas if (prec < 0) 1081219422Sdas prec = 0; 1082219422Sdas#ifdef GDTOA_H_INCLUDED 1083219422Sdas if (fpbits == dfpbits) { 1084219422Sdas#endif 1085219422Sdas x = va_arg(ap, double); 1086219422Sdas s = s0 = dtoa(x, prec ? 2 : 0, prec, &decpt, 1087219422Sdas &fpb.sign, &se); 1088219422Sdas#ifdef GDTOA_H_INCLUDED 1089219422Sdas } 1090219422Sdas else { 1091219422Sdas#ifdef GDTOA_both 1092219422Sdas if (fpbits == GDTOA_LD_fpbits) 1093219422Sdas u.ld = va_arg(ap, long double); 1094219422Sdas else 1095219422Sdas u.Qd = va_arg(ap, GDTOA_Qtype); 1096219422Sdas#else 1097219422Sdas u.ld = va_arg(ap, long double); 1098219422Sdas#endif 1099219422Sdas fpbits(&u, &fpb); 1100219422Sdas RoundCheck 1101219422Sdas s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits, 1102219422Sdas &fpb.kind, prec ? 2 : 0, prec, &decpt, &se); 1103219422Sdas } 1104219422Sdas#endif 1105219422Sdas if (decpt == 9999) 1106219422Sdas goto fmt9999; 1107219422Sdas c = se - s; 1108219422Sdas prec1 = prec; 1109219422Sdas if (!prec) { 1110219422Sdas prec = c; 1111219422Sdas prec1 = c + (s[1] || alt ? 5 : 4); 1112219422Sdas /* %.0g gives 10 rather than 1e1 */ 1113219422Sdas } 1114219422Sdas if (decpt > -4 && decpt <= prec1) { 1115219422Sdas if (alt) 1116219422Sdas prec -= decpt; 1117219422Sdas else 1118219422Sdas prec = c - decpt; 1119219422Sdas if (prec < 0) 1120219422Sdas prec = 0; 1121219422Sdas goto f_fmt; 1122219422Sdas } 1123219422Sdas conv -= 2; 1124219422Sdas if (!alt && prec > c) 1125219422Sdas prec = c; 1126219422Sdas --prec; 1127219422Sdas goto e_fmt; 1128219422Sdas case 'e': 1129219422Sdas case 'E': 1130219422Sdas if (!dot) 1131219422Sdas prec = 6; 1132219422Sdas if (prec < 0) 1133219422Sdas prec = 0; 1134219422Sdas#ifdef GDTOA_H_INCLUDED 1135219422Sdas if (fpbits == dfpbits) { 1136219422Sdas#endif 1137219422Sdas x = va_arg(ap, double); 1138219422Sdas s = s0 = dtoa(x, prec ? 2 : 0, prec+1, &decpt, 1139219422Sdas &fpb.sign, &se); 1140219422Sdas#ifdef GDTOA_H_INCLUDED 1141219422Sdas } 1142219422Sdas else { 1143219422Sdas#ifdef GDTOA_both 1144219422Sdas if (fpbits == GDTOA_LD_fpbits) 1145219422Sdas u.ld = va_arg(ap, long double); 1146219422Sdas else 1147219422Sdas u.Qd = va_arg(ap, GDTOA_Qtype); 1148219422Sdas#else 1149219422Sdas u.ld = va_arg(ap, long double); 1150219422Sdas#endif 1151219422Sdas fpbits(&u, &fpb); 1152219422Sdas RoundCheck 1153219422Sdas s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits, 1154219422Sdas &fpb.kind, prec ? 2 : 0, prec, &decpt, &se); 1155219422Sdas } 1156219422Sdas#endif 1157219422Sdas if (decpt == 9999) 1158219422Sdas goto fmt9999; 1159219422Sdas e_fmt: 1160219422Sdas if (fpb.sign && (x||sign)) 1161219422Sdas sign = '-'; 1162219422Sdas if ((width -= prec + 5) > 0) { 1163219422Sdas if (sign) 1164219422Sdas --width; 1165219422Sdas if (prec || alt) 1166219422Sdas --width; 1167219422Sdas } 1168219422Sdas if ((c = --decpt) < 0) 1169219422Sdas c = -c; 1170219422Sdas while(c >= 100) { 1171219422Sdas --width; 1172219422Sdas c /= 10; 1173219422Sdas } 1174219422Sdas if (width > 0 && !left) { 1175219422Sdas if (lead0) { 1176219422Sdas if (sign) 1177219422Sdas put(sign) 1178219422Sdas sign = 0; 1179219422Sdas do put('0') 1180219422Sdas while(--width > 0); 1181219422Sdas } 1182219422Sdas else do put(' ') 1183219422Sdas while(--width > 0); 1184219422Sdas } 1185219422Sdas if (sign) 1186219422Sdas put(sign) 1187219422Sdas put(*s++) 1188219422Sdas if (prec || alt) 1189219422Sdas put('.') 1190219422Sdas while(--prec >= 0) { 1191219422Sdas if ((c = *s)) 1192219422Sdas s++; 1193219422Sdas else 1194219422Sdas c = '0'; 1195219422Sdas put(c) 1196219422Sdas } 1197219422Sdas put(conv) 1198219422Sdas if (decpt < 0) { 1199219422Sdas put('-') 1200219422Sdas decpt = -decpt; 1201219422Sdas } 1202219422Sdas else 1203219422Sdas put('+') 1204219422Sdas for(c = 2, k = 10; 10*k <= decpt; c++, k *= 10); 1205219422Sdas for(;;) { 1206219422Sdas i1 = decpt / k; 1207219422Sdas put(i1 + '0') 1208219422Sdas if (--c <= 0) 1209219422Sdas break; 1210219422Sdas decpt -= i1*k; 1211219422Sdas decpt *= 10; 1212219422Sdas } 1213219422Sdas while(--width >= 0) 1214219422Sdas put(' ') 1215219422Sdas freedtoa(s0); 1216219422Sdas continue; 1217219422Sdas#ifndef NO_PRINTF_A_FMT 1218219422Sdas case 'a': 1219219422Sdas digits = hex; 1220219422Sdas goto more_a; 1221219422Sdas case 'A': 1222219422Sdas digits = Hex; 1223219422Sdas more_a: 1224219422Sdas#ifdef GDTOA_H_INCLUDED /*{{*/ 1225219422Sdas if (fpbits == dfpbits) 1226219422Sdas u.d = va_arg(ap, double); 1227219422Sdas#ifdef GDTOA_both /*{*/ 1228219422Sdas else if (fpbits == GDTOA_LD_fpbits) 1229219422Sdas u.ld = va_arg(ap, long double); 1230219422Sdas else 1231219422Sdas u.Qd = va_arg(ap, GDTOA_Qtype); 1232219422Sdas#else 1233219422Sdas else 1234219422Sdas u.ld = va_arg(ap, long double); 1235219422Sdas#endif /*}*/ 1236219422Sdas#else /*}{*/ 1237219422Sdas u.d = va_arg(ap, double); 1238219422Sdas#endif /*}}*/ 1239219422Sdas fpbits(&u, &fpb); 1240219422Sdas if (fpb.kind == STRTOG_Infinite) { 1241219422Sdas s = "Infinity"; 1242219422Sdas s0 = 0; 1243219422Sdas goto fmt9999; 1244219422Sdas } 1245219422Sdas if (fpb.kind == STRTOG_NaN) { 1246219422Sdas s = "NaN"; 1247219422Sdas s0 = 0; 1248219422Sdas goto fmt9999; 1249219422Sdas } 1250219422Sdas prec1 = fpiprec(&fpb); 1251219422Sdas if (dot && prec < prec1) 1252219422Sdas prec1 = bround(&fpb, prec, prec1); 1253219422Sdas bw = 1; 1254219422Sdas bex = fpb.ex + 4*prec1; 1255219422Sdas if (bex) { 1256219422Sdas if ((i1 = bex) < 0) 1257219422Sdas i1 = -i1; 1258219422Sdas while(i1 >= 10) { 1259219422Sdas ++bw; 1260219422Sdas i1 /= 10; 1261219422Sdas } 1262219422Sdas } 1263219422Sdas if (fpb.sign && (sign || fpb.kind != STRTOG_Zero)) 1264219422Sdas sign = '-'; 1265219422Sdas if ((width -= bw + 5) > 0) { 1266219422Sdas if (sign) 1267219422Sdas --width; 1268219422Sdas if (prec1 || alt) 1269219422Sdas --width; 1270219422Sdas } 1271219422Sdas if ((width -= prec1) > 0 && !left && !lead0) { 1272219422Sdas do put(' ') 1273219422Sdas while(--width > 0); 1274219422Sdas } 1275219422Sdas if (sign) 1276219422Sdas put(sign) 1277219422Sdas put('0') 1278219422Sdas put(digits[17]) 1279219422Sdas if (lead0 && width > 0 && !left) { 1280219422Sdas do put('0') 1281219422Sdas while(--width > 0); 1282219422Sdas } 1283219422Sdas i1 = prec1 & 7; 1284219422Sdas k = prec1 >> 3; 1285219422Sdas put(digits[(fpb.bits[k] >> 4*i1) & 0xf]) 1286219422Sdas if (prec1 > 0 || alt) 1287219422Sdas put('.') 1288219422Sdas if (prec1 > 0) { 1289219422Sdas prec -= prec1; 1290219422Sdas while(prec1 > 0) { 1291219422Sdas if (--i1 < 0) { 1292219422Sdas if (--k < 0) 1293219422Sdas break; 1294219422Sdas i1 = 7; 1295219422Sdas } 1296219422Sdas put(digits[(fpb.bits[k] >> 4*i1) & 0xf]) 1297219422Sdas --prec1; 1298219422Sdas } 1299219422Sdas if (alt && prec > 0) 1300219422Sdas do put(0) 1301219422Sdas while(--prec > 0); 1302219422Sdas } 1303219422Sdas put(digits[16]) 1304219422Sdas if (bex < 0) { 1305219422Sdas put('-') 1306219422Sdas bex = -bex; 1307219422Sdas } 1308219422Sdas else 1309219422Sdas put('+') 1310219422Sdas for(c = 1; 10*c <= bex; c *= 10); 1311219422Sdas for(;;) { 1312219422Sdas i1 = bex / c; 1313219422Sdas put('0' + i1) 1314219422Sdas if (!--bw) 1315219422Sdas break; 1316219422Sdas bex -= i1 * c; 1317219422Sdas bex *= 10; 1318219422Sdas } 1319219422Sdas while(--width >= 0) 1320219422Sdas put(' ') 1321219422Sdas continue; 1322219422Sdas#endif /* NO_PRINTF_A_FMT */ 1323219422Sdas default: 1324219422Sdas put('%') 1325219422Sdas while(fmt0 < fmt) 1326219422Sdas put(*fmt0++) 1327219422Sdas continue; 1328219422Sdas } 1329219422Sdas } 1330219422Sdas done: 1331219422Sdas *outbuf = 0; 1332219422Sdas return (f->lastlen = outbuf - ob0) + rv; 1333219422Sdas } 1334219422Sdas 1335219422Sdas#define Bsize 256 1336219422Sdas 1337219422Sdas int 1338219422SdasPrintf 1339219422Sdas#ifdef KR_headers 1340219422Sdas (va_alist) 1341219422Sdas va_dcl 1342219422Sdas{ 1343219422Sdas char *fmt; 1344219422Sdas 1345219422Sdas va_list ap; 1346219422Sdas int rv; 1347219422Sdas Finfo f; 1348219422Sdas char buf[Bsize]; 1349219422Sdas 1350219422Sdas va_start(ap); 1351219422Sdas fmt = va_arg(ap, char*); 1352219422Sdas /*}*/ 1353219422Sdas#else 1354219422Sdas (const char *fmt, ...) 1355219422Sdas{ 1356219422Sdas va_list ap; 1357219422Sdas int rv; 1358219422Sdas Finfo f; 1359219422Sdas char buf[Bsize]; 1360219422Sdas 1361219422Sdas va_start(ap, fmt); 1362219422Sdas#endif 1363219422Sdas f.u.cf = stdout; 1364219422Sdas f.ob0 = buf; 1365219422Sdas f.obe1 = buf + Bsize - 1; 1366219422Sdas#ifdef _windows_ 1367219422Sdas if (fileno(stdout) == stdout_fileno_ASL) { 1368219422Sdas rv = x_sprintf(f.obe1, Wput, &f, fmt, ap); 1369219422Sdas mwrite(buf, f.lastlen); 1370219422Sdas } 1371219422Sdas else 1372219422Sdas#endif 1373219422Sdas#ifdef PF_BUF 1374219422Sdas if (stdout == stderr_ASL) { 1375219422Sdas rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1376219422Sdas pf_put(buf, f.lastlen); 1377219422Sdas } 1378219422Sdas else 1379219422Sdas#endif 1380219422Sdas { 1381219422Sdas rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1382219422Sdas fputs(buf, stdout); 1383219422Sdas } 1384219422Sdas va_end(ap); 1385219422Sdas return rv; 1386219422Sdas } 1387219422Sdas 1388219422Sdas static char * 1389219422SdasSput 1390219422Sdas#ifdef KR_headers 1391219422Sdas (f, rvp) Finfo *f; int *rvp; 1392219422Sdas#else 1393219422Sdas (Finfo *f, int *rvp) 1394219422Sdas#endif 1395219422Sdas{ 1396219422Sdas if (Printf("\nBUG! Sput called!\n", f, rvp)) 1397219422Sdas /* pass vp, rvp and return 0 to shut diagnostics off */ 1398219422Sdas exit(250); 1399219422Sdas return 0; 1400219422Sdas } 1401219422Sdas 1402219422Sdas int 1403219422SdasSprintf 1404219422Sdas#ifdef KR_headers 1405219422Sdas (va_alist) 1406219422Sdas va_dcl 1407219422Sdas{ 1408219422Sdas char *s, *fmt; 1409219422Sdas va_list ap; 1410219422Sdas int rv; 1411219422Sdas Finfo f; 1412219422Sdas 1413219422Sdas va_start(ap); 1414219422Sdas s = va_arg(ap, char*); 1415219422Sdas fmt = va_arg(ap, char*); 1416219422Sdas /*}*/ 1417219422Sdas#else 1418219422Sdas (char *s, const char *fmt, ...) 1419219422Sdas{ 1420219422Sdas va_list ap; 1421219422Sdas int rv; 1422219422Sdas Finfo f; 1423219422Sdas 1424219422Sdas va_start(ap, fmt); 1425219422Sdas#endif 1426219422Sdas f.ob0 = s; 1427219422Sdas rv = x_sprintf(s, Sput, &f, fmt, ap); 1428219422Sdas va_end(ap); 1429219422Sdas return rv; 1430219422Sdas } 1431219422Sdas 1432219422Sdas int 1433219422SdasFprintf 1434219422Sdas#ifdef KR_headers 1435219422Sdas (va_alist) 1436219422Sdas va_dcl 1437219422Sdas{ 1438219422Sdas FILE *F; 1439219422Sdas char *s, *fmt; 1440219422Sdas va_list ap; 1441219422Sdas int rv; 1442219422Sdas Finfo f; 1443219422Sdas char buf[Bsize]; 1444219422Sdas 1445219422Sdas va_start(ap); 1446219422Sdas F = va_arg(ap, FILE*); 1447219422Sdas fmt = va_arg(ap, char*); 1448219422Sdas /*}*/ 1449219422Sdas#else 1450219422Sdas (FILE *F, const char *fmt, ...) 1451219422Sdas{ 1452219422Sdas va_list ap; 1453219422Sdas int rv; 1454219422Sdas Finfo f; 1455219422Sdas char buf[Bsize]; 1456219422Sdas 1457219422Sdas va_start(ap, fmt); 1458219422Sdas#endif 1459219422Sdas f.u.cf = F; 1460219422Sdas f.ob0 = buf; 1461219422Sdas f.obe1 = buf + Bsize - 1; 1462219422Sdas#ifdef MESS 1463219422Sdas if (stdout_or_err(F)) { 1464219422Sdas#ifdef _windows_ 1465219422Sdas if (fileno(stdout) == stdout_fileno_ASL) { 1466219422Sdas rv = x_sprintf(f.obe1, Wput, &f, fmt, ap); 1467219422Sdas mwrite(buf, f.lastlen); 1468219422Sdas } 1469219422Sdas else 1470219422Sdas#endif 1471219422Sdas#ifdef PF_BUF 1472219422Sdas if (F == stderr_ASL) { 1473219422Sdas rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1474219422Sdas pf_put(buf, f.lastlen); 1475219422Sdas } 1476219422Sdas else 1477219422Sdas#endif 1478219422Sdas { 1479219422Sdas rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1480219422Sdas fputs(buf, F); 1481219422Sdas } 1482219422Sdas } 1483219422Sdas else 1484219422Sdas#endif /*MESS*/ 1485219422Sdas { 1486219422Sdas#ifdef PF_BUF 1487219422Sdas if (F == stderr_ASL) { 1488219422Sdas rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1489219422Sdas pf_put(buf, f.lastlen); 1490219422Sdas } 1491219422Sdas else 1492219422Sdas#endif 1493219422Sdas { 1494219422Sdas rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1495219422Sdas fputs(buf, F); 1496219422Sdas } 1497219422Sdas } 1498219422Sdas va_end(ap); 1499219422Sdas return rv; 1500219422Sdas } 1501219422Sdas 1502219422Sdas int 1503219422SdasVsprintf 1504219422Sdas#ifdef KR_headers 1505219422Sdas (s, fmt, ap) char *s, *fmt; va_list ap; 1506219422Sdas#else 1507219422Sdas (char *s, const char *fmt, va_list ap) 1508219422Sdas#endif 1509219422Sdas{ 1510219422Sdas Finfo f; 1511219422Sdas return x_sprintf(f.ob0 = s, Sput, &f, fmt, ap); 1512219422Sdas } 1513219422Sdas 1514219422Sdas int 1515219422SdasVfprintf 1516219422Sdas#ifdef KR_headers 1517219422Sdas (F, fmt, ap) FILE *F; char *fmt; va_list ap; 1518219422Sdas#else 1519219422Sdas (FILE *F, const char *fmt, va_list ap) 1520219422Sdas#endif 1521219422Sdas{ 1522219422Sdas char buf[Bsize]; 1523219422Sdas int rv; 1524219422Sdas Finfo f; 1525219422Sdas 1526219422Sdas f.u.cf = F; 1527219422Sdas f.ob0 = buf; 1528219422Sdas f.obe1 = buf + Bsize - 1; 1529219422Sdas#ifdef MESS 1530219422Sdas if (stdout_or_err(F)) { 1531219422Sdas#ifdef _windows_ 1532219422Sdas if (fileno(stdout) == stdout_fileno_ASL) { 1533219422Sdas rv = x_sprintf(f.obe1, Wput, &f, fmt, ap); 1534219422Sdas mwrite(buf, f.lastlen); 1535219422Sdas } 1536219422Sdas else 1537219422Sdas#endif 1538219422Sdas#ifdef PF_BUF 1539219422Sdas if (F == stderr_ASL) { 1540219422Sdas rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1541219422Sdas pf_put(buf, f.lastlen); 1542219422Sdas } 1543219422Sdas else 1544219422Sdas#endif 1545219422Sdas { 1546219422Sdas rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1547219422Sdas fputs(buf, F); 1548219422Sdas } 1549219422Sdas } 1550219422Sdas else 1551219422Sdas#endif /*MESS*/ 1552219422Sdas { 1553219422Sdas#ifdef PF_BUF 1554219422Sdas if (F == stderr_ASL) { 1555219422Sdas rv = x_sprintf(f.obe1, pfput, &f, fmt, ap); 1556219422Sdas pf_put(buf, f.lastlen); 1557219422Sdas } 1558219422Sdas else 1559219422Sdas#endif 1560219422Sdas { 1561219422Sdas rv = x_sprintf(f.obe1, Fput, &f, fmt, ap); 1562219422Sdas fputs(buf, F); 1563219422Sdas } 1564219422Sdas } 1565219422Sdas va_end(ap); 1566219422Sdas return rv; 1567219422Sdas } 1568219422Sdas 1569219422Sdas void 1570219422SdasPerror 1571219422Sdas#ifdef KR_headers 1572219422Sdas (s) char *s; 1573219422Sdas#else 1574219422Sdas (const char *s) 1575219422Sdas#endif 1576219422Sdas{ 1577219422Sdas if (s && *s) 1578219422Sdas Fprintf(Stderr, "%s: ", s); 1579219422Sdas Fprintf(Stderr, "%s\n", strerror(errno)); 1580219422Sdas } 1581219422Sdas 1582219422Sdas static char * 1583219422SdasSnput 1584219422Sdas#ifdef KR_headers 1585219422Sdas (f, rvp) Finfo *f; int *rvp; 1586219422Sdas#else 1587219422Sdas (Finfo *f, int *rvp) 1588219422Sdas#endif 1589219422Sdas{ 1590219422Sdas char *s, *s0; 1591219422Sdas size_t L; 1592219422Sdas 1593219422Sdas *rvp += Bsize; 1594219422Sdas s0 = f->ob0; 1595219422Sdas s = f->u.sf; 1596219422Sdas if ((L = f->obe1 - s) > Bsize) { 1597219422Sdas L = Bsize; 1598219422Sdas goto copy; 1599219422Sdas } 1600219422Sdas if (L > 0) { 1601219422Sdas copy: 1602219422Sdas memcpy(s, s0, L); 1603219422Sdas f->u.sf = s + L; 1604219422Sdas } 1605219422Sdas return s0; 1606219422Sdas } 1607219422Sdas 1608219422Sdas int 1609219422SdasVsnprintf 1610219422Sdas#ifdef KR_headers 1611219422Sdas (s, n, fmt, ap) char *s; size_t n; char *fmt; va_list ap; 1612219422Sdas#else 1613219422Sdas (char *s, size_t n, const char *fmt, va_list ap) 1614219422Sdas#endif 1615219422Sdas{ 1616219422Sdas Finfo f; 1617219422Sdas char buf[Bsize]; 1618219422Sdas int L, rv; 1619219422Sdas 1620219422Sdas if (n <= 0 || !s) { 1621219422Sdas n = 1; 1622219422Sdas s = buf; 1623219422Sdas } 1624219422Sdas f.u.sf = s; 1625219422Sdas f.ob0 = buf; 1626219422Sdas f.obe1 = s + n - 1; 1627219422Sdas rv = x_sprintf(buf + Bsize, Snput, &f, fmt, ap); 1628219422Sdas if (f.lastlen > (L = f.obe1 - f.u.sf)) 1629219422Sdas f.lastlen = L; 1630219422Sdas if (f.lastlen > 0) { 1631219422Sdas memcpy(f.u.sf, buf, f.lastlen); 1632219422Sdas f.u.sf += f.lastlen; 1633219422Sdas } 1634219422Sdas *f.u.sf = 0; 1635219422Sdas return rv; 1636219422Sdas } 1637219422Sdas int 1638219422SdasSnprintf 1639219422Sdas#ifdef KR_headers 1640219422Sdas (va_alist) 1641219422Sdas va_dcl 1642219422Sdas{ 1643219422Sdas char *s, *fmt; 1644219422Sdas int rv; 1645219422Sdas size_t n; 1646219422Sdas va_list ap; 1647219422Sdas 1648219422Sdas va_start(ap); 1649219422Sdas s = va_arg(ap, char*); 1650219422Sdas n = va_arg(ap, size_t); 1651219422Sdas fmt = va_arg(ap, char*); 1652219422Sdas /*}*/ 1653219422Sdas#else 1654219422Sdas (char *s, size_t n, const char *fmt, ...) 1655219422Sdas{ 1656219422Sdas int rv; 1657219422Sdas va_list ap; 1658219422Sdas 1659219422Sdas va_start(ap, fmt); 1660219422Sdas#endif 1661219422Sdas rv = Vsnprintf(s, n, fmt, ap); 1662219422Sdas va_end(ap); 1663219422Sdas return rv; 1664219422Sdas } 1665219422Sdas 1666219422Sdas 1667219422Sdas#ifdef __cplusplus 1668219422Sdas} 1669219422Sdas#endif 1670