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 (at) 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 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 } 155