summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdtime
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/stdtime
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/stdtime')
-rw-r--r--lib/libc/stdtime/strftime.c62
-rw-r--r--lib/libc/stdtime/strptime.c170
-rw-r--r--lib/libc/stdtime/timelocal.c57
-rw-r--r--lib/libc/stdtime/timelocal.h8
4 files changed, 197 insertions, 100 deletions
diff --git a/lib/libc/stdtime/strftime.c b/lib/libc/stdtime/strftime.c
index dac910b..d3571ad 100644
--- a/lib/libc/stdtime/strftime.c
+++ b/lib/libc/stdtime/strftime.c
@@ -2,6 +2,11 @@
* Copyright (c) 1989 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.
+ *
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
@@ -43,7 +48,7 @@ __FBSDID("$FreeBSD$");
static char * _add(const char *, char *, const char *);
static char * _conv(int, const char *, char *, const char *);
static char * _fmt(const char *, const struct tm *, char *, const char *,
- int *);
+ int *, locale_t);
static char * _yconv(int, int, int, int, char *, const char *);
extern char * tzname[];
@@ -82,29 +87,30 @@ static const char* fmt_padding[][4] = {
};
size_t
-strftime(char * __restrict s, size_t maxsize, const char * __restrict format,
- const struct tm * __restrict t)
+strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format,
+ const struct tm * __restrict t, locale_t loc)
{
char * p;
int warn;
+ FIX_LOCALE(loc);
tzset();
warn = IN_NONE;
- p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
+ p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, loc);
#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
- (void) fprintf(stderr, "\n");
+ (void) fprintf_l(stderr, loc, "\n");
if (format == NULL)
- (void) fprintf(stderr, "NULL strftime format ");
- else (void) fprintf(stderr, "strftime format \"%s\" ",
+ (void) fprintf_l(stderr, loc, "NULL strftime format ");
+ else (void) fprintf_l(stderr, loc, "strftime format \"%s\" ",
format);
- (void) fprintf(stderr, "yields only two digits of years in ");
+ (void) fprintf_l(stderr, loc, "yields only two digits of years in ");
if (warn == IN_SOME)
- (void) fprintf(stderr, "some locales");
+ (void) fprintf_l(stderr, loc, "some locales");
else if (warn == IN_THIS)
- (void) fprintf(stderr, "the current locale");
- else (void) fprintf(stderr, "all locales");
- (void) fprintf(stderr, "\n");
+ (void) fprintf_l(stderr, loc, "the current locale");
+ else (void) fprintf_l(stderr, loc, "all locales");
+ (void) fprintf_l(stderr, loc, "\n");
}
#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
if (p == s + maxsize)
@@ -113,16 +119,24 @@ strftime(char * __restrict s, size_t maxsize, const char * __restrict format,
return p - s;
}
+size_t
+strftime(char * __restrict s, size_t maxsize, const char * __restrict format,
+ const struct tm * __restrict t)
+{
+ return strftime_l(s, maxsize, format, t, __get_locale());
+}
+
static char *
-_fmt(format, t, pt, ptlim, warnp)
+_fmt(format, t, pt, ptlim, warnp, loc)
const char * format;
const struct tm * const t;
char * pt;
const char * const ptlim;
int * warnp;
+locale_t loc;
{
int Ealternative, Oalternative, PadIndex;
- struct lc_time_T *tptr = __get_current_time_locale();
+ struct lc_time_T *tptr = __get_current_time_locale(loc);
for ( ; *format; ++format) {
if (*format == '%') {
@@ -175,7 +189,7 @@ label:
{
int warn2 = IN_SOME;
- pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2);
+ pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, loc);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
@@ -183,7 +197,7 @@ label:
}
continue;
case 'D':
- pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
+ pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, loc);
continue;
case 'd':
pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex],
@@ -216,7 +230,7 @@ label:
fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim);
continue;
case 'F':
- pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
+ pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, loc);
continue;
case 'H':
pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex],
@@ -285,11 +299,11 @@ label:
pt, ptlim);
continue;
case 'R':
- pt = _fmt("%H:%M", t, pt, ptlim, warnp);
+ pt = _fmt("%H:%M", t, pt, ptlim, warnp, loc);
continue;
case 'r':
pt = _fmt(tptr->ampm_fmt, t, pt, ptlim,
- warnp);
+ warnp, loc);
continue;
case 'S':
pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex],
@@ -313,7 +327,7 @@ label:
}
continue;
case 'T':
- pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
+ pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, loc);
continue;
case 't':
pt = _add("\t", pt, ptlim);
@@ -428,7 +442,7 @@ label:
** "date as dd-bbb-YYYY"
** (ado, 1993-05-24)
*/
- pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
+ pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, loc);
continue;
case 'W':
pt = _conv((t->tm_yday + DAYSPERWEEK -
@@ -441,13 +455,13 @@ label:
pt = _conv(t->tm_wday, "%d", pt, ptlim);
continue;
case 'X':
- pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp);
+ pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp, loc);
continue;
case 'x':
{
int warn2 = IN_SOME;
- pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2);
+ pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2, loc);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
@@ -534,7 +548,7 @@ label:
continue;
case '+':
pt = _fmt(tptr->date_fmt, t, pt, ptlim,
- warnp);
+ warnp, loc);
continue;
case '-':
if (PadIndex != PAD_DEFAULT)
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index 401350e..fb94dcd 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -22,6 +22,11 @@
/*
* Copyright (c) 1994 Powerdog Industries. 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.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -72,19 +77,20 @@ __FBSDID("$FreeBSD$");
#include "libc_private.h"
#include "timelocal.h"
-static char * _strptime(const char *, const char *, struct tm *, int *);
+static char * _strptime(const char *, const char *, struct tm *, int *, locale_t);
#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
static char *
-_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp)
+_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,
+ locale_t locale)
{
char c;
const char *ptr;
int i,
len;
int Ealternative, Oalternative;
- struct lc_time_T *tptr = __get_current_time_locale();
+ struct lc_time_T *tptr = __get_current_time_locale(locale);
ptr = fmt;
while (*ptr != 0) {
@@ -94,8 +100,9 @@ _strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp)
c = *ptr++;
if (c != '%') {
- if (isspace((unsigned char)c))
- while (*buf != 0 && isspace((unsigned char)*buf))
+ if (isspace_l((unsigned char)c, locale))
+ while (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
buf++;
else if (c != *buf++)
return 0;
@@ -114,18 +121,19 @@ label:
break;
case '+':
- buf = _strptime(buf, tptr->date_fmt, tm, GMTp);
+ buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale);
if (buf == 0)
return 0;
break;
case 'C':
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
/* XXX This will break for 3-digit centuries. */
len = 2;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
i *= 10;
i += *buf - '0';
len--;
@@ -137,13 +145,13 @@ label:
break;
case 'c':
- buf = _strptime(buf, tptr->c_fmt, tm, GMTp);
+ buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale);
if (buf == 0)
return 0;
break;
case 'D':
- buf = _strptime(buf, "%m/%d/%y", tm, GMTp);
+ buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale);
if (buf == 0)
return 0;
break;
@@ -161,47 +169,48 @@ label:
goto label;
case 'F':
- buf = _strptime(buf, "%Y-%m-%d", tm, GMTp);
+ buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale);
if (buf == 0)
return 0;
break;
case 'R':
- buf = _strptime(buf, "%H:%M", tm, GMTp);
+ buf = _strptime(buf, "%H:%M", tm, GMTp, locale);
if (buf == 0)
return 0;
break;
case 'r':
- buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp);
+ buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, locale);
if (buf == 0)
return 0;
break;
case 'T':
- buf = _strptime(buf, "%H:%M:%S", tm, GMTp);
+ buf = _strptime(buf, "%H:%M:%S", tm, GMTp, locale);
if (buf == 0)
return 0;
break;
case 'X':
- buf = _strptime(buf, tptr->X_fmt, tm, GMTp);
+ buf = _strptime(buf, tptr->X_fmt, tm, GMTp, locale);
if (buf == 0)
return 0;
break;
case 'x':
- buf = _strptime(buf, tptr->x_fmt, tm, GMTp);
+ buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale);
if (buf == 0)
return 0;
break;
case 'j':
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
len = 3;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++){
i *= 10;
i += *buf - '0';
len--;
@@ -214,14 +223,16 @@ label:
case 'M':
case 'S':
- if (*buf == 0 || isspace((unsigned char)*buf))
+ if (*buf == 0 ||
+ isspace_l((unsigned char)*buf, locale))
break;
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
len = 2;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++){
i *= 10;
i += *buf - '0';
len--;
@@ -237,8 +248,10 @@ label:
tm->tm_sec = i;
}
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
ptr++;
break;
@@ -254,11 +267,12 @@ label:
* XXX The %l specifier may gobble one too many
* digits if used incorrectly.
*/
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
len = 2;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
i *= 10;
i += *buf - '0';
len--;
@@ -271,8 +285,10 @@ label:
tm->tm_hour = i;
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
ptr++;
break;
@@ -282,7 +298,7 @@ label:
* specifiers.
*/
len = strlen(tptr->am);
- if (strncasecmp(buf, tptr->am, len) == 0) {
+ if (strncasecmp_l(buf, tptr->am, len, locale) == 0) {
if (tm->tm_hour > 12)
return 0;
if (tm->tm_hour == 12)
@@ -292,7 +308,7 @@ label:
}
len = strlen(tptr->pm);
- if (strncasecmp(buf, tptr->pm, len) == 0) {
+ if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) {
if (tm->tm_hour > 12)
return 0;
if (tm->tm_hour != 12)
@@ -307,12 +323,12 @@ label:
case 'a':
for (i = 0; i < asizeof(tptr->weekday); i++) {
len = strlen(tptr->weekday[i]);
- if (strncasecmp(buf, tptr->weekday[i],
- len) == 0)
+ if (strncasecmp_l(buf, tptr->weekday[i],
+ len, locale) == 0)
break;
len = strlen(tptr->wday[i]);
- if (strncasecmp(buf, tptr->wday[i],
- len) == 0)
+ if (strncasecmp_l(buf, tptr->wday[i],
+ len, locale) == 0)
break;
}
if (i == asizeof(tptr->weekday))
@@ -330,11 +346,12 @@ label:
* point to calculate a real value, so just check the
* range for now.
*/
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
len = 2;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
i *= 10;
i += *buf - '0';
len--;
@@ -342,13 +359,15 @@ label:
if (i > 53)
return 0;
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
ptr++;
break;
case 'w':
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
i = *buf - '0';
@@ -357,8 +376,10 @@ label:
tm->tm_wday = i;
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
ptr++;
break;
@@ -372,11 +393,12 @@ label:
* XXX The %e specifier may gobble one too many
* digits if used incorrectly.
*/
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
len = 2;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
i *= 10;
i += *buf - '0';
len--;
@@ -386,8 +408,10 @@ label:
tm->tm_mday = i;
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
ptr++;
break;
@@ -398,15 +422,15 @@ label:
if (Oalternative) {
if (c == 'B') {
len = strlen(tptr->alt_month[i]);
- if (strncasecmp(buf,
+ if (strncasecmp_l(buf,
tptr->alt_month[i],
- len) == 0)
+ len, locale) == 0)
break;
}
} else {
len = strlen(tptr->month[i]);
- if (strncasecmp(buf, tptr->month[i],
- len) == 0)
+ if (strncasecmp_l(buf, tptr->month[i],
+ len, locale) == 0)
break;
}
}
@@ -417,8 +441,8 @@ label:
if (i == asizeof(tptr->month) && !Oalternative) {
for (i = 0; i < asizeof(tptr->month); i++) {
len = strlen(tptr->mon[i]);
- if (strncasecmp(buf, tptr->mon[i],
- len) == 0)
+ if (strncasecmp_l(buf, tptr->mon[i],
+ len, locale) == 0)
break;
}
}
@@ -430,11 +454,12 @@ label:
break;
case 'm':
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
len = 2;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
i *= 10;
i += *buf - '0';
len--;
@@ -444,8 +469,10 @@ label:
tm->tm_mon = i - 1;
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
ptr++;
break;
@@ -458,7 +485,7 @@ label:
sverrno = errno;
errno = 0;
- n = strtol(buf, &cp, 10);
+ n = strtol_l(buf, &cp, 10, locale);
if (errno == ERANGE || (long)(t = n) != n) {
errno = sverrno;
return 0;
@@ -472,14 +499,16 @@ label:
case 'Y':
case 'y':
- if (*buf == 0 || isspace((unsigned char)*buf))
+ if (*buf == 0 ||
+ isspace_l((unsigned char)*buf, locale))
break;
- if (!isdigit((unsigned char)*buf))
+ if (!isdigit_l((unsigned char)*buf, locale))
return 0;
len = (c == 'Y') ? 4 : 2;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
i *= 10;
i += *buf - '0';
len--;
@@ -493,8 +522,10 @@ label:
tm->tm_year = i;
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
ptr++;
break;
@@ -503,7 +534,9 @@ label:
const char *cp;
char *zonestr;
- for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/}
+ for (cp = buf; *cp &&
+ isupper_l((unsigned char)*cp, locale); ++cp) {
+ /*empty*/}
if (cp - buf) {
zonestr = alloca(cp - buf + 1);
strncpy(zonestr, buf, cp - buf);
@@ -537,7 +570,7 @@ label:
buf++;
i = 0;
for (len = 4; len > 0; len--) {
- if (isdigit((unsigned char)*buf)) {
+ if (isdigit_l((unsigned char)*buf, locale)) {
i *= 10;
i += *buf - '0';
buf++;
@@ -557,14 +590,15 @@ label:
char *
-strptime(const char * __restrict buf, const char * __restrict fmt,
- struct tm * __restrict tm)
+strptime_l(const char * __restrict buf, const char * __restrict fmt,
+ struct tm * __restrict tm, locale_t loc)
{
char *ret;
int gmt;
+ FIX_LOCALE(loc);
gmt = 0;
- ret = _strptime(buf, fmt, tm, &gmt);
+ ret = _strptime(buf, fmt, tm, &gmt, loc);
if (ret && gmt) {
time_t t = timegm(tm);
localtime_r(&t, tm);
@@ -572,3 +606,9 @@ strptime(const char * __restrict buf, const char * __restrict fmt,
return (ret);
}
+char *
+strptime(const char * __restrict buf, const char * __restrict fmt,
+ struct tm * __restrict tm)
+{
+ return strptime_l(buf, fmt, tm, __get_locale());
+}
diff --git a/lib/libc/stdtime/timelocal.c b/lib/libc/stdtime/timelocal.c
index 6917e6b..3d9d096 100644
--- a/lib/libc/stdtime/timelocal.c
+++ b/lib/libc/stdtime/timelocal.c
@@ -3,6 +3,11 @@
* Copyright (c) 1997 FreeBSD Inc.
* 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.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -33,9 +38,13 @@ __FBSDID("$FreeBSD$");
#include "ldpart.h"
#include "timelocal.h"
-static struct lc_time_T _time_locale;
-static int _time_using_locale;
-static char *time_locale_buf;
+struct xlocale_time {
+ struct xlocale_component header;
+ char *buffer;
+ struct lc_time_T locale;
+};
+
+struct xlocale_time __xlocale_global_time;
#define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *))
@@ -99,19 +108,47 @@ static const struct lc_time_T _C_time_locale = {
"%I:%M:%S %p"
};
+static void destruct_time(void *v)
+{
+ struct xlocale_time *l = v;
+ if (l->buffer)
+ free(l->buffer);
+ free(l);
+}
+
+#include <stdio.h>
struct lc_time_T *
-__get_current_time_locale(void)
+__get_current_time_locale(locale_t loc)
{
- return (_time_using_locale
- ? &_time_locale
+ return (loc->using_time_locale
+ ? &((struct xlocale_time *)loc->components[XLC_TIME])->locale
: (struct lc_time_T *)&_C_time_locale);
}
+static int
+time_load_locale(struct xlocale_time *l, int *using_locale, const char *name)
+{
+ struct lc_time_T *time_locale = &l->locale;
+ return (__part_load_locale(name, using_locale,
+ &l->buffer, "LC_TIME",
+ LCTIME_SIZE, LCTIME_SIZE,
+ (const char **)time_locale));
+}
int
__time_load_locale(const char *name)
{
- return (__part_load_locale(name, &_time_using_locale,
- &time_locale_buf, "LC_TIME",
- LCTIME_SIZE, LCTIME_SIZE,
- (const char **)&_time_locale));
+ return time_load_locale(&__xlocale_global_time,
+ &__xlocale_global_locale.using_time_locale, name);
}
+void* __time_load(const char* name, locale_t loc)
+{
+ struct xlocale_time *new = calloc(sizeof(struct xlocale_time), 1);
+ new->header.header.destructor = destruct_time;
+ if (time_load_locale(new, &loc->using_time_locale, name) == _LDP_ERROR)
+ {
+ xlocale_release(new);
+ return NULL;
+ }
+ return new;
+}
+
diff --git a/lib/libc/stdtime/timelocal.h b/lib/libc/stdtime/timelocal.h
index 5d26bf9..2e44415 100644
--- a/lib/libc/stdtime/timelocal.h
+++ b/lib/libc/stdtime/timelocal.h
@@ -2,6 +2,11 @@
* Copyright (c) 1997-2002 FreeBSD Project.
* 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.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -28,6 +33,7 @@
#ifndef _TIMELOCAL_H_
#define _TIMELOCAL_H_
+#include "xlocale_private.h"
/*
* Private header file for the strftime and strptime localization
@@ -49,7 +55,7 @@ struct lc_time_T {
const char *ampm_fmt;
};
-struct lc_time_T *__get_current_time_locale(void);
+struct lc_time_T *__get_current_time_locale(locale_t);
int __time_load_locale(const char *);
#endif /* !_TIMELOCAL_H_ */
OpenPOWER on IntegriCloud