OSDN Git Service

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