@@ -20,15 +20,24 @@ #include #include #include #include #include + +#ifdef HAVE_ASPRINTF_L +# include +#endif +#ifdef HAVE_XLOCALE_H +# include +#endif #include #import "OFString.h" #import "OFSystemInfo.h" + +#import "OFInitializationFailedException.h" #define MAX_SUBFORMAT_LEN 64 #ifndef HAVE_ASPRINTF /* @@ -67,10 +76,21 @@ LENGTH_MODIFIER_T, LENGTH_MODIFIER_CAPITAL_L } lengthModifier; bool useLocale; }; + +#ifdef HAVE_ASPRINTF_L +static locale_t cLocale; + +static void __attribute__((init)) +init(void) +{ + if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL) + @throw [OFInitializationFailedException exception]; +} +#endif #ifndef HAVE_ASPRINTF static int vasprintf(char **string, const char *format, va_list arguments) { @@ -492,10 +512,30 @@ case 'E': case 'g': case 'G': case 'a': case 'A': +#ifdef HAVE_ASPRINTF_L + { + locale_t locale = (ctx->useLocale ? NULL : cLocale); + + switch (ctx->lengthModifier) { + case LENGTH_MODIFIER_NONE: + case LENGTH_MODIFIER_L: + tmpLen = asprintf(&tmp, ctx->subformat, + va_arg(ctx->arguments, double), locale); + break; + case LENGTH_MODIFIER_CAPITAL_L: + tmpLen = asprintf(&tmp, ctx->subformat, + va_arg(ctx->arguments, long double), + locale); + break; + default: + return false; + } + } +#else switch (ctx->lengthModifier) { case LENGTH_MODIFIER_NONE: case LENGTH_MODIFIER_L: tmpLen = asprintf(&tmp, ctx->subformat, va_arg(ctx->arguments, double)); @@ -507,12 +547,13 @@ default: return false; } /* - * Ugly hack to undo locale, as there is nothing such as - * asprintf_l in POSIX. + * If there's no asprintf_l, we have no other choice than to + * use this ugly hack to replace the locale's decimal point + * back to ".". */ if (!ctx->useLocale) { void *pool = objc_autoreleasePoolPush(); char *tmp2; @@ -534,10 +575,11 @@ objc_autoreleasePoolPop(pool); } tmp = tmp2; } +#endif break; case 'c': switch (ctx->lengthModifier) { case LENGTH_MODIFIER_NONE: