1 /*
2 * "streamable kanji code filter and converter"
3 * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
4 *
5 * LICENSE NOTICES
6 *
7 * This file is part of "streamable kanji code filter and converter",
8 * which is distributed under the terms of GNU Lesser General Public
9 * License (version 2) as published by the Free Software Foundation.
10 *
11 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with "streamable kanji code filter and converter";
18 * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
19 * Suite 330, Boston, MA 02111-1307 USA
20 *
21 * The author of this file:
22 *
23 */
24 /*
25 * The source code included in this files was separated from mbfilter_ja.c
26 * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
27 *
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "mbfilter.h"
35 #include "mbfilter_jis.h"
36
37 #include "unicode_table_cp932_ext.h"
38 #include "unicode_table_jis.h"
39
40 static int mbfl_filt_ident_jis(int c, mbfl_identify_filter *filter);
41 static int mbfl_filt_ident_2022jp(int c, mbfl_identify_filter *filter);
42
43 const mbfl_encoding mbfl_encoding_jis = {
44 mbfl_no_encoding_jis,
45 "JIS",
46 "ISO-2022-JP",
47 NULL,
48 NULL,
49 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE,
50 &vtbl_jis_wchar,
51 &vtbl_wchar_jis
52 };
53
54 const mbfl_encoding mbfl_encoding_2022jp = {
55 mbfl_no_encoding_2022jp,
56 "ISO-2022-JP",
57 "ISO-2022-JP",
58 NULL,
59 NULL,
60 MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE,
61 &vtbl_2022jp_wchar,
62 &vtbl_wchar_2022jp
63 };
64
65 const struct mbfl_identify_vtbl vtbl_identify_jis = {
66 mbfl_no_encoding_jis,
67 mbfl_filt_ident_common_ctor,
68 mbfl_filt_ident_common_dtor,
69 mbfl_filt_ident_jis
70 };
71
72 const struct mbfl_identify_vtbl vtbl_identify_2022jp = {
73 mbfl_no_encoding_2022jp,
74 mbfl_filt_ident_common_ctor,
75 mbfl_filt_ident_common_dtor,
76 mbfl_filt_ident_2022jp
77 };
78
79 const struct mbfl_convert_vtbl vtbl_jis_wchar = {
80 mbfl_no_encoding_jis,
81 mbfl_no_encoding_wchar,
82 mbfl_filt_conv_common_ctor,
83 mbfl_filt_conv_common_dtor,
84 mbfl_filt_conv_jis_wchar,
85 mbfl_filt_conv_common_flush
86 };
87
88 const struct mbfl_convert_vtbl vtbl_wchar_jis = {
89 mbfl_no_encoding_wchar,
90 mbfl_no_encoding_jis,
91 mbfl_filt_conv_common_ctor,
92 mbfl_filt_conv_common_dtor,
93 mbfl_filt_conv_wchar_jis,
94 mbfl_filt_conv_any_jis_flush
95 };
96
97 const struct mbfl_convert_vtbl vtbl_2022jp_wchar = {
98 mbfl_no_encoding_2022jp,
99 mbfl_no_encoding_wchar,
100 mbfl_filt_conv_common_ctor,
101 mbfl_filt_conv_common_dtor,
102 mbfl_filt_conv_jis_wchar,
103 mbfl_filt_conv_common_flush
104 };
105
106 const struct mbfl_convert_vtbl vtbl_wchar_2022jp = {
107 mbfl_no_encoding_wchar,
108 mbfl_no_encoding_2022jp,
109 mbfl_filt_conv_common_ctor,
110 mbfl_filt_conv_common_dtor,
111 mbfl_filt_conv_wchar_2022jp,
112 mbfl_filt_conv_any_jis_flush
113 };
114
115 #define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
116
117 /*
118 * JIS => wchar
119 */
120 int
mbfl_filt_conv_jis_wchar(int c,mbfl_convert_filter * filter)121 mbfl_filt_conv_jis_wchar(int c, mbfl_convert_filter *filter)
122 {
123 int c1, s, w;
124
125 retry:
126 switch (filter->status & 0xf) {
127 /* case 0x00: ASCII */
128 /* case 0x10: X 0201 latin */
129 /* case 0x20: X 0201 kana */
130 /* case 0x80: X 0208 */
131 /* case 0x90: X 0212 */
132 case 0:
133 if (c == 0x1b) {
134 filter->status += 2;
135 } else if (c == 0x0e) { /* "kana in" */
136 filter->status = 0x20;
137 } else if (c == 0x0f) { /* "kana out" */
138 filter->status = 0;
139 } else if (filter->status == 0x10 && c == 0x5c) { /* YEN SIGN */
140 CK((*filter->output_function)(0xa5, filter->data));
141 } else if (filter->status == 0x10 && c == 0x7e) { /* OVER LINE */
142 CK((*filter->output_function)(0x203e, filter->data));
143 } else if (filter->status == 0x20 && c > 0x20 && c < 0x60) { /* kana */
144 CK((*filter->output_function)(0xff40 + c, filter->data));
145 } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) { /* kanji first char */
146 filter->cache = c;
147 filter->status += 1;
148 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
149 CK((*filter->output_function)(c, filter->data));
150 } else if (c > 0xa0 && c < 0xe0) { /* GR kana */
151 CK((*filter->output_function)(0xfec0 + c, filter->data));
152 } else {
153 w = c & MBFL_WCSGROUP_MASK;
154 w |= MBFL_WCSGROUP_THROUGH;
155 CK((*filter->output_function)(w, filter->data));
156 }
157 break;
158
159 /* case 0x81: X 0208 second char */
160 /* case 0x91: X 0212 second char */
161 case 1:
162 filter->status &= ~0xf;
163 c1 = filter->cache;
164 if (c > 0x20 && c < 0x7f) {
165 s = (c1 - 0x21)*94 + c - 0x21;
166 if (filter->status == 0x80) {
167 if (s >= 0 && s < jisx0208_ucs_table_size) {
168 w = jisx0208_ucs_table[s];
169 } else {
170 w = 0;
171 }
172 if (w <= 0) {
173 w = (c1 << 8) | c;
174 w &= MBFL_WCSPLANE_MASK;
175 w |= MBFL_WCSPLANE_JIS0208;
176 }
177 } else {
178 if (s >= 0 && s < jisx0212_ucs_table_size) {
179 w = jisx0212_ucs_table[s];
180 } else {
181 w = 0;
182 }
183 if (w <= 0) {
184 w = (c1 << 8) | c;
185 w &= MBFL_WCSPLANE_MASK;
186 w |= MBFL_WCSPLANE_JIS0212;
187 }
188 }
189 CK((*filter->output_function)(w, filter->data));
190 } else if (c == 0x1b) {
191 filter->status += 2;
192 } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
193 CK((*filter->output_function)(c, filter->data));
194 } else {
195 w = (c1 << 8) | c;
196 w &= MBFL_WCSGROUP_MASK;
197 w |= MBFL_WCSGROUP_THROUGH;
198 CK((*filter->output_function)(w, filter->data));
199 }
200 break;
201
202 /* ESC */
203 /* case 0x02: */
204 /* case 0x12: */
205 /* case 0x22: */
206 /* case 0x82: */
207 /* case 0x92: */
208 case 2:
209 if (c == 0x24) { /* '$' */
210 filter->status++;
211 } else if (c == 0x28) { /* '(' */
212 filter->status += 3;
213 } else {
214 filter->status &= ~0xf;
215 CK((*filter->output_function)(0x1b, filter->data));
216 goto retry;
217 }
218 break;
219
220 /* ESC $ */
221 /* case 0x03: */
222 /* case 0x13: */
223 /* case 0x23: */
224 /* case 0x83: */
225 /* case 0x93: */
226 case 3:
227 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
228 filter->status = 0x80;
229 } else if (c == 0x28) { /* '(' */
230 filter->status++;
231 } else {
232 filter->status &= ~0xf;
233 CK((*filter->output_function)(0x1b, filter->data));
234 CK((*filter->output_function)(0x24, filter->data));
235 goto retry;
236 }
237 break;
238
239 /* ESC $ ( */
240 /* case 0x04: */
241 /* case 0x14: */
242 /* case 0x24: */
243 /* case 0x84: */
244 /* case 0x94: */
245 case 4:
246 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
247 filter->status = 0x80;
248 } else if (c == 0x44) { /* 'D' */
249 filter->status = 0x90;
250 } else {
251 filter->status &= ~0xf;
252 CK((*filter->output_function)(0x1b, filter->data));
253 CK((*filter->output_function)(0x24, filter->data));
254 CK((*filter->output_function)(0x28, filter->data));
255 goto retry;
256 }
257 break;
258
259 /* ESC ( */
260 /* case 0x05: */
261 /* case 0x15: */
262 /* case 0x25: */
263 /* case 0x85: */
264 /* case 0x95: */
265 case 5:
266 if (c == 0x42 || c == 0x48) { /* 'B' or 'H' */
267 filter->status = 0;
268 } else if (c == 0x4a) { /* 'J' */
269 filter->status = 0x10;
270 } else if (c == 0x49) { /* 'I' */
271 filter->status = 0x20;
272 } else {
273 filter->status &= ~0xf;
274 CK((*filter->output_function)(0x1b, filter->data));
275 CK((*filter->output_function)(0x28, filter->data));
276 goto retry;
277 }
278 break;
279
280 default:
281 filter->status = 0;
282 break;
283 }
284
285 return c;
286 }
287
288 /*
289 * wchar => JIS
290 */
291 int
mbfl_filt_conv_wchar_jis(int c,mbfl_convert_filter * filter)292 mbfl_filt_conv_wchar_jis(int c, mbfl_convert_filter *filter)
293 {
294 int c1, s;
295
296 s = 0;
297 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
298 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
299 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
300 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
301 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
302 s = ucs_i_jis_table[c - ucs_i_jis_table_min];
303 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
304 s = ucs_r_jis_table[c - ucs_r_jis_table_min];
305 }
306 if (s <= 0) {
307 c1 = c & ~MBFL_WCSPLANE_MASK;
308 if (c1 == MBFL_WCSPLANE_JIS0208) {
309 s = c & MBFL_WCSPLANE_MASK;
310 } else if (c1 == MBFL_WCSPLANE_JIS0212) {
311 s = c & MBFL_WCSPLANE_MASK;
312 s |= 0x8080;
313 } else if (c == 0xa5) { /* YEN SIGN */
314 s = 0x1005c;
315 } else if (c == 0x203e) { /* OVER LINE */
316 s = 0x1007e;
317 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
318 s = 0x2140;
319 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
320 s = 0x2141;
321 } else if (c == 0x2225) { /* PARALLEL TO */
322 s = 0x2142;
323 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */
324 s = 0x215d;
325 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */
326 s = 0x2171;
327 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */
328 s = 0x2172;
329 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
330 s = 0x224c;
331 }
332 if (c == 0) {
333 s = 0;
334 } else if (s <= 0) {
335 s = -1;
336 }
337 }
338 if (s >= 0) {
339 if (s < 0x80) { /* ASCII */
340 if ((filter->status & 0xff00) != 0) {
341 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
342 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
343 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
344 }
345 filter->status = 0;
346 CK((*filter->output_function)(s, filter->data));
347 } else if (s < 0x100) { /* kana */
348 if ((filter->status & 0xff00) != 0x100) {
349 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
350 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
351 CK((*filter->output_function)(0x49, filter->data)); /* 'I' */
352 }
353 filter->status = 0x100;
354 CK((*filter->output_function)(s & 0x7f, filter->data));
355 } else if (s < 0x8080) { /* X 0208 */
356 if ((filter->status & 0xff00) != 0x200) {
357 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
358 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
359 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
360 }
361 filter->status = 0x200;
362 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
363 CK((*filter->output_function)(s & 0x7f, filter->data));
364 } else if (s < 0x10000) { /* X 0212 */
365 if ((filter->status & 0xff00) != 0x300) {
366 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
367 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
368 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
369 CK((*filter->output_function)(0x44, filter->data)); /* 'D' */
370 }
371 filter->status = 0x300;
372 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
373 CK((*filter->output_function)(s & 0x7f, filter->data));
374 } else { /* X 0201 latin */
375 if ((filter->status & 0xff00) != 0x400) {
376 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
377 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
378 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */
379 }
380 filter->status = 0x400;
381 CK((*filter->output_function)(s & 0x7f, filter->data));
382 }
383 } else {
384 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
385 CK(mbfl_filt_conv_illegal_output(c, filter));
386 }
387 }
388
389 return c;
390 }
391
392
393 /*
394 * wchar => ISO-2022-JP
395 */
396 int
mbfl_filt_conv_wchar_2022jp(int c,mbfl_convert_filter * filter)397 mbfl_filt_conv_wchar_2022jp(int c, mbfl_convert_filter *filter)
398 {
399 int s;
400
401 s = 0;
402 if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
403 s = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
404 } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
405 s = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
406 } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
407 s = ucs_i_jis_table[c - ucs_i_jis_table_min];
408 } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
409 s = ucs_r_jis_table[c - ucs_r_jis_table_min];
410 }
411 if (s <= 0) {
412 if (c == 0xa5) { /* YEN SIGN */
413 s = 0x1005c;
414 } else if (c == 0x203e) { /* OVER LINE */
415 s = 0x1007e;
416 } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
417 s = 0x2140;
418 } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
419 s = 0x2141;
420 } else if (c == 0x2225) { /* PARALLEL TO */
421 s = 0x2142;
422 } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */
423 s = 0x215d;
424 } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */
425 s = 0x2171;
426 } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */
427 s = 0x2172;
428 } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
429 s = 0x224c;
430 }
431 if (c == 0) {
432 s = 0;
433 } else if (s <= 0) {
434 s = -1;
435 }
436 } else if ((s >= 0x80 && s < 0x2121) || (s > 0x8080)) {
437 s = -1;
438 }
439 if (s >= 0) {
440 if (s < 0x80) { /* ASCII */
441 if ((filter->status & 0xff00) != 0) {
442 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
443 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
444 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
445 }
446 filter->status = 0;
447 CK((*filter->output_function)(s, filter->data));
448 } else if (s < 0x10000) { /* X 0208 */
449 if ((filter->status & 0xff00) != 0x200) {
450 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
451 CK((*filter->output_function)(0x24, filter->data)); /* '$' */
452 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
453 }
454 filter->status = 0x200;
455 CK((*filter->output_function)((s >> 8) & 0x7f, filter->data));
456 CK((*filter->output_function)(s & 0x7f, filter->data));
457 } else { /* X 0201 latin */
458 if ((filter->status & 0xff00) != 0x400) {
459 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
460 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
461 CK((*filter->output_function)(0x4a, filter->data)); /* 'J' */
462 }
463 filter->status = 0x400;
464 CK((*filter->output_function)(s & 0x7f, filter->data));
465 }
466 } else {
467 if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
468 CK(mbfl_filt_conv_illegal_output(c, filter));
469 }
470 }
471
472 return c;
473 }
474
475 int
mbfl_filt_conv_any_jis_flush(mbfl_convert_filter * filter)476 mbfl_filt_conv_any_jis_flush(mbfl_convert_filter *filter)
477 {
478 /* back to latin */
479 if ((filter->status & 0xff00) != 0) {
480 CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
481 CK((*filter->output_function)(0x28, filter->data)); /* '(' */
482 CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
483 }
484 filter->status &= 0xff;
485
486 if (filter->flush_function != NULL) {
487 return (*filter->flush_function)(filter->data);
488 }
489
490 return 0;
491 }
492
mbfl_filt_ident_jis(int c,mbfl_identify_filter * filter)493 static int mbfl_filt_ident_jis(int c, mbfl_identify_filter *filter)
494 {
495 retry:
496 switch (filter->status & 0xf) {
497 /* case 0x00: ASCII */
498 /* case 0x10: X 0201 latin */
499 /* case 0x20: X 0201 kana */
500 /* case 0x80: X 0208 */
501 /* case 0x90: X 0212 */
502 case 0:
503 if (c == 0x1b) {
504 filter->status += 2;
505 } else if (c == 0x0e) { /* "kana in" */
506 filter->status = 0x20;
507 } else if (c == 0x0f) { /* "kana out" */
508 filter->status = 0;
509 } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) { /* kanji first char */
510 filter->status += 1;
511 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
512 ;
513 } else {
514 filter->flag = 1; /* bad */
515 }
516 break;
517
518 /* case 0x81: X 0208 second char */
519 /* case 0x91: X 0212 second char */
520 case 1:
521 filter->status &= ~0xf;
522 if (c == 0x1b) {
523 goto retry;
524 } else if (c < 0x21 || c > 0x7e) { /* bad */
525 filter->flag = 1;
526 }
527 break;
528
529 /* ESC */
530 case 2:
531 if (c == 0x24) { /* '$' */
532 filter->status++;
533 } else if (c == 0x28) { /* '(' */
534 filter->status += 3;
535 } else {
536 filter->flag = 1; /* bad */
537 filter->status &= ~0xf;
538 goto retry;
539 }
540 break;
541
542 /* ESC $ */
543 case 3:
544 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
545 filter->status = 0x80;
546 } else if (c == 0x28) { /* '(' */
547 filter->status++;
548 } else {
549 filter->flag = 1; /* bad */
550 filter->status &= ~0xf;
551 goto retry;
552 }
553 break;
554
555 /* ESC $ ( */
556 case 4:
557 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
558 filter->status = 0x80;
559 } else if (c == 0x44) { /* 'D' */
560 filter->status = 0x90;
561 } else {
562 filter->flag = 1; /* bad */
563 filter->status &= ~0xf;
564 goto retry;
565 }
566 break;
567
568 /* ESC ( */
569 case 5:
570 if (c == 0x42 || c == 0x48) { /* 'B' or 'H' */
571 filter->status = 0;
572 } else if (c == 0x4a) { /* 'J' */
573 filter->status = 0x10;
574 } else if (c == 0x49) { /* 'I' */
575 filter->status = 0x20;
576 } else {
577 filter->flag = 1; /* bad */
578 filter->status &= ~0xf;
579 goto retry;
580 }
581 break;
582
583 default:
584 filter->status = 0;
585 break;
586 }
587
588 return c;
589 }
590
mbfl_filt_ident_2022jp(int c,mbfl_identify_filter * filter)591 static int mbfl_filt_ident_2022jp(int c, mbfl_identify_filter *filter)
592 {
593 retry:
594 switch (filter->status & 0xf) {
595 /* case 0x00: ASCII */
596 /* case 0x10: X 0201 latin */
597 /* case 0x80: X 0208 */
598 case 0:
599 if (c == 0x1b) {
600 filter->status += 2;
601 } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */
602 filter->status += 1;
603 } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
604 ;
605 } else {
606 filter->flag = 1; /* bad */
607 }
608 break;
609
610 /* case 0x81: X 0208 second char */
611 case 1:
612 if (c == 0x1b) {
613 filter->status++;
614 } else {
615 filter->status &= ~0xf;
616 if (c < 0x21 || c > 0x7e) { /* bad */
617 filter->flag = 1;
618 }
619 }
620 break;
621
622 /* ESC */
623 case 2:
624 if (c == 0x24) { /* '$' */
625 filter->status++;
626 } else if (c == 0x28) { /* '(' */
627 filter->status += 3;
628 } else {
629 filter->flag = 1; /* bad */
630 filter->status &= ~0xf;
631 goto retry;
632 }
633 break;
634
635 /* ESC $ */
636 case 3:
637 if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
638 filter->status = 0x80;
639 } else {
640 filter->flag = 1; /* bad */
641 filter->status &= ~0xf;
642 goto retry;
643 }
644 break;
645
646 /* ESC ( */
647 case 5:
648 if (c == 0x42) { /* 'B' */
649 filter->status = 0;
650 } else if (c == 0x4a) { /* 'J' */
651 filter->status = 0x10;
652 } else {
653 filter->flag = 1; /* bad */
654 filter->status &= ~0xf;
655 goto retry;
656 }
657 break;
658
659 default:
660 filter->status = 0;
661 break;
662 }
663
664 return c;
665 }
666