This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Take2: Enable LC_MONETARY, LC_NUMERIC and LC_TIME handling


On Jan 19 21:09, Corinna Vinschen wrote:
> Hi,
> 
> this patch supercedes the one from
> http://sourceware.org/ml/newlib/2010/msg00032.html
> 
> In the meantime I added LC_MONETARY and LC_NUMERIC handling in the same
> manner as LC_TIME.  Cygwin provides the matching functions to read the
> information from the Windows locale info.
> [...]

Small cosmetic change:  Copying the values from the lc_monetary and
lc_numeric arrays is now done in _localeconv_r.  This is analogue to BSD
systems and no problem since localeconv is not suppsoed to be thread-safe.


Corinna


 	* 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): Enable 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.


Index: libc/locale/lmonetary.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/lmonetary.c,v
retrieving revision 1.1
diff -u -p -r1.1 lmonetary.c
--- libc/locale/lmonetary.c	23 Aug 2002 01:56:03 -0000	1.1
+++ libc/locale/lmonetary.c	20 Jan 2010 14:32:34 -0000
@@ -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;
 }
 
Index: libc/locale/lmonetary.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/lmonetary.h,v
retrieving revision 1.1
diff -u -p -r1.1 lmonetary.h
--- libc/locale/lmonetary.h	23 Aug 2002 01:56:03 -0000	1.1
+++ libc/locale/lmonetary.h	20 Jan 2010 14:32:34 -0000
@@ -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_ */
Index: libc/locale/lnumeric.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/lnumeric.c,v
retrieving revision 1.1
diff -u -p -r1.1 lnumeric.c
--- libc/locale/lnumeric.c	23 Aug 2002 01:56:03 -0000	1.1
+++ libc/locale/lnumeric.c	20 Jan 2010 14:32:34 -0000
@@ -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;
 }
 
Index: libc/locale/lnumeric.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/lnumeric.h,v
retrieving revision 1.1
diff -u -p -r1.1 lnumeric.h
--- libc/locale/lnumeric.h	23 Aug 2002 01:56:03 -0000	1.1
+++ libc/locale/lnumeric.h	20 Jan 2010 14:32:34 -0000
@@ -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_ */
Index: libc/locale/locale.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/locale.c,v
retrieving revision 1.32
diff -u -p -r1.32 locale.c
--- libc/locale/locale.c	17 Jan 2010 14:57:32 -0000	1.32
+++ libc/locale/locale.c	20 Jan 2010 14:32:34 -0000
@@ -172,6 +172,8 @@ No supporting OS subroutines are require
 #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 +185,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 +426,7 @@ 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);
 #endif /* __CYGWIN__ */
 
 extern void __set_ctype (const char *charset);
@@ -447,6 +453,9 @@ loadlocale(struct _reent *p, int categor
 #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 +511,7 @@ loadlocale(struct _reent *p, int categor
       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
@@ -729,6 +738,16 @@ loadlocale(struct _reent *p, int categor
     }
   else if (category == LC_MESSAGES)
     strcpy (lc_message_charset, charset);
+#ifdef __CYGWIN__
+  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 +797,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;
 }
 
Index: libc/locale/nl_langinfo.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/nl_langinfo.c,v
retrieving revision 1.5
diff -u -p -r1.5 nl_langinfo.c
--- libc/locale/nl_langinfo.c	20 Jan 2010 13:18:24 -0000	1.5
+++ libc/locale/nl_langinfo.c	20 Jan 2010 14:32:34 -0000
@@ -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:
Index: libc/locale/timelocal.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/timelocal.c,v
retrieving revision 1.1
diff -u -p -r1.1 timelocal.c
--- libc/locale/timelocal.c	23 Aug 2002 01:56:03 -0000	1.1
+++ libc/locale/timelocal.c	20 Jan 2010 14:32:34 -0000
@@ -70,11 +70,8 @@ static const struct lc_time_T	_C_time_lo
 	 */
 	"%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);
 }
Index: libc/locale/timelocal.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/timelocal.h,v
retrieving revision 1.1
diff -u -p -r1.1 timelocal.h
--- libc/locale/timelocal.h	23 Aug 2002 01:56:03 -0000	1.1
+++ libc/locale/timelocal.h	20 Jan 2010 14:32:34 -0000
@@ -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_ */
Index: libc/time/strftime.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/strftime.c,v
retrieving revision 1.12
diff -u -p -r1.12 strftime.c
--- libc/time/strftime.c	12 Mar 2009 10:27:10 -0000	1.12
+++ libc/time/strftime.c	20 Jan 2010 14:32:35 -0000
@@ -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 lea
 
 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 1
 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 i
 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, t
 {
   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, t
       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, t
 	  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, t
 	    return 0;
 	  break;
 	case CQ('p'):
-	  if (count < maxsize - 1)
+	case CQ('P'):
+	  _ctloc (am_pm[tim_p->tm_hour < 12 ? 0 : 1]);
+	  for (i = 0; i < ctloclen; i++)
 	    {
-	      if (tim_p->tm_hour < 12)
-		s[count++] = CQ('A');
+	      if (count < maxsize - 1)
+		s[count++] = (*format == CQ('P') ? TOLOWER (ctloc[i])
+						 : ctloc[i]);
 	      else
-		s[count++] = CQ('P');
-	    }
-	  if (count < maxsize - 1)
-	    {
-	      s[count++] = CQ('M');
+		return 0;
 	    }
-	  else
-	    return 0;
-	  break;
-	case CQ('r'):
-	  {
-	    register int  h12;
-	    h12 = (tim_p->tm_hour == 0 || tim_p->tm_hour == 12)  ?
-						12  :  tim_p->tm_hour % 12;
-	    len = snprintf (&s[count], maxsize - count,
-			CQ("%.2d:%.2d:%.2d %cM"),
-			h12, 
-			tim_p->tm_min,
-			tim_p->tm_sec,
-			(tim_p->tm_hour < 12)  ?  CQ('A') :  CQ('P'));
-	    if (len < 0  ||  (count+=len) >= maxsize)  return 0;
-	  }
 	  break;
 	case CQ('R'):
           len = snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d"),
@@ -627,7 +636,6 @@ _DEFUN (strftime, (s, maxsize, format, t
 	    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;
Index: libc/time/strptime.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/time/strptime.c,v
retrieving revision 1.4
diff -u -p -r1.4 strptime.c
--- libc/time/strptime.c	18 Nov 2005 19:00:29 -0000	1.4
+++ libc/time/strptime.c	20 Jan 2010 14:32:35 -0000
@@ -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)


-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]