aboutsummaryrefslogtreecommitdiff
path: root/contrib/gdtoa/printf.c0
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gdtoa/printf.c0')
-rw-r--r--contrib/gdtoa/printf.c01669
1 files changed, 1669 insertions, 0 deletions
diff --git a/contrib/gdtoa/printf.c0 b/contrib/gdtoa/printf.c0
new file mode 100644
index 000000000000..c33bcc1a4f70
--- /dev/null
+++ b/contrib/gdtoa/printf.c0
@@ -0,0 +1,1669 @@
+/****************************************************************
+Copyright (C) 1997, 1999, 2001 Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+****************************************************************/
+
+/* This implements most of ANSI C's printf, fprintf, and sprintf,
+ * omitting L, with %.0g and %.0G giving the shortest decimal string
+ * that rounds to the number being converted, and with negative
+ * precisions allowed for %f.
+ */
+
+#ifdef KR_headers
+#include "varargs.h"
+#else
+#include "stddef.h"
+#include "stdarg.h"
+#include "stdlib.h"
+#endif
+
+#ifdef Use_GDTOA_for_i386_long_double /*{{*/
+#include "gdtoa.h"
+#else /*}{*/
+#ifndef NO_PRINTF_A_FMT /*{*/
+#include "gdtoa.h"
+#endif /*}*/
+#endif /*}}*/
+
+#ifdef __i386
+#define NO_GDTOA_i386_Quad
+#endif
+
+#ifdef Use_GDTOA_for_i386_long_double /*{*/
+#ifndef NO_GDTOA_i386_Quad /*{*/
+#define GDTOA_both
+#define Use_GDTOA_Qtype
+#ifdef __ICC__ /* or __INTEL_COMPILER__ or __INTEL_COMPILER ?? */
+#define GDTOA_Qtype _Quad
+#else
+#define GDTOA_Qtype __float128
+#endif
+#endif /*} NO_GDTOA_i386_Quad */
+#endif /*} Use_GDTOA_for_i386_long_double */
+
+#ifdef Use_GDTOA_Qtype /*{*/
+#ifndef GDTOA_H_INCLUDED
+#include "gdtoa.h"
+#endif
+#ifndef GDTOA_Qtype
+#define GDTOA_Qtype long double
+#endif
+#endif /*}*/
+
+#ifndef GDTOA_H_INCLUDED /*{*/
+
+ enum { /* return values from strtodg */
+ STRTOG_Zero = 0,
+ STRTOG_Normal = 1,
+ STRTOG_Denormal = 2,
+ STRTOG_Infinite = 3,
+ STRTOG_NaN = 4,
+ STRTOG_NaNbits = 5,
+ STRTOG_NoNumber = 6,
+ STRTOG_Retmask = 7};
+
+ typedef struct
+FPI {
+ int nbits;
+ int emin;
+ int emax;
+ int rounding;
+ int sudden_underflow;
+ } FPI;
+
+enum { /* FPI.rounding values: same as FLT_ROUNDS */
+ FPI_Round_zero = 0,
+ FPI_Round_near = 1,
+ FPI_Round_up = 2,
+ FPI_Round_down = 3
+ };
+#endif /*}*/
+
+#ifdef NO_PRINTF_A_FMT /*{{*/
+#define WANT_A_FMT(x) /*nothing*/
+#else /*}{*/
+#define WANT_A_FMT(x) x
+#endif /*}}*/
+
+#include "stdio1.h"
+#include "string.h"
+#include "errno.h"
+
+ typedef struct
+Finfo {
+ union { FILE *cf; char *sf; } u;
+ char *ob0, *obe1;
+ size_t lastlen;
+ } Finfo;
+
+ typedef char *(*pgdtoa) ANSI((FPI*, int be, ULong *bits, int *kind, int mode, int ndigits, int *decpt, char **rve));
+
+ typedef struct
+FPBits {
+ ULong bits[4]; /* sufficient for quad; modify if considering wider types */
+ FPI *fpi;
+ pgdtoa gdtoa;
+ int sign;
+ int ex; /* exponent */
+ int kind;
+ } FPBits;
+
+ typedef union U
+{
+ double d;
+ long double ld;
+#ifdef GDTOA_Qtype
+ GDTOA_Qtype Qd;
+#endif
+ unsigned int ui[4];
+ unsigned short us[5];
+ } U;
+
+ typedef char *(*Putfunc) ANSI((Finfo*, int*));
+ typedef void (*Fpbits) ANSI((U*, FPBits*));
+
+/* Would have preferred typedef void (*Fpbits)(va_list*, FPBits*)
+ * but gcc is buggy in this regard.
+ */
+
+#ifdef Use_GDTOA_for_i386_long_double /*{*/
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#define _4 4
+#endif
+#ifdef IEEE_8087
+#define _0 4
+#define _1 3
+#define _2 2
+#define _3 1
+#define _4 0
+#endif
+
+ static void
+xfpbits(U *u, FPBits *b)
+{
+ ULong *bits;
+ int ex, i;
+ static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
+
+ b->fpi = &fpi0;
+ b->gdtoa = gdtoa;
+ b->sign = u->us[_0] & 0x8000;
+ bits = b->bits;
+ bits[1] = (u->us[_1] << 16) | u->us[_2];
+ bits[0] = (u->us[_3] << 16) | u->us[_4];
+ if ( (ex = u->us[_0] & 0x7fff) !=0) {
+ i = STRTOG_Normal;
+ if (ex == 0x7fff)
+ /* Infinity or NaN */
+ i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite;
+ }
+ else if (bits[0] | bits[1]) {
+ i = STRTOG_Denormal;
+ ex = 1;
+ }
+ else
+ i = STRTOG_Zero;
+ b->kind = i;
+ b->ex = ex - (0x3fff + 63);
+ }
+
+#undef _0
+#undef _1
+#undef _2
+#undef _3
+#undef _4
+#define GDTOA_LD_fpbits xfpbits
+#endif /*} Use_GDTOA_for_i386_long_double */
+
+#ifdef Use_GDTOA_Qtype /*{*/
+#include "gdtoa.h"
+#ifndef GDTOA_Qtype
+#define GDTOA_Qtype long double
+#endif
+#ifdef GDTOA_LD_fpbits
+#define GDTOA_Q_fpbits Qfpbits
+#else
+#define GDTOA_LD_fpbits Qfpbits
+#endif
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#endif
+#ifdef IEEE_8087
+#define _0 3
+#define _1 2
+#define _2 1
+#define _3 0
+#endif
+
+ static void
+Qfpbits(U *u, FPBits *b)
+{
+ ULong *bits;
+ int ex, i;
+ static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 };
+
+ b->fpi = &fpi0;
+ b->gdtoa = gdtoa;
+ b->sign = u->ui[_0] & 0x80000000L;
+ bits = b->bits;
+ bits[3] = u->ui[_0] & 0xffff;
+ bits[2] = u->ui[_1];
+ bits[1] = u->ui[_2];
+ bits[0] = u->ui[_3];
+ if ( (ex = (u->ui[_0] & 0x7fff0000L) >> 16) !=0) {
+ if (ex == 0x7fff) {
+ /* Infinity or NaN */
+ i = bits[0] | bits[1] | bits[2] | bits[3]
+ ? STRTOG_NaN : STRTOG_Infinite;
+ }
+ else {
+ i = STRTOG_Normal;
+ bits[3] |= 0x10000;
+ }
+ }
+ else if (bits[0] | bits[1] | bits[2] | bits[3]) {
+ i = STRTOG_Denormal;
+ ex = 1;
+ }
+ else
+ i = STRTOG_Zero;
+ b->kind = i;
+ b->ex = ex - (0x3fff + 112);
+ }
+
+#undef _0
+#undef _1
+#undef _2
+#undef _3
+#endif /*} GDTOA_Qtype */
+
+#ifdef KR_headers
+#define Const /* const */
+#define Voidptr char*
+#ifndef size_t__
+#define size_t int
+#define size_t__
+#endif
+
+#else
+
+#define Const const
+#define Voidptr void*
+
+#endif
+
+#undef MESS
+#ifndef Stderr
+#define Stderr stderr
+#endif
+
+#ifdef _windows_
+#undef PF_BUF
+#define MESS
+#include "mux0.h"
+#define stdout_or_err(f) (f == stdout)
+#else
+#define stdout_or_err(f) (f == Stderr || f == stdout)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern char *dtoa ANSI((double, int, int, int*, int*, char **));
+ extern void freedtoa ANSI((char*));
+
+
+
+#ifdef USE_ULDIV
+/* This is for avoiding 64-bit divisions on the DEC Alpha, since */
+/* they are not portable among variants of OSF1 (DEC's Unix). */
+
+#define ULDIV(a,b) uldiv_ASL(a,(unsigned long)(b))
+
+#ifndef LLBITS
+#define LLBITS 6
+#endif
+#ifndef ULONG
+#define ULONG unsigned long
+#endif
+
+ static int
+klog(ULONG x)
+{
+ int k, rv = 0;
+
+ if (x > 1L)
+ for(k = 1 << LLBITS-1;;) {
+ if (x >= (1L << k)) {
+ rv |= k;
+ x >>= k;
+ }
+ if (!(k >>= 1))
+ break;
+ }
+ return rv;
+ }
+
+ ULONG
+uldiv_ASL(ULONG a, ULONG b)
+{
+ int ka;
+ ULONG c, k;
+ static ULONG b0;
+ static int kb;
+
+ if (a < b)
+ return 0;
+ if (b != b0) {
+ b0 = b;
+ kb = klog(b);
+ }
+ k = 1;
+ if ((ka = klog(a) - kb) > 0) {
+ k <<= ka;
+ b <<= ka;
+ }
+ c = 0;
+ for(;;) {
+ if (a >= b) {
+ a -= b;
+ c |= k;
+ }
+ if (!(k >>= 1))
+ break;
+ a <<= 1;
+ }
+ return c;
+ }
+
+#else
+#define ULDIV(a,b) a / b
+#endif /* USE_ULDIV */
+
+#ifdef PF_BUF
+FILE *stderr_ASL = (FILE*)&stderr_ASL;
+void (*pfbuf_print_ASL) ANSI((char*));
+char *pfbuf_ASL;
+static char *pfbuf_next;
+static size_t pfbuf_len;
+extern Char *mymalloc_ASL ANSI((size_t));
+extern Char *myralloc_ASL ANSI((void *, size_t));
+
+#undef fflush
+#ifdef old_fflush_ASL
+#define fflush old_fflush_ASL
+#endif
+
+ void
+fflush_ASL(FILE *f)
+{
+ if (f == stderr_ASL) {
+ if (pfbuf_ASL && pfbuf_print_ASL) {
+ (*pfbuf_print_ASL)(pfbuf_ASL);
+ free(pfbuf_ASL);
+ pfbuf_ASL = 0;
+ }
+ }
+ else
+ fflush(f);
+ }
+
+ static void
+pf_put(char *buf, int len)
+{
+ size_t x, y;
+ if (!pfbuf_ASL) {
+ x = len + 256;
+ if (x < 512)
+ x = 512;
+ pfbuf_ASL = pfbuf_next = (char*)mymalloc_ASL(pfbuf_len = x);
+ }
+ else if ((y = (pfbuf_next - pfbuf_ASL) + len) >= pfbuf_len) {
+ x = pfbuf_len;
+ while((x <<= 1) <= y);
+ y = pfbuf_next - pfbuf_ASL;
+ pfbuf_ASL = (char*)myralloc_ASL(pfbuf_ASL, x);
+ pfbuf_next = pfbuf_ASL + y;
+ pfbuf_len = x;
+ }
+ memcpy(pfbuf_next, buf, len);
+ pfbuf_next += len;
+ *pfbuf_next = 0;
+ }
+
+ static char *
+pfput(Finfo *f, int *rvp)
+{
+ int n;
+ char *ob0 = f->ob0;
+ *rvp += n = (int)(f->obe1 - ob0);
+ pf_put(ob0, n);
+ return ob0;
+ }
+#endif /* PF_BUF */
+
+ static char *
+Fput
+#ifdef KR_headers
+ (f, rvp) Finfo *f; int *rvp;
+#else
+ (Finfo *f, int *rvp)
+#endif
+{
+ char *ob0 = f->ob0;
+
+ *rvp += f->obe1 - ob0;
+ *f->obe1 = 0;
+ fputs(ob0, f->u.cf);
+ return ob0;
+ }
+
+
+#ifdef _windows_
+int stdout_fileno_ASL = 1;
+
+ static char *
+Wput
+#ifdef KR_headers
+ (f, rvp) Finfo *f; int *rvp;
+#else
+ (Finfo *f, int *rvp)
+#endif
+{
+ char *ob0 = f->ob0;
+
+ *rvp += f->obe1 - ob0;
+ *f->obe1 = 0;
+ mwrite(ob0, f->obe1 - ob0);
+ return ob0;
+ }
+#endif /*_windows_*/
+
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#endif
+#ifdef IEEE_8087
+#define _0 1
+#define _1 0
+#endif
+
+ static void
+dfpbits(U *u, FPBits *b)
+{
+ ULong *bits;
+ int ex, i;
+ static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
+
+ b->fpi = &fpi0;
+ b->gdtoa = gdtoa;
+ b->sign = u->ui[_0] & 0x80000000L;
+ bits = b->bits;
+ bits[1] = u->ui[_0] & 0xfffff;
+ bits[0] = u->ui[_1];
+ if ( (ex = (u->ui[_0] & 0x7ff00000L) >> 20) !=0) {
+ if (ex == 0x7ff) {
+ /* Infinity or NaN */
+ i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite;
+ }
+ else {
+ i = STRTOG_Normal;
+ bits[1] |= 0x100000;
+ }
+ }
+ else if (bits[0] | bits[1]) {
+ i = STRTOG_Denormal;
+ ex = 1;
+ }
+ else
+ i = STRTOG_Zero;
+ b->kind = i;
+ b->ex = ex - (0x3ff + 52);
+ }
+
+#undef _0
+#undef _1
+
+#ifdef Honor_FLT_ROUNDS /*{{*/
+#ifdef Trust_FLT_ROUNDS /*{{*/
+#define RoundCheck if (Rounding == -1) Rounding = Flt_Rounds; if (Rounding != 1){\
+ fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;}
+#else /*}{*/
+#define RoundCheck if (Rounding == -1) { Rounding = 1; switch((fegetround()) {\
+ case FE_TOWARDZERO: Rounding = 0; break;\
+ case FE_UPWARD: Rounding = 2; break;\
+ case FE_DOWNWARD: Rounding = 3; }}\
+ if (Rounding != 1){\
+ fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;}
+#endif /*}}*/
+#else /*}{*/
+#define RoundCheck /*nothing*/
+#endif /*}}*/
+
+#ifndef NO_PRINTF_A_FMT /*{*/
+ static int
+fpiprec(FPBits *b) /* return number of hex digits minus 1, or 0 for zero */
+{
+ FPI *fpi;
+ ULong *bits;
+ int i, j, k, m;
+
+ if (b->kind == STRTOG_Zero)
+ return b->ex = 0;
+ fpi = b->fpi;
+ bits = b->bits;
+ for(k = (fpi->nbits - 1) >> 2; k > 0; --k)
+ if ((bits[k >> 3] >> 4*(k & 7)) & 0xf) {
+ m = k >> 3;
+ for(i = 0; i <= m; ++i)
+ if (bits[i]) {
+ if (i > 0) {
+ k -= 8*i;
+ b->ex += 32*i;
+ for(j = i; j <= m; ++j)
+ bits[j-i] = bits[j];
+ }
+ break;
+ }
+ for(i = 0; i < 28 && !((bits[0] >> i) & 0xf); i += 4);
+ if (i) {
+ b->ex += i;
+ m = k >> 3;
+ k -= (i >> 2);
+ for(j = 0;;++j) {
+ bits[j] >>= i;
+ if (j == m)
+ break;
+ bits[j] |= bits[j+1] << (32 - i);
+ }
+ }
+ break;
+ }
+ return k;
+ }
+
+ static int
+bround(FPBits *b, int prec, int prec1) /* round to prec hex digits after the "." */
+{ /* prec1 = incoming precision (after ".") */
+ FPI *fpi = b->fpi;
+ ULong *bits, t;
+ int i, inc, j, k, m, n;
+#ifdef Honor_FLT_ROUNDS
+ int rounding = fpi->rounding;
+
+ if (rounding > FPI_Round_near && b->sign)
+ rounding = FPI_Round_up + FPI_Round_down - rounding;
+ if (rounding == FPI_Round_down)
+ rounding = FPI_Round_zero;
+#endif
+ m = prec1 - prec;
+ bits = b->bits;
+ inc = 0;
+#ifdef Honor_FLT_ROUNDS
+ switch(rounding) {
+ case FPI_Round_up:
+ for(i = 0; i < m; i += 8)
+ if (bits[i>>3])
+ goto inc1;
+ if ((j = i - m) > 0 && bits[(i-8)>>3] << j*4)
+ goto inc1;
+ break;
+ case FPI_Round_near:
+#endif
+ k = m - 1;
+ if ((t = bits[k >> 3] >> (j = (k&7)*4)) & 8) {
+ if (t & 7)
+ goto inc1;
+ if (j && bits[k >> 3] << (32 - j))
+ goto inc1;
+ while(k >= 8) {
+ k -= 8;
+ if (bits[k>>3]) {
+ inc1:
+ inc = 1;
+ goto haveinc;
+ }
+ }
+ }
+#ifdef Honor_FLT_ROUNDS
+ }
+#endif
+ haveinc:
+ b->ex += m*4;
+ i = m >> 3;
+ k = prec1 >> 3;
+ j = i;
+ if ((n = 4*(m & 7)))
+ for(;; ++j) {
+ bits[j-i] = bits[j] >> n;
+ if (j == k)
+ break;
+ bits[j-i] |= bits[j+1] << (32-n);
+ }
+ else
+ for(;; ++j) {
+ bits[j-i] = bits[j];
+ if (j == k)
+ break;
+ }
+ k = prec >> 3;
+ if (inc) {
+ for(j = 0; !(++bits[j] & 0xffffffff); ++j);
+ if (j > k) {
+ onebit:
+ bits[0] = 1;
+ b->ex += 4*prec;
+ return 1;
+ }
+ if ((j = prec & 7) < 7 && bits[k] >> (j+1)*4)
+ goto onebit;
+ }
+ for(i = 0; !(bits[i >> 3] & (0xf << 4*(i&7))); ++i);
+ if (i) {
+ b->ex += 4*i;
+ prec -= i;
+ j = i >> 3;
+ i &= 7;
+ i *= 4;
+ for(m = j; ; ++m) {
+ bits[m-j] = bits[m] >> i;
+ if (m == k)
+ break;
+ bits[m-j] |= bits[m+1] << (32 - i);
+ }
+ }
+ return prec;
+ }
+#endif /*}NO_PRINTF_A_FMT*/
+
+#define put(x) { *outbuf++ = x; if (outbuf == obe) outbuf = (*fput)(f,&rv); }
+
+ static int
+x_sprintf
+#ifdef KR_headers
+ (obe, fput, f, fmt, ap)
+ char *obe, *fmt; Finfo *f; Putfunc fput; va_list ap;
+#else
+ (char *obe, Putfunc fput, Finfo *f, const char *fmt, va_list ap)
+#endif
+{
+ FPBits fpb;
+ Fpbits fpbits;
+ U u;
+ char *digits, *ob0, *outbuf, *s, *s0, *se;
+ Const char *fmt0;
+ char buf[32];
+ long i;
+ unsigned long j, ul;
+ double x;
+ int alt, base, c, decpt, dot, conv, i1, k, lead0, left,
+ len, prec, prec1, psign, rv, sign, width;
+ long Ltmp, *ip;
+ short sh;
+ unsigned short us;
+ unsigned int ui;
+#ifdef Honor_FLT_ROUNDS
+ FPI fpi1;
+ int Rounding = -1;
+#endif
+#ifndef NO_PRINTF_A_FMT /*{*/
+ int bex, bw;
+#endif /*} NO_PRINTF_A_FMT */
+ static char hex[] = "0123456789abcdefpx";
+ static char Hex[] = "0123456789ABCDEFPX";
+
+ ob0 = outbuf = f->ob0;
+ rv = 0;
+ for(;;) {
+ for(;;) {
+ switch(c = *fmt++) {
+ case 0:
+ goto done;
+ case '%':
+ break;
+ default:
+ put(c)
+ continue;
+ }
+ break;
+ }
+ alt=dot=lead0=left=len=prec=psign=sign=width=0;
+ fpbits = dfpbits;
+ fmt0 = fmt;
+ fmtloop:
+ switch(conv = *fmt++) {
+ case ' ':
+ case '+':
+ sign = conv;
+ goto fmtloop;
+ case '-':
+ if (dot)
+ psign = 1;
+ else
+ left = 1;
+ goto fmtloop;
+ case '#':
+ alt = 1;
+ goto fmtloop;
+ case '0':
+ if (!lead0 && !dot) {
+ lead0 = 1;
+ goto fmtloop;
+ }
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ k = conv - '0';
+ while((c = *fmt) >= '0' && c <= '9') {
+ k = 10*k + c - '0';
+ fmt++;
+ }
+ if (dot)
+ prec = psign ? -k : k;
+ else
+ width = k;
+ goto fmtloop;
+ case 'h':
+ len = 2;
+ goto fmtloop;
+ case 'L':
+#ifdef GDTOA_LD_fpbits /*{*/
+ fpbits = GDTOA_LD_fpbits;
+#ifdef GDTOA_Q_fpbits
+ if (*fmt == 'q') {
+ ++fmt;
+ fpbits = Qfpbits;
+ }
+#endif
+#endif /*}*/
+ goto fmtloop;
+ case 'l':
+ len = 1;
+ goto fmtloop;
+ case '.':
+ dot = 1;
+ goto fmtloop;
+ case '*':
+ k = va_arg(ap, int);
+ if (dot)
+ prec = k;
+ else {
+ if (k < 0) {
+ sign = '-';
+ k = -k;
+ }
+ width = k;
+ }
+ goto fmtloop;
+ case 'c':
+ c = va_arg(ap, int);
+ put(c)
+ continue;
+ case '%':
+ put(conv)
+ continue;
+ case 'u':
+ switch(len) {
+ case 0:
+ ui = va_arg(ap, int);
+ i = ui;
+ break;
+ case 1:
+ i = va_arg(ap, long);
+ break;
+ case 2:
+ us = va_arg(ap, int);
+ i = us;
+ }
+ sign = 0;
+ goto have_i;
+ case 'i':
+ case 'd':
+ switch(len) {
+ case 0:
+ k = va_arg(ap, int);
+ i = k;
+ break;
+ case 1:
+ i = va_arg(ap, long);
+ break;
+ case 2:
+ sh = va_arg(ap, int);
+ i = sh;
+ }
+ if (i < 0) {
+ sign = '-';
+ i = -i;
+ }
+ have_i:
+ base = 10;
+ ul = i;
+ digits = hex;
+ baseloop:
+ if (dot)
+ lead0 = 0;
+ s = buf;
+ if (!ul)
+ alt = 0;
+ do {
+ j = ULDIV(ul, base);
+ *s++ = digits[ul - base*j];
+ }
+ while((ul = j));
+ prec -= c = s - buf;
+ if (alt && conv == 'o' && prec <= 0)
+ prec = 1;
+ if ((width -= c) > 0) {
+ if (prec > 0)
+ width -= prec;
+ if (sign)
+ width--;
+ if (alt == 2)
+ width--;
+ }
+ if (left) {
+ if (alt == 2)
+ put('0') /* for 0x */
+ if (sign)
+ put(sign)
+ while(--prec >= 0)
+ put('0')
+ do put(*--s)
+ while(s > buf);
+ while(--width >= 0)
+ put(' ')
+ continue;
+ }
+ if (width > 0) {
+ if (lead0) {
+ if (alt == 2)
+ put('0')
+ if (sign)
+ put(sign)
+ while(--width >= 0)
+ put('0')
+ goto s_loop;
+ }
+ else
+ while(--width >= 0)
+ put(' ')
+ }
+ if (alt == 2)
+ put('0')
+ if (sign)
+ put(sign)
+ s_loop:
+ while(--prec >= 0)
+ put('0')
+ do put(*--s)
+ while(s > buf);
+ continue;
+ case 'n':
+ ip = va_arg(ap, long*);
+ if (!ip)
+ ip = &Ltmp;
+ c = outbuf - ob0 + rv;
+ switch(len) {
+ case 0:
+ *(int*)ip = c;
+ break;
+ case 1:
+ *ip = c;
+ break;
+ case 2:
+ *(short*)ip = c;
+ }
+ break;
+ case 'p':
+ len = alt = 1;
+ /* no break */
+ case 'x':
+ digits = hex;
+ goto more_x;
+ case 'X':
+ digits = Hex;
+ more_x:
+ if (alt) {
+ alt = 2;
+ sign = conv;
+ }
+ else
+ sign = 0;
+ base = 16;
+ get_u:
+ switch(len) {
+ case 0:
+ ui = va_arg(ap, int);
+ ul = ui;
+ break;
+ case 1:
+ ul = va_arg(ap, long);
+ break;
+ case 2:
+ us = va_arg(ap, int);
+ ul = us;
+ }
+ if (!ul)
+ sign = alt = 0;
+ goto baseloop;
+ case 'o':
+ base = 8;
+ digits = hex;
+ goto get_u;
+ case 's':
+ s0 = 0;
+ s = va_arg(ap, char*);
+ if (!s)
+ s = "<NULL>";
+ if (prec < 0)
+ prec = 0;
+ have_s:
+ if (dot) {
+ for(c = 0; c < prec; c++)
+ if (!s[c])
+ break;
+ prec = c;
+ }
+ else
+ prec = strlen(s);
+ width -= prec;
+ if (!left)
+ while(--width >= 0)
+ put(' ')
+ while(--prec >= 0)
+ put(*s++)
+ while(--width >= 0)
+ put(' ')
+ if (s0)
+ freedtoa(s0);
+ continue;
+ case 'f':
+ if (!dot)
+ prec = 6;
+#ifdef GDTOA_H_INCLUDED
+ if (fpbits == dfpbits) {
+#endif
+ x = va_arg(ap, double);
+ s = s0 = dtoa(x, 3, prec, &decpt, &fpb.sign, &se);
+#ifdef GDTOA_H_INCLUDED
+ }
+ else {
+#ifdef GDTOA_both
+ if (fpbits == GDTOA_LD_fpbits)
+ u.ld = va_arg(ap, long double);
+ else
+ u.Qd = va_arg(ap, GDTOA_Qtype);
+#else
+ u.ld = va_arg(ap, long double);
+#endif
+ fpbits(&u, &fpb);
+ RoundCheck
+ s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
+ &fpb.kind, 3, prec, &decpt, &se);
+ }
+#endif
+ if (decpt == 9999) {
+ fmt9999:
+ dot = prec = alt = 0;
+ if (*s == 'N')
+ goto have_s;
+ decpt = strlen(s);
+ }
+ f_fmt:
+ if (fpb.sign && (x||sign))
+ sign = '-';
+ if (prec > 0)
+ width -= prec;
+ if (width > 0) {
+ if (sign)
+ --width;
+ if (decpt <= 0) {
+ --width;
+ if (prec > 0)
+ --width;
+ }
+ else {
+ if (s == se)
+ decpt = 1;
+ width -= decpt;
+ if (prec > 0 || alt)
+ --width;
+ }
+ }
+ if (width > 0 && !left) {
+ if (lead0) {
+ if (sign)
+ put(sign)
+ sign = 0;
+ do put('0')
+ while(--width > 0);
+ }
+ else do put(' ')
+ while(--width > 0);
+ }
+ if (sign)
+ put(sign)
+ if (decpt <= 0) {
+ put('0')
+ if (prec > 0 || alt)
+ put('.')
+ while(decpt < 0) {
+ put('0')
+ prec--;
+ decpt++;
+ }
+ }
+ else {
+ do {
+ if ((c = *s))
+ s++;
+ else
+ c = '0';
+ put(c)
+ }
+ while(--decpt > 0);
+ if (prec > 0 || alt)
+ put('.')
+ }
+ while(--prec >= 0) {
+ if ((c = *s))
+ s++;
+ else
+ c = '0';
+ put(c)
+ }
+ while(--width >= 0)
+ put(' ')
+ if (s0)
+ freedtoa(s0);
+ continue;
+ case 'G':
+ case 'g':
+ if (!dot)
+ prec = 6;
+ if (prec < 0)
+ prec = 0;
+#ifdef GDTOA_H_INCLUDED
+ if (fpbits == dfpbits) {
+#endif
+ x = va_arg(ap, double);
+ s = s0 = dtoa(x, prec ? 2 : 0, prec, &decpt,
+ &fpb.sign, &se);
+#ifdef GDTOA_H_INCLUDED
+ }
+ else {
+#ifdef GDTOA_both
+ if (fpbits == GDTOA_LD_fpbits)
+ u.ld = va_arg(ap, long double);
+ else
+ u.Qd = va_arg(ap, GDTOA_Qtype);
+#else
+ u.ld = va_arg(ap, long double);
+#endif
+ fpbits(&u, &fpb);
+ RoundCheck
+ s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
+ &fpb.kind, prec ? 2 : 0, prec, &decpt, &se);
+ }
+#endif
+ if (decpt == 9999)
+ goto fmt9999;
+ c = se - s;
+ prec1 = prec;
+ if (!prec) {
+ prec = c;
+ prec1 = c + (s[1] || alt ? 5 : 4);
+ /* %.0g gives 10 rather than 1e1 */
+ }
+ if (decpt > -4 && decpt <= prec1) {
+ if (alt)
+ prec -= decpt;
+ else
+ prec = c - decpt;
+ if (prec < 0)
+ prec = 0;
+ goto f_fmt;
+ }
+ conv -= 2;
+ if (!alt && prec > c)
+ prec = c;
+ --prec;
+ goto e_fmt;
+ case 'e':
+ case 'E':
+ if (!dot)
+ prec = 6;
+ if (prec < 0)
+ prec = 0;
+#ifdef GDTOA_H_INCLUDED
+ if (fpbits == dfpbits) {
+#endif
+ x = va_arg(ap, double);
+ s = s0 = dtoa(x, prec ? 2 : 0, prec+1, &decpt,
+ &fpb.sign, &se);
+#ifdef GDTOA_H_INCLUDED
+ }
+ else {
+#ifdef GDTOA_both
+ if (fpbits == GDTOA_LD_fpbits)
+ u.ld = va_arg(ap, long double);
+ else
+ u.Qd = va_arg(ap, GDTOA_Qtype);
+#else
+ u.ld = va_arg(ap, long double);
+#endif
+ fpbits(&u, &fpb);
+ RoundCheck
+ s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
+ &fpb.kind, prec ? 2 : 0, prec, &decpt, &se);
+ }
+#endif
+ if (decpt == 9999)
+ goto fmt9999;
+ e_fmt:
+ if (fpb.sign && (x||sign))
+ sign = '-';
+ if ((width -= prec + 5) > 0) {
+ if (sign)
+ --width;
+ if (prec || alt)
+ --width;
+ }
+ if ((c = --decpt) < 0)
+ c = -c;
+ while(c >= 100) {
+ --width;
+ c /= 10;
+ }
+ if (width > 0 && !left) {
+ if (lead0) {
+ if (sign)
+ put(sign)
+ sign = 0;
+ do put('0')
+ while(--width > 0);
+ }
+ else do put(' ')
+ while(--width > 0);
+ }
+ if (sign)
+ put(sign)
+ put(*s++)
+ if (prec || alt)
+ put('.')
+ while(--prec >= 0) {
+ if ((c = *s))
+ s++;
+ else
+ c = '0';
+ put(c)
+ }
+ put(conv)
+ if (decpt < 0) {
+ put('-')
+ decpt = -decpt;
+ }
+ else
+ put('+')
+ for(c = 2, k = 10; 10*k <= decpt; c++, k *= 10);
+ for(;;) {
+ i1 = decpt / k;
+ put(i1 + '0')
+ if (--c <= 0)
+ break;
+ decpt -= i1*k;
+ decpt *= 10;
+ }
+ while(--width >= 0)
+ put(' ')
+ freedtoa(s0);
+ continue;
+#ifndef NO_PRINTF_A_FMT
+ case 'a':
+ digits = hex;
+ goto more_a;
+ case 'A':
+ digits = Hex;
+ more_a:
+#ifdef GDTOA_H_INCLUDED /*{{*/
+ if (fpbits == dfpbits)
+ u.d = va_arg(ap, double);
+#ifdef GDTOA_both /*{*/
+ else if (fpbits == GDTOA_LD_fpbits)
+ u.ld = va_arg(ap, long double);
+ else
+ u.Qd = va_arg(ap, GDTOA_Qtype);
+#else
+ else
+ u.ld = va_arg(ap, long double);
+#endif /*}*/
+#else /*}{*/
+ u.d = va_arg(ap, double);
+#endif /*}}*/
+ fpbits(&u, &fpb);
+ if (fpb.kind == STRTOG_Infinite) {
+ s = "Infinity";
+ s0 = 0;
+ goto fmt9999;
+ }
+ if (fpb.kind == STRTOG_NaN) {
+ s = "NaN";
+ s0 = 0;
+ goto fmt9999;
+ }
+ prec1 = fpiprec(&fpb);
+ if (dot && prec < prec1)
+ prec1 = bround(&fpb, prec, prec1);
+ bw = 1;
+ bex = fpb.ex + 4*prec1;
+ if (bex) {
+ if ((i1 = bex) < 0)
+ i1 = -i1;
+ while(i1 >= 10) {
+ ++bw;
+ i1 /= 10;
+ }
+ }
+ if (fpb.sign && (sign || fpb.kind != STRTOG_Zero))
+ sign = '-';
+ if ((width -= bw + 5) > 0) {
+ if (sign)
+ --width;
+ if (prec1 || alt)
+ --width;
+ }
+ if ((width -= prec1) > 0 && !left && !lead0) {
+ do put(' ')
+ while(--width > 0);
+ }
+ if (sign)
+ put(sign)
+ put('0')
+ put(digits[17])
+ if (lead0 && width > 0 && !left) {
+ do put('0')
+ while(--width > 0);
+ }
+ i1 = prec1 & 7;
+ k = prec1 >> 3;
+ put(digits[(fpb.bits[k] >> 4*i1) & 0xf])
+ if (prec1 > 0 || alt)
+ put('.')
+ if (prec1 > 0) {
+ prec -= prec1;
+ while(prec1 > 0) {
+ if (--i1 < 0) {
+ if (--k < 0)
+ break;
+ i1 = 7;
+ }
+ put(digits[(fpb.bits[k] >> 4*i1) & 0xf])
+ --prec1;
+ }
+ if (alt && prec > 0)
+ do put(0)
+ while(--prec > 0);
+ }
+ put(digits[16])
+ if (bex < 0) {
+ put('-')
+ bex = -bex;
+ }
+ else
+ put('+')
+ for(c = 1; 10*c <= bex; c *= 10);
+ for(;;) {
+ i1 = bex / c;
+ put('0' + i1)
+ if (!--bw)
+ break;
+ bex -= i1 * c;
+ bex *= 10;
+ }
+ while(--width >= 0)
+ put(' ')
+ continue;
+#endif /* NO_PRINTF_A_FMT */
+ default:
+ put('%')
+ while(fmt0 < fmt)
+ put(*fmt0++)
+ continue;
+ }
+ }
+ done:
+ *outbuf = 0;
+ return (f->lastlen = outbuf - ob0) + rv;
+ }
+
+#define Bsize 256
+
+ int
+Printf
+#ifdef KR_headers
+ (va_alist)
+ va_dcl
+{
+ char *fmt;
+
+ va_list ap;
+ int rv;
+ Finfo f;
+ char buf[Bsize];
+
+ va_start(ap);
+ fmt = va_arg(ap, char*);
+ /*}*/
+#else
+ (const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+ Finfo f;
+ char buf[Bsize];
+
+ va_start(ap, fmt);
+#endif
+ f.u.cf = stdout;
+ f.ob0 = buf;
+ f.obe1 = buf + Bsize - 1;
+#ifdef _windows_
+ if (fileno(stdout) == stdout_fileno_ASL) {
+ rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
+ mwrite(buf, f.lastlen);
+ }
+ else
+#endif
+#ifdef PF_BUF
+ if (stdout == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, stdout);
+ }
+ va_end(ap);
+ return rv;
+ }
+
+ static char *
+Sput
+#ifdef KR_headers
+ (f, rvp) Finfo *f; int *rvp;
+#else
+ (Finfo *f, int *rvp)
+#endif
+{
+ if (Printf("\nBUG! Sput called!\n", f, rvp))
+ /* pass vp, rvp and return 0 to shut diagnostics off */
+ exit(250);
+ return 0;
+ }
+
+ int
+Sprintf
+#ifdef KR_headers
+ (va_alist)
+ va_dcl
+{
+ char *s, *fmt;
+ va_list ap;
+ int rv;
+ Finfo f;
+
+ va_start(ap);
+ s = va_arg(ap, char*);
+ fmt = va_arg(ap, char*);
+ /*}*/
+#else
+ (char *s, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+ Finfo f;
+
+ va_start(ap, fmt);
+#endif
+ f.ob0 = s;
+ rv = x_sprintf(s, Sput, &f, fmt, ap);
+ va_end(ap);
+ return rv;
+ }
+
+ int
+Fprintf
+#ifdef KR_headers
+ (va_alist)
+ va_dcl
+{
+ FILE *F;
+ char *s, *fmt;
+ va_list ap;
+ int rv;
+ Finfo f;
+ char buf[Bsize];
+
+ va_start(ap);
+ F = va_arg(ap, FILE*);
+ fmt = va_arg(ap, char*);
+ /*}*/
+#else
+ (FILE *F, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+ Finfo f;
+ char buf[Bsize];
+
+ va_start(ap, fmt);
+#endif
+ f.u.cf = F;
+ f.ob0 = buf;
+ f.obe1 = buf + Bsize - 1;
+#ifdef MESS
+ if (stdout_or_err(F)) {
+#ifdef _windows_
+ if (fileno(stdout) == stdout_fileno_ASL) {
+ rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
+ mwrite(buf, f.lastlen);
+ }
+ else
+#endif
+#ifdef PF_BUF
+ if (F == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, F);
+ }
+ }
+ else
+#endif /*MESS*/
+ {
+#ifdef PF_BUF
+ if (F == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, F);
+ }
+ }
+ va_end(ap);
+ return rv;
+ }
+
+ int
+Vsprintf
+#ifdef KR_headers
+ (s, fmt, ap) char *s, *fmt; va_list ap;
+#else
+ (char *s, const char *fmt, va_list ap)
+#endif
+{
+ Finfo f;
+ return x_sprintf(f.ob0 = s, Sput, &f, fmt, ap);
+ }
+
+ int
+Vfprintf
+#ifdef KR_headers
+ (F, fmt, ap) FILE *F; char *fmt; va_list ap;
+#else
+ (FILE *F, const char *fmt, va_list ap)
+#endif
+{
+ char buf[Bsize];
+ int rv;
+ Finfo f;
+
+ f.u.cf = F;
+ f.ob0 = buf;
+ f.obe1 = buf + Bsize - 1;
+#ifdef MESS
+ if (stdout_or_err(F)) {
+#ifdef _windows_
+ if (fileno(stdout) == stdout_fileno_ASL) {
+ rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
+ mwrite(buf, f.lastlen);
+ }
+ else
+#endif
+#ifdef PF_BUF
+ if (F == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, F);
+ }
+ }
+ else
+#endif /*MESS*/
+ {
+#ifdef PF_BUF
+ if (F == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, F);
+ }
+ }
+ va_end(ap);
+ return rv;
+ }
+
+ void
+Perror
+#ifdef KR_headers
+ (s) char *s;
+#else
+ (const char *s)
+#endif
+{
+ if (s && *s)
+ Fprintf(Stderr, "%s: ", s);
+ Fprintf(Stderr, "%s\n", strerror(errno));
+ }
+
+ static char *
+Snput
+#ifdef KR_headers
+ (f, rvp) Finfo *f; int *rvp;
+#else
+ (Finfo *f, int *rvp)
+#endif
+{
+ char *s, *s0;
+ size_t L;
+
+ *rvp += Bsize;
+ s0 = f->ob0;
+ s = f->u.sf;
+ if ((L = f->obe1 - s) > Bsize) {
+ L = Bsize;
+ goto copy;
+ }
+ if (L > 0) {
+ copy:
+ memcpy(s, s0, L);
+ f->u.sf = s + L;
+ }
+ return s0;
+ }
+
+ int
+Vsnprintf
+#ifdef KR_headers
+ (s, n, fmt, ap) char *s; size_t n; char *fmt; va_list ap;
+#else
+ (char *s, size_t n, const char *fmt, va_list ap)
+#endif
+{
+ Finfo f;
+ char buf[Bsize];
+ int L, rv;
+
+ if (n <= 0 || !s) {
+ n = 1;
+ s = buf;
+ }
+ f.u.sf = s;
+ f.ob0 = buf;
+ f.obe1 = s + n - 1;
+ rv = x_sprintf(buf + Bsize, Snput, &f, fmt, ap);
+ if (f.lastlen > (L = f.obe1 - f.u.sf))
+ f.lastlen = L;
+ if (f.lastlen > 0) {
+ memcpy(f.u.sf, buf, f.lastlen);
+ f.u.sf += f.lastlen;
+ }
+ *f.u.sf = 0;
+ return rv;
+ }
+ int
+Snprintf
+#ifdef KR_headers
+ (va_alist)
+ va_dcl
+{
+ char *s, *fmt;
+ int rv;
+ size_t n;
+ va_list ap;
+
+ va_start(ap);
+ s = va_arg(ap, char*);
+ n = va_arg(ap, size_t);
+ fmt = va_arg(ap, char*);
+ /*}*/
+#else
+ (char *s, size_t n, const char *fmt, ...)
+{
+ int rv;
+ va_list ap;
+
+ va_start(ap, fmt);
+#endif
+ rv = Vsnprintf(s, n, fmt, ap);
+ va_end(ap);
+ return rv;
+ }
+
+
+#ifdef __cplusplus
+}
+#endif