]> git.ipfire.org Git - thirdparty/glibc.git/blame - wcsmbs/wcsmbsload.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / wcsmbs / wcsmbsload.c
CommitLineData
b168057a 1/* Copyright (C) 1998-2015 Free Software Foundation, Inc.
4bca4c17
UD
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
4bca4c17
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
4bca4c17 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
4bca4c17 18
e4d0709f 19#include <ctype.h>
4bca4c17
UD
20#include <langinfo.h>
21#include <limits.h>
4553f228
UD
22#include <stdlib.h>
23#include <string.h>
4bca4c17 24
4553f228 25#include <locale/localeinfo.h>
4bca4c17
UD
26#include <wcsmbsload.h>
27#include <bits/libc-lock.h>
4bca4c17
UD
28
29
4bca4c17 30/* These are the descriptions for the default conversion functions. */
bd62cef6 31static const struct __gconv_step to_wc =
4bca4c17 32{
d64b6ad0
UD
33 .__shlib_handle = NULL,
34 .__modname = NULL,
35 .__counter = INT_MAX,
129d706d
UD
36 .__from_name = (char *) "ANSI_X3.4-1968//TRANSLIT",
37 .__to_name = (char *) "INTERNAL",
d64b6ad0 38 .__fct = __gconv_transform_ascii_internal,
f9ad060c 39 .__btowc_fct = __gconv_btwoc_ascii,
d64b6ad0
UD
40 .__init_fct = NULL,
41 .__end_fct = NULL,
42 .__min_needed_from = 1,
43 .__max_needed_from = 1,
44 .__min_needed_to = 4,
45 .__max_needed_to = 4,
46 .__stateful = 0,
47 .__data = NULL
4bca4c17
UD
48};
49
bd62cef6 50static const struct __gconv_step to_mb =
4bca4c17 51{
d64b6ad0
UD
52 .__shlib_handle = NULL,
53 .__modname = NULL,
54 .__counter = INT_MAX,
129d706d
UD
55 .__from_name = (char *) "INTERNAL",
56 .__to_name = (char *) "ANSI_X3.4-1968//TRANSLIT",
d64b6ad0 57 .__fct = __gconv_transform_internal_ascii,
f9ad060c 58 .__btowc_fct = NULL,
d64b6ad0
UD
59 .__init_fct = NULL,
60 .__end_fct = NULL,
61 .__min_needed_from = 4,
62 .__max_needed_from = 4,
63 .__min_needed_to = 1,
64 .__max_needed_to = 1,
65 .__stateful = 0,
66 .__data = NULL
4bca4c17
UD
67};
68
69
70/* For the default locale we only have to handle ANSI_X3.4-1968. */
96310297 71const struct gconv_fcts __wcsmbs_gconv_fcts_c =
4bca4c17 72{
bd62cef6 73 .towc = (struct __gconv_step *) &to_wc,
129d706d 74 .towc_nsteps = 1,
bd62cef6 75 .tomb = (struct __gconv_step *) &to_mb,
db6af3eb 76 .tomb_nsteps = 1,
4bca4c17
UD
77};
78
79
01beb5b9 80attribute_hidden
c4bb5cd8 81struct __gconv_step *
01beb5b9 82__wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp)
4bca4c17
UD
83{
84 size_t nsteps;
d64b6ad0 85 struct __gconv_step *result;
129d706d 86#if 0
d64b6ad0
UD
87 size_t nstateful;
88 size_t cnt;
129d706d 89#endif
4bca4c17 90
c90a2db6 91 if (__gconv_find_transform (to, from, &result, &nsteps, 0) != __GCONV_OK)
4bca4c17
UD
92 /* Loading the conversion step is not possible. */
93 return NULL;
94
129d706d
UD
95 /* Maybe it is someday necessary to allow more than one step.
96 Currently this is not the case since the conversions handled here
97 are from and to INTERNAL and there always is a converted for
98 that. It the directly following code is enabled the libio
99 functions will have to allocate appropriate __gconv_step_data
100 elements instead of only one. */
101#if 0
d64b6ad0
UD
102 /* Count the number of stateful conversions. Since we will only
103 have one 'mbstate_t' object available we can only deal with one
104 stateful conversion. */
105 nstateful = 0;
106 for (cnt = 0; cnt < nsteps; ++cnt)
107 if (result[cnt].__stateful)
108 ++nstateful;
109 if (nstateful > 1)
129d706d
UD
110#else
111 if (nsteps > 1)
112#endif
d64b6ad0
UD
113 {
114 /* We cannot handle this case. */
115 __gconv_close_transform (result, nsteps);
116 result = NULL;
117 }
129d706d
UD
118 else
119 *nstepsp = nsteps;
4bca4c17
UD
120
121 return result;
122}
123
124
4553f228
UD
125/* Extract from the given locale name the character set portion. Since
126 only the XPG form of the name includes this information we don't have
127 to take care for the CEN form. */
128#define extract_charset_name(str) \
129 ({ \
130 const char *cp = str; \
131 char *result = NULL; \
132 \
b17277cf 133 cp += strcspn (cp, "@.+,"); \
4553f228
UD
134 if (*cp == '.') \
135 { \
a7c378d8 136 const char *endp = ++cp; \
4553f228
UD
137 while (*endp != '\0' && *endp != '@') \
138 ++endp; \
139 if (endp != cp) \
a7c378d8 140 result = strndupa (cp, endp - cp); \
4553f228
UD
141 } \
142 result; \
4553f228
UD
143 })
144
145
96310297 146/* Some of the functions here must not be used while setlocale is called. */
91e32540 147__libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
d64b6ad0 148
4bca4c17
UD
149/* Load conversion functions for the currently selected locale. */
150void
00995ca9 151internal_function
f095bb72 152__wcsmbs_load_conv (struct __locale_data *new_category)
4bca4c17 153{
4bca4c17 154 /* Acquire the lock. */
91e32540 155 __libc_rwlock_wrlock (__libc_setlocale_lock);
4bca4c17 156
61d655c1 157 /* We should repeat the test since while we waited some other thread
4bca4c17 158 might have run this function. */
a1ffb40e 159 if (__glibc_likely (new_category->private.ctype == NULL))
4bca4c17 160 {
96310297
RM
161 /* We must find the real functions. */
162 const char *charset_name;
163 const char *complete_name;
164 struct gconv_fcts *new_fcts;
165 int use_translit;
166
167 /* Allocate the gconv_fcts structure. */
9954432e 168 new_fcts = calloc (1, sizeof *new_fcts);
96310297 169 if (new_fcts == NULL)
6e606fad 170 goto failed;
96310297
RM
171
172 /* Get name of charset of the locale. */
173 charset_name = new_category->values[_NL_ITEM_INDEX(CODESET)].string;
174
175 /* Does the user want transliteration? */
176 use_translit = new_category->use_translit;
177
178 /* Normalize the name and add the slashes necessary for a
179 complete lookup. */
180 complete_name = norm_add_slashes (charset_name,
db2f05ba 181 use_translit ? "TRANSLIT" : "");
96310297
RM
182
183 /* It is not necessary to use transliteration in this direction
184 since the internal character set is supposed to be able to
185 represent all others. */
186 new_fcts->towc = __wcsmbs_getfct ("INTERNAL", complete_name,
187 &new_fcts->towc_nsteps);
9954432e
UD
188 if (new_fcts->towc != NULL)
189 new_fcts->tomb = __wcsmbs_getfct (complete_name, "INTERNAL",
190 &new_fcts->tomb_nsteps);
96310297
RM
191
192 /* If any of the conversion functions is not available we don't
193 use any since this would mean we cannot convert back and
d3ed7225 194 forth. NB: NEW_FCTS was allocated with calloc. */
96310297 195 if (new_fcts->tomb == NULL)
4bca4c17 196 {
96310297
RM
197 if (new_fcts->towc != NULL)
198 __gconv_close_transform (new_fcts->towc, new_fcts->towc_nsteps);
199
200 free (new_fcts);
4bca4c17 201
6e606fad
RM
202 failed:
203 new_category->private.ctype = &__wcsmbs_gconv_fcts_c;
204 }
205 else
206 {
207 new_category->private.ctype = new_fcts;
208 new_category->private.cleanup = &_nl_cleanup_ctype;
209 }
4bca4c17
UD
210 }
211
91e32540 212 __libc_rwlock_unlock (__libc_setlocale_lock);
4bca4c17 213}
d64b6ad0
UD
214
215
216/* Clone the current conversion function set. */
217void
218internal_function
219__wcsmbs_clone_conv (struct gconv_fcts *copy)
220{
96310297 221 const struct gconv_fcts *orig;
34e3c127 222
96310297 223 orig = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
d64b6ad0
UD
224
225 /* Copy the data. */
96310297 226 *copy = *orig;
d64b6ad0 227
f9ad060c 228 /* Now increment the usage counters.
9954432e 229 Note: This assumes copy->*_nsteps == 1. */
d64b6ad0
UD
230 if (copy->towc->__shlib_handle != NULL)
231 ++copy->towc->__counter;
232 if (copy->tomb->__shlib_handle != NULL)
233 ++copy->tomb->__counter;
d64b6ad0 234}
4e2e9999
UD
235
236
129d706d 237/* Get converters for named charset. */
4e2e9999
UD
238int
239internal_function
240__wcsmbs_named_conv (struct gconv_fcts *copy, const char *name)
241{
01beb5b9 242 copy->towc = __wcsmbs_getfct ("INTERNAL", name, &copy->towc_nsteps);
db6af3eb
UD
243 if (copy->towc == NULL)
244 return 1;
245
246 copy->tomb = __wcsmbs_getfct (name, "INTERNAL", &copy->tomb_nsteps);
247 if (copy->tomb == NULL)
4e2e9999 248 {
db6af3eb 249 __gconv_close_transform (copy->towc, copy->towc_nsteps);
db6af3eb 250 return 1;
4e2e9999
UD
251 }
252
db6af3eb 253 return 0;
129d706d 254}
4e2e9999 255
96310297 256void internal_function
f095bb72 257_nl_cleanup_ctype (struct __locale_data *locale)
129d706d 258{
96310297
RM
259 const struct gconv_fcts *const data = locale->private.ctype;
260 if (data != NULL)
129d706d 261 {
96310297
RM
262 locale->private.ctype = NULL;
263 locale->private.cleanup = NULL;
129d706d 264
96310297
RM
265 /* Free the old conversions. */
266 __gconv_close_transform (data->tomb, data->tomb_nsteps);
267 __gconv_close_transform (data->towc, data->towc_nsteps);
268 free ((char *) data);
129d706d 269 }
4e2e9999 270}