(root)/
libxml2-2.12.3/
os400/
iconv/
iconv.c
       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
      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  }