OSDN Git Service

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