aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miscutils/iconv.c120
1 files changed, 34 insertions, 86 deletions
diff --git a/miscutils/iconv.c b/miscutils/iconv.c
index ce0b2087c..0c98ced05 100644
--- a/miscutils/iconv.c
+++ b/miscutils/iconv.c
@@ -54,18 +54,14 @@ typedef unsigned int uint;
54 54
55typedef void* iconv_t; 55typedef void* iconv_t;
56 56
57iconv_t iconv_open(const char *tocode, const char *fromcode); 57static iconv_t iconv_open(const char *tocode, const char *fromcode);
58int iconv_close(iconv_t cd); 58static int iconv_close(iconv_t cd);
59size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); 59static size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
60 60
61typedef struct compat_t compat_t; 61typedef struct compat_t compat_t;
62typedef struct csconv_t csconv_t; 62typedef struct csconv_t csconv_t;
63typedef struct rec_iconv_t rec_iconv_t; 63typedef struct rec_iconv_t rec_iconv_t;
64 64
65typedef iconv_t (*f_iconv_open)(const char *tocode, const char *fromcode);
66typedef int (*f_iconv_close)(iconv_t cd);
67typedef size_t (*f_iconv)(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
68typedef int* (*f_errno)(void);
69typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); 65typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
70typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); 66typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
71typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize); 67typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize);
@@ -94,17 +90,10 @@ struct csconv_t {
94 90
95struct rec_iconv_t { 91struct rec_iconv_t {
96 iconv_t cd; 92 iconv_t cd;
97 f_iconv_close iconv_close;
98 f_iconv iconv;
99 f_errno _errno;
100 csconv_t from; 93 csconv_t from;
101 csconv_t to; 94 csconv_t to;
102}; 95};
103 96
104static int win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode);
105static int win_iconv_close(iconv_t cd);
106static size_t win_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
107
108static int load_mlang(void); 97static int load_mlang(void);
109static int make_csconv(const char *name, csconv_t *cv); 98static int make_csconv(const char *name, csconv_t *cv);
110static int name_to_codepage(const char *name); 99static int name_to_codepage(const char *name);
@@ -697,7 +686,7 @@ load_mlang(void)
697 return TRUE; 686 return TRUE;
698} 687}
699 688
700iconv_t 689static iconv_t
701iconv_open(const char *tocode, const char *fromcode) 690iconv_open(const char *tocode, const char *fromcode)
702{ 691{
703 rec_iconv_t *cd; 692 rec_iconv_t *cd;
@@ -707,54 +696,24 @@ iconv_open(const char *tocode, const char *fromcode)
707 /* reset the errno to prevent reporting wrong error code. 696 /* reset the errno to prevent reporting wrong error code.
708 * 0 for unsorted error. */ 697 * 0 for unsorted error. */
709 errno = 0; 698 errno = 0;
710 if (win_iconv_open(cd, tocode, fromcode)) 699 if (make_csconv(fromcode, &cd->from) && make_csconv(tocode, &cd->to)) {
700 cd->cd = (iconv_t)cd;
711 return (iconv_t)cd; 701 return (iconv_t)cd;
702 }
712 703
713 free(cd); 704 free(cd);
714
715 return (iconv_t)(-1); 705 return (iconv_t)(-1);
716} 706}
717 707
718int
719iconv_close(iconv_t _cd)
720{
721 rec_iconv_t *cd = (rec_iconv_t *)_cd;
722 int r = cd->iconv_close(cd->cd);
723 int e = *(cd->_errno());
724 free(cd);
725 errno = e;
726 return r;
727}
728
729size_t
730iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
731{
732 rec_iconv_t *cd = (rec_iconv_t *)_cd;
733 size_t r = cd->iconv(cd->cd, inbuf, inbytesleft, outbuf, outbytesleft);
734 errno = *(cd->_errno());
735 return r;
736}
737
738static int 708static int
739win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode) 709iconv_close(iconv_t _cd)
740{
741 if (!make_csconv(fromcode, &cd->from) || !make_csconv(tocode, &cd->to))
742 return FALSE;
743 cd->iconv_close = win_iconv_close;
744 cd->iconv = win_iconv;
745 cd->_errno = _errno;
746 cd->cd = (iconv_t)cd;
747 return TRUE;
748}
749
750static int
751win_iconv_close(iconv_t cd UNUSED_PARAM)
752{ 710{
711 free(_cd);
753 return 0; 712 return 0;
754} 713}
755 714
756static size_t 715static size_t
757win_iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) 716iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
758{ 717{
759 rec_iconv_t *cd = (rec_iconv_t *)_cd; 718 rec_iconv_t *cd = (rec_iconv_t *)_cd;
760 ushort wbuf[MB_CHAR_MAX]; /* enough room for one character */ 719 ushort wbuf[MB_CHAR_MAX]; /* enough room for one character */
@@ -1778,53 +1737,41 @@ static void process_file(iconv_t cd, FILE *in, FILE *out)
1778 bb_perror_msg_and_die("conversion error"); 1737 bb_perror_msg_and_die("conversion error");
1779} 1738}
1780 1739
1740enum {
1741 OPT_f = (1 << 0),
1742 OPT_t = (1 << 1),
1743 OPT_l = (1 << 2),
1744 OPT_c = (1 << 3),
1745 OPT_o = (1 << 4),
1746};
1747
1781int iconv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1748int iconv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1782int iconv_main(int argc, char **argv) 1749int iconv_main(int argc, char **argv)
1783{ 1750{
1784 char *fromcode = NULL; 1751 char *fromcode, *tocode, *outfile;
1785 char *tocode = NULL; 1752 int i, opt;
1786 int i;
1787 iconv_t cd; 1753 iconv_t cd;
1788 FILE *in = stdin; 1754 FILE *in = stdin;
1789 FILE *out = stdout; 1755 FILE *out = stdout;
1790 int ignore = 0;
1791 const char *alias;
1792
1793 while ((i = getopt(argc, argv, "f:t:lco:")) != -1) {
1794 switch (i) {
1795 case 'l':
1796 alias = cp_alias;
1797 while (*alias) {
1798 printf("%s\n", alias);
1799 alias += strlen(alias) + 1;
1800 }
1801 return 0;
1802
1803 case 'f':
1804 fromcode = optarg;
1805 break;
1806 1756
1807 case 't': 1757 opt = getopt32(argv, "f:t:lco:", &fromcode, &tocode, &outfile);
1808 tocode = optarg;
1809 break;
1810 1758
1811 case 'c': 1759 if (opt & OPT_l) {
1812 ignore = 1; 1760 const char *alias = cp_alias;
1813 break; 1761 while (*alias) {
1814 1762 printf("%s\n", alias);
1815 case 'o': 1763 alias += strlen(alias) + 1;
1816 out = xfopen(optarg, "wb");
1817 break;
1818
1819 default:
1820 bb_show_usage();
1821 } 1764 }
1765 return 0;
1822 } 1766 }
1823 1767
1824 if (fromcode == NULL || tocode == NULL) 1768 if ((opt & (OPT_f|OPT_t)) != (OPT_f|OPT_t))
1825 bb_show_usage(); 1769 bb_show_usage();
1826 1770
1827 if (ignore) 1771 if (opt & OPT_o)
1772 out = xfopen(outfile, "wb");
1773
1774 if (opt & OPT_c)
1828 tocode = xasprintf("%s//IGNORE", tocode); 1775 tocode = xasprintf("%s//IGNORE", tocode);
1829 1776
1830 cd = iconv_open(tocode, fromcode); 1777 cd = iconv_open(tocode, fromcode);
@@ -1843,6 +1790,7 @@ int iconv_main(int argc, char **argv)
1843 } 1790 }
1844 } 1791 }
1845 1792
1846 iconv_close(cd); 1793 if (ENABLE_FEATURE_CLEAN_UP)
1794 iconv_close(cd);
1847 return 0; 1795 return 0;
1848} 1796}