summaryrefslogtreecommitdiff
path: root/src/locale/iconv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/locale/iconv.c')
-rw-r--r--src/locale/iconv.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
index 0696b555..2107b055 100644
--- a/src/locale/iconv.c
+++ b/src/locale/iconv.c
@@ -18,6 +18,7 @@
#define UTF_8 0310
#define EUC_JP 0320
#define SHIFT_JIS 0321
+#define ISO2022_JP 0322
#define GB18030 0330
#define GBK 0331
#define GB2312 0332
@@ -41,6 +42,7 @@ static const unsigned char charmaps[] =
"ascii\0usascii\0iso646\0iso646us\0\0\307"
"eucjp\0\0\320"
"shiftjis\0sjis\0\0\321"
+"iso2022jp\0\0\322"
"gb18030\0\0\330"
"gbk\0\0\331"
"gb2312\0\0\332"
@@ -123,6 +125,7 @@ static size_t extract_to(iconv_t cd)
iconv_t iconv_open(const char *to, const char *from)
{
size_t f, t;
+ struct stateful_cd *scd;
if ((t = find_charmap(to))==-1
|| (f = find_charmap(from))==-1
@@ -132,8 +135,9 @@ iconv_t iconv_open(const char *to, const char *from)
}
iconv_t cd = combine_to_from(t, f);
- if (0) {
- struct stateful_cd *scd = malloc(sizeof *scd);
+ switch (charmaps[f]) {
+ case ISO2022_JP:
+ scd = malloc(sizeof *scd);
if (!scd) return (iconv_t)-1;
scd->base_cd = cd;
scd->state = 0;
@@ -294,6 +298,45 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
c = jis0208[c][d];
if (!c) goto ilseq;
break;
+ case ISO2022_JP:
+ if (c >= 128) goto ilseq;
+ if (c == '\033') {
+ l = 3;
+ if (*inb < 3) goto starved;
+ c = *((unsigned char *)*in + 1);
+ d = *((unsigned char *)*in + 2);
+ if (c != '(' && c != '$') goto ilseq;
+ switch (128*(c=='$') + d) {
+ case 'B': scd->state=0; continue;
+ case 'J': scd->state=1; continue;
+ case 'I': scd->state=4; continue;
+ case 128+'@': scd->state=2; continue;
+ case 128+'B': scd->state=3; continue;
+ }
+ goto ilseq;
+ }
+ switch (scd->state) {
+ case 1:
+ if (c=='\\') c = 0xa5;
+ if (c=='~') c = 0x203e;
+ break;
+ case 2:
+ case 3:
+ l = 2;
+ if (*inb < 2) goto starved;
+ d = *((unsigned char *)*in + 1);
+ c -= 0x21;
+ d -= 0x21;
+ if (c >= 84 || d >= 94) goto ilseq;
+ c = jis0208[c][d];
+ if (!c) goto ilseq;
+ break;
+ case 4:
+ if (c-0x60 < 0x1f) goto ilseq;
+ if (c-0x21 < 0x5e) c += 0xff61-0x21;
+ break;
+ }
+ break;
case GB2312:
if (c < 128) break;
if (c < 0xa1) goto ilseq;