OSDN Git Service

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