OSDN Git Service

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