Update headers and omit CVS Ids.
[yaz-moved-to-github.git] / util / yaziconv.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2008 Index Data
3  * See the file LICENSE for details.
4  */
5
6 #if HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9
10 #include <stdlib.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <ctype.h>
14
15 #include <yaz/yaz-util.h>
16
17 #define CHUNK_IN 64
18 #define CHUNK_OUT 64
19
20 void convert (FILE *inf, yaz_iconv_t cd, int verbose)
21 {
22     char inbuf0[CHUNK_IN], *inbuf = inbuf0;
23     char outbuf0[CHUNK_OUT], *outbuf = outbuf0;
24     size_t inbytesleft = CHUNK_IN;
25     size_t outbytesleft = CHUNK_OUT;
26     int mustread = 1;
27
28     while (1)
29     {
30         size_t r;
31         if (mustread)
32         {
33             r = fread (inbuf, 1, inbytesleft, inf);
34             if (inbytesleft != r)
35             {
36                 if (ferror(inf))
37                 {
38                     fprintf (stderr, "yaziconv: error reading file\n");
39                     exit (6);
40                 }
41                 if (r == 0)
42                 {
43                     if (outbuf != outbuf0)
44                         fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
45                     outbuf = outbuf0;
46                     outbytesleft = CHUNK_OUT;
47                     r = yaz_iconv (cd, 0, 0, &outbuf, &outbytesleft);
48                     if (outbuf != outbuf0)
49                         fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
50                     break;
51                 }
52                 inbytesleft = r;
53             }
54         }
55         if (verbose > 1)
56         {
57             fprintf (stderr, "yaz_iconv: inbytesleft=%ld outbytesleft=%ld\n",
58                      (long) inbytesleft, (long) outbytesleft);
59
60         }
61         r = yaz_iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
62         if (r == (size_t)(-1))
63         {
64             int e = yaz_iconv_error(cd);
65             if (e == YAZ_ICONV_EILSEQ)
66             {
67                 fprintf (stderr, "invalid sequence\n");
68                 return ;
69             }
70             else if (e == YAZ_ICONV_EINVAL) /* incomplete input */
71             { 
72                 size_t i;
73                 for (i = 0; i<inbytesleft; i++)
74                     inbuf0[i] = inbuf[i];
75
76                 r = fread(inbuf0 + i, 1, CHUNK_IN - i, inf);
77                 if (r != CHUNK_IN - i)
78                 {
79                     if (ferror(inf))
80                     {
81                         fprintf (stderr, "yaziconv: error reading file\n");
82                         exit(6);
83                     }
84                 }
85                 if (r == 0)
86                 {
87                     fprintf (stderr, "invalid sequence due to missing input\n");
88                     return ;
89                 }
90                 inbytesleft += r;
91                 inbuf = inbuf0;
92                 mustread = 0;
93             }
94             else if (e == YAZ_ICONV_E2BIG) /* no more output space */
95             {
96                 fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
97                 outbuf = outbuf0;
98                 outbytesleft = CHUNK_OUT;
99                 mustread = 0;
100             }
101             else
102             {
103                 fprintf (stderr, "yaziconv: unknown error\n");
104                 exit (7);
105             }
106         }
107         else
108         {
109             inbuf = inbuf0;
110             inbytesleft = CHUNK_IN;
111
112             fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
113             outbuf = outbuf0;
114             outbytesleft = CHUNK_OUT;
115
116             mustread = 1;
117         }
118     }
119 }
120
121 int main (int argc, char **argv)
122 {
123     int ret;
124     int verbose = 0;
125     char *from = 0;
126     char *to = 0;
127     char *arg;
128     yaz_iconv_t cd;
129     FILE *inf = stdin;
130
131     while ((ret = options ("vf:t:", argv, argc, &arg)) != -2)
132     {
133         switch (ret)
134         {
135         case 0:
136             inf = fopen (arg, "rb");
137             if (!inf)
138             {
139                 fprintf (stderr, "yaziconv: cannot open %s", arg);
140                 exit (2);
141             }
142             break;
143         case 'f':
144             from = arg;
145             break;
146         case 't':
147             to = arg;
148             break;
149         case 'v':
150             verbose++;
151             break;
152         default:
153             fprintf (stderr, "yaziconv: Usage\n"
154                      "yaziconv -f encoding -t encoding [-v] [file]\n");
155             exit(1);
156         }
157     }
158     if (!to)
159     {
160         fprintf (stderr, "yaziconv: -t encoding missing\n");
161         exit (3);
162     }
163     if (!from)
164     {
165         fprintf (stderr, "yaziconv: -f encoding missing\n");
166         exit (4);
167     }
168     cd = yaz_iconv_open (to, from);
169     if (!cd)
170     {
171         fprintf (stderr, "yaziconv: unsupported encoding\n");
172         exit (5);
173     }
174     else
175     {
176         if (verbose)
177         {
178             fprintf (stderr, "yaziconv: using %s\n",
179                      yaz_iconv_isbuiltin(cd) ? "YAZ" : "iconv");
180         }
181     }
182     convert (inf, cd, verbose);
183     yaz_iconv_close (cd);
184     return 0;
185 }
186 /*
187  * Local variables:
188  * c-basic-offset: 4
189  * indent-tabs-mode: nil
190  * End:
191  * vim: shiftwidth=4 tabstop=8 expandtab
192  */
193