1 /* Copyright (C) 1997-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #ifndef _GCONV_INT_H
19 #define _GCONV_INT_H	1
20 
21 #include "gconv.h"
22 #include <stdlib.h>		/* For alloca used in macro below.  */
23 #include <ctype.h>		/* For __toupper_l used in macro below.  */
24 #include <string.h>		/* For strlen et al used in macro below.  */
25 #include <libc-lock.h>
26 
27 __BEGIN_DECLS
28 
29 
30 /* Structure for alias definition.  Simply two strings.  */
31 struct gconv_alias
32 {
33   char *fromname;
34   char *toname;
35 };
36 
37 
38 /* Structure describing one loaded shared object.  This normally are
39    objects to perform conversation but as a special case the db shared
40    object is also handled.  */
41 struct __gconv_loaded_object
42 {
43   /* Name of the object.  It must be the first structure element.  */
44   const char *name;
45 
46   /* Reference counter for the db functionality.  If no conversion is
47      needed we unload the db library.  */
48   int counter;
49 
50   /* The handle for the shared object.  */
51   void *handle;
52 
53   /* Pointer to the functions the module defines.  */
54   __gconv_fct fct;
55   __gconv_init_fct init_fct;
56   __gconv_end_fct end_fct;
57 };
58 
59 
60 /* Description for an available conversion module.  */
61 struct gconv_module
62 {
63   const char *from_string;
64   const char *to_string;
65 
66   int cost_hi;
67   int cost_lo;
68 
69   const char *module_name;
70 
71   struct gconv_module *left;	/* Prefix smaller.  */
72   struct gconv_module *same;	/* List of entries with identical prefix.  */
73   struct gconv_module *right;	/* Prefix larger.  */
74 };
75 
76 
77 /* The specification of the conversion that needs to be performed.  */
78 struct gconv_spec
79 {
80   char *fromcode;
81   char *tocode;
82   bool translit;
83   bool ignore;
84 };
85 
86 /* Flags for `gconv_open'.  */
87 enum
88 {
89   GCONV_AVOID_NOCONV = 1 << 0
90 };
91 
92 /* When GCONV_AVOID_NOCONV is set and no conversion is needed,
93    __GCONV_NULCONV should be returned.  */
94 enum
95 {
96   __GCONV_NULCONV = -1
97 };
98 
99 /* Global variables.  */
100 
101 /* Database of alias names.  */
102 extern void *__gconv_alias_db attribute_hidden;
103 
104 /* Array with available modules.  */
105 extern struct gconv_module *__gconv_modules_db attribute_hidden;
106 
107 /* Value of the GCONV_PATH environment variable.  */
108 extern const char *__gconv_path_envvar attribute_hidden;
109 
110 /* Lock for the conversion database content.  */
111 __libc_lock_define (extern, __gconv_lock attribute_hidden)
112 
113 
114 /* The gconv functions expects the name to be in upper case and complete,
115    including the trailing slashes if necessary.  */
116 #define norm_add_slashes(str,suffix) \
117   ({									      \
118     const char *cp = (str);						      \
119     char *result;							      \
120     char *tmp;								      \
121     size_t cnt = 0;							      \
122     const size_t suffix_len = strlen (suffix);				      \
123 									      \
124     while (*cp != '\0')							      \
125       if (*cp++ == '/')							      \
126 	++cnt;								      \
127 									      \
128     tmp = result = __alloca (cp - (str) + 3 + suffix_len);		      \
129     cp = (str);								      \
130     while (*cp != '\0')							      \
131       *tmp++ = __toupper_l (*cp++, _nl_C_locobj_ptr);			      \
132     if (cnt < 2)							      \
133       {									      \
134 	*tmp++ = '/';							      \
135 	if (cnt < 1)							      \
136 	  {								      \
137 	    *tmp++ = '/';						      \
138 	    if (suffix_len != 0)					      \
139 	      tmp = __mempcpy (tmp, suffix, suffix_len);		      \
140 	  }								      \
141       }									      \
142     *tmp = '\0';							      \
143     result;								      \
144   })
145 
146 
147 /* Return in *HANDLE, a decriptor for the transformation.  The function expects
148    the specification of the transformation in the structure pointed to by
149    CONV_SPEC.  It only reads *CONV_SPEC and does not take ownership of it.  */
150 extern int __gconv_open (struct gconv_spec *conv_spec,
151                          __gconv_t *handle, int flags);
152 libc_hidden_proto (__gconv_open)
153 
154 /* This function accepts the charset names of the source and destination of the
155    conversion and populates *conv_spec with an equivalent conversion
156    specification that may later be used by __gconv_open.  The charset names
157    might contain options in the form of suffixes that alter the conversion,
158    e.g. "ISO-10646/UTF-8/TRANSLIT".  It processes the charset names, ignoring
159    and truncating any suffix options in fromcode, and processing and truncating
160    any suffix options in tocode.  Supported suffix options ("TRANSLIT" or
161    "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec
162    to be set to true.  Unrecognized suffix options are silently discarded.  If
163    the function succeeds, it returns conv_spec back to the caller.  It returns
164    NULL upon failure.  */
165 extern struct gconv_spec *
166 __gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode,
167                      const char *tocode);
168 libc_hidden_proto (__gconv_create_spec)
169 
170 /* This function frees all heap memory allocated by __gconv_create_spec.  */
171 extern void
172 __gconv_destroy_spec (struct gconv_spec *conv_spec);
173 libc_hidden_proto (__gconv_destroy_spec)
174 
175 /* Free resources associated with transformation descriptor CD.  */
176 extern int __gconv_close (__gconv_t cd)
177      attribute_hidden;
178 
179 /* Transform at most *INBYTESLEFT bytes from buffer starting at *INBUF
180    according to rules described by CD and place up to *OUTBYTESLEFT
181    bytes in buffer starting at *OUTBUF.  Return number of non-identical
182    conversions in *IRREVERSIBLE if this pointer is not null.  */
183 extern int __gconv (__gconv_t cd, const unsigned char **inbuf,
184 		    const unsigned char *inbufend, unsigned char **outbuf,
185 		    unsigned char *outbufend, size_t *irreversible)
186      attribute_hidden;
187 
188 /* Return in *HANDLE a pointer to an array with *NSTEPS elements describing
189    the single steps necessary for transformation from FROMSET to TOSET.  */
190 extern int __gconv_find_transform (const char *toset, const char *fromset,
191 				   struct __gconv_step **handle,
192 				   size_t *nsteps, int flags)
193      attribute_hidden;
194 
195 /* Search for transformation in cache data.  */
196 extern int __gconv_lookup_cache (const char *toset, const char *fromset,
197 				 struct __gconv_step **handle, size_t *nsteps,
198 				 int flags)
199      attribute_hidden;
200 
201 /* Compare the two name for whether they are after alias expansion the
202    same.  This function uses the cache and fails if none is
203    loaded.  */
204 extern int __gconv_compare_alias_cache (const char *name1, const char *name2,
205 					int *result)
206      attribute_hidden;
207 
208 /* Free data associated with a step's structure.  */
209 extern void __gconv_release_step (struct __gconv_step *step)
210      attribute_hidden;
211 
212 /* Read all the configuration data and cache it if not done so already.  */
213 extern void __gconv_load_conf (void) attribute_hidden;
214 
215 /* Try to read module cache file.  */
216 extern int __gconv_load_cache (void) attribute_hidden;
217 
218 /* Retrieve pointer to internal cache.  */
219 extern void *__gconv_get_cache (void);
220 
221 /* Retrieve pointer to internal module database.  */
222 extern struct gconv_module *__gconv_get_modules_db (void);
223 
224 /* Retrieve pointer to internal alias database.  */
225 extern void *__gconv_get_alias_db (void);
226 
227 /* Comparison function to search alias.  */
228 extern int __gconv_alias_compare (const void *p1, const void *p2)
229      attribute_hidden;
230 
231 /* Clear reference to transformation step implementations which might
232    cause the code to be unloaded.  */
233 extern int __gconv_close_transform (struct __gconv_step *steps,
234 				    size_t nsteps)
235      attribute_hidden;
236 
237 /* Free all resources allocated for the transformation record when
238    using the cache.  */
239 extern void __gconv_release_cache (struct __gconv_step *steps, size_t nsteps)
240      attribute_hidden;
241 
242 /* Load shared object named by NAME.  If already loaded increment reference
243    count.  */
244 extern struct __gconv_loaded_object *__gconv_find_shlib (const char *name)
245      attribute_hidden;
246 
247 /* Release shared object.  If no further reference is available unload
248    the object.  */
249 extern void __gconv_release_shlib (struct __gconv_loaded_object *handle)
250      attribute_hidden;
251 
252 /* Fill STEP with information about builtin module with NAME.  */
253 extern void __gconv_get_builtin_trans (const char *name,
254 				       struct __gconv_step *step)
255      attribute_hidden;
256 
257 /* Transliteration using the locale's data.  */
258 extern int __gconv_transliterate (struct __gconv_step *step,
259                                   struct __gconv_step_data *step_data,
260                                   const unsigned char *inbufstart,
261                                   const unsigned char **inbufp,
262                                   const unsigned char *inbufend,
263                                   unsigned char **outbufstart,
264                                   size_t *irreversible);
265 libc_hidden_proto (__gconv_transliterate)
266 
267 /* If NAME is an codeset alias expand it.  */
268 extern int __gconv_compare_alias (const char *name1, const char *name2)
269      attribute_hidden;
270 
271 
272 /* Builtin transformations.  */
273 #ifdef _LIBC
274 # define __BUILTIN_TRANSFORM(Name) \
275   extern int Name (struct __gconv_step *step,				      \
276 		   struct __gconv_step_data *data,			      \
277 		   const unsigned char **inbuf,				      \
278 		   const unsigned char *inbufend,			      \
279 		   unsigned char **outbufstart, size_t *irreversible,	      \
280 		   int do_flush, int consume_incomplete)
281 
282 __BUILTIN_TRANSFORM (__gconv_transform_ascii_internal);
283 __BUILTIN_TRANSFORM (__gconv_transform_internal_ascii);
284 __BUILTIN_TRANSFORM (__gconv_transform_utf8_internal);
285 __BUILTIN_TRANSFORM (__gconv_transform_internal_utf8);
286 __BUILTIN_TRANSFORM (__gconv_transform_ucs2_internal);
287 __BUILTIN_TRANSFORM (__gconv_transform_internal_ucs2);
288 __BUILTIN_TRANSFORM (__gconv_transform_ucs2reverse_internal);
289 __BUILTIN_TRANSFORM (__gconv_transform_internal_ucs2reverse);
290 __BUILTIN_TRANSFORM (__gconv_transform_internal_ucs4);
291 __BUILTIN_TRANSFORM (__gconv_transform_ucs4_internal);
292 __BUILTIN_TRANSFORM (__gconv_transform_internal_ucs4le);
293 __BUILTIN_TRANSFORM (__gconv_transform_ucs4le_internal);
294 __BUILTIN_TRANSFORM (__gconv_transform_internal_utf16);
295 __BUILTIN_TRANSFORM (__gconv_transform_utf16_internal);
296 # undef __BUITLIN_TRANSFORM
297 
298 /* Specialized conversion function for a single byte to INTERNAL, recognizing
299    only ASCII characters.  */
300 extern wint_t __gconv_btwoc_ascii (struct __gconv_step *step, unsigned char c);
301 
302 #endif
303 
304 __END_DECLS
305 
306 #endif /* gconv_int.h */
307