OSDN Git Service

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