OSDN Git Service

--guess オプションなど
[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             guess_f = TRUE;
1225             continue;
1226         case ' ':    
1227         /* module muliple options in a string are allowed for Perl moudle  */
1228             while(*cp && *cp!='-') cp++;
1229             if(*cp=='-') cp++;
1230             continue;
1231         default:
1232             /* bogus option but ignored */
1233             continue;
1234         }
1235     }
1236 }
1237
1238 #ifdef ANSI_C_PROTOTYPE
1239 struct input_code * find_inputcode_byfunc(int (*iconv_func)(int c2,int c1,int c0))
1240 #else
1241 struct input_code * find_inputcode_byfunc(iconv_func)
1242      int (*iconv_func)();
1243 #endif
1244 {
1245     if (iconv_func){
1246         struct input_code *p = input_code_list;
1247         while (p->name){
1248             if (iconv_func == p->iconv_func){
1249                 return p;
1250             }
1251             p++;
1252         }
1253     }
1254     return 0;
1255 }
1256
1257 #ifdef ANSI_C_PROTOTYPE
1258 void set_iconv(int f, int (*iconv_func)(int c2,int c1,int c0))
1259 #else
1260 void set_iconv(f, iconv_func)
1261      int f;
1262      int (*iconv_func)();
1263 #endif
1264 {
1265 #ifdef CHECK_OPTION
1266     static int (*iconv_for_check)() = 0;
1267 #endif
1268 #ifdef INPUT_CODE_FIX
1269     if (f || !input_f)
1270 #endif
1271         if (estab_f != f){
1272             estab_f = f;
1273         }
1274
1275     if (iconv_func
1276 #ifdef INPUT_CODE_FIX
1277         && (f == -TRUE || !input_f) /* -TRUE means "FORCE" */
1278 #endif
1279         ){
1280         iconv = iconv_func;
1281     }
1282 #ifdef CHECK_OPTION
1283     if (estab_f && iconv_for_check != iconv){
1284         struct input_code *p = find_inputcode_byfunc(iconv);
1285         if (p){
1286             set_input_codename(p->name);
1287             debug(input_codename);
1288         }
1289         iconv_for_check = iconv;
1290     }
1291 #endif
1292 }
1293
1294 #define SCORE_L2       (1)                   /* \e$BBh\e(B2\e$B?e=`4A;z\e(B */
1295 #define SCORE_KANA     (SCORE_L2 << 1)       /* \e$B$$$o$f$kH>3Q%+%J\e(B */
1296 #define SCORE_DEPEND   (SCORE_KANA << 1)     /* \e$B5!<o0MB8J8;z\e(B */
1297 #ifdef SHIFTJIS_CP932
1298 #define SCORE_CP932    (SCORE_DEPEND << 1)   /* CP932 \e$B$K$h$kFI$_49$(\e(B */
1299 #define SCORE_NO_EXIST (SCORE_CP932 << 1)    /* \e$BB8:_$7$J$$J8;z\e(B */
1300 #else
1301 #define SCORE_NO_EXIST (SCORE_DEPEND << 1)   /* \e$BB8:_$7$J$$J8;z\e(B */
1302 #endif
1303 #define SCORE_iMIME    (SCORE_NO_EXIST << 1) /* MIME \e$B$K$h$k;XDj\e(B */
1304 #define SCORE_ERROR    (SCORE_iMIME << 1) /* \e$B%(%i!<\e(B */
1305
1306 #define SCORE_INIT (SCORE_iMIME)
1307
1308 int score_table_A0[] = {
1309     0, 0, 0, 0,
1310     0, 0, 0, 0,
1311     0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1312     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
1313 };
1314
1315 int score_table_F0[] = {
1316     SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
1317     SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
1318     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1319     SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
1320 };
1321
1322 void set_code_score(ptr, score)
1323      struct input_code *ptr;
1324      int score;
1325 {
1326     if (ptr){
1327         ptr->score |= score;
1328     }
1329 }
1330
1331 void clr_code_score(ptr, score)
1332      struct input_code *ptr;
1333      int score;
1334 {
1335     if (ptr){
1336         ptr->score &= ~score;
1337     }
1338 }
1339
1340 void code_score(ptr)
1341      struct input_code *ptr;
1342 {
1343     int c2 = ptr->buf[0];
1344     int c1 = ptr->buf[1];
1345     if (c2 < 0){
1346         set_code_score(ptr, SCORE_ERROR);
1347     }else if (c2 == SSO){
1348         set_code_score(ptr, SCORE_KANA);
1349 #ifdef UTF8_OUTPUT_ENABLE
1350     }else if (!e2w_conv(c2, c1)){
1351         set_code_score(ptr, SCORE_NO_EXIST);
1352 #endif
1353     }else if ((c2 & 0x70) == 0x20){
1354         set_code_score(ptr, score_table_A0[c2 & 0x0f]);
1355     }else if ((c2 & 0x70) == 0x70){
1356         set_code_score(ptr, score_table_F0[c2 & 0x0f]);
1357     }else if ((c2 & 0x70) >= 0x50){
1358         set_code_score(ptr, SCORE_L2);
1359     }
1360 }
1361
1362 void status_disable(ptr)
1363 struct input_code *ptr;
1364 {
1365     ptr->stat = -1;
1366     ptr->buf[0] = -1;
1367     code_score(ptr);
1368     if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
1369 }
1370
1371 void status_push_ch(ptr, c)
1372      struct input_code *ptr;
1373      int c;
1374 {
1375     ptr->buf[ptr->index++] = c;
1376 }
1377
1378 void status_clear(ptr)
1379      struct input_code *ptr;
1380 {
1381     ptr->stat = 0;
1382     ptr->index = 0;
1383 }
1384
1385 void status_reset(ptr)
1386      struct input_code *ptr;
1387 {
1388     status_clear(ptr);
1389     ptr->score = SCORE_INIT;
1390 }
1391
1392 void status_reinit(ptr)
1393      struct input_code *ptr;
1394 {
1395     status_reset(ptr);
1396     ptr->_file_stat = 0;
1397 }
1398
1399 void status_check(ptr, c)
1400      struct input_code *ptr;
1401      int c;
1402 {
1403     if (c <= DEL && estab_f){
1404         status_reset(ptr);
1405     }
1406 }
1407
1408 void s_status(ptr, c)
1409      struct input_code *ptr;
1410      int c;
1411 {
1412     switch(ptr->stat){
1413       case -1:
1414           status_check(ptr, c);
1415           break;
1416       case 0:
1417           if (c <= DEL){
1418               break;
1419 #ifdef NUMCHAR_OPTION
1420           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1421               break;
1422 #endif
1423           }else if (0xa1 <= c && c <= 0xdf){
1424               status_push_ch(ptr, SSO);
1425               status_push_ch(ptr, c);
1426               code_score(ptr);
1427               status_clear(ptr);
1428           }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xef)){
1429               ptr->stat = 1;
1430               status_push_ch(ptr, c);
1431 #ifdef SHIFTJIS_CP932
1432           }else if (cp932_f
1433                     && CP932_TABLE_BEGIN <= c && c <= CP932_TABLE_END){
1434               ptr->stat = 2;
1435               status_push_ch(ptr, c);
1436 #endif /* SHIFTJIS_CP932 */
1437           }else{
1438               status_disable(ptr);
1439           }
1440           break;
1441       case 1:
1442           if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1443               status_push_ch(ptr, c);
1444               s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
1445               code_score(ptr);
1446               status_clear(ptr);
1447           }else{
1448               status_disable(ptr);
1449           }
1450           break;
1451 #ifdef SHIFTJIS_CP932
1452       case 2:
1453           if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1454               status_push_ch(ptr, c);
1455               if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0){
1456                   set_code_score(ptr, SCORE_CP932);
1457                   status_clear(ptr);
1458                   break;
1459               }
1460           }
1461           status_disable(ptr);
1462           break;
1463 #endif /* SHIFTJIS_CP932 */
1464     }
1465 }
1466
1467 void e_status(ptr, c)
1468      struct input_code *ptr;
1469      int c;
1470 {
1471     switch (ptr->stat){
1472       case -1:
1473           status_check(ptr, c);
1474           break;
1475       case 0:
1476           if (c <= DEL){
1477               break;
1478 #ifdef NUMCHAR_OPTION
1479           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1480               break;
1481 #endif
1482           }else if (SSO == c || (0xa1 <= c && c <= 0xfe)){
1483               ptr->stat = 1;
1484               status_push_ch(ptr, c);
1485           }else{
1486               status_disable(ptr);
1487           }
1488           break;
1489       case 1:
1490           if (0xa1 <= c && c <= 0xfe){
1491               status_push_ch(ptr, c);
1492               code_score(ptr);
1493               status_clear(ptr);
1494           }else{
1495               status_disable(ptr);
1496           }
1497           break;
1498     }
1499 }
1500
1501 #ifdef UTF8_INPUT_ENABLE
1502 void w16_status(ptr, c)
1503      struct input_code *ptr;
1504      int c;
1505 {
1506     switch (ptr->stat){
1507       case -1:
1508           break;
1509       case 0:
1510           if (ptr->_file_stat == 0){
1511               if (c == 0xfe || c == 0xff){
1512                   ptr->stat = c;
1513                   status_push_ch(ptr, c);
1514                   ptr->_file_stat = 1;
1515               }else{
1516                   status_disable(ptr);
1517                   ptr->_file_stat = -1;
1518               }
1519           }else if (ptr->_file_stat > 0){
1520               ptr->stat = 1;
1521               status_push_ch(ptr, c);
1522           }else if (ptr->_file_stat < 0){
1523               status_disable(ptr);
1524           }
1525           break;
1526
1527       case 1:
1528           if (c == EOF){
1529               status_disable(ptr);
1530               ptr->_file_stat = -1;
1531           }else{
1532               status_push_ch(ptr, c);
1533               status_clear(ptr);
1534           }
1535           break;
1536
1537       case 0xfe:
1538       case 0xff:
1539           if (ptr->stat != c && (c == 0xfe || c == 0xff)){
1540               status_push_ch(ptr, c);
1541               status_clear(ptr);
1542           }else{
1543               status_disable(ptr);
1544               ptr->_file_stat = -1;
1545           }
1546           break;
1547     }
1548 }
1549
1550 void w_status(ptr, c)
1551      struct input_code *ptr;
1552      int c;
1553 {
1554     switch (ptr->stat){
1555       case -1:
1556           status_check(ptr, c);
1557           break;
1558       case 0:
1559           if (c <= DEL){
1560               break;
1561 #ifdef NUMCHAR_OPTION
1562           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1563               break;
1564 #endif
1565           }else if (0xc0 <= c && c <= 0xdf){
1566               ptr->stat = 1;
1567               status_push_ch(ptr, c);
1568           }else if (0xe0 <= c && c <= 0xef){
1569               ptr->stat = 2;
1570               status_push_ch(ptr, c);
1571           }else{
1572               status_disable(ptr);
1573           }
1574           break;
1575       case 1:
1576       case 2:
1577           if (0x80 <= c && c <= 0xbf){
1578               status_push_ch(ptr, c);
1579               if (ptr->index > ptr->stat){
1580                   int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
1581                              && ptr->buf[2] == 0xbf);
1582                   w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
1583                            &ptr->buf[0], &ptr->buf[1]);
1584                   if (!bom){
1585                       code_score(ptr);
1586                   }
1587                   status_clear(ptr);
1588               }
1589           }else{
1590               status_disable(ptr);
1591           }
1592           break;
1593     }
1594 }
1595 #endif
1596
1597 void
1598 code_status(c)
1599      int c;
1600 {
1601     int action_flag = 1;
1602     struct input_code *result = 0;
1603     struct input_code *p = input_code_list;
1604     while (p->name){
1605         (p->status_func)(p, c);
1606         if (p->stat > 0){
1607             action_flag = 0;
1608         }else if(p->stat == 0){
1609             if (result){
1610                 action_flag = 0;
1611             }else{
1612                 result = p;
1613             }
1614         }
1615         ++p;
1616     }
1617
1618     if (action_flag){
1619         if (result && !estab_f){
1620             set_iconv(TRUE, result->iconv_func);
1621         }else if (c <= DEL){
1622             struct input_code *ptr = input_code_list;
1623             while (ptr->name){
1624                 status_reset(ptr);
1625                 ++ptr;
1626             }
1627         }
1628     }
1629 }
1630
1631 #ifdef PERL_XS
1632 #define STD_GC_BUFSIZE (256)
1633 int std_gc_buf[STD_GC_BUFSIZE];
1634 int std_gc_ndx;
1635 #endif
1636
1637 int 
1638 std_getc(f)
1639 FILE *f;
1640 {
1641 #ifdef PERL_XS
1642     if (std_gc_ndx){
1643         return std_gc_buf[--std_gc_ndx];
1644     }
1645 #endif
1646     return getc(f);
1647 }
1648
1649 int 
1650 std_ungetc(c,f)
1651 int c;
1652 FILE *f;
1653 {
1654 #ifdef PERL_XS
1655     if (std_gc_ndx == STD_GC_BUFSIZE){
1656         return EOF;
1657     }
1658     std_gc_buf[std_gc_ndx++] = c;
1659     return c;
1660 #endif
1661     return ungetc(c,f);
1662 }
1663
1664 void 
1665 std_putc(c)
1666 int c;
1667 {
1668     if(c!=EOF)
1669       putchar(c);
1670 }
1671
1672 int
1673 noconvert(f)
1674     FILE  *f;
1675 {
1676     int    c;
1677
1678     while ((c = (*i_getc)(f)) != EOF)
1679       (*o_putc)(c);
1680     return 1;
1681 }
1682
1683
1684 void
1685 module_connection()
1686 {
1687     oconv = output_conv; 
1688     o_putc = std_putc;
1689
1690     /* replace continucation module, from output side */
1691
1692     /* output redicrection */
1693 #ifdef CHECK_OPTION
1694     if (noout_f || guess_f){
1695         o_putc = no_putc;
1696     }
1697 #endif
1698     if (mimeout_f) {
1699         o_mputc = o_putc;
1700         o_putc = mime_putc;
1701         if (mimeout_f == TRUE) {
1702             o_base64conv = oconv; oconv = base64_conv;
1703         }
1704         /* base64_count = 0; */
1705     }
1706
1707     if (crmode_f) {
1708         o_crconv = oconv; oconv = cr_conv;
1709     }
1710     if (rot_f) {
1711         o_rot_conv = oconv; oconv = rot_conv;
1712     }
1713     if (iso2022jp_f) {
1714         o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
1715     }
1716     if (hira_f) {
1717         o_hira_conv = oconv; oconv = hira_conv;
1718     }
1719     if (fold_f) {
1720         o_fconv = oconv; oconv = fold_conv;
1721         f_line = 0;
1722     }
1723     if (alpha_f || x0201_f) {
1724         o_zconv = oconv; oconv = z_conv;
1725     }
1726
1727     i_getc = std_getc;
1728     i_ungetc = std_ungetc;
1729     /* input redicrection */
1730 #ifdef INPUT_OPTION
1731     if (cap_f){
1732         i_cgetc = i_getc; i_getc = cap_getc;
1733         i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
1734     }
1735     if (url_f){
1736         i_ugetc = i_getc; i_getc = url_getc;
1737         i_uungetc = i_ungetc; i_ungetc= url_ungetc;
1738     }
1739 #endif
1740 #ifdef NUMCHAR_OPTION
1741     if (numchar_f){
1742         i_ngetc = i_getc; i_getc = numchar_getc;
1743         i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
1744     }
1745 #endif
1746     if (mime_f && mimebuf_f==FIXED_MIME) {
1747         i_mgetc = i_getc; i_getc = mime_getc;
1748         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
1749     }
1750     if (broken_f & 1) {
1751         i_bgetc = i_getc; i_getc = broken_getc;
1752         i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
1753     }
1754     if (input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
1755         set_iconv(-TRUE, e_iconv);
1756     } else if (input_f == SJIS_INPUT) {
1757         set_iconv(-TRUE, s_iconv);
1758 #ifdef UTF8_INPUT_ENABLE
1759     } else if (input_f == UTF8_INPUT) {
1760         set_iconv(-TRUE, w_iconv);
1761     } else if (input_f == UTF16_INPUT) {
1762         set_iconv(-TRUE, w_iconv16);
1763 #endif
1764     } else {
1765         set_iconv(FALSE, e_iconv);
1766     }
1767
1768     {
1769         struct input_code *p = input_code_list;
1770         while (p->name){
1771             status_reinit(p++);
1772         }
1773     }
1774 }
1775
1776 /*
1777    Conversion main loop. Code detection only. 
1778  */
1779
1780 int
1781 kanji_convert(f)
1782     FILE  *f;
1783 {
1784     int    c1,
1785                     c2, c3;
1786
1787     module_connection();
1788     c2 = 0;
1789
1790
1791     input_mode = ASCII;
1792     output_mode = ASCII;
1793     shift_mode = FALSE;
1794
1795 #define NEXT continue      /* no output, get next */
1796 #define SEND ;             /* output c1 and c2, get next */
1797 #define LAST break         /* end of loop, go closing  */
1798
1799     while ((c1 = (*i_getc)(f)) != EOF) {
1800         code_status(c1);
1801         if (c2) {
1802             /* second byte */
1803             if (c2 > DEL) {
1804                 /* in case of 8th bit is on */
1805                 if (!estab_f) {
1806                     /* in case of not established yet */
1807                     /* It is still ambiguious */
1808                     if (h_conv(f, c2, c1)==EOF) 
1809                         LAST;
1810                     else 
1811                         c2 = 0;
1812                     NEXT;
1813                 } else
1814                     /* in case of already established */
1815                     if (c1 < AT) {
1816                         /* ignore bogus code */
1817                         c2 = 0;
1818                         NEXT;
1819                     } else
1820                         SEND;
1821             } else
1822                 /* second byte, 7 bit code */
1823                 /* it might be kanji shitfted */
1824                 if ((c1 == DEL) || (c1 <= SPACE)) {
1825                     /* ignore bogus first code */
1826                     c2 = 0;
1827                     NEXT;
1828                 } else
1829                     SEND;
1830         } else {
1831             /* first byte */
1832             if (
1833 #ifdef UTF8_INPUT_ENABLE
1834                 iconv == w_iconv16
1835 #else
1836                 0
1837 #endif
1838                 ) {
1839                 c2 = c1;
1840                 c1 = (*i_getc)(f);
1841                 SEND;
1842 #ifdef NUMCHAR_OPTION
1843             } else if ((c1 & CLASS_MASK) == CLASS_UTF16){
1844                 SEND;
1845 #endif
1846             } else if (c1 > DEL) {
1847                 /* 8 bit code */
1848                 if (!estab_f && !iso8859_f) {
1849                     /* not established yet */
1850                     c2 = c1;
1851                     NEXT;
1852                 } else { /* estab_f==TRUE */
1853                     if (iso8859_f) {
1854                         c2 = ISO8859_1;
1855                         c1 &= 0x7f;
1856                         SEND;
1857                     } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
1858                         /* SJIS X0201 Case... */
1859                         if(iso2022jp_f && x0201_f==NO_X0201) {
1860                             (*oconv)(GETA1, GETA2);
1861                             NEXT;
1862                         } else {
1863                             c2 = X0201;
1864                             c1 &= 0x7f;
1865                             SEND;
1866                         }
1867                     } else if (c1==SSO && iconv != s_iconv) {
1868                         /* EUC X0201 Case */
1869                         c1 = (*i_getc)(f);  /* skip SSO */
1870                         code_status(c1);
1871                         if (SSP<=c1 && c1<0xe0) {
1872                             if(iso2022jp_f &&  x0201_f==NO_X0201) {
1873                                 (*oconv)(GETA1, GETA2);
1874                                 NEXT;
1875                             } else {
1876                                 c2 = X0201;
1877                                 c1 &= 0x7f;
1878                                 SEND;
1879                             }
1880                         } else  { /* bogus code, skip SSO and one byte */
1881                             NEXT;
1882                         }
1883                     } else {
1884                        /* already established */
1885                        c2 = c1;
1886                        NEXT;
1887                     }
1888                 }
1889             } else if ((c1 > SPACE) && (c1 != DEL)) {
1890                 /* in case of Roman characters */
1891                 if (shift_mode) { 
1892                     /* output 1 shifted byte */
1893                     if (iso8859_f) {
1894                         c2 = ISO8859_1;
1895                         SEND;
1896                     } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
1897                       /* output 1 shifted byte */
1898                         if(iso2022jp_f && x0201_f==NO_X0201) {
1899                             (*oconv)(GETA1, GETA2);
1900                             NEXT;
1901                         } else {
1902                             c2 = X0201;
1903                             SEND;
1904                         }
1905                     } else {
1906                         /* look like bogus code */
1907                         NEXT;
1908                     }
1909                 } else if (input_mode == X0208) {
1910                     /* in case of Kanji shifted */
1911                     c2 = c1;
1912                     NEXT;
1913                 } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
1914                     /* Check MIME code */
1915                     if ((c1 = (*i_getc)(f)) == EOF) {
1916                         (*oconv)(0, '=');
1917                         LAST;
1918                     } else if (c1 == '?') {
1919                         /* =? is mime conversion start sequence */
1920                         if(mime_f == STRICT_MIME) {
1921                             /* check in real detail */
1922                             if (mime_begin_strict(f) == EOF) 
1923                                 LAST;
1924                             else
1925                                 NEXT;
1926                         } else if (mime_begin(f) == EOF) 
1927                             LAST;
1928                         else
1929                             NEXT;
1930                     } else {
1931                         (*oconv)(0, '=');
1932                         (*i_ungetc)(c1,f);
1933                         NEXT;
1934                     }
1935                 } else {
1936                     /* normal ASCII code */ 
1937                     SEND;
1938                 }
1939             } else if (c1 == SI) {
1940                 shift_mode = FALSE; 
1941                 NEXT;
1942             } else if (c1 == SO) {
1943                 shift_mode = TRUE; 
1944                 NEXT;
1945             } else if (c1 == ESC ) {
1946                 if ((c1 = (*i_getc)(f)) == EOF) {
1947                     /*  (*oconv)(0, ESC); don't send bogus code */
1948                     LAST;
1949                 } else if (c1 == '$') {
1950                     if ((c1 = (*i_getc)(f)) == EOF) {
1951                         /*
1952                         (*oconv)(0, ESC); don't send bogus code 
1953                         (*oconv)(0, '$'); */
1954                         LAST;
1955                     } else if (c1 == '@'|| c1 == 'B') {
1956                         /* This is kanji introduction */
1957                         input_mode = X0208;
1958                         shift_mode = FALSE;
1959                         set_input_codename("ISO-2022-JP");
1960                         debug(input_codename);
1961                         NEXT;
1962                     } else if (c1 == '(') {
1963                         if ((c1 = (*i_getc)(f)) == EOF) {
1964                             /* don't send bogus code 
1965                             (*oconv)(0, ESC);
1966                             (*oconv)(0, '$');
1967                             (*oconv)(0, '(');
1968                                 */
1969                             LAST;
1970                         } else if (c1 == '@'|| c1 == 'B') {
1971                             /* This is kanji introduction */
1972                             input_mode = X0208;
1973                             shift_mode = FALSE;
1974                             NEXT;
1975                         } else {
1976                             /* could be some special code */
1977                             (*oconv)(0, ESC);
1978                             (*oconv)(0, '$');
1979                             (*oconv)(0, '(');
1980                             (*oconv)(0, c1);
1981                             NEXT;
1982                         }
1983                     } else if (broken_f&0x2) {
1984                         /* accept any ESC-(-x as broken code ... */
1985                         input_mode = X0208;
1986                         shift_mode = FALSE;
1987                         NEXT;
1988                     } else {
1989                         (*oconv)(0, ESC);
1990                         (*oconv)(0, '$');
1991                         (*oconv)(0, c1);
1992                         NEXT;
1993                     }
1994                 } else if (c1 == '(') {
1995                     if ((c1 = (*i_getc)(f)) == EOF) {
1996                         /* don't send bogus code 
1997                         (*oconv)(0, ESC);
1998                         (*oconv)(0, '('); */
1999                         LAST;
2000                     } else {
2001                         if (c1 == 'I') {
2002                             /* This is X0201 kana introduction */
2003                             input_mode = X0201; shift_mode = X0201;
2004                             NEXT;
2005                         } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
2006                             /* This is X0208 kanji introduction */
2007                             input_mode = ASCII; shift_mode = FALSE;
2008                             NEXT;
2009                         } else if (broken_f&0x2) {
2010                             input_mode = ASCII; shift_mode = FALSE;
2011                             NEXT;
2012                         } else {
2013                             (*oconv)(0, ESC);
2014                             (*oconv)(0, '(');
2015                             /* maintain various input_mode here */
2016                             SEND;
2017                         }
2018                     }
2019                } else if ( c1 == 'N' || c1 == 'n' ){
2020                    /* SS2 */
2021                    c3 = (*i_getc)(f);  /* skip SS2 */
2022                    if ( (SPACE<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
2023                        c1 = c3;
2024                        c2 = X0201;
2025                        SEND;
2026                    }else{
2027                        (*i_ungetc)(c3, f);
2028                        /* lonely ESC  */
2029                        (*oconv)(0, ESC);
2030                        SEND;
2031                    }
2032                 } else {
2033                     /* lonely ESC  */
2034                     (*oconv)(0, ESC);
2035                     SEND;
2036                 }
2037             } else if ((c1 == NL || c1 == CR) && broken_f&4) {
2038                 input_mode = ASCII; set_iconv(FALSE, 0);
2039                 SEND;
2040             } else 
2041                 SEND;
2042         }
2043         /* send: */
2044         if (input_mode == X0208) 
2045             (*oconv)(c2, c1);  /* this is JIS, not SJIS/EUC case */
2046         else if (input_mode) 
2047             (*oconv)(input_mode, c1);  /* other special case */
2048         else if ((*iconv)(c2, c1, 0) < 0){  /* can be EUC/SJIS */
2049             int c0 = (*i_getc)(f);
2050             if (c0 != EOF){
2051                 code_status(c0);
2052                 (*iconv)(c2, c1, c0);
2053             }
2054         }
2055
2056         c2 = 0;
2057         continue;
2058         /* goto next_word */
2059     }
2060
2061     /* epilogue */
2062     (*iconv)(EOF, 0, 0);
2063     return 1;
2064 }
2065
2066 int
2067 h_conv(f, c2, c1)
2068     FILE  *f;
2069     int    c1,
2070                     c2;
2071 {
2072     int    wc,c3;
2073
2074
2075     /** it must NOT be in the kanji shifte sequence      */
2076     /** it must NOT be written in JIS7                   */
2077     /** and it must be after 2 byte 8bit code            */
2078
2079     hold_count = 0;
2080     push_hold_buf(c2);
2081     push_hold_buf(c1);
2082     c2 = 0;
2083
2084     while ((c1 = (*i_getc)(f)) != EOF) {
2085         if (c1 == ESC){
2086             (*i_ungetc)(c1,f);
2087             break;
2088         }
2089         code_status(c1);
2090         if (push_hold_buf(c1) == EOF || estab_f){
2091             break;
2092         }
2093     }
2094
2095     if (!estab_f){
2096         struct input_code *p = input_code_list;
2097         struct input_code *result = p;
2098         if (c1 == EOF){
2099             code_status(c1);
2100         }
2101         while (p->name){
2102             if (p->score < result->score){
2103                 result = p;
2104             }
2105             ++p;
2106         }
2107         set_iconv(FALSE, result->iconv_func);
2108     }
2109
2110
2111     /** now,
2112      ** 1) EOF is detected, or
2113      ** 2) Code is established, or
2114      ** 3) Buffer is FULL (but last word is pushed)
2115      **
2116      ** in 1) and 3) cases, we continue to use
2117      ** Kanji codes by oconv and leave estab_f unchanged.
2118      **/
2119
2120     c3=c1;
2121     wc = 0;
2122     while (wc < hold_count){
2123         c2 = hold_buf[wc++];
2124         if (c2 <= DEL
2125 #ifdef NUMCHAR_OPTION
2126             || (c2 & CLASS_MASK) == CLASS_UTF16
2127 #endif
2128             ){
2129             (*iconv)(0, c2, 0);
2130             continue;
2131         }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
2132             (*iconv)(X0201, c2, 0);
2133             continue;
2134         }
2135         if (wc < hold_count){
2136             c1 = hold_buf[wc++];
2137         }else{
2138             c1 = (*i_getc)(f);
2139             if (c1 == EOF){
2140                 c3 = EOF;
2141                 break;
2142             }
2143             code_status(c1);
2144         }
2145         if ((*iconv)(c2, c1, 0) < 0){
2146             int c0;
2147             if (wc < hold_count){
2148                 c0 = hold_buf[wc++];
2149             }else{
2150                 c0 = (*i_getc)(f);
2151                 if (c0 == EOF){
2152                     c3 = EOF;
2153                     break;
2154                 }
2155                 code_status(c0);
2156             }
2157             (*iconv)(c2, c1, c0);
2158             c1 = c0;
2159         }
2160     }
2161     return c3;
2162 }
2163
2164
2165
2166 int
2167 push_hold_buf(c2)
2168      int             c2;
2169 {
2170     if (hold_count >= HOLD_SIZE*2)
2171         return (EOF);
2172     hold_buf[hold_count++] = c2;
2173     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
2174 }
2175
2176 int s2e_conv(c2, c1, p2, p1)
2177      int c2, c1;
2178      int *p2, *p1;
2179 {
2180 #ifdef SHIFTJIS_CP932
2181     if (cp932_f && CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END){
2182         extern unsigned short shiftjis_cp932[3][189];
2183         c1 = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
2184         if (c1 == 0) return 1;
2185         c2 = c1 >> 8;
2186         c1 &= 0xff;
2187     }
2188 #endif /* SHIFTJIS_CP932 */
2189     c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
2190     if (c1 < 0x9f)
2191         c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
2192     else {
2193         c1 = c1 - 0x7e;
2194         c2++;
2195     }
2196     if (p2) *p2 = c2;
2197     if (p1) *p1 = c1;
2198     return 0;
2199 }
2200
2201 int
2202 s_iconv(c2, c1, c0)
2203     int    c2,
2204                     c1, c0;
2205 {
2206     if (c2 == X0201) {
2207         c1 &= 0x7f;
2208     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2209         /* NOP */
2210     } else {
2211         int ret = s2e_conv(c2, c1, &c2, &c1);
2212         if (ret) return ret;
2213     }
2214     (*oconv)(c2, c1);
2215     return 0;
2216 }
2217
2218 int
2219 e_iconv(c2, c1, c0)
2220     int    c2,
2221                     c1, c0;
2222 {
2223     if (c2 == X0201) {
2224         c1 &= 0x7f;
2225     } else if (c2 == SSO){
2226         c2 = X0201;
2227         c1 &= 0x7f;
2228     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2229         /* NOP */
2230     } else {
2231         c1 &= 0x7f;
2232         c2 &= 0x7f;
2233     }
2234     (*oconv)(c2, c1);
2235     return 0;
2236 }
2237
2238 #ifdef UTF8_INPUT_ENABLE
2239 int
2240 w2e_conv(c2, c1, c0, p2, p1)
2241     int    c2, c1, c0;
2242     int *p2, *p1;
2243 {
2244     extern unsigned short * utf8_to_euc_2bytes[];
2245     extern unsigned short ** utf8_to_euc_3bytes[];
2246     int ret = 0;
2247
2248     if (0xc0 <= c2 && c2 <= 0xef) {
2249         unsigned short **pp;
2250
2251         if (0xe0 <= c2) {
2252             if (c0 == 0) return -1;
2253             pp = utf8_to_euc_3bytes[c2 - 0x80];
2254             ret = w_iconv_common(c1, c0, pp, sizeof_utf8_to_euc_C2, p2, p1);
2255         } else {
2256             ret =  w_iconv_common(c2, c1, utf8_to_euc_2bytes, sizeof_utf8_to_euc_2bytes, p2, p1);
2257         }
2258 #ifdef NUMCHAR_OPTION
2259         if (ret){
2260             if (p2) *p2 = 0;
2261             if (p1) *p1 = CLASS_UTF16 | ww16_conv(c2, c1, c0);
2262             ret = 0;
2263         }
2264 #endif
2265         return ret;
2266     } else if (c2 == X0201) {
2267         c1 &= 0x7f;
2268     }
2269     if (p2) *p2 = c2;
2270     if (p1) *p1 = c1;
2271     return ret;
2272 }
2273
2274 int
2275 w_iconv(c2, c1, c0)
2276     int    c2,
2277                     c1, c0;
2278 {
2279     int ret = w2e_conv(c2, c1, c0, &c2, &c1);
2280     if (ret == 0){
2281         (*oconv)(c2, c1);
2282     }
2283     return ret;
2284 }
2285
2286 void
2287 w16w_conv(val, p2, p1, p0)
2288      unsigned short val;
2289      int *p2, *p1, *p0;
2290 {
2291     if (val < 0x80){
2292         *p2 = val;
2293         *p1 = 0;
2294         *p0 = 0;
2295     }else if (val < 0x800){
2296         *p2 = 0xc0 | (val >> 6);
2297         *p1 = 0x80 | (val & 0x3f);
2298         *p0 = 0;
2299     }else{
2300         *p2 = 0xe0 | (val >> 12);
2301         *p1 = 0x80 | ((val >> 6) & 0x3f);
2302         *p0 = 0x80 | (val        & 0x3f);
2303     }
2304 }
2305
2306 int
2307 ww16_conv(c2, c1, c0)
2308      int c2, c1, c0;
2309 {
2310     unsigned short val;
2311     if (c2 >= 0xe0){
2312         val = (c2 & 0x0f) << 12;
2313         val |= (c1 & 0x3f) << 6;
2314         val |= (c0 & 0x3f);
2315     }else if (c2 >= 0xc0){
2316         val = (c2 & 0x1f) << 6;
2317         val |= (c1 & 0x3f) << 6;
2318     }else{
2319         val = c2;
2320     }
2321     return val;
2322 }
2323
2324 int
2325 w16e_conv(val, p2, p1)
2326      unsigned short val;
2327      int *p2, *p1;
2328 {
2329     extern unsigned short * utf8_to_euc_2bytes[];
2330     extern unsigned short ** utf8_to_euc_3bytes[];
2331     int c2, c1, c0;
2332     unsigned short **pp;
2333     int psize;
2334     int ret = 0;
2335
2336     w16w_conv(val, &c2, &c1, &c0);
2337     if (c1){
2338         if (c0){
2339             pp = utf8_to_euc_3bytes[c2 - 0x80];
2340             psize = sizeof_utf8_to_euc_C2;
2341             ret =  w_iconv_common(c1, c0, pp, psize, p2, p1);
2342         }else{
2343             pp = utf8_to_euc_2bytes;
2344             psize = sizeof_utf8_to_euc_2bytes;
2345             ret =  w_iconv_common(c2, c1, pp, psize, p2, p1);
2346         }
2347 #ifdef NUMCHAR_OPTION
2348         if (ret){
2349             *p2 = 0;
2350             *p1 = CLASS_UTF16 | val;
2351             ret = 0;
2352         }
2353 #endif
2354     }
2355     return ret;
2356 }
2357
2358 int
2359 w_iconv16(c2, c1, c0)
2360     int    c2, c1,c0;
2361 {
2362     int ret;
2363
2364     if (c2==0376 && c1==0377){
2365         utf16_mode = UTF16_INPUT;
2366         return 0;    
2367     } else if (c2==0377 && c1==0376){
2368         utf16_mode = UTF16BE_INPUT;
2369         return 0;    
2370     }
2371     if (utf16_mode == UTF16BE_INPUT) {
2372         int tmp;
2373         tmp=c1; c1=c2; c2=tmp;
2374     }
2375     if ((c2==0 && c1 < 0x80) || c2==EOF) {
2376         (*oconv)(c2, c1);
2377         return 0;
2378     }
2379     ret = w16e_conv(((c2<<8)&0xff00) + c1, &c2, &c1);
2380     if (ret) return ret;
2381     (*oconv)(c2, c1);
2382     return 0;
2383 }
2384
2385 int
2386 w_iconv_common(c1, c0, pp, psize, p2, p1)
2387     int    c1,c0;
2388     unsigned short **pp;
2389     int psize;
2390     int *p2, *p1;
2391 {
2392     int c2;
2393     unsigned short *p ;
2394     unsigned short val;
2395
2396     if (pp == 0) return 1;
2397
2398     c1 -= 0x80;
2399     if (c1 < 0 || psize <= c1) return 1;
2400     p = pp[c1];
2401     if (p == 0)  return 1;
2402
2403     c0 -= 0x80;
2404     if (c0 < 0 || sizeof_utf8_to_euc_E5B8 <= c0) return 1;
2405     val = p[c0];
2406     if (val == 0) return 1;
2407
2408     c2 = val >> 8;
2409     if (c2 == SO) c2 = X0201;
2410     c1 = val & 0x7f;
2411     if (p2) *p2 = c2;
2412     if (p1) *p1 = c1;
2413     return 0;
2414 }
2415
2416 #endif
2417
2418 #ifdef UTF8_OUTPUT_ENABLE
2419 int
2420 e2w_conv(c2, c1)
2421     int    c2, c1;
2422 {
2423     extern unsigned short euc_to_utf8_1byte[];
2424     extern unsigned short * euc_to_utf8_2bytes[];
2425     unsigned short *p;
2426
2427     if (c2 == X0201) {
2428         p = euc_to_utf8_1byte;
2429     } else {
2430         c2 &= 0x7f;
2431         c2 = (c2&0x7f) - 0x21;
2432         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
2433             p = euc_to_utf8_2bytes[c2];
2434         else
2435             return 0;
2436     }
2437     if (!p) return 0;
2438     c1 = (c1 & 0x7f) - 0x21;
2439     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
2440         return p[c1];
2441     return 0;
2442 }
2443
2444 void
2445 w_oconv(c2, c1)
2446     int    c2,
2447                     c1;
2448 {
2449     int c0;
2450 #ifdef NUMCHAR_OPTION
2451     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2452         w16w_conv(c1, &c2, &c1, &c0);
2453         (*o_putc)(c2);
2454         if (c1){
2455             (*o_putc)(c1);
2456             if (c0) (*o_putc)(c0);
2457         }
2458     }
2459 #endif
2460     if (c2 == EOF) {
2461         (*o_putc)(EOF);
2462         return;
2463     } else if (c2 == 0) { 
2464         output_mode = ASCII;
2465         (*o_putc)(c1);
2466     } else if (c2 == ISO8859_1) {
2467         output_mode = ISO8859_1;
2468         (*o_putc)(c1 | 0x080);
2469     } else {
2470         output_mode = UTF8;
2471         w16w_conv((unsigned short)e2w_conv(c2, c1), &c2, &c1, &c0);
2472         (*o_putc)(c2);
2473         if (c1){
2474             (*o_putc)(c1);
2475             if (c0) (*o_putc)(c0);
2476         }
2477     }
2478 }
2479
2480 void
2481 w_oconv16(c2, c1)
2482     int    c2,
2483                     c1;
2484 {
2485     if (c2 == EOF) {
2486         (*o_putc)(EOF);
2487         return;
2488     }    
2489
2490     if (w_oconv16_begin_f==2) {
2491         if (w_oconv16_LE){
2492             (*o_putc)((unsigned char)'\377');
2493             (*o_putc)('\376');
2494         }else{
2495             (*o_putc)('\376');
2496             (*o_putc)((unsigned char)'\377');
2497         }
2498         w_oconv16_begin_f=1;
2499     }
2500
2501     if (c2 == ISO8859_1) {
2502         c2 = 0;
2503         c1 |= 0x80;
2504 #ifdef NUMCHAR_OPTION
2505     } else if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16) {
2506         c2 = (c1 >> 8) & 0xff;
2507         c1 &= 0xff;
2508 #endif
2509     } else if (c2) {
2510         unsigned short val = (unsigned short)e2w_conv(c2, c1);
2511         c2 = (val >> 8) & 0xff;
2512         c1 = val & 0xff;
2513     }
2514     if (w_oconv16_LE){
2515         (*o_putc)(c1);
2516         (*o_putc)(c2);
2517     }else{
2518         (*o_putc)(c2);
2519         (*o_putc)(c1);
2520     }
2521 }
2522
2523 #endif
2524
2525 void
2526 e_oconv(c2, c1)
2527     int    c2,
2528                     c1;
2529 {
2530 #ifdef NUMCHAR_OPTION
2531     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2532         w16e_conv(c1, &c2, &c1);
2533     }
2534 #endif
2535     if (c2 == EOF) {
2536         (*o_putc)(EOF);
2537         return;
2538     } else if (c2 == 0) { 
2539         output_mode = ASCII;
2540         (*o_putc)(c1);
2541     } else if (c2 == X0201) {
2542         output_mode = JAPANESE_EUC;
2543         (*o_putc)(SSO); (*o_putc)(c1|0x80);
2544     } else if (c2 == ISO8859_1) {
2545         output_mode = ISO8859_1;
2546         (*o_putc)(c1 | 0x080);
2547     } else {
2548         if ((c1<0x21 || 0x7e<c1) ||
2549            (c2<0x21 || 0x7e<c2)) {
2550             set_iconv(FALSE, 0);
2551             return; /* too late to rescue this char */
2552         }
2553         output_mode = JAPANESE_EUC;
2554         (*o_putc)(c2 | 0x080);
2555         (*o_putc)(c1 | 0x080);
2556     }
2557 }
2558
2559 void
2560 e2s_conv(c2, c1, p2, p1)
2561      int c2, c1, *p2, *p1;
2562 {
2563     if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
2564     if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
2565 }
2566
2567 void
2568 s_oconv(c2, c1)
2569     int    c2,
2570                     c1;
2571 {
2572 #ifdef NUMCHAR_OPTION
2573     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2574         w16e_conv(c1, &c2, &c1);
2575     }
2576 #endif
2577     if (c2 == EOF) {
2578         (*o_putc)(EOF);
2579         return;
2580     } else if (c2 == 0) {
2581         output_mode = ASCII;
2582         (*o_putc)(c1);
2583     } else if (c2 == X0201) {
2584         output_mode = SHIFT_JIS;
2585         (*o_putc)(c1|0x80);
2586     } else if (c2 == ISO8859_1) {
2587         output_mode = ISO8859_1;
2588         (*o_putc)(c1 | 0x080);
2589     } else {
2590         if ((c1<0x20 || 0x7e<c1) ||
2591            (c2<0x20 || 0x7e<c2)) {
2592             set_iconv(FALSE, 0);
2593             return; /* too late to rescue this char */
2594         }
2595         output_mode = SHIFT_JIS;
2596         e2s_conv(c2, c1, &c2, &c1);
2597
2598 #ifdef SHIFTJIS_CP932
2599         if (cp932inv_f
2600             && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
2601             extern unsigned short cp932inv[2][189];
2602             int c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
2603             if (c){
2604                 c2 = c >> 8;
2605                 c1 = c & 0xff;
2606             }
2607         }
2608 #endif /* SHIFTJIS_CP932 */
2609
2610         (*o_putc)(c2);
2611         if (prefix_table[(unsigned char)c1]){
2612             (*o_putc)(prefix_table[(unsigned char)c1]);
2613         }
2614         (*o_putc)(c1);
2615     }
2616 }
2617
2618 void
2619 j_oconv(c2, c1)
2620     int    c2,
2621                     c1;
2622 {
2623 #ifdef NUMCHAR_OPTION
2624     if ((c1 & CLASS_MASK) == CLASS_UTF16){
2625         w16e_conv(c1, &c2, &c1);
2626     }
2627 #endif
2628     if (c2 == EOF) {
2629         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2630             (*o_putc)(ESC);
2631             (*o_putc)('(');
2632             (*o_putc)(ascii_intro);
2633             output_mode = ASCII;
2634         }
2635         (*o_putc)(EOF);
2636     } else if (c2==X0201) {
2637         if (output_mode!=X0201) {
2638             output_mode = X0201;
2639             (*o_putc)(ESC);
2640             (*o_putc)('(');
2641             (*o_putc)('I');
2642         }
2643         (*o_putc)(c1);
2644     } else if (c2==ISO8859_1) {
2645             /* iso8859 introduction, or 8th bit on */
2646             /* Can we convert in 7bit form using ESC-'-'-A ? 
2647                Is this popular? */
2648         output_mode = ISO8859_1;
2649         (*o_putc)(c1|0x80);
2650     } else if (c2 == 0) {
2651         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2652             (*o_putc)(ESC);
2653             (*o_putc)('(');
2654             (*o_putc)(ascii_intro);
2655             output_mode = ASCII;
2656         }
2657         (*o_putc)(c1);
2658     } else {
2659         if (output_mode != X0208) {
2660             output_mode = X0208;
2661             (*o_putc)(ESC);
2662             (*o_putc)('$');
2663             (*o_putc)(kanji_intro);
2664         }
2665         if (c1<0x20 || 0x7e<c1) 
2666             return;
2667         if (c2<0x20 || 0x7e<c2) 
2668             return;
2669         (*o_putc)(c2);
2670         (*o_putc)(c1);
2671     }
2672 }
2673
2674 void
2675 base64_conv(c2, c1)
2676     int    c2,
2677                     c1;
2678 {
2679     if (base64_count>50 && !mimeout_mode && c2==0 && c1==SPACE) {
2680         (*o_putc)(NL);
2681     } else if (base64_count>66 && mimeout_mode) {
2682         (*o_base64conv)(EOF,0);
2683         (*o_putc)(NL);
2684         (*o_putc)('\t'); base64_count += 7;
2685     }
2686     (*o_base64conv)(c2,c1);
2687 }
2688
2689
2690 static int broken_buf[3];
2691 static int broken_counter = 0;
2692 static int broken_last = 0;
2693 int
2694 broken_getc(f)
2695 FILE *f;
2696 {
2697     int c,c1;
2698
2699     if (broken_counter>0) {
2700         return broken_buf[--broken_counter];
2701     }
2702     c= (*i_bgetc)(f);
2703     if (c=='$' && broken_last != ESC 
2704             && (input_mode==ASCII || input_mode==X0201)) {
2705         c1= (*i_bgetc)(f);
2706         broken_last = 0;
2707         if (c1=='@'|| c1=='B') {
2708             broken_buf[0]=c1; broken_buf[1]=c; 
2709             broken_counter=2;
2710             return ESC;
2711         } else {
2712             (*i_bungetc)(c1,f);
2713             return c;
2714         }
2715     } else if (c=='(' && broken_last != ESC 
2716             && (input_mode==X0208 || input_mode==X0201)) { /* ) */
2717         c1= (*i_bgetc)(f);
2718         broken_last = 0;
2719         if (c1=='J'|| c1=='B') {
2720             broken_buf[0]=c1; broken_buf[1]=c;
2721             broken_counter=2;
2722             return ESC;
2723         } else {
2724             (*i_bungetc)(c1,f);
2725             return c;
2726         }
2727     } else {
2728         broken_last = c;
2729         return c;
2730     }
2731 }
2732
2733 int
2734 broken_ungetc(c,f)
2735 int c;
2736 FILE *f;
2737 {
2738     if (broken_counter<2)
2739         broken_buf[broken_counter++]=c;
2740     return c;
2741 }
2742
2743 static int prev_cr = 0;
2744
2745 void
2746 cr_conv(c2,c1) 
2747 int c2,c1;
2748 {
2749     if (prev_cr) {
2750         prev_cr = 0;
2751         if (! (c2==0&&c1==NL) ) {
2752             cr_conv(0,'\n');
2753         }
2754     }
2755     if (c2) {
2756         (*o_crconv)(c2,c1);
2757     } else if (c1=='\r') {
2758         prev_cr = c1;
2759     } else if (c1=='\n') {
2760         if (crmode_f==CRLF) {
2761             (*o_crconv)(0,'\r');
2762         } else if (crmode_f==CR) {
2763             (*o_crconv)(0,'\r');
2764             return;
2765         } 
2766         (*o_crconv)(0,NL);
2767     } else if (c1!='\032' || crmode_f!=NL){
2768         (*o_crconv)(c2,c1);
2769     }
2770 }
2771
2772 /* 
2773   Return value of fold_conv()
2774
2775        \n  add newline  and output char
2776        \r  add newline  and output nothing
2777        ' ' space
2778        0   skip  
2779        1   (or else) normal output 
2780
2781   fold state in prev (previous character)
2782
2783       >0x80 Japanese (X0208/X0201)
2784       <0x80 ASCII
2785       \n    new line 
2786       ' '   space
2787
2788   This fold algorthm does not preserve heading space in a line.
2789   This is the main difference from fmt.
2790 */
2791
2792 #define char_size(c2,c1) (c2?2:1)
2793
2794 void
2795 fold_conv(c2,c1) 
2796 int c2,c1;
2797
2798     int prev0;
2799     int fold_state=0;
2800
2801     if (c1== '\r' && !fold_preserve_f) {
2802         fold_state=0;  /* ignore cr */
2803     }else if (c1== '\n'&&f_prev=='\r' && fold_preserve_f) {
2804         f_prev = '\n';
2805         fold_state=0;  /* ignore cr */
2806     } else if (c1== BS) {
2807         if (f_line>0) f_line--;
2808         fold_state =  1;
2809     } else if (c2==EOF && f_line != 0) {    /* close open last line */
2810             fold_state = '\n';
2811     } else if ((c1=='\n' && !fold_preserve_f)
2812                || ((c1=='\r'||(c1=='\n'&&f_prev!='\r'))
2813                    && fold_preserve_f)) {
2814         /* new line */
2815         if (fold_preserve_f) { 
2816             f_prev = c1;
2817             f_line = 0;
2818             fold_state =  '\r';
2819         } else if ((f_prev == c1 && !fold_preserve_f)
2820                    || (f_prev == '\n' && fold_preserve_f)
2821                    ) {        /* duplicate newline */
2822             if (f_line) {
2823                 f_line = 0;
2824                 fold_state =  '\n';    /* output two newline */
2825             } else {
2826                 f_line = 0;
2827                 fold_state =  1;
2828             }
2829         } else  {
2830             if (f_prev&0x80) {     /* Japanese? */
2831                 f_prev = c1;
2832                 fold_state =  0;       /* ignore given single newline */
2833             } else if (f_prev==' ') {
2834                 fold_state =  0;
2835             } else {
2836                 f_prev = c1;
2837                 if (++f_line<=fold_len) 
2838                     fold_state =  ' ';
2839                 else {
2840                     f_line = 0;
2841                     fold_state =  '\r';        /* fold and output nothing */
2842                 }
2843             }
2844         }
2845     } else if (c1=='\f') {
2846         f_prev = '\n';
2847         if (f_line==0)
2848             fold_state =  1;
2849         f_line = 0;
2850         fold_state =  '\n';            /* output newline and clear */
2851     } else if ( (c2==0  && c1==' ')||
2852                (c2==0  && c1=='\t')||
2853                (c2=='!'&& c1=='!')) {
2854         /* X0208 kankaku or ascii space */
2855             if (f_prev == ' ') {
2856                 fold_state = 0;         /* remove duplicate spaces */
2857             } else {
2858                 f_prev = ' ';    
2859                 if (++f_line<=fold_len) 
2860                     fold_state = ' ';         /* output ASCII space only */
2861                 else {
2862                     f_prev = ' '; f_line = 0;
2863                     fold_state = '\r';        /* fold and output nothing */
2864                 }
2865             }
2866     } else {
2867         prev0 = f_prev; /* we still need this one... , but almost done */
2868         f_prev = c1;
2869         if (c2 || c2==X0201) 
2870             f_prev |= 0x80;  /* this is Japanese */
2871         f_line += char_size(c2,c1);
2872         if (f_line<=fold_len) {   /* normal case */
2873             fold_state = 1;
2874         } else {
2875             if (f_line>=fold_len+fold_margin) { /* too many kinsou suspension */
2876                 f_line = char_size(c2,c1);
2877                 fold_state =  '\n';       /* We can't wait, do fold now */
2878             } else if (c2==X0201) {
2879             /* simple kinsoku rules  return 1 means no folding  */
2880                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
2881                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
2882                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
2883                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
2884                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
2885                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
2886                 else if (SPACE<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
2887                     f_line = 1;
2888                     fold_state = '\n';/* add one new f_line before this character */
2889                 } else {
2890                     f_line = 1;
2891                     fold_state = '\n';/* add one new f_line before this character */
2892                 }
2893             } else if (c2==0) {
2894                 /* kinsoku point in ASCII */ 
2895                 if (  c1==')'||    /* { [ ( */
2896                      c1==']'||
2897                      c1=='}'||
2898                      c1=='.'||
2899                      c1==','||
2900                      c1=='!'||
2901                      c1=='?'||
2902                      c1=='/'||
2903                      c1==':'||
2904                      c1==';' ) {
2905                     fold_state = 1;
2906                 /* just after special */
2907                 } else if (!is_alnum(prev0)) {
2908                     f_line = char_size(c2,c1);
2909                     fold_state = '\n';
2910                 } else if ((prev0==' ') ||   /* ignored new f_line */
2911                       (prev0=='\n')||        /* ignored new f_line */
2912                       (prev0&0x80)) {        /* X0208 - ASCII */
2913                     f_line = char_size(c2,c1);
2914                     fold_state = '\n';/* add one new f_line before this character */
2915                 } else {
2916                     fold_state = 1;  /* default no fold in ASCII */
2917                 }
2918             } else {
2919                 if (c2=='!') {
2920                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
2921                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
2922                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
2923                     else if (c1=='K')  fold_state = 1; /* \e$B!K\e(B */
2924                     else if (c1=='$')  fold_state = 1; /* \e$B!$\e(B */
2925                     else if (c1=='%')  fold_state = 1; /* \e$B!%\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                          /* default no fold in kinsoku */
2933                     else { 
2934                         fold_state = '\n';
2935                         f_line = char_size(c2,c1);
2936                         /* add one new f_line before this character */
2937                     }
2938                 } else {
2939                     f_line = char_size(c2,c1);
2940                     fold_state = '\n'; 
2941                     /* add one new f_line before this character */
2942                 }
2943             }
2944         }
2945     }
2946     /* terminator process */
2947     switch(fold_state) {
2948         case '\n': 
2949             (*o_fconv)(0,'\n');
2950             (*o_fconv)(c2,c1);
2951             break;
2952         case 0:    
2953             return;
2954         case '\r': 
2955             (*o_fconv)(0,'\n');
2956             break;
2957         case '\t': 
2958         case ' ': 
2959             (*o_fconv)(0,' ');
2960             break;
2961         default:
2962             (*o_fconv)(c2,c1);
2963     }
2964 }
2965
2966 int z_prev2=0,z_prev1=0;
2967
2968 void
2969 z_conv(c2,c1)
2970 int c2,c1;
2971 {
2972
2973     /* if (c2) c1 &= 0x7f; assertion */
2974
2975     if (x0201_f && z_prev2==X0201) {  /* X0201 */
2976         if (c1==(0xde&0x7f)) { /* \e$BByE@\e(B */
2977             z_prev2=0;
2978             (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
2979             return;
2980         } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) {  /* \e$BH>ByE@\e(B */
2981             z_prev2=0;
2982             (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
2983             return;
2984         } else {
2985             z_prev2=0;
2986             (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
2987         }
2988     }
2989
2990     if (c2==EOF) {
2991         (*o_zconv)(c2,c1);
2992         return;
2993     }
2994
2995     if (x0201_f && c2==X0201) {
2996         if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
2997             /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
2998             z_prev1 = c1; z_prev2 = c2;
2999             return;
3000         } else {
3001             (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
3002             return;
3003         }
3004     }
3005
3006     /* JISX0208 Alphabet */
3007     if (alpha_f && c2 == 0x23 ) {
3008         c2 = 0;
3009     } else if (alpha_f && c2 == 0x21 ) { 
3010     /* JISX0208 Kigou */
3011        if (0x21==c1) {
3012            if (alpha_f&0x2) {
3013                c1 = ' ';
3014                c2 = 0;
3015            } else if (alpha_f&0x4) {
3016                 (*o_zconv)(0,' ');
3017                 (*o_zconv)(0,' ');
3018                 return;
3019            } 
3020        } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
3021            c1 = fv[c1-0x20];
3022            c2 =  0;
3023            if (alpha_f&0x8) {
3024                char *entity = 0;
3025                switch (c1){
3026                  case '>': entity = "&gt;"; break;
3027                  case '<': entity = "&lt;"; break;
3028                  case '\"': entity = "&quot;"; break;
3029                  case '&': entity = "&amp;"; break;
3030                }
3031                if (entity){
3032                    while (*entity) (*o_zconv)(0, *entity++);
3033                    return;
3034                }
3035            }
3036        } 
3037     }
3038     (*o_zconv)(c2,c1);
3039 }
3040
3041
3042 #define rot13(c)  ( \
3043       ( c < 'A' ) ? c: \
3044       (c <= 'M')  ? (c + 13): \
3045       (c <= 'Z')  ? (c - 13): \
3046       (c < 'a')   ? (c): \
3047       (c <= 'm')  ? (c + 13): \
3048       (c <= 'z')  ? (c - 13): \
3049       (c) \
3050 )
3051
3052 #define  rot47(c) ( \
3053       ( c < '!' ) ? c: \
3054       ( c <= 'O' ) ? (c + 47) : \
3055       ( c <= '~' ) ?  (c - 47) : \
3056       c \
3057 )
3058
3059 void
3060 rot_conv(c2,c1)
3061 int c2,c1;
3062 {
3063     if (c2==0 || c2==X0201 || c2==ISO8859_1) {
3064         c1 = rot13(c1);
3065     } else if (c2) {
3066         c1 = rot47(c1);
3067         c2 = rot47(c2);
3068     }
3069     (*o_rot_conv)(c2,c1);
3070 }
3071
3072 void
3073 hira_conv(c2,c1)
3074 int c2,c1;
3075 {
3076     if ((hira_f & 1) && c2==0x25 && 0x20<c1 && c1<0x74) {
3077         c2 = 0x24;
3078     } else if ((hira_f & 2) && c2==0x24 && 0x20<c1 && c1<0x74) {
3079         c2 = 0x25;
3080     } 
3081     (*o_hira_conv)(c2,c1);
3082 }
3083
3084
3085 void
3086 iso2022jp_check_conv(c2,c1)
3087 int    c2, c1;
3088 {
3089     static int range[RANGE_NUM_MAX][2] = {
3090         {0x222f, 0x2239,},
3091         {0x2242, 0x2249,},
3092         {0x2251, 0x225b,},
3093         {0x226b, 0x2271,},
3094         {0x227a, 0x227d,},
3095         {0x2321, 0x232f,},
3096         {0x233a, 0x2340,},
3097         {0x235b, 0x2360,},
3098         {0x237b, 0x237e,},
3099         {0x2474, 0x247e,},
3100         {0x2577, 0x257e,},
3101         {0x2639, 0x2640,},
3102         {0x2659, 0x267e,},
3103         {0x2742, 0x2750,},
3104         {0x2772, 0x277e,},
3105         {0x2841, 0x287e,},
3106         {0x4f54, 0x4f7e,},
3107         {0x7425, 0x747e},
3108     };
3109     int i;
3110     int start, end, c;
3111
3112     if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
3113         c2 = GETA1;
3114         c1 = GETA2;
3115     }
3116     if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
3117         c2 = GETA1;
3118         c1 = GETA2;
3119     }
3120
3121     for (i = 0; i < RANGE_NUM_MAX; i++) {
3122         start = range[i][0];
3123         end   = range[i][1];
3124         c     = (c2 << 8) + c1;
3125         if (c >= start && c <= end) {
3126             c2 = GETA1;
3127             c1 = GETA2;
3128         }
3129     }
3130     (*o_iso2022jp_check_conv)(c2,c1);
3131 }
3132
3133
3134 /* This converts  =?ISO-2022-JP?B?HOGE HOGE?= */
3135
3136 unsigned char *mime_pattern[] = {
3137    (unsigned char *)"\075?EUC-JP?B?",
3138    (unsigned char *)"\075?SHIFT_JIS?B?",
3139    (unsigned char *)"\075?ISO-8859-1?Q?",
3140    (unsigned char *)"\075?ISO-8859-1?B?",
3141    (unsigned char *)"\075?ISO-2022-JP?B?",
3142    (unsigned char *)"\075?ISO-2022-JP?Q?",
3143 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3144    (unsigned char *)"\075?UTF-8?B?",
3145 #endif
3146    (unsigned char *)"\075?US-ASCII?Q?",
3147    NULL
3148 };
3149
3150
3151 /* \e$B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u\e(B */
3152 int (*mime_priority_func[])PROTO((int c2, int c1, int c0)) = {
3153     e_iconv, s_iconv, 0, 0, 0, 0,
3154 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3155     w_iconv,
3156 #endif
3157     0,
3158 };
3159
3160 int      mime_encode[] = {
3161     JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
3162 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3163     UTF8,
3164 #endif
3165     ASCII,
3166     0
3167 };
3168
3169 int      mime_encode_method[] = {
3170     'B', 'B','Q', 'B', 'B', 'Q',
3171 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3172     'B',
3173 #endif
3174     'Q',
3175     0
3176 };
3177
3178
3179 #define MAXRECOVER 20
3180
3181 /* I don't trust portablity of toupper */
3182 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
3183 #define nkf_isdigit(c)  ('0'<=c && c<='9')
3184 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
3185
3186 void
3187 switch_mime_getc()
3188 {
3189     if (i_getc!=mime_getc) {
3190         i_mgetc = i_getc; i_getc = mime_getc;
3191         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
3192         if(mime_f==STRICT_MIME) {
3193             i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
3194             i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
3195         }
3196     }
3197 }
3198
3199 void
3200 unswitch_mime_getc()
3201 {
3202     if(mime_f==STRICT_MIME) {
3203         i_mgetc = i_mgetc_buf;
3204         i_mungetc = i_mungetc_buf;
3205     }
3206     i_getc = i_mgetc;
3207     i_ungetc = i_mungetc;
3208 }
3209
3210 int
3211 mime_begin_strict(f)
3212 FILE *f;
3213 {
3214     int c1 = 0;
3215     int i,j,k;
3216     unsigned char *p,*q;
3217     int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */
3218
3219     mime_decode_mode = FALSE;
3220     /* =? has been checked */
3221     j = 0;
3222     p = mime_pattern[j];
3223     r[0]='='; r[1]='?';
3224
3225     for(i=2;p[i]>' ';i++) {                   /* start at =? */
3226         if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
3227             /* pattern fails, try next one */
3228             q = p;
3229             while ((p = mime_pattern[++j])) {
3230                 for(k=2;k<i;k++)              /* assume length(p) > i */
3231                     if (p[k]!=q[k]) break;
3232                 if (k==i && nkf_toupper(c1)==p[k]) break;
3233             }
3234             if (p) continue;  /* found next one, continue */
3235             /* all fails, output from recovery buffer */
3236             (*i_ungetc)(c1,f);
3237             for(j=0;j<i;j++) {
3238                 (*oconv)(0,r[j]);
3239             }
3240             return c1;
3241         }
3242     }
3243     mime_decode_mode = p[i-2];
3244
3245     clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
3246
3247     if (mime_decode_mode=='B') {
3248         mimebuf_f = unbuf_f;
3249         if (!unbuf_f) {
3250             /* do MIME integrity check */
3251             return mime_integrity(f,mime_pattern[j]);
3252         } 
3253     }
3254     switch_mime_getc();
3255     mimebuf_f = TRUE;
3256     return c1;
3257 }
3258
3259 int
3260 mime_getc_buf(f) 
3261 FILE *f;
3262 {
3263     /* we don't keep eof of Fifo, becase it contains ?= as
3264        a terminator. It was checked in mime_integrity. */
3265     return ((mimebuf_f)?
3266         (*i_mgetc_buf)(f):Fifo(mime_input++));
3267 }
3268
3269 int
3270 mime_ungetc_buf(c,f) 
3271 FILE *f;
3272 int c;
3273 {
3274     if (mimebuf_f)
3275         (*i_mungetc_buf)(c,f);
3276     else 
3277         Fifo(--mime_input)=c;
3278     return c;
3279 }
3280
3281 int
3282 mime_begin(f)
3283 FILE *f;
3284 {
3285     int c1;
3286     int i,k;
3287
3288     /* In NONSTRICT mode, only =? is checked. In case of failure, we  */
3289     /* re-read and convert again from mime_buffer.  */
3290
3291     /* =? has been checked */
3292     k = mime_last;
3293     Fifo(mime_last++)='='; Fifo(mime_last++)='?';
3294     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
3295         /* We accept any character type even if it is breaked by new lines */
3296         c1 = (*i_getc)(f); Fifo(mime_last++)= c1 ;
3297         if (c1=='\n'||c1==' '||c1=='\r'||
3298                 c1=='-'||c1=='_'||is_alnum(c1) ) continue;
3299         if (c1=='=') {
3300             /* Failed. But this could be another MIME preemble */
3301             (*i_ungetc)(c1,f);
3302             mime_last--;
3303             break;
3304         }
3305         if (c1!='?') break;
3306         else {
3307             /* c1=='?' */
3308             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3309             if (!(++i<MAXRECOVER) || c1==EOF) break;
3310             if (c1=='b'||c1=='B') {
3311                 mime_decode_mode = 'B';
3312             } else if (c1=='q'||c1=='Q') {
3313                 mime_decode_mode = 'Q';
3314             } else {
3315                 break;
3316             }
3317             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3318             if (!(++i<MAXRECOVER) || c1==EOF) break;
3319             if (c1!='?') {
3320                 mime_decode_mode = FALSE;
3321             }
3322             break;
3323         }
3324     }
3325     switch_mime_getc();
3326     if (!mime_decode_mode) {
3327         /* false MIME premble, restart from mime_buffer */
3328         mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
3329         /* Since we are in MIME mode until buffer becomes empty,    */
3330         /* we never go into mime_begin again for a while.           */
3331         return c1;
3332     }
3333     /* discard mime preemble, and goto MIME mode */
3334     mime_last = k;
3335     /* do no MIME integrity check */
3336     return c1;   /* used only for checking EOF */
3337 }
3338
3339 #ifdef CHECK_OPTION
3340 void
3341 no_putc(c)
3342      int c;
3343 {
3344     ;
3345 }
3346
3347 void debug(str)
3348      char *str;
3349 {
3350     if (debug_f){
3351         fprintf(stderr, "%s\n", str);
3352     }
3353 }
3354 #endif
3355
3356 void
3357 set_input_codename (codename)
3358     char *codename;
3359 {
3360     if (guess_f && 
3361         is_inputcode_set &&
3362         strcmp(codename, "") != 0 && 
3363         strcmp(codename, input_codename) != 0)
3364     {
3365         is_inputcode_mixed = TRUE;
3366     }
3367     input_codename = codename;
3368     is_inputcode_set = TRUE;
3369 }
3370
3371 void
3372 print_guessed_code (filename)
3373     char *filename;
3374 {
3375     char *codename = "BINARY";
3376     if (!is_inputcode_mixed) {
3377         if (strcmp(input_codename, "") == 0) {
3378             codename = "ASCII";
3379         } else {
3380             codename = input_codename;
3381         }
3382     }
3383     if (filename != NULL) printf("%s:", filename);
3384     printf("%s\n", codename);
3385 }
3386
3387 int
3388 hex2bin(x)
3389      int x;
3390 {
3391     if (nkf_isdigit(x)) return x - '0';
3392     return nkf_toupper(x) - 'A' + 10;
3393 }
3394
3395 #ifdef INPUT_OPTION 
3396
3397 #ifdef ANSI_C_PROTOTYPE
3398 int hex_getc(int ch, FILE *f, int (*g)(FILE *f), int (*u)(int c, FILE *f))
3399 #else
3400 int
3401 hex_getc(ch, f, g, u)
3402      int ch;
3403      FILE *f;
3404      int (*g)();
3405      int (*u)();
3406 #endif
3407 {
3408     int c1, c2, c3;
3409     c1 = (*g)(f);
3410     if (c1 != ch){
3411         return c1;
3412     }
3413     c2 = (*g)(f);
3414     if (!nkf_isxdigit(c2)){
3415         (*u)(c2, f);
3416         return c1;
3417     }
3418     c3 = (*g)(f);
3419     if (!nkf_isxdigit(c3)){
3420         (*u)(c2, f);
3421         (*u)(c3, f);
3422         return c1;
3423     }
3424     return (hex2bin(c2) << 4) | hex2bin(c3);
3425 }
3426
3427 int
3428 cap_getc(f)
3429      FILE *f;
3430 {
3431     return hex_getc(':', f, i_cgetc, i_cungetc);
3432 }
3433
3434 int
3435 cap_ungetc(c, f)
3436      int c;
3437      FILE *f;
3438 {
3439     return (*i_cungetc)(c, f);
3440 }
3441
3442 int
3443 url_getc(f)
3444      FILE *f;
3445 {
3446     return hex_getc('%', f, i_ugetc, i_uungetc);
3447 }
3448
3449 int
3450 url_ungetc(c, f)
3451      int c;
3452      FILE *f;
3453 {
3454     return (*i_uungetc)(c, f);
3455 }
3456 #endif
3457
3458 #ifdef NUMCHAR_OPTION
3459 int
3460 numchar_getc(f)
3461      FILE *f;
3462 {
3463     int (*g)() = i_ngetc;
3464     int (*u)() = i_nungetc;
3465     int i = 0, j;
3466     int buf[8];
3467     long c = -1;
3468
3469     buf[i] = (*g)(f);
3470     if (buf[i] == '&'){
3471         buf[++i] = (*g)(f);
3472         if (buf[i] == '#'){
3473             c = 0;
3474             buf[++i] = (*g)(f);
3475             if (buf[i] == 'x' || buf[i] == 'X'){
3476                 for (j = 0; j < 5; j++){
3477                     buf[++i] = (*g)(f);
3478                     if (!nkf_isxdigit(buf[i])){
3479                         if (buf[i] != ';'){
3480                             c = -1;
3481                         }
3482                         break;
3483                     }
3484                     c <<= 4;
3485                     c |= hex2bin(buf[i]);
3486                 }
3487             }else{
3488                 for (j = 0; j < 6; j++){
3489                     if (j){
3490                         buf[++i] = (*g)(f);
3491                     }
3492                     if (!nkf_isdigit(buf[i])){
3493                         if (buf[i] != ';'){
3494                             c = -1;
3495                         }
3496                         break;
3497                     }
3498                     c *= 10;
3499                     c += hex2bin(buf[i]);
3500                 }
3501             }
3502         }
3503     }
3504     if (c != -1){
3505         return CLASS_UTF16 | c;
3506     }
3507     while (i > 0){
3508         (*u)(buf[i], f);
3509         --i;
3510     }
3511     return buf[0];
3512 }
3513
3514 int
3515 numchar_ungetc(c, f)
3516      int c;
3517      FILE *f;
3518 {
3519     return (*i_nungetc)(c, f);
3520 }
3521 #endif
3522
3523
3524 int 
3525 mime_getc(f)
3526 FILE *f;
3527 {
3528     int c1, c2, c3, c4, cc;
3529     int t1, t2, t3, t4, mode, exit_mode;
3530
3531     if (mime_top != mime_last) {  /* Something is in FIFO */
3532         return  Fifo(mime_top++);
3533     }
3534     if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
3535         mime_decode_mode=FALSE;
3536         unswitch_mime_getc();
3537         return (*i_getc)(f);
3538     }
3539
3540     if (mimebuf_f == FIXED_MIME)
3541         exit_mode = mime_decode_mode;
3542     else
3543         exit_mode = FALSE;
3544     if (mime_decode_mode == 'Q') {
3545         if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
3546 restart_mime_q:
3547         if (c1=='_') return ' ';
3548         if (c1!='=' && c1!='?') {
3549             return c1;
3550         }
3551                 
3552         mime_decode_mode = exit_mode; /* prepare for quit */
3553         if (c1<=' ') return c1;
3554         if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
3555         if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
3556             /* end Q encoding */
3557             input_mode = exit_mode;
3558             while((c1=(*i_getc)(f))!=EOF && c1==SPACE 
3559                         /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
3560             return c1;
3561         }
3562         if (c1=='='&&c2<' ') { /* this is soft wrap */
3563             while((c1 =  (*i_mgetc)(f)) <=' ') {
3564                 if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
3565             }
3566             mime_decode_mode = 'Q'; /* still in MIME */
3567             goto restart_mime_q;
3568         }
3569         if (c1=='?') {
3570             mime_decode_mode = 'Q'; /* still in MIME */
3571             (*i_mungetc)(c2,f);
3572             return c1;
3573         }
3574         if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
3575         if (c2<=' ') return c2;
3576         mime_decode_mode = 'Q'; /* still in MIME */
3577 #define hex(c)   (('0'<=c&&c<='9')?(c-'0'):\
3578      ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
3579         return ((hex(c2)<<4) + hex(c3));
3580     }
3581
3582     if (mime_decode_mode != 'B') {
3583         mime_decode_mode = FALSE;
3584         return (*i_mgetc)(f);
3585     }
3586
3587
3588     /* Base64 encoding */
3589     /* 
3590         MIME allows line break in the middle of 
3591         Base64, but we are very pessimistic in decoding
3592         in unbuf mode because MIME encoded code may broken by 
3593         less or editor's control sequence (such as ESC-[-K in unbuffered
3594         mode. ignore incomplete MIME.
3595     */
3596     mode = mime_decode_mode;
3597     mime_decode_mode = exit_mode;  /* prepare for quit */
3598
3599     while ((c1 = (*i_mgetc)(f))<=' ') {
3600         if (c1==EOF)
3601             return (EOF);
3602     }
3603 mime_c2_retry:
3604     if ((c2 = (*i_mgetc)(f))<=' ') {
3605         if (c2==EOF)
3606             return (EOF);
3607         if (mime_f != STRICT_MIME) goto mime_c2_retry;
3608         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3609         return c2;
3610     }
3611     if ((c1 == '?') && (c2 == '=')) {
3612         input_mode = ASCII;
3613         while((c1=(*i_getc)(f))!=EOF && c1==SPACE 
3614                     /* && (c1==NL||c1==TAB||c1=='\r') */ ) ;
3615         return c1;
3616     }
3617 mime_c3_retry:
3618     if ((c3 = (*i_mgetc)(f))<=' ') {
3619         if (c3==EOF)
3620             return (EOF);
3621         if (mime_f != STRICT_MIME) goto mime_c3_retry;
3622         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3623         return c3;
3624     }
3625 mime_c4_retry:
3626     if ((c4 = (*i_mgetc)(f))<=' ') {
3627         if (c4==EOF)
3628             return (EOF);
3629         if (mime_f != STRICT_MIME) goto mime_c4_retry;
3630         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
3631         return c4;
3632     }
3633
3634     mime_decode_mode = mode; /* still in MIME sigh... */
3635
3636     /* BASE 64 decoding */
3637
3638     t1 = 0x3f & base64decode(c1);
3639     t2 = 0x3f & base64decode(c2);
3640     t3 = 0x3f & base64decode(c3);
3641     t4 = 0x3f & base64decode(c4);
3642     cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
3643     if (c2 != '=') {
3644         Fifo(mime_last++) = cc;
3645         cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
3646         if (c3 != '=') {
3647             Fifo(mime_last++) = cc;
3648             cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
3649             if (c4 != '=') 
3650                 Fifo(mime_last++) = cc;
3651         }
3652     } else {
3653         return c1;
3654     }
3655     return  Fifo(mime_top++);
3656 }
3657
3658 int
3659 mime_ungetc(c,f) 
3660 int   c;
3661 FILE  *f;
3662 {
3663     Fifo(--mime_top) = c;
3664     return c;
3665 }
3666
3667 int
3668 mime_integrity(f,p)
3669 FILE *f;
3670 unsigned char *p;
3671 {
3672     int c,d;
3673     unsigned int q;
3674     /* In buffered mode, read until =? or NL or buffer full
3675      */
3676     mime_input = mime_top;
3677     mime_last = mime_top;
3678     while(*p) Fifo(mime_input++) = *p++;
3679     d = 0;
3680     q = mime_input;
3681     while((c=(*i_getc)(f))!=EOF) {
3682         if (((mime_input-mime_top)&MIME_BUF_MASK)==0) {
3683             break;   /* buffer full */
3684         }
3685         if (c=='=' && d=='?') {
3686             /* checked. skip header, start decode */
3687             Fifo(mime_input++) = c;
3688             /* mime_last_input = mime_input; */
3689             mime_input = q; 
3690             switch_mime_getc();
3691             return 1;
3692         }
3693         if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
3694             break;
3695         /* Should we check length mod 4? */
3696         Fifo(mime_input++) = c;
3697         d=c;
3698     }
3699     /* In case of Incomplete MIME, no MIME decode  */
3700     Fifo(mime_input++) = c;
3701     mime_last = mime_input;     /* point undecoded buffer */
3702     mime_decode_mode = 1;              /* no decode on Fifo last in mime_getc */
3703     switch_mime_getc();         /* anyway we need buffered getc */
3704     return 1;
3705 }
3706
3707 int
3708 base64decode(c)
3709     int            c;
3710 {
3711     int             i;
3712     if (c > '@') {
3713         if (c < '[') {
3714             i = c - 'A';                        /* A..Z 0-25 */
3715         } else {
3716             i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
3717         }
3718     } else if (c > '/') {
3719         i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
3720     } else if (c == '+') {
3721         i = '>'             /* 62 */ ;          /* +  62 */
3722     } else {
3723         i = '?'             /* 63 */ ;          /* / 63 */
3724     }
3725     return (i);
3726 }
3727
3728 static char basis_64[] =
3729    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3730
3731 static int b64c;
3732
3733 void
3734 open_mime(mode)
3735 int mode;
3736 {
3737     unsigned char *p;
3738     int i;
3739     p  = mime_pattern[0];
3740     for(i=0;mime_encode[i];i++) {
3741         if (mode == mime_encode[i]) {
3742             p = mime_pattern[i];
3743                 break;
3744         }
3745     }
3746     mimeout_mode = mime_encode_method[i];
3747             
3748     /* (*o_mputc)(' '); */
3749     while(*p) {
3750         (*o_mputc)(*p++);
3751         base64_count ++;
3752     }
3753 }
3754
3755 void
3756 close_mime()
3757 {
3758     (*o_mputc)('?');
3759     (*o_mputc)('=');
3760     (*o_mputc)(' ');
3761     base64_count += 3;
3762     mimeout_mode = 0;
3763 }
3764
3765 #define itoh4(c)   (c>=10?c+'A'-10:c+'0')
3766
3767 void
3768 mime_putc(c)
3769     int            c;
3770 {
3771     if (mimeout_f==FIXED_MIME) {
3772         if (base64_count>71) {
3773             (*o_mputc)('\n');
3774             base64_count=0;
3775         }
3776     } else if (c==NL) {
3777         base64_count=0;
3778     } 
3779     if (c!=EOF) {
3780         if ( c<=DEL &&(output_mode==ASCII ||output_mode == ISO8859_1 )
3781                 && mimeout_f!=FIXED_MIME) {
3782             if (mimeout_mode=='Q') {
3783                 if (c<=SPACE) {
3784                     close_mime();
3785                 }
3786                 (*o_mputc)(c);
3787                 return;
3788             }
3789             if (mimeout_mode!='B' || c!=SPACE) {
3790                 if (mimeout_mode) {
3791                     mime_putc(EOF);
3792                     mimeout_mode=0;
3793                 }
3794                 (*o_mputc)(c);
3795                 base64_count ++;
3796                 return;
3797             }
3798         } else if (!mimeout_mode && mimeout_f!=FIXED_MIME) {
3799             open_mime(output_mode);
3800         }
3801     } else { /* c==EOF */
3802         switch(mimeout_mode) {
3803         case 'Q':
3804         case 'B':
3805             break;
3806         case 2:
3807             (*o_mputc)(basis_64[((b64c & 0x3)<< 4)]);
3808             (*o_mputc)('=');
3809             (*o_mputc)('=');
3810             base64_count += 3;
3811             break;
3812         case 1:
3813             (*o_mputc)(basis_64[((b64c & 0xF) << 2)]);
3814             (*o_mputc)('=');
3815             base64_count += 2;
3816             break;
3817         }
3818         if (mimeout_mode) {
3819             if (mimeout_f!=FIXED_MIME) {
3820                 close_mime(); 
3821             } else if (mimeout_mode != 'Q')
3822                 mimeout_mode = 'B';
3823         }
3824         return;
3825     }
3826     switch(mimeout_mode) {
3827     case 'Q':
3828         if(c>=DEL) {
3829             (*o_mputc)('=');
3830             (*o_mputc)(itoh4(((c>>4)&0xf)));
3831             (*o_mputc)(itoh4((c&0xf)));
3832         } else {
3833             (*o_mputc)(c);
3834         }
3835         break;
3836     case 'B':
3837         b64c=c;
3838         (*o_mputc)(basis_64[c>>2]);
3839         mimeout_mode=2;
3840         base64_count ++;
3841         break;
3842     case 2:
3843         (*o_mputc)(basis_64[((b64c & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
3844         b64c=c;
3845         mimeout_mode=1;
3846         base64_count ++;
3847         break;
3848     case 1:
3849         (*o_mputc)(basis_64[((b64c & 0xF) << 2) | ((c & 0xC0) >>6)]);
3850         (*o_mputc)(basis_64[c & 0x3F]);
3851         mimeout_mode='B';
3852         base64_count += 2;
3853         break;
3854     }
3855 }
3856
3857
3858 #ifdef PERL_XS
3859 void 
3860 reinit()
3861 {
3862     unbuf_f = FALSE;
3863     estab_f = FALSE;
3864     nop_f = FALSE;
3865     binmode_f = TRUE;       
3866     rot_f = FALSE;         
3867     hira_f = FALSE;         
3868     input_f = FALSE;      
3869     alpha_f = FALSE;     
3870     mime_f = STRICT_MIME; 
3871     mimebuf_f = FALSE; 
3872     broken_f = FALSE;  
3873     iso8859_f = FALSE; 
3874 #if defined(MSDOS) || defined(__OS2__) 
3875      x0201_f = TRUE;   
3876 #else
3877      x0201_f = NO_X0201;
3878 #endif
3879     iso2022jp_f = FALSE;
3880
3881     kanji_intro = DEFAULT_J;
3882     ascii_intro = DEFAULT_R;
3883
3884     output_conv = DEFAULT_CONV; 
3885     oconv = DEFAULT_CONV; 
3886
3887     i_mgetc  = std_getc; 
3888     i_mungetc  = std_ungetc;
3889     i_mgetc_buf = std_getc; 
3890     i_mungetc_buf = std_ungetc;
3891
3892     i_getc= std_getc; 
3893     i_ungetc=std_ungetc;
3894
3895     i_bgetc= std_getc;
3896     i_bungetc= std_ungetc;
3897
3898     o_putc = std_putc;
3899     o_mputc = std_putc;
3900     o_crconv = no_connection; 
3901     o_rot_conv = no_connection; 
3902     o_iso2022jp_check_conv = no_connection;
3903     o_hira_conv = no_connection; 
3904     o_fconv = no_connection; 
3905     o_zconv = no_connection;
3906
3907     i_getc = std_getc;
3908     i_ungetc = std_ungetc;
3909     i_mgetc = std_getc; 
3910     i_mungetc = std_ungetc; 
3911
3912     output_mode = ASCII;
3913     input_mode =  ASCII;
3914     shift_mode =  FALSE;
3915     mime_decode_mode =   FALSE;
3916     file_out = FALSE;
3917     mimeout_mode = 0;
3918     mimeout_f = FALSE;
3919     base64_count = 0;
3920     option_mode = 0;
3921     crmode_f = 0;
3922
3923     {
3924         struct input_code *p = input_code_list;
3925         while (p->name){
3926             status_reinit(p++);
3927         }
3928     }
3929 #ifdef UTF8_OUTPUT_ENABLE
3930     if (w_oconv16_begin_f) {
3931         w_oconv16_begin_f = 2;
3932     }
3933 #endif
3934     f_line = 0;    
3935     f_prev = 0;
3936     fold_preserve_f = FALSE; 
3937     fold_f  = FALSE;
3938     fold_len  = 0;
3939     fold_margin  = FOLD_MARGIN;
3940     broken_counter = 0;
3941     broken_last = 0;
3942     z_prev2=0,z_prev1=0;
3943
3944     {
3945         int i;
3946         for (i = 0; i < 256; i++){
3947             prefix_table[i] = 0;
3948         }
3949     }
3950     input_codename = "";
3951     is_inputcode_mixed = FALSE;
3952     is_inputcode_set   = FALSE;
3953 }
3954 #endif
3955
3956 void 
3957 no_connection(c2,c1) 
3958 int c2,c1;
3959 {
3960     no_connection2(c2,c1,0);
3961 }
3962
3963 int
3964 no_connection2(c2,c1,c0) 
3965 int c2,c1,c0;
3966 {
3967     fprintf(stderr,"nkf internal module connection failure.\n");
3968     exit(1);
3969 }
3970
3971 #ifndef PERL_XS
3972 void 
3973 usage()   
3974 {
3975     fprintf(stderr,"USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
3976     fprintf(stderr,"Flags:\n");
3977     fprintf(stderr,"b,u      Output is buffered (DEFAULT),Output is unbuffered\n");
3978 #ifdef DEFAULT_CODE_SJIS
3979     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC), UTF-8\n");
3980 #endif
3981 #ifdef DEFAULT_CODE_JIS
3982     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC), UTF-8\n");
3983 #endif
3984 #ifdef DEFAULT_CODE_EUC
3985     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT), UTF-8\n");
3986 #endif
3987 #ifdef DEFAULT_CODE_UTF8
3988     fprintf(stderr,"j,s,e,w  Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC), UTF-8 (DEFAULT)\n");
3989 #endif
3990     fprintf(stderr,"J,S,E,W  Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC), UTF-8\n");
3991     fprintf(stderr,"t        no conversion\n");
3992     fprintf(stderr,"i_/o_    Output sequence to designate JIS-kanji/ASCII (DEFAULT B)\n");
3993     fprintf(stderr,"r        {de/en}crypt ROT13/47\n");
3994     fprintf(stderr,"h        1 hirakana->katakana, 2 katakana->hirakana,3 both\n");
3995     fprintf(stderr,"v        Show this usage. V: show version\n");
3996     fprintf(stderr,"m[BQN0]  MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
3997     fprintf(stderr,"M[BQ]    MIME encode [B:base64 Q:quoted]\n");
3998     fprintf(stderr,"l        ISO8859-1 (Latin-1) support\n");
3999     fprintf(stderr,"f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
4000     fprintf(stderr,"Z[0-3]   Convert X0208 alphabet to ASCII  1: Kankaku to space,2: 2 spaces,\n");
4001     fprintf(stderr,"                                          3: Convert HTML Entity\n");
4002     fprintf(stderr,"X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
4003     fprintf(stderr,"B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
4004 #ifdef MSDOS
4005     fprintf(stderr,"T        Text mode output\n");
4006 #endif
4007     fprintf(stderr,"O        Output to File (DEFAULT 'nkf.out')\n");
4008     fprintf(stderr,"d,c      Delete \\r in line feed and \\032, Add \\r in line feed\n");
4009     fprintf(stderr,"I        Convert non ISO-2022-JP charactor to GETA\n");
4010     fprintf(stderr,"-L[uwm]  line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
4011     fprintf(stderr,"long name options\n");
4012     fprintf(stderr," --fj,--unix,--mac,--windows                convert for the system\n");
4013     fprintf(stderr," --jis,--euc,--sjis,--utf8,--utf16,--mime,--base64  convert for the code\n");
4014 #ifdef OVERWRITE
4015     fprintf(stderr," --overwrite          Overwrite original listed files by filtered result\n");
4016 #endif
4017     fprintf(stderr," -g, --guess          Guess the input code\n");
4018     fprintf(stderr," --help,--version\n");
4019     version();
4020 }
4021
4022 void
4023 version()
4024 {
4025     fprintf(stderr,"Network Kanji Filter Version %s (%s) "
4026 #if defined(MSDOS) && !defined(__WIN32__) && !defined(__WIN16__)
4027                   "for DOS"
4028 #endif
4029 #if defined(MSDOS) && defined(__WIN16__)
4030                   "for Win16"
4031 #endif
4032 #if defined(MSDOS) && defined(__WIN32__)
4033                   "for Win32"
4034 #endif
4035 #ifdef __OS2__
4036                   "for OS/2"
4037 #endif
4038                   ,Version,Patchlevel);
4039     fprintf(stderr,"\n%s\n",CopyRight);
4040 }
4041 #endif
4042
4043 /**
4044  ** \e$B%Q%C%A@):n<T\e(B
4045  **  void@merope.pleiades.or.jp (Kusakabe Youichi)
4046  **  NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
4047  **  ohta@src.ricoh.co.jp (Junn Ohta)
4048  **  inouet@strl.nhk.or.jp (Tomoyuki Inoue)
4049  **  kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
4050  **  Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
4051  **  a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
4052  **  kono@ie.u-ryukyu.ac.jp (Shinji Kono)
4053  **  GHG00637@nifty-serve.or.jp (COW)
4054  **
4055  **/
4056
4057 /* end */