gcc50: Change c++ locale handling
authorJohn Marino <draco@marino.st>
Sat, 18 Jul 2015 22:22:03 +0000 (00:22 +0200)
committerJohn Marino <draco@marino.st>
Sat, 18 Jul 2015 22:30:06 +0000 (00:30 +0200)
The biggest change is removing the modification of the specified locale.
Before locales without extensions were appended with ".UTF-8" and
modifiers (e.g. @euro) were silently stripped off.

The latter is probably a bad idea, and even if we want to continue doing
this (modifiers are not supported), it should be done at the library
level, not at c++ on gcc level.  The no-extension problem has been solved
today by creating symlinks at /usr/share/locale.

The logic of the "gnu" support was mimicked by using newlocale, duplocale,
and freelocale.  The generic version uses setlocale only.  This patch will
be pushed upstream most likely.

contrib/gcc-5.0/README.DRAGONFLY
contrib/gcc-5.0/libstdc++-v3/config/locale/dragonfly/c_locale.cc

index 415cca6..241d0e0 100644 (file)
@@ -23,3 +23,4 @@ The following files have been patched (* planned)
   gcc/ginclude/stddef.h
 * gcc/tree-inline.c
   libstdc++-v3/config/os/bsd/dragonfly/os_defines.h
+  libstdc++-v3/config/locale/dragonfly/c_locale.cc
index dea7a39..18c6ad7 100644 (file)
@@ -36,6 +36,7 @@
 #include <locale>
 #include <limits>
 
+#include <xlocale.h>
 #ifdef _GLIBCXX_HAVE_IEEEFP_H
 #include <ieeefp.h>
 #endif
@@ -206,61 +207,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       delete [] __sav;
     }
 
-
-  /*  DragonFly's implementation of setlocale won't accept something like
-      "de_DE".  According to nls manpage, the expected format is:
-      language[_territory][.codeset][@modifier], but it seems that both
-      the _territory and .codeset components are required.
-      
-      As an attempt to correct for this, we'll tack on ".UTF-8" if 
-      a period is not detected in the locale string.  
-
-      There are no locales with modifiers on DragonFly so if found, they
-      will just be stripped off silently.  e.g "de_DE@euro" will be reduced
-      to "de_DE".  The UTF-8 default would be added after that.
-  */
-
   void
   locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
-                                   __c_locale)
+                                   __c_locale __old)
   {
-    const size_t size__s = (__s == NULL) ? 1 : strlen (__s);
-    const char UTF8[] = ".UTF-8";
-    char localspec[size__s + 6 + 1];
-    
-    if (__s == NULL) {
-       localspec[0] = '\0';
-    } else {
-       strcpy (localspec, __s);
-       char * pch = strchr (localspec, '@');
-       if (pch != NULL)
-          *pch = 0;
-
-       if (  (strchr (__s, '.') == NULL)
-          && (strcmp (__s, "C") != 0)
-          && (strcmp (__s, "POSIX") != 0))
-          strncat (localspec, UTF8, 6);
-    }
-
-    const char * result = std::setlocale(LC_ALL, localspec);
+    __cloc = (__c_locale)newlocale(LC_ALL_MASK, __s, (locale_t)__old);
     
-    if ((strcmp(result, "C") != 0) && (strcmp (result, localspec) != 0))
+    if (!__cloc)
       __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
                            "name not valid"));
-    __cloc = 0;
   }
 
   void
   locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
-  { __cloc = 0; }
+  {
+    if (__cloc && _S_get_c_locale() != __cloc)
+      freelocale((locale_t)__cloc);
+  }
 
   __c_locale
-  locale::facet::_S_clone_c_locale(__c_locale&) throw()
-  { return __c_locale(); }
+  locale::facet::_S_clone_c_locale(__c_locale& __cloc) throw()
+  { return (__c_locale)duplocale((locale_t)__cloc); }
 
   __c_locale
-  locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*)
-  { return __c_locale(); }
+  locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s)
+  {
+    __c_locale __dup = (__c_locale)duplocale((locale_t)__cloc);
+    if (__dup == __c_locale(0))
+      __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
+                               "duplocale error"));
+    __c_locale __changed = (__c_locale)newlocale(LC_CTYPE_MASK, __s,
+                                                   (locale_t)__dup);
+    if (__changed == __c_locale(0))
+      {
+       freelocale((locale_t)__dup);
+       __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
+                                 "newlocale error"));
+      }
+    return __changed;
+  }
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace