Blame os400/iconv/iconv.c

Packit 423ecb
/**
Packit 423ecb
***     iconv_open(), iconv(), iconv_close() wrappers for the OS/400.
Packit 423ecb
***
Packit 423ecb
***     See Copyright for the status of this software.
Packit 423ecb
***
Packit 423ecb
***     Author: Patrick Monnerat <pm@datasphere.ch>, DATASPHERE S.A.
Packit 423ecb
**/
Packit 423ecb
Packit 423ecb
#include <errno.h>
Packit 423ecb
#include <stdio.h>
Packit 423ecb
#include <stdlib.h>
Packit 423ecb
Packit 423ecb
#include "/QIBM/include/iconv.h"        /* Force system definition. */
Packit 423ecb
Packit 423ecb
#define USE_SYSTEM_ICONV
Packit 423ecb
#include "iconv.h"                      /* Use local definitions. */
Packit 423ecb
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
***     Bring-in the name-->CCSID mapping DFA tables.
Packit 423ecb
**/
Packit 423ecb
Packit 423ecb
#include "ianatables.c"
Packit 423ecb
Packit 423ecb
Packit 423ecb
Packit 423ecb
static int
Packit 423ecb
findEncoding(const unsigned char * * namep)
Packit 423ecb
Packit 423ecb
{
Packit 423ecb
        t_staterange curstate;
Packit 423ecb
        t_ccsid ccsid;
Packit 423ecb
        t_ccsid final;
Packit 423ecb
        t_transrange l;
Packit 423ecb
        t_transrange h;
Packit 423ecb
        const unsigned char * name;
Packit 423ecb
Packit 423ecb
        /**
Packit 423ecb
        ***     Get the CCSID correspong to the name at *`namep'.
Packit 423ecb
        ***     If success, update pointer at `namep' to 1st byte after matched
Packit 423ecb
        ***             name and return the CCSID.
Packit 423ecb
        ***     If failure, set errno and return -1.
Packit 423ecb
        **/
Packit 423ecb
Packit 423ecb
        if (!namep || !(name = *namep)) {
Packit 423ecb
                errno = EINVAL;
Packit 423ecb
                return -1;
Packit 423ecb
                }
Packit 423ecb
Packit 423ecb
        curstate = 0;
Packit 423ecb
        final = 0;
Packit 423ecb
Packit 423ecb
        for (;;) {
Packit 423ecb
                if (curstate < sizeof final_array / sizeof final_array[0])
Packit 423ecb
                        if (final_array[curstate]) {
Packit 423ecb
                                final = final_array[curstate];
Packit 423ecb
                                *namep = name;
Packit 423ecb
                                }
Packit 423ecb
Packit 423ecb
                l = trans_array[curstate] - 1;
Packit 423ecb
                h = trans_array[curstate + 1];
Packit 423ecb
Packit 423ecb
                do {
Packit 423ecb
                        if (++l >= h) {
Packit 423ecb
                                if (!final) {
Packit 423ecb
                                        errno = EINVAL;
Packit 423ecb
                                        return -1;
Packit 423ecb
                                        }
Packit 423ecb
Packit 423ecb
                                return final - 1;
Packit 423ecb
                                }
Packit 423ecb
                } while (label_array[l] != *name);
Packit 423ecb
Packit 423ecb
                curstate = goto_array[l];
Packit 423ecb
                name++;
Packit 423ecb
                }
Packit 423ecb
Packit 423ecb
        /* NOTREACHED. */
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
static void
Packit 423ecb
makeos400codename(char * buf, unsigned int ccsid)
Packit 423ecb
Packit 423ecb
{
Packit 423ecb
        ccsid &= 0xFFFF;
Packit 423ecb
        memset(buf, 0, 32);
Packit 423ecb
        sprintf(buf, "IBMCCSID%05u0000000", ccsid);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
Iconv_t
Packit 423ecb
IconvOpen(const char * tocode, const char * fromcode)
Packit 423ecb
Packit 423ecb
{
Packit 423ecb
        int toccsid = findEncoding(&tocode);
Packit 423ecb
        int fromccsid = findEncoding(&fromcode);
Packit 423ecb
        char fromibmccsid[33];
Packit 423ecb
        char toibmccsid[33];
Packit 423ecb
        iconv_t * cd;
Packit 423ecb
Packit 423ecb
        if (toccsid < 0 || fromccsid < 0)
Packit 423ecb
                return (Iconv_t) -1;
Packit 423ecb
Packit 423ecb
        makeos400codename(fromibmccsid, fromccsid);
Packit 423ecb
        makeos400codename(toibmccsid, toccsid);
Packit 423ecb
        memset(toibmccsid + 13, 0, sizeof toibmccsid - 13);
Packit 423ecb
Packit 423ecb
        cd = (iconv_t *) malloc(sizeof *cd);
Packit 423ecb
Packit 423ecb
        if (!cd)
Packit 423ecb
                return (Iconv_t) -1;
Packit 423ecb
Packit 423ecb
        *cd = iconv_open(toibmccsid, fromibmccsid);
Packit 423ecb
Packit 423ecb
        if (cd->return_value) {
Packit 423ecb
                free((char *) cd);
Packit 423ecb
                return (Iconv_t) -1;
Packit 423ecb
                }
Packit 423ecb
Packit 423ecb
        return (Iconv_t) cd;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
size_t
Packit 423ecb
Iconv(Iconv_t cd, char * * inbuf, size_t * inbytesleft,
Packit 423ecb
                                        char * * outbuf, size_t * outbytesleft)
Packit 423ecb
Packit 423ecb
{
Packit 423ecb
        if (!cd || cd == (Iconv_t) -1) {
Packit 423ecb
                errno = EINVAL;
Packit 423ecb
                return (size_t) -1;
Packit 423ecb
                }
Packit 423ecb
Packit 423ecb
        return iconv(*(iconv_t *) cd, inbuf, inbytesleft, outbuf, outbytesleft);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
IconvClose(Iconv_t cd)
Packit 423ecb
Packit 423ecb
{
Packit 423ecb
        if (!cd || cd == (Iconv_t) -1) {
Packit 423ecb
                errno = EINVAL;
Packit 423ecb
                return -1;
Packit 423ecb
                }
Packit 423ecb
Packit 423ecb
        if (iconv_close(*(iconv_t *) cd))
Packit 423ecb
                return -1;
Packit 423ecb
Packit 423ecb
        free((char *) cd);
Packit 423ecb
        return 0;
Packit 423ecb
}