* 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:
Corinna Vinschen 2010-01-22 13:03:42 +00:00
parent 2d7f21da1e
commit fe57329f99
11 changed files with 302 additions and 172 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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:

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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;

View File

@ -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)