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] locale.c: Review __CYGWIN__ usage


Hi,


Jeff expressed his unhappiness about the massive usage of __CYGWIN__ in
newlib code.  I had to agree.  When I started with locale support in
Cygwin I had the problem that newlib's locale support was only sort of a
stub, and I saw no other way to implement this since I was sure that no
other newlib target was really interested in supporting all the kinks
and bits of POSIX locales.

For a start, to ease the pain, I change the locale.c function so that
all the usage of __CYGWIN__ is at least documented so that porters to
other targets know what this very piece of code is good for.  I also
guarded the calls to the various category-specific __foo_load_locale
functions and the depending code in _localeconv_r with a new macro
called __HAVE_LOCALE_INFO__.  This should be set in sys/config.h and
I did that for Cygwin, obviously.

I also removed the _CONST for the lconv array entirely.  It's not
required, it's not const on other systems.

So I just applied the below patch.  I'm open for discussion how to
replace more __CYGWIN__ usage by more generic flags.


Corinna


	* libc/locale/locale.c:  Throughout, extensively comment on the
	reason for using __CYGWIN__.
	(lconv): Remove _CONST entirely.
	(loadlocale): Guard calls to function loading locale-specific
	category data with __HAVE_LOCALE_INFO__ rather than __CYGWIN__.
	* libc/sys/config.h (__HAVE_LOCALE_INFO__): Define for Cygwin.


Index: libc/locale/locale.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/locale/locale.c,v
retrieving revision 1.40
diff -u -p -r1.40 locale.c
--- libc/locale/locale.c	9 Feb 2010 08:58:38 -0000	1.40
+++ libc/locale/locale.c	25 Feb 2010 16:07:22 -0000
@@ -192,9 +192,6 @@ int __mlocale_changed = 0;
 char *_PathLocale = NULL;
 
 static
-#ifndef __CYGWIN__
-_CONST
-#endif /* !__CYGWIN__ */
 struct lconv lconv = 
 {
   ".", "", "", "", "", "", "", "", "", "",
@@ -460,6 +457,15 @@ loadlocale(struct _reent *p, int categor
 		   const char *, mbstate_t *);
   int cjknarrow = 0;
 #ifdef __CYGWIN__
+  /* This additional code handles the case that the incoming locale string
+     is not valid.  If so, it calls the function __set_locale_from_locale_alias,
+     which is only available on Cygwin right now.  The function reads the
+     file /usr/share/locale/locale.alias.  The file contains locale aliases
+     and their replacement locale.  For instance, the alias "french" is
+     translated to "fr_FR.ISO-8859-1", the alias "thai" is translated to
+     "th_TH.TIS-620".  If successful, the function returns with a pointer
+     to the second argument, which is a buffer in which the reaplcement locale
+     gets stored.  Otherwise the function returns NULL. */
   char tmp_locale[ENCODING_LEN + 1];
   int ret = 0;
 
@@ -532,6 +538,12 @@ restart:
       else if (c[0] == '\0' || c[0] == '@')
 	/* End of string or just a modifier */
 #ifdef __CYGWIN__
+	/* The Cygwin-only function __set_charset_from_locale checks
+	   for the default charset which is connected to the given locale.
+	   The function uses Windows functions in turn so it can't be easily
+	   adapted to other targets.  However, if any other target provides
+	   equivalent functionality, preferrably using the same function name
+	   it would be sufficient to change the guarding #ifdef. */
 	__set_charset_from_locale (locale, charset);
 #else
 	strcpy (charset, "ISO-8859-1");
@@ -562,6 +574,7 @@ restart:
       l_mbtowc = __utf8_mbtowc;
     break;
 #ifndef __CYGWIN__
+    /* Cygwin does not support JIS at all. */
     case 'J':
     case 'j':
       if (strcasecmp (charset, "JIS"))
@@ -582,6 +595,8 @@ restart:
 	  l_mbtowc = __eucjp_mbtowc;
 	}
 #ifdef __CYGWIN__
