1 /** Network Kanji Filter. (PDS Version)
2 ************************************************************************
3 ** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
4 **
\e$BO"Mm@h!'
\e(B
\e$B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T@n!!;j
\e(B
5 **
\e$B!J
\e(BE-Mail Address: ichikawa@flab.fujitsu.co.jp
\e$B!K
\e(B
6 ** Copyright (C) 1996,1998
8 **
\e$BO"Mm@h!'
\e(B
\e$BN05eBg3X>pJs9)3X2J
\e(B
\e$B2OLn
\e(B
\e$B??<#
\e(B mime/X0208 support
9 **
\e$B!J
\e(BE-Mail Address: kono@ie.u-ryukyu.ac.jp
\e$B!K
\e(B
10 **
\e$BO"Mm@h!'
\e(B COW for DOS & Win16 & Win32 & OS/2
11 **
\e$B!J
\e(BE-Mail Address: GHG00637@niftyserve.or.p
\e$B!K
\e(B
13 **
\e$B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"
\e(B
14 **
\e$B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#
\e(B
15 **
\e$B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#
\e(B
16 **
\e$B1DMxMxMQ$b>e5-$KH?$7$J$$HO0O$G5v2D$7$^$9!#
\e(B
17 **
\e$B%P%$%J%j$NG[I[$N:]$K$O
\e(Bversion message
\e$B$rJ]B8$9$k$3$H$r>r7o$H$7$^$9!#
\e(B
18 **
\e$B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#
\e(B
20 ** Everyone is permitted to do anything on this program
21 ** including copying, modifying, improving,
22 ** as long as you don't try to pretend that you wrote it.
23 ** i.e., the above copyright notice has to appear in all copies.
24 ** Binary distribution requires original version messages.
25 ** You don't have to ask before copying, redistribution or publishing.
26 ** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
27 ***********************************************************************/
29 /***********************************************************************
30 ** UTF-8
\e$B%5%]!<%H$K$D$$$F
\e(B
31 **
\e$B=>Mh$N
\e(B nkf
\e$B$HF~$l$+$($F$=$N$^$^;H$($k$h$&$K$J$C$F$$$^$9
\e(B
32 ** nkf -e
\e$B$J$I$H$7$F5/F0$9$k$H!"<+F0H=JL$G
\e(B UTF-8
\e$B$HH=Dj$5$l$l$P!"
\e(B
33 **
\e$B$=$N$^$^
\e(B euc-jp
\e$B$KJQ49$5$l$^$9
\e(B
35 **
\e$B$^$@%P%0$,$"$k2DG=@-$,9b$$$G$9!#
\e(B
36 ** (
\e$BFC$K<+F0H=JL!"%3!<%I:.:_!"%(%i!<=hM}7O
\e(B)
38 **
\e$B2?$+LdBj$r8+$D$1$?$i!"
\e(B
39 ** E-Mail: furukawa@tcp-ip.or.jp
40 **
\e$B$^$G8fO"Mm$r$*4j$$$7$^$9!#
\e(B
41 ***********************************************************************/
42 /* $Id: nkf.c,v 1.38 2004/11/09 13:08:39 naruse Exp $ */
43 #define NKF_VERSION "2.0.4"
44 #define NKF_RELEASE_DATE "2004-11-09"
47 static char *CopyRight =
48 "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW, 2002-2004 Kono, Furukawa";
55 ** USAGE: nkf [flags] [file]
58 ** b Output is buffered (DEFAULT)
59 ** u Output is unbuffered
63 ** j Outout code is JIS 7 bit (DEFAULT SELECT)
64 ** s Output code is MS Kanji (DEFAULT SELECT)
65 ** e Output code is AT&T JIS (DEFAULT SELECT)
66 ** w Output code is AT&T JIS (DEFAULT SELECT)
67 ** l Output code is JIS 7bit and ISO8859-1 Latin-1
69 ** m MIME conversion for ISO-2022-JP
70 ** I Convert non ISO-2022-JP charactor to GETA by Pekoe <pekoe@lair.net>
71 ** i_ Output sequence to designate JIS-kanji (DEFAULT_J)
72 ** o_ Output sequence to designate single-byte roman characters (DEFAULT_R)
73 ** M MIME output conversion
75 ** r {de/en}crypt ROT13/47
79 ** T Text mode output (for MS-DOS)
81 ** x Do not convert X0201 kana into X0208
82 ** Z Convert X0208 alphabet to ASCII
87 ** B try to fix broken JIS, missing Escape
88 ** B[1-9] broken level
90 ** O Output to 'nkf.out' file or last file name
91 ** d Delete \r in line feed
92 ** c Add \r in line feed
93 ** -- other long option
94 ** -- ignore following option (don't use with -O )
98 #if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || defined(__MINGW32__)) && !defined(MSDOS)
100 #if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
113 #if defined(MSDOS) || defined(__OS2__)
120 #define setbinmode(fp) fsetbin(fp)
121 #else /* Microsoft C, Turbo C */
122 #define setbinmode(fp) setmode(fileno(fp), O_BINARY)
124 #else /* UNIX,OS/2 */
125 #define setbinmode(fp)
128 #ifdef _IOFBF /* SysV and MSDOS, Windows */
129 #define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size)
131 #define setvbuffer(fp, buf, size) setbuffer(fp, buf, size)
134 /*Borland C++ 4.5 EasyWin*/
135 #if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
144 /* added by satoru@isoternet.org */
147 #include <sys/stat.h>
148 #ifndef MSDOS /* UNIX, OS/2 */
152 #if defined(_MSC_VER) || defined(__MINGW32__) /* VC++, MinGW */
153 #include <sys/utime.h>
154 #elif defined(__TURBOC__) /* BCC */
156 #elif defined(LSI_C) /* LSI C */
168 /* state of output_mode and input_mode
185 /* Input Assumption */
189 #define LATIN1_INPUT 6
191 #define STRICT_MIME 8
196 #define JAPANESE_EUC 10
200 #define UTF8_INPUT 13
201 #define UTF16LE_INPUT 14
202 #define UTF16BE_INPUT 15
220 #define is_alnum(c) \
221 (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
223 #define HOLD_SIZE 1024
224 #define IOBUF_SIZE 16384
226 #define DEFAULT_J 'B'
227 #define DEFAULT_R 'B'
229 #define SJ0162 0x00e1 /* 01 - 62 ku offset */
230 #define SJ6394 0x0161 /* 63 - 94 ku offset */
232 #define RANGE_NUM_MAX 18
237 #if defined( UTF8_OUTPUT_ENABLE ) || defined( UTF8_INPUT_ENABLE )
238 #define sizeof_euc_utf8 94
239 #define sizeof_euc_to_utf8_1byte 94
240 #define sizeof_euc_to_utf8_2bytes 94
241 #define sizeof_utf8_to_euc_C2 64
242 #define sizeof_utf8_to_euc_E5B8 64
243 #define sizeof_utf8_to_euc_2bytes 112
244 #define sizeof_utf8_to_euc_3bytes 112
247 /* MIME preprocessor */
250 #ifdef EASYWIN /*Easy Win */
251 extern POINT _BufferSize;
254 /* function prototype */
256 #ifdef ANSI_C_PROTOTYPE
258 #define STATIC static
270 void (*status_func)PROTO((struct input_code *, int));
271 int (*iconv_func)PROTO((int c2, int c1, int c0));
275 STATIC char *input_codename = "";
277 STATIC int noconvert PROTO((FILE *f));
278 STATIC int kanji_convert PROTO((FILE *f));
279 STATIC int h_conv PROTO((FILE *f,int c2,int c1));
280 STATIC int push_hold_buf PROTO((int c2));
281 STATIC void set_iconv PROTO((int f, int (*iconv_func)()));
282 STATIC int s_iconv PROTO((int c2,int c1,int c0));
283 STATIC int s2e_conv PROTO((int c2, int c1, int *p2, int *p1));
284 STATIC int e_iconv PROTO((int c2,int c1,int c0));
285 #ifdef UTF8_INPUT_ENABLE
286 STATIC int w2e_conv PROTO((int c2,int c1,int c0,int *p2,int *p1));
287 STATIC int w_iconv PROTO((int c2,int c1,int c0));
288 STATIC int w_iconv16 PROTO((int c2,int c1,int c0));
289 STATIC int w_iconv_common PROTO((int c1,int c0,unsigned short **pp,int psize,int *p2,int *p1));
290 STATIC int ww16_conv PROTO((int c2, int c1, int c0));
292 #ifdef UTF8_OUTPUT_ENABLE
293 STATIC int e2w_conv PROTO((int c2,int c1));
294 STATIC void w_oconv PROTO((int c2,int c1));
295 STATIC void w_oconv16 PROTO((int c2,int c1));
297 STATIC void e_oconv PROTO((int c2,int c1));
298 STATIC void e2s_conv PROTO((int c2, int c1, int *p2, int *p1));
299 STATIC void s_oconv PROTO((int c2,int c1));
300 STATIC void j_oconv PROTO((int c2,int c1));
301 STATIC void fold_conv PROTO((int c2,int c1));
302 STATIC void cr_conv PROTO((int c2,int c1));
303 STATIC void z_conv PROTO((int c2,int c1));
304 STATIC void rot_conv PROTO((int c2,int c1));
305 STATIC void hira_conv PROTO((int c2,int c1));
306 STATIC void base64_conv PROTO((int c2,int c1));
307 STATIC void iso2022jp_check_conv PROTO((int c2,int c1));
308 STATIC void no_connection PROTO((int c2,int c1));
309 STATIC int no_connection2 PROTO((int c2,int c1,int c0));
311 STATIC void code_score PROTO((struct input_code *ptr));
312 STATIC void code_status PROTO((int c));
314 STATIC void std_putc PROTO((int c));
315 STATIC int std_getc PROTO((FILE *f));
316 STATIC int std_ungetc PROTO((int c,FILE *f));
318 STATIC int broken_getc PROTO((FILE *f));
319 STATIC int broken_ungetc PROTO((int c,FILE *f));
321 STATIC int mime_begin PROTO((FILE *f));
322 STATIC int mime_getc PROTO((FILE *f));
323 STATIC int mime_ungetc PROTO((int c,FILE *f));
325 STATIC int mime_begin_strict PROTO((FILE *f));
326 STATIC int mime_getc_buf PROTO((FILE *f));
327 STATIC int mime_ungetc_buf PROTO((int c,FILE *f));
328 STATIC int mime_integrity PROTO((FILE *f,unsigned char *p));
330 STATIC int base64decode PROTO((int c));
331 STATIC void mime_putc PROTO((int c));
332 STATIC void open_mime PROTO((int c));
333 STATIC void close_mime PROTO(());
334 STATIC void usage PROTO(());
335 STATIC void version PROTO(());
336 STATIC void options PROTO((unsigned char *c));
338 STATIC void reinit PROTO(());
343 static unsigned char stdibuf[IOBUF_SIZE];
344 static unsigned char stdobuf[IOBUF_SIZE];
345 static unsigned char hold_buf[HOLD_SIZE*2];
346 static int hold_count;
348 /* MIME preprocessor fifo */
350 #define MIME_BUF_SIZE (1024) /* 2^n ring buffer */
351 #define MIME_BUF_MASK (MIME_BUF_SIZE-1)
352 #define Fifo(n) mime_buf[(n)&MIME_BUF_MASK]
353 static unsigned char mime_buf[MIME_BUF_SIZE];
354 static unsigned int mime_top = 0;
355 static unsigned int mime_last = 0; /* decoded */
356 static unsigned int mime_input = 0; /* undecoded */
359 static int unbuf_f = FALSE;
360 static int estab_f = FALSE;
361 static int nop_f = FALSE;
362 static int binmode_f = TRUE; /* binary mode */
363 static int rot_f = FALSE; /* rot14/43 mode */
364 static int hira_f = FALSE; /* hira/kata henkan */
365 static int input_f = FALSE; /* non fixed input code */
366 static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */
367 static int mime_f = STRICT_MIME; /* convert MIME B base64 or Q */
368 static int mimebuf_f = FALSE; /* MIME buffered input */
369 static int broken_f = FALSE; /* convert ESC-less broken JIS */
370 static int iso8859_f = FALSE; /* ISO8859 through */
371 static int mimeout_f = FALSE; /* base64 mode */
372 #if defined(MSDOS) || defined(__OS2__)
373 static int x0201_f = TRUE; /* Assume JISX0201 kana */
375 static int x0201_f = NO_X0201; /* Assume NO JISX0201 */
377 static int iso2022jp_f = FALSE; /* convert ISO-2022-JP */
378 #ifdef UTF8_OUTPUT_ENABLE
379 static int unicode_bom_f= 0; /* Output Unicode BOM */
380 static int w_oconv16_LE = 0; /* utf-16 little endian */
381 static int ms_ucs_map_f = FALSE; /* Microsoft UCS Mapping Compatible */
385 #ifdef NUMCHAR_OPTION
387 #define CLASS_MASK 0x0f000000
388 #define CLASS_UTF16 0x01000000
392 static int cap_f = FALSE;
393 static int (*i_cgetc)PROTO((FILE *)) = std_getc; /* input of cgetc */
394 static int (*i_cungetc)PROTO((int c ,FILE *f)) = std_ungetc;
395 STATIC int cap_getc PROTO((FILE *f));
396 STATIC int cap_ungetc PROTO((int c,FILE *f));
398 static int url_f = FALSE;
399 static int (*i_ugetc)PROTO((FILE *)) = std_getc; /* input of ugetc */
400 static int (*i_uungetc)PROTO((int c ,FILE *f)) = std_ungetc;
401 STATIC int url_getc PROTO((FILE *f));
402 STATIC int url_ungetc PROTO((int c,FILE *f));
404 static int numchar_f = FALSE;
405 static int (*i_ngetc)PROTO((FILE *)) = std_getc; /* input of ugetc */
406 static int (*i_nungetc)PROTO((int c ,FILE *f)) = std_ungetc;
407 STATIC int numchar_getc PROTO((FILE *f));
408 STATIC int numchar_ungetc PROTO((int c,FILE *f));
412 static int noout_f = FALSE;
413 STATIC void no_putc PROTO((int c));
414 static int debug_f = FALSE;
415 STATIC void debug PROTO((char *str));
418 static int guess_f = FALSE;
419 STATIC void print_guessed_code PROTO((char *filename));
420 STATIC void set_input_codename PROTO((char *codename));
421 static int is_inputcode_mixed = FALSE;
422 static int is_inputcode_set = FALSE;
425 static int exec_f = 0;
428 #ifdef SHIFTJIS_CP932
429 STATIC int cp932_f = TRUE;
430 #define CP932_TABLE_BEGIN (0xfa)
431 #define CP932_TABLE_END (0xfc)
433 STATIC int cp932inv_f = FALSE;
434 #define CP932INV_TABLE_BEGIN (0xed)
435 #define CP932INV_TABLE_END (0xee)
437 #endif /* SHIFTJIS_CP932 */
439 STATIC unsigned char prefix_table[256];
441 STATIC void e_status PROTO((struct input_code *, int));
442 STATIC void s_status PROTO((struct input_code *, int));
444 #ifdef UTF8_INPUT_ENABLE
445 STATIC void w_status PROTO((struct input_code *, int));
446 STATIC void w16_status PROTO((struct input_code *, int));
447 static int utf16_mode = UTF16LE_INPUT;
450 struct input_code input_code_list[] = {
451 {"EUC-JP", 0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
452 {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
453 {"UTF-8", 0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
454 {"UTF-16", 0, 0, 0, {0, 0, 0}, w16_status, w_iconv16, 0},
458 static int mimeout_mode = 0;
459 static int base64_count = 0;
461 /* X0208 -> ASCII converter */
464 static int f_line = 0; /* chars in line */
465 static int f_prev = 0;
466 static int fold_preserve_f = FALSE; /* preserve new lines */
467 static int fold_f = FALSE;
468 static int fold_len = 0;
471 static unsigned char kanji_intro = DEFAULT_J;
472 static unsigned char ascii_intro = DEFAULT_R;
476 #define FOLD_MARGIN 10
477 #define DEFAULT_FOLD 60
479 static int fold_margin = FOLD_MARGIN;
483 #ifdef DEFAULT_CODE_JIS
484 # define DEFAULT_CONV j_oconv
486 #ifdef DEFAULT_CODE_SJIS
487 # define DEFAULT_CONV s_oconv
489 #ifdef DEFAULT_CODE_EUC
490 # define DEFAULT_CONV e_oconv
492 #ifdef DEFAULT_CODE_UTF8
493 # define DEFAULT_CONV w_oconv
496 /* process default */
497 static void (*output_conv)PROTO((int c2,int c1)) = DEFAULT_CONV;
499 static void (*oconv)PROTO((int c2,int c1)) = no_connection;
500 /* s_iconv or oconv */
501 static int (*iconv)PROTO((int c2,int c1,int c0)) = no_connection2;
503 static void (*o_zconv)PROTO((int c2,int c1)) = no_connection;
504 static void (*o_fconv)PROTO((int c2,int c1)) = no_connection;
505 static void (*o_crconv)PROTO((int c2,int c1)) = no_connection;
506 static void (*o_rot_conv)PROTO((int c2,int c1)) = no_connection;
507 static void (*o_hira_conv)PROTO((int c2,int c1)) = no_connection;
508 static void (*o_base64conv)PROTO((int c2,int c1)) = no_connection;
509 static void (*o_iso2022jp_check_conv)PROTO((int c2,int c1)) = no_connection;
511 /* static redirections */
513 static void (*o_putc)PROTO((int c)) = std_putc;
515 static int (*i_getc)PROTO((FILE *f)) = std_getc; /* general input */
516 static int (*i_ungetc)PROTO((int c,FILE *f)) =std_ungetc;
518 static int (*i_bgetc)PROTO((FILE *)) = std_getc; /* input of mgetc */
519 static int (*i_bungetc)PROTO((int c ,FILE *f)) = std_ungetc;
521 static void (*o_mputc)PROTO((int c)) = std_putc ; /* output of mputc */
523 static int (*i_mgetc)PROTO((FILE *)) = std_getc; /* input of mgetc */
524 static int (*i_mungetc)PROTO((int c ,FILE *f)) = std_ungetc;
526 /* for strict mime */
527 static int (*i_mgetc_buf)PROTO((FILE *)) = std_getc; /* input of mgetc_buf */
528 static int (*i_mungetc_buf)PROTO((int c,FILE *f)) = std_ungetc;
531 static int output_mode = ASCII, /* output kanji mode */
532 input_mode = ASCII, /* input kanji mode */
533 shift_mode = FALSE; /* TRUE shift out, or X0201 */
534 static int mime_decode_mode = FALSE; /* MIME mode B base64, Q hex */
536 /* X0201 / X0208 conversion tables */
538 /* X0201 kana conversion table */
541 unsigned char cv[]= {
542 0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
543 0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
544 0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
545 0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
546 0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
547 0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
548 0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
549 0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
550 0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
551 0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
552 0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
553 0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
554 0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
555 0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
556 0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
557 0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
561 /* X0201 kana conversion table for daguten */
564 unsigned char dv[]= {
565 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
566 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
567 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
568 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
569 0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74,
570 0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
571 0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
572 0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
573 0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
574 0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
575 0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
576 0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
577 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
578 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
579 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
580 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
583 /* X0201 kana conversion table for han-daguten */
586 unsigned char ev[]= {
587 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
588 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
589 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
590 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
591 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
592 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
593 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
594 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
595 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
596 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
597 0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
598 0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
599 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
600 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
601 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
602 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
606 /* X0208 kigou conversion table */
607 /* 0x8140 - 0x819e */
609 unsigned char fv[] = {
611 0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
612 0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
613 0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
614 0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
615 0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
616 0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
617 0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
618 0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
619 0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
620 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
621 0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
622 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
628 static int file_out = FALSE;
630 static int overwrite = FALSE;
633 static int crmode_f = 0; /* CR, NL, CRLF */
634 #ifdef EASYWIN /*Easy Win */
635 static int end_check;
650 #ifdef EASYWIN /*Easy Win */
651 _BufferSize.y = 400;/*Set Scroll Buffer Size*/
654 for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
655 cp = (unsigned char *)*argv;
660 if (pipe(fds) < 0 || (pid = fork()) < 0){
671 execvp(argv[1], &argv[1]);
685 if(x0201_f == WISH_TRUE)
686 x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
688 if (binmode_f == TRUE)
690 if (freopen("","wb",stdout) == NULL)
697 setbuf(stdout, (char *) NULL);
699 setvbuffer(stdout, stdobuf, IOBUF_SIZE);
702 if (binmode_f == TRUE)
704 if (freopen("","rb",stdin) == NULL) return (-1);
708 setvbuffer(stdin, stdibuf, IOBUF_SIZE);
712 kanji_convert(stdin);
713 if (guess_f) print_guessed_code(NULL);
718 if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
727 /* reopen file for stdout */
728 if (file_out == TRUE) {
731 outfname = malloc(strlen(origfname)
732 + strlen(".nkftmpXXXXXX")
738 strcpy(outfname, origfname);
742 for (i = strlen(outfname); i; --i){
743 if (outfname[i - 1] == '/'
744 || outfname[i - 1] == '\\'){
750 strcat(outfname, "ntXXXXXX");
752 fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC,
755 strcat(outfname, ".nkftmpXXXXXX");
756 fd = mkstemp(outfname);
759 || (fd_backup = dup(fileno(stdout))) < 0
760 || dup2(fd, fileno(stdout)) < 0
771 outfname = "nkf.out";
774 if(freopen(outfname, "w", stdout) == NULL) {
778 if (binmode_f == TRUE) {
780 if (freopen("","wb",stdout) == NULL)
787 if (binmode_f == TRUE)
789 if (freopen("","rb",fin) == NULL)
794 setvbuffer(fin, stdibuf, IOBUF_SIZE);
798 char *filename = NULL;
800 if (nfiles > 1) filename = origfname;
801 if (guess_f) print_guessed_code(filename);
807 #if defined(MSDOS) && !defined(__MINGW32__)
815 if (dup2(fd_backup, fileno(stdout)) < 0){
818 if (stat(origfname, &sb)) {
819 fprintf(stderr, "Can't stat %s\n", origfname);
821 /*
\e$B%Q!<%_%C%7%g%s$rI|85
\e(B */
822 if (chmod(outfname, sb.st_mode)) {
823 fprintf(stderr, "Can't set permission %s\n", outfname);
826 /*
\e$B%?%$%`%9%?%s%W$rI|85
\e(B */
827 #if defined(MSDOS) && !defined(__MINGW32__)
828 tb[0] = tb[1] = sb.st_mtime;
829 if (utime(outfname, tb)) {
830 fprintf(stderr, "Can't set timestamp %s\n", outfname);
833 tb.actime = sb.st_atime;
834 tb.modtime = sb.st_mtime;
835 if (utime(outfname, &tb)) {
836 fprintf(stderr, "Can't set timestamp %s\n", outfname);
840 if (unlink(origfname)){
844 if (rename(outfname, origfname)) {
846 fprintf(stderr, "Can't rename %s to %s\n",
847 outfname, origfname);
855 #ifdef EASYWIN /*Easy Win */
856 if (file_out == FALSE)
857 scanf("%d",&end_check);
860 #else /* for Other OS */
861 if (file_out == TRUE)
891 {"katakana-hiragana","h3"},
893 #ifdef UTF8_OUTPUT_ENABLE
898 #ifdef UTF8_INPUT_ENABLE
900 {"utf16-input", "W16"},
909 #ifdef NUMCHAR_OPTION
910 {"numchar-input", ""},
916 #ifdef SHIFTJIS_CP932
927 static int option_mode = 0;
946 case '-': /* literal options */
947 if (!*cp) { /* ignore the rest of arguments */
951 for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
953 p = (unsigned char *)long_option[i].name;
954 for (j=0;*p && (*p != '=') && *p == cp[j];p++, j++);
955 if (!*p || *p == cp[j]){
962 cp = (unsigned char *)long_option[i].alias;
965 if (strcmp(long_option[i].name, "overwrite") == 0){
972 if (strcmp(long_option[i].name, "cap-input") == 0){
976 if (strcmp(long_option[i].name, "url-input") == 0){
981 #ifdef NUMCHAR_OPTION
982 if (strcmp(long_option[i].name, "numchar-input") == 0){
988 if (strcmp(long_option[i].name, "no-output") == 0){
992 if (strcmp(long_option[i].name, "debug") == 0){
997 #ifdef SHIFTJIS_CP932
998 if (strcmp(long_option[i].name, "no-cp932") == 0){
1002 if (strcmp(long_option[i].name, "cp932inv") == 0){
1008 if (strcmp(long_option[i].name, "exec-in") == 0){
1012 if (strcmp(long_option[i].name, "exec-out") == 0){
1017 #ifdef UTF8_OUTPUT_ENABLE
1018 if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
1019 ms_ucs_map_f = TRUE;
1023 if (strcmp(long_option[i].name, "prefix=") == 0){
1024 if (*p == '=' && ' ' < p[1] && p[1] < 128){
1025 for (i = 2; ' ' < p[i] && p[i] < 128; i++){
1026 prefix_table[p[i]] = p[1];
1033 case 'b': /* buffered mode */
1036 case 'u': /* non bufferd mode */
1039 case 't': /* transparent mode */
1042 case 'j': /* JIS output */
1044 output_conv = j_oconv;
1046 case 'e': /* AT&T EUC output */
1047 output_conv = e_oconv;
1049 case 's': /* SJIS output */
1050 output_conv = s_oconv;
1052 case 'l': /* ISO8859 Latin-1 support, no conversion */
1053 iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
1054 input_f = LATIN1_INPUT;
1056 case 'i': /* Kanji IN ESC-$-@/B */
1057 if (*cp=='@'||*cp=='B')
1058 kanji_intro = *cp++;
1060 case 'o': /* ASCII IN ESC-(-J/B */
1061 if (*cp=='J'||*cp=='B'||*cp=='H')
1062 ascii_intro = *cp++;
1069 if ('9'>= *cp && *cp>='0')
1070 hira_f |= (*cp++ -'0');
1077 #if defined(MSDOS) || defined(__OS2__)
1092 #ifdef UTF8_OUTPUT_ENABLE
1093 case 'w': /* UTF-8 output */
1094 if ('1'== cp[0] && '6'==cp[1]) {
1095 output_conv = w_oconv16; cp+=2;
1097 unicode_bom_f=2; cp++;
1100 unicode_bom_f=1; cp++;
1102 } else if (cp[0] == 'B') {
1103 unicode_bom_f=2; cp++;
1105 unicode_bom_f=1; cp++;
1108 } else if (cp[0] == '8') {
1109 output_conv = w_oconv; cp++;
1112 unicode_bom_f=1; cp++;
1115 output_conv = w_oconv;
1118 #ifdef UTF8_INPUT_ENABLE
1119 case 'W': /* UTF-8 input */
1120 if ('1'== cp[0] && '6'==cp[1]) {
1121 input_f = UTF16LE_INPUT;
1124 } else if (cp[0] == 'B') {
1126 input_f = UTF16BE_INPUT;
1128 } else if (cp[0] == '8') {
1130 input_f = UTF8_INPUT;
1132 input_f = UTF8_INPUT;
1135 /* Input code assumption */
1136 case 'J': /* JIS input */
1137 case 'E': /* AT&T EUC input */
1138 input_f = JIS_INPUT;
1140 case 'S': /* MS Kanji input */
1141 input_f = SJIS_INPUT;
1142 if (x0201_f==NO_X0201) x0201_f=TRUE;
1144 case 'Z': /* Convert X0208 alphabet to asii */
1145 /* bit:0 Convert X0208
1146 bit:1 Convert Kankaku to one space
1147 bit:2 Convert Kankaku to two spaces
1148 bit:3 Convert HTML Entity
1150 if ('9'>= *cp && *cp>='0')
1151 alpha_f |= 1<<(*cp++ -'0');
1155 case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
1156 x0201_f = FALSE; /* No X0201->X0208 conversion */
1158 ESC-(-I in JIS, EUC, MS Kanji
1159 SI/SO in JIS, EUC, MS Kanji
1160 SSO in EUC, JIS, not in MS Kanji
1161 MS Kanji (0xa0-0xdf)
1163 ESC-(-I in JIS (0x20-0x5f)
1164 SSO in EUC (0xa0-0xdf)
1165 0xa0-0xd in MS Kanji (0xa0-0xdf)
1168 case 'X': /* Assume X0201 kana */
1169 /* Default value is NO_X0201 for EUC/MS-Kanji mix */
1172 case 'F': /* prserve new lines */
1173 fold_preserve_f = TRUE;
1174 case 'f': /* folding -f60 or -f */
1177 while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
1179 fold_len += *cp++ - '0';
1181 if (!(0<fold_len && fold_len<BUFSIZ))
1182 fold_len = DEFAULT_FOLD;
1186 while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
1188 fold_margin += *cp++ - '0';
1192 case 'm': /* MIME support */
1193 if (*cp=='B'||*cp=='Q') {
1194 mime_decode_mode = *cp++;
1195 mimebuf_f = FIXED_MIME;
1196 } else if (*cp=='N') {
1197 mime_f = TRUE; cp++;
1198 } else if (*cp=='S') {
1199 mime_f = STRICT_MIME; cp++;
1200 } else if (*cp=='0') {
1201 mime_f = FALSE; cp++;
1204 case 'M': /* MIME output */
1207 mimeout_f = FIXED_MIME; cp++;
1208 } else if (*cp=='Q') {
1210 mimeout_f = FIXED_MIME; cp++;
1215 case 'B': /* Broken JIS support */
1217 bit:1 allow any x on ESC-(-x or ESC-$-x
1218 bit:2 reset to ascii on NL
1220 if ('9'>= *cp && *cp>='0')
1221 broken_f |= 1<<(*cp++ -'0');
1226 case 'O':/* for Output file */
1230 case 'c':/* add cr code */
1233 case 'd':/* delete cr code */
1236 case 'I': /* ISO-2022-JP output */
1239 case 'L': /* line mode */
1240 if (*cp=='u') { /* unix */
1241 crmode_f = NL; cp++;
1242 } else if (*cp=='m') { /* mac */
1243 crmode_f = CR; cp++;
1244 } else if (*cp=='w') { /* windows */
1245 crmode_f = CRLF; cp++;
1246 } else if (*cp=='0') { /* no conversion */
1256 /* module muliple options in a string are allowed for Perl moudle */
1257 while(*cp && *cp!='-') cp++;
1261 /* bogus option but ignored */
1267 #ifdef ANSI_C_PROTOTYPE
1268 struct input_code * find_inputcode_byfunc(int (*iconv_func)(int c2,int c1,int c0))
1270 struct input_code * find_inputcode_byfunc(iconv_func)
1271 int (*iconv_func)();
1275 struct input_code *p = input_code_list;
1277 if (iconv_func == p->iconv_func){
1286 #ifdef ANSI_C_PROTOTYPE
1287 void set_iconv(int f, int (*iconv_func)(int c2,int c1,int c0))
1289 void set_iconv(f, iconv_func)
1291 int (*iconv_func)();
1295 static int (*iconv_for_check)() = 0;
1297 #ifdef INPUT_CODE_FIX
1305 #ifdef INPUT_CODE_FIX
1306 && (f == -TRUE || !input_f) /* -TRUE means "FORCE" */
1312 if (estab_f && iconv_for_check != iconv){
1313 struct input_code *p = find_inputcode_byfunc(iconv);
1315 set_input_codename(p->name);
1316 debug(input_codename);
1318 iconv_for_check = iconv;
1323 #define SCORE_L2 (1) /*
\e$BBh
\e(B2
\e$B?e=`4A;z
\e(B */
1324 #define SCORE_KANA (SCORE_L2 << 1) /*
\e$B$$$o$f$kH>3Q%+%J
\e(B */
1325 #define SCORE_DEPEND (SCORE_KANA << 1) /*
\e$B5!<o0MB8J8;z
\e(B */
1326 #ifdef SHIFTJIS_CP932
1327 #define SCORE_CP932 (SCORE_DEPEND << 1) /* CP932
\e$B$K$h$kFI$_49$(
\e(B */
1328 #define SCORE_NO_EXIST (SCORE_CP932 << 1) /*
\e$BB8:_$7$J$$J8;z
\e(B */
1330 #define SCORE_NO_EXIST (SCORE_DEPEND << 1) /*
\e$BB8:_$7$J$$J8;z
\e(B */
1332 #define SCORE_iMIME (SCORE_NO_EXIST << 1) /* MIME
\e$B$K$h$k;XDj
\e(B */
1333 #define SCORE_ERROR (SCORE_iMIME << 1) /*
\e$B%(%i!<
\e(B */
1335 #define SCORE_INIT (SCORE_iMIME)
1337 int score_table_A0[] = {
1340 0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1341 SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
1344 int score_table_F0[] = {
1345 SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
1346 SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
1347 SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1348 SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
1351 void set_code_score(ptr, score)
1352 struct input_code *ptr;
1356 ptr->score |= score;
1360 void clr_code_score(ptr, score)
1361 struct input_code *ptr;
1365 ptr->score &= ~score;
1369 void code_score(ptr)
1370 struct input_code *ptr;
1372 int c2 = ptr->buf[0];
1373 int c1 = ptr->buf[1];
1375 set_code_score(ptr, SCORE_ERROR);
1376 }else if (c2 == SSO){
1377 set_code_score(ptr, SCORE_KANA);
1378 #ifdef UTF8_OUTPUT_ENABLE
1379 }else if (!e2w_conv(c2, c1)){
1380 set_code_score(ptr, SCORE_NO_EXIST);
1382 }else if ((c2 & 0x70) == 0x20){
1383 set_code_score(ptr, score_table_A0[c2 & 0x0f]);
1384 }else if ((c2 & 0x70) == 0x70){
1385 set_code_score(ptr, score_table_F0[c2 & 0x0f]);
1386 }else if ((c2 & 0x70) >= 0x50){
1387 set_code_score(ptr, SCORE_L2);
1391 void status_disable(ptr)
1392 struct input_code *ptr;
1397 if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
1400 void status_push_ch(ptr, c)
1401 struct input_code *ptr;
1404 ptr->buf[ptr->index++] = c;
1407 void status_clear(ptr)
1408 struct input_code *ptr;
1414 void status_reset(ptr)
1415 struct input_code *ptr;
1418 ptr->score = SCORE_INIT;
1421 void status_reinit(ptr)
1422 struct input_code *ptr;
1425 ptr->_file_stat = 0;
1428 void status_check(ptr, c)
1429 struct input_code *ptr;
1432 if (c <= DEL && estab_f){
1437 void s_status(ptr, c)
1438 struct input_code *ptr;
1443 status_check(ptr, c);
1448 #ifdef NUMCHAR_OPTION
1449 }else if ((c & CLASS_MASK) == CLASS_UTF16){
1452 }else if (0xa1 <= c && c <= 0xdf){
1453 status_push_ch(ptr, SSO);
1454 status_push_ch(ptr, c);
1457 }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xef)){
1459 status_push_ch(ptr, c);
1460 #ifdef SHIFTJIS_CP932
1462 && CP932_TABLE_BEGIN <= c && c <= CP932_TABLE_END){
1464 status_push_ch(ptr, c);
1465 #endif /* SHIFTJIS_CP932 */
1467 status_disable(ptr);
1471 if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1472 status_push_ch(ptr, c);
1473 s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
1477 status_disable(ptr);
1480 #ifdef SHIFTJIS_CP932
1482 if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1483 status_push_ch(ptr, c);
1484 if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0){
1485 set_code_score(ptr, SCORE_CP932);
1490 status_disable(ptr);
1492 #endif /* SHIFTJIS_CP932 */
1496 void e_status(ptr, c)
1497 struct input_code *ptr;
1502 status_check(ptr, c);
1507 #ifdef NUMCHAR_OPTION
1508 }else if ((c & CLASS_MASK) == CLASS_UTF16){
1511 }else if (SSO == c || (0xa1 <= c && c <= 0xfe)){
1513 status_push_ch(ptr, c);
1515 status_disable(ptr);
1519 if (0xa1 <= c && c <= 0xfe){
1520 status_push_ch(ptr, c);
1524 status_disable(ptr);
1530 #ifdef UTF8_INPUT_ENABLE
1531 void w16_status(ptr, c)
1532 struct input_code *ptr;
1539 if (ptr->_file_stat == 0){
1540 if (c == 0xfe || c == 0xff){
1542 status_push_ch(ptr, c);
1543 ptr->_file_stat = 1;
1545 status_disable(ptr);
1546 ptr->_file_stat = -1;
1548 }else if (ptr->_file_stat > 0){
1550 status_push_ch(ptr, c);
1551 }else if (ptr->_file_stat < 0){
1552 status_disable(ptr);
1558 status_disable(ptr);
1559 ptr->_file_stat = -1;
1561 status_push_ch(ptr, c);
1568 if (ptr->stat != c && (c == 0xfe || c == 0xff)){
1569 status_push_ch(ptr, c);
1572 status_disable(ptr);
1573 ptr->_file_stat = -1;
1579 void w_status(ptr, c)
1580 struct input_code *ptr;
1585 status_check(ptr, c);
1590 #ifdef NUMCHAR_OPTION
1591 }else if ((c & CLASS_MASK) == CLASS_UTF16){
1594 }else if (0xc0 <= c && c <= 0xdf){
1596 status_push_ch(ptr, c);
1597 }else if (0xe0 <= c && c <= 0xef){
1599 status_push_ch(ptr, c);
1601 status_disable(ptr);
1606 if (0x80 <= c && c <= 0xbf){
1607 status_push_ch(ptr, c);
1608 if (ptr->index > ptr->stat){
1609 int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
1610 && ptr->buf[2] == 0xbf);
1611 w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
1612 &ptr->buf[0], &ptr->buf[1]);
1619 status_disable(ptr);
1630 int action_flag = 1;
1631 struct input_code *result = 0;
1632 struct input_code *p = input_code_list;
1634 (p->status_func)(p, c);
1637 }else if(p->stat == 0){
1648 if (result && !estab_f){
1649 set_iconv(TRUE, result->iconv_func);
1650 }else if (c <= DEL){
1651 struct input_code *ptr = input_code_list;
1661 #define STD_GC_BUFSIZE (256)
1662 int std_gc_buf[STD_GC_BUFSIZE];
1672 return std_gc_buf[--std_gc_ndx];
1684 if (std_gc_ndx == STD_GC_BUFSIZE){
1687 std_gc_buf[std_gc_ndx++] = c;
1707 while ((c = (*i_getc)(f)) != EOF)
1716 oconv = output_conv;
1719 /* replace continucation module, from output side */
1721 /* output redicrection */
1723 if (noout_f || guess_f){
1730 if (mimeout_f == TRUE) {
1731 o_base64conv = oconv; oconv = base64_conv;
1733 /* base64_count = 0; */
1737 o_crconv = oconv; oconv = cr_conv;
1740 o_rot_conv = oconv; oconv = rot_conv;
1743 o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
1746 o_hira_conv = oconv; oconv = hira_conv;
1749 o_fconv = oconv; oconv = fold_conv;
1752 if (alpha_f || x0201_f) {
1753 o_zconv = oconv; oconv = z_conv;
1757 i_ungetc = std_ungetc;
1758 /* input redicrection */
1761 i_cgetc = i_getc; i_getc = cap_getc;
1762 i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
1765 i_ugetc = i_getc; i_getc = url_getc;
1766 i_uungetc = i_ungetc; i_ungetc= url_ungetc;
1769 #ifdef NUMCHAR_OPTION
1771 i_ngetc = i_getc; i_getc = numchar_getc;
1772 i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
1775 if (mime_f && mimebuf_f==FIXED_MIME) {
1776 i_mgetc = i_getc; i_getc = mime_getc;
1777 i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
1780 i_bgetc = i_getc; i_getc = broken_getc;
1781 i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
1783 if (input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
1784 set_iconv(-TRUE, e_iconv);
1785 } else if (input_f == SJIS_INPUT) {
1786 set_iconv(-TRUE, s_iconv);
1787 #ifdef UTF8_INPUT_ENABLE
1788 } else if (input_f == UTF8_INPUT) {
1789 set_iconv(-TRUE, w_iconv);
1790 } else if (input_f == UTF16LE_INPUT) {
1791 set_iconv(-TRUE, w_iconv16);
1794 set_iconv(FALSE, e_iconv);
1798 struct input_code *p = input_code_list;
1806 Conversion main loop. Code detection only.
1816 module_connection();
1821 output_mode = ASCII;
1824 #define NEXT continue /* no output, get next */
1825 #define SEND ; /* output c1 and c2, get next */
1826 #define LAST break /* end of loop, go closing */
1828 while ((c1 = (*i_getc)(f)) != EOF) {
1833 /* in case of 8th bit is on */
1835 /* in case of not established yet */
1836 /* It is still ambiguious */
1837 if (h_conv(f, c2, c1)==EOF)
1843 /* in case of already established */
1845 /* ignore bogus code */
1851 /* second byte, 7 bit code */
1852 /* it might be kanji shitfted */
1853 if ((c1 == DEL) || (c1 <= SPACE)) {
1854 /* ignore bogus first code */
1862 #ifdef UTF8_INPUT_ENABLE
1871 #ifdef NUMCHAR_OPTION
1872 } else if ((c1 & CLASS_MASK) == CLASS_UTF16){
1875 } else if (c1 > DEL) {
1877 if (!estab_f && !iso8859_f) {
1878 /* not established yet */
1881 } else { /* estab_f==TRUE */
1886 } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
1887 /* SJIS X0201 Case... */
1888 if(iso2022jp_f && x0201_f==NO_X0201) {
1889 (*oconv)(GETA1, GETA2);
1896 } else if (c1==SSO && iconv != s_iconv) {
1897 /* EUC X0201 Case */
1898 c1 = (*i_getc)(f); /* skip SSO */
1900 if (SSP<=c1 && c1<0xe0) {
1901 if(iso2022jp_f && x0201_f==NO_X0201) {
1902 (*oconv)(GETA1, GETA2);
1909 } else { /* bogus code, skip SSO and one byte */
1913 /* already established */
1918 } else if ((c1 > SPACE) && (c1 != DEL)) {
1919 /* in case of Roman characters */
1921 /* output 1 shifted byte */
1925 } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
1926 /* output 1 shifted byte */
1927 if(iso2022jp_f && x0201_f==NO_X0201) {
1928 (*oconv)(GETA1, GETA2);
1935 /* look like bogus code */
1938 } else if (input_mode == X0208) {
1939 /* in case of Kanji shifted */
1942 } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
1943 /* Check MIME code */
1944 if ((c1 = (*i_getc)(f)) == EOF) {
1947 } else if (c1 == '?') {
1948 /* =? is mime conversion start sequence */
1949 if(mime_f == STRICT_MIME) {
1950 /* check in real detail */
1951 if (mime_begin_strict(f) == EOF)
1955 } else if (mime_begin(f) == EOF)
1965 /* normal ASCII code */
1968 } else if (c1 == SI) {
1971 } else if (c1 == SO) {
1974 } else if (c1 == ESC ) {
1975 if ((c1 = (*i_getc)(f)) == EOF) {
1976 /* (*oconv)(0, ESC); don't send bogus code */
1978 } else if (c1 == '$') {
1979 if ((c1 = (*i_getc)(f)) == EOF) {
1981 (*oconv)(0, ESC); don't send bogus code
1982 (*oconv)(0, '$'); */
1984 } else if (c1 == '@'|| c1 == 'B') {
1985 /* This is kanji introduction */
1988 set_input_codename("ISO-2022-JP");
1989 debug(input_codename);
1991 } else if (c1 == '(') {
1992 if ((c1 = (*i_getc)(f)) == EOF) {
1993 /* don't send bogus code
1999 } else if (c1 == '@'|| c1 == 'B') {
2000 /* This is kanji introduction */
2005 /* could be some special code */
2012 } else if (broken_f&0x2) {
2013 /* accept any ESC-(-x as broken code ... */
2023 } else if (c1 == '(') {
2024 if ((c1 = (*i_getc)(f)) == EOF) {
2025 /* don't send bogus code
2027 (*oconv)(0, '('); */
2031 /* This is X0201 kana introduction */
2032 input_mode = X0201; shift_mode = X0201;
2034 } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
2035 /* This is X0208 kanji introduction */
2036 input_mode = ASCII; shift_mode = FALSE;
2038 } else if (broken_f&0x2) {
2039 input_mode = ASCII; shift_mode = FALSE;
2044 /* maintain various input_mode here */
2048 } else if ( c1 == 'N' || c1 == 'n' ){
2050 c3 = (*i_getc)(f); /* skip SS2 */
2051 if ( (SPACE<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
2066 } else if ((c1 == NL || c1 == CR) && broken_f&4) {
2067 input_mode = ASCII; set_iconv(FALSE, 0);
2073 if (input_mode == X0208)
2074 (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
2075 else if (input_mode)
2076 (*oconv)(input_mode, c1); /* other special case */
2077 else if ((*iconv)(c2, c1, 0) < 0){ /* can be EUC/SJIS */
2078 int c0 = (*i_getc)(f);
2081 (*iconv)(c2, c1, c0);
2087 /* goto next_word */
2091 (*iconv)(EOF, 0, 0);
2104 /** it must NOT be in the kanji shifte sequence */
2105 /** it must NOT be written in JIS7 */
2106 /** and it must be after 2 byte 8bit code */
2113 while ((c1 = (*i_getc)(f)) != EOF) {
2119 if (push_hold_buf(c1) == EOF || estab_f){
2125 struct input_code *p = input_code_list;
2126 struct input_code *result = p;
2131 if (p->score < result->score){
2136 set_iconv(FALSE, result->iconv_func);
2141 ** 1) EOF is detected, or
2142 ** 2) Code is established, or
2143 ** 3) Buffer is FULL (but last word is pushed)
2145 ** in 1) and 3) cases, we continue to use
2146 ** Kanji codes by oconv and leave estab_f unchanged.
2151 while (wc < hold_count){
2152 c2 = hold_buf[wc++];
2154 #ifdef NUMCHAR_OPTION
2155 || (c2 & CLASS_MASK) == CLASS_UTF16
2160 }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
2161 (*iconv)(X0201, c2, 0);
2164 if (wc < hold_count){
2165 c1 = hold_buf[wc++];
2174 if ((*iconv)(c2, c1, 0) < 0){
2176 if (wc < hold_count){
2177 c0 = hold_buf[wc++];
2186 (*iconv)(c2, c1, c0);
2199 if (hold_count >= HOLD_SIZE*2)
2201 hold_buf[hold_count++] = c2;
2202 return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
2205 int s2e_conv(c2, c1, p2, p1)
2209 #ifdef SHIFTJIS_CP932
2210 if (cp932_f && CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END){
2211 extern unsigned short shiftjis_cp932[3][189];
2212 c1 = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
2213 if (c1 == 0) return 1;
2217 #endif /* SHIFTJIS_CP932 */
2218 c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
2220 c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
2237 } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2240 int ret = s2e_conv(c2, c1, &c2, &c1);
2241 if (ret) return ret;
2254 } else if (c2 == SSO){
2257 } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2267 #ifdef UTF8_INPUT_ENABLE
2269 w2e_conv(c2, c1, c0, p2, p1)
2273 extern unsigned short * utf8_to_euc_2bytes[];
2274 extern unsigned short ** utf8_to_euc_3bytes[];
2277 if (0xc0 <= c2 && c2 <= 0xef) {
2278 unsigned short **pp;
2281 if (c0 == 0) return -1;
2282 pp = utf8_to_euc_3bytes[c2 - 0x80];
2283 ret = w_iconv_common(c1, c0, pp, sizeof_utf8_to_euc_C2, p2, p1);
2285 ret = w_iconv_common(c2, c1, utf8_to_euc_2bytes, sizeof_utf8_to_euc_2bytes, p2, p1);
2287 #ifdef NUMCHAR_OPTION
2290 if (p1) *p1 = CLASS_UTF16 | ww16_conv(c2, c1, c0);
2295 } else if (c2 == X0201) {
2308 int ret = w2e_conv(c2, c1, c0, &c2, &c1);
2316 w16w_conv(val, p2, p1, p0)
2324 }else if (val < 0x800){
2325 *p2 = 0xc0 | (val >> 6);
2326 *p1 = 0x80 | (val & 0x3f);
2329 *p2 = 0xe0 | (val >> 12);
2330 *p1 = 0x80 | ((val >> 6) & 0x3f);
2331 *p0 = 0x80 | (val & 0x3f);
2336 ww16_conv(c2, c1, c0)
2341 val = (c2 & 0x0f) << 12;
2342 val |= (c1 & 0x3f) << 6;
2344 }else if (c2 >= 0xc0){
2345 val = (c2 & 0x1f) << 6;
2346 val |= (c1 & 0x3f) << 6;
2354 w16e_conv(val, p2, p1)
2358 extern unsigned short * utf8_to_euc_2bytes[];
2359 extern unsigned short ** utf8_to_euc_3bytes[];
2361 unsigned short **pp;
2365 w16w_conv(val, &c2, &c1, &c0);
2368 pp = utf8_to_euc_3bytes[c2 - 0x80];
2369 psize = sizeof_utf8_to_euc_C2;
2370 ret = w_iconv_common(c1, c0, pp, psize, p2, p1);
2372 pp = utf8_to_euc_2bytes;
2373 psize = sizeof_utf8_to_euc_2bytes;
2374 ret = w_iconv_common(c2, c1, pp, psize, p2, p1);
2376 #ifdef NUMCHAR_OPTION
2379 *p1 = CLASS_UTF16 | val;
2388 w_iconv16(c2, c1, c0)
2393 if (c2==0376 && c1==0377){
2394 utf16_mode = UTF16LE_INPUT;
2396 } else if (c2==0377 && c1==0376){
2397 utf16_mode = UTF16BE_INPUT;
2400 if (c2 != EOF && utf16_mode == UTF16BE_INPUT) {
2402 tmp=c1; c1=c2; c2=tmp;
2404 if ((c2==0 && c1 < 0x80) || c2==EOF) {
2408 ret = w16e_conv(((c2<<8)&0xff00) + c1, &c2, &c1);
2409 if (ret) return ret;
2415 w_iconv_common(c1, c0, pp, psize, p2, p1)
2417 unsigned short **pp;
2425 if (pp == 0) return 1;
2428 if (c1 < 0 || psize <= c1) return 1;
2430 if (p == 0) return 1;
2433 if (c0 < 0 || sizeof_utf8_to_euc_E5B8 <= c0) return 1;
2435 if (val == 0) return 1;
2438 if (c2 == SO) c2 = X0201;
2447 #ifdef UTF8_OUTPUT_ENABLE
2452 extern unsigned short euc_to_utf8_1byte[];
2453 extern unsigned short * euc_to_utf8_2bytes[];
2454 extern unsigned short * euc_to_utf8_2bytes_ms[];
2458 p = euc_to_utf8_1byte;
2461 c2 = (c2&0x7f) - 0x21;
2462 if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
2463 p = ms_ucs_map_f ? euc_to_utf8_2bytes_ms[c2] : euc_to_utf8_2bytes[c2];
2468 c1 = (c1 & 0x7f) - 0x21;
2469 if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
2480 #ifdef NUMCHAR_OPTION
2481 if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2482 w16w_conv(c1, &c2, &c1, &c0);
2486 if (c0) (*o_putc)(c0);
2495 if (unicode_bom_f==2) {
2503 output_mode = ASCII;
2505 } else if (c2 == ISO8859_1) {
2506 output_mode = ISO8859_1;
2507 (*o_putc)(c1 | 0x080);
2510 w16w_conv((unsigned short)e2w_conv(c2, c1), &c2, &c1, &c0);
2514 if (c0) (*o_putc)(c0);
2529 if (unicode_bom_f==2) {
2531 (*o_putc)((unsigned char)'\377');
2535 (*o_putc)((unsigned char)'\377');
2540 if (c2 == ISO8859_1) {
2543 #ifdef NUMCHAR_OPTION
2544 } else if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16) {
2545 c2 = (c1 >> 8) & 0xff;
2549 unsigned short val = (unsigned short)e2w_conv(c2, c1);
2550 c2 = (val >> 8) & 0xff;
2569 #ifdef NUMCHAR_OPTION
2570 if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2571 w16e_conv(c1, &c2, &c1);
2577 } else if (c2 == 0) {
2578 output_mode = ASCII;
2580 } else if (c2 == X0201) {
2581 output_mode = JAPANESE_EUC;
2582 (*o_putc)(SSO); (*o_putc)(c1|0x80);
2583 } else if (c2 == ISO8859_1) {
2584 output_mode = ISO8859_1;
2585 (*o_putc)(c1 | 0x080);
2587 if ((c1<0x21 || 0x7e<c1) ||
2588 (c2<0x21 || 0x7e<c2)) {
2589 set_iconv(FALSE, 0);
2590 return; /* too late to rescue this char */
2592 output_mode = JAPANESE_EUC;
2593 (*o_putc)(c2 | 0x080);
2594 (*o_putc)(c1 | 0x080);
2599 e2s_conv(c2, c1, p2, p1)
2600 int c2, c1, *p2, *p1;
2602 if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
2603 if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
2611 #ifdef NUMCHAR_OPTION
2612 if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2613 w16e_conv(c1, &c2, &c1);
2619 } else if (c2 == 0) {
2620 output_mode = ASCII;
2622 } else if (c2 == X0201) {
2623 output_mode = SHIFT_JIS;
2625 } else if (c2 == ISO8859_1) {
2626 output_mode = ISO8859_1;
2627 (*o_putc)(c1 | 0x080);
2629 if ((c1<0x20 || 0x7e<c1) ||
2630 (c2<0x20 || 0x7e<c2)) {
2631 set_iconv(FALSE, 0);
2632 return; /* too late to rescue this char */
2634 output_mode = SHIFT_JIS;
2635 e2s_conv(c2, c1, &c2, &c1);
2637 #ifdef SHIFTJIS_CP932
2639 && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
2640 extern unsigned short cp932inv[2][189];
2641 int c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
2647 #endif /* SHIFTJIS_CP932 */
2650 if (prefix_table[(unsigned char)c1]){
2651 (*o_putc)(prefix_table[(unsigned char)c1]);
2662 #ifdef NUMCHAR_OPTION
2663 if ((c1 & CLASS_MASK) == CLASS_UTF16){
2664 w16e_conv(c1, &c2, &c1);
2668 if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2671 (*o_putc)(ascii_intro);
2672 output_mode = ASCII;
2675 } else if (c2==X0201) {
2676 if (output_mode!=X0201) {
2677 output_mode = X0201;
2683 } else if (c2==ISO8859_1) {
2684 /* iso8859 introduction, or 8th bit on */
2685 /* Can we convert in 7bit form using ESC-'-'-A ?
2687 output_mode = ISO8859_1;
2689 } else if (c2 == 0) {
2690 if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2693 (*o_putc)(ascii_intro);
2694 output_mode = ASCII;
2698 if (output_mode != X0208) {
2699 output_mode = X0208;
2702 (*o_putc)(kanji_intro);
2704 if (c1<0x20 || 0x7e<c1)
2706 if (c2<0x20 || 0x7e<c2)
2718 if (base64_count>50 && !mimeout_mode && c2==0 && c1==SPACE) {
2720 } else if (base64_count>66 && mimeout_mode) {
2721 (*o_base64conv)(EOF,0);
2723 (*o_putc)('\t'); base64_count += 7;
2725 (*o_base64conv)(c2,c1);
2729 static int broken_buf[3];
2730 static int broken_counter = 0;
2731 static int broken_last = 0;
2738 if (broken_counter>0) {
2739 return broken_buf[--broken_counter];
2742 if (c=='$' && broken_last != ESC
2743 && (input_mode==ASCII || input_mode==X0201)) {
2746 if (c1=='@'|| c1=='B') {
2747 broken_buf[0]=c1; broken_buf[1]=c;
2754 } else if (c=='(' && broken_last != ESC
2755 && (input_mode==X0208 || input_mode==X0201)) { /* ) */
2758 if (c1=='J'|| c1=='B') {
2759 broken_buf[0]=c1; broken_buf[1]=c;
2777 if (broken_counter<2)
2778 broken_buf[broken_counter++]=c;
2782 static int prev_cr = 0;
2790 if (! (c2==0&&c1==NL) ) {
2796 } else if (c1=='\r') {
2798 } else if (c1=='\n') {
2799 if (crmode_f==CRLF) {
2800 (*o_crconv)(0,'\r');
2801 } else if (crmode_f==CR) {
2802 (*o_crconv)(0,'\r');
2806 } else if (c1!='\032' || crmode_f!=NL){
2812 Return value of fold_conv()
2814 \n add newline and output char
2815 \r add newline and output nothing
2818 1 (or else) normal output
2820 fold state in prev (previous character)
2822 >0x80 Japanese (X0208/X0201)
2827 This fold algorthm does not preserve heading space in a line.
2828 This is the main difference from fmt.
2831 #define char_size(c2,c1) (c2?2:1)
2840 if (c1== '\r' && !fold_preserve_f) {
2841 fold_state=0; /* ignore cr */
2842 }else if (c1== '\n'&&f_prev=='\r' && fold_preserve_f) {
2844 fold_state=0; /* ignore cr */
2845 } else if (c1== BS) {
2846 if (f_line>0) f_line--;
2848 } else if (c2==EOF && f_line != 0) { /* close open last line */
2850 } else if ((c1=='\n' && !fold_preserve_f)
2851 || ((c1=='\r'||(c1=='\n'&&f_prev!='\r'))
2852 && fold_preserve_f)) {
2854 if (fold_preserve_f) {
2858 } else if ((f_prev == c1 && !fold_preserve_f)
2859 || (f_prev == '\n' && fold_preserve_f)
2860 ) { /* duplicate newline */
2863 fold_state = '\n'; /* output two newline */
2869 if (f_prev&0x80) { /* Japanese? */
2871 fold_state = 0; /* ignore given single newline */
2872 } else if (f_prev==' ') {
2876 if (++f_line<=fold_len)
2880 fold_state = '\r'; /* fold and output nothing */
2884 } else if (c1=='\f') {
2889 fold_state = '\n'; /* output newline and clear */
2890 } else if ( (c2==0 && c1==' ')||
2891 (c2==0 && c1=='\t')||
2892 (c2=='!'&& c1=='!')) {
2893 /* X0208 kankaku or ascii space */
2894 if (f_prev == ' ') {
2895 fold_state = 0; /* remove duplicate spaces */
2898 if (++f_line<=fold_len)
2899 fold_state = ' '; /* output ASCII space only */
2901 f_prev = ' '; f_line = 0;
2902 fold_state = '\r'; /* fold and output nothing */
2906 prev0 = f_prev; /* we still need this one... , but almost done */
2908 if (c2 || c2==X0201)
2909 f_prev |= 0x80; /* this is Japanese */
2910 f_line += char_size(c2,c1);
2911 if (f_line<=fold_len) { /* normal case */
2914 if (f_line>=fold_len+fold_margin) { /* too many kinsou suspension */
2915 f_line = char_size(c2,c1);
2916 fold_state = '\n'; /* We can't wait, do fold now */
2917 } else if (c2==X0201) {
2918 /* simple kinsoku rules return 1 means no folding */
2919 if (c1==(0xde&0x7f)) fold_state = 1; /*
\e$B!+
\e(B*/
2920 else if (c1==(0xdf&0x7f)) fold_state = 1; /*
\e$B!,
\e(B*/
2921 else if (c1==(0xa4&0x7f)) fold_state = 1; /*
\e$B!#
\e(B*/
2922 else if (c1==(0xa3&0x7f)) fold_state = 1; /*
\e$B!$
\e(B*/
2923 else if (c1==(0xa1&0x7f)) fold_state = 1; /*
\e$B!W
\e(B*/
2924 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
2925 else if (SPACE<=c1 && c1<=(0xdf&0x7f)) { /* X0201 */
2927 fold_state = '\n';/* add one new f_line before this character */
2930 fold_state = '\n';/* add one new f_line before this character */
2933 /* kinsoku point in ASCII */
2934 if ( c1==')'|| /* { [ ( */
2945 /* just after special */
2946 } else if (!is_alnum(prev0)) {
2947 f_line = char_size(c2,c1);
2949 } else if ((prev0==' ') || /* ignored new f_line */
2950 (prev0=='\n')|| /* ignored new f_line */
2951 (prev0&0x80)) { /* X0208 - ASCII */
2952 f_line = char_size(c2,c1);
2953 fold_state = '\n';/* add one new f_line before this character */
2955 fold_state = 1; /* default no fold in ASCII */
2959 if (c1=='"') fold_state = 1; /*
\e$B!"
\e(B */
2960 else if (c1=='#') fold_state = 1; /*
\e$B!#
\e(B */
2961 else if (c1=='W') fold_state = 1; /*
\e$B!W
\e(B */
2962 else if (c1=='K') fold_state = 1; /*
\e$B!K
\e(B */
2963 else if (c1=='$') fold_state = 1; /*
\e$B!$
\e(B */
2964 else if (c1=='%') fold_state = 1; /*
\e$B!%
\e(B */
2965 else if (c1=='\'') fold_state = 1; /*
\e$B!\
\e(B */
2966 else if (c1=='(') fold_state = 1; /*
\e$B!(
\e(B */
2967 else if (c1==')') fold_state = 1; /*
\e$B!)
\e(B */
2968 else if (c1=='*') fold_state = 1; /*
\e$B!*
\e(B */
2969 else if (c1=='+') fold_state = 1; /*
\e$B!+
\e(B */
2970 else if (c1==',') fold_state = 1; /*
\e$B!,
\e(B */
2971 /* default no fold in kinsoku */
2974 f_line = char_size(c2,c1);
2975 /* add one new f_line before this character */
2978 f_line = char_size(c2,c1);
2980 /* add one new f_line before this character */
2985 /* terminator process */
2986 switch(fold_state) {
3005 int z_prev2=0,z_prev1=0;
3012 /* if (c2) c1 &= 0x7f; assertion */
3014 if (x0201_f && z_prev2==X0201) { /* X0201 */
3015 if (c1==(0xde&0x7f)) { /*
\e$BByE@
\e(B */
3017 (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
3019 } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) { /*
\e$BH>ByE@
\e(B */
3021 (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
3025 (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
3034 if (x0201_f && c2==X0201) {
3035 if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
3036 /* wait for
\e$BByE@
\e(B or
\e$BH>ByE@
\e(B */
3037 z_prev1 = c1; z_prev2 = c2;
3040 (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
3045 /* JISX0208 Alphabet */
3046 if (alpha_f && c2 == 0x23 ) {
3048 } else if (alpha_f && c2 == 0x21 ) {
3049 /* JISX0208 Kigou */
3054 } else if (alpha_f&0x4) {
3059 } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
3065 case '>': entity = ">"; break;
3066 case '<': entity = "<"; break;
3067 case '\"': entity = """; break;
3068 case '&': entity = "&"; break;
3071 while (*entity) (*o_zconv)(0, *entity++);
3081 #define rot13(c) ( \
3083 (c <= 'M') ? (c + 13): \
3084 (c <= 'Z') ? (c - 13): \
3086 (c <= 'm') ? (c + 13): \
3087 (c <= 'z') ? (c - 13): \
3091 #define rot47(c) ( \
3093 ( c <= 'O' ) ? (c + 47) : \
3094 ( c <= '~' ) ? (c - 47) : \
3102 if (c2==0 || c2==X0201 || c2==ISO8859_1) {
3108 (*o_rot_conv)(c2,c1);
3115 if ((hira_f & 1) && c2==0x25 && 0x20<c1 && c1<0x74) {
3117 } else if ((hira_f & 2) && c2==0x24 && 0x20<c1 && c1<0x74) {
3120 (*o_hira_conv)(c2,c1);
3125 iso2022jp_check_conv(c2,c1)
3128 static int range[RANGE_NUM_MAX][2] = {
3151 if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
3155 if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
3160 for (i = 0; i < RANGE_NUM_MAX; i++) {
3161 start = range[i][0];
3164 if (c >= start && c <= end) {
3169 (*o_iso2022jp_check_conv)(c2,c1);
3173 /* This converts =?ISO-2022-JP?B?HOGE HOGE?= */
3175 unsigned char *mime_pattern[] = {
3176 (unsigned char *)"\075?EUC-JP?B?",
3177 (unsigned char *)"\075?SHIFT_JIS?B?",
3178 (unsigned char *)"\075?ISO-8859-1?Q?",
3179 (unsigned char *)"\075?ISO-8859-1?B?",
3180 (unsigned char *)"\075?ISO-2022-JP?B?",
3181 (unsigned char *)"\075?ISO-2022-JP?Q?",
3182 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3183 (unsigned char *)"\075?UTF-8?B?",
3184 (unsigned char *)"\075?UTF-8?Q?",
3186 (unsigned char *)"\075?US-ASCII?Q?",
3191 /*
\e$B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u
\e(B */
3192 int (*mime_priority_func[])PROTO((int c2, int c1, int c0)) = {
3193 e_iconv, s_iconv, 0, 0, 0, 0,
3194 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3200 int mime_encode[] = {
3201 JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
3202 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3209 int mime_encode_method[] = {
3210 'B', 'B','Q', 'B', 'B', 'Q',
3211 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3219 #define MAXRECOVER 20
3221 /* I don't trust portablity of toupper */
3222 #define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c)
3223 #define nkf_isdigit(c) ('0'<=c && c<='9')
3224 #define nkf_isxdigit(c) (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
3229 if (i_getc!=mime_getc) {
3230 i_mgetc = i_getc; i_getc = mime_getc;
3231 i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
3232 if(mime_f==STRICT_MIME) {
3233 i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
3234 i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
3240 unswitch_mime_getc()
3242 if(mime_f==STRICT_MIME) {
3243 i_mgetc = i_mgetc_buf;
3244 i_mungetc = i_mungetc_buf;
3247 i_ungetc = i_mungetc;
3251 mime_begin_strict(f)
3256 unsigned char *p,*q;
3257 int r[MAXRECOVER]; /* recovery buffer, max mime pattern lenght */
3259 mime_decode_mode = FALSE;
3260 /* =? has been checked */
3262 p = mime_pattern[j];
3265 for(i=2;p[i]>' ';i++) { /* start at =? */
3266 if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
3267 /* pattern fails, try next one */
3269 while ((p = mime_pattern[++j])) {
3270 for(k=2;k<i;k++) /* assume length(p) > i */
3271 if (p[k]!=q[k]) break;
3272 if (k==i && nkf_toupper(c1)==p[k]) break;
3274 if (p) continue; /* found next one, continue */
3275 /* all fails, output from recovery buffer */
3283 mime_decode_mode = p[i-2];
3285 clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
3287 if (mime_decode_mode=='B') {
3288 mimebuf_f = unbuf_f;
3290 /* do MIME integrity check */
3291 return mime_integrity(f,mime_pattern[j]);
3303 /* we don't keep eof of Fifo, becase it contains ?= as
3304 a terminator. It was checked in mime_integrity. */
3305 return ((mimebuf_f)?
3306 (*i_mgetc_buf)(f):Fifo(mime_input++));
3310 mime_ungetc_buf(c,f)
3315 (*i_mungetc_buf)(c,f);
3317 Fifo(--mime_input)=c;
3328 /* In NONSTRICT mode, only =? is checked. In case of failure, we */
3329 /* re-read and convert again from mime_buffer. */
3331 /* =? has been checked */
3333 Fifo(mime_last++)='='; Fifo(mime_last++)='?';
3334 for(i=2;i<MAXRECOVER;i++) { /* start at =? */
3335 /* We accept any character type even if it is breaked by new lines */
3336 c1 = (*i_getc)(f); Fifo(mime_last++)= c1 ;
3337 if (c1=='\n'||c1==' '||c1=='\r'||
3338 c1=='-'||c1=='_'||is_alnum(c1) ) continue;
3340 /* Failed. But this could be another MIME preemble */
3348 c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3349 if (!(++i<MAXRECOVER) || c1==EOF) break;
3350 if (c1=='b'||c1=='B') {
3351 mime_decode_mode = 'B';
3352 } else if (c1=='q'||c1=='Q') {
3353 mime_decode_mode = 'Q';
3357 c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3358 if (!(++i<MAXRECOVER) || c1==EOF) break;
3360 mime_decode_mode = FALSE;
3366 if (!mime_decode_mode) {
3367 /* false MIME premble, restart from mime_buffer */
3368 mime_decode_mode = 1; /* no decode, but read from the mime_buffer */
3369 /* Since we are in MIME mode until buffer becomes empty, */
3370 /* we never go into mime_begin again for a while. */
3373 /* discard mime preemble, and goto MIME mode */
3375 /* do no MIME integrity check */
3376 return c1; /* used only for checking EOF */
3391 fprintf(stderr, "%s\n", str);
3397 set_input_codename (codename)
3402 strcmp(codename, "") != 0 &&
3403 strcmp(codename, input_codename) != 0)
3405 is_inputcode_mixed = TRUE;
3407 input_codename = codename;
3408 is_inputcode_set = TRUE;
3412 print_guessed_code (filename)
3415 char *codename = "BINARY";
3416 if (!is_inputcode_mixed) {
3417 if (strcmp(input_codename, "") == 0) {
3420 codename = input_codename;
3423 if (filename != NULL) printf("%s:", filename);
3424 printf("%s\n", codename);
3431 if (nkf_isdigit(x)) return x - '0';
3432 return nkf_toupper(x) - 'A' + 10;
3437 #ifdef ANSI_C_PROTOTYPE
3438 int hex_getc(int ch, FILE *f, int (*g)(FILE *f), int (*u)(int c, FILE *f))
3441 hex_getc(ch, f, g, u)
3454 if (!nkf_isxdigit(c2)){
3459 if (!nkf_isxdigit(c3)){
3464 return (hex2bin(c2) << 4) | hex2bin(c3);
3471 return hex_getc(':', f, i_cgetc, i_cungetc);
3479 return (*i_cungetc)(c, f);
3486 return hex_getc('%', f, i_ugetc, i_uungetc);
3494 return (*i_uungetc)(c, f);
3498 #ifdef NUMCHAR_OPTION
3503 int (*g)() = i_ngetc;
3504 int (*u)() = i_nungetc;
3515 if (buf[i] == 'x' || buf[i] == 'X'){
3516 for (j = 0; j < 5; j++){
3518 if (!nkf_isxdigit(buf[i])){
3525 c |= hex2bin(buf[i]);
3528 for (j = 0; j < 6; j++){
3532 if (!nkf_isdigit(buf[i])){
3539 c += hex2bin(buf[i]);
3545 return CLASS_UTF16 | c;
3555 numchar_ungetc(c, f)
3559 return (*i_nungetc)(c, f);
3568 int c1, c2, c3, c4, cc;
3569 int t1, t2, t3, t4, mode, exit_mode;
3571 if (mime_top != mime_last) { /* Something is in FIFO */
3572 return Fifo(mime_top++);
3574 if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
3575 mime_decode_mode=FALSE;
3576 unswitch_mime_getc();
3577 return (*i_getc)(f);
3580 if (mimebuf_f == FIXED_MIME)
3581 exit_mode = mime_decode_mode;
3584 if (mime_decode_mode == 'Q') {
3585 if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
3587 if (c1=='_') return ' ';
3588 if (c1!='=' && c1!='?') {
3592 mime_decode_mode = exit_mode; /* prepare for quit */
3593 if (c1<=' ') return c1;
3594 if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
3595 if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
3596 /* end Q encoding */
3597 input_mode = exit_mode;
3598 while((c1=(*i_getc)(f))!=EOF && c1==SPACE
3599 /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
3602 if (c1=='='&&c2<' ') { /* this is soft wrap */
3603 while((c1 = (*i_mgetc)(f)) <=' ') {
3604 if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
3606 mime_decode_mode = 'Q'; /* still in MIME */
3607 goto restart_mime_q;
3610 mime_decode_mode = 'Q'; /* still in MIME */
3614 if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
3615 if (c2<=' ') return c2;
3616 mime_decode_mode = 'Q'; /* still in MIME */
3617 #define hex(c) (('0'<=c&&c<='9')?(c-'0'):\
3618 ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
3619 return ((hex(c2)<<4) + hex(c3));
3622 if (mime_decode_mode != 'B') {
3623 mime_decode_mode = FALSE;
3624 return (*i_mgetc)(f);
3628 /* Base64 encoding */
3630 MIME allows line break in the middle of
3631 Base64, but we are very pessimistic in decoding
3632 in unbuf mode because MIME encoded code may broken by
3633 less or editor's control sequence (such as ESC-[-K in unbuffered
3634 mode. ignore incomplete MIME.
3636 mode = mime_decode_mode;
3637 mime_decode_mode = exit_mode; /* prepare for quit */
3639 while ((c1 = (*i_mgetc)(f))<=' ') {
3644 if ((c2 = (*i_mgetc)(f))<=' ') {
3647 if (mime_f != STRICT_MIME) goto mime_c2_retry;
3648 if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
3651 if ((c1 == '?') && (c2 == '=')) {
3653 while((c1=(*i_getc)(f))!=EOF && c1==SPACE
3654 /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
3658 if ((c3 = (*i_mgetc)(f))<=' ') {
3661 if (mime_f != STRICT_MIME) goto mime_c3_retry;
3662 if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
3666 if ((c4 = (*i_mgetc)(f))<=' ') {
3669 if (mime_f != STRICT_MIME) goto mime_c4_retry;
3670 if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
3674 mime_decode_mode = mode; /* still in MIME sigh... */
3676 /* BASE 64 decoding */
3678 t1 = 0x3f & base64decode(c1);
3679 t2 = 0x3f & base64decode(c2);
3680 t3 = 0x3f & base64decode(c3);
3681 t4 = 0x3f & base64decode(c4);
3682 cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
3684 Fifo(mime_last++) = cc;
3685 cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
3687 Fifo(mime_last++) = cc;
3688 cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
3690 Fifo(mime_last++) = cc;
3695 return Fifo(mime_top++);
3703 Fifo(--mime_top) = c;
3714 /* In buffered mode, read until =? or NL or buffer full
3716 mime_input = mime_top;
3717 mime_last = mime_top;
3718 while(*p) Fifo(mime_input++) = *p++;
3721 while((c=(*i_getc)(f))!=EOF) {
3722 if (((mime_input-mime_top)&MIME_BUF_MASK)==0) {
3723 break; /* buffer full */
3725 if (c=='=' && d=='?') {
3726 /* checked. skip header, start decode */
3727 Fifo(mime_input++) = c;
3728 /* mime_last_input = mime_input; */
3733 if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
3735 /* Should we check length mod 4? */
3736 Fifo(mime_input++) = c;
3739 /* In case of Incomplete MIME, no MIME decode */
3740 Fifo(mime_input++) = c;
3741 mime_last = mime_input; /* point undecoded buffer */
3742 mime_decode_mode = 1; /* no decode on Fifo last in mime_getc */
3743 switch_mime_getc(); /* anyway we need buffered getc */
3754 i = c - 'A'; /* A..Z 0-25 */
3756 i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */
3758 } else if (c > '/') {
3759 i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */
3760 } else if (c == '+') {
3761 i = '>' /* 62 */ ; /* + 62 */
3763 i = '?' /* 63 */ ; /* / 63 */
3768 static char basis_64[] =
3769 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3779 p = mime_pattern[0];
3780 for(i=0;mime_encode[i];i++) {
3781 if (mode == mime_encode[i]) {
3782 p = mime_pattern[i];
3786 mimeout_mode = mime_encode_method[i];
3788 /* (*o_mputc)(' '); */
3805 #define itoh4(c) (c>=10?c+'A'-10:c+'0')
3811 if (mimeout_f==FIXED_MIME) {
3812 if (base64_count>71) {
3820 if ( c<=DEL &&(output_mode==ASCII ||output_mode == ISO8859_1 )
3821 && mimeout_f!=FIXED_MIME) {
3822 if (mimeout_mode=='Q') {
3829 if (mimeout_mode!='B' || c!=SPACE) {
3838 } else if (!mimeout_mode && mimeout_f!=FIXED_MIME) {
3839 open_mime(output_mode);
3841 } else { /* c==EOF */
3842 switch(mimeout_mode) {
3847 (*o_mputc)(basis_64[((b64c & 0x3)<< 4)]);
3853 (*o_mputc)(basis_64[((b64c & 0xF) << 2)]);
3859 if (mimeout_f!=FIXED_MIME) {
3861 } else if (mimeout_mode != 'Q')
3866 switch(mimeout_mode) {
3870 (*o_mputc)(itoh4(((c>>4)&0xf)));
3871 (*o_mputc)(itoh4((c&0xf)));
3878 (*o_mputc)(basis_64[c>>2]);
3883 (*o_mputc)(basis_64[((b64c & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
3889 (*o_mputc)(basis_64[((b64c & 0xF) << 2) | ((c & 0xC0) >>6)]);
3890 (*o_mputc)(basis_64[c & 0x3F]);
3903 struct input_code *p = input_code_list;
3916 mime_f = STRICT_MIME;
3921 #if defined(MSDOS) || defined(__OS2__)
3926 iso2022jp_f = FALSE;
3927 #ifdef UTF8_OUTPUT_ENABLE
3930 ms_ucs_map_f = FALSE;
3942 is_inputcode_mixed = FALSE;
3943 is_inputcode_set = FALSE;
3947 #ifdef SHIFTJIS_CP932
3953 for (i = 0; i < 256; i++){
3954 prefix_table[i] = 0;
3957 #ifdef UTF8_INPUT_ENABLE
3958 utf16_mode = UTF16LE_INPUT;
3964 fold_preserve_f = FALSE;
3967 kanji_intro = DEFAULT_J;
3968 ascii_intro = DEFAULT_R;
3969 fold_margin = FOLD_MARGIN;
3970 output_conv = DEFAULT_CONV;
3971 oconv = DEFAULT_CONV;
3972 o_zconv = no_connection;
3973 o_fconv = no_connection;
3974 o_crconv = no_connection;
3975 o_rot_conv = no_connection;
3976 o_hira_conv = no_connection;
3977 o_base64conv = no_connection;
3978 o_iso2022jp_check_conv = no_connection;
3981 i_ungetc = std_ungetc;
3983 i_bungetc = std_ungetc;
3986 i_mungetc = std_ungetc;
3987 i_mgetc_buf = std_getc;
3988 i_mungetc_buf = std_ungetc;
3989 output_mode = ASCII;
3992 mime_decode_mode = FALSE;
3998 z_prev2=0,z_prev1=0;
4004 no_connection(c2,c1)
4007 no_connection2(c2,c1,0);
4011 no_connection2(c2,c1,c0)
4014 fprintf(stderr,"nkf internal module connection failure.\n");
4022 fprintf(stderr,"USAGE: nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
4023 fprintf(stderr,"Flags:\n");
4024 fprintf(stderr,"b,u Output is buffered (DEFAULT),Output is unbuffered\n");
4025 #ifdef DEFAULT_CODE_SJIS
4026 fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC), UTF-8\n");
4028 #ifdef DEFAULT_CODE_JIS
4029 fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC), UTF-8\n");
4031 #ifdef DEFAULT_CODE_EUC
4032 fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT), UTF-8\n");
4034 #ifdef DEFAULT_CODE_UTF8
4035 fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC), UTF-8 (DEFAULT)\n");
4037 #ifdef UTF8_OUTPUT_ENABLE
4038 fprintf(stderr," After 'w' you can add more options. (80?|16((B|L)0?)?) \n");
4040 fprintf(stderr,"J,S,E,W Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC), UTF-8\n");
4041 #ifdef UTF8_INPUT_ENABLE
4042 fprintf(stderr," After 'W' you can add more options. (8|16(B|L)?) \n");
4044 fprintf(stderr,"t no conversion\n");
4045 fprintf(stderr,"i_/o_ Output sequence to designate JIS-kanji/ASCII (DEFAULT B)\n");
4046 fprintf(stderr,"r {de/en}crypt ROT13/47\n");
4047 fprintf(stderr,"h 1 hirakana->katakana, 2 katakana->hirakana,3 both\n");
4048 fprintf(stderr,"v Show this usage. V: show version\n");
4049 fprintf(stderr,"m[BQN0] MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
4050 fprintf(stderr,"M[BQ] MIME encode [B:base64 Q:quoted]\n");
4051 fprintf(stderr,"l ISO8859-1 (Latin-1) support\n");
4052 fprintf(stderr,"f/F Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
4053 fprintf(stderr,"Z[0-3] Convert X0208 alphabet to ASCII 1: Kankaku to space,2: 2 spaces,\n");
4054 fprintf(stderr," 3: Convert HTML Entity\n");
4055 fprintf(stderr,"X,x Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
4056 fprintf(stderr,"B[0-2] Broken input 0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
4058 fprintf(stderr,"T Text mode output\n");
4060 fprintf(stderr,"O Output to File (DEFAULT 'nkf.out')\n");
4061 fprintf(stderr,"d,c Delete \\r in line feed and \\032, Add \\r in line feed\n");
4062 fprintf(stderr,"I Convert non ISO-2022-JP charactor to GETA\n");
4063 fprintf(stderr,"-L[uwm] line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
4064 fprintf(stderr,"long name options\n");
4065 fprintf(stderr," --fj,--unix,--mac,--windows convert for the system\n");
4066 fprintf(stderr," --jis,--euc,--sjis,--utf8,--utf16,--mime,--base64 convert for the code\n");
4067 fprintf(stderr," --hiragana, --katakana Hiragana/Katakana Conversion\n");
4069 fprintf(stderr," --cap-input, --url-input Convert hex after ':' or '%'\n");
4071 #ifdef NUMCHAR_OPTION
4072 fprintf(stderr," --numchar-input Convert Unicode Character Reference\n");
4074 #ifdef SHIFTJIS_CP932
4075 fprintf(stderr," --no-cp932 Don't convert Shift_JIS FAxx-FCxx to equivalnet CP932\n");
4076 fprintf(stderr," --cp932inv convert Shift_JIS EDxx-EFxx to equivalnet CP932 FAxx-FCxx\n");
4078 #ifdef UTF8_OUTPUT_ENABLE
4079 fprintf(stderr," --ms-ucs-map Microsoft UCS Mapping Compatible\n");
4082 fprintf(stderr," --overwrite Overwrite original listed files by filtered result\n");
4084 fprintf(stderr," -g, --guess Guess the input code\n");
4085 fprintf(stderr," --help,--version\n");
4092 fprintf(stderr,"Network Kanji Filter Version %s (%s) "
4093 #if defined(MSDOS) && !defined(__WIN32__) && !defined(__WIN16__)
4096 #if defined(MSDOS) && defined(__WIN16__)
4099 #if defined(MSDOS) && defined(__WIN32__)
4105 ,NKF_VERSION,NKF_RELEASE_DATE);
4106 fprintf(stderr,"\n%s\n",CopyRight);
4111 **
\e$B%Q%C%A@):n<T
\e(B
4112 ** void@merope.pleiades.or.jp (Kusakabe Youichi)
4113 ** NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
4114 ** ohta@src.ricoh.co.jp (Junn Ohta)
4115 ** inouet@strl.nhk.or.jp (Tomoyuki Inoue)
4116 ** kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
4117 ** Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
4118 ** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
4119 ** kono@ie.u-ryukyu.ac.jp (Shinji Kono)
4120 ** GHG00637@nifty-serve.or.jp (COW)