]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib/printf: use system printf for floats
authorDavid Lamparter <equinox@diac24.net>
Sun, 12 May 2019 19:14:12 +0000 (21:14 +0200)
committerDavid Lamparter <equinox@diac24.net>
Mon, 3 Jun 2019 14:44:18 +0000 (16:44 +0200)
We're not libc, we can just fall back to snprintf() to avoid all this
low-level float mangling.

Signed-off-by: David Lamparter <equinox@diac24.net>
lib/printf/printfcommon.h
lib/printf/vfprintf.c

index 68454bce1e737c851ecb85cb7d1b1e2db89c5f10..716177c57ddc9cc161e71d4a27756b591c4924d0 100644 (file)
  */
 
 
-#ifndef NO_FLOATING_POINT
-
-#define        dtoa            __dtoa
-#define        freedtoa        __freedtoa
-
-#include <float.h>
-#include <math.h>
-
-#define        DEFPREC         6
-
-static int exponent(CHAR *, int, CHAR);
-
-#endif /* !NO_FLOATING_POINT */
-
 static CHAR    *__ujtoa(uintmax_t, CHAR *, int, int, const char *);
 static CHAR    *__ultoa(u_long, CHAR *, int, int, const char *);
 
@@ -254,43 +240,3 @@ __ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
        }
        return (cp);
 }
-
-#ifndef NO_FLOATING_POINT
-
-static int
-exponent(CHAR *p0, int exp, CHAR fmtch)
-{
-       CHAR *p, *t;
-       CHAR expbuf[MAXEXPDIG];
-
-       p = p0;
-       *p++ = fmtch;
-       if (exp < 0) {
-               exp = -exp;
-               *p++ = '-';
-       }
-       else
-               *p++ = '+';
-       t = expbuf + MAXEXPDIG;
-       if (exp > 9) {
-               do {
-                       *--t = to_char(exp % 10);
-               } while ((exp /= 10) > 9);
-               *--t = to_char(exp);
-               for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
-       }
-       else {
-               /*
-                * Exponents for decimal floating point conversions
-                * (%[eEgG]) must be at least two characters long,
-                * whereas exponents for hexadecimal conversions can
-                * be only one character long.
-                */
-               if (fmtch == 'e' || fmtch == 'E')
-                       *p++ = '0';
-               *p++ = to_char(exp);
-       }
-       return (p - p0);
-}
-
-#endif /* !NO_FLOATING_POINT */
index 69b9e2da9f45ff6a5f356f83afda198aa460321f..58412a48ceb56fc6a42eb9f55cd06b02a57a995a 100644 (file)
@@ -143,7 +143,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
  * write a uintmax_t in octal (plus one byte).
  */
 #if UINTMAX_MAX <= UINT64_MAX
-#define        BUF     32
+#define        BUF     64
 #else
 #error "BUF must be large enough to format a uintmax_t"
 #endif
@@ -165,36 +165,6 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
        int saved_errno;
        char sign;              /* sign prefix (' ', '+', '-', or \0) */
 
-#ifndef NO_FLOATING_POINT
-       /*
-        * We can decompose the printed representation of floating
-        * point numbers into several parts, some of which may be empty:
-        *
-        * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
-        *    A       B     ---C---      D       E   F
-        *
-        * A:   'sign' holds this value if present; '\0' otherwise
-        * B:   ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
-        * C:   cp points to the string MMMNNN.  Leading and trailing
-        *      zeros are not in the string and must be added.
-        * D:   expchar holds this character; '\0' if no exponent, e.g. %f
-        * F:   at least two digits for decimal, at least one digit for hex
-        */
-       char *decimal_point;    /* locale specific decimal point */
-       int decpt_len;          /* length of decimal_point */
-       int signflag;           /* true if float is negative */
-       union {                 /* floating point arguments %[aAeEfFgG] */
-               double dbl;
-               long double ldbl;
-       } fparg;
-       int expt;               /* integer value of exponent */
-       char expchar;           /* exponent character: [eEpP\0] */
-       char *dtoaend;          /* pointer to end of converted digits */
-       int expsize;            /* character count for expstr */
-       int ndig;               /* actual number of digits returned by dtoa */
-       char expstr[MAXEXPDIG+2];       /* buffer for exponent string: e+ZZZ */
-       char *dtoaresult;       /* buffer allocated by dtoa */
-#endif
        u_long  ulval;          /* integer arguments %[diouxX] */
        uintmax_t ujval;        /* %j, %ll, %q, %t, %z integers */
        int base;               /* base for [diouxX] conversion */
