1242 lines
21 KiB
C
1242 lines
21 KiB
C
|
/****************************************************************
|
||
|
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,
|
||
|
* with %.0g and %.0G giving the shortest decimal string
|
||
|
* that rounds to the number being converted, and with negative
|
||
|
* precisions allowed for %f.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Extracted from the AMPL solvers library module
|
||
|
* http://www.netlib.org/ampl/solvers/printf.c
|
||
|
* and modified for use in libmingwex.a.
|
||
|
*
|
||
|
* libstdc++ amd libgfortran expect an snprintf that can handle host
|
||
|
* widest float type. This one handle 80 bit long double. Printing
|
||
|
* to streams using this alternative implementation is not yet
|
||
|
* supported,
|
||
|
*
|
||
|
* Danny Smith <dannysmith@users.sourceforge.net>
|
||
|
* 2007-06-01
|
||
|
*/
|
||
|
|
||
|
|
||
|
#ifdef KR_headers
|
||
|
#include "varargs.h"
|
||
|
#else
|
||
|
#include "stddef.h"
|
||
|
#include "stdarg.h"
|
||
|
#include "stdlib.h"
|
||
|
#endif
|
||
|
|
||
|
#define VA_LIST va_list
|
||
|
|
||
|
/* #include "stdio1.h" */
|
||
|
#include "string.h"
|
||
|
#include "errno.h"
|
||
|
|
||
|
#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
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef USE_FILE_OUTPUT
|
||
|
#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
|
||
|
|
||
|
#endif /* USE_FILE_OUTPUT */
|
||
|
|
||
|
#include <math.h>
|
||
|
#include <stdint.h>
|
||
|
#include "gdtoa.h"
|
||
|
|
||
|
|
||
|
#define Snprintf __mingw_snprintf
|
||
|
#define Vsnprintf __mingw_vsnprintf
|
||
|
|
||
|
|
||
|
static char* __ldtoa (long double ld, int mode, int ndig, int *decpt,
|
||
|
int *sign, char **rve)
|
||
|
{
|
||
|
|
||
|
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
|
||
|
ULong bits[2];
|
||
|
int ex, kind;
|
||
|
int fptype = __fpclassifyl (ld);
|
||
|
union
|
||
|
{
|
||
|
unsigned short L[6];
|
||
|
long double ld;
|
||
|
} u;
|
||
|
|
||
|
u.ld = ld;
|
||
|
|
||
|
*sign = u.L[4] & 0x8000;
|
||
|
ex = u.L[4] & 0x7fff;
|
||
|
|
||
|
bits[1] = (u.L[3] << 16) | u.L[2];
|
||
|
bits[0] = (u.L[1] << 16) | u.L[0];
|
||
|
|
||
|
if (fptype & FP_NAN) /* NaN or Inf */
|
||
|
{
|
||
|
if (fptype & FP_NORMAL)
|
||
|
kind = STRTOG_Infinite;
|
||
|
else
|
||
|
kind = STRTOG_NaN;
|
||
|
}
|
||
|
else if (fptype & FP_NORMAL) /* Normal or subnormal */
|
||
|
{
|
||
|
if (fptype & FP_ZERO)
|
||
|
{
|
||
|
kind = STRTOG_Denormal;
|
||
|
ex = 1;
|
||
|
}
|
||
|
else
|
||
|
kind = STRTOG_Normal;
|
||
|
|
||
|
ex -= 0x3fff + 63;
|
||
|
}
|
||
|
else
|
||
|
kind = STRTOG_Zero;
|
||
|
|
||
|
return __gdtoa (&fpi, ex, bits, &kind, mode, ndig, decpt, rve);
|
||
|
}
|
||
|
|
||
|
#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 */
|
||
|
|
||
|
typedef struct
|
||
|
Finfo {
|
||
|
union {
|
||
|
#ifdef USE_FILE_OUTPUT
|
||
|
FILE *cf;
|
||
|
#endif
|
||
|
char *sf;
|
||
|
} u;
|
||
|
char *ob0, *obe1;
|
||
|
size_t lastlen;
|
||
|
} Finfo;
|
||
|
|
||
|
typedef char *(*Putfunc) ANSI((Finfo*, int*));
|
||
|
|
||
|
#ifdef USE_FILE_OUTPUT
|
||
|
#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) register Finfo *f; int *rvp;
|
||
|
#else
|
||
|
(register Finfo *f, int *rvp)
|
||
|
#endif
|
||
|
{
|
||
|
register 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) register Finfo *f; int *rvp;
|
||
|
#else
|
||
|
(register Finfo *f, int *rvp)
|
||
|
#endif
|
||
|
{
|
||
|
register char *ob0 = f->ob0;
|
||
|
|
||
|
*rvp += f->obe1 - ob0;
|
||
|
*f->obe1 = 0;
|
||
|
mwrite(ob0, f->obe1 - ob0);
|
||
|
return ob0;
|
||
|
}
|
||
|
#endif /*_windows_*/
|
||
|
#endif /* USE_FILE_OUTPUT */
|
||
|
|
||
|
#ifndef INT_IS_LONG
|
||
|
#if defined (__SIZEOF_LONG__) && defined (__SIZEOF_INT__) \
|
||
|
&& (__SIZEOF_LONG__) == (__SIZEOF_INT__)
|
||
|
#define INT_IS_LONG 1
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#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
|
||
|
{
|
||
|
char *digits, *ob0, *outbuf, *s, *s0, *se;
|
||
|
Const char *fmt0;
|
||
|
char buf[32];
|
||
|
long long i = 0;
|
||
|
unsigned long long j;
|
||
|
unsigned long long u = 0;
|
||
|
|
||
|
double x;
|
||
|
long double xx;
|
||
|
int flag_ld = 0;
|
||
|
int alt, base, c, decpt, dot, conv, i1, lead0, left,
|
||
|
prec, prec1, psign, rv, sgn, sign, width;
|
||
|
enum {
|
||
|
LEN_I,
|
||
|
LEN_L,
|
||
|
LEN_S,
|
||
|
LEN_LL
|
||
|
} len;
|
||
|
long long Ltmp;
|
||
|
intptr_t ip;
|
||
|
short sh;
|
||
|
long k;
|
||
|
unsigned short us;
|
||
|
unsigned long ui;
|
||
|
static char hex[] = "0123456789abcdef";
|
||
|
static char Hex[] = "0123456789ABCDEF";
|
||
|
|
||
|
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=prec=psign=sign=width=0;
|
||
|
len = LEN_I;
|
||
|
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 = LEN_S;
|
||
|
goto fmtloop;
|
||
|
#ifndef NO_MSVC_EXTENSIONS
|
||
|
case 'I':
|
||
|
if (fmt[0] == '3' && fmt[1] == '2')
|
||
|
{
|
||
|
fmt += 2;
|
||
|
len = LEN_L;
|
||
|
}
|
||
|
else if (fmt[0] == '6' && fmt[1] == '4')
|
||
|
{
|
||
|
fmt += 2;
|
||
|
len = LEN_LL;
|
||
|
}
|
||
|
else
|
||
|
len = sizeof (intptr_t) == sizeof (long long)
|
||
|
? LEN_LL : LEN_L;
|
||
|
goto fmtloop;
|
||
|
#endif
|
||
|
case 'l':
|
||
|
if (fmt[0] == 'l')
|
||
|
{
|
||
|
fmt++;
|
||
|
len = LEN_LL;
|
||
|
}
|
||
|
else
|
||
|
len = LEN_LL;
|
||
|
goto fmtloop;
|
||
|
case 'L':
|
||
|
flag_ld++;
|
||
|
goto fmtloop;
|
||
|
case '.':
|
||
|
dot = 1;
|
||
|
lead0 = 0;
|
||
|
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':
|
||
|
/* %lc (for wctomb conversion) is not implemented. */
|
||
|
c = va_arg(ap, int);
|
||
|
put(c)
|
||
|
continue;
|
||
|
case '%':
|
||
|
put(conv)
|
||
|
continue;
|
||
|
case 'u':
|
||
|
switch(len) {
|
||
|
case LEN_I:
|
||
|
#if !INT_IS_LONG
|
||
|
ui = va_arg(ap, int);
|
||
|
i = ui;
|
||
|
break;
|
||
|
#endif
|
||
|
case LEN_L:
|
||
|
ui = va_arg(ap, long);
|
||
|
i = ui;
|
||
|
break;
|
||
|
case LEN_S:
|
||
|
us = va_arg(ap, long);
|
||
|
i = us;
|
||
|
break;
|
||
|
case LEN_LL:
|
||
|
i = va_arg(ap, long long);
|
||
|
}
|
||
|
sign = 0;
|
||
|
goto have_i;
|
||
|
case 'i':
|
||
|
case 'd':
|
||
|
switch(len) {
|
||
|
case LEN_I:
|
||
|
#if !INT_IS_LONG
|
||
|
k = va_arg(ap, int);
|
||
|
i = k;
|
||
|
break;
|
||
|
#endif
|
||
|
case LEN_L:
|
||
|
k = va_arg(ap, long);
|
||
|
i = k;
|
||
|
break;
|
||
|
case LEN_S:
|
||
|
sh = va_arg(ap, long);
|
||
|
i = sh;
|
||
|
break;
|
||
|
case LEN_LL:
|
||
|
i = va_arg(ap, long long);
|
||
|
|
||
|
}
|
||
|
if (i < 0) {
|
||
|
sign = '-';
|
||
|
i = -i;
|
||
|
}
|
||
|
have_i:
|
||
|
base = 10;
|
||
|
u = i;
|
||
|
digits = hex;
|
||
|
baseloop:
|
||
|
s = buf;
|
||
|
if (!u)
|
||
|
alt = 0;
|
||
|
do {
|
||
|
j = ULDIV(u, base);
|
||
|
*s++ = digits[u - base * j];
|
||
|
}
|
||
|
while((u = 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, intptr_t);
|
||
|
if (!ip)
|
||
|
ip = (intptr_t) &Ltmp;
|
||
|
c = outbuf - ob0 + rv;
|
||
|
switch(len) {
|
||
|
case LEN_I:
|
||
|
#if !INT_IS_LONG
|
||
|
*(int*)ip = c;
|
||
|
break;
|
||
|
#endif
|
||
|
case LEN_L:
|
||
|
*(long*)ip = c;
|
||
|
break;
|
||
|
case LEN_S:
|
||
|
*(short*)ip = c;
|
||
|
case LEN_LL:
|
||
|
*(long long*) ip = c;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case 'p':
|
||
|
alt = 1;
|
||
|
len = sizeof (intptr_t) == sizeof (long long)
|
||
|
? LEN_LL : LEN_L;
|
||
|
/* 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 LEN_I:
|
||
|
#if !INT_IS_LONG
|
||
|
ui = va_arg(ap, int);
|
||
|
u = ui;
|
||
|
break;
|
||
|
#endif
|
||
|
case LEN_L:
|
||
|
ui = va_arg(ap, long);
|
||
|
u = ui;
|
||
|
break;
|
||
|
case LEN_S:
|
||
|
us = va_arg(ap, long);
|
||
|
u = us;
|
||
|
break;
|
||
|
case LEN_LL:
|
||
|
u = va_arg(ap, long long);
|
||
|
}
|
||
|
if (!u)
|
||
|
sign = alt = 0;
|
||
|
goto baseloop;
|
||
|
case 'o':
|
||
|
base = 8;
|
||
|
digits = hex;
|
||
|
goto get_u;
|
||
|
case 's':
|
||
|
/* %ls (for wctombs conversion) is not implemented. */
|
||
|
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;
|
||
|
if (flag_ld)
|
||
|
xx = va_arg(ap, long double);
|
||
|
else
|
||
|
{
|
||
|
x = va_arg(ap, double);
|
||
|
xx = x;
|
||
|
}
|
||
|
|
||
|
s = s0 = __ldtoa(xx, 3, prec, &decpt, &sgn, &se);
|
||
|
if (decpt == -32768) {
|
||
|
fmt9999:
|
||
|
dot = prec = alt = 0;
|
||
|
if (*s == 'N' || *s == 'I')
|
||
|
goto have_s;
|
||
|
decpt = strlen(s);
|
||
|
}
|
||
|
f_fmt:
|
||
|
if (sgn && (xx||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(' ')
|
||
|
__freedtoa(s0);
|
||
|
continue;
|
||
|
case 'G':
|
||
|
case 'g':
|
||
|
if (!dot)
|
||
|
prec = 6;
|
||
|
if (flag_ld)
|
||
|
xx = va_arg(ap, long double);
|
||
|
else
|
||
|
{
|
||
|
x = va_arg(ap, double);
|
||
|
xx = x;
|
||
|
}
|
||
|
if (prec < 0)
|
||
|
prec = 0;
|
||
|
s = s0 = __ldtoa(xx, prec ? 2 : 0, prec, &decpt,
|
||
|
&sgn, &se);
|
||
|
if (decpt == -32768)
|
||
|
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 (flag_ld)
|
||
|
xx = va_arg(ap, long double);
|
||
|
else
|
||
|
{
|
||
|
x = va_arg(ap, double);
|
||
|
xx = x;
|
||
|
}
|
||
|
if (prec < 0)
|
||
|
prec = 0;
|
||
|
s = s0 = __ldtoa(xx, prec ? 2 : 0, prec + 1, &decpt,
|
||
|
&sgn, &se);
|
||
|
if (decpt == -32768)
|
||
|
goto fmt9999;
|
||
|
e_fmt:
|
||
|
if (sgn && (xx||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;
|
||
|
default:
|
||
|
put('%')
|
||
|
while(fmt0 < fmt)
|
||
|
put(*fmt0++)
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
done:
|
||
|
*outbuf = 0;
|
||
|
return (f->lastlen = outbuf - ob0) + rv;
|
||
|
}
|
||
|
|
||
|
#define Bsize 256
|
||
|
#ifdef USE_FILE_OUTPUT
|
||
|
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 /* PF_BUF */
|
||
|
{
|
||
|
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));
|
||
|
}
|
||
|
#endif /* USE_FILE_OUTPUT */
|
||
|
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|
||
|
#if (EXPORT_WEAK_SNPRINTF_ALIAS)
|
||
|
int __cdecl snprintf(char*, size_t, const char* , ...) __attribute__ ((weak, alias ("__mingw_snprintf")));
|
||
|
int __cdecl vsnprintf (char*, size_t n, const char*, __gnuc_va_list) __attribute__ ((weak, alias ("__mingw_vsnprintf")));
|
||
|
#endif
|
||
|
|