OSDN Git Service

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