summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio/vfscanf.c
diff options
context:
space:
mode:
authortheraven <theraven@FreeBSD.org>2011-11-20 14:45:42 +0000
committertheraven <theraven@FreeBSD.org>2011-11-20 14:45:42 +0000
commit0f6ef690b3118882121ed67561c7ce2660cfebe1 (patch)
tree909189922493cddbeeac84af2e316dc897661311 /lib/libc/stdio/vfscanf.c
parent18b29f3fb8abee5d57ed8f4a44f806bec7e0eeff (diff)
downloadFreeBSD-src-0f6ef690b3118882121ed67561c7ce2660cfebe1.zip
FreeBSD-src-0f6ef690b3118882121ed67561c7ce2660cfebe1.tar.gz
Implement xlocale APIs from Darwin, mainly for use by libc++. This adds a
load of _l suffixed versions of various standard library functions that use the global locale, making them take an explicit locale parameter. Also adds support for per-thread locales. This work was funded by the FreeBSD Foundation. Please test any code you have that uses the C standard locale functions! Reviewed by: das (gdtoa changes) Approved by: dim (mentor)
Diffstat (limited to 'lib/libc/stdio/vfscanf.c')
-rw-r--r--lib/libc/stdio/vfscanf.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index bce4481..0e78949 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -2,6 +2,11 @@
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
@@ -51,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include "collate.h"
#include "libc_private.h"
#include "local.h"
+#include "xlocale_private.h"
#ifndef NO_FLOATING_POINT
#include <locale.h>
@@ -95,7 +101,7 @@ __FBSDID("$FreeBSD$");
static const u_char *__sccl(char *, const u_char *);
#ifndef NO_FLOATING_POINT
-static int parsefloat(FILE *, char *, char *);
+static int parsefloat(FILE *, char *, char *, locale_t);
#endif
__weak_reference(__vfscanf, vfscanf);
@@ -109,7 +115,18 @@ __vfscanf(FILE *fp, char const *fmt0, va_list ap)
int ret;
FLOCKFILE(fp);
- ret = __svfscanf(fp, fmt0, ap);
+ ret = __svfscanf(fp, __get_locale(), fmt0, ap);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+int
+vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap)
+{
+ int ret;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(fp);
+ ret = __svfscanf(fp, locale, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
@@ -118,7 +135,7 @@ __vfscanf(FILE *fp, char const *fmt0, va_list ap)
* __svfscanf - non-MT-safe version of __vfscanf
*/
int
-__svfscanf(FILE *fp, const char *fmt0, va_list ap)
+__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap)
{
const u_char *fmt = (const u_char *)fmt0;
int c; /* character from format, or conversion */
@@ -733,9 +750,9 @@ literal:
*p = 0;
if ((flags & UNSIGNED) == 0)
- res = strtoimax(buf, (char **)NULL, base);
+ res = strtoimax_l(buf, (char **)NULL, base, locale);
else
- res = strtoumax(buf, (char **)NULL, base);
+ res = strtoumax_l(buf, (char **)NULL, base, locale);
if (flags & POINTER)
*va_arg(ap, void **) =
(void *)(uintptr_t)res;
@@ -766,17 +783,17 @@ literal:
/* scan a floating point number as if by strtod */
if (width == 0 || width > sizeof(buf) - 1)
width = sizeof(buf) - 1;
- if ((width = parsefloat(fp, buf, buf + width)) == 0)
+ if ((width = parsefloat(fp, buf, buf + width, locale)) == 0)
goto match_failure;
if ((flags & SUPPRESS) == 0) {
if (flags & LONGDBL) {
- long double res = strtold(buf, &p);
+ long double res = strtold_l(buf, &p, locale);
*va_arg(ap, long double *) = res;
} else if (flags & LONG) {
- double res = strtod(buf, &p);
+ double res = strtod_l(buf, &p, locale);
*va_arg(ap, double *) = res;
} else {
- float res = strtof(buf, &p);
+ float res = strtof_l(buf, &p, locale);
*va_arg(ap, float *) = res;
}
nassigned++;
@@ -805,6 +822,8 @@ __sccl(tab, fmt)
const u_char *fmt;
{
int c, n, v, i;
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
/* first `clear' the whole table */
c = *fmt++; /* first char hat => negated scanset */
@@ -858,8 +877,8 @@ doswitch:
*/
n = *fmt;
if (n == ']'
- || (__collate_load_error ? n < c :
- __collate_range_cmp (n, c) < 0
+ || (table->__collate_load_error ? n < c :
+ __collate_range_cmp (table, n, c) < 0
)
) {
c = '-';
@@ -867,14 +886,14 @@ doswitch:
}
fmt++;
/* fill in the range */
- if (__collate_load_error) {
+ if (table->__collate_load_error) {
do {
tab[++c] = v;
} while (c < n);
} else {
for (i = 0; i < 256; i ++)
- if ( __collate_range_cmp (c, i) < 0
- && __collate_range_cmp (i, n) <= 0
+ if ( __collate_range_cmp (table, c, i) < 0
+ && __collate_range_cmp (table, i, n) <= 0
)
tab[i] = v;
}
@@ -908,7 +927,7 @@ doswitch:
#ifndef NO_FLOATING_POINT
static int
-parsefloat(FILE *fp, char *buf, char *end)
+parsefloat(FILE *fp, char *buf, char *end, locale_t locale)
{
char *commit, *p;
int infnanpos = 0, decptpos = 0;
@@ -917,7 +936,7 @@ parsefloat(FILE *fp, char *buf, char *end)
S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
unsigned char c;
- const char *decpt = localeconv()->decimal_point;
+ const char *decpt = localeconv_l(locale)->decimal_point;
_Bool gotmantdig = 0, ishex = 0;
/*
OpenPOWER on IntegriCloud