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