* 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:
		| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user