@@ -305,12 +275,6 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
        va_copy(orgap, ap);
        io_init(&io, fp);
        ret = 0;
-#ifndef NO_FLOATING_POINT
-       dtoaresult = NULL;
-       decimal_point = ".";
-       /* The overwhelmingly common case is decpt_len == 1. */
-       decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
-#endif
 
        /*
         * Scan the format for conversions (`%' character).
@@ -489,121 +453,39 @@ reswitch:        switch (ch) {
 #ifndef NO_FLOATING_POINT
                case 'a':
                case 'A':
-                       if (ch == 'a') {
-                               ox[1] = 'x';
-                               xdigs = xdigs_lower;
-                               expchar = 'p';
-                       } else {
-                               ox[1] = 'X';
-                               xdigs = xdigs_upper;
-                               expchar = 'P';
-                       }
-                       if (prec >= 0)
-                               prec++;
-                       if (dtoaresult != NULL)
-                               freedtoa(dtoaresult);
-                       if (flags & LONGDBL) {
-                               fparg.ldbl = GETARG(long double);
-                               dtoaresult = cp =
-                                   __hldtoa(fparg.ldbl, xdigs, prec,
-                                   &expt, &signflag, &dtoaend);
-                       } else {
-                               fparg.dbl = GETARG(double);
-                               dtoaresult = cp =
-                                   __hdtoa(fparg.dbl, xdigs, prec,
-                                   &expt, &signflag, &dtoaend);
-                       }
-                       if (prec < 0)
-                               prec = dtoaend - cp;
-                       if (expt == INT_MAX)
-                               ox[1] = '\0';
-                       goto fp_common;
                case 'e':
                case 'E':
-                       expchar = ch;
-                       if (prec < 0)   /* account for digit before decpt */
-                               prec = DEFPREC + 1;
-                       else
-                               prec++;
-                       goto fp_begin;
                case 'f':
                case 'F':
-                       expchar = '\0';
-                       goto fp_begin;
                case 'g':
                case 'G':
-                       expchar = ch - ('g' - 'e');
-                       if (prec == 0)
-                               prec = 1;
-fp_begin:
-                       if (prec < 0)
-                               prec = DEFPREC;
-                       if (dtoaresult != NULL)
-                               freedtoa(dtoaresult);
                        if (flags & LONGDBL) {
-                               fparg.ldbl = GETARG(long double);
-                               dtoaresult = cp =
-                                   __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
-                                   &expt, &signflag, &dtoaend);
+                               long double arg = GETARG(long double);
+                               char fmt[6] = "%.*L";
+                               fmt[4] = ch;
+                               fmt[5] = '\0';
+
+                               snprintf(buf, sizeof(buf), fmt, prec, arg);
                        } else {
-                               fparg.dbl = GETARG(double);
-                               dtoaresult = cp =
-                                   dtoa(fparg.dbl, expchar ? 2 : 3, prec,
-                                   &expt, &signflag, &dtoaend);
-                               if (expt == 9999)
-                                       expt = INT_MAX;
+                               double arg = GETARG(double);
+                               char fmt[5] = "%.*";
+                               fmt[3] = ch;
+                               fmt[4] = '\0';
+
+                               snprintf(buf, sizeof(buf), fmt, prec, arg);
                        }
