OSDN Git Service

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