From: VMware, Inc <> Date: Tue, 29 Mar 2011 18:53:55 +0000 (-0700) Subject: lib/string: support a fixed locale for "%f" output X-Git-Tag: 2011.03.28-387002~77 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8a22f85b064640f0b1fd3c35d1a1818cb5bd2eec;p=thirdparty%2Fopen-vm-tools.git lib/string: support a fixed locale for "%f" output Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/include/bsd_output.h b/open-vm-tools/lib/include/bsd_output.h index 238c0e67d..060ed1b6c 100644 --- a/open-vm-tools/lib/include/bsd_output.h +++ b/open-vm-tools/lib/include/bsd_output.h @@ -47,6 +47,10 @@ int bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap); +int +bsd_vsnprintf_c_locale(char **outbuf, size_t bufSize, const char *fmt0, + va_list ap); + int bsd_vsnwprintf(wchar_t **outbuf, size_t bufSize, const wchar_t *fmt0, va_list ap); diff --git a/open-vm-tools/lib/include/str.h b/open-vm-tools/lib/include/str.h index 2a0fc1476..c5904e921 100644 --- a/open-vm-tools/lib/include/str.h +++ b/open-vm-tools/lib/include/str.h @@ -87,6 +87,11 @@ * strings of "wchar_t" units, regardless of platform. */ +#ifdef HAS_BSD_PRINTF +EXTERN int Str_Sprintf_C_Locale(char *buf, size_t max, + const char *fmt, ...) PRINTF_DECL(3, 4); +#endif + EXTERN int Str_Sprintf(char *buf, size_t max, const char *fmt, ...) PRINTF_DECL(3, 4); EXTERN int Str_Snprintf(char *buf, size_t len, diff --git a/open-vm-tools/lib/string/bsd_vsnprintf.c b/open-vm-tools/lib/string/bsd_vsnprintf.c index 7ffb4502c..91d1011dc 100644 --- a/open-vm-tools/lib/string/bsd_vsnprintf.c +++ b/open-vm-tools/lib/string/bsd_vsnprintf.c @@ -402,7 +402,13 @@ BSDFmt_WCharToUTF8(wchar_t *wcsarg, int prec) int -bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap) +bsd_vsnprintf_core(char **outbuf, + char *grouping, + char thousands_sep, + char *decimal_point, + size_t bufSize, + const char *fmt0, + va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -414,8 +420,6 @@ bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap) int width; /* width from format (%8d), or 0 */ int prec; /* precision from format; <0 for N/A */ char sign; /* sign prefix (' ', '+', '-', or \0) */ - char thousands_sep; /* locale specific thousands separator */ - const char *grouping; /* locale specific numeric grouping rules */ #ifndef NO_FLOATING_POINT /* @@ -432,10 +436,6 @@ bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap) * 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 */ -#if defined __ANDROID__ - static const char dp = '.'; -#endif int signflag; /* true if float is negative */ union { /* floating point arguments %[aAeEfFgG] */ double dbl; @@ -585,20 +585,9 @@ bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap) xdigs = xdigs_lower; thousands_sep = '\0'; - grouping = NULL; convbuf = NULL; #ifndef NO_FLOATING_POINT dtoaresult = NULL; -#if defined(__ANDROID__) - /* - * Struct lconv is not working! For decimal_point, - * using '.' instead is a workaround. - */ - NOT_TESTED(); - decimal_point = &dp; -#else - decimal_point = localeconv()->decimal_point; -#endif #endif fmt = (char *)fmt0; @@ -714,16 +703,6 @@ bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap) goto rflag; case '\'': flags |= GROUPING; -#if defined(__ANDROID__) - /* - * Struct lconv is not working! The code below is a workaround. - */ - NOT_TESTED(); - thousands_sep = ','; -#else - thousands_sep = *(localeconv()->thousands_sep); - grouping = localeconv()->grouping; -#endif /* * Grouping should not begin with 0, but it nevertheless * does (see bug 281072) and makes the formatting code @@ -1303,12 +1282,65 @@ error: #undef FIND_ARGUMENTS } +int +bsd_vsnprintf_c_locale(char **outbuf, + size_t bufSize, + const char *fmt0, + va_list ap) +{ + char thousands_sep; + char *decimal_point; + static char dp = '.'; + + /* + * Perform a "%f" conversion always using the locale associated + * with the C locale - "," for thousands, '.' for decimal point. + */ + + thousands_sep = ','; + decimal_point = &dp; + + return bsd_vsnprintf_core(outbuf, NULL, thousands_sep, decimal_point, + bufSize, fmt0, ap); +} + +int +bsd_vsnprintf(char **outbuf, + size_t bufSize, + const char *fmt0, + va_list ap) +{ + char *grouping; + char thousands_sep; + char *decimal_point; + +#if defined(__ANDROID__) + static char dp = '.'; + + /* + * Struct lconv is not working! The code below is a workaround. + */ + NOT_TESTED(); + grouping = NULL; + thousands_sep = ','; + decimal_point = &dp; +#else + grouping = localeconv()->grouping; + thousands_sep = *(localeconv()->thousands_sep); + decimal_point = localeconv()->decimal_point; +#endif + + return bsd_vsnprintf_core(outbuf, grouping, thousands_sep, decimal_point, + bufSize, fmt0, ap); +} + /* * Find all arguments when a positional parameter is encountered. Returns a * table, indexed by argument number, of pointers to each arguments. The * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. * It will be replaces with a malloc-ed one if it overflows. */ + static void __find_arguments (const char *fmt0, va_list ap, union arg **argtable) { diff --git a/open-vm-tools/lib/string/str.c b/open-vm-tools/lib/string/str.c index 72cf25ce6..50102950e 100644 --- a/open-vm-tools/lib/string/str.c +++ b/open-vm-tools/lib/string/str.c @@ -131,10 +131,13 @@ Str_Vsnprintf(char *str, // OUT * those cases. */ - if ((retval < 0 || retval >= size) && size > 0) { - /* Find UTF-8 code point boundary and place NUL termination there */ - int trunc = CodeSet_Utf8FindCodePointBoundary(str, size - 1); - str[trunc] = '\0'; + if ((retval < 0) || (retval >= size)) { + if (size > 0) { + /* Find UTF-8 code point boundary and place NUL termination there */ + int trunc = CodeSet_Utf8FindCodePointBoundary(str, size - 1); + + str[trunc] = '\0'; + } } if (retval >= size) { return -1; @@ -143,6 +146,58 @@ Str_Vsnprintf(char *str, // OUT } +#ifdef HAS_BSD_PRINTF +/* + *---------------------------------------------------------------------- + * + * Str_Sprintf_C_Locale -- + * + * sprintf wrapper that fails on overflow. Enforces numeric C locale. + * + * Results: + * Returns the number of bytes stored in 'buf'. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Str_Sprintf_C_Locale(char *buf, // OUT: + size_t maxSize, // IN: + const char *fmt, // IN: + ...) // IN: +{ + uint32 *stack = (uint32*) &buf; + va_list args; + int retval; + + ASSERT(buf); + ASSERT(fmt); + + va_start(args, fmt); + retval = bsd_vsnprintf_c_locale(&buf, maxSize, fmt, args); + va_end(args); + + if ((retval < 0) || (retval >= maxSize)) { + if (maxSize > 0) { + /* Find UTF-8 code point boundary and place NUL termination there */ + int trunc = CodeSet_Utf8FindCodePointBoundary(buf, maxSize - 1); + + buf[trunc] = '\0'; + } + } + + if (retval >= maxSize) { + Panic("%s:%d Buffer too small 0x%x\n", __FILE__, __LINE__, stack[-1]); + } + + return retval; +} +#endif + + /* *---------------------------------------------------------------------- *