Skip to content

Commit f941ebe

Browse files
committed
Implement iconv(3) wrapper
1 parent d09181e commit f941ebe

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

Makefile

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,20 @@
33
#TARG = iconv.a
44
OFILES = iconv.o
55

6+
# uncomment if you want to use iconv_wrapped
7+
#OFILES += iconv_wrapped.o
8+
69
all: $(OFILES)
710
iconv.c: _cp932tab.c
811
_cp932tab.c: cp932tab.awk CP932.TXT
912
awk -f cp932tab.awk -F' ' CP932.TXT > $@
1013

14+
iconv_wrapped.c: _iconv_wrapped.c
15+
_iconv_wrapped.c: iconv.c
16+
sed -e 's/^#include "iconv.h"//' \
17+
-e 's/iconv_t/struct sjconv_state */g' \
18+
-e 's/^iconv/sjc_&/' \
19+
-e 's/struct sjconv_state/struct sjc_sjconv_state/' $< > $@
20+
1121
clean:
12-
rm -f $(TARG) $(OFILES) _cp932tab.c
22+
rm -f $(TARG) $(OFILES) _cp932tab.c _iconv_wrapped.c

iconv_wrapped.c

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <stdbool.h>
2+
3+
#include <iconv.h>
4+
5+
#include "_iconv_wrapped.c"
6+
7+
/* iconv_wrapped.c - wrapper around system iconv(3) calls
8+
*
9+
* Use this if you want to add cp932 support to your existing iconv(3)
10+
* implementation.
11+
*
12+
* To be able to use this, your linker needs to support the --wrap option.
13+
* Example usage (gcc):
14+
* gcc someprogramobj1.o someprogramobj2.o iconv_wrapped.o \
15+
* -Wl,--wrap=iconv -Wl,--wrap=iconv_open -Wl,--wrap=iconv_close \
16+
* -o someprogram
17+
*/
18+
19+
size_t __real_iconv(iconv_t cd, char **restrict inbuf, size_t *restrict inleft, char **restrict outbuf, size_t *restrict outleft);
20+
iconv_t __real_iconv_open(const char *to, const char *from);
21+
int __real_iconv_close(iconv_t cd);
22+
23+
struct sjconv_state {
24+
union {
25+
struct sjc_sjconv_state *sjc;
26+
iconv_t real;
27+
} cd;
28+
bool is_sjconv;
29+
};
30+
31+
size_t
32+
__wrap_iconv(struct sjconv_state *s, char **restrict inbuf, size_t *restrict inleft, char **restrict outbuf, size_t *restrict outleft)
33+
{
34+
if(s->is_sjconv)
35+
return sjc_iconv(s->cd.sjc, inbuf, inleft, outbuf, outleft);
36+
else
37+
return __real_iconv(s->cd.real, inbuf, inleft, outbuf, outleft);
38+
}
39+
40+
iconv_t
41+
__wrap_iconv_open(const char *to, const char *from)
42+
{
43+
44+
struct sjconv_state *s = malloc(sizeof *s);
45+
iconv_t cd = __real_iconv_open(to, from);
46+
if(cd != (iconv_t)-1) {
47+
s->is_sjconv = false;
48+
s->cd.real = cd;
49+
return s;
50+
}
51+
52+
/* TODO: try converting to utf-8 and then to the target encoding for wider support? */
53+
struct sjc_sjconv_state *scd = sjc_iconv_open(to, from);
54+
if(scd != (struct sjc_sjconv_state *)-1) {
55+
s->is_sjconv = true;
56+
s->cd.sjc = scd;
57+
return s;
58+
}
59+
60+
free(s);
61+
return (iconv_t)-1;
62+
}
63+
64+
int
65+
__wrap_iconv_close(struct sjconv_state *s)
66+
{
67+
int ret;
68+
if(s->is_sjconv) {
69+
if((ret = sjc_iconv_close(s->cd.sjc)) != 0)
70+
return ret;
71+
} else {
72+
if((ret = __real_iconv_close(s->cd.real)) != 0)
73+
return ret;
74+
}
75+
76+
free(s);
77+
return 0;
78+
}

0 commit comments

Comments
 (0)