+      /* Newlib does not provide EUC-KR and Cygwin's implementation
+	 requires Windows support. */
       else if (!strcasecmp (charset, "EUCKR")
 	       || !strcasecmp (charset, "EUC-KR"))
 	{
@@ -720,6 +735,8 @@ restart:
     case 'G':
     case 'g':
 #ifdef __CYGWIN__
+      /* Newlib does not provide GBK and Cygwin's implementation
+	 requires Windows support. */
       if (!strcasecmp (charset, "GBK"))
       	{
 	  strcpy (charset, "GBK");
@@ -785,6 +802,8 @@ restart:
 #endif /* _MB_EXTENDED_CHARSETS_WINDOWS */
       break;
 #ifdef __CYGWIN__
+    /* Newlib does not provide Big5 and Cygwin's implementation
+       requires Windows support. */
     case 'B':
     case 'b':
       if (strcasecmp (charset, "BIG5"))
@@ -818,15 +837,18 @@ restart:
     }
   else if (category == LC_MESSAGES)
     {
-#ifdef __CYGWIN__
+#ifdef __HAVE_LOCALE_INFO__
       ret = __messages_load_locale (locale, (void *) l_wctomb, charset);
       if (!ret)
-#endif
+#endif /* __HAVE_LOCALE_INFO__ */
       strcpy (lc_message_charset, charset);
     }
+#ifdef __HAVE_LOCALE_INFO__
 #ifdef __CYGWIN__
+  /* Right now only Cygwin supports a __collate_load_locale function at all. */
   else if (category == LC_COLLATE)
     ret = __collate_load_locale (locale, (void *) l_mbtowc, charset);
+#endif
   else if (category == LC_MONETARY)
     ret = __monetary_load_locale (locale, (void *) l_wctomb, charset);
   else if (category == LC_NUMERIC)
@@ -835,7 +857,7 @@ restart:
     ret = __time_load_locale (locale, (void *) l_wctomb, charset);
   if (ret)
     FAIL;
-#endif /* __CYGWIN__ */
+#endif /* __HAVE_LOCALE_INFO__ */
   return strcpy(current_categories[category], new_categories[category]);
 }
 
@@ -885,7 +907,7 @@ struct lconv *
 _DEFUN(_localeconv_r, (data), 
       struct _reent *data)
 {
-#ifdef __CYGWIN__
+#ifdef __HAVE_LOCALE_INFO__
   if (__nlocale_changed)
     {
       struct lc_numeric_T *n = __get_current_numeric_locale ();
@@ -920,13 +942,15 @@ _DEFUN(_localeconv_r, (data), 
       lconv.int_p_sign_posn = m->p_sign_posn[0];
       __mlocale_changed = 0;
     }
-#endif /* __CYGWIN__ */
+#endif /* __HAVE_LOCALE_INFO__ */
   return (struct lconv *) &lconv;
 }
 
 #ifndef _REENT_ONLY
 
 #ifndef __CYGWIN__
+/* Cygwin provides its own version of setlocale to perform some more
+   initialization work.  It calls _setlocale_r, though. */
 char *
 _DEFUN(setlocale, (category, locale),
        int category _AND
Index: libc/include/sys/config.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/sys/config.h,v
retrieving revision 1.56
diff -u -p -r1.56 config.h
--- libc/include/sys/config.h	10 Dec 2009 17:12:11 -0000	1.56
+++ libc/include/sys/config.h	25 Feb 2010 16:07:22 -0000
@@ -190,6 +190,7 @@
 #include <cygwin/config.h>
 #define __LINUX_ERRNO_EXTENSIONS__ 1
 #define _MB_EXTENDED_CHARSETS_ALL 1
+#define __HAVE_LOCALE_INFO__ 1
 #if !defined (__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L)
 #define __USE_XOPEN2K 1
 #endif


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