diff options
-rw-r--r-- | miscutils/iconv.c | 120 |
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 | ||
55 | typedef void* iconv_t; | 55 | typedef void* iconv_t; |
56 | 56 | ||
57 | iconv_t iconv_open(const char *tocode, const char *fromcode); | 57 | static iconv_t iconv_open(const char *tocode, const char *fromcode); |
58 | int iconv_close(iconv_t cd); | 58 | static int iconv_close(iconv_t cd); |
59 | size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); | 59 | static size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); |
60 | 60 | ||
61 | typedef struct compat_t compat_t; | 61 | typedef struct compat_t compat_t; |
62 | typedef struct csconv_t csconv_t; | 62 | typedef struct csconv_t csconv_t; |
63 | typedef struct rec_iconv_t rec_iconv_t; | 63 | typedef struct rec_iconv_t rec_iconv_t; |
64 | 64 | ||
65 | typedef iconv_t (*f_iconv_open)(const char *tocode, const char *fromcode); | ||
66 | typedef int (*f_iconv_close)(iconv_t cd); | ||
67 | typedef size_t (*f_iconv)(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); | ||
68 | typedef int* (*f_errno)(void); | ||
69 | typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); | 65 | typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); |
70 | typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); | 66 | typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); |
71 | typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize); | 67 | typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize); |
@@ -94,17 +90,10 @@ struct csconv_t { | |||
94 | 90 | ||
95 | struct rec_iconv_t { | 91 | struct 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 | ||
104 | static int win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode); | ||
105 | static int win_iconv_close(iconv_t cd); | ||
106 | static size_t win_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); | ||
107 | |||
108 | static int load_mlang(void); | 97 | static int load_mlang(void); |
109 | static int make_csconv(const char *name, csconv_t *cv); | 98 | static int make_csconv(const char *name, csconv_t *cv); |
110 | static int name_to_codepage(const char *name); | 99 | static int name_to_codepage(const char *name); |
@@ -697,7 +686,7 @@ load_mlang(void) | |||
697 | return TRUE; | 686 | return TRUE; |
698 | } | 687 | } |
699 | 688 | ||
700 | iconv_t | 689 | static iconv_t |
701 | iconv_open(const char *tocode, const char *fromcode) | 690 | iconv_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 | ||
718 | int | ||
719 | iconv_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 | |||
729 | size_t | ||
730 | iconv(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 | |||
738 | static int | 708 | static int |
739 | win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode) | 709 | iconv_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 | |||
750 | static int | ||
751 | win_iconv_close(iconv_t cd UNUSED_PARAM) | ||
752 | { | 710 | { |
711 | free(_cd); | ||
753 | return 0; | 712 | return 0; |
754 | } | 713 | } |
755 | 714 | ||
756 | static size_t | 715 | static size_t |
757 | win_iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) | 716 | iconv(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 | ||
1740 | enum { | ||
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 | |||
1781 | int iconv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1748 | int iconv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1782 | int iconv_main(int argc, char **argv) | 1749 | int 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 | } |