diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2002-03-12 01:18:50 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2002-03-12 01:18:50 +0000 |
commit | 03e039820dc5092e27e81f3671652f25da7f25f1 (patch) | |
tree | 37bddad6951b8a6aa5d75184353705f672217812 /libc/misc/internals | |
parent | ff3e48d94097ed02480bb0df538620b221ccd72f (diff) |
Swap in the new stdio code.
Diffstat (limited to 'libc/misc/internals')
-rw-r--r-- | libc/misc/internals/Makefile | 8 | ||||
-rw-r--r-- | libc/misc/internals/__uClibc_main.c | 18 | ||||
-rw-r--r-- | libc/misc/internals/dtostr.c | 423 | ||||
-rw-r--r-- | libc/misc/internals/lltostr.c | 39 | ||||
-rw-r--r-- | libc/misc/internals/ltostr.c | 39 | ||||
-rw-r--r-- | libc/misc/internals/tempname.c | 37 | ||||
-rw-r--r-- | libc/misc/internals/ulltostr.c | 37 | ||||
-rw-r--r-- | libc/misc/internals/ultostr.c | 37 | ||||
-rw-r--r-- | libc/misc/internals/zoicheck.c | 16 |
9 files changed, 33 insertions, 621 deletions
diff --git a/libc/misc/internals/Makefile b/libc/misc/internals/Makefile index 6e1c2c29d..c35c636ef 100644 --- a/libc/misc/internals/Makefile +++ b/libc/misc/internals/Makefile @@ -24,13 +24,7 @@ TOPDIR=../../../ include $(TOPDIR)Rules.mak -CSRC=ultostr.c ltostr.c __uClibc_main.c tempname.c errno.c __errno_location.c __h_errno_location.c -ifeq ($(HAS_FLOATING_POINT),true) - CSRC += dtostr.c zoicheck.c -endif -ifeq ($(HAS_LONG_LONG),true) - CSRC += ulltostr.c lltostr.c -endif +CSRC=__uClibc_main.c tempname.c errno.c __errno_location.c __h_errno_location.c COBJS=$(patsubst %.c,%.o, $(CSRC)) OBJS=$(COBJS) diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index 7f5e6e805..7c2eaf35c 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -28,13 +28,13 @@ void __uClibc_main(int argc, char **argv, char **envp) #ifdef HAVE_ELF weak_alias(__environ, environ); -extern void weak_function __init_stdio(void); -extern void weak_function __stdio_flush_buffers(void); +extern void weak_function _stdio_init(void); +extern void weak_function _stdio_term(void); extern int *weak_const_function __errno_location (void); extern int *weak_const_function __h_errno_location (void); #else -extern void __init_stdio(void); -extern void __stdio_flush_buffers(void); +extern void _stdio_init(void); +extern void _stdio_term(void); extern int *__errno_location (void); extern int *__h_errno_location (void); #endif @@ -71,8 +71,8 @@ void __uClibc_main(int argc, char **argv, char **envp) * Initialize stdio here. In the static library case, this will * be bypassed if not needed because of the weak alias above. */ - if (__init_stdio) - __init_stdio(); + if (_stdio_init) + _stdio_init(); /* * Note: It is possible that any initialization done above could @@ -95,7 +95,7 @@ void __uClibc_main(int argc, char **argv, char **envp) /* * Define an empty function and use it as a weak alias for the stdio * initialization routine. That way we don't pull in all the stdio - * code unless we need to. Similarly, do the same for __stdio_flush_buffers + * code unless we need to. Similarly, do the same for _stdio_term * so as not to include atexit unnecessarily. * * NOTE!!! This is only true for the _static_ case!!! @@ -106,7 +106,7 @@ weak_alias(__environ, environ); void __uClibc_empty_func(void) { } -weak_alias(__uClibc_empty_func, __init_stdio); -weak_alias(__uClibc_empty_func, __stdio_flush_buffers); +weak_alias(__uClibc_empty_func, _stdio_init); +weak_alias(__uClibc_empty_func, _stdio_term); #endif #endif diff --git a/libc/misc/internals/dtostr.c b/libc/misc/internals/dtostr.c deleted file mode 100644 index 85ec69b12..000000000 --- a/libc/misc/internals/dtostr.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Manuel Novoa III - * - * Function: int __dtostr(FILE * fp, size_t size, long double x, - * char flag[], int width, int preci, char mode) - * - * This was written for uClibc to provide floating point support for - * the printf functions. It handles +/- infinity and nan on i386. - * - * Notes: - * - * At most MAX_DIGITS significant digits are kept. Any trailing digits - * are treated as 0 as they are really just the results of rounding noise - * anyway. If you want to do better, use an arbitary precision arithmetic - * package. ;-) - * - * It should also be fairly portable, as not assumptions are made about the - * bit-layout of doubles. - * - * It should be too difficult to convert this to handle long doubles on i386. - * For information, see the comments below. - * - * TODO: - * long double and/or float version? (note: for float can trim code some). - * - * Decrease the size. This is really much bigger than I'd like. - */ - -/*****************************************************************************/ -/* Don't change anything that follows unless you know what you're doing. */ -/*****************************************************************************/ - -/* - * Configuration for the scaling power table. Ignoring denormals, you - * should have 2**EXP_TABLE_SIZE >= LDBL_MAX_EXP >= 2**(EXP_TABLE_SIZE-1). - * The minimum for standard C is 6. For IEEE 8bit doubles, 9 suffices. - * For long doubles on i386, use 13. - */ -#define EXP_TABLE_SIZE 13 - -/* - * Set this to the maximum number of digits you want converted. - * Conversion is done in blocks of DIGITS_PER_BLOCK (9 by default) digits. - * (20) 17 digits suffices to uniquely determine a (long) double on i386. - */ -#define MAX_DIGITS 20 - -/* - * Set this to the smallest integer type capable of storing a pointer. - */ -#define INT_OR_PTR int - -/* - * This is really only used to check for infinities. The macro produces - * smaller code for i386 and, since this is tested before any floating point - * calculations, it doesn't appear to suffer from the excess precision problem - * caused by the FPU that strtod had. If it causes problems, call the function - * and compile zoicheck.c with -ffloat-store. - */ -#define _zero_or_inf_check(x) ( x == (x/4) ) - -/* - * Fairly portable nan check. Bitwise for i386 generated larger code. - * If you have a better version, comment this out. - */ -#define isnan(x) (x != x) - -/*****************************************************************************/ -/* Don't change anything that follows peroid!!! ;-) */ -/*****************************************************************************/ - -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <float.h> -#include <limits.h> - -extern int fnprintf(FILE * fp, size_t size, const char *fmt, ...); - -/* from printf.c -- should really be in an internal header file */ -enum { - FLAG_PLUS = 0, - FLAG_MINUS_LJUSTIFY, - FLAG_HASH, - FLAG_0_PAD, - FLAG_SPACE, -}; - -/*****************************************************************************/ - -/* - * Set things up for the scaling power table. - */ - -#if EXP_TABLE_SIZE < 6 -#error EXP_TABLE_SIZE should be at least 6 to comply with standards -#endif - -#define EXP_TABLE_MAX (1U<<(EXP_TABLE_SIZE-1)) - -/* - * Only bother checking if this is too small. - */ - -#if LDBL_MAX_10_EXP/2 > EXP_TABLE_MAX -#error larger EXP_TABLE_SIZE needed -#endif - -/* - * With 32 bit ints, we can get 9 digits per block. - */ -#define DIGITS_PER_BLOCK 9 - -#if (INT_MAX >> 30) -#define DIGIT_BLOCK_TYPE int -#define DB_FMT "%.*d" -#elif (LONG_MAX >> 30) -#define DIGIT_BLOCK_TYPE long -#define DB_FMT "%.*ld" -#else -#error need at least 32 bit longs -#endif - -/* Are there actually any machines where this might fail? */ -#if 'A' > 'a' -#error ordering assumption violated : 'A' > 'a' -#endif - -/* Maximum number of calls to fnprintf to output double. */ -#define MAX_CALLS 8 - -/*****************************************************************************/ - -#define NUM_DIGIT_BLOCKS ((MAX_DIGITS+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK) - -/* extra space for '-', '.', 'e+###', and nul */ -#define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK ) -/*****************************************************************************/ - -static const char *fmts[] = { - "%0*d", "%.*s", ".", "inf", "INF", "nan", "NAN", "%*s" -}; - -/*****************************************************************************/ - -int __dtostr(FILE * fp, size_t size, long double x, - char flag[], int width, int preci, char mode) -{ - long double exp_table[EXP_TABLE_SIZE]; - long double p10; - DIGIT_BLOCK_TYPE digit_block; /* int of at least 32 bits */ - int i, j; - int round, o_exp; - int exp, exp_neg; - char *s; - char *e; - char buf[BUF_SIZE]; - INT_OR_PTR pc_fwi[2*MAX_CALLS]; - INT_OR_PTR *ppc; - char exp_buf[8]; - char drvr[8]; - char *pdrvr; - int npc; - int cnt; - char sign_str[2]; - char o_mode; - - /* check that INT_OR_PTR is sufficiently large */ - assert( sizeof(INT_OR_PTR) == sizeof(char *) ); - - *sign_str = flag[FLAG_PLUS]; - *(sign_str+1) = 0; - if (isnan(x)) { /* nan check */ - pdrvr = drvr + 1; - *pdrvr++ = 5 + (mode < 'a'); - pc_fwi[2] = 3; - flag[FLAG_0_PAD] = 0; - goto EXIT_SPECIAL; - } - - if (x == 0) { /* handle 0 now to avoid false positive */ - exp = -1; - goto GENERATE_DIGITS; - } - - if (x < 0) { /* convert negatives to positives */ - *sign_str = '-'; - x = -x; - } - - if (_zero_or_inf_check(x)) { /* must be inf since zero handled above */ - pdrvr = drvr + 1; - *pdrvr++ = 3 + + (mode < 'a'); - pc_fwi[2] = 3; - flag[FLAG_0_PAD] = 0; - goto EXIT_SPECIAL; - } - - /* need to build the scaling table */ - for (i = 0, p10 = 10 ; i < EXP_TABLE_SIZE ; i++) { - exp_table[i] = p10; - p10 *= p10; - } - - exp_neg = 0; - if (x < 1e8) { /* do we need to scale up or down? */ - exp_neg = 1; - } - - exp = DIGITS_PER_BLOCK - 1; - - i = EXP_TABLE_SIZE; - j = EXP_TABLE_MAX; - while ( i-- ) { /* scale x such that 1e8 <= x < 1e9 */ - if (exp_neg) { - if (x * exp_table[i] < 1e9) { - x *= exp_table[i]; - exp -= j; - } - } else { - if (x / exp_table[i] >= 1e8) { - x /= exp_table[i]; - exp += j; - } - } - j >>= 1; - } - if (x >= 1e9) { /* handle bad rounding case */ - x /= 10; - ++exp; - } - assert(x < 1e9); - - GENERATE_DIGITS: - s = buf + 2; /* leave space for '\0' and '0' */ - - for (i = 0 ; i < NUM_DIGIT_BLOCKS ; ++i ) { - digit_block = (DIGIT_BLOCK_TYPE) x; - x = (x - digit_block) * 1e9; - s += sprintf(s, DB_FMT, DIGITS_PER_BLOCK, digit_block); - } - - /*************************************************************************/ - - *exp_buf = 'e'; - if (mode < 'a') { - *exp_buf = 'E'; - mode += ('a' - 'A'); - } - - o_mode = mode; - - round = preci; - - if ((mode == 'g') && (round > 0)){ - --round; - } - - if (mode == 'f') { - round += exp; - } - - s = buf; - *s++ = 0; /* terminator for rounding and 0-triming */ - *s = '0'; /* space to round */ - - i = 0; - e = s + MAX_DIGITS + 1; - if (round < MAX_DIGITS) { - e = s + round + 2; - if (*e >= '5') { - i = 1; - } - } - - do { /* handle rounding and trim trailing 0s */ - *--e += i; /* add the carry */ - } while ((*e == '0') || (*e > '9')); - - o_exp = exp; - if (e <= s) { /* we carried into extra digit */ - ++o_exp; - e = s; /* needed if all 0s */ - } else { - ++s; - } - *++e = 0; /* ending nul char */ - - if ((mode == 'g') && ((o_exp >= -4) && (o_exp <= round))) { - mode = 'f'; - } - - exp = o_exp; - if (mode != 'f') { - o_exp = 0; - } - - if (o_exp < 0) { - *--s = '0'; /* fake the first digit */ - } - - pdrvr = drvr+1; - ppc = pc_fwi+2; - - *pdrvr++ = 0; - *ppc++ = 1; - *ppc++ = (INT_OR_PTR)(*s++ - '0'); - - i = e - s; /* total digits */ - if (o_exp >= 0) { - if (o_exp >= i) { /* all digit(s) left of decimal */ - *pdrvr++ = 1; - *ppc++ = i; - *ppc++ = (INT_OR_PTR)(s); - o_exp -= i; - i = 0; - if (o_exp>0) { /* have 0s left of decimal */ - *pdrvr++ = 0; - *ppc++ = o_exp; - *ppc++ = 0; - } - } else if (o_exp > 0) { /* decimal between digits */ - *pdrvr++ = 1; - *ppc++ = o_exp; - *ppc++ = (INT_OR_PTR)(s); - s += o_exp; - i -= o_exp; - } - o_exp = -1; - } - - if (flag[FLAG_HASH] || (i) || ((o_mode != 'g') && (preci > 0))) { - *pdrvr++ = 2; /* need decimal */ - *ppc++ = 1; /* needed for width calc */ - ppc++; - } - - if (++o_exp < 0) { /* have 0s right of decimal */ - *pdrvr++ = 0; - *ppc++ = -o_exp; - *ppc++ = 0; - } - if (i) { /* have digit(s) right of decimal */ - *pdrvr++ = 1; - *ppc++ = i; - *ppc++ = (INT_OR_PTR)(s); - } - - if (o_mode != 'g') { - i -= o_exp; - if (i < preci) { /* have 0s right of digits */ - i = preci - i; - *pdrvr++ = 0; - *ppc++ = i; - *ppc++ = 0; - } - } - - /* build exponent string */ - if (mode != 'f') { - *pdrvr++ = 1; - *ppc++ = sprintf(exp_buf,"%c%+.2d", *exp_buf, exp); - *ppc++ = (INT_OR_PTR) exp_buf; - } - - EXIT_SPECIAL: - npc = pdrvr - drvr; - ppc = pc_fwi + 2; - for (i=1 ; i< npc ; i++) { - width -= *(ppc++); - ppc++; - } - i = 0; - if (*sign_str) { - i = 1; - } - width -= i; - if (width <= 0) { - width = 0; - } else { - if (flag[FLAG_MINUS_LJUSTIFY]) { /* padding on right */ - ++npc; - *pdrvr++ = 7; - *ppc = width; - *++ppc = (INT_OR_PTR)(""); - width = 0; - } else if (flag[FLAG_0_PAD] == '0') { /* 0 padding */ - pc_fwi[2] += width; - width = 0; - } - } - *drvr = 7; - ppc = pc_fwi; - *ppc++ = width + i; - *ppc = (INT_OR_PTR) sign_str; - - pdrvr = drvr; - ppc = pc_fwi; - cnt = 0; - for (i=0 ; i<npc ; i++) { -#if 1 - fnprintf(fp, size, fmts[(int)(*pdrvr++)], (INT_OR_PTR)(*(ppc)), - (INT_OR_PTR)(*(ppc+1))); -#else - j = fnprintf(fp, size, fmts[(int)(*pdrvr++)], (INT_OR_PTR)(*(ppc)), - (INT_OR_PTR)(*(ppc+1))); - assert(j == *ppc); -#endif - if (size > *ppc) { - size -= *ppc; - } - cnt += *ppc; /* to avoid problems if j == -1 */ - ppc += 2; - } - - return cnt; -} - - - - - - diff --git a/libc/misc/internals/lltostr.c b/libc/misc/internals/lltostr.c deleted file mode 100644 index 2ce359615..000000000 --- a/libc/misc/internals/lltostr.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2000 Manuel Novoa III - * - * Note: buf is a pointer to the END of the buffer passed. - * Call like this: - * char buf[SIZE], *p; - * p = __lltostr(buf + sizeof(buf) - 1, ...) - * For long longs of 64 bits, appropriate buffer sizes are: - * base = 2 66 = 1 (possible -) sign + 64 digits + 1 nul - * base = 10 21 = 1 (possible -) sign + 19 digits + 1 nul - * base = 16 18 = 1 (possible -) sign + 16 hex digits + 1 nul - */ - -extern char *__ulltostr(char *buf, unsigned long long uval, int base, - int uppercase); - -char *__lltostr(char *buf, long long val, int base, int uppercase) -{ - unsigned long long uval; - char *pos; - int negative; - - negative = 0; - if (val < 0) { - negative = 1; - uval = ((unsigned long long)(-(1+val))) + 1; - } else { - uval = val; - } - - - pos = __ulltostr(buf, uval, base, uppercase); - - if (pos && negative) { - *--pos = '-'; - } - - return pos; -} diff --git a/libc/misc/internals/ltostr.c b/libc/misc/internals/ltostr.c deleted file mode 100644 index 7e45fec30..000000000 --- a/libc/misc/internals/ltostr.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2000 Manuel Novoa III - * - * Note: buf is a pointer to the END of the buffer passed. - * Call like this: - * char buf[SIZE], *p; - * p = __ltostr(buf + sizeof(buf) - 1, ...) - * - * For longs of 32 bits, appropriate buffer sizes are: - * base = 2 34 = 1 (possible -) sign + 32 digits + 1 nul - * base = 10 12 = 1 (possible -) sign + 10 digits + 1 nul - * base = 16 10 = 1 (possible -) sign + 8 hex digits + 1 nul - */ - -extern char *__ultostr(char *buf, unsigned long uval, int base, int uppercase); - -char *__ltostr(char *buf, long val, int base, int uppercase) -{ - unsigned long uval; - char *pos; - int negative; - - negative = 0; - if (val < 0) { - negative = 1; - uval = ((unsigned long)(-(1+val))) + 1; - } else { - uval = val; - } - - - pos = __ultostr(buf, uval, base, uppercase); - - if (pos && negative) { - *--pos = '-'; - } - - return pos; -} diff --git a/libc/misc/internals/tempname.c b/libc/misc/internals/tempname.c index 3c43f9b85..41325d998 100644 --- a/libc/misc/internals/tempname.c +++ b/libc/misc/internals/tempname.c @@ -16,6 +16,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* March 11, 2002 Manuel Novoa III + * + * Modify code to remove dependency on libgcc long long arith support funcs. + */ + #include <stddef.h> #include <stdint.h> #include <stdio.h> @@ -117,8 +122,11 @@ int __gen_tempname (char *tmpl, int openit) char *XXXXXX; static uint64_t value; struct timeval tv; + uint32_t high, low, rh; + unsigned int k; int count, fd; int save_errno = errno; + int i; len = strlen (tmpl); if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) @@ -136,20 +144,21 @@ int __gen_tempname (char *tmpl, int openit) for (count = 0; count < TMP_MAX; value += 7777, ++count) { - uint64_t v = value; - - /* Fill in the random bits. */ - XXXXXX[0] = letters[v % 62]; - v /= 62; - XXXXXX[1] = letters[v % 62]; - v /= 62; - XXXXXX[2] = letters[v % 62]; - v /= 62; - XXXXXX[3] = letters[v % 62]; - v /= 62; - XXXXXX[4] = letters[v % 62]; - v /= 62; - XXXXXX[5] = letters[v % 62]; + low = value & UINT32_MAX; + high = value >> 32; + + for (i = 0 ; i < 6 ; i++) { + rh = high % 62; + high /= 62; +#define L ((UINT32_MAX % 62 + 1) % 62) + k = (low % 62) + (L * rh); +#undef L +#define H ((UINT32_MAX / 62) + ((UINT32_MAX % 62 + 1) / 62)) + low = (low / 62) + (H * rh) + (k / 62); +#undef H + k %= 62; + XXXXXX[i] = letters[k]; + } if (openit) { diff --git a/libc/misc/internals/ulltostr.c b/libc/misc/internals/ulltostr.c deleted file mode 100644 index 50246d3bc..000000000 --- a/libc/misc/internals/ulltostr.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2000 Manuel Novoa III - * - * Note: buf is a pointer to the END of the buffer passed. - * Call like this: - * char buf[SIZE], *p; - * p = __ulltostr(buf + sizeof(buf) - 1, ...) - * - * For long longs of 64 bits, appropriate buffer sizes are: - * base = 2 65 = 64 digits + 1 nul - * base = 10 20 = 19 digits + 1 nul - * base = 16 17 = 16 hex digits + 1 nul - */ - -char *__ulltostr(char *buf, unsigned long long uval, int base, int uppercase) -{ - int digit; - - if ((base < 2) || (base > 36)) { - return 0; - } - - *buf = '\0'; - - do { - digit = uval % base; - uval /= base; - - /* note: slightly slower but generates less code */ - *--buf = '0' + digit; - if (digit > 9) { - *buf = (uppercase ? 'A' : 'a') + digit - 10; - } - } while (uval); - - return buf; -} diff --git a/libc/misc/internals/ultostr.c b/libc/misc/internals/ultostr.c deleted file mode 100644 index d4663fb39..000000000 --- a/libc/misc/internals/ultostr.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2000 Manuel Novoa III - * - * Note: buf is a pointer to the END of the buffer passed. - * Call like this; - * char buf[SIZE], *p; - * p = __ultostr(buf + sizeof(buf) - 1, ...) - * - * For longs of 32 bits, appropriate buffer sizes are: - * base = 2 33 = 32 digits + 1 nul - * base = 10 11 = 10 digits + 1 nul - * base = 16 9 = 8 hex digits + 1 nul - */ - -char *__ultostr(char *buf, unsigned long uval, int base, int uppercase) -{ - int digit; - - if ((base < 2) || (base > 36)) { - return 0; - } - - *buf = '\0'; - - do { - digit = uval % base; - uval /= base; - - /* note: slightly slower but generates less code */ - *--buf = '0' + digit; - if (digit > 9) { - *buf = (uppercase ? 'A' : 'a') + digit - 10; - } - } while (uval); - - return buf; -} diff --git a/libc/misc/internals/zoicheck.c b/libc/misc/internals/zoicheck.c deleted file mode 100644 index 2113c6298..000000000 --- a/libc/misc/internals/zoicheck.c +++ /dev/null @@ -1,16 +0,0 @@ - -/* - * Copyright (C) 2000 Manuel Novoa III - * - * This is a utility routine for strtod errno support. - * As the name implies, it checks if a double is either 0 or +/-infinity. - * Doing this inline doesn't work on i386 because of excess precission - * stored in the FPU. - * - * TODO: Check bitmasks directly? - */ - -int _zero_or_inf_check(double x) -{ - return ( x == x/4 ); -} |