alicelinux

A lightweight musl + clang/llvm + libressl + busybox distro
git clone https://codeberg.org/emmett1/alicelinux
Log | Files | Refs | README | LICENSE

iconv.c (2577B)


      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  */
      7 
      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>
     16 
     17 int main(int argc, char **argv)
     18 {
     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;
     30 
     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);
     41 	}
     42 
     43 	if (!from || !to) {
     44 		setlocale(LC_CTYPE, "");
     45 		if (!to) to = nl_langinfo(CODESET);
     46 		if (!from) from = nl_langinfo(CODESET);
     47 	}
     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);
     56 	}
     57 	if (optind == argc) argv[argc++] = "-";
     58 
     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;
     68 		}
     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;
     91 					}
     92 				}
     93 				inb-=unitsize;
     94 				in+=unitsize;
     95 			}
     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);
    100 			}
    101 			if (inb) memmove(buf, in, inb);
    102 		}
    103 		if (ferror(f)) {
    104 			fprintf(stderr, "iconv: %s: ", argv[optind]);
    105 			perror("");
    106 			err = 1;
    107 		}
    108 	}
    109 	return err;
    110 }