Print this page
2964 need POSIX 2008 locale object support

@@ -1,10 +1,15 @@
 /*
  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
  * All rights reserved.
  *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.

@@ -27,14 +32,14 @@
 
 #include "lint.h"
 #include <limits.h>
 #include <stddef.h>
 #include <stdlib.h>
+
 #include "ldpart.h"
 #include "lmonetary.h"
 
-extern int __mlocale_changed;
 extern const char *__fix_locale_grouping_str(const char *);
 
 #define LCMONETARY_SIZE_FULL (sizeof (struct lc_monetary_T) / sizeof (char *))
 #define LCMONETARY_SIZE_MIN \
         (offsetof(struct lc_monetary_T, int_p_cs_precedes) / sizeof (char *))

@@ -68,38 +73,53 @@
 
 static struct lc_monetary_T _monetary_locale;
 static int      _monetary_using_locale;
 static char     *_monetary_locale_buf;
 
+struct xlocale_monetary __xlocale_global_monetary;
+
 static char
 cnv(const char *str)
 {
         int i = strtol(str, NULL, 10);
 
         if (i == -1)
                 i = CHAR_MAX;
         return ((char)i);
 }
 
-int
-__monetary_load_locale(const char *name)
+static void
+destruct_monetary(void *v)
+{
+        struct xlocale_monetary *l = v;
+
+        if (l->buffer != NULL)
+                free(l->buffer);
+
+        free(l);
+}
+
+static int
+monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale,
+    int *changed, const char *name)
 {
         int ret;
+        struct lc_monetary_T *l = &loc->locale;
 
-        ret = __part_load_locale(name, &_monetary_using_locale,
-            &_monetary_locale_buf, "LC_MONETARY",
+        ret = __part_load_locale(name, using_locale,
+            &loc->buffer, "LC_MONETARY",
             LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
-            (const char **)&_monetary_locale);
+            (const char **)l);
         if (ret != _LDP_ERROR)
-                __mlocale_changed = 1;
+                *changed = 1;
         if (ret == _LDP_LOADED) {
-                _monetary_locale.mon_grouping =
-                    __fix_locale_grouping_str(_monetary_locale.mon_grouping);
+                l->mon_grouping =
+                    __fix_locale_grouping_str(l->mon_grouping);
 
 #define M_ASSIGN_CHAR(NAME) \
-                (((char *)_monetary_locale.NAME)[0] = \
-                        cnv(_monetary_locale.NAME))
+                (((char *)l->NAME)[0] = \
+                        cnv(l->NAME))
 
                 M_ASSIGN_CHAR(int_frac_digits);
                 M_ASSIGN_CHAR(frac_digits);
                 M_ASSIGN_CHAR(p_cs_precedes);
                 M_ASSIGN_CHAR(p_sep_by_space);

@@ -112,15 +132,17 @@
                  * The six additional C99 international monetary formatting
                  * parameters default to the national parameters when
                  * reading FreeBSD LC_MONETARY data files.
                  */
 #define M_ASSIGN_ICHAR(NAME)                                    \
-                if (_monetary_locale.int_##NAME == NULL)        \
-                        _monetary_locale.int_##NAME =           \
-                            _monetary_locale.NAME;              \
+                do {                                            \
+                        if (l->int_##NAME == NULL)              \
+                                l->int_##NAME =                 \
+                                    l->NAME;                    \
                 else                                            \
-                        M_ASSIGN_CHAR(int_##NAME);
+                                M_ASSIGN_CHAR(int_##NAME);      \
+                } while (0)
 
                 M_ASSIGN_ICHAR(p_cs_precedes);
                 M_ASSIGN_ICHAR(n_cs_precedes);
                 M_ASSIGN_ICHAR(p_sep_by_space);
                 M_ASSIGN_ICHAR(n_sep_by_space);

@@ -128,11 +150,39 @@
                 M_ASSIGN_ICHAR(n_sign_posn);
         }
         return (ret);
 }
 
+int
+__monetary_load_locale(const char *name)
+{
+        return (monetary_load_locale_l(&__xlocale_global_monetary,
+            &__xlocale_global_locale.using_monetary_locale,
+            &__xlocale_global_locale.monetary_locale_changed, name));
+}
+
+void *
+__monetary_load(const char *name, locale_t loc)
+{
+        struct xlocale_monetary *new;
+
+        new = calloc(sizeof(struct xlocale_monetary), 1);
+        if (new == NULL)
+                return (NULL);
+
+        new->header.header.destructor = destruct_monetary;
+        if (monetary_load_locale_l(new, &loc->using_monetary_locale,
+            &loc->monetary_locale_changed, name) == _LDP_ERROR) {
+                xlocale_release(new);
+                return (NULL);
+        }
+
+        return (NULL);
+}
+
 struct lc_monetary_T *
-__get_current_monetary_locale(void)
+__get_current_monetary_locale(locale_t loc)
 {
-        return (_monetary_using_locale ? &_monetary_locale :
-            (struct lc_monetary_T *)&_C_monetary_locale);
+        return (loc->using_monetary_locale
+            ? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale
+            : (struct lc_monetary_T *)&_C_monetary_locale);
 }