OSDN Git Service

UTF8_INPUT_ENABLE が undef の時にコンパイルできなかったのを修正
[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 (
1456 #ifdef UTF8_INPUT_ENABLE
1457                 iconv == w_iconv16
1458 #else
1459                 0
1460 #endif
1461                 ) {
1462                 c2 = c1;
1463                 c1 = (*i_getc)(f);
1464                 SEND;
1465             } else if (c1 > DEL) {
1466                 /* 8 bit code */
1467                 if (!estab_f && !iso8859_f) {
1468                     /* not established yet */
1469                     c2 = c1;
1470                     NEXT;
1471                 } else { /* estab_f==TRUE */
1472                     if (iso8859_f) {
1473                         c2 = ISO8859_1;
1474                         c1 &= 0x7f;
1475                         SEND;
1476                     } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
1477                         /* SJIS X0201 Case... */
1478                         if(iso2022jp_f && x0201_f==NO_X0201) {
1479                             (*oconv)(GETA1, GETA2);
1480                             NEXT;
1481                         } else {
1482                             c2 = X0201;
1483                             c1 &= 0x7f;
1484                             SEND;
1485                         }
1486                     } else if (c1==SSO && iconv != s_iconv) {
1487                         /* EUC X0201 Case */
1488                         c1 = (*i_getc)(f);  /* skip SSO */
1489                         code_status(c1);
1490                         if (SSP<=c1 && c1<0xe0) {
1491                             if(iso2022jp_f &&  x0201_f==NO_X0201) {
1492                                 (*oconv)(GETA1, GETA2);
1493                                 NEXT;
1494                             } else {
1495                                 c2 = X0201;
1496                                 c1 &= 0x7f;
1497                                 SEND;
1498                             }
1499                         } else  { /* bogus code, skip SSO and one byte */
1500                             NEXT;
1501                         }
1502                     } else {
1503                        /* already established */
1504                        c2 = c1;
1505                        NEXT;
1506                     }
1507                 }
1508             } else if ((c1 > SPACE) && (c1 != DEL)) {
1509                 /* in case of Roman characters */
1510                 if (shift_mode) { 
1511                     /* output 1 shifted byte */
1512                     if (iso8859_f) {
1513                         c2 = ISO8859_1;
1514                         SEND;
1515                     } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
1516                       /* output 1 shifted byte */
1517                         if(iso2022jp_f && x0201_f==NO_X0201) {
1518                             (*oconv)(GETA1, GETA2);
1519                             NEXT;
1520                         } else {
1521                             c2 = X0201;
1522                             SEND;
1523                         }
1524                     } else {
1525                         /* look like bogus code */
1526                         NEXT;
1527                     }
1528                 } else if (input_mode == X0208) {
1529                     /* in case of Kanji shifted */
1530                     c2 = c1;
1531                     NEXT;
1532                 } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
1533                     /* Check MIME code */
1534                     if ((c1 = (*i_getc)(f)) == EOF) {
1535                         (*oconv)(0, '=');
1536                         LAST;
1537                     } else if (c1 == '?') {
1538                         /* =? is mime conversion start sequence */
1539                         if(mime_f == STRICT_MIME) {
1540                             /* check in real detail */
1541                             if (mime_begin_strict(f) == EOF) 
1542                                 LAST;
1543                             else
1544                                 NEXT;
1545                         } else if (mime_begin(f) == EOF) 
1546                             LAST;
1547                         else
1548                             NEXT;
1549                     } else {
1550                         (*oconv)(0, '=');
1551                         (*i_ungetc)(c1,f);
1552                         NEXT;
1553                     }
1554                 } else {
1555                     /* normal ASCII code */ 
1556                     SEND;
1557                 }
1558             } else if (c1 == SI) {
1559                 shift_mode = FALSE; 
1560                 NEXT;
1561             } else if (c1 == SO) {
1562                 shift_mode = TRUE; 
1563                 NEXT;
1564             } else if (c1 == ESC ) {
1565                 if ((c1 = (*i_getc)(f)) == EOF) {
1566                     /*  (*oconv)(0, ESC); don't send bogus code */
1567                     LAST;
1568                 } else if (c1 == '$') {
1569                     if ((c1 = (*i_getc)(f)) == EOF) {
1570                         /*
1571                         (*oconv)(0, ESC); don't send bogus code 
1572                         (*oconv)(0, '$'); */
1573                         LAST;
1574                     } else if (c1 == '@'|| c1 == 'B') {
1575                         /* This is kanji introduction */
1576                         input_mode = X0208;
1577                         shift_mode = FALSE;
1578                         NEXT;
1579                     } else if (c1 == '(') {
1580                         if ((c1 = (*i_getc)(f)) == EOF) {
1581                             /* don't send bogus code 
1582                             (*oconv)(0, ESC);
1583                             (*oconv)(0, '$');
1584                             (*oconv)(0, '(');
1585                                 */
1586                             LAST;
1587                         } else if (c1 == '@'|| c1 == 'B') {
1588                             /* This is kanji introduction */
1589                             input_mode = X0208;
1590                             shift_mode = FALSE;
1591                             NEXT;
1592                         } else {
1593                             /* could be some special code */
1594                             (*oconv)(0, ESC);
1595                             (*oconv)(0, '$');
1596                             (*oconv)(0, '(');
1597                             (*oconv)(0, c1);
1598                             NEXT;
1599                         }
1600                     } else if (broken_f&0x2) {
1601                         /* accept any ESC-(-x as broken code ... */
1602                         input_mode = X0208;
1603                         shift_mode = FALSE;
1604                         NEXT;
1605                     } else {
1606                         (*oconv)(0, ESC);
1607                         (*oconv)(0, '$');
1608                         (*oconv)(0, c1);
1609                         NEXT;
1610                     }
1611                 } else if (c1 == '(') {
1612                     if ((c1 = (*i_getc)(f)) == EOF) {
1613                         /* don't send bogus code 
1614                         (*oconv)(0, ESC);
1615                         (*oconv)(0, '('); */
1616                         LAST;
1617                     } else {
1618                         if (c1 == 'I') {
1619                             /* This is X0201 kana introduction */
1620                             input_mode = X0201; shift_mode = X0201;
1621                             NEXT;
1622                         } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
1623                             /* This is X0208 kanji introduction */
1624                             input_mode = ASCII; shift_mode = FALSE;
1625                             NEXT;
1626                         } else if (broken_f&0x2) {
1627                             input_mode = ASCII; shift_mode = FALSE;
1628                             NEXT;
1629                         } else {
1630                             (*oconv)(0, ESC);
1631                             (*oconv)(0, '(');
1632                             /* maintain various input_mode here */
1633                             SEND;
1634                         }
1635                     }
1636                } else if ( c1 == 'N' || c1 == 'n' ){
1637                    /* SS2 */
1638                    c1 = (*i_getc)(f);  /* skip SS2 */
1639                    if ( SPACE<=c1 && c1 < 0xe0 ) {
1640                        c2 = X0201;
1641                        SEND;
1642                    }
1643                 } else {
1644                     /* lonely ESC  */
1645                     (*oconv)(0, ESC);
1646                     SEND;
1647                 }
1648             } else if ((c1 == NL || c1 == CR) && broken_f&4) {
1649                 input_mode = ASCII; set_iconv(FALSE, 0);
1650                 SEND;
1651             } else 
1652                 SEND;
1653         }
1654         /* send: */
1655         if (input_mode == X0208) 
1656             (*oconv)(c2, c1);  /* this is JIS, not SJIS/EUC case */
1657         else if (input_mode) 
1658             (*oconv)(input_mode, c1);  /* other special case */
1659         else if ((*iconv)(c2, c1, 0) < 0){  /* can be EUC/SJIS */
1660             int c0 = (*i_getc)(f);
1661             if (c0 != EOF){
1662                 code_status(c0);
1663                 (*iconv)(c2, c1, c0);
1664             }
1665         }
1666
1667         c2 = 0;
1668         continue;
1669         /* goto next_word */
1670     }
1671
1672     /* epilogue */
1673     (*iconv)(EOF, 0, 0);
1674     return 1;
1675 }
1676
1677 int
1678 h_conv(f, c2, c1)
1679     FILE  *f;
1680     int    c1,
1681                     c2;
1682 {
1683     int    wc,c3;
1684
1685
1686     /** it must NOT be in the kanji shifte sequence      */
1687     /** it must NOT be written in JIS7                   */
1688     /** and it must be after 2 byte 8bit code            */
1689
1690     hold_count = 0;
1691     push_hold_buf(c2);
1692     push_hold_buf(c1);
1693     c2 = 0;
1694
1695     while ((c1 = (*i_getc)(f)) != EOF) {
1696         if (c1 == ESC){
1697             (*i_ungetc)(c1,f);
1698             break;
1699         }
1700         code_status(c1);
1701         if (push_hold_buf(c1) == EOF || estab_f){
1702             break;
1703         }
1704     }
1705
1706     if (!estab_f){
1707         if (e_score <= s_score
1708 #ifdef UTF8_INPUT_ENABLE
1709             && e_score <= w_score
1710 #endif
1711             ){
1712             set_iconv(FALSE, e_iconv);
1713         }
1714         else if (s_score <= e_score
1715 #ifdef UTF8_INPUT_ENABLE
1716                  && s_score <= w_score
1717 #endif
1718                  ){
1719             set_iconv(FALSE, s_iconv);
1720         }
1721 #ifdef UTF8_INPUT_ENABLE
1722         else{
1723             set_iconv(FALSE, w_iconv);
1724         }
1725 #endif
1726     }
1727
1728
1729     /** now,
1730      ** 1) EOF is detected, or
1731      ** 2) Code is established, or
1732      ** 3) Buffer is FULL (but last word is pushed)
1733      **
1734      ** in 1) and 3) cases, we continue to use
1735      ** Kanji codes by oconv and leave estab_f unchanged.
1736      **/
1737
1738     wc = 0;
1739     while (wc < hold_count){
1740         c2 = hold_buf[wc++];
1741         if (c2 <= DEL){
1742             (*iconv)(0, c2, 0);
1743             continue;
1744         }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
1745             (*iconv)(X0201, c2, 0);
1746             continue;
1747         }
1748         if (wc < hold_count){
1749             c1 = hold_buf[wc++];
1750         }else{
1751             c1 = (*i_getc)(f);
1752             if (c1 == EOF) break;
1753             code_status(c1);
1754         }
1755         if ((*iconv)(c2, c1, 0) < 0){
1756             int c0;
1757             if (wc < hold_count){
1758                 c0 = hold_buf[wc++];
1759             }else{
1760                 c0 = (*i_getc)(f);
1761                 if (c0 == EOF) break;
1762                 code_status(c0);
1763             }
1764             (*iconv)(c2, c1, c0);
1765             c1 = c0;
1766         }
1767     }
1768     c3=c1;
1769     return c3;
1770 }
1771
1772
1773
1774 int
1775 push_hold_buf(c2)
1776      int             c2;
1777 {
1778     if (hold_count >= HOLD_SIZE*2)
1779         return (EOF);
1780     hold_buf[hold_count++] = c2;
1781     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
1782 }
1783
1784 int s2e_conv(c2, c1, p2, p1)
1785      int c2, c1;
1786      int *p2, *p1;
1787 {
1788     c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
1789     if (c1 < 0x9f)
1790         c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
1791     else {
1792         c1 = c1 - 0x7e;
1793         c2++;
1794     }
1795     if (p2) *p2 = c2;
1796     if (p1) *p1 = c1;
1797     return (c2 << 8) | c1;
1798 }
1799
1800 int
1801 s_iconv(c2, c1, c0)
1802     int    c2,
1803                     c1, c0;
1804 {
1805     if (c2 == X0201) {
1806         c1 &= 0x7f;
1807     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
1808         /* NOP */
1809     } else {
1810         s2e_conv(c2, c1, &c2, &c1);
1811     }
1812     (*oconv)(c2, c1);
1813     return 0;
1814 }
1815
1816 int
1817 e_iconv(c2, c1, c0)
1818     int    c2,
1819                     c1, c0;
1820 {
1821     if (c2 == X0201) {
1822         c1 &= 0x7f;
1823     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
1824         /* NOP */
1825     } else {
1826         c1 &= 0x7f;
1827         c2 &= 0x7f;
1828     }
1829     (*oconv)(c2, c1);
1830     return 0;
1831 }
1832
1833 #ifdef UTF8_INPUT_ENABLE
1834 int
1835 w2e_conv(c2, c1, c0, p2, p1)
1836     int    c2, c1, c0;
1837     int *p2, *p1;
1838 {
1839     extern unsigned short * utf8_to_euc_2bytes[];
1840     extern unsigned short ** utf8_to_euc_3bytes[];
1841
1842     if (0xc0 <= c2 && c2 <= 0xef) {
1843         unsigned short **pp;
1844
1845         if (0xe0 <= c2) {
1846             if (c0 == 0) return -1;
1847             pp = utf8_to_euc_3bytes[c2 - 0x80];
1848             return w_iconv_common(c1, c0, pp, sizeof_utf8_to_euc_C2, p2, p1);
1849         } else {
1850             return w_iconv_common(c2, c1, utf8_to_euc_2bytes, sizeof_utf8_to_euc_2bytes, p2, p1);
1851         }
1852     } else if (c2 == X0201) {
1853         c1 &= 0x7f;
1854     }
1855     if (p2) *p2 = c2;
1856     if (p1) *p1 = c1;
1857     return 0;
1858 }
1859
1860 int
1861 w_iconv(c2, c1, c0)
1862     int    c2,
1863                     c1, c0;
1864 {
1865     int ret = w2e_conv(c2, c1, c0, &c2, &c1);
1866     if (ret == 0){
1867         (*oconv)(c2, c1);
1868     }
1869     return ret;
1870 }
1871
1872 int
1873 w_iconv16(c2, c1, c0)
1874     int    c2, c1,c0;
1875 {
1876     extern unsigned short * utf8_to_euc_2bytes[];
1877     extern unsigned short ** utf8_to_euc_3bytes[];
1878     unsigned short **pp;
1879     unsigned short val;
1880     int psize;
1881     int ret;
1882
1883     if (c2==0376 && c1==0377){
1884         utf16_mode = UTF16_INPUT;
1885         return 0;    
1886     } else if (c2==0377 && c1==0376){
1887         utf16_mode = UTF16BE_INPUT;
1888         return 0;    
1889     }
1890     if (utf16_mode == UTF16BE_INPUT) {
1891         int tmp;
1892         tmp=c1; c1=c2; c2=tmp;
1893     }
1894     if (c2==0 || c2==EOF) {
1895         (*oconv)(c2, c1);
1896         return 0;
1897     }
1898     val = ((c2<<8)&0xff00) + c1;
1899     if (c2 < 0x8){
1900         c0 = (0x80 | (c1 & 0x3f));
1901         c1 = (0xc0 | (val >> 6));
1902         pp = utf8_to_euc_2bytes;
1903         psize = sizeof_utf8_to_euc_2bytes;
1904     }else{
1905         c0 = (0x80 | (c1 & 0x3f));
1906         c2 = (0xe0 | (val >> 12));
1907         c1 = (0x80 | ((val >> 6) & 0x3f));
1908         if (c0 == 0) return -1;
1909         if (0<=c2-0x80 && c2-0x80 <sizeof_utf8_to_euc_3bytes){
1910             pp = utf8_to_euc_3bytes[c2 - 0x80];
1911             psize = sizeof_utf8_to_euc_C2;
1912         }else{
1913             return 0;
1914         }
1915     }
1916     ret = w_iconv_common(c1, c0, pp, psize, &c2, &c1);
1917     if (ret) return ret;
1918     (*oconv)(c2, c1);
1919     return 0;
1920 }
1921
1922 int
1923 w_iconv_common(c1, c0, pp, psize, p2, p1)
1924     int    c1,c0;
1925     unsigned short **pp;
1926     int psize;
1927     int *p2, *p1;
1928 {
1929     int c2;
1930     unsigned short *p ;
1931     unsigned short val;
1932
1933     if (pp == 0) return 1;
1934
1935     c1 -= 0x80;
1936     if (c1 < 0 || psize <= c1) return 1;
1937     p = pp[c1];
1938     if (p == 0)  return 1;
1939
1940     c0 -= 0x80;
1941     if (c0 < 0 || sizeof_utf8_to_euc_E5B8 <= c0) return 1;
1942     val = p[c0];
1943     if (val == 0) return 1;
1944
1945     c2 = val >> 8;
1946     if (c2 == SO) c2 = X0201;
1947     c1 = val & 0x7f;
1948     if (p2) *p2 = c2;
1949     if (p1) *p1 = c1;
1950     return 0;
1951 }
1952
1953 #endif
1954
1955 #ifdef UTF8_OUTPUT_ENABLE
1956 int
1957 e2w_conv(c2, c1)
1958     int    c2, c1;
1959 {
1960     extern unsigned short euc_to_utf8_1byte[];
1961     extern unsigned short * euc_to_utf8_2bytes[];
1962     unsigned short *p;
1963
1964     if (c2 == X0201) {
1965         p = euc_to_utf8_1byte;
1966     } else {
1967         c2 &= 0x7f;
1968         c2 = (c2&0x7f) - 0x21;
1969         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
1970             p = euc_to_utf8_2bytes[c2];
1971         else
1972             return 0;
1973     }
1974     if (!p) return 0;
1975     c1 = (c1 & 0x7f) - 0x21;
1976     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
1977         return p[c1];
1978     return 0;
1979 }
1980
1981 void
1982 w_oconv(c2, c1)
1983     int    c2,
1984                     c1;
1985 {
1986     if (c2 == EOF) {
1987         return;
1988     } else if (c2 == 0) { 
1989         output_mode = ASCII;
1990         (*o_putc)(c1);
1991     } else if (c2 == ISO8859_1) {
1992         output_mode = ISO8859_1;
1993         (*o_putc)(c1 | 0x080);
1994     } else {
1995         unsigned short val = (unsigned short)e2w_conv(c2, c1);
1996         output_mode = UTF8;
1997
1998         if (0 < val && val < 0x80){
1999             (*o_putc)(val);
2000         }else if (val < 0x800){
2001             (*o_putc)(0xc0 | (val >> 6));
2002             (*o_putc)(0x80 | (val & 0x3f));
2003         }else{
2004             (*o_putc)(0xe0 | (val >> 12));
2005             (*o_putc)(0x80 | ((val >> 6) & 0x3f));
2006             (*o_putc)(0x80 | (val & 0x3f));
2007         }
2008     }
2009 }
2010
2011 void
2012 w_oconv16(c2, c1)
2013     int    c2,
2014                     c1;
2015 {
2016     
2017     if (w_oconv16_begin_f==2) {
2018         (*o_putc)('\376');
2019         (*o_putc)('\377');
2020         w_oconv16_begin_f=1;
2021     }
2022     if (c2 == EOF) {
2023         return;
2024     } else if (c2 == 0) { 
2025         (*o_putc)(0);
2026         (*o_putc)(c1);
2027     } else if (c2 == ISO8859_1) {
2028         (*o_putc)(0);
2029         (*o_putc)(c1 | 0x080);
2030     } else {
2031         unsigned short val = (unsigned short)e2w_conv(c2, c1);
2032         (*o_putc)((val&0xff00)>>8);
2033         (*o_putc)(val&0xff);
2034     }
2035 }
2036
2037 #endif
2038
2039 void
2040 e_oconv(c2, c1)
2041     int    c2,
2042                     c1;
2043 {
2044     if (c2 == EOF) {
2045         return;
2046     } else if (c2 == 0) { 
2047         output_mode = ASCII;
2048         (*o_putc)(c1);
2049     } else if (c2 == X0201) {
2050         output_mode = JAPANESE_EUC;
2051         (*o_putc)(SSO); (*o_putc)(c1|0x80);
2052     } else if (c2 == ISO8859_1) {
2053         output_mode = ISO8859_1;
2054         (*o_putc)(c1 | 0x080);
2055     } else {
2056         if ((c1<0x20 || 0x7e<c1) ||
2057            (c2<0x20 || 0x7e<c2)) {
2058             set_iconv(FALSE, 0);
2059             return; /* too late to rescue this char */
2060         }
2061         output_mode = JAPANESE_EUC;
2062         (*o_putc)(c2 | 0x080);
2063         (*o_putc)(c1 | 0x080);
2064     }
2065 }
2066
2067
2068
2069 void
2070 s_oconv(c2, c1)
2071     int    c2,
2072                     c1;
2073 {
2074     if (c2 == EOF) {
2075         return;
2076     } else if (c2 == 0) {
2077         output_mode = ASCII;
2078         (*o_putc)(c1);
2079     } else if (c2 == X0201) {
2080         output_mode = SHIFT_JIS;
2081         (*o_putc)(c1|0x80);
2082     } else if (c2 == ISO8859_1) {
2083         output_mode = ISO8859_1;
2084         (*o_putc)(c1 | 0x080);
2085     } else {
2086         if ((c1<0x20 || 0x7e<c1) ||
2087            (c2<0x20 || 0x7e<c2)) {
2088             set_iconv(FALSE, 0);
2089             return; /* too late to rescue this char */
2090         }
2091         output_mode = SHIFT_JIS;
2092         (*o_putc)((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
2093         (*o_putc)((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
2094     }
2095 }
2096
2097 void
2098 j_oconv(c2, c1)
2099     int    c2,
2100                     c1;
2101 {
2102     if (c2 == EOF) {
2103         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2104             (*o_putc)(ESC);
2105             (*o_putc)('(');
2106             (*o_putc)(ascii_intro);
2107             output_mode = ASCII;
2108         }
2109     } else if (c2==X0201) {
2110         if (output_mode!=X0201) {
2111             output_mode = X0201;
2112             (*o_putc)(ESC);
2113             (*o_putc)('(');
2114             (*o_putc)('I');
2115         }
2116         (*o_putc)(c1);
2117     } else if (c2==ISO8859_1) {
2118             /* iso8859 introduction, or 8th bit on */
2119             /* Can we convert in 7bit form using ESC-'-'-A ? 
2120                Is this popular? */
2121         output_mode = ISO8859_1;
2122         (*o_putc)(c1|0x80);
2123     } else if (c2 == 0) {
2124         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2125             (*o_putc)(ESC);
2126             (*o_putc)('(');
2127             (*o_putc)(ascii_intro);
2128             output_mode = ASCII;
2129         }
2130         (*o_putc)(c1);
2131     } else {
2132         if (output_mode != X0208) {
2133             output_mode = X0208;
2134             (*o_putc)(ESC);
2135             (*o_putc)('$');
2136             (*o_putc)(kanji_intro);
2137         }
2138         if (c1<0x20 || 0x7e<c1) 
2139             return;
2140         if (c2<0x20 || 0x7e<c2) 
2141             return;
2142         (*o_putc)(c2);
2143         (*o_putc)(c1);
2144     }
2145 }
2146
2147 void
2148 base64_conv(c2, c1)
2149     int    c2,
2150                     c1;
2151 {
2152     if (base64_count>50 && !mimeout_mode && c2==0 && c1==SPACE) {
2153         (*o_putc)(NL);
2154     } else if (base64_count>66 && mimeout_mode) {
2155         (*o_base64conv)(EOF,0);
2156         (*o_putc)(NL);
2157         (*o_putc)(' ');
2158     }
2159     (*o_base64conv)(c2,c1);
2160 }
2161
2162
2163 static int broken_buf[3];
2164 static int broken_counter = 0;
2165 static int broken_last = 0;
2166 int
2167 broken_getc(f)
2168 FILE *f;
2169 {
2170     int c,c1;
2171
2172     if (broken_counter>0) {
2173         return broken_buf[--broken_counter];
2174     }
2175     c= (*i_bgetc)(f);
2176     if (c=='$' && broken_last != ESC 
2177             && (input_mode==ASCII || input_mode==X0201)) {
2178         c1= (*i_bgetc)(f);
2179         broken_last = 0;
2180         if (c1=='@'|| c1=='B') {
2181             broken_buf[0]=c1; broken_buf[1]=c; 
2182             broken_counter=2;
2183             return ESC;
2184         } else {
2185             (*i_bungetc)(c1,f);
2186             return c;
2187         }
2188     } else if (c=='(' && broken_last != ESC 
2189             && (input_mode==X0208 || input_mode==X0201)) { /* ) */
2190         c1= (*i_bgetc)(f);
2191         broken_last = 0;
2192         if (c1=='J'|| c1=='B') {
2193             broken_buf[0]=c1; broken_buf[1]=c;
2194             broken_counter=2;
2195             return ESC;
2196         } else {
2197             (*i_bungetc)(c1,f);
2198             return c;
2199         }
2200     } else {
2201         broken_last = c;
2202         return c;
2203     }
2204 }
2205
2206 int
2207 broken_ungetc(c,f)
2208 int c;
2209 FILE *f;
2210 {
2211     if (broken_counter<2)
2212         broken_buf[broken_counter++]=c;
2213     return c;
2214 }
2215
2216 static int prev_cr = 0;
2217
2218 void
2219 cr_conv(c2,c1) 
2220 int c2,c1;
2221 {
2222     if (prev_cr) {
2223         prev_cr = 0;
2224         if (! (c2==0&&c1==NL) ) {
2225             cr_conv(0,'\n');
2226         }
2227     }
2228     if (c2) {
2229         (*o_crconv)(c2,c1);
2230     } else if (c1=='\r') {
2231         prev_cr = c1;
2232     } else if (c1=='\n') {
2233         if (crmode_f==CRLF) {
2234             (*o_crconv)(0,'\r');
2235         } else if (crmode_f==CR) {
2236             (*o_crconv)(0,'\r');
2237             return;
2238         } 
2239         (*o_crconv)(0,NL);
2240     } else if (c1!='\032' || crmode_f!=NL){
2241         (*o_crconv)(c2,c1);
2242     }
2243 }
2244
2245 /* 
2246   Return value of fold_conv()
2247
2248        \n  add newline  and output char
2249        \r  add newline  and output nothing
2250        ' ' space
2251        0   skip  
2252        1   (or else) normal output 
2253
2254   fold state in prev (previous character)
2255
2256       >0x80 Japanese (X0208/X0201)
2257       <0x80 ASCII
2258       \n    new line 
2259       ' '   space
2260
2261   This fold algorthm does not preserve heading space in a line.
2262   This is the main difference from fmt.
2263 */
2264
2265 #define char_size(c2,c1) (c2?2:1)
2266
2267 void
2268 fold_conv(c2,c1) 
2269 int c2,c1;
2270
2271     int prev0;
2272     int fold_state=0;
2273
2274     if (c1== '\r') {
2275         fold_state=0;  /* ignroe cr */
2276     } else if (c1== BS) {
2277         if (f_line>0) f_line--;
2278         fold_state =  1;
2279     } else if (c2==EOF && f_line != 0) {    /* close open last line */
2280             fold_state = '\n';
2281     } else if (c1=='\n') {
2282         /* new line */
2283         if (fold_preserve_f) { 
2284                 f_line = 0;
2285                 fold_state =  '\r';
2286         } else if (f_prev == c1) {        /* duplicate newline */
2287             if (f_line) {
2288                 f_line = 0;
2289                 fold_state =  '\n';    /* output two newline */
2290             } else {
2291                 f_line = 0;
2292                 fold_state =  1;
2293             }
2294         } else  {
2295             if (f_prev&0x80) {     /* Japanese? */
2296                 f_prev = c1;
2297                 fold_state =  0;       /* ignore given single newline */
2298             } else if (f_prev==' ') {
2299                 fold_state =  0;
2300             } else {
2301                 f_prev = c1;
2302                 if (++f_line<=fold_len) 
2303                     fold_state =  ' ';
2304                 else {
2305                     f_line = 0;
2306                     fold_state =  '\r';        /* fold and output nothing */
2307                 }
2308             }
2309         }
2310     } else if (c1=='\f') {
2311         f_prev = '\n';
2312         if (f_line==0)
2313             fold_state =  1;
2314         f_line = 0;
2315         fold_state =  '\n';            /* output newline and clear */
2316     } else if ( (c2==0  && c1==' ')||
2317                (c2==0  && c1=='\t')||
2318                (c2=='!'&& c1=='!')) {
2319         /* X0208 kankaku or ascii space */
2320             if (f_prev == ' ') {
2321                 fold_state = 0;         /* remove duplicate spaces */
2322             } else {
2323                 f_prev = ' ';    
2324                 if (++f_line<=fold_len) 
2325                     fold_state = ' ';         /* output ASCII space only */
2326                 else {
2327                     f_prev = ' '; f_line = 0;
2328                     fold_state = '\r';        /* fold and output nothing */
2329                 }
2330             }
2331     } else {
2332         prev0 = f_prev; /* we still need this one... , but almost done */
2333         f_prev = c1;
2334         if (c2 || c2==X0201) 
2335             f_prev |= 0x80;  /* this is Japanese */
2336         f_line += char_size(c2,c1);
2337         if (f_line<=fold_len) {   /* normal case */
2338             fold_state = 1;
2339         } else {
2340             if (f_line>=fold_len+fold_margin) { /* too many kinsou suspension */
2341                 f_line = char_size(c2,c1);
2342                 fold_state =  '\n';       /* We can't wait, do fold now */
2343             } else if (c2==X0201) {
2344             /* simple kinsoku rules  return 1 means no folding  */
2345                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
2346                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
2347                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
2348                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
2349                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
2350                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
2351                 else if (SPACE<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
2352                     f_line = 1;
2353                     fold_state = '\n';/* add one new f_line before this character */
2354                 } else {
2355                     f_line = 1;
2356                     fold_state = '\n';/* add one new f_line before this character */
2357                 }
2358             } else if (c2==0) {
2359                 /* kinsoku point in ASCII */ 
2360                 if (  c1==')'||    /* { [ ( */
2361                      c1==']'||
2362                      c1=='}'||
2363                      c1=='.'||
2364                      c1==','||
2365                      c1=='!'||
2366                      c1=='?'||
2367                      c1=='/'||
2368                      c1==':'||
2369                      c1==';' ) {
2370                     fold_state = 1;
2371                 /* just after special */
2372                 } else if (!is_alnum(prev0)) {
2373                     f_line = char_size(c2,c1);
2374                     fold_state = '\n';
2375                 } else if ((prev0==' ') ||   /* ignored new f_line */
2376                       (prev0=='\n')||        /* ignored new f_line */
2377                       (prev0&0x80)) {        /* X0208 - ASCII */
2378                     f_line = char_size(c2,c1);
2379                     fold_state = '\n';/* add one new f_line before this character */
2380                 } else {
2381                     fold_state = 1;  /* default no fold in ASCII */
2382                 }
2383             } else {
2384                 if (c2=='!') {
2385                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
2386                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
2387                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
2388                     else if (c1=='K')  fold_state = 1; /* \e$B!K\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                     else if (c1=='\'') fold_state = 1; /* \e$B!\\e(B */
2392                     else if (c1=='(')  fold_state = 1; /* \e$B!(\e(B */
2393                     else if (c1==')')  fold_state = 1; /* \e$B!)\e(B */
2394                     else if (c1=='*')  fold_state = 1; /* \e$B!*\e(B */
2395                     else if (c1=='+')  fold_state = 1; /* \e$B!+\e(B */
2396                     else if (c1==',')  fold_state = 1; /* \e$B!,\e(B */
2397                          /* default no fold in kinsoku */
2398                     else { 
2399                         fold_state = '\n';
2400                         f_line = char_size(c2,c1);
2401                         /* add one new f_line before this character */
2402                     }
2403                 } else {
2404                     f_line = char_size(c2,c1);
2405                     fold_state = '\n'; 
2406                     /* add one new f_line before this character */
2407                 }
2408             }
2409         }
2410     }
2411     /* terminator process */
2412     switch(fold_state) {
2413         case '\n': 
2414             (*o_fconv)(0,'\n');
2415             (*o_fconv)(c2,c1);
2416             break;
2417         case 0:    
2418             return;
2419         case '\r': 
2420             (*o_fconv)(0,'\n');
2421             break;
2422         case '\t': 
2423         case ' ': 
2424             (*o_fconv)(0,' ');
2425             break;
2426         default:
2427             (*o_fconv)(c2,c1);
2428     }
2429 }
2430
2431 int z_prev2=0,z_prev1=0;
2432
2433 void
2434 z_conv(c2,c1)
2435 int c2,c1;
2436 {
2437
2438     /* if (c2) c1 &= 0x7f; assertion */
2439
2440     if (x0201_f && z_prev2==X0201) {  /* X0201 */
2441         if (c1==(0xde&0x7f)) { /* \e$BByE@\e(B */
2442             z_prev2=0;
2443             (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
2444             return;
2445         } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) {  /* \e$BH>ByE@\e(B */
2446             z_prev2=0;
2447             (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
2448             return;
2449         } else {
2450             z_prev2=0;
2451             (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
2452         }
2453     }
2454
2455     if (c2==EOF) {
2456         (*o_zconv)(c2,c1);
2457         return;
2458     }
2459
2460     if (x0201_f && c2==X0201) {
2461         if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
2462             /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
2463             z_prev1 = c1; z_prev2 = c2;
2464             return;
2465         } else {
2466             (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
2467             return;
2468         }
2469     }
2470
2471     /* JISX0208 Alphabet */
2472     if (alpha_f && c2 == 0x23 ) {
2473         c2 = 0;
2474     } else if (alpha_f && c2 == 0x21 ) { 
2475     /* JISX0208 Kigou */
2476        if (0x21==c1) {
2477            if (alpha_f&0x2) {
2478                c1 = ' ';
2479                c2 = 0;
2480            } else if (alpha_f&0x4) {
2481                 (*o_zconv)(0,' ');
2482                 (*o_zconv)(0,' ');
2483                 return;
2484            } 
2485        } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
2486            c1 = fv[c1-0x20];
2487            c2 =  0;
2488            if (alpha_f&0x8) {
2489                char *entity = 0;
2490                switch (c1){
2491                  case '>': entity = "&gt;"; break;
2492                  case '<': entity = "&lt;"; break;
2493                  case '\"': entity = "&quot;"; break;
2494                  case '&': entity = "&amp;"; break;
2495                }
2496                if (entity){
2497                    while (*entity) (*o_zconv)(0, *entity++);
2498                    return;
2499                }
2500            }
2501        } 
2502     }
2503     (*o_zconv)(c2,c1);
2504 }
2505
2506
2507 #define rot13(c)  ( \
2508       ( c < 'A' ) ? c: \
2509       (c <= 'M')  ? (c + 13): \
2510       (c <= 'Z')  ? (c - 13): \
2511       (c < 'a')   ? (c): \
2512       (c <= 'm')  ? (c + 13): \
2513       (c <= 'z')  ? (c - 13): \
2514       (c) \
2515 )
2516
2517 #define  rot47(c) ( \
2518       ( c < '!' ) ? c: \
2519       ( c <= 'O' ) ? (c + 47) : \
2520       ( c <= '~' ) ?  (c - 47) : \
2521       c \
2522 )
2523
2524 void
2525 rot_conv(c2,c1)
2526 int c2,c1;
2527 {
2528     if (c2==0 || c2==X0201 || c2==ISO8859_1) {
2529         c1 = rot13(c1);
2530     } else if (c2) {
2531         c1 = rot47(c1);
2532         c2 = rot47(c2);
2533     }
2534     (*o_rot_conv)(c2,c1);
2535 }
2536
2537 void
2538 hira_conv(c2,c1)
2539 int c2,c1;
2540 {
2541     if ((hira_f & 1) && c2==0x25 && 0x20<c1 && c1<0x74) {
2542         c2 = 0x24;
2543     } else if ((hira_f & 2) && c2==0x24 && 0x20<c1 && c1<0x74) {
2544         c2 = 0x25;
2545     } 
2546     (*o_hira_conv)(c2,c1);
2547 }
2548
2549
2550 void
2551 iso2022jp_check_conv(c2,c1)
2552 int    c2, c1;
2553 {
2554     static int range[RANGE_NUM_MAX][2] = {
2555         {0x222f, 0x2239,},
2556         {0x2242, 0x2249,},
2557         {0x2251, 0x225b,},
2558         {0x226b, 0x2271,},
2559         {0x227a, 0x227d,},
2560         {0x2321, 0x232f,},
2561         {0x233a, 0x2340,},
2562         {0x235b, 0x2360,},
2563         {0x237b, 0x237e,},
2564         {0x2474, 0x247e,},
2565         {0x2577, 0x257e,},
2566         {0x2639, 0x2640,},
2567         {0x2659, 0x267e,},
2568         {0x2742, 0x2750,},
2569         {0x2772, 0x277e,},
2570         {0x2841, 0x287e,},
2571         {0x4f54, 0x4f7e,},
2572         {0x7425, 0x747e},
2573     };
2574     int i;
2575     int start, end, c;
2576
2577     if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
2578         c2 = GETA1;
2579         c1 = GETA2;
2580     }
2581     if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
2582         c2 = GETA1;
2583         c1 = GETA2;
2584     }
2585
2586     for (i = 0; i < RANGE_NUM_MAX; i++) {
2587         start = range[i][0];
2588         end   = range[i][1];
2589         c     = (c2 << 8) + c1;
2590         if (c >= start && c <= end) {
2591             c2 = GETA1;
2592             c1 = GETA2;
2593         }
2594     }
2595     (*o_iso2022jp_check_conv)(c2,c1);
2596 }
2597
2598
2599 /* This converts  =?ISO-2022-JP?B?HOGE HOGE?= */
2600
2601 unsigned char *mime_pattern[] = {
2602    (unsigned char *)"\075?EUC-JP?B?",
2603    (unsigned char *)"\075?SHIFT_JIS?B?",
2604    (unsigned char *)"\075?ISO-8859-1?Q?",
2605    (unsigned char *)"\075?ISO-2022-JP?B?",
2606    (unsigned char *)"\075?ISO-2022-JP?Q?",
2607 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
2608    (unsigned char *)"\075?UTF-8?B?",
2609 #endif
2610    NULL
2611 };
2612
2613 int      mime_encode[] = {
2614     JAPANESE_EUC, SHIFT_JIS,ISO8859_1, X0208, X0201,
2615 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
2616     UTF8,
2617 #endif
2618     0
2619 };
2620
2621 int      mime_encode_method[] = {
2622     'B', 'B','Q', 'B', 'Q',
2623 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
2624     'B',
2625 #endif
2626     0
2627 };
2628
2629
2630 #define MAXRECOVER 20
2631
2632 /* I don't trust portablity of toupper */
2633 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
2634 #define nkf_isdigit(c)  ('0'<=c && c<='9')
2635 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
2636
2637 void
2638 switch_mime_getc()
2639 {
2640     if (i_getc!=mime_getc) {
2641         i_mgetc = i_getc; i_getc = mime_getc;
2642         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
2643         if(mime_f==STRICT_MIME) {
2644             i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
2645             i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
2646         }
2647     }
2648 }
2649
2650 void
2651 unswitch_mime_getc()
2652 {
2653     if(mime_f==STRICT_MIME) {
2654         i_mgetc = i_mgetc_buf;
2655         i_mungetc = i_mungetc_buf;
2656     }
2657     i_getc = i_mgetc;
2658     i_ungetc = i_mungetc;
2659 }
2660
2661 int
2662 mime_begin_strict(f)
2663 FILE *f;
2664 {
2665     int c1 = 0;
2666     int i,j,k;
2667     unsigned char *p,*q;
2668     int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */
2669
2670     mime_decode_mode = FALSE;
2671     /* =? has been checked */
2672     j = 0;
2673     p = mime_pattern[j];
2674     r[0]='='; r[1]='?';
2675
2676     for(i=2;p[i]>' ';i++) {                   /* start at =? */
2677         if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
2678             /* pattern fails, try next one */
2679             q = p;
2680             while ((p = mime_pattern[++j])) {
2681                 for(k=2;k<i;k++)              /* assume length(p) > i */
2682                     if (p[k]!=q[k]) break;
2683                 if (k==i && nkf_toupper(c1)==p[k]) break;
2684             }
2685             if (p) continue;  /* found next one, continue */
2686             /* all fails, output from recovery buffer */
2687             (*i_ungetc)(c1,f);
2688             for(j=0;j<i;j++) {
2689                 (*oconv)(0,r[j]);
2690             }
2691             return c1;
2692         }
2693     }
2694     mime_decode_mode = p[i-2];
2695     if (mime_decode_mode=='B') {
2696         mimebuf_f = unbuf_f;
2697         if (!unbuf_f) {
2698             /* do MIME integrity check */
2699             return mime_integrity(f,mime_pattern[j]);
2700         } 
2701     }
2702     switch_mime_getc();
2703     mimebuf_f = TRUE;
2704     return c1;
2705 }
2706
2707 int
2708 mime_getc_buf(f) 
2709 FILE *f;
2710 {
2711     /* we don't keep eof of Fifo, becase it contains ?= as
2712        a terminator. It was checked in mime_integrity. */
2713     return ((mimebuf_f)?
2714         (*i_mgetc_buf)(f):Fifo(mime_input++));
2715 }
2716
2717 int
2718 mime_ungetc_buf(c,f) 
2719 FILE *f;
2720 int c;
2721 {
2722     if (mimebuf_f)
2723         (*i_mungetc_buf)(c,f);
2724     else 
2725         Fifo(--mime_input)=c;
2726     return c;
2727 }
2728
2729 int
2730 mime_begin(f)
2731 FILE *f;
2732 {
2733     int c1;
2734     int i,k;
2735
2736     /* In NONSTRICT mode, only =? is checked. In case of failure, we  */
2737     /* re-read and convert again from mime_buffer.  */
2738
2739     /* =? has been checked */
2740     k = mime_last;
2741     Fifo(mime_last++)='='; Fifo(mime_last++)='?';
2742     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
2743         /* We accept any character type even if it is breaked by new lines */
2744         c1 = (*i_getc)(f); Fifo(mime_last++)= c1 ;
2745         if (c1=='\n'||c1==' '||c1=='\r'||
2746                 c1=='-'||c1=='_'||is_alnum(c1) ) continue;
2747         if (c1=='=') {
2748             /* Failed. But this could be another MIME preemble */
2749             (*i_ungetc)(c1,f);
2750             mime_last--;
2751             break;
2752         }
2753         if (c1!='?') break;
2754         else {
2755             /* c1=='?' */
2756             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
2757             if (!(++i<MAXRECOVER) || c1==EOF) break;
2758             if (c1=='b'||c1=='B') {
2759                 mime_decode_mode = 'B';
2760             } else if (c1=='q'||c1=='Q') {
2761                 mime_decode_mode = 'Q';
2762             } else {
2763                 break;
2764             }
2765             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
2766             if (!(++i<MAXRECOVER) || c1==EOF) break;
2767             if (c1!='?') {
2768                 mime_decode_mode = FALSE;
2769             }
2770             break;
2771         }
2772     }
2773     switch_mime_getc();
2774     if (!mime_decode_mode) {
2775         /* false MIME premble, restart from mime_buffer */
2776         mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
2777         /* Since we are in MIME mode until buffer becomes empty,    */
2778         /* we never go into mime_begin again for a while.           */
2779         return c1;
2780     }
2781     /* discard mime preemble, and goto MIME mode */
2782     mime_last = k;
2783     /* do no MIME integrity check */
2784     return c1;   /* used only for checking EOF */
2785 }
2786
2787 #ifdef CHECK_OPTION
2788 void
2789 no_putc(c)
2790      int c;
2791 {
2792     ;
2793 }
2794
2795 void debug(str)
2796      char *str;
2797 {
2798     if (debug_f){
2799         fputs(str, stderr);
2800     }
2801 }
2802 #endif
2803
2804 #ifdef CAP_URL_OPTION
2805 int
2806 hex2bin(x)
2807      int x;
2808 {
2809     if (nkf_isdigit(x)) return x - '0';
2810     return nkf_toupper(x) - 'A' + 10;
2811 }
2812
2813 #ifdef ANSI_C_PROTOTYPE
2814 int hex_getc(int ch, FILE *f, int (*g)(FILE *f), int (*u)(int c, FILE *f))
2815 #else
2816 int
2817 hex_getc(ch, f, g, u)
2818      int ch;
2819      FILE *f;
2820      int (*g)();
2821      int (*u)();
2822 #endif
2823 {
2824     int c1, c2, c3;
2825     c1 = (*g)(f);
2826     if (c1 != ch){
2827         return c1;
2828     }
2829     c2 = (*g)(f);
2830     if (!nkf_isxdigit(c2) == EOF){
2831         (*u)(c2, f);
2832         return c1;
2833     }
2834     c3 = (*g)(f);
2835     if (!nkf_isxdigit(c3) == EOF){
2836         (*u)(c2, f);
2837         (*u)(c3, f);
2838         return c1;
2839     }
2840     return (hex2bin(c2) << 4) | hex2bin(c3);
2841 }
2842
2843 int
2844 cap_getc(f)
2845      FILE *f;
2846 {
2847     return hex_getc(':', f, i_cgetc, i_cungetc);
2848 }
2849
2850 int
2851 cap_ungetc(c, f)
2852      int c;
2853      FILE *f;
2854 {
2855     return (*i_cungetc)(c, f);
2856 }
2857
2858 int
2859 url_getc(f)
2860      FILE *f;
2861 {
2862     return hex_getc('%', f, i_ugetc, i_uungetc);
2863 }
2864
2865 int
2866 url_ungetc(c, f)
2867      int c;
2868      FILE *f;
2869 {
2870     return (*i_uungetc)(c, f);
2871 }
2872 #endif
2873
2874
2875 int 
2876 mime_getc(f)
2877 FILE *f;
2878 {
2879     int c1, c2, c3, c4, cc;
2880     int t1, t2, t3, t4, mode, exit_mode;
2881
2882     if (mime_top != mime_last) {  /* Something is in FIFO */
2883         return  Fifo(mime_top++);
2884     }
2885     if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
2886         mime_decode_mode=FALSE;
2887         unswitch_mime_getc();
2888         return (*i_getc)(f);
2889     }
2890
2891     if (mimebuf_f == FIXED_MIME)
2892         exit_mode = mime_decode_mode;
2893     else
2894         exit_mode = FALSE;
2895     if (mime_decode_mode == 'Q') {
2896         if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
2897 restart_mime_q:
2898         if (c1=='_') return ' ';
2899         if (c1!='=' && c1!='?') {
2900             return c1;
2901         }
2902                 
2903         mime_decode_mode = exit_mode; /* prepare for quit */
2904         if (c1<=' ') return c1;
2905         if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
2906         if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
2907             /* end Q encoding */
2908             input_mode = exit_mode;
2909             while((c1=(*i_getc)(f))!=EOF && c1==SPACE 
2910                         /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
2911             return c1;
2912         }
2913         if (c1=='='&&c2<' ') { /* this is soft wrap */
2914             while((c1 =  (*i_mgetc)(f)) <=' ') {
2915                 if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
2916             }
2917             mime_decode_mode = 'Q'; /* still in MIME */
2918             goto restart_mime_q;
2919         }
2920         if (c1=='?') {
2921             mime_decode_mode = 'Q'; /* still in MIME */
2922             (*i_mungetc)(c2,f);
2923             return c1;
2924         }
2925         if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
2926         if (c2<=' ') return c2;
2927         mime_decode_mode = 'Q'; /* still in MIME */
2928 #define hex(c)   (('0'<=c&&c<='9')?(c-'0'):\
2929      ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
2930         return ((hex(c2)<<4) + hex(c3));
2931     }
2932
2933     if (mime_decode_mode != 'B') {
2934         mime_decode_mode = FALSE;
2935         return (*i_mgetc)(f);
2936     }
2937
2938
2939     /* Base64 encoding */
2940     /* 
2941         MIME allows line break in the middle of 
2942         Base64, but we are very pessimistic in decoding
2943         in unbuf mode because MIME encoded code may broken by 
2944         less or editor's control sequence (such as ESC-[-K in unbuffered
2945         mode. ignore incomplete MIME.
2946     */
2947     mode = mime_decode_mode;
2948     mime_decode_mode = exit_mode;  /* prepare for quit */
2949
2950     while ((c1 = (*i_mgetc)(f))<=' ') {
2951         if (c1==EOF)
2952             return (EOF);
2953     }
2954 mime_c2_retry:
2955     if ((c2 = (*i_mgetc)(f))<=' ') {
2956         if (c2==EOF)
2957             return (EOF);
2958         if (mime_f != STRICT_MIME) goto mime_c2_retry;
2959         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
2960         return c2;
2961     }
2962     if ((c1 == '?') && (c2 == '=')) {
2963         input_mode = ASCII;
2964         while((c1=(*i_getc)(f))!=EOF && c1==SPACE 
2965                     /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
2966         return c1;
2967     }
2968 mime_c3_retry:
2969     if ((c3 = (*i_mgetc)(f))<=' ') {
2970         if (c3==EOF)
2971             return (EOF);
2972         if (mime_f != STRICT_MIME) goto mime_c3_retry;
2973         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
2974         return c3;
2975     }
2976 mime_c4_retry:
2977     if ((c4 = (*i_mgetc)(f))<=' ') {
2978         if (c4==EOF)
2979             return (EOF);
2980         if (mime_f != STRICT_MIME) goto mime_c4_retry;
2981         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
2982         return c4;
2983     }
2984
2985     mime_decode_mode = mode; /* still in MIME sigh... */
2986
2987     /* BASE 64 decoding */
2988
2989     t1 = 0x3f & base64decode(c1);
2990     t2 = 0x3f & base64decode(c2);
2991     t3 = 0x3f & base64decode(c3);
2992     t4 = 0x3f & base64decode(c4);
2993     cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
2994     if (c2 != '=') {
2995         Fifo(mime_last++) = cc;
2996         cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
2997         if (c3 != '=') {
2998             Fifo(mime_last++) = cc;
2999             cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
3000             if (c4 != '=') 
3001                 Fifo(mime_last++) = cc;
3002         }
3003     } else {
3004         return c1;
3005     }
3006     return  Fifo(mime_top++);
3007 }
3008
3009 int
3010 mime_ungetc(c,f) 
3011 int   c;
3012 FILE  *f;
3013 {
3014     Fifo(--mime_top) = c;
3015     return c;
3016 }
3017
3018 int
3019 mime_integrity(f,p)
3020 FILE *f;
3021 unsigned char *p;
3022 {
3023     int c,d;
3024     unsigned int q;
3025     /* In buffered mode, read until =? or NL or buffer full
3026      */
3027     mime_input = mime_top;
3028     mime_last = mime_top;
3029     while(*p) Fifo(mime_input++) = *p++;
3030     d = 0;
3031     q = mime_input;
3032     while((c=(*i_getc)(f))!=EOF) {
3033         if (((mime_input-mime_top)&MIME_BUF_MASK)==0) {
3034             break;   /* buffer full */
3035         }
3036         if (c=='=' && d=='?') {
3037             /* checked. skip header, start decode */
3038             Fifo(mime_input++) = c;
3039             /* mime_last_input = mime_input; */
3040             mime_input = q; 
3041             switch_mime_getc();
3042             return 1;
3043         }
3044         if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
3045             break;
3046         /* Should we check length mod 4? */
3047         Fifo(mime_input++) = c;
3048         d=c;
3049     }
3050     /* In case of Incomplete MIME, no MIME decode  */
3051     Fifo(mime_input++) = c;
3052     mime_last = mime_input;     /* point undecoded buffer */
3053     mime_decode_mode = 1;              /* no decode on Fifo last in mime_getc */
3054     switch_mime_getc();         /* anyway we need buffered getc */
3055     return 1;
3056 }
3057
3058 int
3059 base64decode(c)
3060     int            c;
3061 {
3062     int             i;
3063     if (c > '@') {
3064         if (c < '[') {
3065             i = c - 'A';                        /* A..Z 0-25 */
3066         } else {
3067             i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
3068         }
3069     } else if (c > '/') {
3070         i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
3071     } else if (c == '+') {
3072         i = '>'             /* 62 */ ;          /* +  62 */
3073     } else {
3074         i = '?'             /* 63 */ ;          /* / 63 */
3075     }
3076     return (i);
3077 }
3078
3079 static char basis_64[] =
3080    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3081
3082 static int b64c;
3083
3084 void
3085 open_mime(mode)
3086 int mode;
3087 {
3088     unsigned char *p;
3089     int i;
3090     p  = mime_pattern[0];
3091     for(i=0;mime_encode[i];i++) {
3092         if (mode == mime_encode[i]) {
3093             p = mime_pattern[i];
3094                 break;
3095         }
3096     }
3097     mimeout_mode = mime_encode_method[i];
3098             
3099     /* (*o_mputc)(' '); */
3100     while(*p) {
3101         (*o_mputc)(*p++);
3102         base64_count ++;
3103     }
3104 }
3105
3106 void
3107 close_mime()
3108 {
3109     (*o_mputc)('?');
3110     (*o_mputc)('=');
3111     (*o_mputc)(' ');
3112     base64_count += 3;
3113     mimeout_mode = 0;
3114 }
3115
3116 #define itoh4(c)   (c>=10?c+'A'-10:c+'0')
3117
3118 void
3119 mime_putc(c)
3120     int            c;
3121 {
3122     if (mimeout_f==FIXED_MIME) {
3123         if (base64_count>71) {
3124             (*o_mputc)('\n');
3125             base64_count=0;
3126         }
3127     } else if (c==NL) {
3128         base64_count=0;
3129     } 
3130     if (c!=EOF) {
3131         if ( c<=DEL &&(output_mode==ASCII ||output_mode == ISO8859_1 )
3132                 && mimeout_f!=FIXED_MIME) {
3133             if (mimeout_mode=='Q') {
3134                 if (c<=SPACE) {
3135                     close_mime();
3136                 }
3137                 (*o_mputc)(c);
3138                 return;
3139             }
3140             if (mimeout_mode!='B' || c!=SPACE) {
3141                 if (mimeout_mode) {
3142                     mime_putc(EOF);
3143                     mimeout_mode=0;
3144                 }
3145                 (*o_mputc)(c);
3146                 base64_count ++;
3147                 return;
3148             }
3149         } else if (!mimeout_mode && mimeout_f!=FIXED_MIME) {
3150             open_mime(output_mode);
3151         }
3152     } else { /* c==EOF */
3153         switch(mimeout_mode) {
3154         case 'Q':
3155         case 'B':
3156             break;
3157         case 2:
3158             (*o_mputc)(basis_64[((b64c & 0x3)<< 4)]);
3159             (*o_mputc)('=');
3160             (*o_mputc)('=');
3161             base64_count += 3;
3162             break;
3163         case 1:
3164             (*o_mputc)(basis_64[((b64c & 0xF) << 2)]);
3165             (*o_mputc)('=');
3166             base64_count += 2;
3167             break;
3168         }
3169         if (mimeout_mode) {
3170             if (mimeout_f!=FIXED_MIME) {
3171                 close_mime(); 
3172             } else if (mimeout_mode != 'Q')
3173                 mimeout_mode = 'B';
3174         }
3175         return;
3176     }
3177     switch(mimeout_mode) {
3178     case 'Q':
3179         if(c>=DEL) {
3180             (*o_mputc)('=');
3181             (*o_mputc)(itoh4(((c>>4)&0xf)));
3182             (*o_mputc)(itoh4((c&0xf)));
3183         } else {
3184             (*o_mputc)(c);
3185         }
3186         break;
3187     case 'B':
3188         b64c=c;
3189         (*o_mputc)(basis_64[c>>2]);
3190         mimeout_mode=2;
3191         base64_count ++;
3192         break;
3193     case 2:
3194         (*o_mputc)(basis_64[((b64c & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
3195         b64c=c;
3196         mimeout_mode=1;
3197         base64_count ++;
3198         break;
3199     case 1:
3200         (*o_mputc)(basis_64[((b64c & 0xF) << 2) | ((c & 0xC0) >>6)]);
3201         (*o_mputc)(basis_64[c & 0x3F]);
3202         mimeout_mode='B';
3203         base64_count += 2;
3204         break;
3205     }
3206 }
3207
3208
3209 #ifdef PERL_XS
3210 void 
3211 reinit()
3212 {
3213     unbuf_f = FALSE;
3214     estab_f = FALSE;
3215     nop_f = FALSE;
3216     binmode_f = TRUE;       
3217     rot_f = FALSE;         
3218     hira_f = FALSE;         
3219     input_f = FALSE;      
3220     alpha_f = FALSE;     
3221     mime_f = STRICT_MIME; 
3222     mimebuf_f = FALSE; 
3223     broken_f = FALSE;  
3224     iso8859_f = FALSE; 
3225 #if defined(MSDOS) || defined(__OS2__) 
3226      x0201_f = TRUE;   
3227 #else
3228      x0201_f = NO_X0201;
3229 #endif
3230     iso2022jp_f = FALSE;
3231
3232     kanji_intro = DEFAULT_J;
3233     ascii_intro = DEFAULT_R;
3234
3235     output_conv = DEFAULT_CONV; 
3236     oconv = DEFAULT_CONV; 
3237
3238     i_mgetc  = std_getc; 
3239     i_mungetc  = std_ungetc;
3240     i_mgetc_buf = std_getc; 
3241     i_mungetc_buf = std_ungetc;
3242
3243     i_getc= std_getc; 
3244     i_ungetc=std_ungetc;
3245
3246     i_bgetc= std_getc;
3247     i_bungetc= std_ungetc;
3248
3249     o_putc = std_putc;
3250     o_mputc = std_putc;
3251     o_crconv = no_connection; 
3252     o_rot_conv = no_connection; 
3253     o_iso2022jp_check_conv = no_connection;
3254     o_hira_conv = no_connection; 
3255     o_fconv = no_connection; 
3256     o_zconv = no_connection;
3257
3258     i_getc = std_getc;
3259     i_ungetc = std_ungetc;
3260     i_mgetc = std_getc; 
3261     i_mungetc = std_ungetc; 
3262
3263     output_mode = ASCII;
3264     input_mode =  ASCII;
3265     shift_mode =  FALSE;
3266     mime_decode_mode =   FALSE;
3267     file_out = FALSE;
3268     mimeout_mode = 0;
3269     mimeout_f = FALSE;
3270     base64_count = 0;
3271     option_mode = 0;
3272     crmode_f = 0;
3273
3274     e_stat = 0;
3275     s_stat = 0;
3276 #ifdef UTF8_INPUT_ENABLE
3277     w_stat = 0;
3278 #else
3279     w_stat = -1;
3280 #endif
3281 #ifdef UTF8_OUTPUT_ENABLE
3282     if (w_oconv16_begin_f) {
3283         w_oconv16_begin_f = 2;
3284     }
3285 #endif
3286     f_line = 0;    
3287     f_prev = 0;
3288     fold_preserve_f = FALSE; 
3289     fold_f  = FALSE;
3290     fold_len  = 0;
3291     fold_margin  = FOLD_MARGIN;
3292     broken_counter = 0;
3293     broken_last = 0;
3294     z_prev2=0,z_prev1=0;
3295
3296 }
3297 #endif
3298
3299 void 
3300 no_connection(c2,c1) 
3301 int c2,c1;
3302 {
3303     no_connection2(c2,c1,0);
3304 }
3305
3306 int
3307 no_connection2(c2,c1,c0) 
3308 int c2,c1,c0;
3309 {
3310     fprintf(stderr,"nkf internal module connection failure.\n");
3311     exit(1);
3312 }
3313
3314 #ifndef PERL_XS
3315 void 
3316 usage()   
3317 {
3318     fprintf(stderr,"USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
3319     fprintf(stderr,"Flags:\n");
3320     fprintf(stderr,"b,u      Output is bufferred (DEFAULT),Output is unbufferred\n");
3321 #ifdef DEFAULT_CODE_SJIS
3322     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC), UTF-8\n");
3323 #endif
3324 #ifdef DEFAULT_CODE_JIS
3325     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC), UTF-8\n");
3326 #endif
3327 #ifdef DEFAULT_CODE_EUC
3328     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT), UTF-8\n");
3329 #endif
3330 #ifdef DEFAULT_CODE_UTF8
3331     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC), UTF-8 (DEFAULT)\n");
3332 #endif
3333     fprintf(stderr,"J,S,E,W  Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC), UTF-8\n");
3334     fprintf(stderr,"t        no conversion\n");
3335     fprintf(stderr,"i_/o_    Output sequence to designate JIS-kanji/ASCII (DEFAULT B)\n");
3336     fprintf(stderr,"r        {de/en}crypt ROT13/47\n");
3337     fprintf(stderr,"h        1 hirakana->katakana, 2 katakana->hirakana,3 both\n");
3338     fprintf(stderr,"v        Show this usage. V: show version\n");
3339     fprintf(stderr,"m[BQN0]  MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
3340     fprintf(stderr,"M[BQ]    MIME encode [B:base64 Q:quoted]\n");
3341     fprintf(stderr,"l        ISO8859-1 (Latin-1) support\n");
3342     fprintf(stderr,"f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
3343     fprintf(stderr,"Z[0-3]   Convert X0208 alphabet to ASCII  1: Kankaku to space,2: 2 spaces,\n");
3344     fprintf(stderr,"                                          3: Convert HTML Entity\n");
3345     fprintf(stderr,"X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
3346     fprintf(stderr,"B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
3347 #ifdef MSDOS
3348     fprintf(stderr,"T        Text mode output\n");
3349 #endif
3350     fprintf(stderr,"O        Output to File (DEFAULT 'nkf.out')\n");
3351     fprintf(stderr,"d,c      Delete \\r in line feed and \\032, Add \\r in line feed\n");
3352     fprintf(stderr,"I        Convert non ISO-2022-JP charactor to GETA\n");
3353     fprintf(stderr,"-L[uwm]  line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
3354     fprintf(stderr,"long name options\n");
3355     fprintf(stderr," --fj,--unix,--mac,--windows                convert for the system\n");
3356     fprintf(stderr," --jis,--euc,--sjis,--utf8,--utf16,--mime,--base64  convert for the code\n");
3357     fprintf(stderr," --help,--version\n");
3358     version();
3359 }
3360
3361 void
3362 version()
3363 {
3364     fprintf(stderr,"Network Kanji Filter Version %s (%s) "
3365 #if defined(MSDOS) && !defined(_Windows)
3366                   "for DOS"
3367 #endif
3368 #if !defined(__WIN32__) && defined(_Windows)
3369                   "for Win16"
3370 #endif
3371 #if defined(__WIN32__) && defined(_Windows)
3372                   "for Win32"
3373 #endif
3374 #ifdef __OS2__
3375                   "for OS/2"
3376 #endif
3377                   ,Version,Patchlevel);
3378     fprintf(stderr,"\n%s\n",CopyRight);
3379 }
3380 #endif
3381
3382 /**
3383  ** \e$B%Q%C%A@):n<T\e(B
3384  **  void@merope.pleiades.or.jp (Kusakabe Youichi)
3385  **  NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
3386  **  ohta@src.ricoh.co.jp (Junn Ohta)
3387  **  inouet@strl.nhk.or.jp (Tomoyuki Inoue)
3388  **  kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
3389  **  Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
3390  **  a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
3391  **  kono@ie.u-ryukyu.ac.jp (Shinji Kono)
3392  **  GHG00637@nifty-serve.or.jp (COW)
3393  **
3394  ** \e$B:G=*99?7F|\e(B
3395  **  2002.9.24
3396  **/
3397
3398 /* end */