OSDN Git Service

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