qi: publish new version (1.0-rc59). Final RC version
[dragora.git] / archive / musl / iconv.c
blobf5d5ce2aa730461df126cdf8bc8b084b4ebb881c
1 /*
2 * iconv.c
3 * Implementation of SUSv4 XCU iconv utility
4 * Copyright © 2011 Rich Felker
5 * Licensed under the terms of the GNU General Public License, v2 or later
6 */
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <iconv.h>
11 #include <locale.h>
12 #include <langinfo.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <string.h>
17 int main(int argc, char **argv)
19 const char *from=0, *to=0;
20 int b;
21 iconv_t cd;
22 char buf[BUFSIZ];
23 char outbuf[BUFSIZ*4];
24 char *in, *out;
25 size_t inb;
26 size_t l;
27 size_t unitsize=0;
28 int err=0;
29 FILE *f;
31 while ((b = getopt(argc, argv, "f:t:csl")) != EOF) switch(b) {
32 case 'l':
33 puts("UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF32-LE, UCS-2BE, UCS-2LE, WCHAR_T,\n"
34 "US_ASCII, ISO8859-1, ISO8859-2, ISO8859-3, ISO8859-4, ISO8859-5,\n"
35 "ISO8859-6, ISO8859-7, ...");
36 exit(0);
37 case 'c': case 's': break;
38 case 'f': from=optarg; break;
39 case 't': to=optarg; break;
40 default: exit(1);
43 if (!from || !to) {
44 setlocale(LC_CTYPE, "");
45 if (!to) to = nl_langinfo(CODESET);
46 if (!from) from = nl_langinfo(CODESET);
48 cd = iconv_open(to, from);
49 if (cd == (iconv_t)-1) {
50 if (iconv_open(to, "WCHAR_T") == (iconv_t)-1)
51 fprintf(stderr, "iconv: destination charset %s: ", to);
52 else
53 fprintf(stderr, "iconv: source charset %s: ", from);
54 perror("");
55 exit(1);
57 if (optind == argc) argv[argc++] = "-";
59 for (; optind < argc; optind++) {
60 if (argv[optind][0]=='-' && !argv[optind][1]) {
61 f = stdin;
62 argv[optind] = "(stdin)";
63 } else if (!(f = fopen(argv[optind], "rb"))) {
64 fprintf(stderr, "iconv: %s: ", argv[optind]);
65 perror("");
66 err = 1;
67 continue;
69 inb = 0;
70 for (;;) {
71 in = buf;
72 out = outbuf;
73 l = fread(buf+inb, 1, sizeof(buf)-inb, f);
74 inb += l;
75 if (!inb) break;
76 if (iconv(cd, &in, &inb, &out, (size_t [1]){sizeof outbuf})==-1
77 && errno == EILSEQ) {
78 if (!unitsize) {
79 wchar_t wc='0';
80 char dummy[4], *dummyp=dummy;
81 iconv_t cd2 = iconv_open(from, "WCHAR_T");
82 if (cd == (iconv_t)-1) {
83 unitsize = 1;
84 } else {
85 iconv(cd2,
86 (char *[1]){(char *)&wc},
87 (size_t[1]){1},
88 &dummyp, (size_t[1]){4});
89 unitsize = dummyp-dummy;
90 if (!unitsize) unitsize=1;
93 inb-=unitsize;
94 in+=unitsize;
96 if (inb && !l && errno==EINVAL) break;
97 if (out>outbuf && !fwrite(outbuf, out-outbuf, 1, stdout)) {
98 perror("iconv: write error");
99 exit(1);
101 if (inb) memmove(buf, in, inb);
103 if (ferror(f)) {
104 fprintf(stderr, "iconv: %s: ", argv[optind]);
105 perror("");
106 err = 1;
109 return err;