* crypt/md5.h (MD5_DIGEST_SIZE, MD5_BLOCK_SIZE): New macros.
[glibc.git] / libio / iofwide.c
blob7af9a633f8c38fa6c3c3deed373a58c111711329
1 /* Copyright (C) 1999-2003, 2005 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA.
19 As a special exception, if you link the code in this file with
20 files compiled with a GNU compiler to produce an executable,
21 that does not cause the resulting executable to be covered by
22 the GNU Lesser General Public License. This exception does not
23 however invalidate any other reasons why the executable file
24 might be covered by the GNU Lesser General Public License.
25 This exception applies to code released by its copyright holders
26 in files containing the exception. */
28 #include <libioP.h>
29 #ifdef _LIBC
30 # include <dlfcn.h>
31 # include <wchar.h>
32 #endif
33 #include <assert.h>
34 #include <stdlib.h>
35 #include <string.h>
37 #ifdef _LIBC
38 # include <langinfo.h>
39 # include <locale/localeinfo.h>
40 # include <wcsmbs/wcsmbsload.h>
41 # include <iconv/gconv_int.h>
42 # include <shlib-compat.h>
43 #endif
46 /* Prototypes of libio's codecvt functions. */
47 static enum __codecvt_result do_out (struct _IO_codecvt *codecvt,
48 __mbstate_t *statep,
49 const wchar_t *from_start,
50 const wchar_t *from_end,
51 const wchar_t **from_stop, char *to_start,
52 char *to_end, char **to_stop);
53 static enum __codecvt_result do_unshift (struct _IO_codecvt *codecvt,
54 __mbstate_t *statep, char *to_start,
55 char *to_end, char **to_stop);
56 static enum __codecvt_result do_in (struct _IO_codecvt *codecvt,
57 __mbstate_t *statep,
58 const char *from_start,
59 const char *from_end,
60 const char **from_stop, wchar_t *to_start,
61 wchar_t *to_end, wchar_t **to_stop);
62 static int do_encoding (struct _IO_codecvt *codecvt);
63 static int do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
64 const char *from_start,
65 const char *from_end, _IO_size_t max);
66 static int do_max_length (struct _IO_codecvt *codecvt);
67 static int do_always_noconv (struct _IO_codecvt *codecvt);
70 /* The functions used in `codecvt' for libio are always the same. */
71 struct _IO_codecvt __libio_codecvt =
73 .__codecvt_destr = NULL, /* Destructor, never used. */
74 .__codecvt_do_out = do_out,
75 .__codecvt_do_unshift = do_unshift,
76 .__codecvt_do_in = do_in,
77 .__codecvt_do_encoding = do_encoding,
78 .__codecvt_do_always_noconv = do_always_noconv,
79 .__codecvt_do_length = do_length,
80 .__codecvt_do_max_length = do_max_length
84 #ifdef _LIBC
85 struct __gconv_trans_data __libio_translit attribute_hidden =
87 .__trans_fct = __gconv_transliterate
89 #endif
92 /* Return orientation of stream. If mode is nonzero try to change
93 the orientation first. */
94 #undef _IO_fwide
95 int
96 _IO_fwide (fp, mode)
97 _IO_FILE *fp;
98 int mode;
100 /* Normalize the value. */
101 mode = mode < 0 ? -1 : (mode == 0 ? 0 : 1);
103 #if defined SHARED && defined _LIBC \
104 && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
105 if (__builtin_expect (&_IO_stdin_used == NULL, 0)
106 && (fp == _IO_stdin || fp == _IO_stdout || fp == _IO_stderr))
107 /* This is for a stream in the glibc 2.0 format. */
108 return -1;
109 #endif
111 /* The orientation already has been determined. */
112 if (fp->_mode != 0
113 /* Or the caller simply wants to know about the current orientation. */
114 || mode == 0)
115 return fp->_mode;
117 /* Set the orientation appropriately. */
118 if (mode > 0)
120 struct _IO_codecvt *cc = fp->_codecvt = &fp->_wide_data->_codecvt;
122 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
123 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;
125 /* Get the character conversion functions based on the currently
126 selected locale for LC_CTYPE. */
127 #ifdef _LIBC
129 struct gconv_fcts fcts;
131 /* Clear the state. We start all over again. */
132 memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
133 memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
135 __wcsmbs_clone_conv (&fcts);
136 assert (fcts.towc_nsteps == 1);
137 assert (fcts.tomb_nsteps == 1);
139 /* The functions are always the same. */
140 *cc = __libio_codecvt;
142 cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
143 cc->__cd_in.__cd.__steps = fcts.towc;
145 cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
146 cc->__cd_in.__cd.__data[0].__internal_use = 1;
147 cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
148 cc->__cd_in.__cd.__data[0].__statep = &fp->_wide_data->_IO_state;
150 /* XXX For now no transliteration. */
151 cc->__cd_in.__cd.__data[0].__trans = NULL;
153 cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
154 cc->__cd_out.__cd.__steps = fcts.tomb;
156 cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
157 cc->__cd_out.__cd.__data[0].__internal_use = 1;
158 cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
159 cc->__cd_out.__cd.__data[0].__statep = &fp->_wide_data->_IO_state;
161 /* And now the transliteration. */
162 cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
164 #else
165 # ifdef _GLIBCPP_USE_WCHAR_T
167 /* Determine internal and external character sets.
169 XXX For now we make our life easy: we assume a fixed internal
170 encoding (as most sane systems have; hi HP/UX!). If somebody
171 cares about systems which changing internal charsets they
172 should come up with a solution for the determination of the
173 currently used internal character set. */
174 const char *internal_ccs = _G_INTERNAL_CCS;
175 const char *external_ccs = NULL;
177 # ifdef HAVE_NL_LANGINFO
178 external_ccs = nl_langinfo (CODESET);
179 # endif
180 if (external_ccs == NULL)
181 external_ccs = "ISO-8859-1";
183 cc->__cd_in = iconv_open (internal_ccs, external_ccs);
184 if (cc->__cd_in != (iconv_t) -1)
185 cc->__cd_out = iconv_open (external_ccs, internal_ccs);
187 if (cc->__cd_in == (iconv_t) -1 || cc->__cd_out == (iconv_t) -1)
189 if (cc->__cd_in != (iconv_t) -1)
190 iconv_close (cc->__cd_in);
191 /* XXX */
192 abort ();
195 # else
196 # error "somehow determine this from LC_CTYPE"
197 # endif
198 #endif
200 /* From now on use the wide character callback functions. */
201 ((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
203 /* One last twist: we get the current stream position. The wide
204 char streams have much more problems with not knowing the
205 current position and so we should disable the optimization
206 which allows the functions without knowing the position. */
207 fp->_offset = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
210 /* Set the mode now. */
211 fp->_mode = mode;
213 return mode;
217 static enum __codecvt_result
218 do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep,
219 const wchar_t *from_start, const wchar_t *from_end,
220 const wchar_t **from_stop, char *to_start, char *to_end,
221 char **to_stop)
223 enum __codecvt_result result;
225 #ifdef _LIBC
226 struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps;
227 int status;
228 size_t dummy;
229 const unsigned char *from_start_copy = (unsigned char *) from_start;
231 codecvt->__cd_out.__cd.__data[0].__outbuf = (unsigned char *) to_start;
232 codecvt->__cd_out.__cd.__data[0].__outbufend = (unsigned char *) to_end;
233 codecvt->__cd_out.__cd.__data[0].__statep = statep;
235 status = DL_CALL_FCT (gs->__fct,
236 (gs, codecvt->__cd_out.__cd.__data, &from_start_copy,
237 (const unsigned char *) from_end, NULL,
238 &dummy, 0, 0));
240 *from_stop = (wchar_t *) from_start_copy;
241 *to_stop = (char *) codecvt->__cd_out.__cd.__data[0].__outbuf;
243 switch (status)
245 case __GCONV_OK:
246 case __GCONV_EMPTY_INPUT:
247 result = __codecvt_ok;
248 break;
250 case __GCONV_FULL_OUTPUT:
251 case __GCONV_INCOMPLETE_INPUT:
252 result = __codecvt_partial;
253 break;
255 default:
256 result = __codecvt_error;
257 break;
259 #else
260 # ifdef _GLIBCPP_USE_WCHAR_T
261 size_t res;
262 const char *from_start_copy = (const char *) from_start;
263 size_t from_len = from_end - from_start;
264 char *to_start_copy = to_start;
265 size_t to_len = to_end - to_start;
266 res = iconv (codecvt->__cd_out, &from_start_copy, &from_len,
267 &to_start_copy, &to_len);
269 if (res == 0 || from_len == 0)
270 result = __codecvt_ok;
271 else if (to_len < codecvt->__codecvt_do_max_length (codecvt))
272 result = __codecvt_partial;
273 else
274 result = __codecvt_error;
276 # else
277 /* Decide what to do. */
278 result = __codecvt_error;
279 # endif
280 #endif
282 return result;
286 static enum __codecvt_result
287 do_unshift (struct _IO_codecvt *codecvt, __mbstate_t *statep,
288 char *to_start, char *to_end, char **to_stop)
290 enum __codecvt_result result;
292 #ifdef _LIBC
293 struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps;
294 int status;
295 size_t dummy;
297 codecvt->__cd_out.__cd.__data[0].__outbuf = (unsigned char *) to_start;
298 codecvt->__cd_out.__cd.__data[0].__outbufend = (unsigned char *) to_end;
299 codecvt->__cd_out.__cd.__data[0].__statep = statep;
301 status = DL_CALL_FCT (gs->__fct,
302 (gs, codecvt->__cd_out.__cd.__data, NULL, NULL,
303 NULL, &dummy, 1, 0));
305 *to_stop = (char *) codecvt->__cd_out.__cd.__data[0].__outbuf;
307 switch (status)
309 case __GCONV_OK:
310 case __GCONV_EMPTY_INPUT:
311 result = __codecvt_ok;
312 break;
314 case __GCONV_FULL_OUTPUT:
315 case __GCONV_INCOMPLETE_INPUT:
316 result = __codecvt_partial;
317 break;
319 default:
320 result = __codecvt_error;
321 break;
323 #else
324 # ifdef _GLIBCPP_USE_WCHAR_T
325 size_t res;
326 char *to_start_copy = (char *) to_start;
327 size_t to_len = to_end - to_start;
329 res = iconv (codecvt->__cd_out, NULL, NULL, &to_start_copy, &to_len);
331 if (res == 0)
332 result = __codecvt_ok;
333 else if (to_len < codecvt->__codecvt_do_max_length (codecvt))
334 result = __codecvt_partial;
335 else
336 result = __codecvt_error;
337 # else
338 /* Decide what to do. */
339 result = __codecvt_error;
340 # endif
341 #endif
343 return result;
347 static enum __codecvt_result
348 do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep,
349 const char *from_start, const char *from_end, const char **from_stop,
350 wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop)
352 enum __codecvt_result result;
354 #ifdef _LIBC
355 struct __gconv_step *gs = codecvt->__cd_in.__cd.__steps;
356 int status;
357 size_t dummy;
358 const unsigned char *from_start_copy = (unsigned char *) from_start;
360 codecvt->__cd_in.__cd.__data[0].__outbuf = (unsigned char *) to_start;
361 codecvt->__cd_in.__cd.__data[0].__outbufend = (unsigned char *) to_end;
362 codecvt->__cd_in.__cd.__data[0].__statep = statep;
364 status = DL_CALL_FCT (gs->__fct,
365 (gs, codecvt->__cd_in.__cd.__data, &from_start_copy,
366 (const unsigned char *) from_end, NULL,
367 &dummy, 0, 0));
369 *from_stop = (const char *) from_start_copy;
370 *to_stop = (wchar_t *) codecvt->__cd_in.__cd.__data[0].__outbuf;
372 switch (status)
374 case __GCONV_OK:
375 case __GCONV_EMPTY_INPUT:
376 result = __codecvt_ok;
377 break;
379 case __GCONV_FULL_OUTPUT:
380 case __GCONV_INCOMPLETE_INPUT:
381 result = __codecvt_partial;
382 break;
384 default:
385 result = __codecvt_error;
386 break;
388 #else
389 # ifdef _GLIBCPP_USE_WCHAR_T
390 size_t res;
391 const char *from_start_copy = (const char *) from_start;
392 size_t from_len = from_end - from_start;
393 char *to_start_copy = (char *) from_start;
394 size_t to_len = to_end - to_start;
396 res = iconv (codecvt->__cd_in, &from_start_copy, &from_len,
397 &to_start_copy, &to_len);
399 if (res == 0)
400 result = __codecvt_ok;
401 else if (to_len == 0)
402 result = __codecvt_partial;
403 else if (from_len < codecvt->__codecvt_do_max_length (codecvt))
404 result = __codecvt_partial;
405 else
406 result = __codecvt_error;
407 # else
408 /* Decide what to do. */
409 result = __codecvt_error;
410 # endif
411 #endif
413 return result;
417 static int
418 do_encoding (struct _IO_codecvt *codecvt)
420 #ifdef _LIBC
421 /* See whether the encoding is stateful. */
422 if (codecvt->__cd_in.__cd.__steps[0].__stateful)
423 return -1;
424 /* Fortunately not. Now determine the input bytes for the conversion
425 necessary for each wide character. */
426 if (codecvt->__cd_in.__cd.__steps[0].__min_needed_from
427 != codecvt->__cd_in.__cd.__steps[0].__max_needed_from)
428 /* Not a constant value. */
429 return 0;
431 return codecvt->__cd_in.__cd.__steps[0].__min_needed_from;
432 #else
433 /* Worst case scenario. */
434 return -1;
435 #endif
439 static int
440 do_always_noconv (struct _IO_codecvt *codecvt)
442 return 0;
446 static int
447 do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
448 const char *from_start, const char *from_end, _IO_size_t max)
450 int result;
451 #ifdef _LIBC
452 const unsigned char *cp = (const unsigned char *) from_start;
453 wchar_t to_buf[max];
454 struct __gconv_step *gs = codecvt->__cd_in.__cd.__steps;
455 int status;
456 size_t dummy;
458 codecvt->__cd_in.__cd.__data[0].__outbuf = (unsigned char *) to_buf;
459 codecvt->__cd_in.__cd.__data[0].__outbufend = (unsigned char *) &to_buf[max];
460 codecvt->__cd_in.__cd.__data[0].__statep = statep;
462 status = DL_CALL_FCT (gs->__fct,
463 (gs, codecvt->__cd_in.__cd.__data, &cp,
464 (const unsigned char *) from_end, NULL,
465 &dummy, 0, 0));
467 result = cp - (const unsigned char *) from_start;
468 #else
469 # ifdef _GLIBCPP_USE_WCHAR_T
470 const char *from_start_copy = (const char *) from_start;
471 size_t from_len = from_end - from_start;
472 wchar_t to_buf[max];
473 size_t res;
474 char *to_start = (char *) to_buf;
476 res = iconv (codecvt->__cd_in, &from_start_copy, &from_len,
477 &to_start, &max);
479 result = from_start_copy - (char *) from_start;
480 # else
481 /* Decide what to do. */
482 result = 0;
483 # endif
484 #endif
486 return result;
490 static int
491 do_max_length (struct _IO_codecvt *codecvt)
493 #ifdef _LIBC
494 return codecvt->__cd_in.__cd.__steps[0].__max_needed_from;
495 #else
496 return MB_CUR_MAX;
497 #endif