1 | /**
|
---|
2 | *** iconv_open(), iconv(), iconv_close() wrappers for the OS/400.
|
---|
3 | ***
|
---|
4 | *** See Copyright for the status of this software.
|
---|
5 | ***
|
---|
6 | *** Author: Patrick Monnerat <[email protected]>, DATASPHERE S.A.
|
---|
7 | **/
|
---|
8 |
|
---|
9 | #include <errno.h>
|
---|
10 | #include <stdio.h>
|
---|
11 | #include <stdlib.h>
|
---|
12 |
|
---|
13 | #include "/QIBM/include/iconv.h" /* Force system definition. */
|
---|
14 |
|
---|
15 | #define USE_SYSTEM_ICONV
|
---|
16 | #include "iconv.h" /* Use local definitions. */
|
---|
17 |
|
---|
18 |
|
---|
19 |
|
---|
20 | /**
|
---|
21 | *** Bring-in the name-->CCSID mapping DFA tables.
|
---|
22 | **/
|
---|
23 |
|
---|
24 | #include "ianatables.c"
|
---|
25 |
|
---|
26 |
|
---|
27 |
|
---|
28 | static int
|
---|
29 | findEncoding(const unsigned char * * namep)
|
---|
30 |
|
---|
31 | {
|
---|
32 | t_staterange curstate;
|
---|
33 | t_ccsid ccsid;
|
---|
34 | t_ccsid final;
|
---|
35 | t_transrange l;
|
---|
36 | t_transrange h;
|
---|
37 | const unsigned char * name;
|
---|
38 |
|
---|
39 | /**
|
---|
40 | *** Get the CCSID correspong to the name at *`namep'.
|
---|
41 | *** If success, update pointer at `namep' to 1st byte after matched
|
---|
42 | *** name and return the CCSID.
|
---|
43 | *** If failure, set errno and return -1.
|
---|
44 | **/
|
---|
45 |
|
---|
46 | if (!namep || !(name = *namep)) {
|
---|
47 | errno = EINVAL;
|
---|
48 | return -1;
|
---|
49 | }
|
---|
50 |
|
---|
51 | curstate = 0;
|
---|
52 | final = 0;
|
---|
53 |
|
---|
54 | for (;;) {
|
---|
55 | if (curstate < sizeof final_array / sizeof final_array[0])
|
---|
56 | if (final_array[curstate]) {
|
---|
57 | final = final_array[curstate];
|
---|
58 | *namep = name;
|
---|
59 | }
|
---|
60 |
|
---|
61 | l = trans_array[curstate] - 1;
|
---|
62 | h = trans_array[curstate + 1];
|
---|
63 |
|
---|
64 | do {
|
---|
65 | if (++l >= h) {
|
---|
66 | if (!final) {
|
---|
67 | errno = EINVAL;
|
---|
68 | return -1;
|
---|
69 | }
|
---|
70 |
|
---|
71 | return final - 1;
|
---|
72 | }
|
---|
73 | } while (label_array[l] != *name);
|
---|
74 |
|
---|
75 | curstate = goto_array[l];
|
---|
76 | name++;
|
---|
77 | }
|
---|
78 |
|
---|
79 | /* NOTREACHED. */
|
---|
80 | }
|
---|
81 |
|
---|
82 |
|
---|
83 | static void
|
---|
84 | makeos400codename(char * buf, unsigned int ccsid)
|
---|
85 |
|
---|
86 | {
|
---|
87 | ccsid &= 0xFFFF;
|
---|
88 | memset(buf, 0, 32);
|
---|
89 | sprintf(buf, "IBMCCSID%05u0000000", ccsid);
|
---|
90 | }
|
---|
91 |
|
---|
92 |
|
---|
93 | Iconv_t
|
---|
94 | IconvOpen(const char * tocode, const char * fromcode)
|
---|
95 |
|
---|
96 | {
|
---|
97 | int toccsid = findEncoding(&tocode);
|
---|
98 | int fromccsid = findEncoding(&fromcode);
|
---|
99 | char fromibmccsid[33];
|
---|
100 | char toibmccsid[33];
|
---|
101 | iconv_t * cd;
|
---|
102 |
|
---|
103 | if (toccsid < 0 || fromccsid < 0)
|
---|
104 | return (Iconv_t) -1;
|
---|
105 |
|
---|
106 | makeos400codename(fromibmccsid, fromccsid);
|
---|
107 | makeos400codename(toibmccsid, toccsid);
|
---|
108 | memset(toibmccsid + 13, 0, sizeof toibmccsid - 13);
|
---|
109 |
|
---|
110 | cd = (iconv_t *) malloc(sizeof *cd);
|
---|
111 |
|
---|
112 | if (!cd)
|
---|
113 | return (Iconv_t) -1;
|
---|
114 |
|
---|
115 | *cd = iconv_open(toibmccsid, fromibmccsid);
|
---|
116 |
|
---|
117 | if (cd->return_value) {
|
---|
118 | free((char *) cd);
|
---|
119 | return (Iconv_t) -1;
|
---|
120 | }
|
---|
121 |
|
---|
122 | return (Iconv_t) cd;
|
---|
123 | }
|
---|
124 |
|
---|
125 |
|
---|
126 | size_t
|
---|
127 | Iconv(Iconv_t cd, char * * inbuf, size_t * inbytesleft,
|
---|
128 | char * * outbuf, size_t * outbytesleft)
|
---|
129 |
|
---|
130 | {
|
---|
131 | if (!cd || cd == (Iconv_t) -1) {
|
---|
132 | errno = EINVAL;
|
---|
133 | return (size_t) -1;
|
---|
134 | }
|
---|
135 |
|
---|
136 | return iconv(*(iconv_t *) cd, inbuf, inbytesleft, outbuf, outbytesleft);
|
---|
137 | }
|
---|
138 |
|
---|
139 |
|
---|
140 | int
|
---|
141 | IconvClose(Iconv_t cd)
|
---|
142 |
|
---|
143 | {
|
---|
144 | if (!cd || cd == (Iconv_t) -1) {
|
---|
145 | errno = EINVAL;
|
---|
146 | return -1;
|
---|
147 | }
|
---|
148 |
|
---|
149 | if (iconv_close(*(iconv_t *) cd))
|
---|
150 | return -1;
|
---|
151 |
|
---|
152 | free((char *) cd);
|
---|
153 | return 0;
|
---|
154 | }
|
---|