#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <euc.h>
#include "japanese.h"
#include "jfp_iconv_unicode.h"
#ifdef RFC1468_MODE
#define JFP_J2U_ICONV_RFC1468
#else
#define JFP_J2U_ICONV
#endif
#include "jfp_jis_to_ucs2.h"
struct _icv_state {
int _st_cset;
int _st_cset_sav;
};
void *
_icv_open()
{
struct _icv_state *st;
if ((st = (struct _icv_state *)malloc(sizeof (struct _icv_state)))
== NULL)
return ((void *)ERR_RETURN);
st->_st_cset_sav = st->_st_cset = CS_0;
return (st);
}
void
_icv_close(struct _icv_state *st)
{
free(st);
}
size_t
_icv_iconv(struct _icv_state *st, char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int cset, stat, ret_val;
char *ip, ic;
size_t ileft;
size_t retval;
char *op;
size_t oleft;
unsigned int index = 0;
if ((inbuf == NULL) || (*inbuf == NULL)) {
st->_st_cset_sav = st->_st_cset = CS_0;
return ((size_t)0);
}
cset = st->_st_cset;
stat = ST_INIT;
ip = *inbuf;
op = *outbuf;
ileft = *inbytesleft;
oleft = *outbytesleft;
while ((int)ileft > 0) {
GET(ic);
if (stat == ST_ESC) {
if (ic == MBTOG0_1) {
if ((int)ileft > 0) {
stat = ST_MBTOG0_1;
continue;
} else {
UNGET();
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (ic == SBTOG0_1) {
if ((int)ileft > 0) {
stat = ST_SBTOG0;
continue;
} else {
UNGET();
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (ic == X208REV_1) {
if ((int)ileft > 0) {
stat = ST_208REV_1;
continue;
} else {
UNGET();
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else {
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (stat == ST_MBTOG0_1) {
if ((ic == F_X0208_83_90) || (ic == F_X0208_78)) {
stat = ST_INIT;
st->_st_cset_sav = cset = CS_1;
continue;
} else if (ic == MBTOG0_2) {
if ((int)ileft > 0) {
stat = ST_MBTOG0_2;
continue;
} else {
UNGET();
UNGET();
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (ic == F_X0212_90) {
stat = ST_INIT;
st->_st_cset_sav = cset = CS_3;
continue;
} else {
UNGET();
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (stat == ST_MBTOG0_2) {
if ((ic == F_X0208_83_90) || (ic == F_X0208_78)) {
stat = ST_INIT;
st->_st_cset_sav = cset = CS_1;
continue;
} else if (ic == F_X0212_90) {
stat = ST_INIT;
st->_st_cset_sav = cset = CS_3;
continue;
} else {
UNGET();
UNGET();
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (stat == ST_SBTOG0) {
if ((ic == F_ASCII) ||
(ic == F_X0201_RM) ||
(ic == F_ISO646)) {
stat = ST_INIT;
st->_st_cset_sav = cset = CS_0;
continue;
} else if (ic == F_X0201_KN) {
stat = ST_INIT;
st->_st_cset_sav = cset = CS_2;
continue;
} else {
UNGET();
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (stat == ST_208REV_1) {
if (ic == X208REV_2) {
if ((int)ileft > 0) {
stat = ST_208REV_2;
continue;
} else {
UNGET();
UNGET();
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else {
UNGET();
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (stat == ST_208REV_2) {
if (ic == ESC) {
if ((int)ileft > 0) {
stat = ST_REV_AFT_ESC;
continue;
} else {
UNGET();
UNGET();
UNGET();
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else {
UNGET();
UNGET();
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (stat == ST_REV_AFT_ESC) {
if (ic == MBTOG0_1) {
if ((int)ileft > 0) {
stat = ST_REV_AFT_MBTOG0_1;
continue;
} else {
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else {
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (stat == ST_REV_AFT_MBTOG0_1) {
if (ic == F_X0208_83_90) {
stat = ST_INIT;
st->_st_cset_sav = cset = CS_1;
continue;
} else if (ic == MBTOG0_2) {
if ((int)ileft > 0) {
stat = ST_REV_AFT_MBTOG0_2;
continue;
} else {
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else {
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (stat == ST_REV_AFT_MBTOG0_2) {
if (ic == F_X0208_83_90) {
stat = ST_INIT;
st->_st_cset_sav = cset = CS_1;
continue;
} else {
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
}
if (ic == ESC) {
if ((int)ileft > 0) {
stat = ST_ESC;
continue;
} else {
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
} else if (ic == SO) {
cset = CS_2;
stat = ST_INIT;
continue;
} else if (ic == SI) {
cset = st->_st_cset_sav;
stat = ST_INIT;
continue;
} else if (!(ic & CMSB)) {
if ((cset == CS_0) || (cset == CS_2)){
if (cset == CS_0) {
index = (int)_jfp_tbl_jisx0201roman_to_ucs2[(int)ic];
} else if (cset == CS_2) {
index =
(int)_jfp_tbl_jisx0201kana_to_ucs2[(ic - 0x21)];
}
if ((ret_val = write_unicode(
(unsigned int)index, &op, &oleft,
B_FALSE, "writing CS_0/2"))
< 0) {
UNGET();
retval = (size_t)ERR_RETURN;
goto ret;
}
stat = ST_INIT;
continue;
} else if ((cset == CS_1) || (cset == CS_3)) {
if ((int)ileft > 0) {
if ((ic < 0x21) || (ic == 0x7f)) {
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
} else if ((*ip < 0x21) || (*ip ==
0x7f)) {
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
index = ((ic - 0x21) * 94)
+ (*ip - 0x21);
if (cset == CS_1) {
#ifdef RFC1468_MODE
if ((ic == 0x2d) ||
(0x75 <= ic))
index = 0x3013;
else
index = (int)
_jfp_tbl_jisx0208_to_ucs2[index];
#else
index = (int)
_jfp_tbl_jisx0208_to_ucs2[index];
#endif
} else if (cset == CS_3) {
#ifdef RFC1468_MODE
index = 0x3013;
#else
index =
(int)_jfp_tbl_jisx0212_to_ucs2[index];
#endif
}
if ((ret_val = write_unicode(
(unsigned int)index,
&op, &oleft,
B_FALSE, "writing CS_1/3"))
< 0) {
UNGET();
retval =
(size_t)ERR_RETURN;
goto ret;
}
GET(ic);
stat = ST_INIT;
continue;
} else {
UNGET();
errno = EINVAL;
retval = (size_t)ERR_RETURN;
goto ret;
}
}
} else {
UNGET();
errno = EILSEQ;
retval = (size_t)ERR_RETURN;
goto ret;
}
}
retval = ileft;
ret:
*inbuf = ip;
*inbytesleft = ileft;
*outbuf = (char *)op;
*outbytesleft = oleft;
st->_st_cset = cset;
return (retval);
}