1 /* Copyright (C) 2000-2002 Free Software Foundation, Inc.
2 This file is part of the GNU LIBICONV Library.
4 The GNU LIBICONV Library is free software; you can redistribute it
5 and/or modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 The GNU LIBICONV Library is distributed in the hope that it will be
10 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU LIBICONV Library; see the file COPYING.LIB.
16 If not, write to the Free Software Foundation, Inc., 59 Temple Place -
17 Suite 330, Boston, MA 02111-1307, USA. */
36 #define _(str) gettext(str)
38 /* For systems that distinguish between text and binary I/O.
39 O_BINARY is usually declared in <fcntl.h>. */
40 #if !defined O_BINARY && defined _O_BINARY
41 /* For MSC-compatible compilers. */
42 # define O_BINARY _O_BINARY
43 # define O_TEXT _O_TEXT
46 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
51 # if !(defined(__EMX__) || defined(__DJGPP__))
52 # define setmode _setmode
53 # define fileno _fileno
56 # include <io.h> /* declares setmode() */
57 # include <unistd.h> /* declares isatty() */
58 # /* Avoid putting stdin/stdout in binary mode if it is connected to the
59 # console, because that would make it impossible for the user to
60 # interrupt the program through Ctrl-C or Ctrl-Break. */
61 # define SET_BINARY(fd) (!isatty(fd) ? (setmode(fd,O_BINARY), 0) : 0)
63 # define SET_BINARY(fd) setmode(fd,O_BINARY)
68 static int force_binary = 0;
71 static int discard_unconvertible = 0;
72 static int silent = 0;
74 static void usage (int exitcode)
76 const char* helpstring1 =
78 _("Usage: iconv [--binary] [-c] [-s] [-f fromcode] [-t tocode] [file ...]");
80 _("Usage: iconv [-c] [-s] [-f fromcode] [-t tocode] [file ...]");
82 const char* helpstring2 =
84 fprintf(exitcode ? stderr : stdout, "%s\n%s\n", helpstring1, helpstring2);
88 static void print_version (void)
90 printf("iconv (GNU libiconv %d.%d)\n",
91 _libiconv_version >> 8, _libiconv_version & 0xff);
92 printf("Copyright (C) %s Free Software Foundation, Inc.\n", "2000-2002");
94 This is free software; see the source for copying conditions. There is NO\n\
95 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"));
96 printf(_("Written by %s.\n"),"Bruno Haible");
100 static int print_one (unsigned int namescount, const char * const * names,
105 for (i = 0; i < namescount; i++) {
108 fputs(names[i],stdout);
114 static int convert (iconv_t cd, FILE* infile, const char* infilename)
116 char inbuf[4096+4096];
117 size_t inbufrest = 0;
123 SET_BINARY(fileno(infile));
125 iconv(cd,NULL,NULL,NULL,NULL);
127 size_t inbufsize = fread(inbuf+4096,1,4096,infile);
128 if (inbufsize == 0) {
133 fprintf(stderr,_("iconv: %s: incomplete character or shift sequence\n"),infilename);
137 const char* inptr = inbuf+4096-inbufrest;
138 size_t insize = inbufrest+inbufsize;
141 char* outptr = outbuf;
142 size_t outsize = sizeof(outbuf);
143 size_t res = iconv(cd,(ICONV_CONST char**)&inptr,&insize,&outptr,&outsize);
144 if (outptr != outbuf) {
145 int saved_errno = errno;
146 if (fwrite(outbuf,1,outptr-outbuf,stdout) < outptr-outbuf)
150 if (res == (size_t)(-1)) {
151 if (errno == EILSEQ) {
152 if (discard_unconvertible == 1) {
154 iconvctl(cd,ICONV_SET_DISCARD_ILSEQ,&one);
155 discard_unconvertible = 2;
159 fprintf(stderr,_("iconv: %s: cannot convert\n"),infilename);
162 } else if (errno == EINVAL) {
163 if (inbufsize == 0 || insize > 4096) {
165 fprintf(stderr,_("iconv: %s: incomplete character or shift sequence\n"),infilename);
170 /* Like memcpy(inbuf+4096-insize,inptr,insize), except that
171 we cannot use memcpy here, because source and destination
172 regions may overlap. */
173 char* restptr = inbuf+4096-insize;
174 do { *restptr++ = *inptr++; } while (--insize > 0);
178 } else if (errno != E2BIG) {
180 int saved_errno = errno;
181 fprintf(stderr,_("iconv: %s: "),infilename);
192 char* outptr = outbuf;
193 size_t outsize = sizeof(outbuf);
194 size_t res = iconv(cd,NULL,NULL,&outptr,&outsize);
195 if (outptr != outbuf) {
196 int saved_errno = errno;
197 if (fwrite(outbuf,1,outptr-outbuf,stdout) < outptr-outbuf)
201 if (res == (size_t)(-1)) {
202 if (errno == EILSEQ) {
203 if (discard_unconvertible == 1) {
205 iconvctl(cd,ICONV_SET_DISCARD_ILSEQ,&one);
206 discard_unconvertible = 2;
210 fprintf(stderr,_("iconv: %s: cannot convert\n"),infilename);
213 } else if (errno == EINVAL) {
215 fprintf(stderr,_("iconv: %s: incomplete character or shift sequence\n"),infilename);
219 int saved_errno = errno;
220 fprintf(stderr,_("iconv: %s: "),infilename);
228 if (ferror(infile)) {
229 fprintf(stderr,_("iconv: %s: I/O error\n"),infilename);
235 int main (int argc, char* argv[])
237 const char* fromcode = NULL;
238 const char* tocode = NULL;
245 /* Needed for the locale dependent encodings, "char" and "wchar_t",
247 setlocale(LC_CTYPE,"");
249 /* Needed for gettext. */
250 setlocale(LC_MESSAGES,"");
253 bindtextdomain("libiconv",LOCALEDIR);
254 textdomain("libiconv");
255 for (i = 1; i < argc;) {
256 if (!strcmp(argv[i],"-f")) {
257 if (i == argc-1) usage(1);
258 if (fromcode != NULL) usage(1);
259 fromcode = argv[i+1];
263 if (!strcmp(argv[i],"-t")) {
264 if (i == argc-1) usage(1);
265 if (tocode != NULL) usage(1);
270 if (!strcmp(argv[i],"-l")) {
275 if (!strcmp(argv[i],"--help")) {
278 if (!strcmp(argv[i],"--version")) {
282 if (!strcmp(argv[i],"--binary")) {
288 if (argv[i][0] == '-') {
289 const char *option = argv[i] + 1;
292 for (; *option; option++)
294 case 'c': discard_unconvertible = 1; break;
295 case 's': silent = 1; break;
304 if (i != 2 || i != argc)
306 iconvlist(print_one,NULL);
311 SET_BINARY(fileno(stdout));
313 if (fromcode == NULL)
317 cd = iconv_open(tocode,fromcode);
318 if (cd == (iconv_t)(-1)) {
319 if (iconv_open("UCS-4",fromcode) == (iconv_t)(-1))
320 fprintf(stderr,_("iconv: conversion from %s unsupported\n"),fromcode);
321 else if (iconv_open(tocode,"UCS-4") == (iconv_t)(-1))
322 fprintf(stderr,_("iconv: conversion to %s unsupported\n"),tocode);
324 fprintf(stderr,_("iconv: conversion from %s to %s unsupported\n"),fromcode,tocode);
328 status = convert(cd,stdin,_("(stdin)"));
331 for (; i < argc; i++) {
332 const char* infilename = argv[i];
333 FILE* infile = fopen(infilename,"r");
334 if (infile == NULL) {
335 int saved_errno = errno;
336 fprintf(stderr,_("iconv: %s: "),infilename);
341 status |= convert(cd,infile,infilename);
348 if (ferror(stdout)) {
349 fprintf(stderr,_("iconv: I/O error\n"));