summaryrefslogtreecommitdiffstats
path: root/contrib/libio/iovfprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libio/iovfprintf.c')
-rw-r--r--contrib/libio/iovfprintf.c890
1 files changed, 0 insertions, 890 deletions
diff --git a/contrib/libio/iovfprintf.c b/contrib/libio/iovfprintf.c
deleted file mode 100644
index 755334c..0000000
--- a/contrib/libio/iovfprintf.c
+++ /dev/null
@@ -1,890 +0,0 @@
-/*
-Copyright (C) 1993 Free Software Foundation
-
-This file is part of the GNU IO Library. This library is free
-software; you can redistribute it and/or modify it under the
-terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this library; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-As a special exception, if you link this library with files
-compiled with a GNU compiler to produce an executable, this does not cause
-the resulting executable to be covered by the GNU General Public License.
-This exception does not however invalidate any other reasons why
-the executable file might be covered by the GNU General Public License. */
-
-/*
- * Copyright (c) 1990 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "%W% (Berkeley) %G%";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * Actual printf innards.
- *
- * This code is large and complicated...
- */
-
-#include <sys/types.h>
-#include "libioP.h"
-#include <string.h>
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-#ifndef _IO_USE_DTOA
-int __cvt_double __P((double number, register int prec, int flags, int *signp, int fmtch, char *startp, char *endp));
-#endif
-
-/*
- * Define FLOATING_POINT to get floating point.
- */
-#ifndef NO_FLOATING_POINT
-#define FLOATING_POINT
-#endif
-
-/* end of configuration stuff */
-
-
-/*
- * Helper "class" for `fprintf to unbuffered': creates a
- * temporary buffer. */
-
-struct helper_file
-{
- struct _IO_FILE_plus _f;
- _IO_FILE *_put_stream;
-};
-
-static int
-_IO_helper_overflow (fp, c)
- _IO_FILE *fp;
- int c;
-{
- _IO_FILE *target = ((struct helper_file*)fp)->_put_stream;
- int used = fp->_IO_write_ptr - fp->_IO_write_base;
- if (used)
- {
- _IO_sputn(target, fp->_IO_write_base, used);
- fp->_IO_write_ptr -= used;
- }
- return _IO_putc (c, fp);
-}
-
-static struct _IO_jump_t _IO_helper_jumps = {
- JUMP_INIT_DUMMY,
- JUMP_INIT(finish, _IO_default_finish),
- JUMP_INIT(overflow, _IO_helper_overflow),
- JUMP_INIT(underflow, _IO_default_underflow),
- JUMP_INIT(uflow, _IO_default_uflow),
- JUMP_INIT(pbackfail, _IO_default_pbackfail),
- JUMP_INIT(xsputn, _IO_default_xsputn),
- JUMP_INIT(xsgetn, _IO_default_xsgetn),
- JUMP_INIT(seekoff, _IO_default_seekoff),
- JUMP_INIT(seekpos, _IO_default_seekpos),
- JUMP_INIT(setbuf, _IO_default_setbuf),
- JUMP_INIT(sync, _IO_default_sync),
- JUMP_INIT(doallocate, _IO_default_doallocate),
- JUMP_INIT(read, _IO_default_read),
- JUMP_INIT(write, _IO_default_write),
- JUMP_INIT(seek, _IO_default_seek),
- JUMP_INIT(close, _IO_default_close),
- JUMP_INIT(stat, _IO_default_stat)
-};
-
-static int
-helper_vfprintf (fp, fmt0, ap)
- _IO_FILE *fp;
- char const *fmt0;
- _IO_va_list ap;
-{
- char buf[_IO_BUFSIZ];
- struct helper_file helper;
- register _IO_FILE *hp = (_IO_FILE*)&helper;
- int result, to_flush;
-
- /* initialize helper */
- helper._put_stream = fp;
- hp->_IO_write_base = buf;
- hp->_IO_write_ptr = buf;
- hp->_IO_write_end = buf+_IO_BUFSIZ;
- hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS;
- _IO_JUMPS(hp) = &_IO_helper_jumps;
-
- /* Now print to helper instead. */
- result = _IO_vfprintf(hp, fmt0, ap);
-
- /* Now flush anything from the helper to the fp. */
- if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
- {
- if (_IO_sputn(fp, hp->_IO_write_base, to_flush) != to_flush)
- return EOF;
- }
- return result;
-}
-
-#ifdef FLOATING_POINT
-
-#include "floatio.h"
-#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
-#define DEFPREC 6
-extern double modf __P((double, double*));
-
-#else /* no FLOATING_POINT */
-
-#define BUF 40
-
-#endif /* FLOATING_POINT */
-
-
-/*
- * Macros for converting digits to letters and vice versa
- */
-#define to_digit(c) ((c) - '0')
-#define is_digit(c) ((unsigned)to_digit(c) <= 9)
-#define to_char(n) ((n) + '0')
-
-/*
- * Flags used during conversion.
- */
-#define LONGINT 0x01 /* long integer */
-#define LONGDBL 0x02 /* long double; unimplemented */
-#define SHORTINT 0x04 /* short integer */
-#define ALT 0x08 /* alternate form */
-#define LADJUST 0x10 /* left adjustment */
-#define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
-#define HEXPREFIX 0x40 /* add 0x or 0X prefix */
-
-int
-_IO_vfprintf (fp, fmt0, ap)
- _IO_FILE *fp;
- char const *fmt0;
- _IO_va_list ap;
-{
- register const char *fmt; /* format string */
- register int ch; /* character from fmt */
- register int n; /* handy integer (short term usage) */
- register char *cp; /* handy char pointer (short term usage) */
- const char *fmark; /* for remembering a place in fmt */
- register int flags; /* flags as above */
- int ret; /* return value accumulator */
- int width; /* width from format (%8d), or 0 */
- int prec; /* precision from format (%.3d), or -1 */
- char sign; /* sign prefix (' ', '+', '-', or \0) */
-#ifdef FLOATING_POINT
- int softsign; /* temporary negative sign for floats */
- double _double; /* double precision arguments %[eEfgG] */
-#ifndef _IO_USE_DTOA
- int fpprec; /* `extra' floating precision in [eEfgG] */
-#endif
-#endif
- unsigned long _ulong; /* integer arguments %[diouxX] */
- enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
- int dprec; /* a copy of prec if [diouxX], 0 otherwise */
- int dpad; /* extra 0 padding needed for integers */
- int fieldsz; /* field size expanded by sign, dpad etc */
- /* The initialization of 'size' is to suppress a warning that
- 'size' might be used unitialized. It seems gcc can't
- quite grok this spaghetti code ... */
- int size = 0; /* size of converted field or string */
- char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
- char ox[2]; /* space for 0x hex-prefix */
-
- /*
- * BEWARE, these `goto error' on error, and PAD uses `n'.
- */
-#define PRINT(ptr, len) \
- do { if (_IO_sputn(fp,ptr, len) != len) goto error; } while (0)
-#define PAD_SP(howmany) if (_IO_padn(fp, ' ', howmany) < (howmany)) goto error;
-#define PAD_0(howmany) if (_IO_padn(fp, '0', howmany) < (howmany)) goto error;
-
- /*
- * To extend shorts properly, we need both signed and unsigned
- * argument extraction methods.
- */
-#define SARG() \
- (flags&LONGINT ? va_arg(ap, long) : \
- flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
- (long)va_arg(ap, int))
-#define UARG() \
- (flags&LONGINT ? va_arg(ap, unsigned long) : \
- flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
- (unsigned long)va_arg(ap, unsigned int))
-
- /* optimise stderr (and other unbuffered Unix files) */
- if (fp->_IO_file_flags & _IO_UNBUFFERED)
- return helper_vfprintf(fp, fmt0, ap);
-
- fmt = fmt0;
- ret = 0;
-
- /*
- * Scan the format for conversions (`%' character).
- */
- for (;;) {
- for (fmark = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
- /* void */;
- if ((n = fmt - fmark) != 0) {
- PRINT(fmark, n);
- ret += n;
- }
- if (ch == '\0')
- goto done;
- fmt++; /* skip over '%' */
-
- flags = 0;
- dprec = 0;
-#if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
- fpprec = 0;
-#endif
- width = 0;
- prec = -1;
- sign = '\0';
-
-rflag: ch = *fmt++;
-reswitch: switch (ch) {
- case ' ':
- /*
- * ``If the space and + flags both appear, the space
- * flag will be ignored.''
- * -- ANSI X3J11
- */
- if (!sign)
- sign = ' ';
- goto rflag;
- case '#':
- flags |= ALT;
- goto rflag;
- case '*':
- /*
- * ``A negative field width argument is taken as a
- * - flag followed by a positive field width.''
- * -- ANSI X3J11
- * They don't exclude field widths read from args.
- */
- if ((width = va_arg(ap, int)) >= 0)
- goto rflag;
- width = -width;
- /* FALLTHROUGH */
- case '-':
- flags |= LADJUST;
- flags &= ~ZEROPAD; /* '-' disables '0' */
- goto rflag;
- case '+':
- sign = '+';
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
- n = va_arg(ap, int);
- prec = n < 0 ? -1 : n;
- goto rflag;
- }
- n = 0;
- while (is_digit(ch)) {
- n = 10 * n + to_digit(ch);
- ch = *fmt++;
- }
- prec = n < 0 ? -1 : n;
- goto reswitch;
- case '0':
- /*
- * ``Note that 0 is taken as a flag, not as the
- * beginning of a field width.''
- * -- ANSI X3J11
- */
- if (!(flags & LADJUST))
- flags |= ZEROPAD; /* '-' disables '0' */
- goto rflag;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- do {
- n = 10 * n + to_digit(ch);
- ch = *fmt++;
- } while (is_digit(ch));
- width = n;
- goto reswitch;
-#ifdef FLOATING_POINT
- case 'L':
- flags |= LONGDBL;
- goto rflag;
-#endif
- case 'h':
- flags |= SHORTINT;
- goto rflag;
- case 'l':
- flags |= LONGINT;
- goto rflag;
- case 'c':
- *(cp = buf) = va_arg(ap, int);
- size = 1;
- sign = '\0';
- break;
- case 'D':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'd':
- case 'i':
- _ulong = SARG();
- if ((long)_ulong < 0) {
- _ulong = -_ulong;
- sign = '-';
- }
- base = DEC;
- goto number;
-#ifdef FLOATING_POINT
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- _double = va_arg(ap, double);
-#ifdef _IO_USE_DTOA
- {
- int fmt_flags = 0;
- int fill = ' ';
- if (flags & ALT)
- fmt_flags |= _IO_SHOWPOINT;
- if (flags & LADJUST)
- fmt_flags |= _IO_LEFT;
- else if (flags & ZEROPAD)
- fmt_flags |= _IO_INTERNAL, fill = '0';
- n = _IO_outfloat(_double, fp, ch, width,
- prec < 0 ? DEFPREC : prec,
- fmt_flags, sign, fill);
- if (n < 0)
- goto error;
- ret += n;
- }
- /* CHECK ERROR! */
- continue;
-#else
- /*
- * don't do unrealistic precision; just pad it with
- * zeroes later, so buffer size stays rational.
- */
- if (prec > MAXFRACT) {
- if ((ch != 'g' && ch != 'G') || (flags&ALT))
- fpprec = prec - MAXFRACT;
- prec = MAXFRACT;
- } else if (prec == -1)
- prec = DEFPREC;
- /* __cvt_double may have to round up before the
- "start" of its buffer, i.e.
- ``intf("%.2f", (double)9.999);'';
- if the first character is still NUL, it did.
- softsign avoids negative 0 if _double < 0 but
- no significant digits will be shown. */
- cp = buf;
- *cp = '\0';
- size = __cvt_double(_double, prec, flags, &softsign,
- ch, cp, buf + sizeof(buf));
- if (softsign)
- sign = '-';
- if (*cp == '\0')
- cp++;
- break;
-#endif
-#endif /* FLOATING_POINT */
- case 'n':
- if (flags & LONGINT)
- *va_arg(ap, long *) = ret;
- else if (flags & SHORTINT)
- *va_arg(ap, short *) = ret;
- else
- *va_arg(ap, int *) = ret;
- continue; /* no output */
- case 'O':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'o':
- _ulong = UARG();
- base = OCT;
- goto nosign;
- case 'p':
- /*
- * ``The argument shall be a pointer to void. The
- * value of the pointer is converted to a sequence
- * of printable characters, in an implementation-
- * defined manner.''
- * -- ANSI X3J11
- */
- /* NOSTRICT */
- _ulong = (unsigned long)va_arg(ap, void *);
- base = HEX;
- flags |= HEXPREFIX;
- ch = 'x';
- goto nosign;
- case 's':
- if ((cp = va_arg(ap, char *)) == NULL)
- cp = "(null)";
- if (prec >= 0) {
- /*
- * can't use strlen; can only look for the
- * NUL in the first `prec' characters, and
- * strlen() will go further.
- */
- char *p = (char*)memchr(cp, 0, prec);
-
- if (p != NULL) {
- size = p - cp;
- if (size > prec)
- size = prec;
- } else
- size = prec;
- } else
- size = strlen(cp);
- sign = '\0';
- break;
- case 'U':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'u':
- _ulong = UARG();
- base = DEC;
- goto nosign;
- case 'X':
- case 'x':
- _ulong = UARG();
- base = HEX;
- /* leading 0x/X only if non-zero */
- if (flags & ALT && _ulong != 0)
- flags |= HEXPREFIX;
-
- /* unsigned conversions */
-nosign: sign = '\0';
- /*
- * ``... diouXx conversions ... if a precision is
- * specified, the 0 flag will be ignored.''
- * -- ANSI X3J11
- */
-number: if ((dprec = prec) >= 0)
- flags &= ~ZEROPAD;
-
- /*
- * ``The result of converting a zero value with an
- * explicit precision of zero is no characters.''
- * -- ANSI X3J11
- */
- cp = buf + BUF;
- if (_ulong != 0 || prec != 0) {
- char *xdigs; /* digits for [xX] conversion */
- /*
- * unsigned mod is hard, and unsigned mod
- * by a constant is easier than that by
- * a variable; hence this switch.
- */
- switch (base) {
- case OCT:
- do {
- *--cp = to_char(_ulong & 7);
- _ulong >>= 3;
- } while (_ulong);
- /* handle octal leading 0 */
- if (flags & ALT && *cp != '0')
- *--cp = '0';
- break;
-
- case DEC:
- /* many numbers are 1 digit */
- while (_ulong >= 10) {
- *--cp = to_char(_ulong % 10);
- _ulong /= 10;
- }
- *--cp = to_char(_ulong);
- break;
-
- case HEX:
- if (ch == 'X')
- xdigs = "0123456789ABCDEF";
- else /* ch == 'x' || ch == 'p' */
- xdigs = "0123456789abcdef";
- do {
- *--cp = xdigs[_ulong & 15];
- _ulong >>= 4;
- } while (_ulong);
- break;
-
- default:
- cp = "bug in vform: bad base";
- goto skipsize;
- }
- }
- size = buf + BUF - cp;
- skipsize:
- break;
- default: /* "%?" prints ?, unless ? is NUL */
- if (ch == '\0')
- goto done;
- /* pretend it was %c with argument ch */
- cp = buf;
- *cp = ch;
- size = 1;
- sign = '\0';
- break;
- }
-
- /*
- * All reasonable formats wind up here. At this point,
- * `cp' points to a string which (if not flags&LADJUST)
- * should be padded out to `width' places. If
- * flags&ZEROPAD, it should first be prefixed by any
- * sign or other prefix; otherwise, it should be blank
- * padded before the prefix is emitted. After any
- * left-hand padding and prefixing, emit zeroes
- * required by a decimal [diouxX] precision, then print
- * the string proper, then emit zeroes required by any
- * leftover floating precision; finally, if LADJUST,
- * pad with blanks.
- */
-
- /*
- * compute actual size, so we know how much to pad.
- */
-#if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
- fieldsz = size + fpprec;
-#else
- fieldsz = size;
-#endif
- dpad = dprec - size;
- if (dpad < 0)
- dpad = 0;
-
- if (sign)
- fieldsz++;
- else if (flags & HEXPREFIX)
- fieldsz += 2;
- fieldsz += dpad;
-
- /* right-adjusting blank padding */
- if ((flags & (LADJUST|ZEROPAD)) == 0)
- PAD_SP(width - fieldsz);
-
- /* prefix */
- if (sign) {
- PRINT(&sign, 1);
- } else if (flags & HEXPREFIX) {
- ox[0] = '0';
- ox[1] = ch;
- PRINT(ox, 2);
- }
-
- /* right-adjusting zero padding */
- if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
- PAD_0(width - fieldsz);
-
- /* leading zeroes from decimal precision */
- PAD_0(dpad);
-
- /* the string or number proper */
- PRINT(cp, size);
-
-#if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
- /* trailing f.p. zeroes */
- PAD_0(fpprec);
-#endif
-
- /* left-adjusting padding (always blank) */
- if (flags & LADJUST)
- PAD_SP(width - fieldsz);
-
- /* finally, adjust ret */
- ret += width > fieldsz ? width : fieldsz;
-
- }
-done:
- return ret;
-error:
- return EOF;
- /* NOTREACHED */
-}
-
-#if defined(FLOATING_POINT) && !defined(_IO_USE_DTOA)
-
-static char *exponent(register char *p, register int exp, int fmtch)
-{
- register char *t;
- char expbuf[MAXEXP];
-
- *p++ = fmtch;
- if (exp < 0) {
- exp = -exp;
- *p++ = '-';
- }
- else
- *p++ = '+';
- t = expbuf + MAXEXP;
- if (exp > 9) {
- do {
- *--t = to_char(exp % 10);
- } while ((exp /= 10) > 9);
- *--t = to_char(exp);
- for (; t < expbuf + MAXEXP; *p++ = *t++);
- }
- else {
- *p++ = '0';
- *p++ = to_char(exp);
- }
- return (p);
-}
-
-static char * round(double fract, int *exp,
- register char *start, register char *end,
- char ch, int *signp)
-{
- double tmp;
-
- if (fract)
- (void)modf(fract * 10, &tmp);
- else
- tmp = to_digit(ch);
- if (tmp > 4)
- for (;; --end) {
- if (*end == '.')
- --end;
- if (++*end <= '9')
- break;
- *end = '0';
- if (end == start) {
- if (exp) { /* e/E; increment exponent */
- *end = '1';
- ++*exp;
- }
- else { /* f; add extra digit */
- *--end = '1';
- --start;
- }
- break;
- }
- }
- /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
- else if (*signp == '-')
- for (;; --end) {
- if (*end == '.')
- --end;
- if (*end != '0')
- break;
- if (end == start)
- *signp = 0;
- }
- return (start);
-}
-
-int __cvt_double(double number, register int prec, int flags, int *signp,
- int fmtch, char *startp, char *endp)
-{
- register char *p, *t;
- register double fract;
- int dotrim = 0, expcnt, gformat = 0;
- double integer, tmp;
-
- expcnt = 0;
- if (number < 0) {
- number = -number;
- *signp = '-';
- } else
- *signp = 0;
-
- fract = modf(number, &integer);
-
- /* get an extra slot for rounding. */
- t = ++startp;
-
- /*
- * get integer portion of number; put into the end of the buffer; the
- * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
- */
- for (p = endp - 1; p >= startp && integer; ++expcnt) {
- tmp = modf(integer / 10, &integer);
- *p-- = to_char((int)((tmp + .01) * 10));
- }
- switch (fmtch) {
- case 'f':
- case 'F':
- /* reverse integer into beginning of buffer */
- if (expcnt)
- for (; ++p < endp; *t++ = *p);
- else
- *t++ = '0';
- /*
- * if precision required or alternate flag set, add in a
- * decimal point.
- */
- if (prec || flags&ALT)
- *t++ = '.';
- /* if requires more precision and some fraction left */
- if (fract) {
- if (prec)
- do {
- fract = modf(fract * 10, &tmp);
- *t++ = to_char((int)tmp);
- } while (--prec && fract);
- if (fract)
- startp = round(fract, (int *)NULL, startp,
- t - 1, (char)0, signp);
- }
- for (; prec--; *t++ = '0');
- break;
- case 'e':
- case 'E':
-eformat: if (expcnt) {
- *t++ = *++p;
- if (prec || flags&ALT)
- *t++ = '.';
- /* if requires more precision and some integer left */
- for (; prec && ++p < endp; --prec)
- *t++ = *p;
- /*
- * if done precision and more of the integer component,
- * round using it; adjust fract so we don't re-round
- * later.
- */
- if (!prec && ++p < endp) {
- fract = 0;
- startp = round((double)0, &expcnt, startp,
- t - 1, *p, signp);
- }
- /* adjust expcnt for digit in front of decimal */
- --expcnt;
- }
- /* until first fractional digit, decrement exponent */
- else if (fract) {
- /* adjust expcnt for digit in front of decimal */
- for (expcnt = -1;; --expcnt) {
- fract = modf(fract * 10, &tmp);
- if (tmp)
- break;
- }
- *t++ = to_char((int)tmp);
- if (prec || flags&ALT)
- *t++ = '.';
- }
- else {
- *t++ = '0';
- if (prec || flags&ALT)
- *t++ = '.';
- }
- /* if requires more precision and some fraction left */
- if (fract) {
- if (prec)
- do {
- fract = modf(fract * 10, &tmp);
- *t++ = to_char((int)tmp);
- } while (--prec && fract);
- if (fract)
- startp = round(fract, &expcnt, startp,
- t - 1, (char)0, signp);
- }
- /* if requires more precision */
- for (; prec--; *t++ = '0');
-
- /* unless alternate flag, trim any g/G format trailing 0's */
- if (gformat && !(flags&ALT)) {
- while (t > startp && *--t == '0');
- if (*t == '.')
- --t;
- ++t;
- }
- t = exponent(t, expcnt, fmtch);
- break;
- case 'g':
- case 'G':
- /* a precision of 0 is treated as a precision of 1. */
- if (!prec)
- ++prec;
- /*
- * ``The style used depends on the value converted; style e
- * will be used only if the exponent resulting from the
- * conversion is less than -4 or greater than the precision.''
- * -- ANSI X3J11
- */
- if (expcnt > prec || (!expcnt && fract && fract < .0001)) {
- /*
- * g/G format counts "significant digits, not digits of
- * precision; for the e/E format, this just causes an
- * off-by-one problem, i.e. g/G considers the digit
- * before the decimal point significant and e/E doesn't
- * count it as precision.
- */
- --prec;
- fmtch -= 2; /* G->E, g->e */
- gformat = 1;
- goto eformat;
- }
- /*
- * reverse integer into beginning of buffer,
- * note, decrement precision
- */
- if (expcnt)
- for (; ++p < endp; *t++ = *p, --prec);
- else
- *t++ = '0';
- /*
- * if precision required or alternate flag set, add in a
- * decimal point. If no digits yet, add in leading 0.
- */
- if (prec || flags&ALT) {
- dotrim = 1;
- *t++ = '.';
- }
- else
- dotrim = 0;
- /* if requires more precision and some fraction left */
- if (fract) {
- if (prec) {
- /* If no integer part, don't count initial
- * zeros as significant digits. */
- do {
- fract = modf(fract * 10, &tmp);
- *t++ = to_char((int)tmp);
- } while(!tmp && !expcnt);
- while (--prec && fract) {
- fract = modf(fract * 10, &tmp);
- *t++ = to_char((int)tmp);
- }
- }
- if (fract)
- startp = round(fract, (int *)NULL, startp,
- t - 1, (char)0, signp);
- }
- /* alternate format, adds 0's for precision, else trim 0's */
- if (flags&ALT)
- for (; prec--; *t++ = '0');
- else if (dotrim) {
- while (t > startp && *--t == '0');
- if (*t != '.')
- ++t;
- }
- }
- return (t - startp);
-}
-
-#endif /* defined(FLOATING_POINT) && !defined(_IO_USE_DTOA) */
OpenPOWER on IntegriCloud