2 * Copyright (C) 1999-2001 Free Software Foundation, Inc.
3 * This file is part of the GNU LIBICONV Library.
5 * The GNU LIBICONV Library is free software; you can redistribute it
6 * and/or modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * The GNU LIBICONV Library is distributed in the hope that it will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
17 * If not, write to the Free Software Foundation, Inc., 59 Temple Place -
18 * Suite 330, Boston, MA 02111-1307, USA.
26 #include "libcharset.h"
29 * Consider those system dependent encodings that are needed for the
43 * Data type for general conversion loop.
46 size_t (*loop_convert
) (iconv_t icd
,
47 const char* * inbuf
, size_t *inbytesleft
,
48 char* * outbuf
, size_t *outbytesleft
);
49 size_t (*loop_reset
) (iconv_t icd
,
50 char* * outbuf
, size_t *outbytesleft
);
56 #include "converters.h"
59 * Transliteration tables.
61 #include "cjk_variants.h"
65 * Table of all supported encodings.
68 struct mbtowc_funcs ifuncs
; /* conversion multibyte -> unicode */
69 struct wctomb_funcs ofuncs
; /* conversion unicode -> multibyte */
70 int oflags
; /* flags for unicode -> multibyte conversion */
73 #define DEFENCODING(xxx_names,xxx,xxx_ifuncs1,xxx_ifuncs2,xxx_ofuncs1,xxx_ofuncs2) \
75 #include "encodings.def"
77 #include "encodings_aix.def"
80 #include "encodings_osf1.def"
83 #include "encodings_dos.def"
85 #include "encodings_local.def"
87 ei_for_broken_compilers_that_dont_like_trailing_commas
90 static struct encoding
const all_encodings
[] = {
91 #define DEFENCODING(xxx_names,xxx,xxx_ifuncs1,xxx_ifuncs2,xxx_ofuncs1,xxx_ofuncs2) \
92 { xxx_ifuncs1,xxx_ifuncs2, xxx_ofuncs1,xxx_ofuncs2, ei_##xxx##_oflags },
93 #include "encodings.def"
95 #include "encodings_aix.def"
98 #include "encodings_osf1.def"
101 #include "encodings_dos.def"
104 #define DEFENCODING(xxx_names,xxx,xxx_ifuncs1,xxx_ifuncs2,xxx_ofuncs1,xxx_ofuncs2) \
105 { xxx_ifuncs1,xxx_ifuncs2, xxx_ofuncs1,xxx_ofuncs2, 0 },
106 #include "encodings_local.def"
116 * Alias lookup function.
118 * struct alias { const char* name; unsigned int encoding_index; };
119 * const struct alias * aliases_lookup (const char *str, unsigned int len);
120 * #define MAX_WORD_LENGTH ...
125 * System dependent alias lookup function.
127 * const struct alias * aliases2_lookup (const char *str);
129 #if defined(USE_AIX) || defined(USE_OSF1) || defined(USE_DOS) /* || ... */
130 static struct alias sysdep_aliases
[] = {
132 #include "aliases_aix.h"
135 #include "aliases_osf1.h"
138 #include "aliases_dos.h"
145 aliases2_lookup (register const char *str
)
149 for (ptr
= sysdep_aliases
, count
= sizeof(sysdep_aliases
)/sizeof(sysdep_aliases
[0]); count
> 0; ptr
++, count
--)
150 if (!strcmp(str
,ptr
->name
))
155 #define aliases2_lookup(str) NULL
159 /* Like !strcasecmp, except that the both strings can be assumed to be ASCII
160 and the first string can be assumed to be in uppercase. */
161 static int strequal (const char* str1
, const char* str2
)
166 c1
= * (unsigned char *) str1
++;
167 c2
= * (unsigned char *) str2
++;
170 if (c2
>= 'a' && c2
<= 'z')
179 iconv_t
iconv_open (const char* tocode
, const char* fromcode
)
181 struct conv_struct
* cd
;
182 char buf
[MAX_WORD_LENGTH
+10+1];
185 const struct alias
* ap
;
187 unsigned int from_index
;
189 unsigned int to_index
;
191 int transliterate
= 0;
193 /* Before calling aliases_lookup, convert the input string to upper case,
194 * and check whether it's entirely ASCII (we call gperf with option "-7"
195 * to achieve a smaller table) and non-empty. If it's not entirely ASCII,
196 * or if it's too long, it is not a valid encoding name.
198 for (to_wchar
= 0;;) {
199 /* Search tocode in the table. */
200 for (cp
= tocode
, bp
= buf
, count
= MAX_WORD_LENGTH
+10+1; ; cp
++, bp
++) {
201 unsigned char c
= * (unsigned char *) cp
;
204 if (c
>= 'a' && c
<= 'z')
212 if (bp
-buf
>= 10 && memcmp(bp
-10,"//TRANSLIT",10)==0) {
217 if (buf
[0] == '\0') {
218 tocode
= locale_charset();
219 /* Avoid an endless loop that could occur when using an older version
220 of localcharset.c. */
221 if (tocode
[0] == '\0')
225 ap
= aliases_lookup(buf
,bp
-buf
);
227 ap
= aliases2_lookup(buf
);
231 if (ap
->encoding_index
== ei_local_char
) {
232 tocode
= locale_charset();
233 /* Avoid an endless loop that could occur when using an older version
234 of localcharset.c. */
235 if (tocode
[0] == '\0')
239 if (ap
->encoding_index
== ei_local_wchar_t
) {
240 #if __STDC_ISO_10646__
241 if (sizeof(wchar_t) == 4) {
242 to_index
= ei_ucs4internal
;
245 if (sizeof(wchar_t) == 2) {
246 to_index
= ei_ucs2internal
;
249 if (sizeof(wchar_t) == 1) {
250 to_index
= ei_iso8859_1
;
256 tocode
= locale_charset();
261 to_index
= ap
->encoding_index
;
264 for (from_wchar
= 0;;) {
265 /* Search fromcode in the table. */
266 for (cp
= fromcode
, bp
= buf
, count
= MAX_WORD_LENGTH
+10+1; ; cp
++, bp
++) {
267 unsigned char c
= * (unsigned char *) cp
;
270 if (c
>= 'a' && c
<= 'z')
278 if (bp
-buf
>= 10 && memcmp(bp
-10,"//TRANSLIT",10)==0) {
282 if (buf
[0] == '\0') {
283 fromcode
= locale_charset();
284 /* Avoid an endless loop that could occur when using an older version
285 of localcharset.c. */
286 if (fromcode
[0] == '\0')
290 ap
= aliases_lookup(buf
,bp
-buf
);
292 ap
= aliases2_lookup(buf
);
296 if (ap
->encoding_index
== ei_local_char
) {
297 fromcode
= locale_charset();
298 /* Avoid an endless loop that could occur when using an older version
299 of localcharset.c. */
300 if (fromcode
[0] == '\0')
304 if (ap
->encoding_index
== ei_local_wchar_t
) {
305 #if __STDC_ISO_10646__
306 if (sizeof(wchar_t) == 4) {
307 from_index
= ei_ucs4internal
;
310 if (sizeof(wchar_t) == 2) {
311 from_index
= ei_ucs2internal
;
314 if (sizeof(wchar_t) == 1) {
315 from_index
= ei_iso8859_1
;
321 fromcode
= locale_charset();
326 from_index
= ap
->encoding_index
;
329 cd
= (struct conv_struct
*) malloc(from_wchar
!= to_wchar
330 ? sizeof(struct wchar_conv_struct
)
331 : sizeof(struct conv_struct
));
334 return (iconv_t
)(-1);
336 cd
->iindex
= from_index
;
337 cd
->ifuncs
= all_encodings
[from_index
].ifuncs
;
338 cd
->oindex
= to_index
;
339 cd
->ofuncs
= all_encodings
[to_index
].ofuncs
;
340 cd
->oflags
= all_encodings
[to_index
].oflags
;
341 /* Initialize the loop functions. */
346 cd
->lfuncs
.loop_convert
= wchar_id_loop_convert
;
347 cd
->lfuncs
.loop_reset
= wchar_id_loop_reset
;
351 cd
->lfuncs
.loop_convert
= wchar_to_loop_convert
;
352 cd
->lfuncs
.loop_reset
= wchar_to_loop_reset
;
359 cd
->lfuncs
.loop_convert
= wchar_from_loop_convert
;
360 cd
->lfuncs
.loop_reset
= wchar_from_loop_reset
;
364 cd
->lfuncs
.loop_convert
= unicode_loop_convert
;
365 cd
->lfuncs
.loop_reset
= unicode_loop_reset
;
368 /* Initialize the states. */
369 memset(&cd
->istate
,'\0',sizeof(state_t
));
370 memset(&cd
->ostate
,'\0',sizeof(state_t
));
371 /* Initialize the operation flags. */
372 cd
->transliterate
= transliterate
;
373 /* Initialize additional fields. */
374 if (from_wchar
!= to_wchar
) {
375 struct wchar_conv_struct
* wcd
= (struct wchar_conv_struct
*) cd
;
376 memset(&wcd
->state
,'\0',sizeof(mbstate_t));
382 return (iconv_t
)(-1);
385 size_t iconv (iconv_t icd
,
386 ICONV_CONST
char* * inbuf
, size_t *inbytesleft
,
387 char* * outbuf
, size_t *outbytesleft
)
389 conv_t cd
= (conv_t
) icd
;
390 if (inbuf
== NULL
|| *inbuf
== NULL
)
391 return cd
->lfuncs
.loop_reset(icd
,outbuf
,outbytesleft
);
393 return cd
->lfuncs
.loop_convert(icd
,
394 (const char* *)inbuf
,inbytesleft
,
395 outbuf
,outbytesleft
);
398 int iconv_close (iconv_t icd
)
400 conv_t cd
= (conv_t
) icd
;
405 #ifndef LIBICONV_PLUG
407 int iconvctl (iconv_t icd
, int request
, void* argument
)
409 conv_t cd
= (conv_t
) icd
;
413 ((cd
->lfuncs
.loop_convert
== unicode_loop_convert
414 && cd
->iindex
== cd
->oindex
)
415 || cd
->lfuncs
.loop_convert
== wchar_id_loop_convert
418 case ICONV_GET_TRANSLITERATE
:
419 *(int *)argument
= cd
->transliterate
;
421 case ICONV_SET_TRANSLITERATE
:
422 cd
->transliterate
= (*(const int *)argument
? 1 : 0);
430 static int compare_by_index (const void * arg1
, const void * arg2
)
432 const struct alias
* alias1
= (const struct alias
*) arg1
;
433 const struct alias
* alias2
= (const struct alias
*) arg2
;
434 return (int)alias1
->encoding_index
- (int)alias2
->encoding_index
;
437 static int compare_by_name (const void * arg1
, const void * arg2
)
439 const char * name1
= *(const char **)arg1
;
440 const char * name2
= *(const char **)arg2
;
441 /* Compare alphabetically, but put "CS" names at the end. */
442 int sign
= strcmp(name1
,name2
);
444 sign
= ((name1
[0]=='C' && name1
[1]=='S') - (name2
[0]=='C' && name2
[1]=='S'))
445 * 4 + (sign
>= 0 ? 1 : -1);
450 void iconvlist (int (*do_one
) (unsigned int namescount
,
451 const char * const * names
,
455 #define aliascount1 sizeof(aliases)/sizeof(aliases[0])
456 #ifndef aliases2_lookup
457 #define aliascount2 sizeof(sysdep_aliases)/sizeof(sysdep_aliases[0])
459 #define aliascount2 0
461 #define aliascount (aliascount1+aliascount2)
462 struct alias aliasbuf
[aliascount
];
463 const char * namesbuf
[aliascount
];
466 /* Put all existing aliases into a buffer. */
470 for (i
= 0; i
< aliascount1
; i
++) {
471 const struct alias
* p
= &aliases
[i
];
472 if (p
->name
[0] != '\0'
473 && p
->encoding_index
!= ei_local_char
474 && p
->encoding_index
!= ei_local_wchar_t
)
477 #ifndef aliases2_lookup
478 for (i
= 0; i
< aliascount2
; i
++)
479 aliasbuf
[j
++] = sysdep_aliases
[i
];
483 /* Sort by encoding_index. */
485 qsort(aliasbuf
, num_aliases
, sizeof(struct alias
), compare_by_index
);
487 /* Process all aliases with the same encoding_index together. */
490 while (j
< num_aliases
) {
491 unsigned int ei
= aliasbuf
[j
].encoding_index
;
494 namesbuf
[i
++] = aliasbuf
[j
++].name
;
495 while (j
< num_aliases
&& aliasbuf
[j
].encoding_index
== ei
);
497 qsort(namesbuf
, i
, sizeof(const char *), compare_by_name
);
498 /* Call the callback. */
499 if (do_one(i
,namesbuf
,data
))
508 int _libiconv_version
= _LIBICONV_VERSION
;