* 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.
This commit is contained in:
parent
2d7f21da1e
commit
fe57329f99
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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');
|
||||
return 0;
|
||||
}
|
||||
if (count < maxsize - 1)
|
||||
{
|
||||
s[count++] = CQ('M');
|
||||
}
|
||||
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;
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user