OSDN Git Service

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