devctl.h: update for POSIX-1.2024
[newlib-cygwin.git] / newlib / libc / iconv / lib / iconvnls.c
blob5d4b0a273cfb52ecdd1bc0ed8a567bf950d14115
1 /*
2 * Copyright (c) 2003-2004, Artem B. Bityuckiy
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
25 #include <_ansi.h>
26 #include <reent.h>
27 #include <newlib.h>
28 #include <sys/types.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <sys/iconvnls.h>
32 #ifdef _MB_CAPABLE
33 #include <wchar.h>
34 #include <iconv.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <errno.h>
38 #include "local.h"
39 #include "conv.h"
40 #include "ucsconv.h"
41 #include "iconvnls.h"
42 #endif
45 * _iconv_nls_construct_filename -- constructs full file name.
47 * PARAMETERS:
48 * struct _reent *rptr - reent structure of current thread/process.
49 * const char *file - the name of file.
50 * const char *dir - the name of subdirectory;
51 * const char *ext - file extension.
53 * DESCRIPTION:
54 * Function constructs patch to icionv-related file.
55 * 'file' shouldn't be NULL. Doesn't use extension if 'ext' is NULL.
57 * RETURN:
58 * The pointer to file name if success, In case of error returns NULL
59 * and sets current thread's/process's errno.
61 const char *
62 _iconv_nls_construct_filename (struct _reent *rptr,
63 const char *file,
64 const char *dir,
65 const char *ext)
67 int len1, len2, len3;
68 char *path;
69 char *p;
70 int dirlen = strlen (dir);
72 if ((path = _getenv_r (rptr, NLS_ENVVAR_NAME)) == NULL || *path == '\0')
73 path = ICONV_DEFAULT_NLSPATH;
75 len1 = strlen (path);
76 len2 = strlen (file);
77 len3 = strlen (ext);
79 if ((p = _malloc_r (rptr, len1 + dirlen + len2 + len3 + 3)) == NULL)
80 return (const char *)NULL;
82 memcpy (p, path, len1);
83 if (p[len1 - 1] != '/')
84 p[len1++] = '/';
85 memcpy (p + len1, dir, dirlen);
86 len1 += dirlen;
87 p[len1++] = '/';
88 memcpy (p + len1, file, len2);
89 len1 += len2;
90 if (ext != NULL)
92 memcpy (p + len1, ext, len3);
93 len1 += len3;
95 p[len1] = '\0';
97 return (const char *)p;
101 #ifdef _MB_CAPABLE
103 * _iconv_nls_get_mb_cur_max -- return encoding's maximum length
104 * of a multi-byte character.
106 * PARAMETERS:
107 * iconv_t cd - opened iconv conversion descriptor;
108 * int direction - "from encoding" or "to encoding" direction.
110 * DESCRIPTION:
111 * Return maximum length of a multi-byte character in one of 'cd's
112 * encoding. Return "from" encoding's value if 'direction' is 0 and
113 * "to" encoding's value if 'direction' isn't 0.
116 _iconv_nls_get_mb_cur_max (iconv_t cd,
117 int direction)
119 iconv_conversion_t *ic = (iconv_conversion_t *)cd;
121 return ic->handlers->get_mb_cur_max (ic->data, direction);
125 * _iconv_nls_is_stateful -- is encoding stateful?
127 * PARAMETERS:
128 * iconv_t cd - opened iconv conversion descriptor;
129 * int direction - "from encoding" or "to encoding" direction.
131 * DESCRIPTION:
132 * Returns 0 if encoding is stateless or 1 if stateful.
133 * Tests "from" encoding if 'direction' is 0 and
134 * "to" encoding's value if 'direction' isn't 0.
138 _iconv_nls_is_stateful (iconv_t cd,
139 int direction)
141 iconv_conversion_t *ic = (iconv_conversion_t *)cd;
143 return ic->handlers->is_stateful (ic->data, direction);
147 * _iconv_nls_conv - special version of iconv for NLS.
149 * PARAMETERS:
150 * Same as _iconv_r.
152 * DESCRIPTION:
153 * Function behaves as _iconv_r but:
154 * 1. Don't handle reset/return shift states queries
155 * (like iconv does when 'inbuf' == NULL, etc);
156 * 2. Don't save result if 'outbuf' == NULL or
157 * '*outbuf' == NULL;
158 * 3. Don't perform default conversion if there is no character
159 * in "to" encoding that corresponds to character from "from"
160 * encoding.
162 * RETURN:
163 * Same as _iconv_r.
165 size_t
166 _iconv_nls_conv (struct _reent *rptr,
167 iconv_t cd,
168 const char **inbuf,
169 size_t *inbytesleft,
170 char **outbuf,
171 size_t *outbytesleft)
173 iconv_conversion_t *ic = (iconv_conversion_t *)cd;
174 int flags = ICONV_FAIL_BIT;
176 if ((void *)cd == NULL || cd == (iconv_t)-1 || ic->data == NULL
177 || (ic->handlers != &_iconv_null_conversion_handlers
178 && ic->handlers != &_iconv_ucs_conversion_handlers))
180 _REENT_ERRNO (rptr) = EBADF;
181 return (size_t)-1;
184 if (inbytesleft == NULL || *inbytesleft == 0)
185 return (size_t)0;
187 if (outbuf == NULL || *outbuf == NULL)
188 flags |= ICONV_DONT_SAVE_BIT;
190 if (outbytesleft == NULL || *outbytesleft == 0)
192 _REENT_ERRNO (rptr) = E2BIG;
193 return (size_t)-1;
196 return ic->handlers->convert (rptr,
197 ic->data,
198 (const unsigned char**)inbuf,
199 inbytesleft,
200 (unsigned char**)outbuf,
201 outbytesleft,
202 flags);
206 * _iconv_nls_get_state -- get encoding's current shift state value.
208 * PARAMETERS:
209 * iconv_t cd - iconv descriptor;
210 * mbstate_t *ps - where to save shift state;
211 * int direction - "from" encoding if 0, "to" encoding if 1.
213 * DESCRIPTION:
214 * Save encoding's current shift state to 'ps'. Save "from" encoding's
215 * shift state if 'direction' is 0 and "to" encodings's shift state
216 * if 'direction' isn't 0.
218 void
219 _iconv_nls_get_state (iconv_t cd,
220 mbstate_t *ps,
221 int direction)
223 iconv_conversion_t *ic = (iconv_conversion_t *)cd;
225 ic->handlers->get_state (ic->data, ps, direction);
227 return;
231 * _iconv_nls_set_state -- set encoding's current shift state value.
233 * PARAMETERS:
234 * iconv_t cd - iconv descriptor;
235 * mbstate_t *ps - where to save shift state.
236 * int direction - "from" encoding if 0, "to" encoding if 1.
238 * DESCRIPTION:
239 * Set encoding's current shift state.
241 * RETURN:
242 * 0 if success, -1 if failure.
245 _iconv_nls_set_state (iconv_t cd,
246 mbstate_t *ps,
247 int direction)
249 iconv_conversion_t *ic = (iconv_conversion_t *)cd;
251 return ic->handlers->set_state (ic->data, ps, direction);
254 /* Same as iconv_open() but don't perform name resolving */
255 static iconv_t
256 iconv_open1 (struct _reent *rptr,
257 const char *to,
258 const char *from)
260 iconv_conversion_t *ic;
262 if (to == NULL || from == NULL || *to == '\0' || *from == '\0')
263 return (iconv_t)-1;
265 ic = (iconv_conversion_t *)_malloc_r (rptr, sizeof (iconv_conversion_t));
266 if (ic == NULL)
267 return (iconv_t)-1;
269 /* Select which conversion type to use */
270 if (strcmp (from, to) == 0)
272 /* Use null conversion */
273 ic->handlers = &_iconv_null_conversion_handlers;
274 ic->data = ic->handlers->open (rptr, to, from);
276 else
278 /* Use UCS-based conversion */
279 ic->handlers = &_iconv_ucs_conversion_handlers;
280 ic->data = ic->handlers->open (rptr, to, from);
283 if (ic->data == NULL)
285 _free_r (rptr, (void *)ic);
286 return (iconv_t)-1;
289 return (void *)ic;
293 * _iconv_nls_open - open iconv descriptors for NLS.
295 * PARAMETERS:
296 * struct _reent *rptr - process's reent structure;
297 * const char *encoding - encoding name;
298 * iconv_t *tomb - wchar -> encoding iconv descriptor pointer;
299 * iconv_t *towc - encoding -> wchar iconv descriptor pointer;
300 * int flag - perform encoding name resolving flag.
302 * DESCRIPTION:
303 * Opens two iconv descriptors for 'encoding' -> wchar and
304 * wchar -> 'encoding' iconv conversions. Function is used when locale or
305 * wide-oriented stream is opened. If 'flag' is 0, don't perform encoding
306 * name resolving ('encoding' must not be alias in this case).
308 * RETURN:
309 * If successful - return 0, else set errno and return -1.
312 _iconv_nls_open (struct _reent *rptr,
313 const char *encoding,
314 iconv_t *tomb,
315 iconv_t *towc,
316 int flag)
318 const char *wchar_encoding;
320 if (sizeof (wchar_t) > 2 && WCHAR_MAX > 0xFFFF)
321 wchar_encoding = "ucs_4_internal";
322 else if (sizeof (wchar_t) > 1 && WCHAR_MAX > 0xFF)
323 wchar_encoding = "ucs_2_internal";
324 else
325 wchar_encoding = ""; /* This shuldn't happen */
327 if (flag)
329 if ((*towc = _iconv_open_r (rptr, wchar_encoding, encoding)) == (iconv_t)-1)
330 return -1;
332 if ((*tomb = _iconv_open_r (rptr, encoding, wchar_encoding)) == (iconv_t)-1)
334 _iconv_close_r (rptr, *towc);
335 return -1;
338 else
340 if ((*towc = iconv_open1 (rptr, wchar_encoding, encoding)) == (iconv_t)-1)
341 return -1;
343 if ((*tomb = iconv_open1 (rptr, encoding, wchar_encoding)) == (iconv_t)-1)
345 _iconv_close_r (rptr, *towc);
346 return -1;
350 return 0;
353 #endif /* _MB_CAPABLE */