OSDN Git Service

* add some Unicode I/O options
[nkf/nkf.git] / nkf.c
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
7 ** Copyright (C) 2002
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
12 **
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
19 **
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 ***********************************************************************/
28
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
34 **
35 **    \e$B$^$@%P%0$,$"$k2DG=@-$,9b$$$G$9!#\e(B
36 **    (\e$BFC$K<+F0H=JL!"%3!<%I:.:_!"%(%i!<=hM}7O\e(B)
37 **
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 #include "config.h"
43
44 static char *CopyRight =
45       "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW, 2002-2004 Kono, Furukawa";
46 static char *Version =
47       "2.0";
48 static char *Patchlevel =
49       "4/0401/Shinji Kono";
50
51 /*
52 **
53 **
54 **
55 ** USAGE:       nkf [flags] [file] 
56 **
57 ** Flags:
58 ** b    Output is buffered             (DEFAULT)
59 ** u    Output is unbuffered
60 **
61 ** t    no operation
62 **
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
68 **
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 
74 **
75 ** r  {de/en}crypt ROT13/47
76 **
77 ** v  display Version
78 **
79 ** T  Text mode output        (for MS-DOS)
80 **
81 ** x    Do not convert X0201 kana into X0208
82 ** Z    Convert X0208 alphabet to ASCII
83 **
84 ** f60  fold option
85 **
86 ** m    MIME decode
87 ** B    try to fix broken JIS, missing Escape
88 ** B[1-9]  broken level
89 **
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 )
95 **
96 **/
97
98 #if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || defined(__MINGW32__)) && !defined(MSDOS)
99 #define MSDOS
100 #if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
101 #define __WIN32__
102 #endif
103 #endif
104
105 #ifdef PERL_XS
106 #undef OVERWRITE
107 #endif
108
109 #ifndef PERL_XS
110 #include <stdio.h>
111 #endif
112
113 #if defined(MSDOS) || defined(__OS2__) 
114 #include <fcntl.h>
115 #include <io.h>
116 #endif
117
118 #ifdef MSDOS
119 #ifdef LSI_C
120 #define setbinmode(fp) fsetbin(fp)
121 #else /* Microsoft C, Turbo C */
122 #define setbinmode(fp) setmode(fileno(fp), O_BINARY)
123 #endif
124 #else /* UNIX,OS/2 */
125 #define setbinmode(fp)
126 #endif
127
128 #ifdef _IOFBF /* SysV and MSDOS, Windows */
129 #define       setvbuffer(fp, buf, size)       setvbuf(fp, buf, _IOFBF, size)
130 #else /* BSD */
131 #define       setvbuffer(fp, buf, size)       setbuffer(fp, buf, size)
132 #endif
133
134 /*Borland C++ 4.5 EasyWin*/
135 #if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
136 #define         EASYWIN
137 #ifndef __WIN16__
138 #define __WIN16__
139 #endif
140 #include <windows.h>
141 #endif
142
143 #ifdef OVERWRITE
144 /* added by satoru@isoternet.org */
145 #include <stdlib.h>
146 #include <string.h>
147 #include <sys/stat.h>
148 #ifndef MSDOS /* UNIX, OS/2 */
149 #include <unistd.h>
150 #include <utime.h>
151 #else
152 #if defined(_MSC_VER) || defined(__MINGW32__) /* VC++, MinGW */
153 #include <sys/utime.h>
154 #elif defined(__TURBOC__) /* BCC */
155 #include <utime.h>
156 #elif defined(LSI_C) /* LSI C */
157 #endif
158 #endif
159 #endif 
160
161 #ifdef INT_IS_SHORT
162 #define int long
163 #endif
164
165 #define         FALSE   0
166 #define         TRUE    1
167
168 /* state of output_mode and input_mode  
169
170    c2           0 means ASCII
171                 X0201
172                 ISO8859_1
173                 X0208
174                 EOF      all termination
175    c1           32bit data
176
177  */
178
179 #define         ASCII           0
180 #define         X0208           1
181 #define         X0201           2
182 #define         ISO8859_1       8
183 #define         NO_X0201        3
184
185 /* Input Assumption */
186
187 #define         JIS_INPUT       4
188 #define         SJIS_INPUT      5
189 #define         LATIN1_INPUT    6
190 #define         FIXED_MIME      7
191 #define         STRICT_MIME     8
192
193 /* MIME ENCODE */
194
195 #define         ISO2022JP       9
196 #define         JAPANESE_EUC   10
197 #define         SHIFT_JIS      11
198
199 #define         UTF8           12
200 #define         UTF8_INPUT     13
201 #define         UTF16LE_INPUT  14
202 #define         UTF16BE_INPUT  15
203
204 #define         WISH_TRUE      15
205
206 /* ASCII CODE */
207
208 #define         BS      0x08
209 #define         NL      0x0a
210 #define         CR      0x0d
211 #define         ESC     0x1b
212 #define         SPACE   0x20
213 #define         AT      0x40
214 #define         SSP     0xa0
215 #define         DEL     0x7f
216 #define         SI      0x0f
217 #define         SO      0x0e
218 #define         SSO     0x8e
219
220 #define         is_alnum(c)  \
221             (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
222
223 #define         HOLD_SIZE       1024
224 #define         IOBUF_SIZE      16384
225
226 #define         DEFAULT_J       'B'
227 #define         DEFAULT_R       'B'
228
229 #define         SJ0162  0x00e1          /* 01 - 62 ku offset */
230 #define         SJ6394  0x0161          /* 63 - 94 ku offset */
231
232 #define         RANGE_NUM_MAX   18
233 #define         GETA1   0x22
234 #define         GETA2   0x2e
235
236
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
245 #endif
246
247 /* MIME preprocessor */
248
249
250 #ifdef EASYWIN /*Easy Win */
251 extern POINT _BufferSize;
252 #endif
253
254 /*      function prototype  */
255
256 #ifdef ANSI_C_PROTOTYPE
257 #define PROTO(x)  x 
258 #define STATIC static
259 #else
260 #define PROTO(x)  ()
261 #define STATIC
262 #endif
263
264 struct input_code{
265     char *name;
266     int stat;
267     int score;
268     int index;
269     int buf[3];
270     void (*status_func)PROTO((struct input_code *, int));
271     int (*iconv_func)PROTO((int c2, int c1, int c0));
272     int _file_stat;
273 };
274
275 STATIC char *input_codename = "";
276
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));
291 #endif
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));
296 #endif
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));
310
311 STATIC  void    code_score PROTO((struct input_code *ptr));
312 STATIC  void    code_status PROTO((int c));
313
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));
317
318 STATIC  int     broken_getc PROTO((FILE *f));
319 STATIC  int     broken_ungetc PROTO((int c,FILE *f));
320
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));
324
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));
329
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));
337 #ifdef PERL_XS
338 STATIC  void    reinit PROTO(());
339 #endif
340
341 /* buffers */
342
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;
347
348 /* MIME preprocessor fifo */
349
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 */
357
358 /* flags */
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 */
374 #else
375 static int             x0201_f = NO_X0201;     /* Assume NO JISX0201 */
376 #endif
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 #endif
382
383
384 #ifdef NUMCHAR_OPTION
385
386 #define CLASS_MASK  0x0f000000
387 #define CLASS_UTF16 0x01000000
388 #endif
389
390 #ifdef INPUT_OPTION
391 static int cap_f = FALSE;
392 static int (*i_cgetc)PROTO((FILE *)) = std_getc; /* input of cgetc */
393 static int (*i_cungetc)PROTO((int c ,FILE *f)) = std_ungetc;
394 STATIC int cap_getc PROTO((FILE *f));
395 STATIC int cap_ungetc PROTO((int c,FILE *f));
396
397 static int url_f = FALSE;
398 static int (*i_ugetc)PROTO((FILE *)) = std_getc; /* input of ugetc */
399 static int (*i_uungetc)PROTO((int c ,FILE *f)) = std_ungetc;
400 STATIC int url_getc PROTO((FILE *f));
401 STATIC int url_ungetc PROTO((int c,FILE *f));
402
403 static int numchar_f = FALSE;
404 static int (*i_ngetc)PROTO((FILE *)) = std_getc; /* input of ugetc */
405 static int (*i_nungetc)PROTO((int c ,FILE *f)) = std_ungetc;
406 STATIC int numchar_getc PROTO((FILE *f));
407 STATIC int numchar_ungetc PROTO((int c,FILE *f));
408 #endif
409
410 #ifdef CHECK_OPTION
411 static int noout_f = FALSE;
412 STATIC void no_putc PROTO((int c));
413 static int debug_f = FALSE;
414 STATIC void debug PROTO((char *str));
415 #endif
416
417 static int guess_f = FALSE;
418 STATIC  void    print_guessed_code PROTO((char *filename));
419 STATIC  void    set_input_codename PROTO((char *codename));
420 static int is_inputcode_mixed = FALSE;
421 static int is_inputcode_set   = FALSE;
422
423 #ifdef EXEC_IO
424 static int exec_f = 0;
425 #endif
426
427 #ifdef SHIFTJIS_CP932
428 STATIC int cp932_f = TRUE;
429 #define CP932_TABLE_BEGIN (0xfa)
430 #define CP932_TABLE_END   (0xfc)
431
432 STATIC int cp932inv_f = FALSE;
433 #define CP932INV_TABLE_BEGIN (0xed)
434 #define CP932INV_TABLE_END   (0xee)
435
436 #endif /* SHIFTJIS_CP932 */
437
438 STATIC unsigned char prefix_table[256];
439
440 STATIC void e_status PROTO((struct input_code *, int));
441 STATIC void s_status PROTO((struct input_code *, int));
442
443 #ifdef UTF8_INPUT_ENABLE
444 STATIC void w_status PROTO((struct input_code *, int));
445 STATIC void w16_status PROTO((struct input_code *, int));
446 static int             utf16_mode = UTF16LE_INPUT;
447 #endif
448
449 struct input_code input_code_list[] = {
450     {"EUC-JP",    0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
451     {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
452     {"UTF-8",     0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
453     {"UTF-16",    0, 0, 0, {0, 0, 0}, w16_status, w_iconv16, 0},
454     {0}
455 };
456
457 static int              mimeout_mode = 0;
458 static int              base64_count = 0;
459
460 /* X0208 -> ASCII converter */
461
462 /* fold parameter */
463 static int             f_line = 0;    /* chars in line */
464 static int             f_prev = 0;
465 static int             fold_preserve_f = FALSE; /* preserve new lines */
466 static int             fold_f  = FALSE;
467 static int             fold_len  = 0;
468
469 /* options */
470 static unsigned char   kanji_intro = DEFAULT_J,
471                        ascii_intro = DEFAULT_R;
472
473 /* Folding */
474
475 #define FOLD_MARGIN  10
476 #define DEFAULT_FOLD 60
477
478 static int             fold_margin  = FOLD_MARGIN;
479
480 /* converters */
481
482 #ifdef DEFAULT_CODE_JIS
483 #   define  DEFAULT_CONV j_oconv
484 #endif
485 #ifdef DEFAULT_CODE_SJIS
486 #   define  DEFAULT_CONV s_oconv
487 #endif
488 #ifdef DEFAULT_CODE_EUC
489 #   define  DEFAULT_CONV e_oconv
490 #endif
491 #ifdef DEFAULT_CODE_UTF8
492 #   define  DEFAULT_CONV w_oconv
493 #endif
494
495 /* process default */
496 static void (*output_conv)PROTO((int c2,int c1)) = DEFAULT_CONV;   
497
498 static void (*oconv)PROTO((int c2,int c1)) = no_connection; 
499 /* s_iconv or oconv */
500 static int (*iconv)PROTO((int c2,int c1,int c0)) = no_connection2;   
501
502 static void (*o_zconv)PROTO((int c2,int c1)) = no_connection; 
503 static void (*o_fconv)PROTO((int c2,int c1)) = no_connection; 
504 static void (*o_crconv)PROTO((int c2,int c1)) = no_connection; 
505 static void (*o_rot_conv)PROTO((int c2,int c1)) = no_connection; 
506 static void (*o_hira_conv)PROTO((int c2,int c1)) = no_connection; 
507 static void (*o_base64conv)PROTO((int c2,int c1)) = no_connection;
508 static void (*o_iso2022jp_check_conv)PROTO((int c2,int c1)) = no_connection;
509
510 /* static redirections */
511
512 static  void   (*o_putc)PROTO((int c)) = std_putc;
513
514 static  int    (*i_getc)PROTO((FILE *f)) = std_getc; /* general input */
515 static  int    (*i_ungetc)PROTO((int c,FILE *f)) =std_ungetc;
516
517 static  int    (*i_bgetc)PROTO((FILE *)) = std_getc; /* input of mgetc */
518 static  int    (*i_bungetc)PROTO((int c ,FILE *f)) = std_ungetc;
519
520 static  void   (*o_mputc)PROTO((int c)) = std_putc ; /* output of mputc */
521
522 static  int    (*i_mgetc)PROTO((FILE *)) = std_getc; /* input of mgetc */
523 static  int    (*i_mungetc)PROTO((int c ,FILE *f)) = std_ungetc;
524
525 /* for strict mime */
526 static  int    (*i_mgetc_buf)PROTO((FILE *)) = std_getc; /* input of mgetc_buf */
527 static  int    (*i_mungetc_buf)PROTO((int c,FILE *f)) = std_ungetc;
528
529 /* Global states */
530 static int output_mode = ASCII,    /* output kanji mode */
531            input_mode =  ASCII,    /* input kanji mode */
532            shift_mode =  FALSE;    /* TRUE shift out, or X0201  */
533 static int mime_decode_mode =   FALSE;    /* MIME mode B base64, Q hex */
534
535 /* X0201 / X0208 conversion tables */
536
537 /* X0201 kana conversion table */
538 /* 90-9F A0-DF */
539 static
540 unsigned char cv[]= {
541     0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
542     0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
543     0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
544     0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
545     0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
546     0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
547     0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
548     0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
549     0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
550     0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
551     0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
552     0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
553     0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
554     0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
555     0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
556     0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
557     0x00,0x00};
558
559
560 /* X0201 kana conversion table for daguten */
561 /* 90-9F A0-DF */
562 static
563 unsigned char dv[]= { 
564     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
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,0x25,0x74,
569     0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
570     0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
571     0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
572     0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
573     0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
574     0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
575     0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
576     0x00,0x00,0x00,0x00,0x00,0x00,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};
581
582 /* X0201 kana conversion table for han-daguten */
583 /* 90-9F A0-DF */
584 static
585 unsigned char ev[]= { 
586     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
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,0x25,0x51,0x25,0x54,
597     0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
598     0x00,0x00,0x00,0x00,0x00,0x00,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};
603
604
605 /* X0208 kigou conversion table */
606 /* 0x8140 - 0x819e */
607 static
608 unsigned char fv[] = {
609
610     0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
611     0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
612     0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
613     0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
614     0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
615     0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
616     0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
617     0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
618     0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
619     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
620     0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
621     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
622 } ;
623
624
625 #define    CRLF      1
626
627 static int             file_out = FALSE;
628 #ifdef OVERWRITE
629 static int             overwrite = FALSE;
630 #endif
631
632 static int             crmode_f = 0;   /* CR, NL, CRLF */
633 #ifdef EASYWIN /*Easy Win */
634 static int             end_check;
635 #endif /*Easy Win */
636
637 #ifndef PERL_XS
638 int
639 main(argc, argv)
640     int             argc;
641     char          **argv;
642 {
643     FILE  *fin;
644     unsigned char  *cp;
645
646     char *outfname;
647     char *origfname;
648
649 #ifdef EASYWIN /*Easy Win */
650     _BufferSize.y = 400;/*Set Scroll Buffer Size*/
651 #endif
652
653     for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
654         cp = (unsigned char *)*argv;
655         options(cp);
656 #ifdef EXEC_IO
657         if (exec_f){
658             int fds[2], pid;
659             if (pipe(fds) < 0 || (pid = fork()) < 0){
660                 abort();
661             }
662             if (pid == 0){
663                 if (exec_f > 0){
664                     close(fds[0]);
665                     dup2(fds[1], 1);
666                 }else{
667                     close(fds[1]);
668                     dup2(fds[0], 0);
669                 }
670                 execvp(argv[1], &argv[1]);
671             }
672             if (exec_f > 0){
673                 close(fds[1]);
674                 dup2(fds[0], 0);
675             }else{
676                 close(fds[0]);
677                 dup2(fds[1], 1);
678             }
679             argc = 0;
680             break;
681         }
682 #endif
683     }
684     if(x0201_f == WISH_TRUE)
685          x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
686
687     if (binmode_f == TRUE)
688 #ifdef __OS2__
689     if (freopen("","wb",stdout) == NULL) 
690         return (-1);
691 #else
692     setbinmode(stdout);
693 #endif
694
695     if (unbuf_f)
696       setbuf(stdout, (char *) NULL);
697     else
698       setvbuffer(stdout, stdobuf, IOBUF_SIZE);
699
700     if (argc == 0) {
701       if (binmode_f == TRUE)
702 #ifdef __OS2__
703       if (freopen("","rb",stdin) == NULL) return (-1);
704 #else
705       setbinmode(stdin);
706 #endif
707       setvbuffer(stdin, stdibuf, IOBUF_SIZE);
708       if (nop_f)
709           noconvert(stdin);
710       else {
711           kanji_convert(stdin);
712           if (guess_f) print_guessed_code(NULL);
713       }
714     } else {
715       int nfiles = argc;
716       while (argc--) {
717           if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
718               perror(*--argv);
719               return(-1);
720           } else {
721 #ifdef OVERWRITE
722               int fd;
723               int fd_backup;
724 #endif
725
726 /* reopen file for stdout */
727               if (file_out == TRUE) {
728 #ifdef OVERWRITE
729                   if (overwrite){
730                       outfname = malloc(strlen(origfname)
731                                         + strlen(".nkftmpXXXXXX")
732                                         + 1);
733                       if (!outfname){
734                           perror(origfname);
735                           return -1;
736                       }
737                       strcpy(outfname, origfname);
738 #ifdef MSDOS
739                       {
740                           int i;
741                           for (i = strlen(outfname); i; --i){
742                               if (outfname[i - 1] == '/'
743                                   || outfname[i - 1] == '\\'){
744                                   break;
745                               }
746                           }
747                           outfname[i] = '\0';
748                       }
749                       strcat(outfname, "ntXXXXXX");
750                       mktemp(outfname);
751                       fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC,
752                                 S_IREAD | S_IWRITE);
753 #else
754                       strcat(outfname, ".nkftmpXXXXXX");
755                       fd = mkstemp(outfname);
756 #endif
757                       if (fd < 0
758                           || (fd_backup = dup(fileno(stdout))) < 0
759                           || dup2(fd, fileno(stdout)) < 0
760                           ){
761                           perror(origfname);
762                           return -1;
763                       }
764                   }else
765 #endif
766                   if(argc == 1 ) {
767                       outfname = *argv++;
768                       argc--;
769                   } else {
770                       outfname = "nkf.out";
771                   }
772
773                   if(freopen(outfname, "w", stdout) == NULL) {
774                       perror (outfname);
775                       return (-1);
776                   }
777                   if (binmode_f == TRUE) {
778 #ifdef __OS2__
779                       if (freopen("","wb",stdout) == NULL) 
780                            return (-1);
781 #else
782                       setbinmode(stdout);
783 #endif
784                   }
785               }
786               if (binmode_f == TRUE)
787 #ifdef __OS2__
788                  if (freopen("","rb",fin) == NULL) 
789                     return (-1);
790 #else
791                  setbinmode(fin);
792 #endif 
793               setvbuffer(fin, stdibuf, IOBUF_SIZE);
794               if (nop_f)
795                   noconvert(fin);
796               else {
797                   char *filename = NULL;
798                   kanji_convert(fin);
799                   if (nfiles > 1) filename = origfname;
800                   if (guess_f) print_guessed_code(filename);
801               }
802               fclose(fin);
803 #ifdef OVERWRITE
804               if (overwrite) {
805                   struct stat     sb;
806 #if defined(MSDOS) && !defined(__MINGW32__)
807                   time_t tb[2];
808 #else
809                   struct utimbuf  tb;
810 #endif
811
812                   fflush(stdout);
813                   close(fd);
814                   if (dup2(fd_backup, fileno(stdout)) < 0){
815                       perror("dup2");
816                   }
817                   if (stat(origfname, &sb)) {
818                       fprintf(stderr, "Can't stat %s\n", origfname);
819                   }
820                   /* \e$B%Q!<%_%C%7%g%s$rI|85\e(B */
821                   if (chmod(outfname, sb.st_mode)) {
822                       fprintf(stderr, "Can't set permission %s\n", outfname);
823                   }
824
825                   /* \e$B%?%$%`%9%?%s%W$rI|85\e(B */
826 #if defined(MSDOS) && !defined(__MINGW32__)
827                   tb[0] = tb[1] = sb.st_mtime;
828                   if (utime(outfname, tb)) {
829                       fprintf(stderr, "Can't set timestamp %s\n", outfname);
830                   }
831 #else
832                   tb.actime  = sb.st_atime;
833                   tb.modtime = sb.st_mtime;
834                   if (utime(outfname, &tb)) {
835                       fprintf(stderr, "Can't set timestamp %s\n", outfname);
836                   }
837 #endif
838 #ifdef MSDOS
839                   if (unlink(origfname)){
840                       perror(origfname);
841                   }
842 #endif
843                   if (rename(outfname, origfname)) {
844                       perror(origfname);
845                       fprintf(stderr, "Can't rename %s to %s\n",
846                               outfname, origfname);
847                   }
848                   free(outfname);
849               }
850 #endif
851           }
852       }
853     }
854 #ifdef EASYWIN /*Easy Win */
855     if (file_out == FALSE) 
856         scanf("%d",&end_check);
857     else 
858         fclose(stdout);
859 #else /* for Other OS */
860     if (file_out == TRUE) 
861         fclose(stdout);
862 #endif 
863     return (0);
864 }
865 #endif
866
867 static 
868 struct {
869     char *name;
870     char *alias;
871 } long_option[] = {
872     {"base64","jMB"},
873     {"euc","e"},
874     {"euc-input","E"},
875     {"fj","jm"},
876     {"help","v"},
877     {"jis","j"},
878     {"jis-input","J"},
879     {"mac","sLm"},
880     {"mime","jM"},
881     {"mime-input","m"},
882     {"msdos","sLw"},
883     {"sjis","s"},
884     {"sjis-input","S"},
885     {"unix","eLu"},
886     {"version","V"},
887     {"windows","sLw"},
888     {"hiragana","h1"},
889     {"katakana","h2"},
890     {"katakana-hiragana","h3"},
891     {"guess", "g"},
892 #ifdef UTF8_OUTPUT_ENABLE
893     {"utf8", "w"},
894     {"utf16", "w16"},
895 #endif
896 #ifdef UTF8_INPUT_ENABLE
897     {"utf8-input", "W"},
898     {"utf16-input", "W16"},
899 #endif
900 #ifdef OVERWRITE
901     {"overwrite", ""},
902 #endif
903 #ifdef INPUT_OPTION
904     {"cap-input", ""},
905     {"url-input", ""},
906 #endif
907 #ifdef NUMCHAR_OPTION
908     {"numchar-input", ""},
909 #endif
910 #ifdef CHECK_OPTION
911     {"no-output", ""},
912     {"debug", ""},
913 #endif
914 #ifdef SHIFTJIS_CP932
915     {"no-cp932", ""},
916     {"cp932inv", ""},
917 #endif
918 #ifdef EXEC_IO
919     {"exec-in", ""},
920     {"exec-out", ""},
921 #endif
922     {"prefix=", ""},
923 };
924
925 static int option_mode;
926
927 void
928 options(cp) 
929      unsigned char *cp;
930 {
931     int i;
932     unsigned char *p;
933
934     if (option_mode==1)
935         return;
936     if (*cp++ != '-') 
937         return;
938     while (*cp) {
939         switch (*cp++) {
940         case '-':  /* literal options */
941             if (!*cp) {        /* ignore the rest of arguments */
942                 option_mode = 1;
943                 return;
944             }
945             for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
946                 int j;
947                 p = (unsigned char *)long_option[i].name;
948                 for (j=0;*p && (*p != '=') && *p == cp[j];p++, j++);
949                 if (*p == cp[j]){
950                   p = &cp[j];
951                   break;
952                 }
953                 p = 0;
954             }
955             if (p == 0) return;
956             cp = (unsigned char *)long_option[i].alias;
957             if (!*cp){
958 #ifdef OVERWRITE
959                 if (strcmp(long_option[i].name, "overwrite") == 0){
960                     file_out = TRUE;
961                     overwrite = TRUE;
962                     continue;
963                 }
964 #endif
965 #ifdef INPUT_OPTION
966                 if (strcmp(long_option[i].name, "cap-input") == 0){
967                     cap_f = TRUE;
968                     continue;
969                 }
970                 if (strcmp(long_option[i].name, "url-input") == 0){
971                     url_f = TRUE;
972                     continue;
973                 }
974 #endif
975 #ifdef NUMCHAR_OPTION
976                 if (strcmp(long_option[i].name, "numchar-input") == 0){
977                     numchar_f = TRUE;
978                     continue;
979                 }
980 #endif
981 #ifdef CHECK_OPTION
982                 if (strcmp(long_option[i].name, "no-output") == 0){
983                     noout_f = TRUE;
984                     continue;
985                 }
986                 if (strcmp(long_option[i].name, "debug") == 0){
987                     debug_f = TRUE;
988                     continue;
989                 }
990 #endif
991 #ifdef SHIFTJIS_CP932
992                 if (strcmp(long_option[i].name, "no-cp932") == 0){
993                     cp932_f = FALSE;
994                     continue;
995                 }
996                 if (strcmp(long_option[i].name, "cp932inv") == 0){
997                     cp932inv_f = TRUE;
998                     continue;
999                 }
1000 #endif
1001 #ifdef EXEC_IO
1002                   if (strcmp(long_option[i].name, "exec-in") == 0){
1003                       exec_f = 1;
1004                       return;
1005                   }
1006                   if (strcmp(long_option[i].name, "exec-out") == 0){
1007                       exec_f = -1;
1008                       return;
1009                   }
1010 #endif
1011                 if (strcmp(long_option[i].name, "prefix=") == 0){
1012                     if (*p == '=' && ' ' < p[1] && p[1] < 128){
1013                         for (i = 2; ' ' < p[i] && p[i] < 128; i++){
1014                             prefix_table[p[i]] = p[1];
1015                         }
1016                     }
1017                     continue;
1018                 }
1019             }
1020             continue;
1021         case 'b':           /* buffered mode */
1022             unbuf_f = FALSE;
1023             continue;
1024         case 'u':           /* non bufferd mode */
1025             unbuf_f = TRUE;
1026             continue;
1027         case 't':           /* transparent mode */
1028             nop_f = TRUE;
1029             continue;
1030         case 'j':           /* JIS output */
1031         case 'n':
1032             output_conv = j_oconv;
1033             continue;
1034         case 'e':           /* AT&T EUC output */
1035             output_conv = e_oconv;
1036             continue;
1037         case 's':           /* SJIS output */
1038             output_conv = s_oconv;
1039             continue;
1040         case 'l':           /* ISO8859 Latin-1 support, no conversion */
1041             iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
1042             input_f = LATIN1_INPUT;
1043             continue;
1044         case 'i':           /* Kanji IN ESC-$-@/B */
1045             if (*cp=='@'||*cp=='B') 
1046                 kanji_intro = *cp++;
1047             continue;
1048         case 'o':           /* ASCII IN ESC-(-J/B */
1049             if (*cp=='J'||*cp=='B'||*cp=='H') 
1050                 ascii_intro = *cp++;
1051             continue;
1052         case 'h':
1053             /*  
1054                 bit:1   hira -> kata
1055                 bit:2   kata -> hira
1056             */
1057             if ('9'>= *cp && *cp>='0') 
1058                 hira_f |= (*cp++ -'0');
1059             else 
1060                 hira_f |= 1;
1061             continue;
1062         case 'r':
1063             rot_f = TRUE;
1064             continue;
1065 #if defined(MSDOS) || defined(__OS2__) 
1066         case 'T':
1067             binmode_f = FALSE;
1068             continue;
1069 #endif
1070 #ifndef PERL_XS
1071         case 'V':
1072             version();
1073             exit(1);
1074             break;
1075         case 'v':
1076             usage();
1077             exit(1);
1078             break;
1079 #endif
1080 #ifdef UTF8_OUTPUT_ENABLE
1081         case 'w':           /* UTF-8 output */
1082             if ('1'== cp[0] && '6'==cp[1]) {
1083                 output_conv = w_oconv16; cp+=2;
1084                 if (cp[0]=='L') {
1085                     unicode_bom_f=2; cp++;
1086                     w_oconv16_LE = 1;
1087                     if (cp[0] == '0'){
1088                         unicode_bom_f=1; cp++;
1089                     }
1090                 } else if (cp[0] == 'B') {
1091                     unicode_bom_f=2; cp++;
1092                     if (cp[0] == '0'){
1093                         unicode_bom_f=1; cp++;
1094                     }
1095                 }
1096             } else if (cp[0] == '8') {
1097                 output_conv = w_oconv; cp++;
1098                 unicode_bom_f=2;
1099                 if (cp[0] == '0'){
1100                     unicode_bom_f=1; cp++;
1101                 }
1102             } else
1103                 output_conv = w_oconv;
1104             continue;
1105 #endif
1106 #ifdef UTF8_INPUT_ENABLE
1107         case 'W':           /* UTF-8 input */
1108             if ('1'== cp[0] && '6'==cp[1]) {
1109                 input_f = UTF16LE_INPUT;
1110                 if (cp[0]=='L') {
1111                     cp++;
1112                 } else if (cp[0] == 'B') {
1113                     cp++;
1114                     input_f = UTF16BE_INPUT;
1115                 }
1116             } else
1117                 input_f = UTF8_INPUT;
1118             continue;
1119 #endif
1120         /* Input code assumption */
1121         case 'J':   /* JIS input */
1122         case 'E':   /* AT&T EUC input */
1123             input_f = JIS_INPUT;
1124             continue;
1125         case 'S':   /* MS Kanji input */
1126             input_f = SJIS_INPUT;
1127             if (x0201_f==NO_X0201) x0201_f=TRUE;
1128             continue;
1129         case 'Z':   /* Convert X0208 alphabet to asii */
1130             /*  bit:0   Convert X0208
1131                 bit:1   Convert Kankaku to one space
1132                 bit:2   Convert Kankaku to two spaces
1133                 bit:3   Convert HTML Entity
1134             */
1135             if ('9'>= *cp && *cp>='0') 
1136                 alpha_f |= 1<<(*cp++ -'0');
1137             else 
1138                 alpha_f |= TRUE;
1139             continue;
1140         case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
1141             x0201_f = FALSE;    /* No X0201->X0208 conversion */
1142             /* accept  X0201
1143                     ESC-(-I     in JIS, EUC, MS Kanji
1144                     SI/SO       in JIS, EUC, MS Kanji
1145                     SSO         in EUC, JIS, not in MS Kanji
1146                     MS Kanji (0xa0-0xdf) 
1147                output  X0201
1148                     ESC-(-I     in JIS (0x20-0x5f)
1149                     SSO         in EUC (0xa0-0xdf)
1150                     0xa0-0xd    in MS Kanji (0xa0-0xdf) 
1151             */
1152             continue;
1153         case 'X':   /* Assume X0201 kana */
1154             /* Default value is NO_X0201 for EUC/MS-Kanji mix */
1155             x0201_f = TRUE;
1156             continue;
1157         case 'F':   /* prserve new lines */
1158             fold_preserve_f = TRUE;
1159         case 'f':   /* folding -f60 or -f */
1160             fold_f = TRUE;
1161             fold_len = 0;
1162             while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
1163                 fold_len *= 10;
1164                 fold_len += *cp++ - '0';
1165             }
1166             if (!(0<fold_len && fold_len<BUFSIZ)) 
1167                 fold_len = DEFAULT_FOLD;
1168             if (*cp=='-') {
1169                 fold_margin = 0;
1170                 cp++;
1171                 while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
1172                     fold_margin *= 10;
1173                     fold_margin += *cp++ - '0';
1174                 }
1175             }
1176             continue;
1177         case 'm':   /* MIME support */
1178             if (*cp=='B'||*cp=='Q') {
1179                 mime_decode_mode = *cp++;
1180                 mimebuf_f = FIXED_MIME;
1181             } else if (*cp=='N') {
1182                 mime_f = TRUE; cp++;
1183             } else if (*cp=='S') {
1184                 mime_f = STRICT_MIME; cp++;
1185             } else if (*cp=='0') {
1186                 mime_f = FALSE; cp++;
1187             }
1188             continue;
1189         case 'M':   /* MIME output */
1190             if (*cp=='B') {
1191                 mimeout_mode = 'B';
1192                 mimeout_f = FIXED_MIME; cp++;
1193             } else if (*cp=='Q') {
1194                 mimeout_mode = 'Q';
1195                 mimeout_f = FIXED_MIME; cp++;
1196             } else {
1197                 mimeout_f = TRUE;
1198             }
1199             continue;
1200         case 'B':   /* Broken JIS support */
1201             /*  bit:0   no ESC JIS
1202                 bit:1   allow any x on ESC-(-x or ESC-$-x
1203                 bit:2   reset to ascii on NL
1204             */
1205             if ('9'>= *cp && *cp>='0') 
1206                 broken_f |= 1<<(*cp++ -'0');
1207             else 
1208                 broken_f |= TRUE;
1209             continue;
1210 #ifndef PERL_XS
1211         case 'O':/* for Output file */
1212             file_out = TRUE;
1213             continue;
1214 #endif
1215         case 'c':/* add cr code */
1216             crmode_f = CRLF;
1217             continue;
1218         case 'd':/* delete cr code */
1219             crmode_f = NL;
1220             continue;
1221         case 'I':   /* ISO-2022-JP output */
1222             iso2022jp_f = TRUE;
1223             continue;
1224         case 'L':  /* line mode */
1225             if (*cp=='u') {         /* unix */
1226                 crmode_f = NL; cp++;
1227             } else if (*cp=='m') { /* mac */
1228                 crmode_f = CR; cp++;
1229             } else if (*cp=='w') { /* windows */
1230                 crmode_f = CRLF; cp++;
1231             } else if (*cp=='0') { /* no conversion  */
1232                 crmode_f = 0; cp++;
1233             }
1234             continue;
1235         case 'g':
1236 #ifndef PERL_XS
1237             guess_f = TRUE;
1238 #endif
1239             continue;
1240         case ' ':    
1241         /* module muliple options in a string are allowed for Perl moudle  */
1242             while(*cp && *cp!='-') cp++;
1243             if(*cp=='-') cp++;
1244             continue;
1245         default:
1246             /* bogus option but ignored */
1247             continue;
1248         }
1249     }
1250 }
1251
1252 #ifdef ANSI_C_PROTOTYPE
1253 struct input_code * find_inputcode_byfunc(int (*iconv_func)(int c2,int c1,int c0))
1254 #else
1255 struct input_code * find_inputcode_byfunc(iconv_func)
1256      int (*iconv_func)();
1257 #endif
1258 {
1259     if (iconv_func){
1260         struct input_code *p = input_code_list;
1261         while (p->name){
1262             if (iconv_func == p->iconv_func){
1263                 return p;
1264             }
1265             p++;
1266         }
1267     }
1268     return 0;
1269 }
1270
1271 #ifdef ANSI_C_PROTOTYPE
1272 void set_iconv(int f, int (*iconv_func)(int c2,int c1,int c0))
1273 #else
1274 void set_iconv(f, iconv_func)
1275      int f;
1276      int (*iconv_func)();
1277 #endif
1278 {
1279 #ifdef CHECK_OPTION
1280     static int (*iconv_for_check)() = 0;
1281 #endif
1282 #ifdef INPUT_CODE_FIX
1283     if (f || !input_f)
1284 #endif
1285         if (estab_f != f){
1286             estab_f = f;
1287         }
1288
1289     if (iconv_func
1290 #ifdef INPUT_CODE_FIX
1291         && (f == -TRUE || !input_f) /* -TRUE means "FORCE" */
1292 #endif
1293         ){
1294         iconv = iconv_func;
1295     }
1296 #ifdef CHECK_OPTION
1297     if (estab_f && iconv_for_check != iconv){
1298         struct input_code *p = find_inputcode_byfunc(iconv);
1299         if (p){
1300             set_input_codename(p->name);
1301             debug(input_codename);
1302         }
1303         iconv_for_check = iconv;
1304     }
1305 #endif
1306 }
1307
1308 #define SCORE_L2       (1)                   /* \e$BBh\e(B2\e$B?e=`4A;z\e(B */
1309 #define SCORE_KANA     (SCORE_L2 << 1)       /* \e$B$$$o$f$kH>3Q%+%J\e(B */
1310 #define SCORE_DEPEND   (SCORE_KANA << 1)     /* \e$B5!<o0MB8J8;z\e(B */
1311 #ifdef SHIFTJIS_CP932
1312 #define SCORE_CP932    (SCORE_DEPEND << 1)   /* CP932 \e$B$K$h$kFI$_49$(\e(B */
1313 #define SCORE_NO_EXIST (SCORE_CP932 << 1)    /* \e$BB8:_$7$J$$J8;z\e(B */
1314 #else
1315 #define SCORE_NO_EXIST (SCORE_DEPEND << 1)   /* \e$BB8:_$7$J$$J8;z\e(B */
1316 #endif
1317 #define SCORE_iMIME    (SCORE_NO_EXIST << 1) /* MIME \e$B$K$h$k;XDj\e(B */
1318 #define SCORE_ERROR    (SCORE_iMIME << 1) /* \e$B%(%i!<\e(B */
1319
1320 #define SCORE_INIT (SCORE_iMIME)
1321
1322 int score_table_A0[] = {
1323     0, 0, 0, 0,
1324     0, 0, 0, 0,
1325     0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1326     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
1327 };
1328
1329 int score_table_F0[] = {
1330     SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
1331     SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
1332     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1333     SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
1334 };
1335
1336 void set_code_score(ptr, score)
1337      struct input_code *ptr;
1338      int score;
1339 {
1340     if (ptr){
1341         ptr->score |= score;
1342     }
1343 }
1344
1345 void clr_code_score(ptr, score)
1346      struct input_code *ptr;
1347      int score;
1348 {
1349     if (ptr){
1350         ptr->score &= ~score;
1351     }
1352 }
1353
1354 void code_score(ptr)
1355      struct input_code *ptr;
1356 {
1357     int c2 = ptr->buf[0];
1358     int c1 = ptr->buf[1];
1359     if (c2 < 0){
1360         set_code_score(ptr, SCORE_ERROR);
1361     }else if (c2 == SSO){
1362         set_code_score(ptr, SCORE_KANA);
1363 #ifdef UTF8_OUTPUT_ENABLE
1364     }else if (!e2w_conv(c2, c1)){
1365         set_code_score(ptr, SCORE_NO_EXIST);
1366 #endif
1367     }else if ((c2 & 0x70) == 0x20){
1368         set_code_score(ptr, score_table_A0[c2 & 0x0f]);
1369     }else if ((c2 & 0x70) == 0x70){
1370         set_code_score(ptr, score_table_F0[c2 & 0x0f]);
1371     }else if ((c2 & 0x70) >= 0x50){
1372         set_code_score(ptr, SCORE_L2);
1373     }
1374 }
1375
1376 void status_disable(ptr)
1377 struct input_code *ptr;
1378 {
1379     ptr->stat = -1;
1380     ptr->buf[0] = -1;
1381     code_score(ptr);
1382     if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
1383 }
1384
1385 void status_push_ch(ptr, c)
1386      struct input_code *ptr;
1387      int c;
1388 {
1389     ptr->buf[ptr->index++] = c;
1390 }
1391
1392 void status_clear(ptr)
1393      struct input_code *ptr;
1394 {
1395     ptr->stat = 0;
1396     ptr->index = 0;
1397 }
1398
1399 void status_reset(ptr)
1400      struct input_code *ptr;
1401 {
1402     status_clear(ptr);
1403     ptr->score = SCORE_INIT;
1404 }
1405
1406 void status_reinit(ptr)
1407      struct input_code *ptr;
1408 {
1409     status_reset(ptr);
1410     ptr->_file_stat = 0;
1411 }
1412
1413 void status_check(ptr, c)
1414      struct input_code *ptr;
1415      int c;
1416 {
1417     if (c <= DEL && estab_f){
1418         status_reset(ptr);
1419     }
1420 }
1421
1422 void s_status(ptr, c)
1423      struct input_code *ptr;
1424      int c;
1425 {
1426     switch(ptr->stat){
1427       case -1:
1428           status_check(ptr, c);
1429           break;
1430       case 0:
1431           if (c <= DEL){
1432               break;
1433 #ifdef NUMCHAR_OPTION
1434           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1435               break;
1436 #endif
1437           }else if (0xa1 <= c && c <= 0xdf){
1438               status_push_ch(ptr, SSO);
1439               status_push_ch(ptr, c);
1440               code_score(ptr);
1441               status_clear(ptr);
1442           }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xef)){
1443               ptr->stat = 1;
1444               status_push_ch(ptr, c);
1445 #ifdef SHIFTJIS_CP932
1446           }else if (cp932_f
1447                     && CP932_TABLE_BEGIN <= c && c <= CP932_TABLE_END){
1448               ptr->stat = 2;
1449               status_push_ch(ptr, c);
1450 #endif /* SHIFTJIS_CP932 */
1451           }else{
1452               status_disable(ptr);
1453           }
1454           break;
1455       case 1:
1456           if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1457               status_push_ch(ptr, c);
1458               s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
1459               code_score(ptr);
1460               status_clear(ptr);
1461           }else{
1462               status_disable(ptr);
1463           }
1464           break;
1465 #ifdef SHIFTJIS_CP932
1466       case 2:
1467           if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1468               status_push_ch(ptr, c);
1469               if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0){
1470                   set_code_score(ptr, SCORE_CP932);
1471                   status_clear(ptr);
1472                   break;
1473               }
1474           }
1475           status_disable(ptr);
1476           break;
1477 #endif /* SHIFTJIS_CP932 */
1478     }
1479 }
1480
1481 void e_status(ptr, c)
1482      struct input_code *ptr;
1483      int c;
1484 {
1485     switch (ptr->stat){
1486       case -1:
1487           status_check(ptr, c);
1488           break;
1489       case 0:
1490           if (c <= DEL){
1491               break;
1492 #ifdef NUMCHAR_OPTION
1493           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1494               break;
1495 #endif
1496           }else if (SSO == c || (0xa1 <= c && c <= 0xfe)){
1497               ptr->stat = 1;
1498               status_push_ch(ptr, c);
1499           }else{
1500               status_disable(ptr);
1501           }
1502           break;
1503       case 1:
1504           if (0xa1 <= c && c <= 0xfe){
1505               status_push_ch(ptr, c);
1506               code_score(ptr);
1507               status_clear(ptr);
1508           }else{
1509               status_disable(ptr);
1510           }
1511           break;
1512     }
1513 }
1514
1515 #ifdef UTF8_INPUT_ENABLE
1516 void w16_status(ptr, c)
1517      struct input_code *ptr;
1518      int c;
1519 {
1520     switch (ptr->stat){
1521       case -1:
1522           break;
1523       case 0:
1524           if (ptr->_file_stat == 0){
1525               if (c == 0xfe || c == 0xff){
1526                   ptr->stat = c;
1527                   status_push_ch(ptr, c);
1528                   ptr->_file_stat = 1;
1529               }else{
1530                   status_disable(ptr);
1531                   ptr->_file_stat = -1;
1532               }
1533           }else if (ptr->_file_stat > 0){
1534               ptr->stat = 1;
1535               status_push_ch(ptr, c);
1536           }else if (ptr->_file_stat < 0){
1537               status_disable(ptr);
1538           }
1539           break;
1540
1541       case 1:
1542           if (c == EOF){
1543               status_disable(ptr);
1544               ptr->_file_stat = -1;
1545           }else{
1546               status_push_ch(ptr, c);
1547               status_clear(ptr);
1548           }
1549           break;
1550
1551       case 0xfe:
1552       case 0xff:
1553           if (ptr->stat != c && (c == 0xfe || c == 0xff)){
1554               status_push_ch(ptr, c);
1555               status_clear(ptr);
1556           }else{
1557               status_disable(ptr);
1558               ptr->_file_stat = -1;
1559           }
1560           break;
1561     }
1562 }
1563
1564 void w_status(ptr, c)
1565      struct input_code *ptr;
1566      int c;
1567 {
1568     switch (ptr->stat){
1569       case -1:
1570           status_check(ptr, c);
1571           break;
1572       case 0:
1573           if (c <= DEL){
1574               break;
1575 #ifdef NUMCHAR_OPTION
1576           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1577               break;
1578 #endif
1579           }else if (0xc0 <= c && c <= 0xdf){
1580               ptr->stat = 1;
1581               status_push_ch(ptr, c);
1582           }else if (0xe0 <= c && c <= 0xef){
1583               ptr->stat = 2;
1584               status_push_ch(ptr, c);
1585           }else{
1586               status_disable(ptr);
1587           }
1588           break;
1589       case 1:
1590       case 2:
1591           if (0x80 <= c && c <= 0xbf){
1592               status_push_ch(ptr, c);
1593               if (ptr->index > ptr->stat){
1594                   int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
1595                              && ptr->buf[2] == 0xbf);
1596                   w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
1597                            &ptr->buf[0], &ptr->buf[1]);
1598                   if (!bom){
1599                       code_score(ptr);
1600                   }
1601                   status_clear(ptr);
1602               }
1603           }else{
1604               status_disable(ptr);
1605           }
1606           break;
1607     }
1608 }
1609 #endif
1610
1611 void
1612 code_status(c)
1613      int c;
1614 {
1615     int action_flag = 1;
1616     struct input_code *result = 0;
1617     struct input_code *p = input_code_list;
1618     while (p->name){
1619         (p->status_func)(p, c);
1620         if (p->stat > 0){
1621             action_flag = 0;
1622         }else if(p->stat == 0){
1623             if (result){
1624                 action_flag = 0;
1625             }else{
1626                 result = p;
1627             }
1628         }
1629         ++p;
1630     }
1631
1632     if (action_flag){
1633         if (result && !estab_f){
1634             set_iconv(TRUE, result->iconv_func);
1635         }else if (c <= DEL){
1636             struct input_code *ptr = input_code_list;
1637             while (ptr->name){
1638                 status_reset(ptr);
1639                 ++ptr;
1640             }
1641         }
1642     }
1643 }
1644
1645 #ifdef PERL_XS
1646 #define STD_GC_BUFSIZE (256)
1647 int std_gc_buf[STD_GC_BUFSIZE];
1648 int std_gc_ndx;
1649 #endif
1650
1651 int 
1652 std_getc(f)
1653 FILE *f;
1654 {
1655 #ifdef PERL_XS
1656     if (std_gc_ndx){
1657         return std_gc_buf[--std_gc_ndx];
1658     }
1659 #endif
1660     return getc(f);
1661 }
1662
1663 int 
1664 std_ungetc(c,f)
1665 int c;
1666 FILE *f;
1667 {
1668 #ifdef PERL_XS
1669     if (std_gc_ndx == STD_GC_BUFSIZE){
1670         return EOF;
1671     }
1672     std_gc_buf[std_gc_ndx++] = c;
1673     return c;
1674 #endif
1675     return ungetc(c,f);
1676 }
1677
1678 void 
1679 std_putc(c)
1680 int c;
1681 {
1682     if(c!=EOF)
1683       putchar(c);
1684 }
1685
1686 int
1687 noconvert(f)
1688     FILE  *f;
1689 {
1690     int    c;
1691
1692     while ((c = (*i_getc)(f)) != EOF)
1693       (*o_putc)(c);
1694     return 1;
1695 }
1696
1697
1698 void
1699 module_connection()
1700 {
1701     oconv = output_conv; 
1702     o_putc = std_putc;
1703
1704     /* replace continucation module, from output side */
1705
1706     /* output redicrection */
1707 #ifdef CHECK_OPTION
1708     if (noout_f || guess_f){
1709         o_putc = no_putc;
1710     }
1711 #endif
1712     if (mimeout_f) {
1713         o_mputc = o_putc;
1714         o_putc = mime_putc;
1715         if (mimeout_f == TRUE) {
1716             o_base64conv = oconv; oconv = base64_conv;
1717         }
1718         /* base64_count = 0; */
1719     }
1720
1721     if (crmode_f) {
1722         o_crconv = oconv; oconv = cr_conv;
1723     }
1724     if (rot_f) {
1725         o_rot_conv = oconv; oconv = rot_conv;
1726     }
1727     if (iso2022jp_f) {
1728         o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
1729     }
1730     if (hira_f) {
1731         o_hira_conv = oconv; oconv = hira_conv;
1732     }
1733     if (fold_f) {
1734         o_fconv = oconv; oconv = fold_conv;
1735         f_line = 0;
1736     }
1737     if (alpha_f || x0201_f) {
1738         o_zconv = oconv; oconv = z_conv;
1739     }
1740
1741     i_getc = std_getc;
1742     i_ungetc = std_ungetc;
1743     /* input redicrection */
1744 #ifdef INPUT_OPTION
1745     if (cap_f){
1746         i_cgetc = i_getc; i_getc = cap_getc;
1747         i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
1748     }
1749     if (url_f){
1750         i_ugetc = i_getc; i_getc = url_getc;
1751         i_uungetc = i_ungetc; i_ungetc= url_ungetc;
1752     }
1753 #endif
1754 #ifdef NUMCHAR_OPTION
1755     if (numchar_f){
1756         i_ngetc = i_getc; i_getc = numchar_getc;
1757         i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
1758     }
1759 #endif
1760     if (mime_f && mimebuf_f==FIXED_MIME) {
1761         i_mgetc = i_getc; i_getc = mime_getc;
1762         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
1763     }
1764     if (broken_f & 1) {
1765         i_bgetc = i_getc; i_getc = broken_getc;
1766         i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
1767     }
1768     if (input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
1769         set_iconv(-TRUE, e_iconv);
1770     } else if (input_f == SJIS_INPUT) {
1771         set_iconv(-TRUE, s_iconv);
1772 #ifdef UTF8_INPUT_ENABLE
1773     } else if (input_f == UTF8_INPUT) {
1774         set_iconv(-TRUE, w_iconv);
1775     } else if (input_f == UTF16LE_INPUT) {
1776         set_iconv(-TRUE, w_iconv16);
1777 #endif
1778     } else {
1779         set_iconv(FALSE, e_iconv);
1780     }
1781
1782     {
1783         struct input_code *p = input_code_list;
1784         while (p->name){
1785             status_reinit(p++);
1786         }
1787     }
1788 }
1789
1790 /*
1791    Conversion main loop. Code detection only. 
1792  */
1793
1794 int
1795 kanji_convert(f)
1796     FILE  *f;
1797 {
1798     int    c1,
1799                     c2, c3;
1800
1801     module_connection();
1802     c2 = 0;
1803
1804
1805     input_mode = ASCII;
1806     output_mode = ASCII;
1807     shift_mode = FALSE;
1808
1809 #define NEXT continue      /* no output, get next */
1810 #define SEND ;             /* output c1 and c2, get next */
1811 #define LAST break         /* end of loop, go closing  */
1812
1813     while ((c1 = (*i_getc)(f)) != EOF) {
1814         code_status(c1);
1815         if (c2) {
1816             /* second byte */
1817             if (c2 > DEL) {
1818                 /* in case of 8th bit is on */
1819                 if (!estab_f) {
1820                     /* in case of not established yet */
1821                     /* It is still ambiguious */
1822                     if (h_conv(f, c2, c1)==EOF) 
1823                         LAST;
1824                     else 
1825                         c2 = 0;
1826                     NEXT;
1827                 } else
1828                     /* in case of already established */
1829                     if (c1 < AT) {
1830                         /* ignore bogus code */
1831                         c2 = 0;
1832                         NEXT;
1833                     } else
1834                         SEND;
1835             } else
1836                 /* second byte, 7 bit code */
1837                 /* it might be kanji shitfted */
1838                 if ((c1 == DEL) || (c1 <= SPACE)) {
1839                     /* ignore bogus first code */
1840                     c2 = 0;
1841                     NEXT;
1842                 } else
1843                     SEND;
1844         } else {
1845             /* first byte */
1846             if (
1847 #ifdef UTF8_INPUT_ENABLE
1848                 iconv == w_iconv16
1849 #else
1850                 0
1851 #endif
1852                 ) {
1853                 c2 = c1;
1854                 c1 = (*i_getc)(f);
1855                 SEND;
1856 #ifdef NUMCHAR_OPTION
1857             } else if ((c1 & CLASS_MASK) == CLASS_UTF16){
1858                 SEND;
1859 #endif
1860             } else if (c1 > DEL) {
1861                 /* 8 bit code */
1862                 if (!estab_f && !iso8859_f) {
1863                     /* not established yet */
1864                     c2 = c1;
1865                     NEXT;
1866                 } else { /* estab_f==TRUE */
1867                     if (iso8859_f) {
1868                         c2 = ISO8859_1;
1869                         c1 &= 0x7f;
1870                         SEND;
1871                     } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
1872                         /* SJIS X0201 Case... */
1873                         if(iso2022jp_f && x0201_f==NO_X0201) {
1874                             (*oconv)(GETA1, GETA2);
1875                             NEXT;
1876                         } else {
1877                             c2 = X0201;
1878                             c1 &= 0x7f;
1879                             SEND;
1880                         }
1881                     } else if (c1==SSO && iconv != s_iconv) {
1882                         /* EUC X0201 Case */
1883                         c1 = (*i_getc)(f);  /* skip SSO */
1884                         code_status(c1);
1885                         if (SSP<=c1 && c1<0xe0) {
1886                             if(iso2022jp_f &&  x0201_f==NO_X0201) {
1887                                 (*oconv)(GETA1, GETA2);
1888                                 NEXT;
1889                             } else {
1890                                 c2 = X0201;
1891                                 c1 &= 0x7f;
1892                                 SEND;
1893                             }
1894                         } else  { /* bogus code, skip SSO and one byte */
1895                             NEXT;
1896                         }
1897                     } else {
1898                        /* already established */
1899                        c2 = c1;
1900                        NEXT;
1901                     }
1902                 }
1903             } else if ((c1 > SPACE) && (c1 != DEL)) {
1904                 /* in case of Roman characters */
1905                 if (shift_mode) { 
1906                     /* output 1 shifted byte */
1907                     if (iso8859_f) {
1908                         c2 = ISO8859_1;
1909                         SEND;
1910                     } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
1911                       /* output 1 shifted byte */
1912                         if(iso2022jp_f && x0201_f==NO_X0201) {
1913                             (*oconv)(GETA1, GETA2);
1914                             NEXT;
1915                         } else {
1916                             c2 = X0201;
1917                             SEND;
1918                         }
1919                     } else {
1920                         /* look like bogus code */
1921                         NEXT;
1922                     }
1923                 } else if (input_mode == X0208) {
1924                     /* in case of Kanji shifted */
1925                     c2 = c1;
1926                     NEXT;
1927                 } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
1928                     /* Check MIME code */
1929                     if ((c1 = (*i_getc)(f)) == EOF) {
1930                         (*oconv)(0, '=');
1931                         LAST;
1932                     } else if (c1 == '?') {
1933                         /* =? is mime conversion start sequence */
1934                         if(mime_f == STRICT_MIME) {
1935                             /* check in real detail */
1936                             if (mime_begin_strict(f) == EOF) 
1937                                 LAST;
1938                             else
1939                                 NEXT;
1940                         } else if (mime_begin(f) == EOF) 
1941                             LAST;
1942                         else
1943                             NEXT;
1944                     } else {
1945                         (*oconv)(0, '=');
1946                         (*i_ungetc)(c1,f);
1947                         NEXT;
1948                     }
1949                 } else {
1950                     /* normal ASCII code */ 
1951                     SEND;
1952                 }
1953             } else if (c1 == SI) {
1954                 shift_mode = FALSE; 
1955                 NEXT;
1956             } else if (c1 == SO) {
1957                 shift_mode = TRUE; 
1958                 NEXT;
1959             } else if (c1 == ESC ) {
1960                 if ((c1 = (*i_getc)(f)) == EOF) {
1961                     /*  (*oconv)(0, ESC); don't send bogus code */
1962                     LAST;
1963                 } else if (c1 == '$') {
1964                     if ((c1 = (*i_getc)(f)) == EOF) {
1965                         /*
1966                         (*oconv)(0, ESC); don't send bogus code 
1967                         (*oconv)(0, '$'); */
1968                         LAST;
1969                     } else if (c1 == '@'|| c1 == 'B') {
1970                         /* This is kanji introduction */
1971                         input_mode = X0208;
1972                         shift_mode = FALSE;
1973                         set_input_codename("ISO-2022-JP");
1974                         debug(input_codename);
1975                         NEXT;
1976                     } else if (c1 == '(') {
1977                         if ((c1 = (*i_getc)(f)) == EOF) {
1978                             /* don't send bogus code 
1979                             (*oconv)(0, ESC);
1980                             (*oconv)(0, '$');
1981                             (*oconv)(0, '(');
1982                                 */
1983                             LAST;
1984                         } else if (c1 == '@'|| c1 == 'B') {
1985                             /* This is kanji introduction */
1986                             input_mode = X0208;
1987                             shift_mode = FALSE;
1988                             NEXT;
1989                         } else {
1990                             /* could be some special code */
1991                             (*oconv)(0, ESC);
1992                             (*oconv)(0, '$');
1993                             (*oconv)(0, '(');
1994                             (*oconv)(0, c1);
1995                             NEXT;
1996                         }
1997                     } else if (broken_f&0x2) {
1998                         /* accept any ESC-(-x as broken code ... */
1999                         input_mode = X0208;
2000                         shift_mode = FALSE;
2001                         NEXT;
2002                     } else {
2003                         (*oconv)(0, ESC);
2004                         (*oconv)(0, '$');
2005                         (*oconv)(0, c1);
2006                         NEXT;
2007                     }
2008                 } else if (c1 == '(') {
2009                     if ((c1 = (*i_getc)(f)) == EOF) {
2010                         /* don't send bogus code 
2011                         (*oconv)(0, ESC);
2012                         (*oconv)(0, '('); */
2013                         LAST;
2014                     } else {
2015                         if (c1 == 'I') {
2016                             /* This is X0201 kana introduction */
2017                             input_mode = X0201; shift_mode = X0201;
2018                             NEXT;
2019                         } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
2020                             /* This is X0208 kanji introduction */
2021                             input_mode = ASCII; shift_mode = FALSE;
2022                             NEXT;
2023                         } else if (broken_f&0x2) {
2024                             input_mode = ASCII; shift_mode = FALSE;
2025                             NEXT;
2026                         } else {
2027                             (*oconv)(0, ESC);
2028                             (*oconv)(0, '(');
2029                             /* maintain various input_mode here */
2030                             SEND;
2031                         }
2032                     }
2033                } else if ( c1 == 'N' || c1 == 'n' ){
2034                    /* SS2 */
2035                    c3 = (*i_getc)(f);  /* skip SS2 */
2036                    if ( (SPACE<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
2037                        c1 = c3;
2038                        c2 = X0201;
2039                        SEND;
2040                    }else{
2041                        (*i_ungetc)(c3, f);
2042                        /* lonely ESC  */
2043                        (*oconv)(0, ESC);
2044                        SEND;
2045                    }
2046                 } else {
2047                     /* lonely ESC  */
2048                     (*oconv)(0, ESC);
2049                     SEND;
2050                 }
2051             } else if ((c1 == NL || c1 == CR) && broken_f&4) {
2052                 input_mode = ASCII; set_iconv(FALSE, 0);
2053                 SEND;
2054             } else 
2055                 SEND;
2056         }
2057         /* send: */
2058         if (input_mode == X0208) 
2059             (*oconv)(c2, c1);  /* this is JIS, not SJIS/EUC case */
2060         else if (input_mode) 
2061             (*oconv)(input_mode, c1);  /* other special case */
2062         else if ((*iconv)(c2, c1, 0) < 0){  /* can be EUC/SJIS */
2063             int c0 = (*i_getc)(f);
2064             if (c0 != EOF){
2065                 code_status(c0);
2066                 (*iconv)(c2, c1, c0);
2067             }
2068         }
2069
2070         c2 = 0;
2071         continue;
2072         /* goto next_word */
2073     }
2074
2075     /* epilogue */
2076     (*iconv)(EOF, 0, 0);
2077     return 1;
2078 }
2079
2080 int
2081 h_conv(f, c2, c1)
2082     FILE  *f;
2083     int    c1,
2084                     c2;
2085 {
2086     int    wc,c3;
2087
2088
2089     /** it must NOT be in the kanji shifte sequence      */
2090     /** it must NOT be written in JIS7                   */
2091     /** and it must be after 2 byte 8bit code            */
2092
2093     hold_count = 0;
2094     push_hold_buf(c2);
2095     push_hold_buf(c1);
2096     c2 = 0;
2097
2098     while ((c1 = (*i_getc)(f)) != EOF) {
2099         if (c1 == ESC){
2100             (*i_ungetc)(c1,f);
2101             break;
2102         }
2103         code_status(c1);
2104         if (push_hold_buf(c1) == EOF || estab_f){
2105             break;
2106         }
2107     }
2108
2109     if (!estab_f){
2110         struct input_code *p = input_code_list;
2111         struct input_code *result = p;
2112         if (c1 == EOF){
2113             code_status(c1);
2114         }
2115         while (p->name){
2116             if (p->score < result->score){
2117                 result = p;
2118             }
2119             ++p;
2120         }
2121         set_iconv(FALSE, result->iconv_func);
2122     }
2123
2124
2125     /** now,
2126      ** 1) EOF is detected, or
2127      ** 2) Code is established, or
2128      ** 3) Buffer is FULL (but last word is pushed)
2129      **
2130      ** in 1) and 3) cases, we continue to use
2131      ** Kanji codes by oconv and leave estab_f unchanged.
2132      **/
2133
2134     c3=c1;
2135     wc = 0;
2136     while (wc < hold_count){
2137         c2 = hold_buf[wc++];
2138         if (c2 <= DEL
2139 #ifdef NUMCHAR_OPTION
2140             || (c2 & CLASS_MASK) == CLASS_UTF16
2141 #endif
2142             ){
2143             (*iconv)(0, c2, 0);
2144             continue;
2145         }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
2146             (*iconv)(X0201, c2, 0);
2147             continue;
2148         }
2149         if (wc < hold_count){
2150             c1 = hold_buf[wc++];
2151         }else{
2152             c1 = (*i_getc)(f);
2153             if (c1 == EOF){
2154                 c3 = EOF;
2155                 break;
2156             }
2157             code_status(c1);
2158         }
2159         if ((*iconv)(c2, c1, 0) < 0){
2160             int c0;
2161             if (wc < hold_count){
2162                 c0 = hold_buf[wc++];
2163             }else{
2164                 c0 = (*i_getc)(f);
2165                 if (c0 == EOF){
2166                     c3 = EOF;
2167                     break;
2168                 }
2169                 code_status(c0);
2170             }
2171             (*iconv)(c2, c1, c0);
2172             c1 = c0;
2173         }
2174     }
2175     return c3;
2176 }
2177
2178
2179
2180 int
2181 push_hold_buf(c2)
2182      int             c2;
2183 {
2184     if (hold_count >= HOLD_SIZE*2)
2185         return (EOF);
2186     hold_buf[hold_count++] = c2;
2187     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
2188 }
2189
2190 int s2e_conv(c2, c1, p2, p1)
2191      int c2, c1;
2192      int *p2, *p1;
2193 {
2194 #ifdef SHIFTJIS_CP932
2195     if (cp932_f && CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END){
2196         extern unsigned short shiftjis_cp932[3][189];
2197         c1 = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
2198         if (c1 == 0) return 1;
2199         c2 = c1 >> 8;
2200         c1 &= 0xff;
2201     }
2202 #endif /* SHIFTJIS_CP932 */
2203     c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
2204     if (c1 < 0x9f)
2205         c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
2206     else {
2207         c1 = c1 - 0x7e;
2208         c2++;
2209     }
2210     if (p2) *p2 = c2;
2211     if (p1) *p1 = c1;
2212     return 0;
2213 }
2214
2215 int
2216 s_iconv(c2, c1, c0)
2217     int    c2,
2218                     c1, c0;
2219 {
2220     if (c2 == X0201) {
2221         c1 &= 0x7f;
2222     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2223         /* NOP */
2224     } else {
2225         int ret = s2e_conv(c2, c1, &c2, &c1);
2226         if (ret) return ret;
2227     }
2228     (*oconv)(c2, c1);
2229     return 0;
2230 }
2231
2232 int
2233 e_iconv(c2, c1, c0)
2234     int    c2,
2235                     c1, c0;
2236 {
2237     if (c2 == X0201) {
2238         c1 &= 0x7f;
2239     } else if (c2 == SSO){
2240         c2 = X0201;
2241         c1 &= 0x7f;
2242     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2243         /* NOP */
2244     } else {
2245         c1 &= 0x7f;
2246         c2 &= 0x7f;
2247     }
2248     (*oconv)(c2, c1);
2249     return 0;
2250 }
2251
2252 #ifdef UTF8_INPUT_ENABLE
2253 int
2254 w2e_conv(c2, c1, c0, p2, p1)
2255     int    c2, c1, c0;
2256     int *p2, *p1;
2257 {
2258     extern unsigned short * utf8_to_euc_2bytes[];
2259     extern unsigned short ** utf8_to_euc_3bytes[];
2260     int ret = 0;
2261
2262     if (0xc0 <= c2 && c2 <= 0xef) {
2263         unsigned short **pp;
2264
2265         if (0xe0 <= c2) {
2266             if (c0 == 0) return -1;
2267             pp = utf8_to_euc_3bytes[c2 - 0x80];
2268             ret = w_iconv_common(c1, c0, pp, sizeof_utf8_to_euc_C2, p2, p1);
2269         } else {
2270             ret =  w_iconv_common(c2, c1, utf8_to_euc_2bytes, sizeof_utf8_to_euc_2bytes, p2, p1);
2271         }
2272 #ifdef NUMCHAR_OPTION
2273         if (ret){
2274             if (p2) *p2 = 0;
2275             if (p1) *p1 = CLASS_UTF16 | ww16_conv(c2, c1, c0);
2276             ret = 0;
2277         }
2278 #endif
2279         return ret;
2280     } else if (c2 == X0201) {
2281         c1 &= 0x7f;
2282     }
2283     if (p2) *p2 = c2;
2284     if (p1) *p1 = c1;
2285     return ret;
2286 }
2287
2288 int
2289 w_iconv(c2, c1, c0)
2290     int    c2,
2291                     c1, c0;
2292 {
2293     int ret = w2e_conv(c2, c1, c0, &c2, &c1);
2294     if (ret == 0){
2295         (*oconv)(c2, c1);
2296     }
2297     return ret;
2298 }
2299
2300 void
2301 w16w_conv(val, p2, p1, p0)
2302      unsigned short val;
2303      int *p2, *p1, *p0;
2304 {
2305     if (val < 0x80){
2306         *p2 = val;
2307         *p1 = 0;
2308         *p0 = 0;
2309     }else if (val < 0x800){
2310         *p2 = 0xc0 | (val >> 6);
2311         *p1 = 0x80 | (val & 0x3f);
2312         *p0 = 0;
2313     }else{
2314         *p2 = 0xe0 | (val >> 12);
2315         *p1 = 0x80 | ((val >> 6) & 0x3f);
2316         *p0 = 0x80 | (val        & 0x3f);
2317     }
2318 }
2319
2320 int
2321 ww16_conv(c2, c1, c0)
2322      int c2, c1, c0;
2323 {
2324     unsigned short val;
2325     if (c2 >= 0xe0){
2326         val = (c2 & 0x0f) << 12;
2327         val |= (c1 & 0x3f) << 6;
2328         val |= (c0 & 0x3f);
2329     }else if (c2 >= 0xc0){
2330         val = (c2 & 0x1f) << 6;
2331         val |= (c1 & 0x3f) << 6;
2332     }else{
2333         val = c2;
2334     }
2335     return val;
2336 }
2337
2338 int
2339 w16e_conv(val, p2, p1)
2340      unsigned short val;
2341      int *p2, *p1;
2342 {
2343     extern unsigned short * utf8_to_euc_2bytes[];
2344     extern unsigned short ** utf8_to_euc_3bytes[];
2345     int c2, c1, c0;
2346     unsigned short **pp;
2347     int psize;
2348     int ret = 0;
2349
2350     w16w_conv(val, &c2, &c1, &c0);
2351     if (c1){
2352         if (c0){
2353             pp = utf8_to_euc_3bytes[c2 - 0x80];
2354             psize = sizeof_utf8_to_euc_C2;
2355             ret =  w_iconv_common(c1, c0, pp, psize, p2, p1);
2356         }else{
2357             pp = utf8_to_euc_2bytes;
2358             psize = sizeof_utf8_to_euc_2bytes;
2359             ret =  w_iconv_common(c2, c1, pp, psize, p2, p1);
2360         }
2361 #ifdef NUMCHAR_OPTION
2362         if (ret){
2363             *p2 = 0;
2364             *p1 = CLASS_UTF16 | val;
2365             ret = 0;
2366         }
2367 #endif
2368     }
2369     return ret;
2370 }
2371
2372 int
2373 w_iconv16(c2, c1, c0)
2374     int    c2, c1,c0;
2375 {
2376     int ret;
2377
2378     if (c2==0376 && c1==0377){
2379         utf16_mode = UTF16LE_INPUT;
2380         return 0;    
2381     } else if (c2==0377 && c1==0376){
2382         utf16_mode = UTF16BE_INPUT;
2383         return 0;    
2384     }
2385     if (c2 != EOF && utf16_mode == UTF16BE_INPUT) {
2386         int tmp;
2387         tmp=c1; c1=c2; c2=tmp;
2388     }
2389     if ((c2==0 && c1 < 0x80) || c2==EOF) {
2390         (*oconv)(c2, c1);
2391         return 0;
2392     }
2393     ret = w16e_conv(((c2<<8)&0xff00) + c1, &c2, &c1);
2394     if (ret) return ret;
2395     (*oconv)(c2, c1);
2396     return 0;
2397 }
2398
2399 int
2400 w_iconv_common(c1, c0, pp, psize, p2, p1)
2401     int    c1,c0;
2402     unsigned short **pp;
2403     int psize;
2404     int *p2, *p1;
2405 {
2406     int c2;
2407     unsigned short *p ;
2408     unsigned short val;
2409
2410     if (pp == 0) return 1;
2411
2412     c1 -= 0x80;
2413     if (c1 < 0 || psize <= c1) return 1;
2414     p = pp[c1];
2415     if (p == 0)  return 1;
2416
2417     c0 -= 0x80;
2418     if (c0 < 0 || sizeof_utf8_to_euc_E5B8 <= c0) return 1;
2419     val = p[c0];
2420     if (val == 0) return 1;
2421
2422     c2 = val >> 8;
2423     if (c2 == SO) c2 = X0201;
2424     c1 = val & 0x7f;
2425     if (p2) *p2 = c2;
2426     if (p1) *p1 = c1;
2427     return 0;
2428 }
2429
2430 #endif
2431
2432 #ifdef UTF8_OUTPUT_ENABLE
2433 int
2434 e2w_conv(c2, c1)
2435     int    c2, c1;
2436 {
2437     extern unsigned short euc_to_utf8_1byte[];
2438     extern unsigned short * euc_to_utf8_2bytes[];
2439     unsigned short *p;
2440
2441     if (c2 == X0201) {
2442         p = euc_to_utf8_1byte;
2443     } else {
2444         c2 &= 0x7f;
2445         c2 = (c2&0x7f) - 0x21;
2446         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
2447             p = euc_to_utf8_2bytes[c2];
2448         else
2449             return 0;
2450     }
2451     if (!p) return 0;
2452     c1 = (c1 & 0x7f) - 0x21;
2453     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
2454         return p[c1];
2455     return 0;
2456 }
2457
2458 void
2459 w_oconv(c2, c1)
2460     int    c2,
2461                     c1;
2462 {
2463     int c0;
2464 #ifdef NUMCHAR_OPTION
2465     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2466         w16w_conv(c1, &c2, &c1, &c0);
2467         (*o_putc)(c2);
2468         if (c1){
2469             (*o_putc)(c1);
2470             if (c0) (*o_putc)(c0);
2471         }
2472     }
2473 #endif
2474     if (c2 == EOF) {
2475         (*o_putc)(EOF);
2476         return;
2477     }
2478
2479     if (unicode_bom_f==2) {
2480         (*o_putc)('\357');
2481         (*o_putc)('\273');
2482         (*o_putc)('\277');
2483         unicode_bom_f=1;
2484     }
2485
2486     if (c2 == 0) { 
2487         output_mode = ASCII;
2488         (*o_putc)(c1);
2489     } else if (c2 == ISO8859_1) {
2490         output_mode = ISO8859_1;
2491         (*o_putc)(c1 | 0x080);
2492     } else {
2493         output_mode = UTF8;
2494         w16w_conv((unsigned short)e2w_conv(c2, c1), &c2, &c1, &c0);
2495         (*o_putc)(c2);
2496         if (c1){
2497             (*o_putc)(c1);
2498             if (c0) (*o_putc)(c0);
2499         }
2500     }
2501 }
2502
2503 void
2504 w_oconv16(c2, c1)
2505     int    c2,
2506                     c1;
2507 {
2508     if (c2 == EOF) {
2509         (*o_putc)(EOF);
2510         return;
2511     }    
2512
2513     if (unicode_bom_f==2) {
2514         if (w_oconv16_LE){
2515             (*o_putc)((unsigned char)'\377');
2516             (*o_putc)('\376');
2517         }else{
2518             (*o_putc)('\376');
2519             (*o_putc)((unsigned char)'\377');
2520         }
2521         unicode_bom_f=1;
2522     }
2523
2524     if (c2 == ISO8859_1) {
2525         c2 = 0;
2526         c1 |= 0x80;
2527 #ifdef NUMCHAR_OPTION
2528     } else if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16) {
2529         c2 = (c1 >> 8) & 0xff;
2530         c1 &= 0xff;
2531 #endif
2532     } else if (c2) {
2533         unsigned short val = (unsigned short)e2w_conv(c2, c1);
2534         c2 = (val >> 8) & 0xff;
2535         c1 = val & 0xff;
2536     }
2537     if (w_oconv16_LE){
2538         (*o_putc)(c1);
2539         (*o_putc)(c2);
2540     }else{
2541         (*o_putc)(c2);
2542         (*o_putc)(c1);
2543     }
2544 }
2545
2546 #endif
2547
2548 void
2549 e_oconv(c2, c1)
2550     int    c2,
2551                     c1;
2552 {
2553 #ifdef NUMCHAR_OPTION
2554     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2555         w16e_conv(c1, &c2, &c1);
2556     }
2557 #endif
2558     if (c2 == EOF) {
2559         (*o_putc)(EOF);
2560         return;
2561     } else if (c2 == 0) { 
2562         output_mode = ASCII;
2563         (*o_putc)(c1);
2564     } else if (c2 == X0201) {
2565         output_mode = JAPANESE_EUC;
2566         (*o_putc)(SSO); (*o_putc)(c1|0x80);
2567     } else if (c2 == ISO8859_1) {
2568         output_mode = ISO8859_1;
2569         (*o_putc)(c1 | 0x080);
2570     } else {
2571         if ((c1<0x21 || 0x7e<c1) ||
2572            (c2<0x21 || 0x7e<c2)) {
2573             set_iconv(FALSE, 0);
2574             return; /* too late to rescue this char */
2575         }
2576         output_mode = JAPANESE_EUC;
2577         (*o_putc)(c2 | 0x080);
2578         (*o_putc)(c1 | 0x080);
2579     }
2580 }
2581
2582 void
2583 e2s_conv(c2, c1, p2, p1)
2584      int c2, c1, *p2, *p1;
2585 {
2586     if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
2587     if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
2588 }
2589
2590 void
2591 s_oconv(c2, c1)
2592     int    c2,
2593                     c1;
2594 {
2595 #ifdef NUMCHAR_OPTION
2596     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2597         w16e_conv(c1, &c2, &c1);
2598     }
2599 #endif
2600     if (c2 == EOF) {
2601         (*o_putc)(EOF);
2602         return;
2603     } else if (c2 == 0) {
2604         output_mode = ASCII;
2605         (*o_putc)(c1);
2606     } else if (c2 == X0201) {
2607         output_mode = SHIFT_JIS;
2608         (*o_putc)(c1|0x80);
2609     } else if (c2 == ISO8859_1) {
2610         output_mode = ISO8859_1;
2611         (*o_putc)(c1 | 0x080);
2612     } else {
2613         if ((c1<0x20 || 0x7e<c1) ||
2614            (c2<0x20 || 0x7e<c2)) {
2615             set_iconv(FALSE, 0);
2616             return; /* too late to rescue this char */
2617         }
2618         output_mode = SHIFT_JIS;
2619         e2s_conv(c2, c1, &c2, &c1);
2620
2621 #ifdef SHIFTJIS_CP932
2622         if (cp932inv_f
2623             && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
2624             extern unsigned short cp932inv[2][189];
2625             int c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
2626             if (c){
2627                 c2 = c >> 8;
2628                 c1 = c & 0xff;
2629             }
2630         }
2631 #endif /* SHIFTJIS_CP932 */
2632
2633         (*o_putc)(c2);
2634         if (prefix_table[(unsigned char)c1]){
2635             (*o_putc)(prefix_table[(unsigned char)c1]);
2636         }
2637         (*o_putc)(c1);
2638     }
2639 }
2640
2641 void
2642 j_oconv(c2, c1)
2643     int    c2,
2644                     c1;
2645 {
2646 #ifdef NUMCHAR_OPTION
2647     if ((c1 & CLASS_MASK) == CLASS_UTF16){
2648         w16e_conv(c1, &c2, &c1);
2649     }
2650 #endif
2651     if (c2 == EOF) {
2652         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2653             (*o_putc)(ESC);
2654             (*o_putc)('(');
2655             (*o_putc)(ascii_intro);
2656             output_mode = ASCII;
2657         }
2658         (*o_putc)(EOF);
2659     } else if (c2==X0201) {
2660         if (output_mode!=X0201) {
2661             output_mode = X0201;
2662             (*o_putc)(ESC);
2663             (*o_putc)('(');
2664             (*o_putc)('I');
2665         }
2666         (*o_putc)(c1);
2667     } else if (c2==ISO8859_1) {
2668             /* iso8859 introduction, or 8th bit on */
2669             /* Can we convert in 7bit form using ESC-'-'-A ? 
2670                Is this popular? */
2671         output_mode = ISO8859_1;
2672         (*o_putc)(c1|0x80);
2673     } else if (c2 == 0) {
2674         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2675             (*o_putc)(ESC);
2676             (*o_putc)('(');
2677             (*o_putc)(ascii_intro);
2678             output_mode = ASCII;
2679         }
2680         (*o_putc)(c1);
2681     } else {
2682         if (output_mode != X0208) {
2683             output_mode = X0208;
2684             (*o_putc)(ESC);
2685             (*o_putc)('$');
2686             (*o_putc)(kanji_intro);
2687         }
2688         if (c1<0x20 || 0x7e<c1) 
2689             return;
2690         if (c2<0x20 || 0x7e<c2) 
2691             return;
2692         (*o_putc)(c2);
2693         (*o_putc)(c1);
2694     }
2695 }
2696
2697 void
2698 base64_conv(c2, c1)
2699     int    c2,
2700                     c1;
2701 {
2702     if (base64_count>50 && !mimeout_mode && c2==0 && c1==SPACE) {
2703         (*o_putc)(NL);
2704     } else if (base64_count>66 && mimeout_mode) {
2705         (*o_base64conv)(EOF,0);
2706         (*o_putc)(NL);
2707         (*o_putc)('\t'); base64_count += 7;
2708     }
2709     (*o_base64conv)(c2,c1);
2710 }
2711
2712
2713 static int broken_buf[3];
2714 static int broken_counter = 0;
2715 static int broken_last = 0;
2716 int
2717 broken_getc(f)
2718 FILE *f;
2719 {
2720     int c,c1;
2721
2722     if (broken_counter>0) {
2723         return broken_buf[--broken_counter];
2724     }
2725     c= (*i_bgetc)(f);
2726     if (c=='$' && broken_last != ESC 
2727             && (input_mode==ASCII || input_mode==X0201)) {
2728         c1= (*i_bgetc)(f);
2729         broken_last = 0;
2730         if (c1=='@'|| c1=='B') {
2731             broken_buf[0]=c1; broken_buf[1]=c; 
2732             broken_counter=2;
2733             return ESC;
2734         } else {
2735             (*i_bungetc)(c1,f);
2736             return c;
2737         }
2738     } else if (c=='(' && broken_last != ESC 
2739             && (input_mode==X0208 || input_mode==X0201)) { /* ) */
2740         c1= (*i_bgetc)(f);
2741         broken_last = 0;
2742         if (c1=='J'|| c1=='B') {
2743             broken_buf[0]=c1; broken_buf[1]=c;
2744             broken_counter=2;
2745             return ESC;
2746         } else {
2747             (*i_bungetc)(c1,f);
2748             return c;
2749         }
2750     } else {
2751         broken_last = c;
2752         return c;
2753     }
2754 }
2755
2756 int
2757 broken_ungetc(c,f)
2758 int c;
2759 FILE *f;
2760 {
2761     if (broken_counter<2)
2762         broken_buf[broken_counter++]=c;
2763     return c;
2764 }
2765
2766 static int prev_cr = 0;
2767
2768 void
2769 cr_conv(c2,c1) 
2770 int c2,c1;
2771 {
2772     if (prev_cr) {
2773         prev_cr = 0;
2774         if (! (c2==0&&c1==NL) ) {
2775             cr_conv(0,'\n');
2776         }
2777     }
2778     if (c2) {
2779         (*o_crconv)(c2,c1);
2780     } else if (c1=='\r') {
2781         prev_cr = c1;
2782     } else if (c1=='\n') {
2783         if (crmode_f==CRLF) {
2784             (*o_crconv)(0,'\r');
2785         } else if (crmode_f==CR) {
2786             (*o_crconv)(0,'\r');
2787             return;
2788         } 
2789         (*o_crconv)(0,NL);
2790     } else if (c1!='\032' || crmode_f!=NL){
2791         (*o_crconv)(c2,c1);
2792     }
2793 }
2794
2795 /* 
2796   Return value of fold_conv()
2797
2798        \n  add newline  and output char
2799        \r  add newline  and output nothing
2800        ' ' space
2801        0   skip  
2802        1   (or else) normal output 
2803
2804   fold state in prev (previous character)
2805
2806       >0x80 Japanese (X0208/X0201)
2807       <0x80 ASCII
2808       \n    new line 
2809       ' '   space
2810
2811   This fold algorthm does not preserve heading space in a line.
2812   This is the main difference from fmt.
2813 */
2814
2815 #define char_size(c2,c1) (c2?2:1)
2816
2817 void
2818 fold_conv(c2,c1) 
2819 int c2,c1;
2820
2821     int prev0;
2822     int fold_state=0;
2823
2824     if (c1== '\r' && !fold_preserve_f) {
2825         fold_state=0;  /* ignore cr */
2826     }else if (c1== '\n'&&f_prev=='\r' && fold_preserve_f) {
2827         f_prev = '\n';
2828         fold_state=0;  /* ignore cr */
2829     } else if (c1== BS) {
2830         if (f_line>0) f_line--;
2831         fold_state =  1;
2832     } else if (c2==EOF && f_line != 0) {    /* close open last line */
2833             fold_state = '\n';
2834     } else if ((c1=='\n' && !fold_preserve_f)
2835                || ((c1=='\r'||(c1=='\n'&&f_prev!='\r'))
2836                    && fold_preserve_f)) {
2837         /* new line */
2838         if (fold_preserve_f) { 
2839             f_prev = c1;
2840             f_line = 0;
2841             fold_state =  '\r';
2842         } else if ((f_prev == c1 && !fold_preserve_f)
2843                    || (f_prev == '\n' && fold_preserve_f)
2844                    ) {        /* duplicate newline */
2845             if (f_line) {
2846                 f_line = 0;
2847                 fold_state =  '\n';    /* output two newline */
2848             } else {
2849                 f_line = 0;
2850                 fold_state =  1;
2851             }
2852         } else  {
2853             if (f_prev&0x80) {     /* Japanese? */
2854                 f_prev = c1;
2855                 fold_state =  0;       /* ignore given single newline */
2856             } else if (f_prev==' ') {
2857                 fold_state =  0;
2858             } else {
2859                 f_prev = c1;
2860                 if (++f_line<=fold_len) 
2861                     fold_state =  ' ';
2862                 else {
2863                     f_line = 0;
2864                     fold_state =  '\r';        /* fold and output nothing */
2865                 }
2866             }
2867         }
2868     } else if (c1=='\f') {
2869         f_prev = '\n';
2870         if (f_line==0)
2871             fold_state =  1;
2872         f_line = 0;
2873         fold_state =  '\n';            /* output newline and clear */
2874     } else if ( (c2==0  && c1==' ')||
2875                (c2==0  && c1=='\t')||
2876                (c2=='!'&& c1=='!')) {
2877         /* X0208 kankaku or ascii space */
2878             if (f_prev == ' ') {
2879                 fold_state = 0;         /* remove duplicate spaces */
2880             } else {
2881                 f_prev = ' ';    
2882                 if (++f_line<=fold_len) 
2883                     fold_state = ' ';         /* output ASCII space only */
2884                 else {
2885                     f_prev = ' '; f_line = 0;
2886                     fold_state = '\r';        /* fold and output nothing */
2887                 }
2888             }
2889     } else {
2890         prev0 = f_prev; /* we still need this one... , but almost done */
2891         f_prev = c1;
2892         if (c2 || c2==X0201) 
2893             f_prev |= 0x80;  /* this is Japanese */
2894         f_line += char_size(c2,c1);
2895         if (f_line<=fold_len) {   /* normal case */
2896             fold_state = 1;
2897         } else {
2898             if (f_line>=fold_len+fold_margin) { /* too many kinsou suspension */
2899                 f_line = char_size(c2,c1);
2900                 fold_state =  '\n';       /* We can't wait, do fold now */
2901             } else if (c2==X0201) {
2902             /* simple kinsoku rules  return 1 means no folding  */
2903                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
2904                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
2905                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
2906                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
2907                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
2908                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
2909                 else if (SPACE<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
2910                     f_line = 1;
2911                     fold_state = '\n';/* add one new f_line before this character */
2912                 } else {
2913                     f_line = 1;
2914                     fold_state = '\n';/* add one new f_line before this character */
2915                 }
2916             } else if (c2==0) {
2917                 /* kinsoku point in ASCII */ 
2918                 if (  c1==')'||    /* { [ ( */
2919                      c1==']'||
2920                      c1=='}'||
2921                      c1=='.'||
2922                      c1==','||
2923                      c1=='!'||
2924                      c1=='?'||
2925                      c1=='/'||
2926                      c1==':'||
2927                      c1==';' ) {
2928                     fold_state = 1;
2929                 /* just after special */
2930                 } else if (!is_alnum(prev0)) {
2931                     f_line = char_size(c2,c1);
2932                     fold_state = '\n';
2933                 } else if ((prev0==' ') ||   /* ignored new f_line */
2934                       (prev0=='\n')||        /* ignored new f_line */
2935                       (prev0&0x80)) {        /* X0208 - ASCII */
2936                     f_line = char_size(c2,c1);
2937                     fold_state = '\n';/* add one new f_line before this character */
2938                 } else {
2939                     fold_state = 1;  /* default no fold in ASCII */
2940                 }
2941             } else {
2942                 if (c2=='!') {
2943                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
2944                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
2945                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
2946                     else if (c1=='K')  fold_state = 1; /* \e$B!K\e(B */
2947                     else if (c1=='$')  fold_state = 1; /* \e$B!$\e(B */
2948                     else if (c1=='%')  fold_state = 1; /* \e$B!%\e(B */
2949                     else if (c1=='\'') fold_state = 1; /* \e$B!\\e(B */
2950                     else if (c1=='(')  fold_state = 1; /* \e$B!(\e(B */
2951                     else if (c1==')')  fold_state = 1; /* \e$B!)\e(B */
2952                     else if (c1=='*')  fold_state = 1; /* \e$B!*\e(B */
2953                     else if (c1=='+')  fold_state = 1; /* \e$B!+\e(B */
2954                     else if (c1==',')  fold_state = 1; /* \e$B!,\e(B */
2955                          /* default no fold in kinsoku */
2956                     else { 
2957                         fold_state = '\n';
2958                         f_line = char_size(c2,c1);
2959                         /* add one new f_line before this character */
2960                     }
2961                 } else {
2962                     f_line = char_size(c2,c1);
2963                     fold_state = '\n'; 
2964                     /* add one new f_line before this character */
2965                 }
2966             }
2967         }
2968     }
2969     /* terminator process */
2970     switch(fold_state) {
2971         case '\n': 
2972             (*o_fconv)(0,'\n');
2973             (*o_fconv)(c2,c1);
2974             break;
2975         case 0:    
2976             return;
2977         case '\r': 
2978             (*o_fconv)(0,'\n');
2979             break;
2980         case '\t': 
2981         case ' ': 
2982             (*o_fconv)(0,' ');
2983             break;
2984         default:
2985             (*o_fconv)(c2,c1);
2986     }
2987 }
2988
2989 int z_prev2=0,z_prev1=0;
2990
2991 void
2992 z_conv(c2,c1)
2993 int c2,c1;
2994 {
2995
2996     /* if (c2) c1 &= 0x7f; assertion */
2997
2998     if (x0201_f && z_prev2==X0201) {  /* X0201 */
2999         if (c1==(0xde&0x7f)) { /* \e$BByE@\e(B */
3000             z_prev2=0;
3001             (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
3002             return;
3003         } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) {  /* \e$BH>ByE@\e(B */
3004             z_prev2=0;
3005             (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
3006             return;
3007         } else {
3008             z_prev2=0;
3009             (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
3010         }
3011     }
3012
3013     if (c2==EOF) {
3014         (*o_zconv)(c2,c1);
3015         return;
3016     }
3017
3018     if (x0201_f && c2==X0201) {
3019         if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
3020             /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
3021             z_prev1 = c1; z_prev2 = c2;
3022             return;
3023         } else {
3024             (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
3025             return;
3026         }
3027     }
3028
3029     /* JISX0208 Alphabet */
3030     if (alpha_f && c2 == 0x23 ) {
3031         c2 = 0;
3032     } else if (alpha_f && c2 == 0x21 ) { 
3033     /* JISX0208 Kigou */
3034        if (0x21==c1) {
3035            if (alpha_f&0x2) {
3036                c1 = ' ';
3037                c2 = 0;
3038            } else if (alpha_f&0x4) {
3039                 (*o_zconv)(0,' ');
3040                 (*o_zconv)(0,' ');
3041                 return;
3042            } 
3043        } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
3044            c1 = fv[c1-0x20];
3045            c2 =  0;
3046            if (alpha_f&0x8) {
3047                char *entity = 0;
3048                switch (c1){
3049                  case '>': entity = "&gt;"; break;
3050                  case '<': entity = "&lt;"; break;
3051                  case '\"': entity = "&quot;"; break;
3052                  case '&': entity = "&amp;"; break;
3053                }
3054                if (entity){
3055                    while (*entity) (*o_zconv)(0, *entity++);
3056                    return;
3057                }
3058            }
3059        } 
3060     }
3061     (*o_zconv)(c2,c1);
3062 }
3063
3064
3065 #define rot13(c)  ( \
3066       ( c < 'A' ) ? c: \
3067       (c <= 'M')  ? (c + 13): \
3068       (c <= 'Z')  ? (c - 13): \
3069       (c < 'a')   ? (c): \
3070       (c <= 'm')  ? (c + 13): \
3071       (c <= 'z')  ? (c - 13): \
3072       (c) \
3073 )
3074
3075 #define  rot47(c) ( \
3076       ( c < '!' ) ? c: \
3077       ( c <= 'O' ) ? (c + 47) : \
3078       ( c <= '~' ) ?  (c - 47) : \
3079       c \
3080 )
3081
3082 void
3083 rot_conv(c2,c1)
3084 int c2,c1;
3085 {
3086     if (c2==0 || c2==X0201 || c2==ISO8859_1) {
3087         c1 = rot13(c1);
3088     } else if (c2) {
3089         c1 = rot47(c1);
3090         c2 = rot47(c2);
3091     }
3092     (*o_rot_conv)(c2,c1);
3093 }
3094
3095 void
3096 hira_conv(c2,c1)
3097 int c2,c1;
3098 {
3099     if ((hira_f & 1) && c2==0x25 && 0x20<c1 && c1<0x74) {
3100         c2 = 0x24;
3101     } else if ((hira_f & 2) && c2==0x24 && 0x20<c1 && c1<0x74) {
3102         c2 = 0x25;
3103     } 
3104     (*o_hira_conv)(c2,c1);
3105 }
3106
3107
3108 void
3109 iso2022jp_check_conv(c2,c1)
3110 int    c2, c1;
3111 {
3112     static int range[RANGE_NUM_MAX][2] = {
3113         {0x222f, 0x2239,},
3114         {0x2242, 0x2249,},
3115         {0x2251, 0x225b,},
3116         {0x226b, 0x2271,},
3117         {0x227a, 0x227d,},
3118         {0x2321, 0x232f,},
3119         {0x233a, 0x2340,},
3120         {0x235b, 0x2360,},
3121         {0x237b, 0x237e,},
3122         {0x2474, 0x247e,},
3123         {0x2577, 0x257e,},
3124         {0x2639, 0x2640,},
3125         {0x2659, 0x267e,},
3126         {0x2742, 0x2750,},
3127         {0x2772, 0x277e,},
3128         {0x2841, 0x287e,},
3129         {0x4f54, 0x4f7e,},
3130         {0x7425, 0x747e},
3131     };
3132     int i;
3133     int start, end, c;
3134
3135     if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
3136         c2 = GETA1;
3137         c1 = GETA2;
3138     }
3139     if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
3140         c2 = GETA1;
3141         c1 = GETA2;
3142     }
3143
3144     for (i = 0; i < RANGE_NUM_MAX; i++) {
3145         start = range[i][0];
3146         end   = range[i][1];
3147         c     = (c2 << 8) + c1;
3148         if (c >= start && c <= end) {
3149             c2 = GETA1;
3150             c1 = GETA2;
3151         }
3152     }
3153     (*o_iso2022jp_check_conv)(c2,c1);
3154 }
3155
3156
3157 /* This converts  =?ISO-2022-JP?B?HOGE HOGE?= */
3158
3159 unsigned char *mime_pattern[] = {
3160    (unsigned char *)"\075?EUC-JP?B?",
3161    (unsigned char *)"\075?SHIFT_JIS?B?",
3162    (unsigned char *)"\075?ISO-8859-1?Q?",
3163    (unsigned char *)"\075?ISO-8859-1?B?",
3164    (unsigned char *)"\075?ISO-2022-JP?B?",
3165    (unsigned char *)"\075?ISO-2022-JP?Q?",
3166 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3167    (unsigned char *)"\075?UTF-8?B?",
3168    (unsigned char *)"\075?UTF-8?Q?",
3169 #endif
3170    (unsigned char *)"\075?US-ASCII?Q?",
3171    NULL
3172 };
3173
3174
3175 /* \e$B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u\e(B */
3176 int (*mime_priority_func[])PROTO((int c2, int c1, int c0)) = {
3177     e_iconv, s_iconv, 0, 0, 0, 0,
3178 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3179     w_iconv, w_iconv,
3180 #endif
3181     0,
3182 };
3183
3184 int      mime_encode[] = {
3185     JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
3186 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3187     UTF8, UTF8,
3188 #endif
3189     ASCII,
3190     0
3191 };
3192
3193 int      mime_encode_method[] = {
3194     'B', 'B','Q', 'B', 'B', 'Q',
3195 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3196     'B', 'Q',
3197 #endif
3198     'Q',
3199     0
3200 };
3201
3202
3203 #define MAXRECOVER 20
3204
3205 /* I don't trust portablity of toupper */
3206 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
3207 #define nkf_isdigit(c)  ('0'<=c && c<='9')
3208 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
3209
3210 void
3211 switch_mime_getc()
3212 {
3213     if (i_getc!=mime_getc) {
3214         i_mgetc = i_getc; i_getc = mime_getc;
3215         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
3216         if(mime_f==STRICT_MIME) {
3217             i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
3218             i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
3219         }
3220     }
3221 }
3222
3223 void
3224 unswitch_mime_getc()
3225 {
3226     if(mime_f==STRICT_MIME) {
3227         i_mgetc = i_mgetc_buf;
3228         i_mungetc = i_mungetc_buf;
3229     }
3230     i_getc = i_mgetc;
3231     i_ungetc = i_mungetc;
3232 }
3233
3234 int
3235 mime_begin_strict(f)
3236 FILE *f;
3237 {
3238     int c1 = 0;
3239     int i,j,k;
3240     unsigned char *p,*q;
3241     int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */
3242
3243     mime_decode_mode = FALSE;
3244     /* =? has been checked */
3245     j = 0;
3246     p = mime_pattern[j];
3247     r[0]='='; r[1]='?';
3248
3249     for(i=2;p[i]>' ';i++) {                   /* start at =? */
3250         if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
3251             /* pattern fails, try next one */
3252             q = p;
3253             while ((p = mime_pattern[++j])) {
3254                 for(k=2;k<i;k++)              /* assume length(p) > i */
3255                     if (p[k]!=q[k]) break;
3256                 if (k==i && nkf_toupper(c1)==p[k]) break;
3257             }
3258             if (p) continue;  /* found next one, continue */
3259             /* all fails, output from recovery buffer */
3260             (*i_ungetc)(c1,f);
3261             for(j=0;j<i;j++) {
3262                 (*oconv)(0,r[j]);
3263             }
3264             return c1;
3265         }
3266     }
3267     mime_decode_mode = p[i-2];
3268
3269     clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
3270
3271     if (mime_decode_mode=='B') {
3272         mimebuf_f = unbuf_f;
3273         if (!unbuf_f) {
3274             /* do MIME integrity check */
3275             return mime_integrity(f,mime_pattern[j]);
3276         } 
3277     }
3278     switch_mime_getc();
3279     mimebuf_f = TRUE;
3280     return c1;
3281 }
3282
3283 int
3284 mime_getc_buf(f) 
3285 FILE *f;
3286 {
3287     /* we don't keep eof of Fifo, becase it contains ?= as
3288        a terminator. It was checked in mime_integrity. */
3289     return ((mimebuf_f)?
3290         (*i_mgetc_buf)(f):Fifo(mime_input++));
3291 }
3292
3293 int
3294 mime_ungetc_buf(c,f) 
3295 FILE *f;
3296 int c;
3297 {
3298     if (mimebuf_f)
3299         (*i_mungetc_buf)(c,f);
3300     else 
3301         Fifo(--mime_input)=c;
3302     return c;
3303 }
3304
3305 int
3306 mime_begin(f)
3307 FILE *f;
3308 {
3309     int c1;
3310     int i,k;
3311
3312     /* In NONSTRICT mode, only =? is checked. In case of failure, we  */
3313     /* re-read and convert again from mime_buffer.  */
3314
3315     /* =? has been checked */
3316     k = mime_last;
3317     Fifo(mime_last++)='='; Fifo(mime_last++)='?';
3318     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
3319         /* We accept any character type even if it is breaked by new lines */
3320         c1 = (*i_getc)(f); Fifo(mime_last++)= c1 ;
3321         if (c1=='\n'||c1==' '||c1=='\r'||
3322                 c1=='-'||c1=='_'||is_alnum(c1) ) continue;
3323         if (c1=='=') {
3324             /* Failed. But this could be another MIME preemble */
3325             (*i_ungetc)(c1,f);
3326             mime_last--;
3327             break;
3328         }
3329         if (c1!='?') break;
3330         else {
3331             /* c1=='?' */
3332             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3333             if (!(++i<MAXRECOVER) || c1==EOF) break;
3334             if (c1=='b'||c1=='B') {
3335                 mime_decode_mode = 'B';
3336             } else if (c1=='q'||c1=='Q') {
3337                 mime_decode_mode = 'Q';
3338             } else {
3339                 break;
3340             }
3341             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3342             if (!(++i<MAXRECOVER) || c1==EOF) break;
3343             if (c1!='?') {
3344                 mime_decode_mode = FALSE;
3345             }
3346             break;
3347         }
3348     }
3349     switch_mime_getc();
3350     if (!mime_decode_mode) {
3351         /* false MIME premble, restart from mime_buffer */
3352         mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
3353         /* Since we are in MIME mode until buffer becomes empty,    */
3354         /* we never go into mime_begin again for a while.           */
3355         return c1;
3356     }
3357     /* discard mime preemble, and goto MIME mode */
3358     mime_last = k;
3359     /* do no MIME integrity check */
3360     return c1;   /* used only for checking EOF */
3361 }
3362
3363 #ifdef CHECK_OPTION
3364 void
3365 no_putc(c)
3366      int c;
3367 {
3368     ;
3369 }
3370
3371 void debug(str)
3372      char *str;
3373 {
3374     if (debug_f){
3375         fprintf(stderr, "%s\n", str);
3376     }
3377 }
3378 #endif
3379
3380 void
3381 set_input_codename (codename)
3382     char *codename;
3383 {
3384     if (guess_f && 
3385         is_inputcode_set &&
3386         strcmp(codename, "") != 0 && 
3387         strcmp(codename, input_codename) != 0)
3388     {
3389         is_inputcode_mixed = TRUE;
3390     }
3391     input_codename = codename;
3392     is_inputcode_set = TRUE;
3393 }
3394
3395 void
3396 print_guessed_code (filename)
3397     char *filename;
3398 {
3399     char *codename = "BINARY";
3400     if (!is_inputcode_mixed) {
3401         if (strcmp(input_codename, "") == 0) {
3402             codename = "ASCII";
3403         } else {
3404             codename = input_codename;
3405         }
3406     }
3407     if (filename != NULL) printf("%s:", filename);
3408     printf("%s\n", codename);
3409 }
3410
3411 int
3412 hex2bin(x)
3413      int x;
3414 {
3415     if (nkf_isdigit(x)) return x - '0';
3416     return nkf_toupper(x) - 'A' + 10;
3417 }
3418
3419 #ifdef INPUT_OPTION 
3420
3421 #ifdef ANSI_C_PROTOTYPE
3422 int hex_getc(int ch, FILE *f, int (*g)(FILE *f), int (*u)(int c, FILE *f))
3423 #else
3424 int
3425 hex_getc(ch, f, g, u)
3426      int ch;
3427      FILE *f;
3428      int (*g)();
3429      int (*u)();
3430 #endif
3431 {
3432     int c1, c2, c3;
3433     c1 = (*g)(f);
3434     if (c1 != ch){
3435         return c1;
3436     }
3437     c2 = (*g)(f);
3438     if (!nkf_isxdigit(c2)){
3439         (*u)(c2, f);
3440         return c1;
3441     }
3442     c3 = (*g)(f);
3443     if (!nkf_isxdigit(c3)){
3444         (*u)(c2, f);
3445         (*u)(c3, f);
3446         return c1;
3447     }
3448     return (hex2bin(c2) << 4) | hex2bin(c3);
3449 }
3450
3451 int
3452 cap_getc(f)
3453      FILE *f;
3454 {
3455     return hex_getc(':', f, i_cgetc, i_cungetc);
3456 }
3457
3458 int
3459 cap_ungetc(c, f)
3460      int c;
3461      FILE *f;
3462 {
3463     return (*i_cungetc)(c, f);
3464 }
3465
3466 int
3467 url_getc(f)
3468      FILE *f;
3469 {
3470     return hex_getc('%', f, i_ugetc, i_uungetc);
3471 }
3472
3473 int
3474 url_ungetc(c, f)
3475      int c;
3476      FILE *f;
3477 {
3478     return (*i_uungetc)(c, f);
3479 }
3480 #endif
3481
3482 #ifdef NUMCHAR_OPTION
3483 int
3484 numchar_getc(f)
3485      FILE *f;
3486 {
3487     int (*g)() = i_ngetc;
3488     int (*u)() = i_nungetc;
3489     int i = 0, j;
3490     int buf[8];
3491     long c = -1;
3492
3493     buf[i] = (*g)(f);
3494     if (buf[i] == '&'){
3495         buf[++i] = (*g)(f);
3496         if (buf[i] == '#'){
3497             c = 0;
3498             buf[++i] = (*g)(f);
3499             if (buf[i] == 'x' || buf[i] == 'X'){
3500                 for (j = 0; j < 5; j++){
3501                     buf[++i] = (*g)(f);
3502                     if (!nkf_isxdigit(buf[i])){
3503                         if (buf[i] != ';'){
3504                             c = -1;
3505                         }
3506                         break;
3507                     }
3508                     c <<= 4;
3509                     c |= hex2bin(buf[i]);
3510                 }
3511             }else{
3512                 for (j = 0; j < 6; j++){
3513                     if (j){
3514                         buf[++i] = (*g)(f);
3515                     }
3516                     if (!nkf_isdigit(buf[i])){
3517                         if (buf[i] != ';'){
3518                             c = -1;
3519                         }
3520                         break;
3521                     }
3522                     c *= 10;
3523                     c += hex2bin(buf[i]);
3524                 }
3525             }
3526         }
3527     }
3528     if (c != -1){
3529         return CLASS_UTF16 | c;
3530     }
3531     while (i > 0){
3532         (*u)(buf[i], f);
3533         --i;
3534     }
3535     return buf[0];
3536 }
3537
3538 int
3539 numchar_ungetc(c, f)
3540      int c;
3541      FILE *f;
3542 {
3543     return (*i_nungetc)(c, f);
3544 }
3545 #endif
3546
3547
3548 int 
3549 mime_getc(f)
3550 FILE *f;
3551 {
3552     int c1, c2, c3, c4, cc;
3553     int t1, t2, t3, t4, mode, exit_mode;
3554
3555     if (mime_top != mime_last) {  /* Something is in FIFO */
3556         return  Fifo(mime_top++);
3557     }
3558     if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
3559         mime_decode_mode=FALSE;
3560         unswitch_mime_getc();
3561         return (*i_getc)(f);
3562     }
3563
3564     if (mimebuf_f == FIXED_MIME)
3565         exit_mode = mime_decode_mode;
3566     else
3567         exit_mode = FALSE;
3568     if (mime_decode_mode == 'Q') {
3569         if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
3570 restart_mime_q:
3571         if (c1=='_') return ' ';
3572         if (c1!='=' && c1!='?') {
3573             return c1;
3574         }
3575                 
3576         mime_decode_mode = exit_mode; /* prepare for quit */
3577         if (c1<=' ') return c1;
3578         if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
3579         if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
3580             /* end Q encoding */
3581             input_mode = exit_mode;
3582             while((c1=(*i_getc)(f))!=EOF && c1==SPACE 
3583                         /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
3584             return c1;
3585         }
3586         if (c1=='='&&c2<' ') { /* this is soft wrap */
3587             while((c1 =  (*i_mgetc)(f)) <=' ') {
3588                 if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
3589             }
3590             mime_decode_mode = 'Q'; /* still in MIME */
3591             goto restart_mime_q;
3592         }
3593         if (c1=='?') {
3594             mime_decode_mode = 'Q'; /* still in MIME */
3595             (*i_mungetc)(c2,f);
3596             return c1;
3597         }
3598         if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
3599         if (c2<=' ') return c2;
3600         mime_decode_mode = 'Q'; /* still in MIME */
3601 #define hex(c)   (('0'<=c&&c<='9')?(c-'0'):\
3602      ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
3603         return ((hex(c2)<<4) + hex(c3));
3604     }
3605
3606     if (mime_decode_mode != 'B') {
3607         mime_decode_mode = FALSE;
3608         return (*i_mgetc)(f);
3609     }
3610
3611
3612     /* Base64 encoding */
3613     /* 
3614         MIME allows line break in the middle of 
3615         Base64, but we are very pessimistic in decoding
3616         in unbuf mode because MIME encoded code may broken by 
3617         less or editor's control sequence (such as ESC-[-K in unbuffered
3618         mode. ignore incomplete MIME.
3619     */
3620     mode = mime_decode_mode;
3621     mime_decode_mode = exit_mode;  /* prepare for quit */
3622
3623     while ((c1 = (*i_mgetc)(f))<=' ') {
3624         if (c1==EOF)
3625             return (EOF);
3626     }
3627 mime_c2_retry:
3628     if ((c2 = (*i_mgetc)(f))<=' ') {
3629         if (c2==EOF)
3630             return (EOF);
3631         if (mime_f != STRICT_MIME) goto mime_c2_retry;
3632         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3633         return c2;
3634     }
3635     if ((c1 == '?') && (c2 == '=')) {
3636         input_mode = ASCII;
3637         while((c1=(*i_getc)(f))!=EOF && c1==SPACE 
3638                     /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
3639         return c1;
3640     }
3641 mime_c3_retry:
3642     if ((c3 = (*i_mgetc)(f))<=' ') {
3643         if (c3==EOF)
3644             return (EOF);
3645         if (mime_f != STRICT_MIME) goto mime_c3_retry;
3646         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3647         return c3;
3648     }
3649 mime_c4_retry:
3650     if ((c4 = (*i_mgetc)(f))<=' ') {
3651         if (c4==EOF)
3652             return (EOF);
3653         if (mime_f != STRICT_MIME) goto mime_c4_retry;
3654         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3655         return c4;
3656     }
3657
3658     mime_decode_mode = mode; /* still in MIME sigh... */
3659
3660     /* BASE 64 decoding */
3661
3662     t1 = 0x3f & base64decode(c1);
3663     t2 = 0x3f & base64decode(c2);
3664     t3 = 0x3f & base64decode(c3);
3665     t4 = 0x3f & base64decode(c4);
3666     cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
3667     if (c2 != '=') {
3668         Fifo(mime_last++) = cc;
3669         cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
3670         if (c3 != '=') {
3671             Fifo(mime_last++) = cc;
3672             cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
3673             if (c4 != '=') 
3674                 Fifo(mime_last++) = cc;
3675         }
3676     } else {
3677         return c1;
3678     }
3679     return  Fifo(mime_top++);
3680 }
3681
3682 int
3683 mime_ungetc(c,f) 
3684 int   c;
3685 FILE  *f;
3686 {
3687     Fifo(--mime_top) = c;
3688     return c;
3689 }
3690
3691 int
3692 mime_integrity(f,p)
3693 FILE *f;
3694 unsigned char *p;
3695 {
3696     int c,d;
3697     unsigned int q;
3698     /* In buffered mode, read until =? or NL or buffer full
3699      */
3700     mime_input = mime_top;
3701     mime_last = mime_top;
3702     while(*p) Fifo(mime_input++) = *p++;
3703     d = 0;
3704     q = mime_input;
3705     while((c=(*i_getc)(f))!=EOF) {
3706         if (((mime_input-mime_top)&MIME_BUF_MASK)==0) {
3707             break;   /* buffer full */
3708         }
3709         if (c=='=' && d=='?') {
3710             /* checked. skip header, start decode */
3711             Fifo(mime_input++) = c;
3712             /* mime_last_input = mime_input; */
3713             mime_input = q; 
3714             switch_mime_getc();
3715             return 1;
3716         }
3717         if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
3718             break;
3719         /* Should we check length mod 4? */
3720         Fifo(mime_input++) = c;
3721         d=c;
3722     }
3723     /* In case of Incomplete MIME, no MIME decode  */
3724     Fifo(mime_input++) = c;
3725     mime_last = mime_input;     /* point undecoded buffer */
3726     mime_decode_mode = 1;              /* no decode on Fifo last in mime_getc */
3727     switch_mime_getc();         /* anyway we need buffered getc */
3728     return 1;
3729 }
3730
3731 int
3732 base64decode(c)
3733     int            c;
3734 {
3735     int             i;
3736     if (c > '@') {
3737         if (c < '[') {
3738             i = c - 'A';                        /* A..Z 0-25 */
3739         } else {
3740             i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
3741         }
3742     } else if (c > '/') {
3743         i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
3744     } else if (c == '+') {
3745         i = '>'             /* 62 */ ;          /* +  62 */
3746     } else {
3747         i = '?'             /* 63 */ ;          /* / 63 */
3748     }
3749     return (i);
3750 }
3751
3752 static char basis_64[] =
3753    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3754
3755 static int b64c;
3756
3757 void
3758 open_mime(mode)
3759 int mode;
3760 {
3761     unsigned char *p;
3762     int i;
3763     p  = mime_pattern[0];
3764     for(i=0;mime_encode[i];i++) {
3765         if (mode == mime_encode[i]) {
3766             p = mime_pattern[i];
3767                 break;
3768         }
3769     }
3770     mimeout_mode = mime_encode_method[i];
3771             
3772     /* (*o_mputc)(' '); */
3773     while(*p) {
3774         (*o_mputc)(*p++);
3775         base64_count ++;
3776     }
3777 }
3778
3779 void
3780 close_mime()
3781 {
3782     (*o_mputc)('?');
3783     (*o_mputc)('=');
3784     (*o_mputc)(' ');
3785     base64_count += 3;
3786     mimeout_mode = 0;
3787 }
3788
3789 #define itoh4(c)   (c>=10?c+'A'-10:c+'0')
3790
3791 void
3792 mime_putc(c)
3793     int            c;
3794 {
3795     if (mimeout_f==FIXED_MIME) {
3796         if (base64_count>71) {
3797             (*o_mputc)('\n');
3798             base64_count=0;
3799         }
3800     } else if (c==NL) {
3801         base64_count=0;
3802     } 
3803     if (c!=EOF) {
3804         if ( c<=DEL &&(output_mode==ASCII ||output_mode == ISO8859_1 )
3805                 && mimeout_f!=FIXED_MIME) {
3806             if (mimeout_mode=='Q') {
3807                 if (c<=SPACE) {
3808                     close_mime();
3809                 }
3810                 (*o_mputc)(c);
3811                 return;
3812             }
3813             if (mimeout_mode!='B' || c!=SPACE) {
3814                 if (mimeout_mode) {
3815                     mime_putc(EOF);
3816                     mimeout_mode=0;
3817                 }
3818                 (*o_mputc)(c);
3819                 base64_count ++;
3820                 return;
3821             }
3822         } else if (!mimeout_mode && mimeout_f!=FIXED_MIME) {
3823             open_mime(output_mode);
3824         }
3825     } else { /* c==EOF */
3826         switch(mimeout_mode) {
3827         case 'Q':
3828         case 'B':
3829             break;
3830         case 2:
3831             (*o_mputc)(basis_64[((b64c & 0x3)<< 4)]);
3832             (*o_mputc)('=');
3833             (*o_mputc)('=');
3834             base64_count += 3;
3835             break;
3836         case 1:
3837             (*o_mputc)(basis_64[((b64c & 0xF) << 2)]);
3838             (*o_mputc)('=');
3839             base64_count += 2;
3840             break;
3841         }
3842         if (mimeout_mode) {
3843             if (mimeout_f!=FIXED_MIME) {
3844                 close_mime(); 
3845             } else if (mimeout_mode != 'Q')
3846                 mimeout_mode = 'B';
3847         }
3848         return;
3849     }
3850     switch(mimeout_mode) {
3851     case 'Q':
3852         if(c>=DEL) {
3853             (*o_mputc)('=');
3854             (*o_mputc)(itoh4(((c>>4)&0xf)));
3855             (*o_mputc)(itoh4((c&0xf)));
3856         } else {
3857             (*o_mputc)(c);
3858         }
3859         break;
3860     case 'B':
3861         b64c=c;
3862         (*o_mputc)(basis_64[c>>2]);
3863         mimeout_mode=2;
3864         base64_count ++;
3865         break;
3866     case 2:
3867         (*o_mputc)(basis_64[((b64c & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
3868         b64c=c;
3869         mimeout_mode=1;
3870         base64_count ++;
3871         break;
3872     case 1:
3873         (*o_mputc)(basis_64[((b64c & 0xF) << 2) | ((c & 0xC0) >>6)]);
3874         (*o_mputc)(basis_64[c & 0x3F]);
3875         mimeout_mode='B';
3876         base64_count += 2;
3877         break;
3878     }
3879 }
3880
3881
3882 #ifdef PERL_XS
3883 void 
3884 reinit()
3885 {
3886     unbuf_f = FALSE;
3887     estab_f = FALSE;
3888     nop_f = FALSE;
3889     binmode_f = TRUE;       
3890     rot_f = FALSE;         
3891     hira_f = FALSE;         
3892     input_f = FALSE;      
3893     alpha_f = FALSE;     
3894     mime_f = STRICT_MIME; 
3895     mimebuf_f = FALSE; 
3896     broken_f = FALSE;  
3897     iso8859_f = FALSE; 
3898 #if defined(MSDOS) || defined(__OS2__) 
3899      x0201_f = TRUE;   
3900 #else
3901      x0201_f = NO_X0201;
3902 #endif
3903     iso2022jp_f = FALSE;
3904
3905     kanji_intro = DEFAULT_J;
3906     ascii_intro = DEFAULT_R;
3907
3908     output_conv = DEFAULT_CONV; 
3909     oconv = DEFAULT_CONV; 
3910
3911     i_mgetc  = std_getc; 
3912     i_mungetc  = std_ungetc;
3913     i_mgetc_buf = std_getc; 
3914     i_mungetc_buf = std_ungetc;
3915
3916     i_getc= std_getc; 
3917     i_ungetc=std_ungetc;
3918
3919     i_bgetc= std_getc;
3920     i_bungetc= std_ungetc;
3921
3922     o_putc = std_putc;
3923     o_mputc = std_putc;
3924     o_crconv = no_connection; 
3925     o_rot_conv = no_connection; 
3926     o_iso2022jp_check_conv = no_connection;
3927     o_hira_conv = no_connection; 
3928     o_fconv = no_connection; 
3929     o_zconv = no_connection;
3930
3931     i_getc = std_getc;
3932     i_ungetc = std_ungetc;
3933     i_mgetc = std_getc; 
3934     i_mungetc = std_ungetc; 
3935
3936     output_mode = ASCII;
3937     input_mode =  ASCII;
3938     shift_mode =  FALSE;
3939     mime_decode_mode =   FALSE;
3940     file_out = FALSE;
3941     mimeout_mode = 0;
3942     mimeout_f = FALSE;
3943     base64_count = 0;
3944     option_mode = 0;
3945     crmode_f = 0;
3946
3947     {
3948         struct input_code *p = input_code_list;
3949         while (p->name){
3950             status_reinit(p++);
3951         }
3952     }
3953 #ifdef UTF8_OUTPUT_ENABLE
3954     if (unicode_bom_f) {
3955         unicode_bom_f = 2;
3956     }
3957 #endif
3958     f_line = 0;    
3959     f_prev = 0;
3960     fold_preserve_f = FALSE; 
3961     fold_f  = FALSE;
3962     fold_len  = 0;
3963     fold_margin  = FOLD_MARGIN;
3964     broken_counter = 0;
3965     broken_last = 0;
3966     z_prev2=0,z_prev1=0;
3967
3968     {
3969         int i;
3970         for (i = 0; i < 256; i++){
3971             prefix_table[i] = 0;
3972         }
3973     }
3974     input_codename = "";
3975     is_inputcode_mixed = FALSE;
3976     is_inputcode_set   = FALSE;
3977 }
3978 #endif
3979
3980 void 
3981 no_connection(c2,c1) 
3982 int c2,c1;
3983 {
3984     no_connection2(c2,c1,0);
3985 }
3986
3987 int
3988 no_connection2(c2,c1,c0) 
3989 int c2,c1,c0;
3990 {
3991     fprintf(stderr,"nkf internal module connection failure.\n");
3992     exit(1);
3993 }
3994
3995 #ifndef PERL_XS
3996 void 
3997 usage()   
3998 {
3999     fprintf(stderr,"USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
4000     fprintf(stderr,"Flags:\n");
4001     fprintf(stderr,"b,u      Output is buffered (DEFAULT),Output is unbuffered\n");
4002 #ifdef DEFAULT_CODE_SJIS
4003     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC), UTF-8\n");
4004 #endif
4005 #ifdef DEFAULT_CODE_JIS
4006     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC), UTF-8\n");
4007 #endif
4008 #ifdef DEFAULT_CODE_EUC
4009     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT), UTF-8\n");
4010 #endif
4011 #ifdef DEFAULT_CODE_UTF8
4012     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC), UTF-8 (DEFAULT)\n");
4013 #endif
4014     fprintf(stderr,"J,S,E,W  Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC), UTF-8\n");
4015     fprintf(stderr,"t        no conversion\n");
4016     fprintf(stderr,"i_/o_    Output sequence to designate JIS-kanji/ASCII (DEFAULT B)\n");
4017     fprintf(stderr,"r        {de/en}crypt ROT13/47\n");
4018     fprintf(stderr,"h        1 hirakana->katakana, 2 katakana->hirakana,3 both\n");
4019     fprintf(stderr,"v        Show this usage. V: show version\n");
4020     fprintf(stderr,"m[BQN0]  MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
4021     fprintf(stderr,"M[BQ]    MIME encode [B:base64 Q:quoted]\n");
4022     fprintf(stderr,"l        ISO8859-1 (Latin-1) support\n");
4023     fprintf(stderr,"f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
4024     fprintf(stderr,"Z[0-3]   Convert X0208 alphabet to ASCII  1: Kankaku to space,2: 2 spaces,\n");
4025     fprintf(stderr,"                                          3: Convert HTML Entity\n");
4026     fprintf(stderr,"X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
4027     fprintf(stderr,"B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
4028 #ifdef MSDOS
4029     fprintf(stderr,"T        Text mode output\n");
4030 #endif
4031     fprintf(stderr,"O        Output to File (DEFAULT 'nkf.out')\n");
4032     fprintf(stderr,"d,c      Delete \\r in line feed and \\032, Add \\r in line feed\n");
4033     fprintf(stderr,"I        Convert non ISO-2022-JP charactor to GETA\n");
4034     fprintf(stderr,"-L[uwm]  line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
4035     fprintf(stderr,"long name options\n");
4036     fprintf(stderr," --fj,--unix,--mac,--windows                convert for the system\n");
4037     fprintf(stderr," --jis,--euc,--sjis,--utf8,--utf16,--mime,--base64  convert for the code\n");
4038 #ifdef OVERWRITE
4039     fprintf(stderr," --overwrite          Overwrite original listed files by filtered result\n");
4040 #endif
4041     fprintf(stderr," -g, --guess          Guess the input code\n");
4042     fprintf(stderr," --help,--version\n");
4043     version();
4044 }
4045
4046 void
4047 version()
4048 {
4049     fprintf(stderr,"Network Kanji Filter Version %s (%s) "
4050 #if defined(MSDOS) && !defined(__WIN32__) && !defined(__WIN16__)
4051                   "for DOS"
4052 #endif
4053 #if defined(MSDOS) && defined(__WIN16__)
4054                   "for Win16"
4055 #endif
4056 #if defined(MSDOS) && defined(__WIN32__)
4057                   "for Win32"
4058 #endif
4059 #ifdef __OS2__
4060                   "for OS/2"
4061 #endif
4062                   ,Version,Patchlevel);
4063     fprintf(stderr,"\n%s\n",CopyRight);
4064 }
4065 #endif
4066
4067 /**
4068  ** \e$B%Q%C%A@):n<T\e(B
4069  **  void@merope.pleiades.or.jp (Kusakabe Youichi)
4070  **  NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
4071  **  ohta@src.ricoh.co.jp (Junn Ohta)
4072  **  inouet@strl.nhk.or.jp (Tomoyuki Inoue)
4073  **  kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
4074  **  Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
4075  **  a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
4076  **  kono@ie.u-ryukyu.ac.jp (Shinji Kono)
4077  **  GHG00637@nifty-serve.or.jp (COW)
4078  **
4079  **/
4080
4081 /* end */