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