OSDN Git Service

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