Home | History | Annotate | Download | only in iconv
      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