Annotation of embedaddon/libiconv/src/iconv.c, revision 1.1

1.1     ! misho       1: /* Copyright (C) 2000-2009 Free Software Foundation, Inc.
        !             2:    This file is part of the GNU LIBICONV Library.
        !             3: 
        !             4:    This program is free software: you can redistribute it and/or modify
        !             5:    it under the terms of the GNU General Public License as published by
        !             6:    the Free Software Foundation; either version 3 of the License, or
        !             7:    (at your option) any later version.
        !             8: 
        !             9:    This program 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
        !            12:    GNU General Public License for more details.
        !            13: 
        !            14:    You should have received a copy of the GNU General Public License
        !            15:    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
        !            16: 
        !            17: #include "config.h"
        !            18: #ifndef ICONV_CONST
        !            19: # define ICONV_CONST
        !            20: #endif
        !            21: 
        !            22: #include <limits.h>
        !            23: #include <stddef.h>
        !            24: #include <stdio.h>
        !            25: #include <stdlib.h>
        !            26: #include <string.h>
        !            27: #include <iconv.h>
        !            28: #include <errno.h>
        !            29: #include <locale.h>
        !            30: #include <fcntl.h>
        !            31: 
        !            32: /* Ensure that iconv_no_i18n does not depend on libintl.  */
        !            33: #ifdef NO_I18N
        !            34: # undef ENABLE_NLS
        !            35: # undef ENABLE_RELOCATABLE
        !            36: #endif
        !            37: 
        !            38: #include "binary-io.h"
        !            39: #include "progname.h"
        !            40: #include "relocatable.h"
        !            41: #include "xalloc.h"
        !            42: #include "uniwidth.h"
        !            43: #include "uniwidth/cjk.h"
        !            44: 
        !            45: /* Ensure that iconv_no_i18n does not depend on libintl.  */
        !            46: #ifdef NO_I18N
        !            47: #include <stdarg.h>
        !            48: static void
        !            49: error (int status, int errnum, const char *message, ...)
        !            50: {
        !            51:   va_list args;
        !            52: 
        !            53:   fflush(stdout);
        !            54:   fprintf(stderr,"%s: ",program_name);
        !            55:   va_start(args,message);
        !            56:   vfprintf(stderr,message,args);
        !            57:   va_end(args);
        !            58:   if (errnum) {
        !            59:     const char *s = strerror(errnum);
        !            60:     if (s == NULL)
        !            61:       s = "Unknown system error";
        !            62:   }
        !            63:   putc('\n',stderr);
        !            64:   fflush(stderr);
        !            65:   if (status)
        !            66:     exit(status);
        !            67: }
        !            68: #else
        !            69: # include "error.h"
        !            70: #endif
        !            71: 
        !            72: #include "gettext.h"
        !            73: 
        !            74: #define _(str) gettext(str)
        !            75: 
        !            76: /* Ensure that iconv_no_i18n does not depend on libintl.  */
        !            77: #ifdef NO_I18N
        !            78: # define xmalloc malloc
        !            79: # define xalloc_die abort
        !            80: #endif
        !            81: 
        !            82: /* Locale independent test for a decimal digit.
        !            83:    Argument can be  'char' or 'unsigned char'.  (Whereas the argument of
        !            84:    <ctype.h> isdigit must be an 'unsigned char'.)  */
        !            85: #undef isdigit
        !            86: #define isdigit(c) ((unsigned int) ((c) - '0') < 10)
        !            87: 
        !            88: /* Locale independent test for a printable character.
        !            89:    Argument can be  'char' or 'unsigned char'.  (Whereas the argument of
        !            90:    <ctype.h> isdigit must be an 'unsigned char'.)  */
        !            91: #define c_isprint(c) ((c) >= ' ' && (c) <= '~')
        !            92: 
        !            93: /* ========================================================================= */
        !            94: 
        !            95: static int discard_unconvertible = 0;
        !            96: static int silent = 0;
        !            97: 
        !            98: static void usage (int exitcode)
        !            99: {
        !           100:   if (exitcode != 0) {
        !           101:     const char* helpstring1 =
        !           102:       /* TRANSLATORS: The first line of the short usage message.  */
        !           103:       _("Usage: iconv [-c] [-s] [-f fromcode] [-t tocode] [file ...]");
        !           104:     const char* helpstring2 =
        !           105:       /* TRANSLATORS: The second line of the short usage message.
        !           106:          Align it correctly against the first line.  */
        !           107:       _("or:    iconv -l");
        !           108:     fprintf(stderr, "%s\n%s\n", helpstring1, helpstring2);
        !           109:     fprintf(stderr, _("Try `%s --help' for more information.\n"), program_name);
        !           110:   } else {
        !           111:     /* xgettext: no-wrap */
        !           112:     /* TRANSLATORS: The first line of the long usage message.
        !           113:        The %s placeholder expands to the program name.  */
        !           114:     printf(_("\
        !           115: Usage: %s [OPTION...] [-f ENCODING] [-t ENCODING] [INPUTFILE...]\n"),
        !           116:            program_name);
        !           117:     /* xgettext: no-wrap */
        !           118:     /* TRANSLATORS: The second line of the long usage message.
        !           119:        Align it correctly against the first line.
        !           120:        The %s placeholder expands to the program name.  */
        !           121:     printf(_("\
        !           122: or:    %s -l\n"),
        !           123:            program_name);
        !           124:     printf("\n");
        !           125:     /* xgettext: no-wrap */
        !           126:     /* TRANSLATORS: Description of the iconv program.  */
        !           127:     printf(_("\
        !           128: Converts text from one encoding to another encoding.\n"));
        !           129:     printf("\n");
        !           130:     /* xgettext: no-wrap */
        !           131:     printf(_("\
        !           132: Options controlling the input and output format:\n"));
        !           133:     /* xgettext: no-wrap */
        !           134:     printf(_("\
        !           135:   -f ENCODING, --from-code=ENCODING\n\
        !           136:                               the encoding of the input\n"));
        !           137:     /* xgettext: no-wrap */
        !           138:     printf(_("\
        !           139:   -t ENCODING, --to-code=ENCODING\n\
        !           140:                               the encoding of the output\n"));
        !           141:     printf("\n");
        !           142:     /* xgettext: no-wrap */
        !           143:     printf(_("\
        !           144: Options controlling conversion problems:\n"));
        !           145:     /* xgettext: no-wrap */
        !           146:     printf(_("\
        !           147:   -c                          discard unconvertible characters\n"));
        !           148:     /* xgettext: no-wrap */
        !           149:     printf(_("\
        !           150:   --unicode-subst=FORMATSTRING\n\
        !           151:                               substitution for unconvertible Unicode characters\n"));
        !           152:     /* xgettext: no-wrap */
        !           153:     printf(_("\
        !           154:   --byte-subst=FORMATSTRING   substitution for unconvertible bytes\n"));
        !           155:     /* xgettext: no-wrap */
        !           156:     printf(_("\
        !           157:   --widechar-subst=FORMATSTRING\n\
        !           158:                               substitution for unconvertible wide characters\n"));
        !           159:     printf("\n");
        !           160:     /* xgettext: no-wrap */
        !           161:     printf(_("\
        !           162: Options controlling error output:\n"));
        !           163:     /* xgettext: no-wrap */
        !           164:     printf(_("\
        !           165:   -s, --silent                suppress error messages about conversion problems\n"));
        !           166:     printf("\n");
        !           167:     /* xgettext: no-wrap */
        !           168:     printf(_("\
        !           169: Informative output:\n"));
        !           170:     /* xgettext: no-wrap */
        !           171:     printf(_("\
        !           172:   -l, --list                  list the supported encodings\n"));
        !           173:     /* xgettext: no-wrap */
        !           174:     printf(_("\
        !           175:   --help                      display this help and exit\n"));
        !           176:     /* xgettext: no-wrap */
        !           177:     printf(_("\
        !           178:   --version                   output version information and exit\n"));
        !           179:     printf("\n");
        !           180:     /* TRANSLATORS: The placeholder indicates the bug-reporting address
        !           181:        for this package.  Please add _another line_ saying
        !           182:        "Report translation bugs to <...>\n" with the address for translation
        !           183:        bugs (typically your translation team's web or email address).  */
        !           184:     fputs(_("Report bugs to <bug-gnu-libiconv@gnu.org>.\n"),stdout);
        !           185:   }
        !           186:   exit(exitcode);
        !           187: }
        !           188: 
        !           189: static void print_version (void)
        !           190: {
        !           191:   printf("iconv (GNU libiconv %d.%d)\n",
        !           192:          _libiconv_version >> 8, _libiconv_version & 0xff);
        !           193:   printf("Copyright (C) %s Free Software Foundation, Inc.\n", "2000-2009");
        !           194:   /* xgettext: no-wrap */
        !           195:   fputs (_("\
        !           196: License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
        !           197: This is free software: you are free to change and redistribute it.\n\
        !           198: There is NO WARRANTY, to the extent permitted by law.\n\
        !           199: "),stdout);
        !           200:   /* TRANSLATORS: The %s placeholder expands to an author's name.  */
        !           201:   printf(_("Written by %s.\n"),"Bruno Haible");
        !           202:   exit(EXIT_SUCCESS);
        !           203: }
        !           204: 
        !           205: static int print_one (unsigned int namescount, const char * const * names,
        !           206:                       void* data)
        !           207: {
        !           208:   unsigned int i;
        !           209:   (void)data;
        !           210:   for (i = 0; i < namescount; i++) {
        !           211:     if (i > 0)
        !           212:       putc(' ',stdout);
        !           213:     fputs(names[i],stdout);
        !           214:   }
        !           215:   putc('\n',stdout);
        !           216:   return 0;
        !           217: }
        !           218: 
        !           219: /* ========================================================================= */
        !           220: 
        !           221: /* Line number and column position. */
        !           222: static unsigned int line;
        !           223: static unsigned int column;
        !           224: static const char* cjkcode;
        !           225: /* Update the line number and column position after a character was
        !           226:    successfully converted. */
        !           227: static void update_line_column (unsigned int uc, void* data)
        !           228: {
        !           229:   if (uc == 0x000A) {
        !           230:     line++;
        !           231:     column = 0;
        !           232:   } else {
        !           233:     int width = uc_width(uc, cjkcode);
        !           234:     if (width >= 0)
        !           235:       column += width;
        !           236:     else if (uc == 0x0009)
        !           237:       column += 8 - (column % 8);
        !           238:   }
        !           239: }
        !           240: 
        !           241: /* ========================================================================= */
        !           242: 
        !           243: /* Production of placeholder strings as fallback for unconvertible
        !           244:    characters. */
        !           245: 
        !           246: /* Check that the argument is a format string taking either no argument
        !           247:    or exactly one unsigned integer argument. Returns the maximum output
        !           248:    size of the format string. */
        !           249: static size_t check_subst_formatstring (const char *format, const char *param_name)
        !           250: {
        !           251:   /* C format strings are described in POSIX (IEEE P1003.1 2001), section
        !           252:      XSH 3 fprintf().  See also Linux fprintf(3) manual page.
        !           253:      For simplicity, we don't accept
        !           254:        - the '%m$' reordering syntax,
        !           255:        - the 'I' flag,
        !           256:        - width specifications referring to an argument,
        !           257:        - precision specifications referring to an argument,
        !           258:        - size specifiers,
        !           259:        - format specifiers other than 'o', 'u', 'x', 'X'.
        !           260:      What remains?
        !           261:      A directive
        !           262:        - starts with '%',
        !           263:        - is optionally followed by any of the characters '#', '0', '-', ' ',
        !           264:          '+', "'", each of which acts as a flag,
        !           265:        - is optionally followed by a width specification: a nonempty digit
        !           266:          sequence,
        !           267:        - is optionally followed by '.' and a precision specification: a
        !           268:          nonempty digit sequence,
        !           269:        - is finished by a specifier
        !           270:          - '%', that needs no argument,
        !           271:          - 'o', 'u', 'x', 'X', that need an unsigned integer argument.
        !           272:    */
        !           273:   size_t maxsize = 0;
        !           274:   unsigned int unnumbered_arg_count = 0;
        !           275: 
        !           276:   for (; *format != '\0';) {
        !           277:     if (*format++ == '%') {
        !           278:       /* A directive. */
        !           279:       unsigned int width = 0;
        !           280:       unsigned int precision = 0;
        !           281:       unsigned int length;
        !           282:       /* Parse flags. */
        !           283:       for (;;) {
        !           284:         if (*format == ' ' || *format == '+' || *format == '-'
        !           285:             || *format == '#' || *format == '0' || *format == '\'')
        !           286:           format++;
        !           287:         else
        !           288:           break;
        !           289:       }
        !           290:       /* Parse width. */
        !           291:       if (*format == '*')
        !           292:         error(EXIT_FAILURE,0,
        !           293:               /* TRANSLATORS: An error message.
        !           294:                  The %s placeholder expands to a command-line option.  */
        !           295:               _("%s argument: A format directive with a variable width is not allowed here."),
        !           296:               param_name);
        !           297:       if (isdigit (*format)) {
        !           298:         do {
        !           299:           width = 10*width + (*format - '0');
        !           300:           format++;
        !           301:         } while (isdigit (*format));
        !           302:       }
        !           303:       /* Parse precision. */
        !           304:       if (*format == '.') {
        !           305:         format++;
        !           306:         if (*format == '*')
        !           307:           error(EXIT_FAILURE,0,
        !           308:                 /* TRANSLATORS: An error message.
        !           309:                    The %s placeholder expands to a command-line option.  */
        !           310:                 _("%s argument: A format directive with a variable precision is not allowed here."),
        !           311:                 param_name);
        !           312:         if (isdigit (*format)) {
        !           313:           do {
        !           314:             precision = 10*precision + (*format - '0');
        !           315:             format++;
        !           316:           } while (isdigit (*format));
        !           317:         }
        !           318:       }
        !           319:       /* Parse size. */
        !           320:       switch (*format) {
        !           321:         case 'h': case 'l': case 'L': case 'q':
        !           322:         case 'j': case 'z': case 'Z': case 't':
        !           323:           error(EXIT_FAILURE,0,
        !           324:                 /* TRANSLATORS: An error message.
        !           325:                    The %s placeholder expands to a command-line option.  */
        !           326:                 _("%s argument: A format directive with a size is not allowed here."),
        !           327:                 param_name);
        !           328:       }
        !           329:       /* Parse end of directive. */
        !           330:       switch (*format) {
        !           331:         case '%':
        !           332:           length = 1;
        !           333:           break;
        !           334:         case 'u': case 'o': case 'x': case 'X':
        !           335:           if (*format == 'u') {
        !           336:             length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT
        !           337:                                      * 0.30103 /* binary -> decimal */
        !           338:                                     )
        !           339:                      + 1; /* turn floor into ceil */
        !           340:             if (length < precision)
        !           341:               length = precision;
        !           342:             length *= 2; /* estimate for FLAG_GROUP */
        !           343:             length += 1; /* account for leading sign */
        !           344:           } else if (*format == 'o') {
        !           345:             length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT
        !           346:                                      * 0.333334 /* binary -> octal */
        !           347:                                     )
        !           348:                      + 1; /* turn floor into ceil */
        !           349:             if (length < precision)
        !           350:               length = precision;
        !           351:             length += 1; /* account for leading sign */
        !           352:           } else { /* 'x', 'X' */
        !           353:             length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT
        !           354:                                      * 0.25 /* binary -> hexadecimal */
        !           355:                                     )
        !           356:                      + 1; /* turn floor into ceil */
        !           357:             if (length < precision)
        !           358:               length = precision;
        !           359:             length += 2; /* account for leading sign or alternate form */
        !           360:           }
        !           361:           unnumbered_arg_count++;
        !           362:           break;
        !           363:         default:
        !           364:           if (*format == '\0')
        !           365:             error(EXIT_FAILURE,0,
        !           366:                   /* TRANSLATORS: An error message.
        !           367:                      The %s placeholder expands to a command-line option.  */
        !           368:                   _("%s argument: The string ends in the middle of a directive."),
        !           369:                   param_name);
        !           370:           else if (c_isprint(*format))
        !           371:             error(EXIT_FAILURE,0,
        !           372:                   /* TRANSLATORS: An error message.
        !           373:                      The %s placeholder expands to a command-line option.
        !           374:                      The %c placeholder expands to an unknown format directive.  */
        !           375:                   _("%s argument: The character '%c' is not a valid conversion specifier."),
        !           376:                   param_name,*format);
        !           377:           else
        !           378:             error(EXIT_FAILURE,0,
        !           379:                   /* TRANSLATORS: An error message.
        !           380:                      The %s placeholder expands to a command-line option.  */
        !           381:                   _("%s argument: The character that terminates the format directive is not a valid conversion specifier."),
        !           382:                   param_name);
        !           383:           abort(); /*NOTREACHED*/
        !           384:       }
        !           385:       format++;
        !           386:       if (length < width)
        !           387:         length = width;
        !           388:       maxsize += length;
        !           389:     } else
        !           390:       maxsize++;
        !           391:   }
        !           392:   if (unnumbered_arg_count > 1)
        !           393:     error(EXIT_FAILURE,0,
        !           394:           /* TRANSLATORS: An error message.
        !           395:              The %s placeholder expands to a command-line option.
        !           396:              The %u placeholder expands to the number of arguments consumed by the format string.  */
        !           397:           ngettext("%s argument: The format string consumes more than one argument: %u argument.",
        !           398:                    "%s argument: The format string consumes more than one argument: %u arguments.",
        !           399:                    unnumbered_arg_count),
        !           400:           param_name,unnumbered_arg_count);
        !           401:   return maxsize;
        !           402: }
        !           403: 
        !           404: /* Format strings. */
        !           405: static const char* ilseq_byte_subst;
        !           406: static const char* ilseq_wchar_subst;
        !           407: static const char* ilseq_unicode_subst;
        !           408: 
        !           409: /* Maximum result size for each format string. */
        !           410: static size_t ilseq_byte_subst_size;
        !           411: static size_t ilseq_wchar_subst_size;
        !           412: static size_t ilseq_unicode_subst_size;
        !           413: 
        !           414: /* Buffer of size ilseq_byte_subst_size+1. */
        !           415: static char* ilseq_byte_subst_buffer;
        !           416: #if HAVE_WCHAR_T
        !           417: /* Buffer of size ilseq_wchar_subst_size+1. */
        !           418: static char* ilseq_wchar_subst_buffer;
        !           419: #endif
        !           420: /* Buffer of size ilseq_unicode_subst_size+1. */
        !           421: static char* ilseq_unicode_subst_buffer;
        !           422: 
        !           423: /* Auxiliary variables for subst_mb_to_uc_fallback. */
        !           424: /* Converter from locale encoding to UCS-4. */
        !           425: static iconv_t subst_mb_to_uc_cd;
        !           426: /* Buffer of size ilseq_byte_subst_size. */
        !           427: static unsigned int* subst_mb_to_uc_temp_buffer;
        !           428: 
        !           429: static void subst_mb_to_uc_fallback
        !           430:             (const char* inbuf, size_t inbufsize,
        !           431:              void (*write_replacement) (const unsigned int *buf, size_t buflen,
        !           432:                                         void* callback_arg),
        !           433:              void* callback_arg,
        !           434:              void* data)
        !           435: {
        !           436:   for (; inbufsize > 0; inbuf++, inbufsize--) {
        !           437:     const char* inptr;
        !           438:     size_t inbytesleft;
        !           439:     char* outptr;
        !           440:     size_t outbytesleft;
        !           441:     sprintf(ilseq_byte_subst_buffer,
        !           442:             ilseq_byte_subst, (unsigned int)(unsigned char)*inbuf);
        !           443:     inptr = ilseq_byte_subst_buffer;
        !           444:     inbytesleft = strlen(ilseq_byte_subst_buffer);
        !           445:     outptr = (char*)subst_mb_to_uc_temp_buffer;
        !           446:     outbytesleft = ilseq_byte_subst_size*sizeof(unsigned int);
        !           447:     iconv(subst_mb_to_uc_cd,NULL,NULL,NULL,NULL);
        !           448:     if (iconv(subst_mb_to_uc_cd, (ICONV_CONST char**)&inptr,&inbytesleft, &outptr,&outbytesleft)
        !           449:         == (size_t)(-1)
        !           450:         || iconv(subst_mb_to_uc_cd, NULL,NULL, &outptr,&outbytesleft)
        !           451:            == (size_t)(-1))
        !           452:       error(EXIT_FAILURE,0,
        !           453:             /* TRANSLATORS: An error message.
        !           454:                The %s placeholder expands to a piece of text, specified through --byte-subst.  */
        !           455:             _("cannot convert byte substitution to Unicode: %s"),
        !           456:             ilseq_byte_subst_buffer);
        !           457:     if (!(outbytesleft%sizeof(unsigned int) == 0))
        !           458:       abort();
        !           459:     write_replacement(subst_mb_to_uc_temp_buffer,
        !           460:                       ilseq_byte_subst_size-(outbytesleft/sizeof(unsigned int)),
        !           461:                       callback_arg);
        !           462:   }
        !           463: }
        !           464: 
        !           465: /* Auxiliary variables for subst_uc_to_mb_fallback. */
        !           466: /* Converter from locale encoding to target encoding. */
        !           467: static iconv_t subst_uc_to_mb_cd;
        !           468: /* Buffer of size ilseq_unicode_subst_size*4. */
        !           469: static char* subst_uc_to_mb_temp_buffer;
        !           470: 
        !           471: static void subst_uc_to_mb_fallback
        !           472:             (unsigned int code,
        !           473:              void (*write_replacement) (const char *buf, size_t buflen,
        !           474:                                         void* callback_arg),
        !           475:              void* callback_arg,
        !           476:              void* data)
        !           477: {
        !           478:   const char* inptr;
        !           479:   size_t inbytesleft;
        !           480:   char* outptr;
        !           481:   size_t outbytesleft;
        !           482:   sprintf(ilseq_unicode_subst_buffer, ilseq_unicode_subst, code);
        !           483:   inptr = ilseq_unicode_subst_buffer;
        !           484:   inbytesleft = strlen(ilseq_unicode_subst_buffer);
        !           485:   outptr = subst_uc_to_mb_temp_buffer;
        !           486:   outbytesleft = ilseq_unicode_subst_size*4;
        !           487:   iconv(subst_uc_to_mb_cd,NULL,NULL,NULL,NULL);
        !           488:   if (iconv(subst_uc_to_mb_cd, (ICONV_CONST char**)&inptr,&inbytesleft, &outptr,&outbytesleft)
        !           489:       == (size_t)(-1)
        !           490:       || iconv(subst_uc_to_mb_cd, NULL,NULL, &outptr,&outbytesleft)
        !           491:          == (size_t)(-1))
        !           492:     error(EXIT_FAILURE,0,
        !           493:           /* TRANSLATORS: An error message.
        !           494:              The %s placeholder expands to a piece of text, specified through --unicode-subst.  */
        !           495:           _("cannot convert unicode substitution to target encoding: %s"),
        !           496:           ilseq_unicode_subst_buffer);
        !           497:   write_replacement(subst_uc_to_mb_temp_buffer,
        !           498:                     ilseq_unicode_subst_size*4-outbytesleft,
        !           499:                     callback_arg);
        !           500: }
        !           501: 
        !           502: #if HAVE_WCHAR_T
        !           503: 
        !           504: /* Auxiliary variables for subst_mb_to_wc_fallback. */
        !           505: /* Converter from locale encoding to wchar_t. */
        !           506: static iconv_t subst_mb_to_wc_cd;
        !           507: /* Buffer of size ilseq_byte_subst_size. */
        !           508: static wchar_t* subst_mb_to_wc_temp_buffer;
        !           509: 
        !           510: static void subst_mb_to_wc_fallback
        !           511:             (const char* inbuf, size_t inbufsize,
        !           512:              void (*write_replacement) (const wchar_t *buf, size_t buflen,
        !           513:                                         void* callback_arg),
        !           514:              void* callback_arg,
        !           515:              void* data)
        !           516: {
        !           517:   for (; inbufsize > 0; inbuf++, inbufsize--) {
        !           518:     const char* inptr;
        !           519:     size_t inbytesleft;
        !           520:     char* outptr;
        !           521:     size_t outbytesleft;
        !           522:     sprintf(ilseq_byte_subst_buffer,
        !           523:             ilseq_byte_subst, (unsigned int)(unsigned char)*inbuf);
        !           524:     inptr = ilseq_byte_subst_buffer;
        !           525:     inbytesleft = strlen(ilseq_byte_subst_buffer);
        !           526:     outptr = (char*)subst_mb_to_wc_temp_buffer;
        !           527:     outbytesleft = ilseq_byte_subst_size*sizeof(wchar_t);
        !           528:     iconv(subst_mb_to_wc_cd,NULL,NULL,NULL,NULL);
        !           529:     if (iconv(subst_mb_to_wc_cd, (ICONV_CONST char**)&inptr,&inbytesleft, &outptr,&outbytesleft)
        !           530:         == (size_t)(-1)
        !           531:         || iconv(subst_mb_to_wc_cd, NULL,NULL, &outptr,&outbytesleft)
        !           532:            == (size_t)(-1))
        !           533:       error(EXIT_FAILURE,0,
        !           534:             /* TRANSLATORS: An error message.
        !           535:                The %s placeholder expands to a piece of text, specified through --byte-subst.  */
        !           536:             _("cannot convert byte substitution to wide string: %s"),
        !           537:             ilseq_byte_subst_buffer);
        !           538:     if (!(outbytesleft%sizeof(wchar_t) == 0))
        !           539:       abort();
        !           540:     write_replacement(subst_mb_to_wc_temp_buffer,
        !           541:                       ilseq_byte_subst_size-(outbytesleft/sizeof(wchar_t)),
        !           542:                       callback_arg);
        !           543:   }
        !           544: }
        !           545: 
        !           546: /* Auxiliary variables for subst_wc_to_mb_fallback. */
        !           547: /* Converter from locale encoding to target encoding. */
        !           548: static iconv_t subst_wc_to_mb_cd;
        !           549: /* Buffer of size ilseq_wchar_subst_size*4.
        !           550:    Hardcode factor 4, because MB_LEN_MAX is not reliable on some platforms. */
        !           551: static char* subst_wc_to_mb_temp_buffer;
        !           552: 
        !           553: static void subst_wc_to_mb_fallback
        !           554:             (wchar_t code,
        !           555:              void (*write_replacement) (const char *buf, size_t buflen,
        !           556:                                         void* callback_arg),
        !           557:              void* callback_arg,
        !           558:              void* data)
        !           559: {
        !           560:   const char* inptr;
        !           561:   size_t inbytesleft;
        !           562:   char* outptr;
        !           563:   size_t outbytesleft;
        !           564:   sprintf(ilseq_wchar_subst_buffer, ilseq_wchar_subst, (unsigned int) code);
        !           565:   inptr = ilseq_wchar_subst_buffer;
        !           566:   inbytesleft = strlen(ilseq_wchar_subst_buffer);
        !           567:   outptr = subst_wc_to_mb_temp_buffer;
        !           568:   outbytesleft = ilseq_wchar_subst_size*4;
        !           569:   iconv(subst_wc_to_mb_cd,NULL,NULL,NULL,NULL);
        !           570:   if (iconv(subst_wc_to_mb_cd, (ICONV_CONST char**)&inptr,&inbytesleft, &outptr,&outbytesleft)
        !           571:       == (size_t)(-1)
        !           572:       || iconv(subst_wc_to_mb_cd, NULL,NULL, &outptr,&outbytesleft)
        !           573:          == (size_t)(-1))
        !           574:     error(EXIT_FAILURE,0,
        !           575:           /* TRANSLATORS: An error message.
        !           576:              The %s placeholder expands to a piece of text, specified through --widechar-subst.  */
        !           577:           _("cannot convert widechar substitution to target encoding: %s"),
        !           578:           ilseq_wchar_subst_buffer);
        !           579:   write_replacement(subst_wc_to_mb_temp_buffer,
        !           580:                     ilseq_wchar_subst_size*4-outbytesleft,
        !           581:                     callback_arg);
        !           582: }
        !           583: 
        !           584: #else
        !           585: 
        !           586: #define subst_mb_to_wc_fallback NULL
        !           587: #define subst_wc_to_mb_fallback NULL
        !           588: 
        !           589: #endif
        !           590: 
        !           591: /* Auxiliary variables for subst_mb_to_mb_fallback. */
        !           592: /* Converter from locale encoding to target encoding. */
        !           593: static iconv_t subst_mb_to_mb_cd;
        !           594: /* Buffer of size ilseq_byte_subst_size*4. */
        !           595: static char* subst_mb_to_mb_temp_buffer;
        !           596: 
        !           597: static void subst_mb_to_mb_fallback (const char* inbuf, size_t inbufsize)
        !           598: {
        !           599:   for (; inbufsize > 0; inbuf++, inbufsize--) {
        !           600:     const char* inptr;
        !           601:     size_t inbytesleft;
        !           602:     char* outptr;
        !           603:     size_t outbytesleft;
        !           604:     sprintf(ilseq_byte_subst_buffer,
        !           605:             ilseq_byte_subst, (unsigned int)(unsigned char)*inbuf);
        !           606:     inptr = ilseq_byte_subst_buffer;
        !           607:     inbytesleft = strlen(ilseq_byte_subst_buffer);
        !           608:     outptr = subst_mb_to_mb_temp_buffer;
        !           609:     outbytesleft = ilseq_byte_subst_size*4;
        !           610:     iconv(subst_mb_to_mb_cd,NULL,NULL,NULL,NULL);
        !           611:     if (iconv(subst_mb_to_mb_cd, (ICONV_CONST char**)&inptr,&inbytesleft, &outptr,&outbytesleft)
        !           612:         == (size_t)(-1)
        !           613:         || iconv(subst_mb_to_mb_cd, NULL,NULL, &outptr,&outbytesleft)
        !           614:            == (size_t)(-1))
        !           615:       error(EXIT_FAILURE,0,
        !           616:             /* TRANSLATORS: An error message.
        !           617:                The %s placeholder expands to a piece of text, specified through --byte-subst.  */
        !           618:             _("cannot convert byte substitution to target encoding: %s"),
        !           619:             ilseq_byte_subst_buffer);
        !           620:     fwrite(subst_mb_to_mb_temp_buffer,1,ilseq_byte_subst_size*4-outbytesleft,
        !           621:            stdout);
        !           622:   }
        !           623: }
        !           624: 
        !           625: /* ========================================================================= */
        !           626: 
        !           627: /* Error messages during conversion.  */
        !           628: 
        !           629: static void conversion_error_EILSEQ (const char* infilename)
        !           630: {
        !           631:   fflush(stdout);
        !           632:   if (column > 0)
        !           633:     putc('\n',stderr);
        !           634:   error(0,0,
        !           635:         /* TRANSLATORS: An error message.
        !           636:            The placeholders expand to the input file name, a line number, and a column number.  */
        !           637:         _("%s:%u:%u: cannot convert"),
        !           638:         infilename,line,column);
        !           639: }
        !           640: 
        !           641: static void conversion_error_EINVAL (const char* infilename)
        !           642: {
        !           643:   fflush(stdout);
        !           644:   if (column > 0)
        !           645:     putc('\n',stderr);
        !           646:   error(0,0,
        !           647:         /* TRANSLATORS: An error message.
        !           648:            The placeholders expand to the input file name, a line number, and a column number.
        !           649:            A "shift sequence" is a sequence of bytes that changes the state of the converter;
        !           650:            this concept exists only for "stateful" encodings like ISO-2022-JP.  */
        !           651:         _("%s:%u:%u: incomplete character or shift sequence"),
        !           652:         infilename,line,column);
        !           653: }
        !           654: 
        !           655: static void conversion_error_other (int errnum, const char* infilename)
        !           656: {
        !           657:   fflush(stdout);
        !           658:   if (column > 0)
        !           659:     putc('\n',stderr);
        !           660:   error(0,errnum,
        !           661:         /* TRANSLATORS: The first part of an error message.
        !           662:            It is followed by a colon and a detail message.
        !           663:            The placeholders expand to the input file name, a line number, and a column number.  */
        !           664:         _("%s:%u:%u"),
        !           665:         infilename,line,column);
        !           666: }
        !           667: 
        !           668: /* Convert the input given in infile.  */
        !           669: 
        !           670: static int convert (iconv_t cd, FILE* infile, const char* infilename)
        !           671: {
        !           672:   char inbuf[4096+4096];
        !           673:   size_t inbufrest = 0;
        !           674:   char initial_outbuf[4096];
        !           675:   char *outbuf = initial_outbuf;
        !           676:   size_t outbufsize = sizeof(initial_outbuf);
        !           677:   int status = 0;
        !           678: 
        !           679: #if O_BINARY
        !           680:   SET_BINARY(fileno(infile));
        !           681: #endif
        !           682:   line = 1; column = 0;
        !           683:   iconv(cd,NULL,NULL,NULL,NULL);
        !           684:   for (;;) {
        !           685:     size_t inbufsize = fread(inbuf+4096,1,4096,infile);
        !           686:     if (inbufsize == 0) {
        !           687:       if (inbufrest == 0)
        !           688:         break;
        !           689:       else {
        !           690:         if (ilseq_byte_subst != NULL)
        !           691:           subst_mb_to_mb_fallback(inbuf+4096-inbufrest, inbufrest);
        !           692:         if (!silent)
        !           693:           conversion_error_EINVAL(infilename);
        !           694:         status = 1;
        !           695:         goto done;
        !           696:       }
        !           697:     } else {
        !           698:       const char* inptr = inbuf+4096-inbufrest;
        !           699:       size_t insize = inbufrest+inbufsize;
        !           700:       inbufrest = 0;
        !           701:       while (insize > 0) {
        !           702:         char* outptr = outbuf;
        !           703:         size_t outsize = outbufsize;
        !           704:         size_t res = iconv(cd,(ICONV_CONST char**)&inptr,&insize,&outptr,&outsize);
        !           705:         if (outptr != outbuf) {
        !           706:           int saved_errno = errno;
        !           707:           if (fwrite(outbuf,1,outptr-outbuf,stdout) < outptr-outbuf) {
        !           708:             status = 1;
        !           709:             goto done;
        !           710:           }
        !           711:           errno = saved_errno;
        !           712:         }
        !           713:         if (res == (size_t)(-1)) {
        !           714:           if (errno == EILSEQ) {
        !           715:             if (discard_unconvertible == 1) {
        !           716:               int one = 1;
        !           717:               iconvctl(cd,ICONV_SET_DISCARD_ILSEQ,&one);
        !           718:               discard_unconvertible = 2;
        !           719:               status = 1;
        !           720:             } else {
        !           721:               if (!silent)
        !           722:                 conversion_error_EILSEQ(infilename);
        !           723:               status = 1;
        !           724:               goto done;
        !           725:             }
        !           726:           } else if (errno == EINVAL) {
        !           727:             if (inbufsize == 0 || insize > 4096) {
        !           728:               if (!silent)
        !           729:                 conversion_error_EINVAL(infilename);
        !           730:               status = 1;
        !           731:               goto done;
        !           732:             } else {
        !           733:               inbufrest = insize;
        !           734:               if (insize > 0) {
        !           735:                 /* Like memcpy(inbuf+4096-insize,inptr,insize), except that
        !           736:                    we cannot use memcpy here, because source and destination
        !           737:                    regions may overlap. */
        !           738:                 char* restptr = inbuf+4096-insize;
        !           739:                 do { *restptr++ = *inptr++; } while (--insize > 0);
        !           740:               }
        !           741:               break;
        !           742:             }
        !           743:           } else if (errno == E2BIG) {
        !           744:             if (outptr==outbuf) {
        !           745:               /* outbuf is too small. Double its size. */
        !           746:               if (outbuf != initial_outbuf)
        !           747:                 free(outbuf);
        !           748:               outbufsize = 2*outbufsize;
        !           749:               if (outbufsize==0) /* integer overflow? */
        !           750:                 xalloc_die();
        !           751:               outbuf = (char*)xmalloc(outbufsize);
        !           752:             }
        !           753:           } else {
        !           754:             if (!silent)
        !           755:               conversion_error_other(errno,infilename);
        !           756:             status = 1;
        !           757:             goto done;
        !           758:           }
        !           759:         }
        !           760:       }
        !           761:     }
        !           762:   }
        !           763:   for (;;) {
        !           764:     char* outptr = outbuf;
        !           765:     size_t outsize = outbufsize;
        !           766:     size_t res = iconv(cd,NULL,NULL,&outptr,&outsize);
        !           767:     if (outptr != outbuf) {
        !           768:       int saved_errno = errno;
        !           769:       if (fwrite(outbuf,1,outptr-outbuf,stdout) < outptr-outbuf) {
        !           770:         status = 1;
        !           771:         goto done;
        !           772:       }
        !           773:       errno = saved_errno;
        !           774:     }
        !           775:     if (res == (size_t)(-1)) {
        !           776:       if (errno == EILSEQ) {
        !           777:         if (discard_unconvertible == 1) {
        !           778:           int one = 1;
        !           779:           iconvctl(cd,ICONV_SET_DISCARD_ILSEQ,&one);
        !           780:           discard_unconvertible = 2;
        !           781:           status = 1;
        !           782:         } else {
        !           783:           if (!silent)
        !           784:             conversion_error_EILSEQ(infilename);
        !           785:           status = 1;
        !           786:           goto done;
        !           787:         }
        !           788:       } else if (errno == EINVAL) {
        !           789:         if (!silent)
        !           790:           conversion_error_EINVAL(infilename);
        !           791:         status = 1;
        !           792:         goto done;
        !           793:       } else if (errno == E2BIG) {
        !           794:         if (outptr==outbuf) {
        !           795:           /* outbuf is too small. Double its size. */
        !           796:           if (outbuf != initial_outbuf)
        !           797:             free(outbuf);
        !           798:           outbufsize = 2*outbufsize;
        !           799:           if (outbufsize==0) /* integer overflow? */
        !           800:             xalloc_die();
        !           801:           outbuf = (char*)xmalloc(outbufsize);
        !           802:         }
        !           803:       } else {
        !           804:         if (!silent)
        !           805:           conversion_error_other(errno,infilename);
        !           806:         status = 1;
        !           807:         goto done;
        !           808:       }
        !           809:     } else
        !           810:       break;
        !           811:   }
        !           812:   if (ferror(infile)) {
        !           813:     fflush(stdout);
        !           814:     if (column > 0)
        !           815:       putc('\n',stderr);
        !           816:     error(0,0,
        !           817:           /* TRANSLATORS: An error message.
        !           818:              The placeholder expands to the input file name.  */
        !           819:           _("%s: I/O error"),
        !           820:           infilename);
        !           821:     status = 1;
        !           822:     goto done;
        !           823:   }
        !           824:  done:
        !           825:   if (outbuf != initial_outbuf)
        !           826:     free(outbuf);
        !           827:   return status;
        !           828: }
        !           829: 
        !           830: /* ========================================================================= */
        !           831: 
        !           832: int main (int argc, char* argv[])
        !           833: {
        !           834:   const char* fromcode = NULL;
        !           835:   const char* tocode = NULL;
        !           836:   int do_list = 0;
        !           837:   iconv_t cd;
        !           838:   struct iconv_fallbacks fallbacks;
        !           839:   struct iconv_hooks hooks;
        !           840:   int i;
        !           841:   int status;
        !           842: 
        !           843:   set_program_name (argv[0]);
        !           844: #if HAVE_SETLOCALE
        !           845:   /* Needed for the locale dependent encodings, "char" and "wchar_t",
        !           846:      and for gettext. */
        !           847:   setlocale(LC_CTYPE,"");
        !           848: #if ENABLE_NLS
        !           849:   /* Needed for gettext. */
        !           850:   setlocale(LC_MESSAGES,"");
        !           851: #endif
        !           852: #endif
        !           853: #if ENABLE_NLS
        !           854:   bindtextdomain("libiconv",relocate(LOCALEDIR));
        !           855: #endif
        !           856:   textdomain("libiconv");
        !           857:   for (i = 1; i < argc;) {
        !           858:     size_t len = strlen(argv[i]);
        !           859:     if (!strcmp(argv[i],"--")) {
        !           860:       i++;
        !           861:       break;
        !           862:     }
        !           863:     if (!strcmp(argv[i],"-f")
        !           864:         /* --f ... --from-code */
        !           865:         || (len >= 3 && len <= 11 && !strncmp(argv[i],"--from-code",len))
        !           866:         /* --from-code=... */
        !           867:         || (len >= 12 && !strncmp(argv[i],"--from-code=",12))) {
        !           868:       if (len < 12)
        !           869:         if (i == argc-1) usage(1);
        !           870:       if (fromcode != NULL) usage(1);
        !           871:       if (len < 12) {
        !           872:         fromcode = argv[i+1];
        !           873:         i += 2;
        !           874:       } else {
        !           875:         fromcode = argv[i]+12;
        !           876:         i++;
        !           877:       }
        !           878:       continue;
        !           879:     }
        !           880:     if (!strcmp(argv[i],"-t")
        !           881:         /* --t ... --to-code */
        !           882:         || (len >= 3 && len <= 9 && !strncmp(argv[i],"--to-code",len))
        !           883:         /* --from-code=... */
        !           884:         || (len >= 10 && !strncmp(argv[i],"--to-code=",10))) {
        !           885:       if (len < 10)
        !           886:         if (i == argc-1) usage(1);
        !           887:       if (tocode != NULL) usage(1);
        !           888:       if (len < 10) {
        !           889:         tocode = argv[i+1];
        !           890:         i += 2;
        !           891:       } else {
        !           892:         tocode = argv[i]+10;
        !           893:         i++;
        !           894:       }
        !           895:       continue;
        !           896:     }
        !           897:     if (!strcmp(argv[i],"-l")
        !           898:         /* --l ... --list */
        !           899:         || (len >= 3 && len <= 6 && !strncmp(argv[i],"--list",len))) {
        !           900:       do_list = 1;
        !           901:       i++;
        !           902:       continue;
        !           903:     }
        !           904:     if (/* --by ... --byte-subst */
        !           905:         (len >= 4 && len <= 12 && !strncmp(argv[i],"--byte-subst",len))
        !           906:         /* --byte-subst=... */
        !           907:         || (len >= 13 && !strncmp(argv[i],"--byte-subst=",13))) {
        !           908:       if (len < 13) {
        !           909:         if (i == argc-1) usage(1);
        !           910:         ilseq_byte_subst = argv[i+1];
        !           911:         i += 2;
        !           912:       } else {
        !           913:         ilseq_byte_subst = argv[i]+13;
        !           914:         i++;
        !           915:       }
        !           916:       ilseq_byte_subst_size =
        !           917:         check_subst_formatstring(ilseq_byte_subst, "--byte-subst");
        !           918:       continue;
        !           919:     }
        !           920:     if (/* --w ... --widechar-subst */
        !           921:         (len >= 3 && len <= 16 && !strncmp(argv[i],"--widechar-subst",len))
        !           922:         /* --widechar-subst=... */
        !           923:         || (len >= 17 && !strncmp(argv[i],"--widechar-subst=",17))) {
        !           924:       if (len < 17) {
        !           925:         if (i == argc-1) usage(1);
        !           926:         ilseq_wchar_subst = argv[i+1];
        !           927:         i += 2;
        !           928:       } else {
        !           929:         ilseq_wchar_subst = argv[i]+17;
        !           930:         i++;
        !           931:       }
        !           932:       ilseq_wchar_subst_size =
        !           933:         check_subst_formatstring(ilseq_wchar_subst, "--widechar-subst");
        !           934:       continue;
        !           935:     }
        !           936:     if (/* --u ... --unicode-subst */
        !           937:         (len >= 3 && len <= 15 && !strncmp(argv[i],"--unicode-subst",len))
        !           938:         /* --unicode-subst=... */
        !           939:         || (len >= 16 && !strncmp(argv[i],"--unicode-subst=",16))) {
        !           940:       if (len < 16) {
        !           941:         if (i == argc-1) usage(1);
        !           942:         ilseq_unicode_subst = argv[i+1];
        !           943:         i += 2;
        !           944:       } else {
        !           945:         ilseq_unicode_subst = argv[i]+16;
        !           946:         i++;
        !           947:       }
        !           948:       ilseq_unicode_subst_size =
        !           949:         check_subst_formatstring(ilseq_unicode_subst, "--unicode-subst");
        !           950:       continue;
        !           951:     }
        !           952:     if /* --s ... --silent */
        !           953:        (len >= 3 && len <= 8 && !strncmp(argv[i],"--silent",len)) {
        !           954:       silent = 1;
        !           955:       continue;
        !           956:     }
        !           957:     if /* --h ... --help */
        !           958:        (len >= 3 && len <= 6 && !strncmp(argv[i],"--help",len)) {
        !           959:       usage(0);
        !           960:     }
        !           961:     if /* --v ... --version */
        !           962:        (len >= 3 && len <= 9 && !strncmp(argv[i],"--version",len)) {
        !           963:       print_version();
        !           964:     }
        !           965: #if O_BINARY
        !           966:     /* Backward compatibility with iconv <= 1.9.1. */
        !           967:     if /* --bi ... --binary */
        !           968:        (len >= 4 && len <= 8 && !strncmp(argv[i],"--binary",len)) {
        !           969:       i++;
        !           970:       continue;
        !           971:     }
        !           972: #endif
        !           973:     if (argv[i][0] == '-') {
        !           974:       const char *option = argv[i] + 1;
        !           975:       if (*option == '\0')
        !           976:         usage(1);
        !           977:       for (; *option; option++)
        !           978:         switch (*option) {
        !           979:           case 'c': discard_unconvertible = 1; break;
        !           980:           case 's': silent = 1; break;
        !           981:           default: usage(1);
        !           982:         }
        !           983:       i++;
        !           984:       continue;
        !           985:     }
        !           986:     break;
        !           987:   }
        !           988:   if (do_list) {
        !           989:     if (i != 2 || i != argc)
        !           990:       usage(1);
        !           991:     iconvlist(print_one,NULL);
        !           992:     status = 0;
        !           993:   } else {
        !           994: #if O_BINARY
        !           995:     SET_BINARY(fileno(stdout));
        !           996: #endif
        !           997:     if (fromcode == NULL)
        !           998:       fromcode = "char";
        !           999:     if (tocode == NULL)
        !          1000:       tocode = "char";
        !          1001:     cd = iconv_open(tocode,fromcode);
        !          1002:     if (cd == (iconv_t)(-1)) {
        !          1003:       if (iconv_open("UCS-4",fromcode) == (iconv_t)(-1))
        !          1004:         error(0,0,
        !          1005:               /* TRANSLATORS: An error message.
        !          1006:                  The placeholder expands to the encoding name, specified through --from-code.  */
        !          1007:               _("conversion from %s unsupported"),
        !          1008:               fromcode);
        !          1009:       else if (iconv_open(tocode,"UCS-4") == (iconv_t)(-1))
        !          1010:         error(0,0,
        !          1011:               /* TRANSLATORS: An error message.
        !          1012:                  The placeholder expands to the encoding name, specified through --to-code.  */
        !          1013:               _("conversion to %s unsupported"),
        !          1014:               tocode);
        !          1015:       else
        !          1016:         error(0,0,
        !          1017:               /* TRANSLATORS: An error message.
        !          1018:                  The placeholders expand to the encoding names, specified through --from-code and --to-code, respectively.  */
        !          1019:               _("conversion from %s to %s unsupported"),
        !          1020:               fromcode,tocode);
        !          1021:       error(EXIT_FAILURE,0,
        !          1022:             /* TRANSLATORS: Additional advice after an error message.
        !          1023:                The %s placeholder expands to the program name.  */
        !          1024:             _("try '%s -l' to get the list of supported encodings"),
        !          1025:             program_name);
        !          1026:     }
        !          1027:     /* Look at fromcode and tocode, to determine whether character widths
        !          1028:        should be determined according to legacy CJK conventions. */
        !          1029:     cjkcode = iconv_canonicalize(tocode);
        !          1030:     if (!is_cjk_encoding(cjkcode))
        !          1031:       cjkcode = iconv_canonicalize(fromcode);
        !          1032:     /* Set up fallback routines for handling impossible conversions. */
        !          1033:     if (ilseq_byte_subst != NULL)
        !          1034:       ilseq_byte_subst_buffer = (char*)xmalloc((ilseq_byte_subst_size+1)*sizeof(char));
        !          1035:     if (!discard_unconvertible) {
        !          1036:       #if HAVE_WCHAR_T
        !          1037:       if (ilseq_wchar_subst != NULL)
        !          1038:         ilseq_wchar_subst_buffer = (char*)xmalloc((ilseq_wchar_subst_size+1)*sizeof(char));
        !          1039:       #endif
        !          1040:       if (ilseq_unicode_subst != NULL)
        !          1041:         ilseq_unicode_subst_buffer = (char*)xmalloc((ilseq_unicode_subst_size+1)*sizeof(char));
        !          1042:       if (ilseq_byte_subst != NULL) {
        !          1043:         subst_mb_to_uc_cd = iconv_open("UCS-4-INTERNAL","char");
        !          1044:         subst_mb_to_uc_temp_buffer = (unsigned int*)xmalloc(ilseq_byte_subst_size*sizeof(unsigned int));
        !          1045:         #if HAVE_WCHAR_T
        !          1046:         subst_mb_to_wc_cd = iconv_open("wchar_t","char");
        !          1047:         subst_mb_to_wc_temp_buffer = (wchar_t*)xmalloc(ilseq_byte_subst_size*sizeof(wchar_t));
        !          1048:         #endif
        !          1049:         subst_mb_to_mb_cd = iconv_open(tocode,"char");
        !          1050:         subst_mb_to_mb_temp_buffer = (char*)xmalloc(ilseq_byte_subst_size*4);
        !          1051:       }
        !          1052:       #if HAVE_WCHAR_T
        !          1053:       if (ilseq_wchar_subst != NULL) {
        !          1054:         subst_wc_to_mb_cd = iconv_open(tocode,"char");
        !          1055:         subst_wc_to_mb_temp_buffer = (char*)xmalloc(ilseq_wchar_subst_size*4);
        !          1056:       }
        !          1057:       #endif
        !          1058:       if (ilseq_unicode_subst != NULL) {
        !          1059:         subst_uc_to_mb_cd = iconv_open(tocode,"char");
        !          1060:         subst_uc_to_mb_temp_buffer = (char*)xmalloc(ilseq_unicode_subst_size*4);
        !          1061:       }
        !          1062:       fallbacks.mb_to_uc_fallback =
        !          1063:         (ilseq_byte_subst != NULL ? subst_mb_to_uc_fallback : NULL);
        !          1064:       fallbacks.uc_to_mb_fallback =
        !          1065:         (ilseq_unicode_subst != NULL ? subst_uc_to_mb_fallback : NULL);
        !          1066:       fallbacks.mb_to_wc_fallback =
        !          1067:         (ilseq_byte_subst != NULL ? subst_mb_to_wc_fallback : NULL);
        !          1068:       fallbacks.wc_to_mb_fallback =
        !          1069:         (ilseq_wchar_subst != NULL ? subst_wc_to_mb_fallback : NULL);
        !          1070:       fallbacks.data = NULL;
        !          1071:       iconvctl(cd, ICONV_SET_FALLBACKS, &fallbacks);
        !          1072:     }
        !          1073:     /* Set up hooks for updating the line and column position. */
        !          1074:     hooks.uc_hook = update_line_column;
        !          1075:     hooks.wc_hook = NULL;
        !          1076:     hooks.data = NULL;
        !          1077:     iconvctl(cd, ICONV_SET_HOOKS, &hooks);
        !          1078:     if (i == argc)
        !          1079:       status = convert(cd,stdin,
        !          1080:                        /* TRANSLATORS: A filename substitute denoting standard input.  */
        !          1081:                        _("(stdin)"));
        !          1082:     else {
        !          1083:       status = 0;
        !          1084:       for (; i < argc; i++) {
        !          1085:         const char* infilename = argv[i];
        !          1086:         FILE* infile = fopen(infilename,"r");
        !          1087:         if (infile == NULL) {
        !          1088:           int saved_errno = errno;
        !          1089:           error(0,saved_errno,
        !          1090:                 /* TRANSLATORS: The first part of an error message.
        !          1091:                    It is followed by a colon and a detail message.
        !          1092:                    The %s placeholder expands to the input file name.  */
        !          1093:                 _("%s"),
        !          1094:                 infilename);
        !          1095:           status = 1;
        !          1096:         } else {
        !          1097:           status |= convert(cd,infile,infilename);
        !          1098:           fclose(infile);
        !          1099:         }
        !          1100:       }
        !          1101:     }
        !          1102:     iconv_close(cd);
        !          1103:   }
        !          1104:   if (ferror(stdout) || fclose(stdout)) {
        !          1105:     error(0,0,
        !          1106:           /* TRANSLATORS: An error message.  */
        !          1107:           _("I/O error"));
        !          1108:     status = 1;
        !          1109:   }
        !          1110:   exit(status);
        !          1111: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>