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;
+}