OSDN Git Service

bug fix
[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 #endif
3148    (unsigned char *)"\075?US-ASCII?Q?",
3149    NULL
3150 };
3151
3152
3153 /* \e$B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u\e(B */
3154 int (*mime_priority_func[])PROTO((int c2, int c1, int c0)) = {
3155     e_iconv, s_iconv, 0, 0, 0, 0,
3156 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3157     w_iconv,
3158 #endif
3159     0,
3160 };
3161
3162 int      mime_encode[] = {
3163     JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
3164 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3165     UTF8,
3166 #endif
3167     ASCII,
3168     0
3169 };
3170
3171 int      mime_encode_method[] = {
3172     'B', 'B','Q', 'B', 'B', 'Q',
3173 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3174     'B',
3175 #endif
3176     'Q',
3177     0
3178 };
3179
3180
3181 #define MAXRECOVER 20
3182
3183 /* I don't trust portablity of toupper */
3184 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
3185 #define nkf_isdigit(c)  ('0'<=c && c<='9')
3186 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
3187
3188 void
3189 switch_mime_getc()
3190 {
3191     if (i_getc!=mime_getc) {
3192         i_mgetc = i_getc; i_getc = mime_getc;
3193         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
3194         if(mime_f==STRICT_MIME) {
3195             i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
3196             i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
3197         }
3198     }
3199 }
3200
3201 void
3202 unswitch_mime_getc()
3203 {
3204     if(mime_f==STRICT_MIME) {
3205         i_mgetc = i_mgetc_buf;
3206         i_mungetc = i_mungetc_buf;
3207     }
3208     i_getc = i_mgetc;
3209     i_ungetc = i_mungetc;
3210 }
3211
3212 int
3213 mime_begin_strict(f)
3214 FILE *f;
3215 {
3216     int c1 = 0;
3217     int i,j,k;
3218     unsigned char *p,*q;
3219     int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */
3220
3221     mime_decode_mode = FALSE;
3222     /* =? has been checked */
3223     j = 0;
3224     p = mime_pattern[j];
3225     r[0]='='; r[1]='?';
3226
3227     for(i=2;p[i]>' ';i++) {                   /* start at =? */
3228         if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
3229             /* pattern fails, try next one */
3230             q = p;
3231             while ((p = mime_pattern[++j])) {
3232                 for(k=2;k<i;k++)              /* assume length(p) > i */
3233                     if (p[k]!=q[k]) break;
3234                 if (k==i && nkf_toupper(c1)==p[k]) break;
3235             }
3236             if (p) continue;  /* found next one, continue */
3237             /* all fails, output from recovery buffer */
3238             (*i_ungetc)(c1,f);
3239             for(j=0;j<i;j++) {
3240                 (*oconv)(0,r[j]);
3241             }
3242             return c1;
3243         }
3244     }
3245     mime_decode_mode = p[i-2];
3246
3247     clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
3248
3249     if (mime_decode_mode=='B') {
3250         mimebuf_f = unbuf_f;
3251         if (!unbuf_f) {
3252             /* do MIME integrity check */
3253             return mime_integrity(f,mime_pattern[j]);
3254         } 
3255     }
3256     switch_mime_getc();
3257     mimebuf_f = TRUE;
3258     return c1;
3259 }
3260
3261 int
3262 mime_getc_buf(f) 
3263 FILE *f;
3264 {
3265     /* we don't keep eof of Fifo, becase it contains ?= as
3266        a terminator. It was checked in mime_integrity. */
3267     return ((mimebuf_f)?
3268         (*i_mgetc_buf)(f):Fifo(mime_input++));
3269 }
3270
3271 int
3272 mime_ungetc_buf(c,f) 
3273 FILE *f;
3274 int c;
3275 {
3276     if (mimebuf_f)
3277         (*i_mungetc_buf)(c,f);
3278     else 
3279         Fifo(--mime_input)=c;
3280     return c;
3281 }
3282
3283 int
3284 mime_begin(f)
3285 FILE *f;
3286 {
3287     int c1;
3288     int i,k;
3289
3290     /* In NONSTRICT mode, only =? is checked. In case of failure, we  */
3291     /* re-read and convert again from mime_buffer.  */
3292
3293     /* =? has been checked */
3294     k = mime_last;
3295     Fifo(mime_last++)='='; Fifo(mime_last++)='?';
3296     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
3297         /* We accept any character type even if it is breaked by new lines */
3298         c1 = (*i_getc)(f); Fifo(mime_last++)= c1 ;
3299         if (c1=='\n'||c1==' '||c1=='\r'||
3300                 c1=='-'||c1=='_'||is_alnum(c1) ) continue;
3301         if (c1=='=') {
3302             /* Failed. But this could be another MIME preemble */
3303             (*i_ungetc)(c1,f);
3304             mime_last--;
3305             break;
3306         }
3307         if (c1!='?') break;
3308         else {
3309             /* c1=='?' */
3310             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3311             if (!(++i<MAXRECOVER) || c1==EOF) break;
3312             if (c1=='b'||c1=='B') {
3313                 mime_decode_mode = 'B';
3314             } else if (c1=='q'||c1=='Q') {
3315                 mime_decode_mode = 'Q';
3316             } else {
3317                 break;
3318             }
3319             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3320             if (!(++i<MAXRECOVER) || c1==EOF) break;
3321             if (c1!='?') {
3322                 mime_decode_mode = FALSE;
3323             }
3324             break;
3325         }
3326     }
3327     switch_mime_getc();
3328     if (!mime_decode_mode) {
3329         /* false MIME premble, restart from mime_buffer */
3330         mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
3331         /* Since we are in MIME mode until buffer becomes empty,    */
3332         /* we never go into mime_begin again for a while.           */
3333         return c1;
3334     }
3335     /* discard mime preemble, and goto MIME mode */
3336     mime_last = k;
3337     /* do no MIME integrity check */
3338     return c1;   /* used only for checking EOF */
3339 }
3340
3341 #ifdef CHECK_OPTION
3342 void
3343 no_putc(c)
3344      int c;
3345 {
3346     ;
3347 }
3348
3349 void debug(str)
3350      char *str;
3351 {
3352     if (debug_f){
3353         fprintf(stderr, "%s\n", str);
3354     }
3355 }
3356 #endif
3357
3358 void
3359 set_input_codename (codename)
3360     char *codename;
3361 {
3362     if (guess_f && 
3363         is_inputcode_set &&
3364         strcmp(codename, "") != 0 && 
3365         strcmp(codename, input_codename) != 0)
3366     {
3367         is_inputcode_mixed = TRUE;
3368     }
3369     input_codename = codename;
3370     is_inputcode_set = TRUE;
3371 }
3372
3373 void
3374 print_guessed_code (filename)
3375     char *filename;
3376 {
3377     char *codename = "BINARY";
3378     if (!is_inputcode_mixed) {
3379         if (strcmp(input_codename, "") == 0) {
3380             codename = "ASCII";
3381         } else {
3382             codename = input_codename;
3383         }
3384     }
3385     if (filename != NULL) printf("%s:", filename);
3386     printf("%s\n", codename);
3387 }
3388
3389 int
3390 hex2bin(x)
3391      int x;
3392 {
3393     if (nkf_isdigit(x)) return x - '0';
3394     return nkf_toupper(x) - 'A' + 10;
3395 }
3396
3397 #ifdef INPUT_OPTION 
3398
3399 #ifdef ANSI_C_PROTOTYPE
3400 int hex_getc(int ch, FILE *f, int (*g)(FILE *f), int (*u)(int c, FILE *f))
3401 #else
3402 int
3403 hex_getc(ch, f, g, u)
3404      int ch;
3405      FILE *f;
3406      int (*g)();
3407      int (*u)();
3408 #endif
3409 {
3410     int c1, c2, c3;
3411     c1 = (*g)(f);
3412     if (c1 != ch){
3413         return c1;
3414     }
3415     c2 = (*g)(f);
3416     if (!nkf_isxdigit(c2)){
3417         (*u)(c2, f);
3418         return c1;
3419     }
3420     c3 = (*g)(f);
3421     if (!nkf_isxdigit(c3)){
3422         (*u)(c2, f);
3423         (*u)(c3, f);
3424         return c1;
3425     }
3426     return (hex2bin(c2) << 4) | hex2bin(c3);
3427 }
3428
3429 int
3430 cap_getc(f)
3431      FILE *f;
3432 {
3433     return hex_getc(':', f, i_cgetc, i_cungetc);
3434 }
3435
3436 int
3437 cap_ungetc(c, f)
3438      int c;
3439      FILE *f;
3440 {
3441     return (*i_cungetc)(c, f);
3442 }
3443
3444 int
3445 url_getc(f)
3446      FILE *f;
3447 {
3448     return hex_getc('%', f, i_ugetc, i_uungetc);
3449 }
3450
3451 int
3452 url_ungetc(c, f)
3453      int c;
3454      FILE *f;
3455 {
3456     return (*i_uungetc)(c, f);
3457 }
3458 #endif
3459
3460 #ifdef NUMCHAR_OPTION
3461 int
3462 numchar_getc(f)
3463      FILE *f;
3464 {
3465     int (*g)() = i_ngetc;
3466     int (*u)() = i_nungetc;
3467     int i = 0, j;
3468     int buf[8];
3469     long c = -1;
3470
3471     buf[i] = (*g)(f);
3472     if (buf[i] == '&'){
3473         buf[++i] = (*g)(f);
3474         if (buf[i] == '#'){
3475             c = 0;
3476             buf[++i] = (*g)(f);
3477             if (buf[i] == 'x' || buf[i] == 'X'){
3478                 for (j = 0; j < 5; j++){
3479                     buf[++i] = (*g)(f);
3480                     if (!nkf_isxdigit(buf[i])){
3481                         if (buf[i] != ';'){
3482                             c = -1;
3483                         }
3484                         break;
3485                     }
3486                     c <<= 4;
3487                     c |= hex2bin(buf[i]);
3488                 }
3489             }else{
3490                 for (j = 0; j < 6; j++){
3491                     if (j){
3492                         buf[++i] = (*g)(f);
3493                     }
3494                     if (!nkf_isdigit(buf[i])){
3495                         if (buf[i] != ';'){
3496                             c = -1;
3497                         }
3498                         break;
3499                     }
3500                     c *= 10;
3501                     c += hex2bin(buf[i]);
3502                 }
3503             }
3504         }
3505     }
3506     if (c != -1){
3507         return CLASS_UTF16 | c;
3508     }
3509     while (i > 0){
3510         (*u)(buf[i], f);
3511         --i;
3512     }
3513     return buf[0];
3514 }
3515
3516 int
3517 numchar_ungetc(c, f)
3518      int c;
3519      FILE *f;
3520 {
3521     return (*i_nungetc)(c, f);
3522 }
3523 #endif
3524
3525
3526 int 
3527 mime_getc(f)
3528 FILE *f;
3529 {
3530     int c1, c2, c3, c4, cc;
3531     int t1, t2, t3, t4, mode, exit_mode;
3532
3533     if (mime_top != mime_last) {  /* Something is in FIFO */
3534         return  Fifo(mime_top++);
3535     }
3536     if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
3537         mime_decode_mode=FALSE;
3538         unswitch_mime_getc();
3539         return (*i_getc)(f);
3540     }
3541
3542     if (mimebuf_f == FIXED_MIME)
3543         exit_mode = mime_decode_mode;
3544     else
3545         exit_mode = FALSE;
3546     if (mime_decode_mode == 'Q') {
3547         if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
3548 restart_mime_q:
3549         if (c1=='_') return ' ';
3550         if (c1!='=' && c1!='?') {
3551             return c1;
3552         }
3553                 
3554         mime_decode_mode = exit_mode; /* prepare for quit */
3555         if (c1<=' ') return c1;
3556         if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
3557         if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
3558             /* end Q encoding */
3559             input_mode = exit_mode;
3560             while((c1=(*i_getc)(f))!=EOF && c1==SPACE 
3561                         /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
3562             return c1;
3563         }
3564         if (c1=='='&&c2<' ') { /* this is soft wrap */
3565             while((c1 =  (*i_mgetc)(f)) <=' ') {
3566                 if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
3567             }
3568             mime_decode_mode = 'Q'; /* still in MIME */
3569             goto restart_mime_q;
3570         }
3571         if (c1=='?') {
3572             mime_decode_mode = 'Q'; /* still in MIME */
3573             (*i_mungetc)(c2,f);
3574             return c1;
3575         }
3576         if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
3577         if (c2<=' ') return c2;
3578         mime_decode_mode = 'Q'; /* still in MIME */
3579 #define hex(c)   (('0'<=c&&c<='9')?(c-'0'):\
3580      ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
3581         return ((hex(c2)<<4) + hex(c3));
3582     }
3583
3584     if (mime_decode_mode != 'B') {
3585         mime_decode_mode = FALSE;
3586         return (*i_mgetc)(f);
3587     }
3588
3589
3590     /* Base64 encoding */
3591     /* 
3592         MIME allows line break in the middle of 
3593         Base64, but we are very pessimistic in decoding
3594         in unbuf mode because MIME encoded code may broken by 
3595         less or editor's control sequence (such as ESC-[-K in unbuffered
3596         mode. ignore incomplete MIME.
3597     */
3598     mode = mime_decode_mode;
3599     mime_decode_mode = exit_mode;  /* prepare for quit */
3600
3601     while ((c1 = (*i_mgetc)(f))<=' ') {
3602         if (c1==EOF)
3603             return (EOF);
3604     }
3605 mime_c2_retry:
3606     if ((c2 = (*i_mgetc)(f))<=' ') {
3607         if (c2==EOF)
3608             return (EOF);
3609         if (mime_f != STRICT_MIME) goto mime_c2_retry;
3610         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3611         return c2;
3612     }
3613     if ((c1 == '?') && (c2 == '=')) {
3614         input_mode = ASCII;
3615         while((c1=(*i_getc)(f))!=EOF && c1==SPACE 
3616                     /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
3617         return c1;
3618     }
3619 mime_c3_retry:
3620     if ((c3 = (*i_mgetc)(f))<=' ') {
3621         if (c3==EOF)
3622             return (EOF);
3623         if (mime_f != STRICT_MIME) goto mime_c3_retry;
3624         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3625         return c3;
3626     }
3627 mime_c4_retry:
3628     if ((c4 = (*i_mgetc)(f))<=' ') {
3629         if (c4==EOF)
3630             return (EOF);
3631         if (mime_f != STRICT_MIME) goto mime_c4_retry;
3632         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3633         return c4;
3634     }
3635
3636     mime_decode_mode = mode; /* still in MIME sigh... */
3637
3638     /* BASE 64 decoding */
3639
3640     t1 = 0x3f & base64decode(c1);
3641     t2 = 0x3f & base64decode(c2);
3642     t3 = 0x3f & base64decode(c3);
3643     t4 = 0x3f & base64decode(c4);
3644     cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
3645     if (c2 != '=') {
3646         Fifo(mime_last++) = cc;
3647         cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
3648         if (c3 != '=') {
3649             Fifo(mime_last++) = cc;
3650             cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
3651             if (c4 != '=') 
3652                 Fifo(mime_last++) = cc;
3653         }
3654     } else {
3655         return c1;
3656     }
3657     return  Fifo(mime_top++);
3658 }
3659
3660 int
3661 mime_ungetc(c,f) 
3662 int   c;
3663 FILE  *f;
3664 {
3665     Fifo(--mime_top) = c;
3666     return c;
3667 }
3668
3669 int
3670 mime_integrity(f,p)
3671 FILE *f;
3672 unsigned char *p;
3673 {
3674     int c,d;
3675     unsigned int q;
3676     /* In buffered mode, read until =? or NL or buffer full
3677      */
3678     mime_input = mime_top;
3679     mime_last = mime_top;
3680     while(*p) Fifo(mime_input++) = *p++;
3681     d = 0;
3682     q = mime_input;
3683     while((c=(*i_getc)(f))!=EOF) {
3684         if (((mime_input-mime_top)&MIME_BUF_MASK)==0) {
3685             break;   /* buffer full */
3686         }
3687         if (c=='=' && d=='?') {
3688             /* checked. skip header, start decode */
3689             Fifo(mime_input++) = c;
3690             /* mime_last_input = mime_input; */
3691             mime_input = q; 
3692             switch_mime_getc();
3693             return 1;
3694         }
3695         if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
3696             break;
3697         /* Should we check length mod 4? */
3698         Fifo(mime_input++) = c;
3699         d=c;
3700     }
3701     /* In case of Incomplete MIME, no MIME decode  */
3702     Fifo(mime_input++) = c;
3703     mime_last = mime_input;     /* point undecoded buffer */
3704     mime_decode_mode = 1;              /* no decode on Fifo last in mime_getc */
3705     switch_mime_getc();         /* anyway we need buffered getc */
3706     return 1;
3707 }
3708
3709 int
3710 base64decode(c)
3711     int            c;
3712 {
3713     int             i;
3714     if (c > '@') {
3715         if (c < '[') {
3716             i = c - 'A';                        /* A..Z 0-25 */
3717         } else {
3718             i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
3719         }
3720     } else if (c > '/') {
3721         i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
3722     } else if (c == '+') {
3723         i = '>'             /* 62 */ ;          /* +  62 */
3724     } else {
3725         i = '?'             /* 63 */ ;          /* / 63 */
3726     }
3727     return (i);
3728 }
3729
3730 static char basis_64[] =
3731    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3732
3733 static int b64c;
3734
3735 void
3736 open_mime(mode)
3737 int mode;
3738 {
3739     unsigned char *p;
3740     int i;
3741     p  = mime_pattern[0];
3742     for(i=0;mime_encode[i];i++) {
3743         if (mode == mime_encode[i]) {
3744             p = mime_pattern[i];
3745                 break;
3746         }
3747     }
3748     mimeout_mode = mime_encode_method[i];
3749             
3750     /* (*o_mputc)(' '); */
3751     while(*p) {
3752         (*o_mputc)(*p++);
3753         base64_count ++;
3754     }
3755 }
3756
3757 void
3758 close_mime()
3759 {
3760     (*o_mputc)('?');
3761     (*o_mputc)('=');
3762     (*o_mputc)(' ');
3763     base64_count += 3;
3764     mimeout_mode = 0;
3765 }
3766
3767 #define itoh4(c)   (c>=10?c+'A'-10:c+'0')
3768
3769 void
3770 mime_putc(c)
3771     int            c;
3772 {
3773     if (mimeout_f==FIXED_MIME) {
3774         if (base64_count>71) {
3775             (*o_mputc)('\n');
3776             base64_count=0;
3777         }
3778     } else if (c==NL) {
3779         base64_count=0;
3780     } 
3781     if (c!=EOF) {
3782         if ( c<=DEL &&(output_mode==ASCII ||output_mode == ISO8859_1 )
3783                 && mimeout_f!=FIXED_MIME) {
3784             if (mimeout_mode=='Q') {
3785                 if (c<=SPACE) {
3786                     close_mime();
3787                 }
3788                 (*o_mputc)(c);
3789                 return;
3790             }
3791             if (mimeout_mode!='B' || c!=SPACE) {
3792                 if (mimeout_mode) {
3793                     mime_putc(EOF);
3794                     mimeout_mode=0;
3795                 }
3796                 (*o_mputc)(c);
3797                 base64_count ++;
3798                 return;
3799             }
3800         } else if (!mimeout_mode && mimeout_f!=FIXED_MIME) {
3801             open_mime(output_mode);
3802         }
3803     } else { /* c==EOF */
3804         switch(mimeout_mode) {
3805         case 'Q':
3806         case 'B':
3807             break;
3808         case 2:
3809             (*o_mputc)(basis_64[((b64c & 0x3)<< 4)]);
3810             (*o_mputc)('=');
3811             (*o_mputc)('=');
3812             base64_count += 3;
3813             break;
3814         case 1:
3815             (*o_mputc)(basis_64[((b64c & 0xF) << 2)]);
3816             (*o_mputc)('=');
3817             base64_count += 2;
3818             break;
3819         }
3820         if (mimeout_mode) {
3821             if (mimeout_f!=FIXED_MIME) {
3822                 close_mime(); 
3823             } else if (mimeout_mode != 'Q')
3824                 mimeout_mode = 'B';
3825         }
3826         return;
3827     }
3828     switch(mimeout_mode) {
3829     case 'Q':
3830         if(c>=DEL) {
3831             (*o_mputc)('=');
3832             (*o_mputc)(itoh4(((c>>4)&0xf)));
3833             (*o_mputc)(itoh4((c&0xf)));
3834         } else {
3835             (*o_mputc)(c);
3836         }
3837         break;
3838     case 'B':
3839         b64c=c;
3840         (*o_mputc)(basis_64[c>>2]);
3841         mimeout_mode=2;
3842         base64_count ++;
3843         break;
3844     case 2:
3845         (*o_mputc)(basis_64[((b64c & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
3846         b64c=c;
3847         mimeout_mode=1;
3848         base64_count ++;
3849         break;
3850     case 1:
3851         (*o_mputc)(basis_64[((b64c & 0xF) << 2) | ((c & 0xC0) >>6)]);
3852         (*o_mputc)(basis_64[c & 0x3F]);
3853         mimeout_mode='B';
3854         base64_count += 2;
3855         break;
3856     }
3857 }
3858
3859
3860 #ifdef PERL_XS
3861 void 
3862 reinit()
3863 {
3864     unbuf_f = FALSE;
3865     estab_f = FALSE;
3866     nop_f = FALSE;
3867     binmode_f = TRUE;       
3868     rot_f = FALSE;         
3869     hira_f = FALSE;         
3870     input_f = FALSE;      
3871     alpha_f = FALSE;     
3872     mime_f = STRICT_MIME; 
3873     mimebuf_f = FALSE; 
3874     broken_f = FALSE;  
3875     iso8859_f = FALSE; 
3876 #if defined(MSDOS) || defined(__OS2__) 
3877      x0201_f = TRUE;   
3878 #else
3879      x0201_f = NO_X0201;
3880 #endif
3881     iso2022jp_f = FALSE;
3882
3883     kanji_intro = DEFAULT_J;
3884     ascii_intro = DEFAULT_R;
3885
3886     output_conv = DEFAULT_CONV; 
3887     oconv = DEFAULT_CONV; 
3888
3889     i_mgetc  = std_getc; 
3890     i_mungetc  = std_ungetc;
3891     i_mgetc_buf = std_getc; 
3892     i_mungetc_buf = std_ungetc;
3893
3894     i_getc= std_getc; 
3895     i_ungetc=std_ungetc;
3896
3897     i_bgetc= std_getc;
3898     i_bungetc= std_ungetc;
3899
3900     o_putc = std_putc;
3901     o_mputc = std_putc;
3902     o_crconv = no_connection; 
3903     o_rot_conv = no_connection; 
3904     o_iso2022jp_check_conv = no_connection;
3905     o_hira_conv = no_connection; 
3906     o_fconv = no_connection; 
3907     o_zconv = no_connection;
3908
3909     i_getc = std_getc;
3910     i_ungetc = std_ungetc;
3911     i_mgetc = std_getc; 
3912     i_mungetc = std_ungetc; 
3913
3914     output_mode = ASCII;
3915     input_mode =  ASCII;
3916     shift_mode =  FALSE;
3917     mime_decode_mode =   FALSE;
3918     file_out = FALSE;
3919     mimeout_mode = 0;
3920     mimeout_f = FALSE;
3921     base64_count = 0;
3922     option_mode = 0;
3923     crmode_f = 0;
3924
3925     {
3926         struct input_code *p = input_code_list;
3927         while (p->name){
3928             status_reinit(p++);
3929         }
3930     }
3931 #ifdef UTF8_OUTPUT_ENABLE
3932     if (w_oconv16_begin_f) {
3933         w_oconv16_begin_f = 2;
3934     }
3935 #endif
3936     f_line = 0;    
3937     f_prev = 0;
3938     fold_preserve_f = FALSE; 
3939     fold_f  = FALSE;
3940     fold_len  = 0;
3941     fold_margin  = FOLD_MARGIN;
3942     broken_counter = 0;
3943     broken_last = 0;
3944     z_prev2=0,z_prev1=0;
3945
3946     {
3947         int i;
3948         for (i = 0; i < 256; i++){
3949             prefix_table[i] = 0;
3950         }
3951     }
3952     input_codename = "";
3953     is_inputcode_mixed = FALSE;
3954     is_inputcode_set   = FALSE;
3955 }
3956 #endif
3957
3958 void 
3959 no_connection(c2,c1) 
3960 int c2,c1;
3961 {
3962     no_connection2(c2,c1,0);
3963 }
3964
3965 int
3966 no_connection2(c2,c1,c0) 
3967 int c2,c1,c0;
3968 {
3969     fprintf(stderr,"nkf internal module connection failure.\n");
3970     exit(1);
3971 }
3972
3973 #ifndef PERL_XS
3974 void 
3975 usage()   
3976 {
3977     fprintf(stderr,"USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
3978     fprintf(stderr,"Flags:\n");
3979     fprintf(stderr,"b,u      Output is buffered (DEFAULT),Output is unbuffered\n");
3980 #ifdef DEFAULT_CODE_SJIS
3981     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC), UTF-8\n");
3982 #endif
3983 #ifdef DEFAULT_CODE_JIS
3984     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC), UTF-8\n");
3985 #endif
3986 #ifdef DEFAULT_CODE_EUC
3987     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT), UTF-8\n");
3988 #endif
3989 #ifdef DEFAULT_CODE_UTF8
3990     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC), UTF-8 (DEFAULT)\n");
3991 #endif
3992     fprintf(stderr,"J,S,E,W  Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC), UTF-8\n");
3993     fprintf(stderr,"t        no conversion\n");
3994     fprintf(stderr,"i_/o_    Output sequence to designate JIS-kanji/ASCII (DEFAULT B)\n");
3995     fprintf(stderr,"r        {de/en}crypt ROT13/47\n");
3996     fprintf(stderr,"h        1 hirakana->katakana, 2 katakana->hirakana,3 both\n");
3997     fprintf(stderr,"v        Show this usage. V: show version\n");
3998     fprintf(stderr,"m[BQN0]  MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
3999     fprintf(stderr,"M[BQ]    MIME encode [B:base64 Q:quoted]\n");
4000     fprintf(stderr,"l        ISO8859-1 (Latin-1) support\n");
4001     fprintf(stderr,"f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
4002     fprintf(stderr,"Z[0-3]   Convert X0208 alphabet to ASCII  1: Kankaku to space,2: 2 spaces,\n");
4003     fprintf(stderr,"                                          3: Convert HTML Entity\n");
4004     fprintf(stderr,"X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
4005     fprintf(stderr,"B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
4006 #ifdef MSDOS
4007     fprintf(stderr,"T        Text mode output\n");
4008 #endif
4009     fprintf(stderr,"O        Output to File (DEFAULT 'nkf.out')\n");
4010     fprintf(stderr,"d,c      Delete \\r in line feed and \\032, Add \\r in line feed\n");
4011     fprintf(stderr,"I        Convert non ISO-2022-JP charactor to GETA\n");
4012     fprintf(stderr,"-L[uwm]  line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
4013     fprintf(stderr,"long name options\n");
4014     fprintf(stderr," --fj,--unix,--mac,--windows                convert for the system\n");
4015     fprintf(stderr," --jis,--euc,--sjis,--utf8,--utf16,--mime,--base64  convert for the code\n");
4016 #ifdef OVERWRITE
4017     fprintf(stderr," --overwrite          Overwrite original listed files by filtered result\n");
4018 #endif
4019     fprintf(stderr," -g, --guess          Guess the input code\n");
4020     fprintf(stderr," --help,--version\n");
4021     version();
4022 }
4023
4024 void
4025 version()
4026 {
4027     fprintf(stderr,"Network Kanji Filter Version %s (%s) "
4028 #if defined(MSDOS) && !defined(__WIN32__) && !defined(__WIN16__)
4029                   "for DOS"
4030 #endif
4031 #if defined(MSDOS) && defined(__WIN16__)
4032                   "for Win16"
4033 #endif
4034 #if defined(MSDOS) && defined(__WIN32__)
4035                   "for Win32"
4036 #endif
4037 #ifdef __OS2__
4038                   "for OS/2"
4039 #endif
4040                   ,Version,Patchlevel);
4041     fprintf(stderr,"\n%s\n",CopyRight);
4042 }
4043 #endif
4044
4045 /**
4046  ** \e$B%Q%C%A@):n<T\e(B
4047  **  void@merope.pleiades.or.jp (Kusakabe Youichi)
4048  **  NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
4049  **  ohta@src.ricoh.co.jp (Junn Ohta)
4050  **  inouet@strl.nhk.or.jp (Tomoyuki Inoue)
4051  **  kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
4052  **  Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
4053  **  a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
4054  **  kono@ie.u-ryukyu.ac.jp (Shinji Kono)
4055  **  GHG00637@nifty-serve.or.jp (COW)
4056  **
4057  **/
4058
4059 /* end */