os/ossrv/genericopenlibs/cstdlib/LSTDIO/VFPRINTF.C
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/LSTDIO/VFPRINTF.C	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,877 @@
     1.4 +/*
     1.5 +* FUNCTION
     1.6 +* <<vprintf>>, <<vfprintf>>, <<vsprintf>>---format argument list
     1.7 +* INDEX
     1.8 +* vprintf
     1.9 +* INDEX
    1.10 +* vfprintf
    1.11 +* INDEX
    1.12 +* vsprintf
    1.13 +* ANSI_SYNOPSIS
    1.14 +* #include <stdio.h>
    1.15 +* #include <stdarg.h>
    1.16 +* int vprintf(const char *<[fmt]>, va_list <[list]>);
    1.17 +* int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
    1.18 +* int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
    1.19 +* int _vprintf_r(void *<[reent]>, const char *<[fmt]>,
    1.20 +* va_list <[list]>);
    1.21 +* int _vfprintf_r(void *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
    1.22 +* va_list <[list]>);
    1.23 +* int _vsprintf_r(void *<[reent]>, char *<[str]>, const char *<[fmt]>,
    1.24 +* va_list <[list]>);
    1.25 +* TRAD_SYNOPSIS
    1.26 +* #include <stdio.h>
    1.27 +* #include <varargs.h>
    1.28 +* int vprintf( <[fmt]>, <[list]>)
    1.29 +* char *<[fmt]>;
    1.30 +* va_list <[list]>;
    1.31 +* int vfprintf(<[fp]>, <[fmt]>, <[list]>)
    1.32 +* FILE *<[fp]>;
    1.33 +* char *<[fmt]>;
    1.34 +* va_list <[list]>;
    1.35 +* int vsprintf(<[str]>, <[fmt]>, <[list]>)
    1.36 +* char *<[str]>;
    1.37 +* char *<[fmt]>;
    1.38 +* va_list <[list]>;
    1.39 +* int _vprintf_r(<[reent]>, <[fmt]>, <[list]>)
    1.40 +* char *<[reent]>;
    1.41 +* char *<[fmt]>;
    1.42 +* va_list <[list]>;
    1.43 +* int _vfprintf_r(<[reent]>, <[fp]>, <[fmt]>, <[list]>)
    1.44 +* char *<[reent]>;
    1.45 +* FILE *<[fp]>;
    1.46 +* char *<[fmt]>;
    1.47 +* va_list <[list]>;
    1.48 +* int _vsprintf_r(<[reent]>, <[str]>, <[fmt]>, <[list]>)
    1.49 +* char *<[reent]>;
    1.50 +* char *<[str]>;
    1.51 +* char *<[fmt]>;
    1.52 +* va_list <[list]>;
    1.53 +* <<vprintf>>, <<vfprintf>>, and <<vsprintf>> are (respectively)
    1.54 +* variants of <<printf>>, <<fprintf>>, and <<sprintf>>.  They differ
    1.55 +* only in allowing their caller to pass the variable argument list as a
    1.56 +* <<va_list>> object (initialized by <<va_start>>) rather than directly
    1.57 +* accepting a variable number of arguments.
    1.58 +* RETURNS
    1.59 +* The return values are consistent with the corresponding functions:
    1.60 +* <<vsprintf>> returns the number of bytes in the output string,
    1.61 +* save that the concluding <<NULL>> is not counted.
    1.62 +* <<vprintf>> and <<vfprintf>> return the number of characters transmitted.
    1.63 +* If an error occurs, <<vprintf>> and <<vfprintf>> return <<EOF>>. No
    1.64 +* error returns occur for <<vsprintf>>.
    1.65 +* PORTABILITY
    1.66 +* ANSI C requires all three functions.
    1.67 +* Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
    1.68 +* <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
    1.69 +* 
    1.70 +*
    1.71 +*/
    1.72 +
    1.73 +
    1.74 +
    1.75 +/*-
    1.76 + * Copyright (c) 1990 The Regents of the University of California.
    1.77 + * All rights reserved.
    1.78 + *
    1.79 + * This code is derived from software contributed to Berkeley by
    1.80 + * Chris Torek.
    1.81 + *
    1.82 + * Redistribution and use in source and binary forms, with or without
    1.83 + * modification, are permitted provided that the following conditions
    1.84 + * are met:
    1.85 + * 1. Redistributions of source code must retain the above copyright
    1.86 + *    notice, this list of conditions and the following disclaimer.
    1.87 + * 2. Redistributions in binary form must reproduce the above copyright
    1.88 + *    notice, this list of conditions and the following disclaimer in the
    1.89 + *    documentation and/or other materials provided with the distribution.
    1.90 + * 3. All advertising materials mentioning features or use of this software
    1.91 + *    must display the following acknowledgement:
    1.92 + *	This product includes software developed by the University of
    1.93 + *	California, Berkeley and its contributors.
    1.94 + * 4. Neither the name of the University nor the names of its contributors
    1.95 + *    may be used to endorse or promote products derived from this software
    1.96 + *    without specific prior written permission.
    1.97 + *
    1.98 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    1.99 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   1.100 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   1.101 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   1.102 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   1.103 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   1.104 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   1.105 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   1.106 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   1.107 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   1.108 + * SUCH DAMAGE.
   1.109 + */
   1.110 +
   1.111 +/*
   1.112 + * Actual printf innards.
   1.113 + *
   1.114 + * This code is large and complicated...
   1.115 + */
   1.116 +
   1.117 +#if 1
   1.118 +#define _NO_LONGLONG
   1.119 +#endif
   1.120 +
   1.121 +#include <_ansi.h>
   1.122 +#include <stdio_r.h>
   1.123 +#include <stdlib_r.h>
   1.124 +#include <string.h>
   1.125 +#include <reent.h>
   1.126 +
   1.127 +#include <stdarg.h>
   1.128 +
   1.129 +#include "LOCAL.H"
   1.130 +#include "FVWRITE.H"
   1.131 +
   1.132 +
   1.133 +//cm
   1.134 +#include <stdlib.h>
   1.135 +
   1.136 +
   1.137 +/*
   1.138 + * Flush out all the vectors defined by the given uio,
   1.139 + * then reset it so that it can be reused.
   1.140 + */
   1.141 +static int
   1.142 +__sprint(FILE *fp,register struct __suio *uio)
   1.143 +{
   1.144 +	register int err;
   1.145 +
   1.146 +	if (uio->uio_resid == 0) {
   1.147 +		uio->uio_iovcnt = 0;
   1.148 +		return (0);
   1.149 +	}
   1.150 +	err = __sfvwrite(fp, uio);
   1.151 +	uio->uio_resid = 0;
   1.152 +	uio->uio_iovcnt = 0;
   1.153 +	return (err);
   1.154 +}
   1.155 +
   1.156 +/*
   1.157 + * Helper function for `fprintf to unbuffered unix file': creates a
   1.158 + * temporary buffer.  We only work on write-only files; this avoids
   1.159 + * worries about ungetc buffers and so forth.
   1.160 + */
   1.161 +static int
   1.162 +__sbprintf(register FILE *fp,const char *fmt,va_list ap)
   1.163 +{
   1.164 +	int ret;
   1.165 +	FILE fake;
   1.166 +	unsigned char buf[BUFSIZ];
   1.167 +
   1.168 +	/* copy the important variables */
   1.169 +	fake._data = fp->_data;
   1.170 +	fake._flags = (short)(fp->_flags & ~__SNBF);
   1.171 +	fake._file = fp->_file;
   1.172 +	fake._cookie = fp->_cookie;
   1.173 +	fake._write = fp->_write;
   1.174 +
   1.175 +	/* set up the buffer */
   1.176 +	fake._bf._base = fake._p = buf;
   1.177 +	fake._bf._size = fake._w = sizeof(buf);
   1.178 +	fake._lbfsize = 0;	/* not actually used, but Just In Case */
   1.179 +
   1.180 +	/* do the work, then copy any error status */
   1.181 +	ret = vfprintf(&fake, fmt, ap);
   1.182 +	if (ret >= 0 && fflush(&fake))
   1.183 +		ret = EOF;
   1.184 +	if (fake._flags & __SERR)
   1.185 +		fp->_flags |= __SERR;
   1.186 +	return (ret);
   1.187 +}
   1.188 +
   1.189 +
   1.190 +/* #include <locale.h>   for decimal_point */
   1.191 +#include <math.h>
   1.192 +#include "FLOATIO.H"
   1.193 +
   1.194 +#define	BUF		(MAXEXP+MAXFRACT+1)	/* + decimal point */
   1.195 +#define	DEFPREC		6
   1.196 +
   1.197 +extern int e32cvt (char *buf, int buflen, double, int width, int prec, int flags, int fmt);
   1.198 +
   1.199 +
   1.200 +/*
   1.201 + * Macros for converting digits to letters and vice versa
   1.202 + */
   1.203 +#define	to_digit(c)	((c) - '0')
   1.204 +#define is_digit(c)	((unsigned)to_digit(c) <= 9)
   1.205 +#define	to_char(n)	((n) + '0')
   1.206 +
   1.207 +/*
   1.208 + * Flags used during conversion.
   1.209 + */
   1.210 +#define	ALT		0x001		/* alternate form */
   1.211 +#define	HEXPREFIX	0x002		/* add 0x or 0X prefix */
   1.212 +#define	LADJUST		0x004		/* left adjustment */
   1.213 +#define	LONGDBL		0x008		/* long double; unimplemented */
   1.214 +#define	LONGINT		0x010		/* long integer */
   1.215 +#define	QUADINT		0x020		/* quad integer */
   1.216 +#define	SHORTINT	0x040		/* short integer */
   1.217 +#define	ZEROPAD		0x080		/* zero (as opposed to blank) pad */
   1.218 +#define FPT		0x100		/* Floating point number */
   1.219 +
   1.220 +EXPORT_C int 
   1.221 +vfprintf (FILE * fp, const char *fmt0, va_list ap)
   1.222 +{
   1.223 +  return _vfprintf_r (fp->_data, fp, fmt0, ap);
   1.224 +}
   1.225 +
   1.226 +/**
   1.227 +A reentrant version of vfprintf().
   1.228 +*/
   1.229 +EXPORT_C int 
   1.230 +_vfprintf_r (struct _reent *data, FILE * fp, const char *fmt0, va_list ap)
   1.231 +{
   1.232 +	register char *fmt;	/* format string */
   1.233 +	register int ch;	/* character from fmt */
   1.234 +	register int n, m;	/* handy integers (short term usage) */
   1.235 +	register char *cp;	/* handy char pointer (short term usage) */
   1.236 +	register struct __siov *iovp;/* for PRINT macro */
   1.237 +	register int flags;	/* flags as above */
   1.238 +	int ret;		/* return value accumulator */
   1.239 +	int width;		/* width from format (%8d), or 0 */
   1.240 +	int prec;		/* precision from format (%.3d), or -1 */
   1.241 +	char sign;		/* sign prefix (' ', '+', '-', or \0) */
   1.242 +	wchar_t wc;
   1.243 +#if 0
   1.244 +	char *decimal_point = "."; /* localeconv()->decimal_point; */
   1.245 +#endif
   1.246 +//	char softsign;		/* temporary negative sign for floats */
   1.247 +	double _double;		/* double precision arguments %[eEfgG] */
   1.248 +//	int expt;		/* integer value of exponent */
   1.249 +//	int expsize;		/* character count for expstr */
   1.250 +//	int ndig;		/* actual number of digits returned by cvt */
   1.251 +//	char expstr[7];		/* buffer for exponent string */
   1.252 +
   1.253 +#ifndef _NO_LONGLONG
   1.254 +#define	quad_t	  long long
   1.255 +#define	u_quad_t  unsigned long long
   1.256 +#endif
   1.257 +
   1.258 +#ifndef _NO_LONGLONG
   1.259 +	u_quad_t _uquad;	/* integer arguments %[diouxX] */
   1.260 +#else
   1.261 +	u_long _uquad;
   1.262 +#endif
   1.263 +	enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
   1.264 +	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
   1.265 +	int realsz;		/* field size expanded by dprec */
   1.266 +	int size;		/* size of converted field or string */
   1.267 +	char *xdigs = NULL;	/* digits for [xX] conversion */
   1.268 +#define NIOV 8
   1.269 +	struct __suio uio;	/* output information: summary */
   1.270 +	struct __siov iov[NIOV];/* ... and individual io vectors */
   1.271 +	char buf[BUF];		/* space for %c, %[diouxX], %[eEfgG] */
   1.272 +	char ox[2];		/* space for 0x hex-prefix */
   1.273 +
   1.274 +	/*
   1.275 +	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
   1.276 +	 * fields occur frequently, increase PADSIZE and make the initialisers
   1.277 +	 * below longer.
   1.278 +	 */
   1.279 +#define	PADSIZE	16		/* pad chunk size */
   1.280 +	static const char blanks[PADSIZE] =
   1.281 +	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
   1.282 +	static const char zeroes[PADSIZE] =
   1.283 +	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
   1.284 +
   1.285 +	/*
   1.286 +	 * BEWARE, these `goto error' on error, and PAD uses `n'.
   1.287 +	 */
   1.288 +#define	PRINT(ptr, len) { \
   1.289 +	iovp->iov_base = (ptr); \
   1.290 +	iovp->iov_len = (len); \
   1.291 +	uio.uio_resid += (len); \
   1.292 +	iovp++; \
   1.293 +	if (++uio.uio_iovcnt >= NIOV) { \
   1.294 +		if (__sprint(fp, &uio)) \
   1.295 +			goto error; \
   1.296 +		iovp = iov; \
   1.297 +	} \
   1.298 +}
   1.299 +#define	PAD(howmany, with) { \
   1.300 +	if ((n = (howmany)) > 0) { \
   1.301 +		while (n > PADSIZE) { \
   1.302 +			PRINT(with, PADSIZE); \
   1.303 +			n -= PADSIZE; \
   1.304 +		} \
   1.305 +		PRINT(with, n); \
   1.306 +	} \
   1.307 +}
   1.308 +#define	FLUSH() { \
   1.309 +	if (uio.uio_resid && __sprint(fp, &uio)) \
   1.310 +		goto error; \
   1.311 +	uio.uio_iovcnt = 0; \
   1.312 +	iovp = iov; \
   1.313 +}
   1.314 +
   1.315 +	/*
   1.316 +	 * To extend shorts properly, we need both signed and unsigned
   1.317 +	 * argument extraction methods.
   1.318 +	 */
   1.319 +#ifndef _NO_LONGLONG
   1.320 +#define	SARG() \
   1.321 +	(flags&QUADINT ? va_arg(ap, quad_t) : \
   1.322 +	    flags&LONGINT ? va_arg(ap, long) : \
   1.323 +	    flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
   1.324 +	    (long)va_arg(ap, int))
   1.325 +#define	UARG() \
   1.326 +	(flags&QUADINT ? va_arg(ap, u_quad_t) : \
   1.327 +	    flags&LONGINT ? va_arg(ap, u_long) : \
   1.328 +	    flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
   1.329 +	    (u_long)va_arg(ap, u_int))
   1.330 +#else
   1.331 +#define	SARG() \
   1.332 +	(flags&LONGINT ? va_arg(ap, long) : \
   1.333 +	    flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
   1.334 +	    (long)va_arg(ap, int))
   1.335 +#define	UARG() \
   1.336 +	(flags&LONGINT ? va_arg(ap, u_long) : \
   1.337 +	    flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
   1.338 +	    (u_long)va_arg(ap, u_int))
   1.339 +#endif
   1.340 +
   1.341 +	CHECK_INIT (fp);
   1.342 +
   1.343 +	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
   1.344 +	if (cantwrite(fp))
   1.345 +		return (EOF);
   1.346 +
   1.347 +	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
   1.348 +	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
   1.349 +	    fp->_file >= 0)
   1.350 +		return (__sbprintf(fp, fmt0, ap));
   1.351 +
   1.352 +	fmt = (char *)fmt0;
   1.353 +	uio.uio_iov = iovp = iov;
   1.354 +	uio.uio_resid = 0;
   1.355 +	uio.uio_iovcnt = 0;
   1.356 +	ret = 0;
   1.357 +
   1.358 +	/*
   1.359 +	 * Scan the format for conversions (`%' character).
   1.360 +	 */
   1.361 +	for (;;) {
   1.362 +		cp = fmt;
   1.363 +		while ((n = mbtowc(&wc, fmt, MB_CUR_MAX)) > 0) {
   1.364 +			fmt += n;
   1.365 +			if (wc == L'%') {
   1.366 +				fmt--;
   1.367 +				break;
   1.368 +			}
   1.369 +		}
   1.370 +		if ((m = fmt - cp) != 0) {
   1.371 +			PRINT(cp, m);
   1.372 +			ret += m;
   1.373 +		}
   1.374 +		if (n <= 0)
   1.375 +			goto done;
   1.376 +		fmt++;		/* skip over '%' */
   1.377 +
   1.378 +		flags = 0;
   1.379 +		dprec = 0;
   1.380 +		width = 0;
   1.381 +		prec = -1;
   1.382 +		sign = '\0';
   1.383 +
   1.384 +rflag:		ch = *fmt++;
   1.385 +reswitch:	switch (ch) {
   1.386 +		case ' ':
   1.387 +			/*
   1.388 +			 * ``If the space and + flags both appear, the space
   1.389 +			 * flag will be ignored.''
   1.390 +			 *	-- ANSI X3J11
   1.391 +			 */
   1.392 +			if (!sign)
   1.393 +				sign = ' ';
   1.394 +			goto rflag;
   1.395 +		case '#':
   1.396 +			flags |= ALT;
   1.397 +			goto rflag;
   1.398 +		case '*':
   1.399 +			/*
   1.400 +			 * ``A negative field width argument is taken as a
   1.401 +			 * - flag followed by a positive field width.''
   1.402 +			 *	-- ANSI X3J11
   1.403 +			 * They don't exclude field widths read from args.
   1.404 +			 */
   1.405 +			if ((width = va_arg(ap, int)) >= 0)
   1.406 +				goto rflag;
   1.407 +			width = -width;
   1.408 +			/* FALLTHROUGH */
   1.409 +		case '-':
   1.410 +			flags |= LADJUST;
   1.411 +			goto rflag;
   1.412 +		case '+':
   1.413 +			sign = '+';
   1.414 +			goto rflag;
   1.415 +		case '.':
   1.416 +			if ((ch = *fmt++) == '*') {
   1.417 +				n = va_arg(ap, int);
   1.418 +				prec = n < 0 ? -1 : n;
   1.419 +				goto rflag;
   1.420 +			}
   1.421 +			n = 0;
   1.422 +			while (is_digit(ch)) {
   1.423 +				n = 10 * n + to_digit(ch);
   1.424 +				ch = *fmt++;
   1.425 +			}
   1.426 +			prec = n < 0 ? -1 : n;
   1.427 +			goto reswitch;
   1.428 +		case '0':
   1.429 +			/*
   1.430 +			 * ``Note that 0 is taken as a flag, not as the
   1.431 +			 * beginning of a field width.''
   1.432 +			 *	-- ANSI X3J11
   1.433 +			 */
   1.434 +			flags |= ZEROPAD;
   1.435 +			goto rflag;
   1.436 +		case '1': case '2': case '3': case '4':
   1.437 +		case '5': case '6': case '7': case '8': case '9':
   1.438 +			n = 0;
   1.439 +			do {
   1.440 +				n = 10 * n + to_digit(ch);
   1.441 +				ch = *fmt++;
   1.442 +			} while (is_digit(ch));
   1.443 +			width = n;
   1.444 +			goto reswitch;
   1.445 +		case 'L':
   1.446 +			flags |= LONGDBL;
   1.447 +			goto rflag;
   1.448 +		case 'h':
   1.449 +			flags |= SHORTINT;
   1.450 +			goto rflag;
   1.451 +		case 'l':
   1.452 +			if (*fmt == 'l') {
   1.453 +				fmt++;
   1.454 +				flags |= QUADINT;
   1.455 +			} else {
   1.456 +				flags |= LONGINT;
   1.457 +			}
   1.458 +			goto rflag;
   1.459 +		case 'q':
   1.460 +			flags |= QUADINT;
   1.461 +			goto rflag;
   1.462 +		case 'c':
   1.463 +			*(cp = buf) = (char)va_arg(ap, int);
   1.464 +			size = 1;
   1.465 +			sign = '\0';
   1.466 +			break;
   1.467 +		case 'D':
   1.468 +			flags |= LONGINT;
   1.469 +			/*FALLTHROUGH*/
   1.470 +		case 'd':
   1.471 +		case 'i':
   1.472 +			_uquad = SARG();
   1.473 +#ifndef _NO_LONGLONG
   1.474 +			if ((quad_t)_uquad < 0)
   1.475 +#else
   1.476 +			if ((long) _uquad < 0)
   1.477 +#endif
   1.478 +			{
   1.479 +
   1.480 +#ifndef _NO_LONGLONG
   1.481 +				_uquad = -_uquad;
   1.482 +#else
   1.483 +				_uquad = (u_long)(-(long)_uquad);
   1.484 +#endif
   1.485 +				sign = '-';
   1.486 +			}
   1.487 +			base = DEC;
   1.488 +			goto number;
   1.489 +
   1.490 +		case 'e':
   1.491 +		case 'E':
   1.492 +		case 'f':
   1.493 +		case 'g':
   1.494 +		case 'G':
   1.495 +			if (prec == -1) {
   1.496 +				prec = DEFPREC;
   1.497 +			} else if ((ch == 'g' || ch == 'G') && prec == 0) {
   1.498 +				prec = 1;
   1.499 +			}
   1.500 +
   1.501 +			if (flags & LONGDBL) {
   1.502 +				_double = (double) va_arg(ap, long double);
   1.503 +			} else {
   1.504 +				_double = va_arg(ap, double);
   1.505 +			}
   1.506 +
   1.507 +			/* do this before tricky precision changes */
   1.508 +			if (isinf(_double)) {
   1.509 +				if (_double < 0)
   1.510 +					sign = '-';
   1.511 +				cp = "Inf";
   1.512 +				size = 3;
   1.513 +				break;
   1.514 +			}
   1.515 +			if (isnan(_double)) {
   1.516 +				cp = "NaN";
   1.517 +				size = 3;
   1.518 +				break;
   1.519 +			}
   1.520 +			flags |= FPT;
   1.521 +#if 0
   1.522 +			cp = cvt(data, _double, prec, flags, &softsign,
   1.523 +				&expt, ch, &ndig);
   1.524 +			if (ch == 'g' || ch == 'G') {
   1.525 +				if (expt <= -4 || expt > prec)
   1.526 +					ch = (ch == 'g') ? 'e' : 'E';
   1.527 +				else
   1.528 +					ch = 'g';
   1.529 +			} 
   1.530 +			if (ch <= 'e') {	/* 'e' or 'E' fmt */
   1.531 +				--expt;
   1.532 +				expsize = exponent(expstr, expt, ch);
   1.533 +				size = expsize + ndig;
   1.534 +				if (ndig > 1 || flags & ALT)
   1.535 +					++size;
   1.536 +			} else if (ch == 'f') {		/* f fmt */
   1.537 +				if (expt > 0) {
   1.538 +					size = expt;
   1.539 +					if (prec || flags & ALT)
   1.540 +						size += prec + 1;
   1.541 +				} else	/* "0.X" */
   1.542 +					size = prec + 2;
   1.543 +			} else if (expt >= ndig) {	/* fixed g fmt */
   1.544 +				size = expt;
   1.545 +				if (flags & ALT)
   1.546 +					++size;
   1.547 +			} else
   1.548 +				size = ndig + (expt > 0 ?
   1.549 +					1 : 2 - expt);
   1.550 +
   1.551 +			if (softsign)
   1.552 +				sign = '-';
   1.553 +#else
   1.554 +			if (_double < 0) {
   1.555 +				_double = -_double;
   1.556 +				sign = '-';
   1.557 +			}
   1.558 +			size = e32cvt(buf, BUF, _double, width, prec, flags, ch);
   1.559 +			cp=buf;
   1.560 +#endif
   1.561 +			break;
   1.562 +
   1.563 +		case 'n':
   1.564 +#ifndef _NO_LONGLONG
   1.565 +			if (flags & QUADINT)
   1.566 +				*va_arg(ap, quad_t *) = ret;
   1.567 +			else 
   1.568 +#endif
   1.569 +			if (flags & LONGINT)
   1.570 +				*va_arg(ap, long *) = ret;
   1.571 +			else if (flags & SHORTINT)
   1.572 +				*va_arg(ap, short *) = (short)ret;
   1.573 +			else
   1.574 +				*va_arg(ap, int *) = ret;
   1.575 +			continue;	/* no output */
   1.576 +		case 'O':
   1.577 +			flags |= LONGINT;
   1.578 +			/*FALLTHROUGH*/
   1.579 +		case 'o':
   1.580 +			_uquad = UARG();
   1.581 +			base = OCT;
   1.582 +			goto nosign;
   1.583 +		case 'p':
   1.584 +			/*
   1.585 +			 * ``The argument shall be a pointer to void.  The
   1.586 +			 * value of the pointer is converted to a sequence
   1.587 +			 * of printable characters, in an implementation-
   1.588 +			 * defined manner.''
   1.589 +			 *	-- ANSI X3J11
   1.590 +			 */
   1.591 +			/* NOSTRICT */
   1.592 +			_uquad = (u_long)va_arg(ap, void *);
   1.593 +			base = HEX;
   1.594 +			xdigs = "0123456789abcdef";
   1.595 +			flags |= HEXPREFIX;
   1.596 +			ch = 'x';
   1.597 +			goto nosign;
   1.598 +		case 's':
   1.599 +			if ((cp = va_arg(ap, char *)) == NULL)
   1.600 +				cp = "(null)";
   1.601 +			if (prec >= 0) {
   1.602 +				/*
   1.603 +				 * can't use strlen; can only look for the
   1.604 +				 * NUL in the first `prec' characters, and
   1.605 +				 * strlen() will go further.
   1.606 +				 */
   1.607 +				char *p = (char *)memchr(cp, 0, prec);
   1.608 +
   1.609 +				if (p != NULL) {
   1.610 +					size = p - cp;
   1.611 +					if (size > prec)
   1.612 +						size = prec;
   1.613 +				} else
   1.614 +					size = prec;
   1.615 +			} else
   1.616 +				size = strlen(cp);
   1.617 +			sign = '\0';
   1.618 +			break;
   1.619 +		case 'U':
   1.620 +			flags |= LONGINT;
   1.621 +			/*FALLTHROUGH*/
   1.622 +		case 'u':
   1.623 +			_uquad = UARG();
   1.624 +			base = DEC;
   1.625 +			goto nosign;
   1.626 +		case 'X':
   1.627 +			xdigs = "0123456789ABCDEF";
   1.628 +			goto hex;
   1.629 +		case 'x':
   1.630 +			xdigs = "0123456789abcdef";
   1.631 +hex:			_uquad = UARG();
   1.632 +			base = HEX;
   1.633 +			/* leading 0x/X only if non-zero */
   1.634 +			if (flags & ALT && _uquad != 0)
   1.635 +				flags |= HEXPREFIX;
   1.636 +
   1.637 +			/* unsigned conversions */
   1.638 +nosign:			sign = '\0';
   1.639 +			/*
   1.640 +			 * ``... diouXx conversions ... if a precision is
   1.641 +			 * specified, the 0 flag will be ignored.''
   1.642 +			 *	-- ANSI X3J11
   1.643 +			 */
   1.644 +number:			if ((dprec = prec) >= 0)
   1.645 +				flags &= ~ZEROPAD;
   1.646 +
   1.647 +			/*
   1.648 +			 * ``The result of converting a zero value with an
   1.649 +			 * explicit precision of zero is no characters.''
   1.650 +			 *	-- ANSI X3J11
   1.651 +			 */
   1.652 +			cp = buf + BUF;
   1.653 +			if (_uquad != 0 || prec != 0) {
   1.654 +				/*
   1.655 +				 * Unsigned mod is hard, and unsigned mod
   1.656 +				 * by a constant is easier than that by
   1.657 +				 * a variable; hence this switch.
   1.658 +				 */
   1.659 +				switch (base) {
   1.660 +				case OCT:
   1.661 +					do {
   1.662 +						*--cp = (char)to_char(_uquad & 7);
   1.663 +						_uquad >>= 3;
   1.664 +					} while (_uquad);
   1.665 +					/* handle octal leading 0 */
   1.666 +					if (flags & ALT && *cp != '0')
   1.667 +						*--cp = '0';
   1.668 +					break;
   1.669 +
   1.670 +				case DEC:
   1.671 +					/* many numbers are 1 digit */
   1.672 +					while (_uquad >= 10) {
   1.673 +						*--cp = (char)to_char(_uquad % 10);
   1.674 +						_uquad /= 10;
   1.675 +					}
   1.676 +					*--cp = (char)to_char(_uquad);
   1.677 +					break;
   1.678 +
   1.679 +				case HEX:
   1.680 +					do {
   1.681 +						*--cp = xdigs[_uquad & 15];
   1.682 +						_uquad >>= 4;
   1.683 +					} while (_uquad);
   1.684 +					break;
   1.685 +
   1.686 +				default:
   1.687 +					cp = "bug in vfprintf: bad base";
   1.688 +					size = strlen(cp);
   1.689 +					goto skipsize;
   1.690 +				}
   1.691 +			}
   1.692 +			/* Workaround GCC compiler bug: size = buf + BUF - cp */
   1.693 +			{
   1.694 +				char *temp = buf+BUF;
   1.695 +				size = temp - cp;
   1.696 +			}
   1.697 +		skipsize:
   1.698 +			break;
   1.699 +		default:	/* "%?" prints ?, unless ? is NUL */
   1.700 +			if (ch == '\0')
   1.701 +				goto done;
   1.702 +			/* pretend it was %c with argument ch */
   1.703 +			cp = buf;
   1.704 +			*cp = (char)ch;
   1.705 +			size = 1;
   1.706 +			sign = '\0';
   1.707 +			break;
   1.708 +		}
   1.709 +
   1.710 +		/*
   1.711 +		 * All reasonable formats wind up here.  At this point, `cp'
   1.712 +		 * points to a string which (if not flags&LADJUST) should be
   1.713 +		 * padded out to `width' places.  If flags&ZEROPAD, it should
   1.714 +		 * first be prefixed by any sign or other prefix; otherwise,
   1.715 +		 * it should be blank padded before the prefix is emitted.
   1.716 +		 * After any left-hand padding and prefixing, emit zeroes
   1.717 +		 * required by a decimal [diouxX] precision, then print the
   1.718 +		 * string proper, then emit zeroes required by any leftover
   1.719 +		 * floating precision; finally, if LADJUST, pad with blanks.
   1.720 +		 *
   1.721 +		 * Compute actual size, so we know how much to pad.
   1.722 +		 * size excludes decimal prec; realsz includes it.
   1.723 +		 */
   1.724 +		realsz = dprec > size ? dprec : size;
   1.725 +		if (sign)
   1.726 +			realsz++;
   1.727 +		else if (flags & HEXPREFIX)
   1.728 +			realsz+= 2;
   1.729 +
   1.730 +		/* right-adjusting blank padding */
   1.731 +		if ((flags & (LADJUST|ZEROPAD)) == 0)
   1.732 +			PAD(width - realsz, blanks);
   1.733 +
   1.734 +		/* prefix */
   1.735 +		if (sign) {
   1.736 +			PRINT(&sign, 1);
   1.737 +		} else if (flags & HEXPREFIX) {
   1.738 +			ox[0] = '0';
   1.739 +			ox[1] = (char)ch;
   1.740 +			PRINT(ox, 2);
   1.741 +		}
   1.742 +
   1.743 +		/* right-adjusting zero padding */
   1.744 +		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
   1.745 +			PAD(width - realsz, zeroes);
   1.746 +
   1.747 +		/* leading zeroes from decimal precision */
   1.748 +		PAD(dprec - size, zeroes);
   1.749 +
   1.750 +		/* the string or number proper */
   1.751 +		PRINT(cp, size);
   1.752 +#if 0
   1.753 +		} else {	/* glue together f_p fragments */
   1.754 +			if (ch >= 'f') {	/* 'f' or 'g' */
   1.755 +				if (_double == 0) {
   1.756 +					/* kludge for __dtoa irregularity */
   1.757 +					PRINT("0", 1);
   1.758 +					if (expt < ndig || (flags & ALT) != 0) {
   1.759 +						PRINT(decimal_point, 1);
   1.760 +						PAD(ndig - 1, zeroes);
   1.761 +					}
   1.762 +				} else if (expt <= 0) {
   1.763 +					PRINT("0", 1);
   1.764 +					PRINT(decimal_point, 1);
   1.765 +					PAD(-expt, zeroes);
   1.766 +					PRINT(cp, ndig);
   1.767 +				} else if (expt >= ndig) {
   1.768 +					PRINT(cp, ndig);
   1.769 +					PAD(expt - ndig, zeroes);
   1.770 +					if (flags & ALT)
   1.771 +						PRINT(".", 1);
   1.772 +				} else {
   1.773 +					PRINT(cp, expt);
   1.774 +					cp += expt;
   1.775 +					PRINT(".", 1);
   1.776 +					PRINT(cp, ndig-expt);
   1.777 +				}
   1.778 +			} else {	/* 'e' or 'E' */
   1.779 +				if (ndig > 1 || flags & ALT) {
   1.780 +					ox[0] = *cp++;
   1.781 +					ox[1] = '.';
   1.782 +					PRINT(ox, 2);
   1.783 +					if (_double || (flags & ALT) == 0) {
   1.784 +						PRINT(cp, ndig-1);
   1.785 +					} else	/* 0.[0..] */
   1.786 +						/* __dtoa irregularity */
   1.787 +						PAD(ndig - 1, zeroes);
   1.788 +				} else	/* XeYYY */
   1.789 +					PRINT(cp, 1);
   1.790 +				PRINT(expstr, expsize);
   1.791 +			}
   1.792 +		}
   1.793 +#endif
   1.794 +		/* left-adjusting padding (always blank) */
   1.795 +		if (flags & LADJUST)
   1.796 +			PAD(width - realsz, blanks);
   1.797 +
   1.798 +		/* finally, adjust ret */
   1.799 +		ret += width > realsz ? width : realsz;
   1.800 +
   1.801 +		FLUSH();	/* copy out the I/O vectors */
   1.802 +	}
   1.803 +done:
   1.804 +	FLUSH();
   1.805 +error:
   1.806 +	return (__sferror(fp) ? EOF : ret);
   1.807 +	/* NOTREACHED */
   1.808 +}
   1.809 +
   1.810 +#if 0
   1.811 +static char *
   1.812 +cvt(struct _reent *data,double value,int ndigits, int flags, char *sign, int *decpt, int ch, int *length)
   1.813 +{
   1.814 +	int mode, dsgn;
   1.815 +	char *digits, *bp, *rve;
   1.816 +
   1.817 +	if (ch == 'f') {
   1.818 +		mode = 3;		/* ndigits after the decimal point */
   1.819 +	} else {
   1.820 +		/* To obtain ndigits after the decimal point for the 'e' 
   1.821 +		 * and 'E' formats, round to ndigits + 1 significant 
   1.822 +		 * figures.
   1.823 +		 */
   1.824 +		if (ch == 'e' || ch == 'E') {
   1.825 +			ndigits++;
   1.826 +		}
   1.827 +		mode = 2;		/* ndigits significant digits */
   1.828 +	}
   1.829 +
   1.830 +	if (value < 0) {
   1.831 +		value = -value;
   1.832 +		*sign = '-';
   1.833 +	} else
   1.834 +		*sign = '\000';
   1.835 +	digits = _dtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve);
   1.836 +	if ((ch != 'g' && ch != 'G') || flags & ALT) {	/* Print trailing zeros */
   1.837 +		bp = digits + ndigits;
   1.838 +		if (ch == 'f') {
   1.839 +			if (*digits == '0' && value)
   1.840 +				*decpt = -ndigits + 1;
   1.841 +			bp += *decpt;
   1.842 +		}
   1.843 +		if (value == 0)	/* kludge for __dtoa irregularity */
   1.844 +			rve = bp;
   1.845 +		while (rve < bp)
   1.846 +			*rve++ = '0';
   1.847 +	}
   1.848 +	*length = rve - digits;
   1.849 +	return (digits);
   1.850 +}
   1.851 +
   1.852 +static int
   1.853 +exponent(char *p0, int exp, int fmtch)
   1.854 +{
   1.855 +	register char *p, *t;
   1.856 +	char expbuf[MAXEXP];
   1.857 +
   1.858 +	p = p0;
   1.859 +	*p++ = (char)fmtch;
   1.860 +	if (exp < 0) {
   1.861 +		exp = -exp;
   1.862 +		*p++ = '-';
   1.863 +	}
   1.864 +	else
   1.865 +		*p++ = '+';
   1.866 +	t = expbuf + MAXEXP;
   1.867 +	if (exp > 9) {
   1.868 +		do {
   1.869 +			*--t = (char)to_char(exp % 10);
   1.870 +		} while ((exp /= 10) > 9);
   1.871 +		*--t = (char)to_char(exp);
   1.872 +		for (; t < expbuf + MAXEXP; *p++ = *t++);
   1.873 +	}
   1.874 +	else {
   1.875 +		*p++ = '0';
   1.876 +		*p++ = (char)to_char(exp);
   1.877 +	}
   1.878 +	return (p - p0);
   1.879 +}
   1.880 +#endif