OSDN Git Service

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