|
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 |
}
|