iconv.c
Upload User: yingmei828
Upload Date: 2007-01-01
Package Size: 1646k
Code Size: 6k
Development Platform:

Unix_Linux

  1. /* Copyright (C) 2000 Free Software Foundation, Inc.
  2.    This file is part of the GNU ICONV Library.
  3.    The GNU ICONV Library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public License as
  5.    published by the Free Software Foundation; either version 2 of the
  6.    License, or (at your option) any later version.
  7.    The GNU ICONV Library is distributed in the hope that it will be useful,
  8.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10.    Library General Public License for more details.
  11.    You should have received a copy of the GNU Library General Public
  12.    License along with the GNU ICONV Library; see the file COPYING.LIB.  If not,
  13.    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14.    Boston, MA 02111-1307, USA.  */
  15. #include <stddef.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <iconv.h>
  20. #include <errno.h>
  21. static void usage ()
  22. {
  23.   fprintf(stderr,"Usage: iconv -f fromcode -t tocode [file ...]n");
  24.   exit(1);
  25. }
  26. static int convert (iconv_t cd, FILE* infile, const char* infilename)
  27. {
  28.   char inbuf[4096+4096];
  29.   size_t inbufrest = 0;
  30.   char outbuf[4096];
  31.   iconv(cd,NULL,NULL,NULL,NULL);
  32.   for (;;) {
  33.     size_t inbufsize = fread(inbuf+4096,1,4096,infile);
  34.     if (inbufsize == 0) {
  35.       if (inbufrest == 0)
  36.         break;
  37.       else {
  38.         fprintf(stderr,"iconv: %s: incomplete character or shift sequencen",infilename);
  39.         return 1;
  40.       }
  41.     } else {
  42.       const char* inptr = inbuf+4096-inbufrest;
  43.       size_t insize = inbufrest+inbufsize;
  44.       inbufrest = 0;
  45.       while (insize > 0) {
  46.         char* outptr = outbuf;
  47.         size_t outsize = sizeof(outbuf);
  48.         size_t res = iconv(cd,&inptr,&insize,&outptr,&outsize);
  49.         if (outptr != outbuf) {
  50.           int saved_errno = errno;
  51.           if (fwrite(outbuf,1,outptr-outbuf,stdout) < outptr-outbuf)
  52.             return 1;
  53.           errno = saved_errno;
  54.         }
  55.         if (res == (size_t)(-1)) {
  56.           if (errno == EILSEQ) {
  57.             fprintf(stderr,"iconv: %s: cannot convertn",infilename);
  58.             return 1;
  59.           } else if (errno == EINVAL) {
  60.             if (inbufsize == 0 || insize > 4096) {
  61.               fprintf(stderr,"iconv: %s: incomplete character or shift sequencen",infilename);
  62.               return 1;
  63.             } else {
  64.               inbufrest = insize;
  65.               if (insize > 0) {
  66.                 /* Like memcpy(inbuf+4096-insize,inptr,insize), except that
  67.                    we cannot use memcpy here, because source and destination
  68.                    regions may overlap. */
  69.                 char* restptr = inbuf+4096-insize;
  70.                 do { *restptr++ = *inptr++; } while (--insize > 0);
  71.               }
  72.               break;
  73.             }
  74.           } else if (errno != E2BIG) {
  75.             int saved_errno = errno;
  76.             fprintf(stderr,"iconv: %s: ",infilename);
  77.             errno = saved_errno;
  78.             perror("");
  79.             return 1;
  80.           }
  81.         }
  82.       }
  83.     }
  84.   }
  85.   {
  86.     char* outptr = outbuf;
  87.     size_t outsize = sizeof(outbuf);
  88.     size_t res = iconv(cd,NULL,NULL,&outptr,&outsize);
  89.     if (outptr != outbuf) {
  90.       int saved_errno = errno;
  91.       if (fwrite(outbuf,1,outptr-outbuf,stdout) < outptr-outbuf)
  92.         return 1;
  93.       errno = saved_errno;
  94.     }
  95.     if (res == (size_t)(-1)) {
  96.       if (errno == EILSEQ) {
  97.         fprintf(stderr,"iconv: %s: cannot convertn",infilename);
  98.         return 1;
  99.       } else if (errno == EINVAL) {
  100.         fprintf(stderr,"iconv: %s: incomplete character or shift sequencen",infilename);
  101.         return 1;
  102.       } else {
  103.         int saved_errno = errno;
  104.         fprintf(stderr,"iconv: %s: ",infilename);
  105.         errno = saved_errno;
  106.         perror("");
  107.         return 1;
  108.       }
  109.     }
  110.   }
  111.   if (ferror(infile)) {
  112.     fprintf(stderr,"iconv: %s: I/O errorn",infilename);
  113.     return 1;
  114.   }
  115.   return 0;
  116. }
  117. int main (int argc, char* argv[])
  118. {
  119.   const char* fromcode = NULL;
  120.   const char* tocode = NULL;
  121.   iconv_t cd;
  122.   int i;
  123.   int status;
  124.   for (i = 1; i < argc;) {
  125.     if (!strcmp(argv[i],"-f")) {
  126.       if (i == argc-1) usage();
  127.       if (fromcode != NULL) usage();
  128.       fromcode = argv[i+1];
  129.       i += 2;
  130.       continue;
  131.     }
  132.     if (!strcmp(argv[i],"-t")) {
  133.       if (i == argc-1) usage();
  134.       if (tocode != NULL) usage();
  135.       tocode = argv[i+1];
  136.       i += 2;
  137.       continue;
  138.     }
  139.     if (argv[i][0] == '-')
  140.       usage();
  141.     break;
  142.   }
  143.   if (fromcode == NULL || tocode == NULL)
  144.     usage();
  145.   cd = iconv_open(tocode,fromcode);
  146.   if (cd == (iconv_t)(-1)) {
  147.     if (iconv_open("UCS-4",fromcode) == (iconv_t)(-1))
  148.       fprintf(stderr,"iconv: conversion from %s unsupportedn",fromcode);
  149.     else if (iconv_open(tocode,"UCS-4") == (iconv_t)(-1))
  150.       fprintf(stderr,"iconv: conversion to %s unsupportedn",tocode);
  151.     else
  152.       fprintf(stderr,"iconv: conversion from %s to %s unsupportedn",fromcode,tocode);
  153.     exit(1);
  154.   }
  155.   if (i == argc)
  156.     status = convert(cd,stdin,"(stdin)");
  157.   else {
  158.     status = 0;
  159.     for (; i < argc; i++) {
  160.       const char* infilename = argv[i];
  161.       FILE* infile = fopen(infilename,"r");
  162.       if (infile == NULL) {
  163.         int saved_errno = errno;
  164.         fprintf(stderr,"iconv: %s: ",infilename);
  165.         errno = saved_errno;
  166.         perror("");
  167.         status = 1;
  168.       } else {
  169.         status |= convert(cd,infile,infilename);
  170.         fclose(infile);
  171.       }
  172.     }
  173.   }
  174.   iconv_close(cd);
  175.   if (ferror(stdout)) {
  176.     fprintf(stderr,"iconv: I/O errorn");
  177.     status = 1;
  178.   }
  179.   exit(status);
  180. }