OSDN Git Service

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