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