1 /* 2 * Copyright (C) 1999-2007 Free Software Foundation, Inc. 3 * This file is part of the GNU LIBICONV Library. 4 * 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. 9 * 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. 14 * 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., 51 Franklin Street, 18 * Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21 #include "iconv.h" 22 23 #include <stdlib.h> 24 #include <string.h> 25 #include "config.h" 26 #include "localcharset.h" 27 28 #if ENABLE_EXTRA 29 /* 30 * Consider all system dependent encodings, for any system, 31 * and the extra encodings. 32 */ 33 #define USE_AIX 34 #define USE_OSF1 35 #define USE_DOS 36 #define USE_EXTRA 37 #else 38 /* 39 * Consider those system dependent encodings that are needed for the 40 * current system. 41 */ 42 #ifdef _AIX 43 #define USE_AIX 44 #endif 45 #if defined(__osf__) || defined(VMS) 46 #define USE_OSF1 47 #endif 48 #if defined(__DJGPP__) || (defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__))) 49 #define USE_DOS 50 #endif 51 #endif 52 53 /* 54 * Data type for general conversion loop. 55 */ 56 struct loop_funcs { 57 size_t (*loop_convert) (iconv_t icd, 58 const char* * inbuf, size_t *inbytesleft, 59 char* * outbuf, size_t *outbytesleft); 60 size_t (*loop_reset) (iconv_t icd, 61 char* * outbuf, size_t *outbytesleft); 62 }; 63 64 /* 65 * Converters. 66 */ 67 #include "converters.h" 68 69 /* 70 * Transliteration tables. 71 */ 72 #include "cjk_variants.h" 73 #include "translit.h" 74 75 /* 76 * Table of all supported encodings. 77 */ 78 struct encoding { 79 struct mbtowc_funcs ifuncs; /* conversion multibyte -> unicode */ 80 struct wctomb_funcs ofuncs; /* conversion unicode -> multibyte */ 81 int oflags; /* flags for unicode -> multibyte conversion */ 82 }; 83 enum { 84 #define DEFENCODING(xxx_names,xxx,xxx_ifuncs1,xxx_ifuncs2,xxx_ofuncs1,xxx_ofuncs2) \ 85 ei_##xxx , 86 #include "encodings.def" 87 #ifdef USE_AIX 88 #include "encodings_aix.def" 89 #endif 90 #ifdef USE_OSF1 91 #include "encodings_osf1.def" 92 #endif 93 #ifdef USE_DOS 94 #include "encodings_dos.def" 95 #endif 96 #ifdef USE_EXTRA 97 #include "encodings_extra.def" 98 #endif 99 #include "encodings_local.def" 100 #undef DEFENCODING 101 ei_for_broken_compilers_that_dont_like_trailing_commas 102 }; 103 #include "flags.h" 104 static struct encoding const all_encodings[] = { 105 #define DEFENCODING(xxx_names,xxx,xxx_ifuncs1,xxx_ifuncs2,xxx_ofuncs1,xxx_ofuncs2) \ 106 { xxx_ifuncs1,xxx_ifuncs2, xxx_ofuncs1,xxx_ofuncs2, ei_##xxx##_oflags }, 107 #include "encodings.def" 108 #ifdef USE_AIX 109 #include "encodings_aix.def" 110 #endif 111 #ifdef USE_OSF1 112 #include "encodings_osf1.def" 113 #endif 114 #ifdef USE_DOS 115 #include "encodings_dos.def" 116 #endif 117 #ifdef USE_EXTRA 118 #include "encodings_extra.def" 119 #endif 120 #undef DEFENCODING 121 #define DEFENCODING(xxx_names,xxx,xxx_ifuncs1,xxx_ifuncs2,xxx_ofuncs1,xxx_ofuncs2) \ 122 { xxx_ifuncs1,xxx_ifuncs2, xxx_ofuncs1,xxx_ofuncs2, 0 }, 123 #include "encodings_local.def" 124 #undef DEFENCODING 125 }; 126 127 /* 128 * Conversion loops. 129 */ 130 #include "loops.h" 131 132 /* 133 * Alias lookup function. 134 * Defines 135 * struct alias { int name; unsigned int encoding_index; }; 136 * const struct alias * aliases_lookup (const char *str, unsigned int len); 137 * #define MAX_WORD_LENGTH ... 138 */ 139 #include "aliases.h" 140 141 /* 142 * System dependent alias lookup function. 143 * Defines 144 * const struct alias * aliases2_lookup (const char *str); 145 */ 146 #if defined(USE_AIX) || defined(USE_OSF1) || defined(USE_DOS) || defined(USE_EXTRA) /* || ... */ 147 struct stringpool2_t { 148 #define S(tag,name,encoding_index) char stringpool_##tag[sizeof(name)]; 149 #include "aliases2.h" 150 #undef S 151 }; 152 static const struct stringpool2_t stringpool2_contents = { 153 #define S(tag,name,encoding_index) name, 154 #include "aliases2.h" 155 #undef S 156 }; 157 #define stringpool2 ((const char *) &stringpool2_contents) 158 static const struct alias sysdep_aliases[] = { 159 #define S(tag,name,encoding_index) { (int)(long)&((struct stringpool2_t *)0)->stringpool_##tag, encoding_index }, 160 #include "aliases2.h" 161 #undef S 162 }; 163 #if defined(__GNUC__) && !defined(DEBUG) 164 __inline 165 #else 166 #ifdef __cplusplus 167 inline 168 #endif 169 #endif 170 static const struct alias * 171 aliases2_lookup (register const char *str) 172 { 173 const struct alias * ptr; 174 unsigned int count; 175 for (ptr = sysdep_aliases, count = sizeof(sysdep_aliases)/sizeof(sysdep_aliases[0]); count > 0; ptr++, count--) 176 if (!strcmp(str, stringpool2 + ptr->name)) 177 return ptr; 178 return NULL; 179 } 180 #else 181 #define aliases2_lookup(str) NULL 182 #define stringpool2 NULL 183 #endif 184 185 #if 0 186 /* Like !strcasecmp, except that the both strings can be assumed to be ASCII 187 and the first string can be assumed to be in uppercase. */ 188 static int strequal (const char* str1, const char* str2) 189 { 190 unsigned char c1; 191 unsigned char c2; 192 for (;;) { 193 c1 = * (unsigned char *) str1++; 194 c2 = * (unsigned char *) str2++; 195 if (c1 == 0) 196 break; 197 if (c2 >= 'a' && c2 <= 'z') 198 c2 -= 'a'-'A'; 199 if (c1 != c2) 200 break; 201 } 202 return (c1 == c2); 203 } 204 #endif 205 206 iconv_t iconv_open (const char* tocode, const char* fromcode) 207 { 208 struct conv_struct * cd; 209 char buf[MAX_WORD_LENGTH+10+1]; 210 const char* cp; 211 char* bp; 212 const struct alias * ap; 213 unsigned int count; 214 unsigned int from_index; 215 int from_wchar; 216 unsigned int to_index; 217 int to_wchar; 218 int transliterate = 0; 219 int discard_ilseq = 0; 220 221 /* Before calling aliases_lookup, convert the input string to upper case, 222 * and check whether it's entirely ASCII (we call gperf with option "-7" 223 * to achieve a smaller table) and non-empty. If it's not entirely ASCII, 224 * or if it's too long, it is not a valid encoding name. 225 */ 226 for (to_wchar = 0;;) { 227 /* Search tocode in the table. */ 228 for (cp = tocode, bp = buf, count = MAX_WORD_LENGTH+10+1; ; cp++, bp++) { 229 unsigned char c = * (unsigned char *) cp; 230 if (c >= 0x80) 231 goto invalid; 232 if (c >= 'a' && c <= 'z') 233 c -= 'a'-'A'; 234 *bp = c; 235 if (c == '\0') 236 break; 237 if (--count == 0) 238 goto invalid; 239 } 240 for (;;) { 241 if (bp-buf >= 10 && memcmp(bp-10,"//TRANSLIT",10)==0) { 242 bp -= 10; 243 *bp = '\0'; 244 transliterate = 1; 245 continue; 246 } 247 if (bp-buf >= 8 && memcmp(bp-8,"//IGNORE",8)==0) { 248 bp -= 8; 249 *bp = '\0'; 250 discard_ilseq = 1; 251 continue; 252 } 253 break; 254 } 255 if (buf[0] == '\0') { 256 tocode = locale_charset(); 257 /* Avoid an endless loop that could occur when using an older version 258 of localcharset.c. */ 259 if (tocode[0] == '\0') 260 goto invalid; 261 continue; 262 } 263 ap = aliases_lookup(buf,bp-buf); 264 if (ap == NULL) { 265 ap = aliases2_lookup(buf); 266 if (ap == NULL) 267 goto invalid; 268 } 269 if (ap->encoding_index == ei_local_char) { 270 tocode = locale_charset(); 271 /* Avoid an endless loop that could occur when using an older version 272 of localcharset.c. */ 273 if (tocode[0] == '\0') 274 goto invalid; 275 continue; 276 } 277 if (ap->encoding_index == ei_local_wchar_t) { 278 /* On systems which define __STDC_ISO_10646__, wchar_t is Unicode. 279 This is also the case on native Woe32 systems. */ 280 #if __STDC_ISO_10646__ || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) 281 if (sizeof(wchar_t) == 4) { 282 to_index = ei_ucs4internal; 283 break; 284 } 285 if (sizeof(wchar_t) == 2) { 286 to_index = ei_ucs2internal; 287 break; 288 } 289 if (sizeof(wchar_t) == 1) { 290 to_index = ei_iso8859_1; 291 break; 292 } 293 #endif 294 #if HAVE_MBRTOWC 295 to_wchar = 1; 296 tocode = locale_charset(); 297 continue; 298 #endif 299 goto invalid; 300 } 301 to_index = ap->encoding_index; 302 break; 303 } 304 for (from_wchar = 0;;) { 305 /* Search fromcode in the table. */ 306 for (cp = fromcode, bp = buf, count = MAX_WORD_LENGTH+10+1; ; cp++, bp++) { 307 unsigned char c = * (unsigned char *) cp; 308 if (c >= 0x80) 309 goto invalid; 310 if (c >= 'a' && c <= 'z') 311 c -= 'a'-'A'; 312 *bp = c; 313 if (c == '\0') 314 break; 315 if (--count == 0) 316 goto invalid; 317 } 318 for (;;) { 319 if (bp-buf >= 10 && memcmp(bp-10,"//TRANSLIT",10)==0) { 320 bp -= 10; 321 *bp = '\0'; 322 continue; 323 } 324 if (bp-buf >= 8 && memcmp(bp-8,"//IGNORE",8)==0) { 325 bp -= 8; 326 *bp = '\0'; 327 continue; 328 } 329 break; 330 } 331 if (buf[0] == '\0') { 332 fromcode = locale_charset(); 333 /* Avoid an endless loop that could occur when using an older version 334 of localcharset.c. */ 335 if (fromcode[0] == '\0') 336 goto invalid; 337 continue; 338 } 339 ap = aliases_lookup(buf,bp-buf); 340 if (ap == NULL) { 341 ap = aliases2_lookup(buf); 342 if (ap == NULL) 343 goto invalid; 344 } 345 if (ap->encoding_index == ei_local_char) { 346 fromcode = locale_charset(); 347 /* Avoid an endless loop that could occur when using an older version 348 of localcharset.c. */ 349 if (fromcode[0] == '\0') 350 goto invalid; 351 continue; 352 } 353 if (ap->encoding_index == ei_local_wchar_t) { 354 /* On systems which define __STDC_ISO_10646__, wchar_t is Unicode. 355 This is also the case on native Woe32 systems. */ 356 #if __STDC_ISO_10646__ || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) 357 if (sizeof(wchar_t) == 4) { 358 from_index = ei_ucs4internal; 359 break; 360 } 361 if (sizeof(wchar_t) == 2) { 362 from_index = ei_ucs2internal; 363 break; 364 } 365 if (sizeof(wchar_t) == 1) { 366 from_index = ei_iso8859_1; 367 break; 368 } 369 #endif 370 #if HAVE_WCRTOMB 371 from_wchar = 1; 372 fromcode = locale_charset(); 373 continue; 374 #endif 375 goto invalid; 376 } 377 from_index = ap->encoding_index; 378 break; 379 } 380 cd = (struct conv_struct *) malloc(from_wchar != to_wchar 381 ? sizeof(struct wchar_conv_struct) 382 : sizeof(struct conv_struct)); 383 if (cd == NULL) { 384 errno = ENOMEM; 385 return (iconv_t)(-1); 386 } 387 cd->iindex = from_index; 388 cd->ifuncs = all_encodings[from_index].ifuncs; 389 cd->oindex = to_index; 390 cd->ofuncs = all_encodings[to_index].ofuncs; 391 cd->oflags = all_encodings[to_index].oflags; 392 /* Initialize the loop functions. */ 393 #if HAVE_MBRTOWC 394 if (to_wchar) { 395 #if HAVE_WCRTOMB 396 if (from_wchar) { 397 cd->lfuncs.loop_convert = wchar_id_loop_convert; 398 cd->lfuncs.loop_reset = wchar_id_loop_reset; 399 } else 400 #endif 401 { 402 cd->lfuncs.loop_convert = wchar_to_loop_convert; 403 cd->lfuncs.loop_reset = wchar_to_loop_reset; 404 } 405 } else 406 #endif 407 { 408 #if HAVE_WCRTOMB 409 if (from_wchar) { 410 cd->lfuncs.loop_convert = wchar_from_loop_convert; 411 cd->lfuncs.loop_reset = wchar_from_loop_reset; 412 } else 413 #endif 414 { 415 cd->lfuncs.loop_convert = unicode_loop_convert; 416 cd->lfuncs.loop_reset = unicode_loop_reset; 417 } 418 } 419 /* Initialize the states. */ 420 memset(&cd->istate,'\0',sizeof(state_t)); 421 memset(&cd->ostate,'\0',sizeof(state_t)); 422 /* Initialize the operation flags. */ 423 cd->transliterate = transliterate; 424 cd->discard_ilseq = discard_ilseq; 425 #ifndef LIBICONV_PLUG 426 cd->fallbacks.mb_to_uc_fallback = NULL; 427 cd->fallbacks.uc_to_mb_fallback = NULL; 428 cd->fallbacks.mb_to_wc_fallback = NULL; 429 cd->fallbacks.wc_to_mb_fallback = NULL; 430 cd->fallbacks.data = NULL; 431 cd->hooks.uc_hook = NULL; 432 cd->hooks.wc_hook = NULL; 433 cd->hooks.data = NULL; 434 #endif 435 /* Initialize additional fields. */ 436 if (from_wchar != to_wchar) { 437 struct wchar_conv_struct * wcd = (struct wchar_conv_struct *) cd; 438 memset(&wcd->state,'\0',sizeof(mbstate_t)); 439 } 440 /* Done. */ 441 return (iconv_t)cd; 442 invalid: 443 errno = EINVAL; 444 return (iconv_t)(-1); 445 } 446 447 size_t iconv (iconv_t icd, 448 ICONV_CONST char* * inbuf, size_t *inbytesleft, 449 char* * outbuf, size_t *outbytesleft) 450 { 451 conv_t cd = (conv_t) icd; 452 if (inbuf == NULL || *inbuf == NULL) 453 return cd->lfuncs.loop_reset(icd,outbuf,outbytesleft); 454 else 455 return cd->lfuncs.loop_convert(icd, 456 (const char* *)inbuf,inbytesleft, 457 outbuf,outbytesleft); 458 } 459 460 int iconv_close (iconv_t icd) 461 { 462 conv_t cd = (conv_t) icd; 463 free(cd); 464 return 0; 465 } 466 467 #ifndef LIBICONV_PLUG 468 469 int iconvctl (iconv_t icd, int request, void* argument) 470 { 471 conv_t cd = (conv_t) icd; 472 switch (request) { 473 case ICONV_TRIVIALP: 474 *(int *)argument = 475 ((cd->lfuncs.loop_convert == unicode_loop_convert 476 && cd->iindex == cd->oindex) 477 || cd->lfuncs.loop_convert == wchar_id_loop_convert 478 ? 1 : 0); 479 return 0; 480 case ICONV_GET_TRANSLITERATE: 481 *(int *)argument = cd->transliterate; 482 return 0; 483 case ICONV_SET_TRANSLITERATE: 484 cd->transliterate = (*(const int *)argument ? 1 : 0); 485 return 0; 486 case ICONV_GET_DISCARD_ILSEQ: 487 *(int *)argument = cd->discard_ilseq; 488 return 0; 489 case ICONV_SET_DISCARD_ILSEQ: 490 cd->discard_ilseq = (*(const int *)argument ? 1 : 0); 491 return 0; 492 case ICONV_SET_HOOKS: 493 if (argument != NULL) { 494 cd->hooks = *(const struct iconv_hooks *)argument; 495 } else { 496 cd->hooks.uc_hook = NULL; 497 cd->hooks.wc_hook = NULL; 498 cd->hooks.data = NULL; 499 } 500 return 0; 501 case ICONV_SET_FALLBACKS: 502 if (argument != NULL) { 503 cd->fallbacks = *(const struct iconv_fallbacks *)argument; 504 } else { 505 cd->fallbacks.mb_to_uc_fallback = NULL; 506 cd->fallbacks.uc_to_mb_fallback = NULL; 507 cd->fallbacks.mb_to_wc_fallback = NULL; 508 cd->fallbacks.wc_to_mb_fallback = NULL; 509 cd->fallbacks.data = NULL; 510 } 511 return 0; 512 default: 513 errno = EINVAL; 514 return -1; 515 } 516 } 517 518 /* An alias after its name has been converted from 'int' to 'const char*'. */ 519 struct nalias { const char* name; unsigned int encoding_index; }; 520 521 static int compare_by_index (const void * arg1, const void * arg2) 522 { 523 const struct nalias * alias1 = (const struct nalias *) arg1; 524 const struct nalias * alias2 = (const struct nalias *) arg2; 525 return (int)alias1->encoding_index - (int)alias2->encoding_index; 526 } 527 528 static int compare_by_name (const void * arg1, const void * arg2) 529 { 530 const char * name1 = *(const char **)arg1; 531 const char * name2 = *(const char **)arg2; 532 /* Compare alphabetically, but put "CS" names at the end. */ 533 int sign = strcmp(name1,name2); 534 if (sign != 0) { 535 sign = ((name1[0]=='C' && name1[1]=='S') - (name2[0]=='C' && name2[1]=='S')) 536 * 4 + (sign >= 0 ? 1 : -1); 537 } 538 return sign; 539 } 540 541 void iconvlist (int (*do_one) (unsigned int namescount, 542 const char * const * names, 543 void* data), 544 void* data) 545 { 546 #define aliascount1 sizeof(aliases)/sizeof(aliases[0]) 547 #ifndef aliases2_lookup 548 #define aliascount2 sizeof(sysdep_aliases)/sizeof(sysdep_aliases[0]) 549 #else 550 #define aliascount2 0 551 #endif 552 #define aliascount (aliascount1+aliascount2) 553 struct nalias aliasbuf[aliascount]; 554 const char * namesbuf[aliascount]; 555 size_t num_aliases; 556 { 557 /* Put all existing aliases into a buffer. */ 558 size_t i; 559 size_t j; 560 j = 0; 561 for (i = 0; i < aliascount1; i++) { 562 const struct alias * p = &aliases[i]; 563 if (p->name >= 0 564 && p->encoding_index != ei_local_char 565 && p->encoding_index != ei_local_wchar_t) { 566 aliasbuf[j].name = stringpool + p->name; 567 aliasbuf[j].encoding_index = p->encoding_index; 568 j++; 569 } 570 } 571 #ifndef aliases2_lookup 572 for (i = 0; i < aliascount2; i++) { 573 aliasbuf[j].name = stringpool2 + sysdep_aliases[i].name; 574 aliasbuf[j].encoding_index = sysdep_aliases[i].encoding_index; 575 j++; 576 } 577 #endif 578 num_aliases = j; 579 } 580 /* Sort by encoding_index. */ 581 if (num_aliases > 1) 582 qsort(aliasbuf, num_aliases, sizeof(struct nalias), compare_by_index); 583 { 584 /* Process all aliases with the same encoding_index together. */ 585 size_t j; 586 j = 0; 587 while (j < num_aliases) { 588 unsigned int ei = aliasbuf[j].encoding_index; 589 size_t i = 0; 590 do 591 namesbuf[i++] = aliasbuf[j++].name; 592 while (j < num_aliases && aliasbuf[j].encoding_index == ei); 593 if (i > 1) 594 qsort(namesbuf, i, sizeof(const char *), compare_by_name); 595 /* Call the callback. */ 596 if (do_one(i,namesbuf,data)) 597 break; 598 } 599 } 600 #undef aliascount 601 #undef aliascount2 602 #undef aliascount1 603 } 604 605 /* 606 * Table of canonical names of encodings. 607 * Instead of strings, it contains offsets into stringpool and stringpool2. 608 */ 609 static const unsigned short all_canonical[] = { 610 #include "canonical.h" 611 #ifdef USE_AIX 612 #include "canonical_aix.h" 613 #endif 614 #ifdef USE_OSF1 615 #include "canonical_osf1.h" 616 #endif 617 #ifdef USE_DOS 618 #include "canonical_dos.h" 619 #endif 620 #ifdef USE_EXTRA 621 #include "canonical_extra.h" 622 #endif 623 #include "canonical_local.h" 624 }; 625 626 const char * iconv_canonicalize (const char * name) 627 { 628 const char* code; 629 char buf[MAX_WORD_LENGTH+10+1]; 630 const char* cp; 631 char* bp; 632 const struct alias * ap; 633 unsigned int count; 634 unsigned int index; 635 const char* pool; 636 637 /* Before calling aliases_lookup, convert the input string to upper case, 638 * and check whether it's entirely ASCII (we call gperf with option "-7" 639 * to achieve a smaller table) and non-empty. If it's not entirely ASCII, 640 * or if it's too long, it is not a valid encoding name. 641 */ 642 for (code = name;;) { 643 /* Search code in the table. */ 644 for (cp = code, bp = buf, count = MAX_WORD_LENGTH+10+1; ; cp++, bp++) { 645 unsigned char c = * (unsigned char *) cp; 646 if (c >= 0x80) 647 goto invalid; 648 if (c >= 'a' && c <= 'z') 649 c -= 'a'-'A'; 650 *bp = c; 651 if (c == '\0') 652 break; 653 if (--count == 0) 654 goto invalid; 655 } 656 for (;;) { 657 if (bp-buf >= 10 && memcmp(bp-10,"//TRANSLIT",10)==0) { 658 bp -= 10; 659 *bp = '\0'; 660 continue; 661 } 662 if (bp-buf >= 8 && memcmp(bp-8,"//IGNORE",8)==0) { 663 bp -= 8; 664 *bp = '\0'; 665 continue; 666 } 667 break; 668 } 669 if (buf[0] == '\0') { 670 code = locale_charset(); 671 /* Avoid an endless loop that could occur when using an older version 672 of localcharset.c. */ 673 if (code[0] == '\0') 674 goto invalid; 675 continue; 676 } 677 pool = stringpool; 678 ap = aliases_lookup(buf,bp-buf); 679 if (ap == NULL) { 680 pool = stringpool2; 681 ap = aliases2_lookup(buf); 682 if (ap == NULL) 683 goto invalid; 684 } 685 if (ap->encoding_index == ei_local_char) { 686 code = locale_charset(); 687 /* Avoid an endless loop that could occur when using an older version 688 of localcharset.c. */ 689 if (code[0] == '\0') 690 goto invalid; 691 continue; 692 } 693 if (ap->encoding_index == ei_local_wchar_t) { 694 /* On systems which define __STDC_ISO_10646__, wchar_t is Unicode. 695 This is also the case on native Woe32 systems. */ 696 #if __STDC_ISO_10646__ || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) 697 if (sizeof(wchar_t) == 4) { 698 index = ei_ucs4internal; 699 break; 700 } 701 if (sizeof(wchar_t) == 2) { 702 index = ei_ucs2internal; 703 break; 704 } 705 if (sizeof(wchar_t) == 1) { 706 index = ei_iso8859_1; 707 break; 708 } 709 #endif 710 } 711 index = ap->encoding_index; 712 break; 713 } 714 return all_canonical[index] + pool; 715 invalid: 716 return name; 717 } 718 719 int _libiconv_version = _LIBICONV_VERSION; 720 721 #if defined __FreeBSD__ && !defined __gnu_freebsd__ 722 /* GNU libiconv is the native FreeBSD iconv implementation since 2002. 723 It wants to define the symbols 'iconv_open', 'iconv', 'iconv_close'. */ 724 #define strong_alias(name, aliasname) _strong_alias(name, aliasname) 725 #define _strong_alias(name, aliasname) \ 726 extern __typeof (name) aliasname __attribute__ ((alias (#name))); 727 #undef iconv_open 728 #undef iconv 729 #undef iconv_close 730 strong_alias (libiconv_open, iconv_open) 731 strong_alias (libiconv, iconv) 732 strong_alias (libiconv_close, iconv_close) 733 #endif 734 735 #endif 736