diff options
author | David Schultz <das@FreeBSD.org> | 2009-01-28 04:36:34 +0000 |
---|---|---|
committer | David Schultz <das@FreeBSD.org> | 2009-01-28 04:36:34 +0000 |
commit | 4848dd0858385db46fa4e0192a134605ee42ab01 (patch) | |
tree | c4d28a7b5d5d1902de89c3a33988ed7f5638277b /contrib/gdtoa/g__fmt.c | |
parent | d568fa54dbafa992ebdb5e912b8f5f790f9094bd (diff) | |
parent | 9ea4d2a87415d5928272c15f22583103f2ccfe30 (diff) | |
download | src-4848dd0858385db46fa4e0192a134605ee42ab01.tar.gz src-4848dd0858385db46fa4e0192a134605ee42ab01.zip |
Vendor import of gdtoa 20081205.
Notes
Notes:
svn path=/head/; revision=187808
Diffstat (limited to 'contrib/gdtoa/g__fmt.c')
-rw-r--r-- | contrib/gdtoa/g__fmt.c | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/contrib/gdtoa/g__fmt.c b/contrib/gdtoa/g__fmt.c index 021ecfb57283..fbccb7d98971 100644 --- a/contrib/gdtoa/g__fmt.c +++ b/contrib/gdtoa/g__fmt.c @@ -37,24 +37,51 @@ THIS SOFTWARE. char * #ifdef KR_headers -g__fmt(b, s, se, decpt, sign) char *b; char *s; char *se; int decpt; ULong sign; +g__fmt(b, s, se, decpt, sign, blen) char *b; char *s; char *se; int decpt; ULong sign; size_t blen; #else -g__fmt(char *b, char *s, char *se, int decpt, ULong sign) +g__fmt(char *b, char *s, char *se, int decpt, ULong sign, size_t blen) #endif { int i, j, k; - char *s0 = s; + char *be, *s0; + size_t len; #ifdef USE_LOCALE - char decimalpoint = *localeconv()->decimal_point; +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + size_t dlen = strlen(decimalpoint); #else -#define decimalpoint '.' + char *decimalpoint; + static char *decimalpoint_cache; + static size_t dlen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + dlen = strlen(s0); + if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + } + decimalpoint = s0; +#endif +#else +#define dlen 0 #endif + s0 = s; + len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */ + if (blen < len) + goto ret0; + be = b + blen - 1; if (sign) *b++ = '-'; if (decpt <= -4 || decpt > se - s + 5) { *b++ = *s++; if (*s) { - *b++ = decimalpoint; +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif while((*b = *s++) !=0) b++; } @@ -69,6 +96,8 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign) for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){} for(;;) { i = decpt / k; + if (b >= be) + goto ret0; *b++ = i + '0'; if (--j <= 0) break; @@ -78,22 +107,41 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign) *b = 0; } else if (decpt <= 0) { - *b++ = decimalpoint; +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif + if (be < b - decpt + (se - s)) + goto ret0; for(; decpt < 0; decpt++) *b++ = '0'; - while((*b = *s++) !=0) + while((*b = *s++) != 0) b++; } else { - while((*b = *s++) !=0) { + while((*b = *s++) != 0) { b++; - if (--decpt == 0 && *s) - *b++ = decimalpoint; + if (--decpt == 0 && *s) { +#ifdef USE_LOCALE + while(*b = *decimalpoint++) + ++b; +#else + *b++ = '.'; +#endif + } + } + if (b + decpt > be) { + ret0: + b = 0; + goto ret; } for(; decpt > 0; decpt--) *b++ = '0'; *b = 0; } + ret: freedtoa(s0); return b; } |