Date: Thu, 15 Jan 2009 04:49:43 +0000 (UTC) From: David Schultz <das@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r187284 - head/lib/libc/stdio Message-ID: <200901150449.n0F4nhlF064834@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: das Date: Thu Jan 15 04:49:43 2009 New Revision: 187284 URL: http://svn.freebsd.org/changeset/base/187284 Log: Reduce code duplication by moving functions that are identical in both vfprintf.c and vfwprintf.c (except for char/wchar_t differences) to a common header file. Modified: head/lib/libc/stdio/printfcommon.h head/lib/libc/stdio/vfprintf.c head/lib/libc/stdio/vfwprintf.c Modified: head/lib/libc/stdio/printfcommon.h ============================================================================== --- head/lib/libc/stdio/printfcommon.h Thu Jan 15 04:49:40 2009 (r187283) +++ head/lib/libc/stdio/printfcommon.h Thu Jan 15 04:49:43 2009 (r187284) @@ -37,6 +37,28 @@ * You must define CHAR to either char or wchar_t prior to including this. */ + +#ifndef NO_FLOATING_POINT + +#define dtoa __dtoa +#define freedtoa __freedtoa + +#include <float.h> +#include <math.h> +#include "floatio.h" +#include "gdtoa.h" + +#define DEFPREC 6 + +static int exponent(CHAR *, int, CHAR); + +#endif /* !NO_FLOATING_POINT */ + +static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *, int, char, + const char *); +static CHAR *__ultoa(u_long, CHAR *, int, int, const char *, int, char, + const char *); + #define NIOV 8 struct io_state { FILE *fp; @@ -128,3 +150,197 @@ io_flush(struct io_state *iop) iop->iovp = iop->iov; return (__sprint(iop->fp, &iop->uio)); } + +/* + * Convert an unsigned long to ASCII for printf purposes, returning + * a pointer to the first character of the string representation. + * Octal numbers can be forced to have a leading zero; hex numbers + * use the given digits. + */ +static CHAR * +__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs, + int needgrp, char thousep, const char *grp) +{ + CHAR *cp = endp; + long sval; + int ndig; + + /* + * Handle the three cases separately, in the hope of getting + * better/faster code. + */ + switch (base) { + case 10: + if (val < 10) { /* many numbers are 1 digit */ + *--cp = to_char(val); + return (cp); + } + ndig = 0; + /* + * On many machines, unsigned arithmetic is harder than + * signed arithmetic, so we do at most one unsigned mod and + * divide; this is sufficient to reduce the range of + * the incoming value to where signed arithmetic works. + */ + if (val > LONG_MAX) { + *--cp = to_char(val % 10); + ndig++; + sval = val / 10; + } else + sval = val; + do { + *--cp = to_char(sval % 10); + ndig++; + /* + * If (*grp == CHAR_MAX) then no more grouping + * should be performed. + */ + if (needgrp && ndig == *grp && *grp != CHAR_MAX + && sval > 9) { + *--cp = thousep; + ndig = 0; + /* + * If (*(grp+1) == '\0') then we have to + * use *grp character (last grouping rule) + * for all next cases + */ + if (*(grp+1) != '\0') + grp++; + } + sval /= 10; + } while (sval != 0); + break; + + case 8: + do { + *--cp = to_char(val & 7); + val >>= 3; + } while (val); + if (octzero && *cp != '0') + *--cp = '0'; + break; + + case 16: + do { + *--cp = xdigs[val & 15]; + val >>= 4; + } while (val); + break; + + default: /* oops */ + abort(); + } + return (cp); +} + +/* Identical to __ultoa, but for intmax_t. */ +static CHAR * +__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs, + int needgrp, char thousep, const char *grp) +{ + CHAR *cp = endp; + intmax_t sval; + int ndig; + + /* quick test for small values; __ultoa is typically much faster */ + /* (perhaps instead we should run until small, then call __ultoa?) */ + if (val <= ULONG_MAX) + return (__ultoa((u_long)val, endp, base, octzero, xdigs, + needgrp, thousep, grp)); + switch (base) { + case 10: + if (val < 10) { + *--cp = to_char(val % 10); + return (cp); + } + ndig = 0; + if (val > INTMAX_MAX) { + *--cp = to_char(val % 10); + ndig++; + sval = val / 10; + } else + sval = val; + do { + *--cp = to_char(sval % 10); + ndig++; + /* + * If (*grp == CHAR_MAX) then no more grouping + * should be performed. + */ + if (needgrp && *grp != CHAR_MAX && ndig == *grp + && sval > 9) { + *--cp = thousep; + ndig = 0; + /* + * If (*(grp+1) == '\0') then we have to + * use *grp character (last grouping rule) + * for all next cases + */ + if (*(grp+1) != '\0') + grp++; + } + sval /= 10; + } while (sval != 0); + break; + + case 8: + do { + *--cp = to_char(val & 7); + val >>= 3; + } while (val); + if (octzero && *cp != '0') + *--cp = '0'; + break; + + case 16: + do { + *--cp = xdigs[val & 15]; + val >>= 4; + } while (val); + break; + + default: + abort(); + } + 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 */ Modified: head/lib/libc/stdio/vfprintf.c ============================================================================== --- head/lib/libc/stdio/vfprintf.c Thu Jan 15 04:49:40 2009 (r187283) +++ head/lib/libc/stdio/vfprintf.c Thu Jan 15 04:49:43 2009 (r187284) @@ -66,10 +66,6 @@ __FBSDID("$FreeBSD$"); static int __sprint(FILE *, struct __suio *); static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0); -static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char, - const char *); -static char *__ultoa(u_long, char *, int, int, const char *, int, char, - const char *); static char *__wcsconv(wchar_t *, int); #define CHAR char @@ -129,160 +125,6 @@ __sbprintf(FILE *fp, const char *fmt, va } /* - * Convert an unsigned long to ASCII for printf purposes, returning - * a pointer to the first character of the string representation. - * Octal numbers can be forced to have a leading zero; hex numbers - * use the given digits. - */ -static char * -__ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs, - int needgrp, char thousep, const char *grp) -{ - char *cp = endp; - long sval; - int ndig; - - /* - * Handle the three cases separately, in the hope of getting - * better/faster code. - */ - switch (base) { - case 10: - if (val < 10) { /* many numbers are 1 digit */ - *--cp = to_char(val); - return (cp); - } - ndig = 0; - /* - * On many machines, unsigned arithmetic is harder than - * signed arithmetic, so we do at most one unsigned mod and - * divide; this is sufficient to reduce the range of - * the incoming value to where signed arithmetic works. - */ - if (val > LONG_MAX) { - *--cp = to_char(val % 10); - ndig++; - sval = val / 10; - } else - sval = val; - do { - *--cp = to_char(sval % 10); - ndig++; - /* - * If (*grp == CHAR_MAX) then no more grouping - * should be performed. - */ - if (needgrp && ndig == *grp && *grp != CHAR_MAX - && sval > 9) { - *--cp = thousep; - ndig = 0; - /* - * If (*(grp+1) == '\0') then we have to - * use *grp character (last grouping rule) - * for all next cases - */ - if (*(grp+1) != '\0') - grp++; - } - sval /= 10; - } while (sval != 0); - break; - - case 8: - do { - *--cp = to_char(val & 7); - val >>= 3; - } while (val); - if (octzero && *cp != '0') - *--cp = '0'; - break; - - case 16: - do { - *--cp = xdigs[val & 15]; - val >>= 4; - } while (val); - break; - - default: /* oops */ - abort(); - } - return (cp); -} - -/* Identical to __ultoa, but for intmax_t. */ -static char * -__ujtoa(uintmax_t val, char *endp, int base, int octzero, const char *xdigs, - int needgrp, char thousep, const char *grp) -{ - char *cp = endp; - intmax_t sval; - int ndig; - - /* quick test for small values; __ultoa is typically much faster */ - /* (perhaps instead we should run until small, then call __ultoa?) */ - if (val <= ULONG_MAX) - return (__ultoa((u_long)val, endp, base, octzero, xdigs, - needgrp, thousep, grp)); - switch (base) { - case 10: - if (val < 10) { - *--cp = to_char(val % 10); - return (cp); - } - ndig = 0; - if (val > INTMAX_MAX) { - *--cp = to_char(val % 10); - ndig++; - sval = val / 10; - } else - sval = val; - do { - *--cp = to_char(sval % 10); - ndig++; - /* - * If (*grp == CHAR_MAX) then no more grouping - * should be performed. - */ - if (needgrp && *grp != CHAR_MAX && ndig == *grp - && sval > 9) { - *--cp = thousep; - ndig = 0; - /* - * If (*(grp+1) == '\0') then we have to - * use *grp character (last grouping rule) - * for all next cases - */ - if (*(grp+1) != '\0') - grp++; - } - sval /= 10; - } while (sval != 0); - break; - - case 8: - do { - *--cp = to_char(val & 7); - val >>= 3; - } while (val); - if (octzero && *cp != '0') - *--cp = '0'; - break; - - case 16: - do { - *--cp = xdigs[val & 15]; - val >>= 4; - } while (val); - break; - - default: - abort(); - } - return (cp); -} - -/* * Convert a wide character string argument for the %ls format to a multibyte * string representation. If not -1, prec specifies the maximum number of * bytes to output, and also means that we can't assume that the wide char. @@ -356,22 +198,6 @@ vfprintf(FILE * __restrict fp, const cha return (ret); } -#ifndef NO_FLOATING_POINT - -#define dtoa __dtoa -#define freedtoa __freedtoa - -#include <float.h> -#include <math.h> -#include "floatio.h" -#include "gdtoa.h" - -#define DEFPREC 6 - -static int exponent(char *, int, int); - -#endif /* !NO_FLOATING_POINT */ - /* * The size of the buffer we use as scratch space for integer * conversions, among other things. Technically, we would need the @@ -1159,42 +985,3 @@ error: /* NOTREACHED */ } - -#ifndef NO_FLOATING_POINT - -static int -exponent(char *p0, int exp, int 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 */ Modified: head/lib/libc/stdio/vfwprintf.c ============================================================================== --- head/lib/libc/stdio/vfwprintf.c Thu Jan 15 04:49:40 2009 (r187283) +++ head/lib/libc/stdio/vfwprintf.c Thu Jan 15 04:49:43 2009 (r187284) @@ -69,10 +69,6 @@ __FBSDID("$FreeBSD$"); static int __sprint(FILE *, struct __suio *); static int __sbprintf(FILE *, const wchar_t *, va_list); static wint_t __xfputwc(wchar_t, FILE *); -static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const char *, int, - char, const char *); -static wchar_t *__ultoa(u_long, wchar_t *, int, int, const char *, int, - char, const char *); static wchar_t *__mbsconv(char *, int); #define CHAR wchar_t @@ -171,160 +167,6 @@ __xfputwc(wchar_t wc, FILE *fp) } /* - * Convert an unsigned long to ASCII for printf purposes, returning - * a pointer to the first character of the string representation. - * Octal numbers can be forced to have a leading zero; hex numbers - * use the given digits. - */ -static wchar_t * -__ultoa(u_long val, wchar_t *endp, int base, int octzero, const char *xdigs, - int needgrp, char thousep, const char *grp) -{ - wchar_t *cp = endp; - long sval; - int ndig; - - /* - * Handle the three cases separately, in the hope of getting - * better/faster code. - */ - switch (base) { - case 10: - if (val < 10) { /* many numbers are 1 digit */ - *--cp = to_char(val); - return (cp); - } - ndig = 0; - /* - * On many machines, unsigned arithmetic is harder than - * signed arithmetic, so we do at most one unsigned mod and - * divide; this is sufficient to reduce the range of - * the incoming value to where signed arithmetic works. - */ - if (val > LONG_MAX) { - *--cp = to_char(val % 10); - ndig++; - sval = val / 10; - } else - sval = val; - do { - *--cp = to_char(sval % 10); - ndig++; - /* - * If (*grp == CHAR_MAX) then no more grouping - * should be performed. - */ - if (needgrp && ndig == *grp && *grp != CHAR_MAX - && sval > 9) { - *--cp = thousep; - ndig = 0; - /* - * If (*(grp+1) == '\0') then we have to - * use *grp character (last grouping rule) - * for all next cases - */ - if (*(grp+1) != '\0') - grp++; - } - sval /= 10; - } while (sval != 0); - break; - - case 8: - do { - *--cp = to_char(val & 7); - val >>= 3; - } while (val); - if (octzero && *cp != '0') - *--cp = '0'; - break; - - case 16: - do { - *--cp = xdigs[val & 15]; - val >>= 4; - } while (val); - break; - - default: /* oops */ - abort(); - } - return (cp); -} - -/* Identical to __ultoa, but for intmax_t. */ -static wchar_t * -__ujtoa(uintmax_t val, wchar_t *endp, int base, int octzero, - const char *xdigs, int needgrp, char thousep, const char *grp) -{ - wchar_t *cp = endp; - intmax_t sval; - int ndig; - - /* quick test for small values; __ultoa is typically much faster */ - /* (perhaps instead we should run until small, then call __ultoa?) */ - if (val <= ULONG_MAX) - return (__ultoa((u_long)val, endp, base, octzero, xdigs, - needgrp, thousep, grp)); - switch (base) { - case 10: - if (val < 10) { - *--cp = to_char(val % 10); - return (cp); - } - ndig = 0; - if (val > INTMAX_MAX) { - *--cp = to_char(val % 10); - ndig++; - sval = val / 10; - } else - sval = val; - do { - *--cp = to_char(sval % 10); - ndig++; - /* - * If (*grp == CHAR_MAX) then no more grouping - * should be performed. - */ - if (needgrp && *grp != CHAR_MAX && ndig == *grp - && sval > 9) { - *--cp = thousep; - ndig = 0; - /* - * If (*(grp+1) == '\0') then we have to - * use *grp character (last grouping rule) - * for all next cases - */ - if (*(grp+1) != '\0') - grp++; - } - sval /= 10; - } while (sval != 0); - break; - - case 8: - do { - *--cp = to_char(val & 7); - val >>= 3; - } while (val); - if (octzero && *cp != '0') - *--cp = '0'; - break; - - case 16: - do { - *--cp = xdigs[val & 15]; - val >>= 4; - } while (val); - break; - - default: - abort(); - } - return (cp); -} - -/* * Convert a multibyte character string argument for the %s format to a wide * string representation. ``prec'' specifies the maximum number of bytes * to output. If ``prec'' is greater than or equal to zero, we can't assume @@ -413,22 +255,6 @@ vfwprintf(FILE * __restrict fp, const wc return (ret); } -#ifndef NO_FLOATING_POINT - -#define dtoa __dtoa -#define freedtoa __freedtoa - -#include <float.h> -#include <math.h> -#include "floatio.h" -#include "gdtoa.h" - -#define DEFPREC 6 - -static int exponent(wchar_t *, int, wchar_t); - -#endif /* !NO_FLOATING_POINT */ - /* * The size of the buffer we use as scratch space for integer * conversions, among other things. Technically, we would need the @@ -1206,43 +1032,3 @@ error: return (ret); /* NOTREACHED */ } - - -#ifndef NO_FLOATING_POINT - -static int -exponent(wchar_t *p0, int exp, wchar_t fmtch) -{ - wchar_t *p, *t; - wchar_t 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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901150449.n0F4nhlF064834>