• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <pm@datasphere.ch>, 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
findEncoding(const unsigned char ** namep)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
makeos400codename(char * buf,unsigned int ccsid)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
IconvOpen(const char * tocode,const char * fromcode)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
Iconv(Iconv_t cd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)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
IconvClose(Iconv_t cd)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 }
155