1670 lines
29 KiB
Plaintext
1670 lines
29 KiB
Plaintext
|
/****************************************************************
|
||
|
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
|