OSDN Git Service

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