-fp_common:
-                       if (signflag)
+                       cp = buf;
+                       /* for proper padding */
+                       if (*cp == '-') {
+                               cp++;
                                sign = '-';
-                       if (expt == INT_MAX) {  /* inf or nan */
-                               if (*cp == 'N') {
-                                       cp = (ch >= 'a') ? "nan" : "NAN";
-                                       sign = '\0';
-                               } else
-                                       cp = (ch >= 'a') ? "inf" : "INF";
-                               size = 3;
-                               flags &= ~ZEROPAD;
-                               break;
-                       }
-                       flags |= FPT;
-                       ndig = dtoaend - cp;
-                       if (ch == 'g' || ch == 'G') {
-                               if (expt > -4 && expt <= prec) {
-                                       /* Make %[gG] smell like %[fF] */
-                                       expchar = '\0';
-                                       if (flags & ALT)
-                                               prec -= expt;
-                                       else
-                                               prec = ndig - expt;
-                                       if (prec < 0)
-                                               prec = 0;
-                               } else {
-                                       /*
-                                        * Make %[gG] smell like %[eE], but
-                                        * trim trailing zeroes if no # flag.
-                                        */
-                                       if (!(flags & ALT))
-                                               prec = ndig;
-                               }
-                       }
-                       if (expchar) {
-                               expsize = exponent(expstr, expt - 1, expchar);
-                               size = expsize + prec;
-                               if (prec > 1 || flags & ALT)
-                                       size += decpt_len;
-                       } else {
-                               /* space for digits before decimal point */
-                               if (expt > 0)
-                                       size = expt;
-                               else    /* "0" */
-                                       size = 1;
-                               /* space for decimal pt and following digits */
-                               if (prec || flags & ALT)
-                                       size += prec + decpt_len;
                        }
+                       /* "inf" */
+                       if (!is_digit(*cp) && *cp != '.')
+                               flags &= ~ZEROPAD;
+                       size = strlen(buf);
                        break;
-#endif /* !NO_FLOATING_POINT */
+#endif
                case 'm':
                        cp = strerror(saved_errno);
                        size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
@@ -797,41 +679,9 @@ number:                    if ((dprec = prec) >= 0)
                        PAD(width - realsz, zeroes);
 
                /* the string or number proper */
-#ifndef NO_FLOATING_POINT
-               if ((flags & FPT) == 0) {
-#endif
-                       /* leading zeroes from decimal precision */
-                       PAD(dprec - size, zeroes);
-                       PRINT(cp, size);
-#ifndef NO_FLOATING_POINT
-               } else {        /* glue together f_p fragments */
-                       if (!expchar) { /* %[fF] or sufficiently short %[gG] */
-                               if (expt <= 0) {
-                                       PRINT(zeroes, 1);
-                                       if (prec || flags & ALT)
-                                               PRINT(decimal_point,decpt_len);
-                                       PAD(-expt, zeroes);
-                                       /* already handled initial 0's */
-                                       prec += expt;
-                               } else {
-                                       PRINTANDPAD(cp, dtoaend, expt, zeroes);
-                                       cp += expt;
-                                       if (prec || flags & ALT)
-                                               PRINT(decimal_point,decpt_len);
-                               }
-                               PRINTANDPAD(cp, dtoaend, prec, zeroes);
-                       } else {        /* %[eE] or sufficiently long %[gG] */
-                               if (prec > 1 || flags & ALT) {
-                                       PRINT(cp++, 1);
-                                       PRINT(decimal_point, decpt_len);
-                                       PRINT(cp, ndig-1);
-                                       PAD(prec - ndig, zeroes);
-                               } else  /* XeYYY */
-                                       PRINT(cp, 1);
-                               PRINT(expstr, expsize);
-                       }
-               }
-#endif
+               /* leading zeroes from decimal precision */
+               PAD(dprec - size, zeroes);
+               PRINT(cp, size);
                /* left-adjusting padding (always blank) */
                if (flags & LADJUST)
                        PAD(width - realsz, blanks);
@@ -845,10 +695,6 @@ done:
        FLUSH();
 error:
        va_end(orgap);
-#ifndef NO_FLOATING_POINT
-       if (dtoaresult != NULL)
-               freedtoa(dtoaresult);
-#endif
        if (convbuf != NULL)
                free(convbuf);
        if ((argtable != NULL) && (argtable != statargtable))