1 /*
   2  * Copyright (c) 2011 The FreeBSD Foundation
   3  * All rights reserved.
   4  *
   5  * This software was developed by David Chisnall under sponsorship from
   6  * the FreeBSD Foundation.
   7  *
   8  * Redistribution and use in source and binary forms, with or without
   9  * modification, are permitted provided that the following conditions
  10  * are met:
  11  * 1. Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 #ifndef _XLOCALE_PRIVATE__H_
  31 #define _XLOCALE_PRIVATE__H_
  32 
  33 //#include <xlocale.h> /* XXX */
  34 #include <locale.h>
  35 #include <stdlib.h>
  36 #include <stdint.h>
  37 #include <sys/types.h>
  38 #include "setlocale.h"
  39 #include <wchar_impl.h>   /* XXX */
  40 
  41 enum {
  42         XLC_COLLATE = 0,
  43         XLC_CTYPE,
  44         XLC_MONETARY,
  45         XLC_NUMERIC,
  46         XLC_TIME,
  47         XLC_MESSAGES,
  48         XLC_LAST
  49 };
  50 
  51 
  52 /*
  53  * Header used for objects that are reference counted.  Objects may optionally
  54  * have a destructor associated, which is responsible for destroying the
  55  * structure.  Global / static versions of the structure should have no
  56  * destructor set - they can then have their reference counts manipulated as
  57  * normal, but will not do anything with them.
  58  *
  59  * The header stores a retain count - objects are assumed to have a reference
  60  * count of 1 when they are created, but the retain count is 0.  When the
  61  * retain count is less than 0, they are freed.
  62  */
  63 struct xlocale_refcounted {
  64         /* Number of references to this component. */
  65         long retain_count;
  66         /* Function used to destroy this component, if one is required */
  67         void(*destructor)(void*);
  68 };
  69 
  70 /*
  71  * Header for a locale component.  All locale components must begin with this
  72  * header.
  73  */
  74 struct xlocale_component {
  75         struct xlocale_refcounted header;
  76         /* Name of the locale used for this component. */
  77         char locale[ENCODING_LEN+1];
  78 };
  79 
  80 /*
  81  * xlocale structure, stores per-thread locale information.  
  82  */
  83 struct _xlocale {
  84         struct xlocale_refcounted header;
  85         /* Components for the locale. */
  86         struct xlocale_component *components[XLC_LAST];
  87         /*
  88          * Flag indicating if components[XLC_MONETARY] has changed since the
  89          * last call to localeconv_l() with this locale.
  90          */
  91         int monetary_locale_changed;
  92         /** Flag indicating whether this locale is actually using a locale for
  93          * LC_MONETARY (1), or if it should use the C default instead (0). */
  94         int using_monetary_locale;
  95         /** Flag indicating if components[XLC_NUMERIC] has changed since the
  96          * last call to localeconv_l() with this locale. */
  97         int numeric_locale_changed;
  98         /** Flag indicating whether this locale is actually using a locale for
  99          * LC_NUMERIC (1), or if it should use the C default instead (0). */
 100         int using_numeric_locale;
 101         /** Flag indicating whether this locale is actually using a locale for
 102          * LC_TIME (1), or if it should use the C default instead (0). */
 103         int using_time_locale;
 104         /** Flag indicating whether this locale is actually using a locale for
 105          * LC_MESSAGES (1), or if it should use the C default instead (0). */
 106         int using_messages_locale;
 107         /** The structure to be returned from localeconv_l() for this locale. */
 108         struct lconv lconv;
 109         /** Persistent state used by mblen() calls. */
 110         __mbstate_t mblen;
 111         /** Persistent state used by mbrlen() calls. */
 112         __mbstate_t mbrlen;
 113         /** Persistent state used by mbrtoc16() calls. */
 114         __mbstate_t mbrtoc16;
 115         /** Persistent state used by mbrtoc32() calls. */
 116         __mbstate_t mbrtoc32;
 117         /** Persistent state used by mbrtowc() calls. */
 118         __mbstate_t mbrtowc;
 119         /** Persistent state used by mbsnrtowcs() calls. */
 120         __mbstate_t mbsnrtowcs;
 121         /** Persistent state used by mbsrtowcs() calls. */
 122         __mbstate_t mbsrtowcs;
 123         /** Persistent state used by mbtowc() calls. */
 124         __mbstate_t mbtowc;
 125         /** Persistent state used by c16rtomb() calls. */
 126         __mbstate_t c16rtomb;
 127         /** Persistent state used by c32rtomb() calls. */
 128         __mbstate_t c32rtomb;
 129         /** Persistent state used by wcrtomb() calls. */
 130         __mbstate_t wcrtomb;
 131         /** Persistent state used by wcsnrtombs() calls. */
 132         __mbstate_t wcsnrtombs;
 133         /** Persistent state used by wcsrtombs() calls. */
 134         __mbstate_t wcsrtombs;
 135         /** Persistent state used by wctomb() calls. */
 136         __mbstate_t wctomb;
 137         /** Buffer used by nl_langinfo_l() */
 138         char *csym;
 139 };
 140 
 141 /*
 142  * XXX freebsd-head/include/xlocale/_ctype.h
 143  */
 144 // typedef struct _xlocale *locale_t;
 145 #define LC_GLOBAL_LOCALE        ((locale_t)-1)
 146 
 147 /*
 148  * Increments the reference count of a reference-counted structure.
 149  */
 150 __attribute__((unused)) static void*
 151 xlocale_retain(void *val)
 152 {
 153         struct xlocale_refcounted *obj = val;
 154         //atomic_add_long(&(obj->retain_count), 1); /* XXX */
 155         return (val);
 156 }
 157 
 158 /**
 159  * Decrements the reference count of a reference-counted structure, freeing it
 160  * if this is the last reference, calling its destructor if it has one.
 161  */
 162 __attribute__((unused)) static void
 163 xlocale_release(void *val)
 164 {
 165         struct xlocale_refcounted *obj = val;
 166         long count = 0; // atomic_fetchadd_long(&(obj->retain_count), -1) - 1; /* XXX */
 167         if (count < 0) {
 168                 if (0 != obj->destructor) {
 169                         obj->destructor(obj);
 170                 }
 171         }
 172 }
 173 
 174 /**
 175  * Load functions.  Each takes the name of a locale and a pointer to the data
 176  * to be initialised as arguments.  Two special values are allowed for the 
 177  */
 178 extern void     *__collate_load(const char*, locale_t);
 179 extern void     *__ctype_load(const char*, locale_t);
 180 extern void     *__messages_load(const char*, locale_t);
 181 extern void     *__monetary_load(const char*, locale_t);
 182 extern void     *__numeric_load(const char*, locale_t);
 183 extern void     *__time_load(const char*, locale_t);
 184 
 185 extern struct _xlocale __xlocale_global_locale;
 186 extern struct _xlocale __xlocale_C_locale;
 187 
 188 /**
 189  * Caches the rune table in TLS for fast access.
 190  */
 191 void __set_thread_rune_locale(locale_t loc);
 192 /**
 193  * Flag indicating whether a per-thread locale has been set.  If no per-thread
 194  * locale has ever been set, then we always use the global locale.
 195  */
 196 extern int __has_thread_locale;
 197 
 198 #ifndef __NO_TLS
 199 /*
 200  * The per-thread locale.  Avoids the need to use pthread lookup functions when
 201  * getting the per-thread locale.
 202  */
 203 extern __thread locale_t __thread_locale;
 204 
 205 /**
 206  * Returns the current locale for this thread, or the global locale if none is
 207  * set.  The caller does not have to free the locale.  The return value from
 208  * this call is not guaranteed to remain valid after the locale changes.  As
 209  * such, this should only be called within libc functions.
 210  */
 211 static inline locale_t __get_locale(void)
 212 {
 213 
 214         if (!__has_thread_locale) {
 215                 return (&__xlocale_global_locale);
 216         }
 217         return (__thread_locale ? __thread_locale : &__xlocale_global_locale);
 218 }
 219 #else
 220 locale_t __get_locale(void);
 221 #endif
 222 
 223 /**
 224  * Two magic values are allowed for locale_t objects.  NULL and -1.  This
 225  * function maps those to the real locales that they represent.
 226  */
 227 static inline locale_t get_real_locale(locale_t locale)
 228 {
 229         switch ((intptr_t)locale) {
 230                 case 0: return (&__xlocale_C_locale);
 231                 case -1: return (&__xlocale_global_locale);
 232                 default: return (locale);
 233         }
 234 }
 235 
 236 /**
 237  * Replace a placeholder locale with the real global or thread-local locale_t.
 238  */
 239 #define FIX_LOCALE(l) (l = get_real_locale(l))
 240 
 241 #endif