1*aef5731fSOliver Tappe /*
2*aef5731fSOliver Tappe * Copyright (C) 1999-2004 Free Software Foundation, Inc.
3*aef5731fSOliver Tappe * This file is part of the GNU LIBICONV Library.
4*aef5731fSOliver Tappe *
5*aef5731fSOliver Tappe * The GNU LIBICONV Library is free software; you can redistribute it
6*aef5731fSOliver Tappe * and/or modify it under the terms of the GNU Library General Public
7*aef5731fSOliver Tappe * License as published by the Free Software Foundation; either version 2
8*aef5731fSOliver Tappe * of the License, or (at your option) any later version.
9*aef5731fSOliver Tappe *
10*aef5731fSOliver Tappe * The GNU LIBICONV Library is distributed in the hope that it will be
11*aef5731fSOliver Tappe * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12*aef5731fSOliver Tappe * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13*aef5731fSOliver Tappe * Library General Public License for more details.
14*aef5731fSOliver Tappe *
15*aef5731fSOliver Tappe * You should have received a copy of the GNU Library General Public
16*aef5731fSOliver Tappe * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
17*aef5731fSOliver Tappe * If not, write to the Free Software Foundation, Inc., 51 Franklin Street,
18*aef5731fSOliver Tappe * Fifth Floor, Boston, MA 02110-1301, USA.
19*aef5731fSOliver Tappe */
20*aef5731fSOliver Tappe
21*aef5731fSOliver Tappe /*
22*aef5731fSOliver Tappe * ISO-2022-JP-3
23*aef5731fSOliver Tappe */
24*aef5731fSOliver Tappe
25*aef5731fSOliver Tappe #include "jisx0213.h"
26*aef5731fSOliver Tappe
27*aef5731fSOliver Tappe #define ESC 0x1b
28*aef5731fSOliver Tappe
29*aef5731fSOliver Tappe /*
30*aef5731fSOliver Tappe * The state is composed of one of the following values
31*aef5731fSOliver Tappe */
32*aef5731fSOliver Tappe #define STATE_ASCII 0 /* Esc ( B */
33*aef5731fSOliver Tappe #define STATE_JISX0201ROMAN 1 /* Esc ( J */
34*aef5731fSOliver Tappe #define STATE_JISX0201KATAKANA 2 /* Esc ( I */
35*aef5731fSOliver Tappe #define STATE_JISX0208 3 /* Esc $ @ or Esc $ B */
36*aef5731fSOliver Tappe #define STATE_JISX02131 4 /* Esc $ ( O or Esc $ ( Q*/
37*aef5731fSOliver Tappe #define STATE_JISX02132 5 /* Esc $ ( P */
38*aef5731fSOliver Tappe
39*aef5731fSOliver Tappe /*
40*aef5731fSOliver Tappe * In the ISO-2022-JP-3 to UCS-4 direction, the state also holds the last
41*aef5731fSOliver Tappe * character to be output, shifted by 3 bits.
42*aef5731fSOliver Tappe */
43*aef5731fSOliver Tappe
44*aef5731fSOliver Tappe static int
iso2022_jp3_mbtowc(conv_t conv,ucs4_t * pwc,const unsigned char * s,int n)45*aef5731fSOliver Tappe iso2022_jp3_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n)
46*aef5731fSOliver Tappe {
47*aef5731fSOliver Tappe ucs4_t last_wc = conv->istate >> 3;
48*aef5731fSOliver Tappe if (last_wc) {
49*aef5731fSOliver Tappe /* Output the buffered character. */
50*aef5731fSOliver Tappe conv->istate &= 7;
51*aef5731fSOliver Tappe *pwc = last_wc;
52*aef5731fSOliver Tappe return 0; /* Don't advance the input pointer. */
53*aef5731fSOliver Tappe } else {
54*aef5731fSOliver Tappe state_t state = conv->istate;
55*aef5731fSOliver Tappe int count = 0;
56*aef5731fSOliver Tappe unsigned char c;
57*aef5731fSOliver Tappe for (;;) {
58*aef5731fSOliver Tappe c = *s;
59*aef5731fSOliver Tappe if (c == ESC) {
60*aef5731fSOliver Tappe if (n < count+3)
61*aef5731fSOliver Tappe goto none;
62*aef5731fSOliver Tappe if (s[1] == '(') {
63*aef5731fSOliver Tappe if (s[2] == 'B') {
64*aef5731fSOliver Tappe state = STATE_ASCII;
65*aef5731fSOliver Tappe s += 3; count += 3;
66*aef5731fSOliver Tappe if (n < count+1)
67*aef5731fSOliver Tappe goto none;
68*aef5731fSOliver Tappe continue;
69*aef5731fSOliver Tappe }
70*aef5731fSOliver Tappe if (s[2] == 'J') {
71*aef5731fSOliver Tappe state = STATE_JISX0201ROMAN;
72*aef5731fSOliver Tappe s += 3; count += 3;
73*aef5731fSOliver Tappe if (n < count+1)
74*aef5731fSOliver Tappe goto none;
75*aef5731fSOliver Tappe continue;
76*aef5731fSOliver Tappe }
77*aef5731fSOliver Tappe if (s[2] == 'I') {
78*aef5731fSOliver Tappe state = STATE_JISX0201KATAKANA;
79*aef5731fSOliver Tappe s += 3; count += 3;
80*aef5731fSOliver Tappe if (n < count+1)
81*aef5731fSOliver Tappe goto none;
82*aef5731fSOliver Tappe continue;
83*aef5731fSOliver Tappe }
84*aef5731fSOliver Tappe return RET_ILSEQ;
85*aef5731fSOliver Tappe }
86*aef5731fSOliver Tappe if (s[1] == '$') {
87*aef5731fSOliver Tappe if (s[2] == '@' || s[2] == 'B') {
88*aef5731fSOliver Tappe /* We don't distinguish JIS X 0208-1978 and JIS X 0208-1983. */
89*aef5731fSOliver Tappe state = STATE_JISX0208;
90*aef5731fSOliver Tappe s += 3; count += 3;
91*aef5731fSOliver Tappe if (n < count+1)
92*aef5731fSOliver Tappe goto none;
93*aef5731fSOliver Tappe continue;
94*aef5731fSOliver Tappe }
95*aef5731fSOliver Tappe if (s[2] == '(') {
96*aef5731fSOliver Tappe if (n < count+4)
97*aef5731fSOliver Tappe goto none;
98*aef5731fSOliver Tappe if (s[3] == 'O' || s[3] == 'Q') {
99*aef5731fSOliver Tappe state = STATE_JISX02131;
100*aef5731fSOliver Tappe s += 4; count += 4;
101*aef5731fSOliver Tappe if (n < count+1)
102*aef5731fSOliver Tappe goto none;
103*aef5731fSOliver Tappe continue;
104*aef5731fSOliver Tappe }
105*aef5731fSOliver Tappe if (s[3] == 'P') {
106*aef5731fSOliver Tappe state = STATE_JISX02132;
107*aef5731fSOliver Tappe s += 4; count += 4;
108*aef5731fSOliver Tappe if (n < count+1)
109*aef5731fSOliver Tappe goto none;
110*aef5731fSOliver Tappe continue;
111*aef5731fSOliver Tappe }
112*aef5731fSOliver Tappe }
113*aef5731fSOliver Tappe return RET_ILSEQ;
114*aef5731fSOliver Tappe }
115*aef5731fSOliver Tappe return RET_ILSEQ;
116*aef5731fSOliver Tappe }
117*aef5731fSOliver Tappe break;
118*aef5731fSOliver Tappe }
119*aef5731fSOliver Tappe switch (state) {
120*aef5731fSOliver Tappe case STATE_ASCII:
121*aef5731fSOliver Tappe if (c < 0x80) {
122*aef5731fSOliver Tappe int ret = ascii_mbtowc(conv,pwc,s,1);
123*aef5731fSOliver Tappe if (ret == RET_ILSEQ)
124*aef5731fSOliver Tappe return RET_ILSEQ;
125*aef5731fSOliver Tappe if (ret != 1) abort();
126*aef5731fSOliver Tappe conv->istate = state;
127*aef5731fSOliver Tappe return count+1;
128*aef5731fSOliver Tappe } else
129*aef5731fSOliver Tappe return RET_ILSEQ;
130*aef5731fSOliver Tappe case STATE_JISX0201ROMAN:
131*aef5731fSOliver Tappe if (c < 0x80) {
132*aef5731fSOliver Tappe int ret = jisx0201_mbtowc(conv,pwc,s,1);
133*aef5731fSOliver Tappe if (ret == RET_ILSEQ)
134*aef5731fSOliver Tappe return RET_ILSEQ;
135*aef5731fSOliver Tappe if (ret != 1) abort();
136*aef5731fSOliver Tappe conv->istate = state;
137*aef5731fSOliver Tappe return count+1;
138*aef5731fSOliver Tappe } else
139*aef5731fSOliver Tappe return RET_ILSEQ;
140*aef5731fSOliver Tappe case STATE_JISX0201KATAKANA:
141*aef5731fSOliver Tappe if (c < 0x80) {
142*aef5731fSOliver Tappe unsigned char buf = c+0x80;
143*aef5731fSOliver Tappe int ret = jisx0201_mbtowc(conv,pwc,&buf,1);
144*aef5731fSOliver Tappe if (ret == RET_ILSEQ)
145*aef5731fSOliver Tappe return RET_ILSEQ;
146*aef5731fSOliver Tappe if (ret != 1) abort();
147*aef5731fSOliver Tappe conv->istate = state;
148*aef5731fSOliver Tappe return count+1;
149*aef5731fSOliver Tappe } else
150*aef5731fSOliver Tappe return RET_ILSEQ;
151*aef5731fSOliver Tappe case STATE_JISX0208:
152*aef5731fSOliver Tappe if (n < count+2)
153*aef5731fSOliver Tappe goto none;
154*aef5731fSOliver Tappe if (s[0] < 0x80 && s[1] < 0x80) {
155*aef5731fSOliver Tappe int ret = jisx0208_mbtowc(conv,pwc,s,2);
156*aef5731fSOliver Tappe if (ret == RET_ILSEQ)
157*aef5731fSOliver Tappe return RET_ILSEQ;
158*aef5731fSOliver Tappe if (ret != 2) abort();
159*aef5731fSOliver Tappe conv->istate = state;
160*aef5731fSOliver Tappe return count+2;
161*aef5731fSOliver Tappe } else
162*aef5731fSOliver Tappe return RET_ILSEQ;
163*aef5731fSOliver Tappe case STATE_JISX02131:
164*aef5731fSOliver Tappe case STATE_JISX02132:
165*aef5731fSOliver Tappe if (n < count+2)
166*aef5731fSOliver Tappe goto none;
167*aef5731fSOliver Tappe if (s[0] < 0x80 && s[1] < 0x80) {
168*aef5731fSOliver Tappe ucs4_t wc = jisx0213_to_ucs4(((state-STATE_JISX02131+1)<<8)+s[0],s[1]);
169*aef5731fSOliver Tappe if (wc) {
170*aef5731fSOliver Tappe if (wc < 0x80) {
171*aef5731fSOliver Tappe /* It's a combining character. */
172*aef5731fSOliver Tappe ucs4_t wc1 = jisx0213_to_ucs_combining[wc - 1][0];
173*aef5731fSOliver Tappe ucs4_t wc2 = jisx0213_to_ucs_combining[wc - 1][1];
174*aef5731fSOliver Tappe /* We cannot output two Unicode characters at once. So,
175*aef5731fSOliver Tappe output the first character and buffer the second one. */
176*aef5731fSOliver Tappe *pwc = wc1;
177*aef5731fSOliver Tappe conv->istate = (wc2 << 3) | state;
178*aef5731fSOliver Tappe } else {
179*aef5731fSOliver Tappe *pwc = wc;
180*aef5731fSOliver Tappe conv->istate = state;
181*aef5731fSOliver Tappe }
182*aef5731fSOliver Tappe return count+2;
183*aef5731fSOliver Tappe }
184*aef5731fSOliver Tappe }
185*aef5731fSOliver Tappe return RET_ILSEQ;
186*aef5731fSOliver Tappe default: abort();
187*aef5731fSOliver Tappe }
188*aef5731fSOliver Tappe none:
189*aef5731fSOliver Tappe conv->istate = state;
190*aef5731fSOliver Tappe return RET_TOOFEW(count);
191*aef5731fSOliver Tappe }
192*aef5731fSOliver Tappe }
193*aef5731fSOliver Tappe
194*aef5731fSOliver Tappe static int
iso2022_jp3_flushwc(conv_t conv,ucs4_t * pwc)195*aef5731fSOliver Tappe iso2022_jp3_flushwc (conv_t conv, ucs4_t *pwc)
196*aef5731fSOliver Tappe {
197*aef5731fSOliver Tappe ucs4_t last_wc = conv->istate >> 3;
198*aef5731fSOliver Tappe if (last_wc) {
199*aef5731fSOliver Tappe /* Output the buffered character. */
200*aef5731fSOliver Tappe conv->istate &= 7;
201*aef5731fSOliver Tappe *pwc = last_wc;
202*aef5731fSOliver Tappe return 1;
203*aef5731fSOliver Tappe } else
204*aef5731fSOliver Tappe return 0;
205*aef5731fSOliver Tappe }
206*aef5731fSOliver Tappe
207*aef5731fSOliver Tappe /*
208*aef5731fSOliver Tappe * In the UCS-4 to ISO-2022-JP-3 direction, the state also holds the last two
209*aef5731fSOliver Tappe * bytes to be output, shifted by 3 bits, and the STATE_xxxxx value that was
210*aef5731fSOliver Tappe * effective before this buffered character, shifted by 19 bits.
211*aef5731fSOliver Tappe */
212*aef5731fSOliver Tappe
213*aef5731fSOliver Tappe /* Composition tables for each of the relevant combining characters. */
214*aef5731fSOliver Tappe static const struct { unsigned short base; unsigned short composed; } iso2022_jp3_comp_table_data[] = {
215*aef5731fSOliver Tappe #define iso2022_jp3_comp_table02e5_idx 0
216*aef5731fSOliver Tappe #define iso2022_jp3_comp_table02e5_len 1
217*aef5731fSOliver Tappe { 0x2b64, 0x2b65 }, /* 0x12B65 = 0x12B64 U+02E5 */
218*aef5731fSOliver Tappe #define iso2022_jp3_comp_table02e9_idx (iso2022_jp3_comp_table02e5_idx+iso2022_jp3_comp_table02e5_len)
219*aef5731fSOliver Tappe #define iso2022_jp3_comp_table02e9_len 1
220*aef5731fSOliver Tappe { 0x2b60, 0x2b66 }, /* 0x12B66 = 0x12B60 U+02E9 */
221*aef5731fSOliver Tappe #define iso2022_jp3_comp_table0300_idx (iso2022_jp3_comp_table02e9_idx+iso2022_jp3_comp_table02e9_len)
222*aef5731fSOliver Tappe #define iso2022_jp3_comp_table0300_len 5
223*aef5731fSOliver Tappe { 0x295c, 0x2b44 }, /* 0x12B44 = 0x1295C U+0300 */
224*aef5731fSOliver Tappe { 0x2b38, 0x2b48 }, /* 0x12B48 = 0x12B38 U+0300 */
225*aef5731fSOliver Tappe { 0x2b37, 0x2b4a }, /* 0x12B4A = 0x12B37 U+0300 */
226*aef5731fSOliver Tappe { 0x2b30, 0x2b4c }, /* 0x12B4C = 0x12B30 U+0300 */
227*aef5731fSOliver Tappe { 0x2b43, 0x2b4e }, /* 0x12B4E = 0x12B43 U+0300 */
228*aef5731fSOliver Tappe #define iso2022_jp3_comp_table0301_idx (iso2022_jp3_comp_table0300_idx+iso2022_jp3_comp_table0300_len)
229*aef5731fSOliver Tappe #define iso2022_jp3_comp_table0301_len 4
230*aef5731fSOliver Tappe { 0x2b38, 0x2b49 }, /* 0x12B49 = 0x12B38 U+0301 */
231*aef5731fSOliver Tappe { 0x2b37, 0x2b4b }, /* 0x12B4B = 0x12B37 U+0301 */
232*aef5731fSOliver Tappe { 0x2b30, 0x2b4d }, /* 0x12B4D = 0x12B30 U+0301 */
233*aef5731fSOliver Tappe { 0x2b43, 0x2b4f }, /* 0x12B4F = 0x12B43 U+0301 */
234*aef5731fSOliver Tappe #define iso2022_jp3_comp_table309a_idx (iso2022_jp3_comp_table0301_idx+iso2022_jp3_comp_table0301_len)
235*aef5731fSOliver Tappe #define iso2022_jp3_comp_table309a_len 14
236*aef5731fSOliver Tappe { 0x242b, 0x2477 }, /* 0x12477 = 0x1242B U+309A */
237*aef5731fSOliver Tappe { 0x242d, 0x2478 }, /* 0x12478 = 0x1242D U+309A */
238*aef5731fSOliver Tappe { 0x242f, 0x2479 }, /* 0x12479 = 0x1242F U+309A */
239*aef5731fSOliver Tappe { 0x2431, 0x247a }, /* 0x1247A = 0x12431 U+309A */
240*aef5731fSOliver Tappe { 0x2433, 0x247b }, /* 0x1247B = 0x12433 U+309A */
241*aef5731fSOliver Tappe { 0x252b, 0x2577 }, /* 0x12577 = 0x1252B U+309A */
242*aef5731fSOliver Tappe { 0x252d, 0x2578 }, /* 0x12578 = 0x1252D U+309A */
243*aef5731fSOliver Tappe { 0x252f, 0x2579 }, /* 0x12579 = 0x1252F U+309A */
244*aef5731fSOliver Tappe { 0x2531, 0x257a }, /* 0x1257A = 0x12531 U+309A */
245*aef5731fSOliver Tappe { 0x2533, 0x257b }, /* 0x1257B = 0x12533 U+309A */
246*aef5731fSOliver Tappe { 0x253b, 0x257c }, /* 0x1257C = 0x1253B U+309A */
247*aef5731fSOliver Tappe { 0x2544, 0x257d }, /* 0x1257D = 0x12544 U+309A */
248*aef5731fSOliver Tappe { 0x2548, 0x257e }, /* 0x1257E = 0x12548 U+309A */
249*aef5731fSOliver Tappe { 0x2675, 0x2678 }, /* 0x12678 = 0x12675 U+309A */
250*aef5731fSOliver Tappe };
251*aef5731fSOliver Tappe
252*aef5731fSOliver Tappe #define SPLIT_STATE \
253*aef5731fSOliver Tappe unsigned short lasttwo = state >> 3; state_t prevstate = state >> 19; state &= 7
254*aef5731fSOliver Tappe #define COMBINE_STATE \
255*aef5731fSOliver Tappe state |= (prevstate << 19) | (lasttwo << 3)
256*aef5731fSOliver Tappe #define COMBINE_STATE_NO_LASTTWO \
257*aef5731fSOliver Tappe /* assume lasttwo == 0, then prevstate is ignored */
258*aef5731fSOliver Tappe
259*aef5731fSOliver Tappe static int
iso2022_jp3_wctomb(conv_t conv,unsigned char * r,ucs4_t wc,int n)260*aef5731fSOliver Tappe iso2022_jp3_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)
261*aef5731fSOliver Tappe {
262*aef5731fSOliver Tappe int count = 0;
263*aef5731fSOliver Tappe unsigned char buf[2];
264*aef5731fSOliver Tappe unsigned short jch;
265*aef5731fSOliver Tappe int ret;
266*aef5731fSOliver Tappe state_t state = conv->ostate;
267*aef5731fSOliver Tappe SPLIT_STATE;
268*aef5731fSOliver Tappe
269*aef5731fSOliver Tappe if (lasttwo) {
270*aef5731fSOliver Tappe /* Attempt to combine the last character with this one. */
271*aef5731fSOliver Tappe unsigned int idx;
272*aef5731fSOliver Tappe unsigned int len;
273*aef5731fSOliver Tappe
274*aef5731fSOliver Tappe if (wc == 0x02e5)
275*aef5731fSOliver Tappe idx = iso2022_jp3_comp_table02e5_idx,
276*aef5731fSOliver Tappe len = iso2022_jp3_comp_table02e5_len;
277*aef5731fSOliver Tappe else if (wc == 0x02e9)
278*aef5731fSOliver Tappe idx = iso2022_jp3_comp_table02e9_idx,
279*aef5731fSOliver Tappe len = iso2022_jp3_comp_table02e9_len;
280*aef5731fSOliver Tappe else if (wc == 0x0300)
281*aef5731fSOliver Tappe idx = iso2022_jp3_comp_table0300_idx,
282*aef5731fSOliver Tappe len = iso2022_jp3_comp_table0300_len;
283*aef5731fSOliver Tappe else if (wc == 0x0301)
284*aef5731fSOliver Tappe idx = iso2022_jp3_comp_table0301_idx,
285*aef5731fSOliver Tappe len = iso2022_jp3_comp_table0301_len;
286*aef5731fSOliver Tappe else if (wc == 0x309a)
287*aef5731fSOliver Tappe idx = iso2022_jp3_comp_table309a_idx,
288*aef5731fSOliver Tappe len = iso2022_jp3_comp_table309a_len;
289*aef5731fSOliver Tappe else
290*aef5731fSOliver Tappe goto not_combining;
291*aef5731fSOliver Tappe
292*aef5731fSOliver Tappe do
293*aef5731fSOliver Tappe if (iso2022_jp3_comp_table_data[idx].base == lasttwo)
294*aef5731fSOliver Tappe break;
295*aef5731fSOliver Tappe while (++idx, --len > 0);
296*aef5731fSOliver Tappe
297*aef5731fSOliver Tappe if (len > 0) {
298*aef5731fSOliver Tappe /* Output the combined character. */
299*aef5731fSOliver Tappe /* We know the combined character is in JISX0213 plane 1, but
300*aef5731fSOliver Tappe the buffered character may have been in JISX0208 or in
301*aef5731fSOliver Tappe JISX0213 plane 1. */
302*aef5731fSOliver Tappe count = (state != STATE_JISX02131 ? 4 : 0) + 2;
303*aef5731fSOliver Tappe if (n < count)
304*aef5731fSOliver Tappe return RET_TOOSMALL;
305*aef5731fSOliver Tappe if (state != STATE_JISX02131) {
306*aef5731fSOliver Tappe r[0] = ESC;
307*aef5731fSOliver Tappe r[1] = '$';
308*aef5731fSOliver Tappe r[2] = '(';
309*aef5731fSOliver Tappe r[3] = 'Q';
310*aef5731fSOliver Tappe r += 4;
311*aef5731fSOliver Tappe state = STATE_JISX02131;
312*aef5731fSOliver Tappe }
313*aef5731fSOliver Tappe lasttwo = iso2022_jp3_comp_table_data[idx].composed;
314*aef5731fSOliver Tappe r[0] = (lasttwo >> 8) & 0xff;
315*aef5731fSOliver Tappe r[1] = lasttwo & 0xff;
316*aef5731fSOliver Tappe COMBINE_STATE_NO_LASTTWO;
317*aef5731fSOliver Tappe conv->ostate = state;
318*aef5731fSOliver Tappe return count;
319*aef5731fSOliver Tappe }
320*aef5731fSOliver Tappe
321*aef5731fSOliver Tappe not_combining:
322*aef5731fSOliver Tappe /* Output the buffered character. */
323*aef5731fSOliver Tappe /* We know it is in JISX0208 or in JISX0213 plane 1. */
324*aef5731fSOliver Tappe count = (prevstate != state ? 3 : 0) + 2;
325*aef5731fSOliver Tappe if (n < count)
326*aef5731fSOliver Tappe return RET_TOOSMALL;
327*aef5731fSOliver Tappe if (prevstate != state) {
328*aef5731fSOliver Tappe if (state != STATE_JISX0208) abort();
329*aef5731fSOliver Tappe r[0] = ESC;
330*aef5731fSOliver Tappe r[1] = '$';
331*aef5731fSOliver Tappe r[2] = 'B';
332*aef5731fSOliver Tappe r += 3;
333*aef5731fSOliver Tappe }
334*aef5731fSOliver Tappe r[0] = (lasttwo >> 8) & 0xff;
335*aef5731fSOliver Tappe r[1] = lasttwo & 0xff;
336*aef5731fSOliver Tappe r += 2;
337*aef5731fSOliver Tappe }
338*aef5731fSOliver Tappe
339*aef5731fSOliver Tappe /* Try ASCII. */
340*aef5731fSOliver Tappe ret = ascii_wctomb(conv,buf,wc,1);
341*aef5731fSOliver Tappe if (ret != RET_ILUNI) {
342*aef5731fSOliver Tappe if (ret != 1) abort();
343*aef5731fSOliver Tappe if (buf[0] < 0x80) {
344*aef5731fSOliver Tappe count += (state == STATE_ASCII ? 1 : 4);
345*aef5731fSOliver Tappe if (n < count)
346*aef5731fSOliver Tappe return RET_TOOSMALL;
347*aef5731fSOliver Tappe if (state != STATE_ASCII) {
348*aef5731fSOliver Tappe r[0] = ESC;
349*aef5731fSOliver Tappe r[1] = '(';
350*aef5731fSOliver Tappe r[2] = 'B';
351*aef5731fSOliver Tappe r += 3;
352*aef5731fSOliver Tappe state = STATE_ASCII;
353*aef5731fSOliver Tappe }
354*aef5731fSOliver Tappe r[0] = buf[0];
355*aef5731fSOliver Tappe COMBINE_STATE_NO_LASTTWO;
356*aef5731fSOliver Tappe conv->ostate = state;
357*aef5731fSOliver Tappe return count;
358*aef5731fSOliver Tappe }
359*aef5731fSOliver Tappe }
360*aef5731fSOliver Tappe
361*aef5731fSOliver Tappe /* Try JIS X 0201-1976 Roman. */
362*aef5731fSOliver Tappe ret = jisx0201_wctomb(conv,buf,wc,1);
363*aef5731fSOliver Tappe if (ret != RET_ILUNI) {
364*aef5731fSOliver Tappe if (ret != 1) abort();
365*aef5731fSOliver Tappe if (buf[0] < 0x80) {
366*aef5731fSOliver Tappe count += (state == STATE_JISX0201ROMAN ? 1 : 4);
367*aef5731fSOliver Tappe if (n < count)
368*aef5731fSOliver Tappe return RET_TOOSMALL;
369*aef5731fSOliver Tappe if (state != STATE_JISX0201ROMAN) {
370*aef5731fSOliver Tappe r[0] = ESC;
371*aef5731fSOliver Tappe r[1] = '(';
372*aef5731fSOliver Tappe r[2] = 'J';
373*aef5731fSOliver Tappe r += 3;
374*aef5731fSOliver Tappe state = STATE_JISX0201ROMAN;
375*aef5731fSOliver Tappe }
376*aef5731fSOliver Tappe r[0] = buf[0];
377*aef5731fSOliver Tappe COMBINE_STATE_NO_LASTTWO;
378*aef5731fSOliver Tappe conv->ostate = state;
379*aef5731fSOliver Tappe return count;
380*aef5731fSOliver Tappe }
381*aef5731fSOliver Tappe }
382*aef5731fSOliver Tappe
383*aef5731fSOliver Tappe jch = ucs4_to_jisx0213(wc);
384*aef5731fSOliver Tappe
385*aef5731fSOliver Tappe /* Try JIS X 0208-1990 in place of JIS X 0208-1978 and JIS X 0208-1983. */
386*aef5731fSOliver Tappe ret = jisx0208_wctomb(conv,buf,wc,2);
387*aef5731fSOliver Tappe if (ret != RET_ILUNI) {
388*aef5731fSOliver Tappe if (ret != 2) abort();
389*aef5731fSOliver Tappe if (buf[0] < 0x80 && buf[1] < 0x80) {
390*aef5731fSOliver Tappe if (jch & 0x0080) {
391*aef5731fSOliver Tappe /* A possible match in comp_table_data. Buffer it. */
392*aef5731fSOliver Tappe prevstate = state;
393*aef5731fSOliver Tappe lasttwo = jch & 0x7f7f;
394*aef5731fSOliver Tappe state = STATE_JISX0208;
395*aef5731fSOliver Tappe COMBINE_STATE;
396*aef5731fSOliver Tappe conv->ostate = state;
397*aef5731fSOliver Tappe return count;
398*aef5731fSOliver Tappe } else {
399*aef5731fSOliver Tappe count += (state == STATE_JISX0208 ? 2 : 5);
400*aef5731fSOliver Tappe if (n < count)
401*aef5731fSOliver Tappe return RET_TOOSMALL;
402*aef5731fSOliver Tappe if (state != STATE_JISX0208) {
403*aef5731fSOliver Tappe r[0] = ESC;
404*aef5731fSOliver Tappe r[1] = '$';
405*aef5731fSOliver Tappe r[2] = 'B';
406*aef5731fSOliver Tappe r += 3;
407*aef5731fSOliver Tappe state = STATE_JISX0208;
408*aef5731fSOliver Tappe }
409*aef5731fSOliver Tappe r[0] = buf[0];
410*aef5731fSOliver Tappe r[1] = buf[1];
411*aef5731fSOliver Tappe COMBINE_STATE_NO_LASTTWO;
412*aef5731fSOliver Tappe conv->ostate = state;
413*aef5731fSOliver Tappe return count;
414*aef5731fSOliver Tappe }
415*aef5731fSOliver Tappe }
416*aef5731fSOliver Tappe }
417*aef5731fSOliver Tappe
418*aef5731fSOliver Tappe /* Try JISX 0213 plane 1 and JISX 0213 plane 2. */
419*aef5731fSOliver Tappe if (jch != 0) {
420*aef5731fSOliver Tappe if (jch & 0x8000) {
421*aef5731fSOliver Tappe /* JISX 0213 plane 2. */
422*aef5731fSOliver Tappe if (state != STATE_JISX02132) {
423*aef5731fSOliver Tappe count += 4;
424*aef5731fSOliver Tappe if (n < count)
425*aef5731fSOliver Tappe return RET_TOOSMALL;
426*aef5731fSOliver Tappe r[0] = ESC;
427*aef5731fSOliver Tappe r[1] = '$';
428*aef5731fSOliver Tappe r[2] = '(';
429*aef5731fSOliver Tappe r[3] = 'P';
430*aef5731fSOliver Tappe r += 4;
431*aef5731fSOliver Tappe state = STATE_JISX02132;
432*aef5731fSOliver Tappe }
433*aef5731fSOliver Tappe } else {
434*aef5731fSOliver Tappe /* JISX 0213 plane 1. */
435*aef5731fSOliver Tappe if (state != STATE_JISX02131) {
436*aef5731fSOliver Tappe count += 4;
437*aef5731fSOliver Tappe if (n < count)
438*aef5731fSOliver Tappe return RET_TOOSMALL;
439*aef5731fSOliver Tappe r[0] = ESC;
440*aef5731fSOliver Tappe r[1] = '$';
441*aef5731fSOliver Tappe r[2] = '(';
442*aef5731fSOliver Tappe r[3] = 'Q';
443*aef5731fSOliver Tappe r += 4;
444*aef5731fSOliver Tappe state = STATE_JISX02131;
445*aef5731fSOliver Tappe }
446*aef5731fSOliver Tappe }
447*aef5731fSOliver Tappe if (jch & 0x0080) {
448*aef5731fSOliver Tappe /* A possible match in comp_table_data. We have to buffer it. */
449*aef5731fSOliver Tappe /* We know it's a JISX 0213 plane 1 character. */
450*aef5731fSOliver Tappe if (jch & 0x8000) abort();
451*aef5731fSOliver Tappe prevstate = state;
452*aef5731fSOliver Tappe lasttwo = jch & 0x7f7f;
453*aef5731fSOliver Tappe COMBINE_STATE;
454*aef5731fSOliver Tappe conv->ostate = state;
455*aef5731fSOliver Tappe return count;
456*aef5731fSOliver Tappe }
457*aef5731fSOliver Tappe count += 2;
458*aef5731fSOliver Tappe if (n < count)
459*aef5731fSOliver Tappe return RET_TOOSMALL;
460*aef5731fSOliver Tappe r[0] = (jch >> 8) & 0x7f;
461*aef5731fSOliver Tappe r[1] = jch & 0x7f;
462*aef5731fSOliver Tappe COMBINE_STATE_NO_LASTTWO;
463*aef5731fSOliver Tappe conv->ostate = state;
464*aef5731fSOliver Tappe return count;
465*aef5731fSOliver Tappe }
466*aef5731fSOliver Tappe
467*aef5731fSOliver Tappe /* Try JIS X 0201-1976 Katakana. This is not officially part of
468*aef5731fSOliver Tappe ISO-2022-JP-3. Therefore we try it after all other attempts. */
469*aef5731fSOliver Tappe ret = jisx0201_wctomb(conv,buf,wc,1);
470*aef5731fSOliver Tappe if (ret != RET_ILUNI) {
471*aef5731fSOliver Tappe if (ret != 1) abort();
472*aef5731fSOliver Tappe if (buf[0] >= 0x80) {
473*aef5731fSOliver Tappe count += (state == STATE_JISX0201KATAKANA ? 1 : 4);
474*aef5731fSOliver Tappe if (n < count)
475*aef5731fSOliver Tappe return RET_TOOSMALL;
476*aef5731fSOliver Tappe if (state != STATE_JISX0201KATAKANA) {
477*aef5731fSOliver Tappe r[0] = ESC;
478*aef5731fSOliver Tappe r[1] = '(';
479*aef5731fSOliver Tappe r[2] = 'I';
480*aef5731fSOliver Tappe r += 3;
481*aef5731fSOliver Tappe state = STATE_JISX0201KATAKANA;
482*aef5731fSOliver Tappe }
483*aef5731fSOliver Tappe r[0] = buf[0]-0x80;
484*aef5731fSOliver Tappe COMBINE_STATE_NO_LASTTWO;
485*aef5731fSOliver Tappe conv->ostate = state;
486*aef5731fSOliver Tappe return count;
487*aef5731fSOliver Tappe }
488*aef5731fSOliver Tappe }
489*aef5731fSOliver Tappe
490*aef5731fSOliver Tappe return RET_ILUNI;
491*aef5731fSOliver Tappe }
492*aef5731fSOliver Tappe
493*aef5731fSOliver Tappe static int
iso2022_jp3_reset(conv_t conv,unsigned char * r,int n)494*aef5731fSOliver Tappe iso2022_jp3_reset (conv_t conv, unsigned char *r, int n)
495*aef5731fSOliver Tappe {
496*aef5731fSOliver Tappe state_t state = conv->ostate;
497*aef5731fSOliver Tappe SPLIT_STATE;
498*aef5731fSOliver Tappe {
499*aef5731fSOliver Tappe int count =
500*aef5731fSOliver Tappe (lasttwo ? (prevstate != state ? 3 : 0) + 2 : 0)
501*aef5731fSOliver Tappe + (state != STATE_ASCII ? 3 : 0);
502*aef5731fSOliver Tappe if (n < count)
503*aef5731fSOliver Tappe return RET_TOOSMALL;
504*aef5731fSOliver Tappe if (lasttwo) {
505*aef5731fSOliver Tappe if (prevstate != state) {
506*aef5731fSOliver Tappe if (state != STATE_JISX0208) abort();
507*aef5731fSOliver Tappe r[0] = ESC;
508*aef5731fSOliver Tappe r[1] = '$';
509*aef5731fSOliver Tappe r[2] = 'B';
510*aef5731fSOliver Tappe r += 3;
511*aef5731fSOliver Tappe }
512*aef5731fSOliver Tappe r[0] = (lasttwo >> 8) & 0xff;
513*aef5731fSOliver Tappe r[1] = lasttwo & 0xff;
514*aef5731fSOliver Tappe r += 2;
515*aef5731fSOliver Tappe }
516*aef5731fSOliver Tappe if (state != STATE_ASCII) {
517*aef5731fSOliver Tappe r[0] = ESC;
518*aef5731fSOliver Tappe r[1] = '(';
519*aef5731fSOliver Tappe r[2] = 'B';
520*aef5731fSOliver Tappe }
521*aef5731fSOliver Tappe /* conv->ostate = 0; will be done by the caller */
522*aef5731fSOliver Tappe return count;
523*aef5731fSOliver Tappe }
524*aef5731fSOliver Tappe }
525*aef5731fSOliver Tappe
526*aef5731fSOliver Tappe #undef COMBINE_STATE_NO_LASTTWO
527*aef5731fSOliver Tappe #undef COMBINE_STATE
528*aef5731fSOliver Tappe #undef SPLIT_STATE
529*aef5731fSOliver Tappe #undef STATE_JISX02132
530*aef5731fSOliver Tappe #undef STATE_JISX02131
531*aef5731fSOliver Tappe #undef STATE_JISX0208
532*aef5731fSOliver Tappe #undef STATE_JISX0201KATAKANA
533*aef5731fSOliver Tappe #undef STATE_JISX0201ROMAN
534*aef5731fSOliver Tappe #undef STATE_ASCII
535