3 <<newlocale>>---create or modify a locale object
13 locale_t newlocale(int <[category_mask]>, const char *<[locale]>,
16 locale_t _newlocale_r(void *<[reent]>, int <[category_mask]>,
17 const char *<[locale]>, locale_t <[locobj]>);
20 The <<newlocale>> function shall create a new locale object or modify an
21 existing one. If the base argument is (locale_t) <<0>>, a new locale
22 object shall be created. It is unspecified whether the locale object
23 pointed to by base shall be modified, or freed and a new locale object
26 The category_mask argument specifies the locale categories to be set or
27 modified. Values for category_mask shall be constructed by a
28 bitwise-inclusive OR of the symbolic constants LC_CTYPE_MASK,
29 LC_NUMERIC_MASK, LC_TIME_MASK, LC_COLLATE_MASK, LC_MONETARY_MASK, and
30 LC_MESSAGES_MASK, or any of the other implementation-defined LC_*_MASK
31 values defined in <locale.h>.
33 For each category with the corresponding bit set in category_mask the
34 data from the locale named by locale shall be used. In the case of
35 modifying an existing locale object, the data from the locale named by
36 locale shall replace the existing data within the locale object. If a
37 completely new locale object is created, the data for all sections not
38 requested by category_mask shall be taken from the default locale.
40 The following preset values of locale are defined for all settings of
43 "POSIX" Specifies the minimal environment for C-language translation
44 called the POSIX locale.
46 "C" Equivalent to "POSIX".
48 "" Specifies an implementation-defined native environment. This
49 corresponds to the value of the associated environment variables,
50 LC_* and LANG; see the Base Definitions volume of POSIX.1‐2008,
51 Chapter 7, Locale and Chapter 8, Environment Variables.
53 If the base argument is not (locale_t) <<0>> and the <<newlocale>>
54 function call succeeds, the contents of base are unspecified.
55 Applications shall ensure that they stop using base as a locale object
56 before calling <<newlocale>>. If the function call fails and the base
57 argument is not (locale_t) <<0>>, the contents of base shall remain
60 The behavior is undefined if the base argument is the special locale
61 object LC_GLOBAL_LOCALE, or is not a valid locale object handle and is
65 Upon successful completion, the <<newlocale>> function shall return a
66 handle which the caller may use on subsequent calls to <<duplocale>>,
67 <<freelocale>>, and other functions taking a locale_t argument.
69 Upon failure, the <<newlocale>> function shall return (locale_t) <<0>>
70 and set errno to indicate the error.
73 <<newlocale>> is POSIX-1.2008.
80 #include "setlocale.h"
82 #define LC_VALID_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MONETARY_MASK \
83 | LC_NUMERIC_MASK | LC_TIME_MASK | LC_MESSAGES_MASK)
86 _newlocale_r (struct _reent
*p
, int category_mask
, const char *locale
,
87 struct __locale_t
*base
)
90 return __get_C_locale ();
91 #else /* _MB_CAPABLE */
92 char new_categories
[_LC_LAST
][ENCODING_LEN
+ 1];
93 struct __locale_t tmp_locale
, *new_locale
;
96 /* Convert LC_ALL_MASK to a mask containing all valid MASK values.
97 This simplifies the code below. */
98 if (category_mask
& LC_ALL_MASK
)
100 category_mask
&= ~LC_ALL_MASK
;
101 category_mask
|= LC_VALID_MASK
;
103 /* Check for invalid mask values and valid locale ptr. */
104 if ((category_mask
& ~LC_VALID_MASK
) || !locale
)
106 _REENT_ERRNO(p
) = EINVAL
;
109 /* If the new locale is supposed to be all default locale, just return
110 a pointer to the default locale. */
111 if ((!base
&& category_mask
== 0)
112 || (category_mask
== LC_VALID_MASK
113 && (!strcmp (locale
, "C") || !strcmp (locale
, "POSIX"))))
114 return __get_C_locale ();
115 /* Start with setting all values to the default locale values. */
116 tmp_locale
= *__get_C_locale ();
117 /* Fill out new category strings. */
118 for (i
= 1; i
< _LC_LAST
; ++i
)
120 if (((1 << i
) & category_mask
) != 0)
122 /* If locale is "", fetch from environment. Otherwise use locale
124 const char *cat
= (locale
[0] == '\0') ? __get_locale_env (p
, i
)
126 if (strlen (cat
) > ENCODING_LEN
)
128 _REENT_ERRNO(p
) = EINVAL
;
131 strcpy (new_categories
[i
], cat
);
134 strcpy (new_categories
[i
], base
? base
->categories
[i
] : "C");
136 /* Now go over all categories and set them. */
137 for (i
= 1; i
< _LC_LAST
; ++i
)
139 /* If we have a base locale, and the category is not in category_mask
140 or the new category is the base categroy, just copy over. */
141 if (base
&& (((1 << i
) & category_mask
) == 0
142 || !strcmp (base
->categories
[i
], new_categories
[i
])))
144 strcpy (tmp_locale
.categories
[i
], new_categories
[i
]);
147 tmp_locale
.wctomb
= base
->wctomb
;
148 tmp_locale
.mbtowc
= base
->mbtowc
;
149 tmp_locale
.cjk_lang
= base
->cjk_lang
;
150 tmp_locale
.ctype_ptr
= base
->ctype_ptr
;
152 #ifdef __HAVE_LOCALE_INFO__
153 /* Mark the values as "has still to be copied". We do this in
154 two steps to simplify freeing new locale types in case of a
156 tmp_locale
.lc_cat
[i
].ptr
= base
->lc_cat
[i
].ptr
;
157 tmp_locale
.lc_cat
[i
].buf
= (void *) -1;
158 #else /* !__HAVE_LOCALE_INFO__ */
160 strcpy (tmp_locale
.ctype_codeset
, base
->ctype_codeset
);
161 else if (i
== LC_MESSAGES
)
162 strcpy (tmp_locale
.message_codeset
, base
->message_codeset
);
163 #endif /* !__HAVE_LOCALE_INFO__ */
165 /* Otherwise, if the category is in category_mask, create entry. */
166 else if (((1 << i
) & category_mask
) != 0)
168 /* Nothing to do for "C"/"POSIX" locale. */
169 if (!strcmp (new_categories
[i
], "C")
170 || !strcmp (new_categories
[i
], "POSIX"))
172 /* Otherwise load locale data. */
173 else if (!__loadlocale (&tmp_locale
, i
, new_categories
[i
]))
175 _REENT_ERRNO(p
) = ENOENT
;
180 /* Allocate new locale_t. */
181 new_locale
= (struct __locale_t
*) _calloc_r (p
, 1, sizeof *new_locale
);
186 #ifdef __HAVE_LOCALE_INFO__
187 /* Step 2 of copying over.. Make sure to invalidate the copied buffer
188 pointers in base, so the subsequent _freelocale_r (base) doesn't free
189 the buffers now used in the new locale. */
190 for (i
= 1; i
< _LC_LAST
; ++i
)
191 if (tmp_locale
.lc_cat
[i
].buf
== (const void *) -1)
193 tmp_locale
.lc_cat
[i
].buf
= base
->lc_cat
[i
].buf
;
194 if (base
!= __get_C_locale ())
195 base
->lc_cat
[i
].ptr
= base
->lc_cat
[i
].buf
= NULL
;
197 #endif /* __HAVE_LOCALE_INFO__ */
198 _freelocale_r (p
, base
);
201 *new_locale
= tmp_locale
;
205 /* An error occured while we had already (potentially) allocated memory.
206 Free memory and return NULL. errno is supposed to be set already. */
207 #ifdef __HAVE_LOCALE_INFO__
208 for (i
= 1; i
< _LC_LAST
; ++i
)
209 if (((1 << i
) & category_mask
) != 0
210 && tmp_locale
.lc_cat
[i
].buf
211 && tmp_locale
.lc_cat
[i
].buf
!= (const void *) -1)
213 _free_r (p
, (void *) tmp_locale
.lc_cat
[i
].ptr
);
214 _free_r (p
, tmp_locale
.lc_cat
[i
].buf
);
216 #endif /* __HAVE_LOCALE_INFO__ */
219 #endif /* _MB_CAPABLE */
223 newlocale (int category_mask
, const char *locale
, struct __locale_t
*base
)
225 return _newlocale_r (_REENT
, category_mask
, locale
, base
);