Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--newlib/ChangeLog44
-rw-r--r--newlib/libc/locale/lmonetary.c24
-rw-r--r--newlib/libc/locale/lmonetary.h8
-rw-r--r--newlib/libc/locale/lnumeric.c23
-rw-r--r--newlib/libc/locale/lnumeric.h8
-rw-r--r--newlib/libc/locale/locale.c73
-rw-r--r--newlib/libc/locale/nl_langinfo.c4
-rw-r--r--newlib/libc/locale/timelocal.c26
-rw-r--r--newlib/libc/locale/timelocal.h11
-rw-r--r--newlib/libc/time/strftime.c168
-rw-r--r--newlib/libc/time/strptime.c85
11 files changed, 302 insertions, 172 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index b8c04ce2b..396d0c3ee 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,47 @@
+2010-01-22 Corinna Vinschen <corinna@vinschen.de>
+
+ * libc/locale/lmonetary.c (__monetary_load_locale): Take additional
+ parameters for wide char to multibyte conversion. Call
+ __set_lc_monetary_from_win on Cygwin.
+ * libc/locale/lmonetary.h: Make C++-safe.
+ (__monetary_load_locale): Change declaration.
+ * libc/locale/lnumeric.c (__numeric_load_locale): Take additional
+ parameters for wide char to multibyte conversion. Call
+ __set_lc_numeric_from_win on Cygwin.
+ * libc/locale/lnumeric.h: Make C++-safe.
+ (__numeric_load_locale): Change declaration.
+ * libc/locale/locale.c (lconv): De-constify for Cygwin.
+ (__set_charset_from_locale): Rename from
+ __set_charset_from_codepage. Take locale as parameter instead of
+ a codepage.
+ (loadlocale): Allow "EUC-JP" for "EUCJP" and "EUC-KR" for "EUCKR".
+ Change documnetation accordingly. Enable LC_COLLATE, LC_MONETARY,
+ LC_NUMERIC, and LC_TIME handling on Cygwin.
+ (_localeconv_r): On Cygwin, copy values from monetary and numeric
+ domain if change has been noted.
+ * libc/locale/nl_langinfo.c (nl_langinfo): Accommodate change of
+ am/pm layout in struct lc_time_T.
+ * libc/locale/timelocal.c (_C_time_locale): Accommodate
+ redefinition of am/pm members.
+ (__time_load_locale): Take additional parameters for wide char
+ to multibyte conversion. Call __set_lc_time_from_win on Cygwin.
+ * libc/locale/timelocal.h: Make C++-safe.
+ (struct lc_time_T): Convert am and pm to a am_pm array for easier
+ consumption by strftime and strptime.
+ (__time_load_locale): Change declaration.
+ * libc/time/strftime.c: Change documentation to reflect changes to
+ strftime. Remove locale constant strings in favor of access to
+ locale-specifc data.
+ (_ctloc): Define access method for locale-specifc data.
+ (TOLOWER): Define for tolower conversion.
+ (strftime): Throughout, convert locale-specific formats to use
+ locale-specific data. Add GNU-specific "%P" format.
+ * libc/time/strptime.c: Remove locale constant strings in favor of
+ access to locale-specifc data.
+ (_ctloc): Define access method for locale-specifc data.
+ (strptime): Throughout, convert locale-specific formats to use
+ locale-specific data.
+
2010-01-20 Corinna Vinschen <corinna@vinschen.de>
* libc/locale/nl_langinfo.c (nl_langinfo): On Cygwin, translate
diff --git a/newlib/libc/locale/lmonetary.c b/newlib/libc/locale/lmonetary.c
index d31e88ccd..745ade517 100644
--- a/newlib/libc/locale/lmonetary.c
+++ b/newlib/libc/locale/lmonetary.c
@@ -70,9 +70,28 @@ cnv(const char *str) {
}
int
-__monetary_load_locale(const char *name) {
-
+__monetary_load_locale(const char *name , void *f_wctomb, const char *charset)
+{
int ret;
+
+#ifdef __CYGWIN__
+ extern int __set_lc_monetary_from_win (const char *,
+ struct lc_monetary_T *,
+ void *, const char *);
+ int old_monetary_using_locale = _monetary_using_locale;
+ _monetary_using_locale = 0;
+ ret = __set_lc_monetary_from_win (name, &_monetary_locale,
+ f_wctomb, charset);
+ /* ret == -1: error, ret == 0: C/POSIX, ret > 0: valid */
+ if (ret < 0)
+ _monetary_using_locale = old_monetary_using_locale;
+ else
+ {
+ _monetary_using_locale = ret;
+ __mlocale_changed = 1;
+ ret = 0;
+ }
+#else
__mlocale_changed = 1;
ret = __part_load_locale(name, &_monetary_using_locale,
_monetary_locale_buf, "LC_MONETARY",
@@ -94,6 +113,7 @@ __monetary_load_locale(const char *name) {
M_ASSIGN_CHAR(p_sign_posn);
M_ASSIGN_CHAR(n_sign_posn);
}
+#endif
return ret;
}
diff --git a/newlib/libc/locale/lmonetary.h b/newlib/libc/locale/lmonetary.h
index bbe77db42..14c9cc15d 100644
--- a/newlib/libc/locale/lmonetary.h
+++ b/newlib/libc/locale/lmonetary.h
@@ -29,6 +29,10 @@
#ifndef _LMONETARY_H_
#define _LMONETARY_H_
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
struct lc_monetary_T {
const char *int_curr_symbol;
const char *currency_symbol;
@@ -48,6 +52,8 @@ struct lc_monetary_T {
};
struct lc_monetary_T *__get_current_monetary_locale(void);
-int __monetary_load_locale(const char *);
+int __monetary_load_locale(const char *, void *, const char *);
+
+__END_DECLS
#endif /* !_LMONETARY_H_ */
diff --git a/newlib/libc/locale/lnumeric.c b/newlib/libc/locale/lnumeric.c
index 90b404ca2..5bf0a7d11 100644
--- a/newlib/libc/locale/lnumeric.c
+++ b/newlib/libc/locale/lnumeric.c
@@ -48,10 +48,28 @@ static int _numeric_using_locale;
static char *_numeric_locale_buf;
int
-__numeric_load_locale(const char *name) {
-
+__numeric_load_locale(const char *name , void *f_wctomb, const char *charset)
+{
int ret;
+#ifdef __CYGWIN__
+ extern int __set_lc_numeric_from_win (const char *,
+ struct lc_numeric_T *,
+ void *, const char *);
+ int old_numeric_using_locale = _numeric_using_locale;
+ _numeric_using_locale = 0;
+ ret = __set_lc_numeric_from_win (name, &_numeric_locale,
+ f_wctomb, charset);
+ /* ret == -1: error, ret == 0: C/POSIX, ret > 0: valid */
+ if (ret < 0)
+ _numeric_using_locale = old_numeric_using_locale;
+ else
+ {
+ _numeric_using_locale = ret;
+ __nlocale_changed = 1;
+ ret = 0;
+ }
+#else
__nlocale_changed = 1;
ret = __part_load_locale(name, &_numeric_using_locale,
_numeric_locale_buf, "LC_NUMERIC",
@@ -60,6 +78,7 @@ __numeric_load_locale(const char *name) {
if (ret == 0 && _numeric_using_locale)
_numeric_locale.grouping =
__fix_locale_grouping_str(_numeric_locale.grouping);
+#endif
return ret;
}
diff --git a/newlib/libc/locale/lnumeric.h b/newlib/libc/locale/lnumeric.h
index 9678c1f02..bed75e868 100644
--- a/newlib/libc/locale/lnumeric.h
+++ b/newlib/libc/locale/lnumeric.h
@@ -29,6 +29,10 @@
#ifndef _LNUMERIC_H_
#define _LNUMERIC_H_
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
struct lc_numeric_T {
const char *decimal_point;
const char *thousands_sep;
@@ -36,6 +40,8 @@ struct lc_numeric_T {
};
struct lc_numeric_T *__get_current_numeric_locale(void);
-int __numeric_load_locale(const char *);
+int __numeric_load_locale(const char *, void *, const char *);
+
+__END_DECLS
#endif /* !_LNUMERIC_H_ */
diff --git a/newlib/libc/locale/locale.c b/newlib/libc/locale/locale.c
index 1349927bf..4dd773463 100644
--- a/newlib/libc/locale/locale.c
+++ b/newlib/libc/locale/locale.c
@@ -75,7 +75,9 @@ Even when using POSIX locale strings, the only charsets allowed are
1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258].
Charsets are case insensitive. For instance, <<"EUCJP">> and <<"eucJP">>
are equivalent. <<"UTF-8">> can also be written without dash, as in
-<<"UTF8">> or <<"utf8">>.
+<<"UTF8">> or <<"utf8">>. <<"EUCJP">> and <<"EUCKR"> can also contain a
+dash, <<"EUC-JP">> and <<"EUC-KR">>.
+
(<<"">> is also accepted; if given, the settings are read from the
corresponding LC_* environment variables and $LANG according to POSIX rules.
@@ -172,6 +174,8 @@ No supporting OS subroutines are required.
#include <reent.h>
#include <stdlib.h>
#include <wchar.h>
+#include "lmonetary.h"
+#include "lnumeric.h"
#include "../stdlib/local.h"
#define _LC_LAST 7
@@ -183,7 +187,11 @@ int __nlocale_changed = 0;
int __mlocale_changed = 0;
char *_PathLocale = NULL;
-static _CONST struct lconv lconv =
+static
+#ifndef __CYGWIN__
+_CONST
+#endif
+struct lconv lconv =
{
".", "", "", "", "", "", "", "", "", "",
CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
@@ -420,7 +428,8 @@ currentlocale()
#ifdef _MB_CAPABLE
#ifdef __CYGWIN__
-extern void *__set_charset_from_codepage (unsigned int, char *charset);
+extern void __set_charset_from_locale (const char *locale, char *charset);
+extern int __collate_load_locale (const char *, void *, const char *);
#endif /* __CYGWIN__ */
extern void __set_ctype (const char *charset);
@@ -447,6 +456,9 @@ loadlocale(struct _reent *p, int category)
#ifdef _MB_CAPABLE
int cjknarrow = 0;
#endif
+#ifdef __CYGWIN__
+ int ret = 0;
+#endif
/* "POSIX" is translated to "C", as on Linux. */
if (!strcmp (locale, "POSIX"))
@@ -502,7 +514,7 @@ loadlocale(struct _reent *p, int category)
else if (c[0] == '\0' || c[0] == '@')
/* End of string or just a modifier */
#ifdef __CYGWIN__
- __set_charset_from_codepage (0, charset);
+ __set_charset_from_locale (locale, charset);
#else
strcpy (charset, "ISO-8859-1");
#endif
@@ -548,7 +560,7 @@ loadlocale(struct _reent *p, int category)
break;
case 'E':
case 'e':
- if (!strcasecmp (charset, "EUCJP"))
+ if (!strcasecmp (charset, "EUCJP") || !strcasecmp (charset, "EUC-JP"))
{
strcpy (charset, "EUCJP");
mbc_max = 3;
@@ -558,7 +570,8 @@ loadlocale(struct _reent *p, int category)
#endif
}
#ifdef __CYGWIN__
- else if (!strcasecmp (charset, "EUCKR"))
+ else if (!strcasecmp (charset, "EUCKR")
+ || !strcasecmp (charset, "EUC-KR"))
{
strcpy (charset, "EUCKR");
mbc_max = 2;
@@ -729,6 +742,18 @@ loadlocale(struct _reent *p, int category)
}
else if (category == LC_MESSAGES)
strcpy (lc_message_charset, charset);
+#ifdef __CYGWIN__
+ else if (category == LC_COLLATE)
+ ret = __collate_load_locale (locale, (void *) l_mbtowc, charset);
+ else if (category == LC_MONETARY)
+ ret = __monetary_load_locale (locale, (void *) l_wctomb, charset);
+ else if (category == LC_NUMERIC)
+ ret = __numeric_load_locale (locale, (void *) l_wctomb, charset);
+ else if (category == LC_TIME)
+ ret = __time_load_locale (locale, (void *) l_wctomb, charset);
+ if (ret)
+ return NULL;
+#endif
return strcpy(current_categories[category], new_categories[category]);
}
@@ -778,6 +803,42 @@ struct lconv *
_DEFUN(_localeconv_r, (data),
struct _reent *data)
{
+#ifdef __CYGWIN__
+ if (__nlocale_changed)
+ {
+ struct lc_numeric_T *n = __get_current_numeric_locale ();
+ lconv.decimal_point = n->decimal_point;
+ lconv.thousands_sep = n->thousands_sep;
+ lconv.grouping = n->grouping;
+ __nlocale_changed = 0;
+ }
+ if (__mlocale_changed)
+ {
+ struct lc_monetary_T *m = __get_current_monetary_locale ();
+ lconv.int_curr_symbol = m->int_curr_symbol;
+ lconv.currency_symbol = m->currency_symbol;
+ lconv.mon_decimal_point = m->mon_decimal_point;
+ lconv.mon_thousands_sep = m->mon_thousands_sep;
+ lconv.mon_grouping = m->mon_grouping;
+ lconv.positive_sign = m->positive_sign;
+ lconv.negative_sign = m->negative_sign;
+ lconv.int_frac_digits = m->int_frac_digits[0];
+ lconv.frac_digits = m->frac_digits[0];
+ lconv.p_cs_precedes = m->p_cs_precedes[0];
+ lconv.p_sep_by_space = m->p_sep_by_space[0];
+ lconv.n_cs_precedes = m->n_cs_precedes[0];
+ lconv.n_sep_by_space = m->n_sep_by_space[0];
+ lconv.p_sign_posn = m->p_sign_posn[0];
+ lconv.n_sign_posn = m->n_sign_posn[0];
+ lconv.int_n_cs_precedes = m->n_cs_precedes[0];
+ lconv.int_n_sep_by_space = m->n_sep_by_space[0];
+ lconv.int_n_sign_posn = m->n_sign_posn[0];
+ lconv.int_p_cs_precedes = m->p_cs_precedes[0];
+ lconv.int_p_sep_by_space = m->p_sep_by_space[0];
+ lconv.int_p_sign_posn = m->p_sign_posn[0];
+ __mlocale_changed = 0;
+ }
+#endif
return (struct lconv *) &lconv;
}
diff --git a/newlib/libc/locale/nl_langinfo.c b/newlib/libc/locale/nl_langinfo.c
index 550f92efd..ae7228cf6 100644
--- a/newlib/libc/locale/nl_langinfo.c
+++ b/newlib/libc/locale/nl_langinfo.c
@@ -133,10 +133,10 @@ _DEFUN(nl_langinfo, (item),
ret = (char *) __get_current_time_locale()->ampm_fmt;
break;
case AM_STR:
- ret = (char *) __get_current_time_locale()->am;
+ ret = (char *) __get_current_time_locale()->am_pm[0];
break;
case PM_STR:
- ret = (char *) __get_current_time_locale()->pm;
+ ret = (char *) __get_current_time_locale()->am_pm[1];
break;
case DAY_1: case DAY_2: case DAY_3:
case DAY_4: case DAY_5: case DAY_6: case DAY_7:
diff --git a/newlib/libc/locale/timelocal.c b/newlib/libc/locale/timelocal.c
index 5b097ad7c..0fe53bf42 100644
--- a/newlib/libc/locale/timelocal.c
+++ b/newlib/libc/locale/timelocal.c
@@ -70,11 +70,8 @@ static const struct lc_time_T _C_time_locale = {
*/
"%a %b %e %H:%M:%S %Y",
- /* am */
- "AM",
-
- /* pm */
- "PM",
+ /* am pm */
+ { "AM", "PM" },
/* date_fmt */
"%a %b %e %H:%M:%S %Z %Y",
@@ -106,14 +103,29 @@ __get_current_time_locale(void) {
}
int
-__time_load_locale(const char *name) {
+__time_load_locale(const char *name, void *f_wctomb, const char *charset) {
int ret;
+#ifdef __CYGWIN__
+ extern int __set_lc_time_from_win (const char *, struct lc_time_T *,
+ void *, const char *);
+ int old_time_using_locale = _time_using_locale;
+ _time_using_locale = 0;
+ ret = __set_lc_time_from_win (name, &_time_locale, f_wctomb, charset);
+ /* ret == -1: error, ret == 0: C/POSIX, ret > 0: valid */
+ if (ret < 0)
+ _time_using_locale = old_time_using_locale;
+ else
+ {
+ _time_using_locale = ret;
+ ret = 0;
+ }
+#else
ret = __part_load_locale(name, &_time_using_locale,
time_locale_buf, "LC_TIME",
LCTIME_SIZE, LCTIME_SIZE,
(const char **)&_time_locale);
-
+#endif
return (ret);
}
diff --git a/newlib/libc/locale/timelocal.h b/newlib/libc/locale/timelocal.h
index 0b0a59a48..e232a7304 100644
--- a/newlib/libc/locale/timelocal.h
+++ b/newlib/libc/locale/timelocal.h
@@ -29,6 +29,10 @@
#ifndef _TIMELOCAL_H_
#define _TIMELOCAL_H_
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
/*
* Private header file for the strftime and strptime localization
* stuff.
@@ -41,8 +45,7 @@ struct lc_time_T {
const char *X_fmt;
const char *x_fmt;
const char *c_fmt;
- const char *am;
- const char *pm;
+ const char *am_pm[2];
const char *date_fmt;
const char *alt_month[12];
const char *md_order;
@@ -50,6 +53,8 @@ struct lc_time_T {
};
struct lc_time_T *__get_current_time_locale(void);
-int __time_load_locale(const char *);
+int __time_load_locale(const char *, void *, const char *);
+
+__END_DECLS
#endif /* !_TIMELOCAL_H_ */
diff --git a/newlib/libc/time/strftime.c b/newlib/libc/time/strftime.c
index e9849ac9b..95fb3019c 100644
--- a/newlib/libc/time/strftime.c
+++ b/newlib/libc/time/strftime.c
@@ -52,26 +52,26 @@ following ways:
o+
o %a
-A three-letter abbreviation for the day of the week. [tm_wday]
+The abbreviated weekday name according to the current locale. [tm_wday]
o %A
-The full name for the day of the week, one of `<<Sunday>>',
-`<<Monday>>', `<<Tuesday>>', `<<Wednesday>>', `<<Thursday>>',
-`<<Friday>>', or `<<Saturday>>'. [tm_wday]
+The full weekday name according to the current locale.
+In the default "C" locale, one of `<<Sunday>>', `<<Monday>>', `<<Tuesday>>',
+`<<Wednesday>>', `<Thursday>>', `<<Friday>>', `<<Saturday>>'. [tm_wday]
o %b
-A three-letter abbreviation for the month name. [tm_mon]
+The abbreviated month name according to the current locale. [tm_mon]
o %B
-The full name of the month, one of `<<January>>', `<<February>>',
+The full month name according to the current locale.
+In the default "C" locale, one of `<<January>>', `<<February>>',
`<<March>>', `<<April>>', `<<May>>', `<<June>>', `<<July>>',
`<<August>>', `<<September>>', `<<October>>', `<<November>>',
`<<December>>'. [tm_mon]
o %c
-A string representing the complete date and time, in the form
-`<<"%a %b %e %H:%M:%S %Y">>' (example "Mon Apr 01 13:13:13
-1992"). [tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday]
+The preferred date and time representation for the current locale.
+[tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday]
o %C
The century, that is, the year divided by 100 then truncated. For
@@ -93,8 +93,7 @@ The day of the month, formatted with leading space if single digit
o %E<<x>>
In some locales, the E modifier selects alternative representations of
-certain modifiers <<x>>. But in the "C" locale supported by newlib,
-it is ignored, and treated as %<<x>>.
+certain modifiers <<x>>. In newlib, it is ignored, and treated as %<<x>>.
o %F
A string representing the ISO 8601:2000 date format, in the form
@@ -115,8 +114,7 @@ Example: "%G" for Saturday 2nd January 1999 gives "1998", and for
Tuesday 30th December 1997 gives "1998". [tm_year, tm_wday, tm_yday]
o %h
-A three-letter abbreviation for the month name (synonym for
-"%b"). [tm_mon]
+Synonym for "%b". [tm_mon]
o %H
The hour (on a 24-hour clock), formatted with two digits (from
@@ -150,15 +148,19 @@ A newline character (`<<\n>>').
o %O<<x>>
In some locales, the O modifier selects alternative digit characters
-for certain modifiers <<x>>. But in the "C" locale supported by newlib, it
-is ignored, and treated as %<<x>>.
+for certain modifiers <<x>>. In newlib, it is ignored, and treated as %<<x>>.
o %p
-Either `<<AM>>' or `<<PM>>' as appropriate. [tm_hour]
+Either `<<AM>>' or `<<PM>>' as appropriate, or the corresponding strings for
+the current locale. [tm_hour]
+
+o %P
+Same as '<<%p>>', but in lowercase. This is a GNU extension. [tm_hour]
o %r
-The 12-hour time, to the second. Equivalent to "%I:%M:%S %p". [tm_sec,
-tm_min, tm_hour]
+Replaced by the time in a.m. and p.m. notation. In the "C" locale this
+is equivalent to "%I:%M:%S %p". In locales which don't define a.m./p.m.
+notations, the result is an empty string. [tm_sec, tm_min, tm_hour]
o %R
The 24-hour time, to the minute. Equivalent to "%H:%M". [tm_min, tm_hour]
@@ -198,12 +200,13 @@ Monday in a year, and earlier days are in week 0. Formatted with two
digits (from `<<00>>' to `<<53>>'). [tm_wday, tm_yday]
o %x
-A string representing the complete date, equivalent to "%m/%d/%y".
+Replaced by the preferred date representation in the current locale.
+In the "C" locale this is equivalent to "%m/%d/%y".
[tm_mon, tm_mday, tm_year]
o %X
-A string representing the full time of day (hours, minutes, and
-seconds), equivalent to "%H:%M:%S". [tm_sec, tm_min, tm_hour]
+Replaced by the preferred time representation in the current locale.
+In the "C" locale this is equivalent to "%H:%M:%S". [tm_sec, tm_min, tm_hour]
o %y
The last two digits of the year (from `<<00>>' to `<<99>>'). [tm_year]
@@ -263,7 +266,10 @@ the "C" locale settings.
#include <string.h>
#include <stdlib.h>
#include <limits.h>
+#include <ctype.h>
+#include <wctype.h>
#include "local.h"
+#include "../locale/timelocal.h"
/* Defines to make the file dual use for either strftime() or wcsftime().
* To get wcsftime, define MAKE_WCSFTIME.
@@ -276,13 +282,28 @@ the "C" locale settings.
# define CHAR char /* string type basis */
# define CQ(a) a /* character constant qualifier */
# define SFLG /* %s flag (null for normal char) */
+# define _ctloc(x) (ctloclen = strlen (ctloc = _CurrentTimeLocale->x), ctloc)
+# define TOLOWER(c) tolower((int)(unsigned char)(c))
# else
# define strftime wcsftime /* Alternate function name */
# define CHAR wchar_t /* string type basis */
# define CQ(a) L##a /* character constant qualifier */
# define snprintf swprintf /* wide-char equivalent function name */
# define strncmp wcsncmp /* wide-char equivalent function name */
+# define TOLOWER(c) towlower((wint_t)(c))
# define SFLG "l" /* %s flag (l for wide char) */
+# define CTLOCBUFLEN 256 /* Arbitrary big buffer size */
+ const wchar_t *
+ __ctloc (wchar_t *buf, const char *elem, size_t *len_ret)
+ {
+ buf[CTLOCBUFLEN - 1] = L'\0';
+ *len_ret = mbstowcs (buf, elem, CTLOCBUFLEN - 1);
+ if (*len_ret == (size_t) -1 )
+ *len_ret = 0;
+ return buf;
+ }
+# define _ctloc(x) (ctloc = __ctloc (ctlocbuf, _CurrentTimeLocale->x, \
+ &ctloclen))
#endif /* MAKE_WCSFTIME */
/* Enforce the coding assumptions that YEAR_BASE is positive. (%C, %Y, etc.) */
@@ -293,18 +314,6 @@ the "C" locale settings.
static _CONST int dname_len[7] =
{6, 6, 7, 9, 8, 6, 8};
-static _CONST CHAR *_CONST dname[7] =
-{CQ("Sunday"), CQ("Monday"), CQ("Tuesday"), CQ("Wednesday"),
- CQ("Thursday"), CQ("Friday"), CQ("Saturday")};
-
-static _CONST int mname_len[12] =
-{7, 8, 5, 5, 3, 4, 4, 6, 9, 7, 8, 8};
-
-static _CONST CHAR *_CONST mname[12] =
-{CQ("January"), CQ("February"), CQ("March"), CQ("April"),
- CQ("May"), CQ("June"), CQ("July"), CQ("August"),
- CQ("September"), CQ("October"), CQ("November"), CQ("December")};
-
/* Using the tm_year, tm_wday, and tm_yday components of TIM_P, return
-1, 0, or 1 as the adjustment to add to the year for the ISO week
numbering used in "%g%G%V", avoiding overflow. */
@@ -361,7 +370,13 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
{
size_t count = 0;
int i, len;
+ const CHAR *ctloc;
+#ifdef MAKE_WCSFTIME
+ CHAR ctlocbuf[CTLOCBUFLEN];
+#endif
+ size_t ctloclen;
+ struct lc_time_T *_CurrentTimeLocale = __get_current_time_locale ();
for (;;)
{
while (*format && *format != CQ('%'))
@@ -382,56 +397,68 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
switch (*format)
{
case CQ('a'):
- for (i = 0; i < 3; i++)
+ _ctloc (wday[tim_p->tm_wday]);
+ for (i = 0; i < ctloclen; i++)
{
if (count < maxsize - 1)
- s[count++] =
- dname[tim_p->tm_wday][i];
+ s[count++] = ctloc[i];
else
return 0;
}
break;
case CQ('A'):
- for (i = 0; i < dname_len[tim_p->tm_wday]; i++)
+ _ctloc (weekday[tim_p->tm_wday]);
+ for (i = 0; i < ctloclen; i++)
{
if (count < maxsize - 1)
- s[count++] =
- dname[tim_p->tm_wday][i];
+ s[count++] = ctloc[i];
else
return 0;
}
break;
case CQ('b'):
case CQ('h'):
- for (i = 0; i < 3; i++)
+ _ctloc (mon[tim_p->tm_mon]);
+ for (i = 0; i < ctloclen; i++)
{
if (count < maxsize - 1)
- s[count++] =
- mname[tim_p->tm_mon][i];
+ s[count++] = ctloc[i];
else
return 0;
}
break;
case CQ('B'):
- for (i = 0; i < mname_len[tim_p->tm_mon]; i++)
+ _ctloc (month[tim_p->tm_mon]);
+ for (i = 0; i < ctloclen; i++)
{
if (count < maxsize - 1)
- s[count++] =
- mname[tim_p->tm_mon][i];
+ s[count++] = ctloc[i];
else
return 0;
}
break;
case CQ('c'):
- {
- /* Recurse to avoid need to replicate %Y formation. */
- size_t adjust = strftime (&s[count], maxsize - count,
- CQ("%a %b %e %H:%M:%S %Y"), tim_p);
- if (adjust > 0)
- count += adjust;
- else
- return 0;
- }
+ _ctloc (c_fmt);
+ goto recurse;
+ case CQ('r'):
+ _ctloc (ampm_fmt);
+ goto recurse;
+ case CQ('x'):
+ _ctloc (x_fmt);
+ goto recurse;
+ case CQ('X'):
+ _ctloc (X_fmt);
+recurse:
+ if (*ctloc)
+ {
+ /* Recurse to avoid need to replicate %Y formation. */
+ size_t adjust = strftime (&s[count], maxsize - count, ctloc,
+ tim_p);
+ if (adjust > 0)
+ count += adjust;
+ else
+ return 0;
+ }
break;
case CQ('C'):
{
@@ -472,7 +499,6 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
if (len < 0 || (count+=len) >= maxsize) return 0;
break;
case CQ('D'):
- case CQ('x'):
/* %m/%d/%y */
len = snprintf (&s[count], maxsize - count,
CQ("%.2d/%.2d/%.2d"),
@@ -582,33 +608,16 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
return 0;
break;
case CQ('p'):
- if (count < maxsize - 1)
+ case CQ('P'):
+ _ctloc (am_pm[tim_p->tm_hour < 12 ? 0 : 1]);
+ for (i = 0; i < ctloclen; i++)
{
- if (tim_p->tm_hour < 12)
- s[count++] = CQ('A');
+ if (count < maxsize - 1)
+ s[count++] = (*format == CQ('P') ? TOLOWER (ctloc[i])
+ : ctloc[i]);
else
- s[count++] = CQ('P');
- }
- if (count < maxsize - 1)
- {
- s[count++] = CQ('M');
+ return 0;
}
- else
- return 0;
- break;
- case CQ('r'):
- {
- register int h12;
- h12 = (tim_p->tm_hour == 0 || tim_p->tm_hour == 12) ?
- 12 : tim_p->tm_hour % 12;
- len = snprintf (&s[count], maxsize - count,
- CQ("%.2d:%.2d:%.2d %cM"),
- h12,
- tim_p->tm_min,
- tim_p->tm_sec,
- (tim_p->tm_hour < 12) ? CQ('A') : CQ('P'));
- if (len < 0 || (count+=len) >= maxsize) return 0;
- }
break;
case CQ('R'):
len = snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d"),
@@ -627,7 +636,6 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
return 0;
break;
case CQ('T'):
- case CQ('X'):
len = snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d:%.2d"),
tim_p->tm_hour, tim_p->tm_min, tim_p->tm_sec);
if (len < 0 || (count+=len) >= maxsize) return 0;
diff --git a/newlib/libc/time/strptime.c b/newlib/libc/time/strptime.c
index 127772460..1457c93ed 100644
--- a/newlib/libc/time/strptime.c
+++ b/newlib/libc/time/strptime.c
@@ -36,66 +36,9 @@
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
+#include "../locale/timelocal.h"
-static const char *abb_weekdays[] = {
- "Sun",
- "Mon",
- "Tue",
- "Wed",
- "Thu",
- "Fri",
- "Sat",
- NULL
-};
-
-static const char *full_weekdays[] = {
- "Sunday",
- "Monday",
- "Tuesday",
- "Wednesday",
- "Thursday",
- "Friday",
- "Saturday",
- NULL
-};
-
-static const char *abb_month[] = {
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov",
- "Dec",
- NULL
-};
-
-static const char *full_month[] = {
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December",
- NULL,
-};
-
-static const char *ampm[] = {
- "am",
- "pm",
- NULL
-};
+#define _ctloc(x) (_CurrentTimeLocale->x)
/*
* tm_year is relative this year
@@ -205,6 +148,7 @@ _DEFUN (strptime, (buf, format, timeptr),
{
char c;
+ struct lc_time_T *_CurrentTimeLocale = __get_current_time_locale ();
for (; (c = *format) != '\0'; ++format) {
char *s;
int ret;
@@ -218,26 +162,26 @@ _DEFUN (strptime, (buf, format, timeptr),
c = *++format;
switch (c) {
case 'A' :
- ret = match_string (&buf, full_weekdays);
+ ret = match_string (&buf, _ctloc (weekday));
if (ret < 0)
return NULL;
timeptr->tm_wday = ret;
break;
case 'a' :
- ret = match_string (&buf, abb_weekdays);
+ ret = match_string (&buf, _ctloc (wday));
if (ret < 0)
return NULL;
timeptr->tm_wday = ret;
break;
case 'B' :
- ret = match_string (&buf, full_month);
+ ret = match_string (&buf, _ctloc (month));
if (ret < 0)
return NULL;
timeptr->tm_mon = ret;
break;
case 'b' :
case 'h' :
- ret = match_string (&buf, abb_month);
+ ret = match_string (&buf, _ctloc (mon));
if (ret < 0)
return NULL;
timeptr->tm_mon = ret;
@@ -250,7 +194,7 @@ _DEFUN (strptime, (buf, format, timeptr),
buf = s;
break;
case 'c' : /* %a %b %e %H:%M:%S %Y */
- s = strptime (buf, "%a %b %e %H:%M:%S %Y", timeptr);
+ s = strptime (buf, _ctloc (c_fmt), timeptr);
if (s == NULL)
return NULL;
buf = s;
@@ -316,7 +260,7 @@ _DEFUN (strptime, (buf, format, timeptr),
return NULL;
break;
case 'p' :
- ret = match_string (&buf, ampm);
+ ret = match_string (&buf, _ctloc (am_pm));
if (ret < 0)
return NULL;
if (timeptr->tm_hour == 0) {
@@ -326,7 +270,7 @@ _DEFUN (strptime, (buf, format, timeptr),
timeptr->tm_hour += 12;
break;
case 'r' : /* %I:%M:%S %p */
- s = strptime (buf, "%I:%M:%S %p", timeptr);
+ s = strptime (buf, _ctloc (ampm_fmt), timeptr);
if (s == NULL)
return NULL;
buf = s;
@@ -351,7 +295,6 @@ _DEFUN (strptime, (buf, format, timeptr),
return NULL;
break;
case 'T' : /* %H:%M:%S */
- case 'X' :
s = strptime (buf, "%H:%M:%S", timeptr);
if (s == NULL)
return NULL;
@@ -393,11 +336,17 @@ _DEFUN (strptime, (buf, format, timeptr),
buf = s;
break;
case 'x' :
- s = strptime (buf, "%Y:%m:%d", timeptr);
+ s = strptime (buf, _ctloc (x_fmt), timeptr);
if (s == NULL)
return NULL;
buf = s;
break;
+ case 'X' :
+ s = strptime (buf, _ctloc (X_fmt), timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
case 'y' :
ret = strtol (buf, &s, 10);
if (s == buf)