OSDN Git Service

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