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]

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


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.

To enable reading the correct localized values from localeconv(), the
information must be written back into the lconv structure.  For that
to work, the lconv structure must not be const, otherwise the compiler
places the struct potentially in R/O memory.

And nl_langinfo.c needed a tiny tweak to match the change in the
lc_time_T structure from the distinct am/pm members to the am_pm array.

The rest of the patch is the same as
http://sourceware.org/ml/newlib/2010/msg00032.html including the changes
from http://sourceware.org/ml/newlib/2010/msg00034.html

A TODO for the near future is support for the thousands_sep character
in calls to functions which handle strings representing numbers, for
instance vfprintf, strtol, etc.

Ok to apply?


Thanks,
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 and store new values in lconv.
	* 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 and store new values in lconv.
	* libc/locale/lnumeric.h: Make C++-safe.
	(__numeric_load_locale): Change declaration.
	* libc/locale/locale.c (loadlocale): De-constify lconv for Cygwin.
	Enable LC_MONETARY, LC_NUMERIC, and LC_TIME handling on Cygwin.
	* 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	19 Jan 2010 20:09:11 -0000
@@ -27,6 +27,7 @@
 #include <sys/cdefs.h>
 
 #include <limits.h>
+#include <locale.h>
 #include <stdlib.h>
 #include "lmonetary.h"
 #include "ldpart.h"
@@ -70,9 +71,46 @@ 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);
+	if (!ret)
+	  {
+	    struct lconv *lc = localeconv ();
+	    lc->int_curr_symbol = _monetary_locale.int_curr_symbol;
+	    lc->currency_symbol = _monetary_locale.currency_symbol;
+	    lc->mon_decimal_point = _monetary_locale.mon_decimal_point;
+	    lc->mon_thousands_sep = _monetary_locale.mon_thousands_sep;
+	    lc->mon_grouping = _monetary_locale.mon_grouping;
+	    lc->positive_sign = _monetary_locale.positive_sign;
+	    lc->negative_sign = _monetary_locale.negative_sign;
+	    lc->int_frac_digits = _monetary_locale.int_frac_digits[0];
+	    lc->frac_digits = _monetary_locale.frac_digits[0];
+	    lc->p_cs_precedes = _monetary_locale.p_cs_precedes[0];
+	    lc->p_sep_by_space = _monetary_locale.p_sep_by_space[0];
+	    lc->n_cs_precedes = _monetary_locale.n_cs_precedes[0];
+	    lc->n_sep_by_space = _monetary_locale.n_sep_by_space[0];
+	    lc->p_sign_posn = _monetary_locale.p_sign_posn[0];
+	    lc->n_sign_posn = _monetary_locale.n_sign_posn[0];
+	    /* No such data on Windows.  Just use the standard values. */
+	    lc->int_n_cs_precedes = _monetary_locale.n_cs_precedes[0];
+	    lc->int_n_sep_by_space = _monetary_locale.n_sep_by_space[0];
+	    lc->int_n_sign_posn = _monetary_locale.n_sign_posn[0];
+	    lc->int_p_cs_precedes = _monetary_locale.p_cs_precedes[0];
+	    lc->int_p_sep_by_space = _monetary_locale.p_sep_by_space[0];
+	    lc->int_p_sign_posn = _monetary_locale.p_sign_posn[0];
+	  }
+	_monetary_using_locale = ret ? old_monetary_using_locale : 1;
+#else
 	__mlocale_changed = 1;
 	ret = __part_load_locale(name, &_monetary_using_locale,
 		_monetary_locale_buf, "LC_MONETARY",
@@ -94,6 +132,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	19 Jan 2010 20:09:11 -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	19 Jan 2010 20:09:11 -0000
@@ -27,6 +27,7 @@
 #include <sys/cdefs.h>
 
 #include <limits.h>
+#include <locale.h>
 #include "lnumeric.h"
 #include "ldpart.h"
 
@@ -48,10 +49,27 @@ 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);
+	if (!ret)
+	  {
+	    struct lconv *lc = localeconv ();
+	    lc->decimal_point = _numeric_locale.decimal_point;
+	    lc->thousands_sep = _numeric_locale.thousands_sep;
+	    lc->grouping = _numeric_locale.grouping;
+	  }
+	_numeric_using_locale = ret ? old_numeric_using_locale : 1;
+#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	19 Jan 2010 20:09:11 -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	19 Jan 2010 20:09:12 -0000
@@ -183,7 +183,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,
@@ -447,6 +451,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"))
@@ -729,6 +736,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]);
 }
 
Index: libc/locale/nl_langinfo.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/nl_langinfo.c,v
retrieving revision 1.4
diff -u -p -r1.4 nl_langinfo.c
--- libc/locale/nl_langinfo.c	15 Oct 2009 08:08:50 -0000	1.4
+++ libc/locale/nl_langinfo.c	19 Jan 2010 20:09:12 -0000
@@ -120,10 +120,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	19 Jan 2010 20:09:12 -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,22 @@ __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);
+	_time_using_locale = ret ? old_time_using_locale : 1;
+#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	19 Jan 2010 20:09:12 -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	19 Jan 2010 20:09:12 -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	19 Jan 2010 20:09:12 -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]