On Sun, Jul 12, 2015 at 05:51:13PM +0200, Sebastien Marie wrote:
> The patch add the following functions:
>   - newlocale(3)
>   - duplocale(3)
>   - freelocale(3)
>   - uselocale(3)
> 
> Documentation is missing for now. A separate patch will be provided.
> 

Updated patch:
  - add stubs for xlocale functions in libstubs (for release(8)
    process).

  - move uselocale() from xlocale.c to setlocale.c as it simplifies
    libstubs modification

-- 
Sebastien Marie


Index: b/include/locale.h
===================================================================
--- a/include/locale.h  2015-07-14 08:53:01.626366226 +0200
+++ b/include/locale.h  2015-07-14 09:00:05.039158777 +0200
@@ -95,6 +95,20 @@
 extern struct _locale_t _lc_global_locale;
 #define LC_GLOBAL_LOCALE (&_lc_global_locale)
 
+#define        LC_CTYPE_MASK           (1 << 0)
+#define        LC_NUMERIC_MASK         (1 << 1)
+#define        LC_TIME_MASK            (1 << 2)
+#define        LC_COLLATE_MASK         (1 << 3)
+#define        LC_MONETARY_MASK        (1 << 4)
+#define        LC_MESSAGES_MASK        (1 << 5)
+
+#define        LC_ALL_MASK             (0xff)
+
+locale_t       newlocale(int, const char *, locale_t);
+locale_t       duplocale(locale_t);
+void           freelocale(locale_t);
+locale_t       uselocale(locale_t);
+
 #endif /* __POSIX_VISIBLE >= 200809 */
 __END_DECLS
 
Index: b/lib/libc/locale/setlocale.c
===================================================================
--- a/lib/libc/locale/setlocale.c       2015-07-14 09:00:04.939159279 +0200
+++ b/lib/libc/locale/setlocale.c       2015-07-14 10:04:40.055055572 +0200
@@ -32,6 +32,7 @@
  */
 
 #include <sys/localedef.h>
+#include <errno.h>
 #include <locale.h>
 #include <limits.h>
 #include <paths.h>
@@ -300,3 +301,141 @@
 
        return env;
 }
+
+
+struct _locale_t *
+newlocale(int category_mask, const char *locale, struct _locale_t *base)
+{
+       int i, loadlocale_success;
+       struct _locale_t *newloc = NULL;
+
+       /* default value for base */
+       if (base == NULL)
+               base = &_lc_global_locale;
+
+       if ((newloc = malloc(sizeof(struct _locale_t))) == NULL)
+               /* errno from malloc */
+               return (NULL);
+
+       /* flags (not installed, no cache) */
+       newloc->flags = 0;
+
+       /* load the locale for each categories */
+       loadlocale_success = 0;
+       for (i=1; i < _LC_LAST; i++)
+               if (((i == LC_COLLATE) && (category_mask & LC_COLLATE_MASK))
+                   || ((i == LC_CTYPE) && (category_mask & LC_CTYPE_MASK))
+                   || ((i == LC_MONETARY) && (category_mask &LC_MONETARY_MASK))
+                   || ((i == LC_NUMERIC) && (category_mask & LC_NUMERIC_MASK))
+                   || ((i == LC_TIME) && (category_mask & LC_MESSAGES_MASK))) {
+
+                       if (loadlocale(i, locale, newloc) != NULL)
+                               loadlocale_success = 1;
+
+               } else {
+                       if (loadlocale(i, base->categories[i], newloc) != NULL)
+                               loadlocale_success = 1;
+               }
+
+        /* failed if all categories failed */
+       if (loadlocale_success == 0) {
+               free(newloc);
+               return (NULL);
+       }
+
+       /* free base (_lc_global_locale is discarded by freelocale) */
+       freelocale(base);
+
+       return (newloc);
+}
+
+
+struct _locale_t *
+duplocale(struct _locale_t *loc)
+{
+       int i, loadlocale_success;
+       struct _locale_t *newloc = NULL;
+
+       /* check argument */
+       if (loc == NULL) {
+               errno = EINVAL;
+               return (NULL);
+       }
+
+       /* alloc */
+       if ((newloc = malloc(sizeof(struct _locale_t))) == NULL)
+               /* errno from malloc */
+               return (NULL);
+
+       /* flags */
+       newloc->flags = 0;
+
+       /* load the locale for each categories */
+       loadlocale_success = 0;
+       for (i=1; i < _LC_LAST; i++)
+               if (loadlocale(i, loc->categories[i], newloc) != NULL)
+                       loadlocale_success = 1;
+
+       /* failed if all categories failed */
+       if (loadlocale_success == 0) {
+               free(newloc);
+               newloc = NULL;
+       }
+
+       return (newloc);
+}
+
+
+void
+freelocale(struct _locale_t *loc)
+{
+       int i;
+
+       /*
+        * discard on:
+        * - NULL
+        * - attempt to free global locale
+        * - attempt to free an currently installed locale
+        */
+       if ((loc == NULL)
+           || (loc == &_lc_global_locale)
+           || xlocale_is_installed(loc->flags))
+               return;
+
+       /* reset to default values */
+       for (i=1; i < _LC_LAST; i++)
+               loadlocale(i, "C", loc);
+
+       free(loc);
+}
+
+
+struct _locale_t *
+uselocale(struct _locale_t * newloc)
+{
+       struct _locale_t * oldloc = NULL;
+
+       /* query mode */
+       if (newloc == NULL)
+               return (_current_locale());
+
+       /* reset to global locale */
+       if (newloc == &_lc_global_locale)
+               newloc = NULL;
+
+       /* a locale is installed once: duplicate it */
+       if (xlocale_is_installed(newloc->flags))
+               if ((newloc = duplocale(newloc)) == NULL)
+                       return (NULL);
+
+       /* install the new locale */
+       newloc->flags |= XLOCALE_INSTALLED;
+       oldloc = _set_current_locale(newloc);
+
+       /* clear install flag on old locale */
+       if (oldloc != &_lc_global_locale)
+               oldloc->flags &= ~XLOCALE_INSTALLED;
+
+       return (oldloc);
+}
+
Index: b/distrib/special/libstubs/setlocale.c
===================================================================
--- a/distrib/special/libstubs/setlocale.c      2005-08-04 00:33:59.000000000 
+0200
+++ b/distrib/special/libstubs/setlocale.c      2015-07-14 09:03:50.690609781 
+0200
@@ -8,3 +8,26 @@
 {
        return 0;
 }
+
+void *
+newlocale(int cat, const char *locale, void *base)
+{
+       return 0;
+}
+
+void *
+duplocale(void *locale)
+{
+       return 0;
+}
+
+void *
+freelocale(void *locale)
+{
+}
+
+void *
+uselocale(void *locale)
+{
+       return 0;
+}

Reply via email to