OSDN Git Service

8b903c9aa5d23a6be275ba701db3e106f31636a3
[nkf/nkf.git] / nkf.c
1 /*
2  * Copyright (c) 1987, Fujitsu LTD. (Itaru ICHIKAWA).
3  * Copyright (c) 1996-2009, The nkf Project.
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  *
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  * misrepresented as being the original software.
20  *
21  * 3. This notice may not be removed or altered from any source distribution.
22  */
23 #define NKF_VERSION "2.1.0"
24 #define NKF_RELEASE_DATE "2009-11-17"
25 #define COPY_RIGHT \
26     "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).\n" \
27     "Copyright (C) 1996-2009, The nkf Project."
28
29 #include "config.h"
30 #include "nkf.h"
31 #include "utf8tbl.h"
32 #ifdef __WIN32__
33 #include <windows.h>
34 #include <locale.h>
35 #endif
36 #if defined(__OS2__)
37 # define INCL_DOS
38 # define INCL_DOSERRORS
39 # include <os2.h>
40 #endif
41 #include <assert.h>
42
43
44 /* state of output_mode and input_mode
45
46    c2           0 means ASCII
47    JIS_X_0201_1976_K
48    ISO_8859_1
49    JIS_X_0208
50    EOF      all termination
51    c1           32bit data
52
53  */
54
55 /* MIME ENCODE */
56
57 #define         FIXED_MIME      7
58 #define         STRICT_MIME     8
59
60 /* byte order */
61 enum byte_order {
62     ENDIAN_BIG    = 1,
63     ENDIAN_LITTLE = 2,
64     ENDIAN_2143   = 3,
65     ENDIAN_3412   = 4
66 };
67
68 /* ASCII CODE */
69
70 #define         BS      0x08
71 #define         TAB     0x09
72 #define         LF      0x0a
73 #define         CR      0x0d
74 #define         ESC     0x1b
75 #define         SP      0x20
76 #define         DEL     0x7f
77 #define         SI      0x0f
78 #define         SO      0x0e
79 #define         SS2     0x8e
80 #define         SS3     0x8f
81 #define         CRLF    0x0D0A
82
83
84 /* encodings */
85
86 enum nkf_encodings {
87     ASCII,
88     ISO_8859_1,
89     ISO_2022_JP,
90     CP50220,
91     CP50221,
92     CP50222,
93     ISO_2022_JP_1,
94     ISO_2022_JP_3,
95     ISO_2022_JP_2004,
96     SHIFT_JIS,
97     WINDOWS_31J,
98     CP10001,
99     EUC_JP,
100     EUCJP_NKF,
101     CP51932,
102     EUCJP_MS,
103     EUCJP_ASCII,
104     SHIFT_JISX0213,
105     SHIFT_JIS_2004,
106     EUC_JISX0213,
107     EUC_JIS_2004,
108     UTF_8,
109     UTF_8N,
110     UTF_8_BOM,
111     UTF8_MAC,
112     UTF_16,
113     UTF_16BE,
114     UTF_16BE_BOM,
115     UTF_16LE,
116     UTF_16LE_BOM,
117     UTF_32,
118     UTF_32BE,
119     UTF_32BE_BOM,
120     UTF_32LE,
121     UTF_32LE_BOM,
122     BINARY,
123     NKF_ENCODING_TABLE_SIZE,
124     JIS_X_0201_1976_K = 0x1013, /* I */ /* JIS C 6220-1969 */
125     /* JIS_X_0201_1976_R = 0x1014, */ /* J */ /* JIS C 6220-1969 */
126     /* JIS_X_0208_1978   = 0x1040, */ /* @ */ /* JIS C 6226-1978 */
127     /* JIS_X_0208_1983   = 0x1087, */ /* B */ /* JIS C 6226-1983 */
128     JIS_X_0208        = 0x1168, /* @B */
129     JIS_X_0212        = 0x1159, /* D */
130     /* JIS_X_0213_2000_1 = 0x1228, */ /* O */
131     JIS_X_0213_2 = 0x1229, /* P */
132     JIS_X_0213_1 = 0x1233 /* Q */
133 };
134
135 static nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
136 static nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
137 static nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
138 static nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0);
139 static nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0);
140 static void j_oconv(nkf_char c2, nkf_char c1);
141 static void s_oconv(nkf_char c2, nkf_char c1);
142 static void e_oconv(nkf_char c2, nkf_char c1);
143 static void w_oconv(nkf_char c2, nkf_char c1);
144 static void w_oconv16(nkf_char c2, nkf_char c1);
145 static void w_oconv32(nkf_char c2, nkf_char c1);
146
147 typedef struct {
148     const char *name;
149     nkf_char (*iconv)(nkf_char c2, nkf_char c1, nkf_char c0);
150     void (*oconv)(nkf_char c2, nkf_char c1);
151 } nkf_native_encoding;
152
153 nkf_native_encoding NkfEncodingASCII =          { "ASCII", e_iconv, e_oconv };
154 nkf_native_encoding NkfEncodingISO_2022_JP =    { "ISO-2022-JP", e_iconv, j_oconv };
155 nkf_native_encoding NkfEncodingShift_JIS =      { "Shift_JIS", s_iconv, s_oconv };
156 nkf_native_encoding NkfEncodingEUC_JP =         { "EUC-JP", e_iconv, e_oconv };
157 nkf_native_encoding NkfEncodingUTF_8 =          { "UTF-8", w_iconv, w_oconv };
158 nkf_native_encoding NkfEncodingUTF_16 =         { "UTF-16", w_iconv16, w_oconv16 };
159 nkf_native_encoding NkfEncodingUTF_32 =         { "UTF-32", w_iconv32, w_oconv32 };
160
161 typedef struct {
162     const int id;
163     const char *name;
164     const nkf_native_encoding *base_encoding;
165 } nkf_encoding;
166
167 nkf_encoding nkf_encoding_table[] = {
168     {ASCII,             "US-ASCII",             &NkfEncodingASCII},
169     {ISO_8859_1,        "ISO-8859-1",           &NkfEncodingASCII},
170     {ISO_2022_JP,       "ISO-2022-JP",          &NkfEncodingISO_2022_JP},
171     {CP50220,           "CP50220",              &NkfEncodingISO_2022_JP},
172     {CP50221,           "CP50221",              &NkfEncodingISO_2022_JP},
173     {CP50222,           "CP50222",              &NkfEncodingISO_2022_JP},
174     {ISO_2022_JP_1,     "ISO-2022-JP-1",        &NkfEncodingISO_2022_JP},
175     {ISO_2022_JP_3,     "ISO-2022-JP-3",        &NkfEncodingISO_2022_JP},
176     {ISO_2022_JP_2004,  "ISO-2022-JP-2004",     &NkfEncodingISO_2022_JP},
177     {SHIFT_JIS,         "Shift_JIS",            &NkfEncodingShift_JIS},
178     {WINDOWS_31J,       "Windows-31J",          &NkfEncodingShift_JIS},
179     {CP10001,           "CP10001",              &NkfEncodingShift_JIS},
180     {EUC_JP,            "EUC-JP",               &NkfEncodingEUC_JP},
181     {EUCJP_NKF,         "eucJP-nkf",            &NkfEncodingEUC_JP},
182     {CP51932,           "CP51932",              &NkfEncodingEUC_JP},
183     {EUCJP_MS,          "eucJP-MS",             &NkfEncodingEUC_JP},
184     {EUCJP_ASCII,       "eucJP-ASCII",          &NkfEncodingEUC_JP},
185     {SHIFT_JISX0213,    "Shift_JISX0213",       &NkfEncodingShift_JIS},
186     {SHIFT_JIS_2004,    "Shift_JIS-2004",       &NkfEncodingShift_JIS},
187     {EUC_JISX0213,      "EUC-JISX0213",         &NkfEncodingEUC_JP},
188     {EUC_JIS_2004,      "EUC-JIS-2004",         &NkfEncodingEUC_JP},
189     {UTF_8,             "UTF-8",                &NkfEncodingUTF_8},
190     {UTF_8N,            "UTF-8N",               &NkfEncodingUTF_8},
191     {UTF_8_BOM,         "UTF-8-BOM",            &NkfEncodingUTF_8},
192     {UTF8_MAC,          "UTF8-MAC",             &NkfEncodingUTF_8},
193     {UTF_16,            "UTF-16",               &NkfEncodingUTF_16},
194     {UTF_16BE,          "UTF-16BE",             &NkfEncodingUTF_16},
195     {UTF_16BE_BOM,      "UTF-16BE-BOM",         &NkfEncodingUTF_16},
196     {UTF_16LE,          "UTF-16LE",             &NkfEncodingUTF_16},
197     {UTF_16LE_BOM,      "UTF-16LE-BOM",         &NkfEncodingUTF_16},
198     {UTF_32,            "UTF-32",               &NkfEncodingUTF_32},
199     {UTF_32BE,          "UTF-32BE",             &NkfEncodingUTF_32},
200     {UTF_32BE_BOM,      "UTF-32BE-BOM",         &NkfEncodingUTF_32},
201     {UTF_32LE,          "UTF-32LE",             &NkfEncodingUTF_32},
202     {UTF_32LE_BOM,      "UTF-32LE-BOM",         &NkfEncodingUTF_32},
203     {BINARY,            "BINARY",               &NkfEncodingASCII},
204     {-1,                NULL,                   NULL}
205 };
206
207 struct {
208     const char *name;
209     const int id;
210 } encoding_name_to_id_table[] = {
211     {"US-ASCII",                ASCII},
212     {"ASCII",                   ASCII},
213     {"ISO-2022-JP",             ISO_2022_JP},
214     {"ISO2022JP-CP932",         CP50220},
215     {"CP50220",                 CP50220},
216     {"CP50221",                 CP50221},
217     {"CSISO2022JP",             CP50221},
218     {"CP50222",                 CP50222},
219     {"ISO-2022-JP-1",           ISO_2022_JP_1},
220     {"ISO-2022-JP-3",           ISO_2022_JP_3},
221     {"ISO-2022-JP-2004",        ISO_2022_JP_2004},
222     {"SHIFT_JIS",               SHIFT_JIS},
223     {"SJIS",                    SHIFT_JIS},
224     {"WINDOWS-31J",             WINDOWS_31J},
225     {"CSWINDOWS31J",            WINDOWS_31J},
226     {"CP932",                   WINDOWS_31J},
227     {"MS932",                   WINDOWS_31J},
228     {"CP10001",                 CP10001},
229     {"EUCJP",                   EUC_JP},
230     {"EUC-JP",                  EUC_JP},
231     {"EUCJP-NKF",               EUCJP_NKF},
232     {"CP51932",                 CP51932},
233     {"EUC-JP-MS",               EUCJP_MS},
234     {"EUCJP-MS",                EUCJP_MS},
235     {"EUCJPMS",                 EUCJP_MS},
236     {"EUC-JP-ASCII",            EUCJP_ASCII},
237     {"EUCJP-ASCII",             EUCJP_ASCII},
238     {"SHIFT_JISX0213",          SHIFT_JISX0213},
239     {"SHIFT_JIS-2004",          SHIFT_JIS_2004},
240     {"EUC-JISX0213",            EUC_JISX0213},
241     {"EUC-JIS-2004",            EUC_JIS_2004},
242     {"UTF-8",                   UTF_8},
243     {"UTF-8N",                  UTF_8N},
244     {"UTF-8-BOM",               UTF_8_BOM},
245     {"UTF8-MAC",                UTF8_MAC},
246     {"UTF-8-MAC",               UTF8_MAC},
247     {"UTF-16",                  UTF_16},
248     {"UTF-16BE",                UTF_16BE},
249     {"UTF-16BE-BOM",            UTF_16BE_BOM},
250     {"UTF-16LE",                UTF_16LE},
251     {"UTF-16LE-BOM",            UTF_16LE_BOM},
252     {"UTF-32",                  UTF_32},
253     {"UTF-32BE",                UTF_32BE},
254     {"UTF-32BE-BOM",            UTF_32BE_BOM},
255     {"UTF-32LE",                UTF_32LE},
256     {"UTF-32LE-BOM",            UTF_32LE_BOM},
257     {"BINARY",                  BINARY},
258     {NULL,                      -1}
259 };
260
261 #if defined(DEFAULT_CODE_JIS)
262 #define     DEFAULT_ENCIDX ISO_2022_JP
263 #elif defined(DEFAULT_CODE_SJIS)
264 #define     DEFAULT_ENCIDX SHIFT_JIS
265 #elif defined(DEFAULT_CODE_WINDOWS_31J)
266 #define     DEFAULT_ENCIDX WINDOWS_31J
267 #elif defined(DEFAULT_CODE_EUC)
268 #define     DEFAULT_ENCIDX EUC_JP
269 #elif defined(DEFAULT_CODE_UTF8)
270 #define     DEFAULT_ENCIDX UTF_8
271 #endif
272
273
274 #define         is_alnum(c)  \
275     (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
276
277 /* I don't trust portablity of toupper */
278 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
279 #define nkf_isoctal(c)  ('0'<=c && c<='7')
280 #define nkf_isdigit(c)  ('0'<=c && c<='9')
281 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
282 #define nkf_isblank(c) (c == SP || c == TAB)
283 #define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == LF)
284 #define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
285 #define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c))
286 #define nkf_isprint(c) (SP<=c && c<='~')
287 #define nkf_isgraph(c) ('!'<=c && c<='~')
288 #define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \
289                     ('A'<=c&&c<='F') ? (c-'A'+10) : \
290                     ('a'<=c&&c<='f') ? (c-'a'+10) : 0)
291 #define bin2hex(c) ("0123456789ABCDEF"[c&15])
292 #define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3)
293 #define nkf_noescape_mime(c) ((c == CR) || (c == LF) || \
294                               ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \
295                                && (c != '(') && (c != ')') && (c != '.') && (c != 0x22)))
296
297 #define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END)
298 #define nkf_byte_jisx0201_katakana_p(c) (SP <= c && c <= 0x5F)
299
300 #define         HOLD_SIZE       1024
301 #if defined(INT_IS_SHORT)
302 #define         IOBUF_SIZE      2048
303 #else
304 #define         IOBUF_SIZE      16384
305 #endif
306
307 #define         DEFAULT_J       'B'
308 #define         DEFAULT_R       'B'
309
310
311 #define         GETA1   0x22
312 #define         GETA2   0x2e
313
314
315 /* MIME preprocessor */
316
317 #ifdef EASYWIN /*Easy Win */
318 extern POINT _BufferSize;
319 #endif
320
321 struct input_code{
322     const char *name;
323     nkf_char stat;
324     nkf_char score;
325     nkf_char index;
326     nkf_char buf[3];
327     void (*status_func)(struct input_code *, nkf_char);
328     nkf_char (*iconv_func)(nkf_char c2, nkf_char c1, nkf_char c0);
329     int _file_stat;
330 };
331
332 static const char *input_codename = NULL; /* NULL: unestablished, "": BINARY */
333 static nkf_encoding *input_encoding = NULL;
334 static nkf_encoding *output_encoding = NULL;
335
336 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
337 /* UCS Mapping
338  * 0: Shift_JIS, eucJP-ascii
339  * 1: eucJP-ms
340  * 2: CP932, CP51932
341  * 3: CP10001
342  */
343 #define UCS_MAP_ASCII   0
344 #define UCS_MAP_MS      1
345 #define UCS_MAP_CP932   2
346 #define UCS_MAP_CP10001 3
347 static int ms_ucs_map_f = UCS_MAP_ASCII;
348 #endif
349 #ifdef UTF8_INPUT_ENABLE
350 /* no NEC special, NEC-selected IBM extended and IBM extended characters */
351 static  int     no_cp932ext_f = FALSE;
352 /* ignore ZERO WIDTH NO-BREAK SPACE */
353 static  int     no_best_fit_chars_f = FALSE;
354 static  int     input_endian = ENDIAN_BIG;
355 static  nkf_char     unicode_subchar = '?'; /* the regular substitution character */
356 static  void    (*encode_fallback)(nkf_char c) = NULL;
357 static  void    w_status(struct input_code *, nkf_char);
358 #endif
359 #ifdef UTF8_OUTPUT_ENABLE
360 static  int     output_bom_f = FALSE;
361 static  int     output_endian = ENDIAN_BIG;
362 #endif
363
364 static  void    std_putc(nkf_char c);
365 static  nkf_char     std_getc(FILE *f);
366 static  nkf_char     std_ungetc(nkf_char c,FILE *f);
367
368 static  nkf_char     broken_getc(FILE *f);
369 static  nkf_char     broken_ungetc(nkf_char c,FILE *f);
370
371 static  nkf_char     mime_getc(FILE *f);
372
373 static void mime_putc(nkf_char c);
374
375 /* buffers */
376
377 #if !defined(PERL_XS) && !defined(WIN32DLL)
378 static unsigned char   stdibuf[IOBUF_SIZE];
379 static unsigned char   stdobuf[IOBUF_SIZE];
380 #endif
381
382 /* flags */
383 static int             unbuf_f = FALSE;
384 static int             estab_f = FALSE;
385 static int             nop_f = FALSE;
386 static int             binmode_f = TRUE;       /* binary mode */
387 static int             rot_f = FALSE;          /* rot14/43 mode */
388 static int             hira_f = FALSE;          /* hira/kata henkan */
389 static int             alpha_f = FALSE;        /* convert JIx0208 alphbet to ASCII */
390 static int             mime_f = MIME_DECODE_DEFAULT;   /* convert MIME B base64 or Q */
391 static int             mime_decode_f = FALSE;  /* mime decode is explicitly on */
392 static int             mimebuf_f = FALSE;      /* MIME buffered input */
393 static int             broken_f = FALSE;       /* convert ESC-less broken JIS */
394 static int             iso8859_f = FALSE;      /* ISO8859 through */
395 static int             mimeout_f = FALSE;       /* base64 mode */
396 static int             x0201_f = X0201_DEFAULT; /* convert JIS X 0201 */
397 static int             iso2022jp_f = FALSE;    /* replace non ISO-2022-JP with GETA */
398
399 #ifdef UNICODE_NORMALIZATION
400 static int nfc_f = FALSE;
401 static nkf_char (*i_nfc_getc)(FILE *) = std_getc; /* input of ugetc */
402 static nkf_char (*i_nfc_ungetc)(nkf_char c ,FILE *f) = std_ungetc;
403 #endif
404
405 #ifdef INPUT_OPTION
406 static int cap_f = FALSE;
407 static nkf_char (*i_cgetc)(FILE *) = std_getc; /* input of cgetc */
408 static nkf_char (*i_cungetc)(nkf_char c ,FILE *f) = std_ungetc;
409
410 static int url_f = FALSE;
411 static nkf_char (*i_ugetc)(FILE *) = std_getc; /* input of ugetc */
412 static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc;
413 #endif
414
415 #define PREFIX_EUCG3    NKF_INT32_C(0x8F00)
416 #define CLASS_MASK      NKF_INT32_C(0xFF000000)
417 #define CLASS_UNICODE   NKF_INT32_C(0x01000000)
418 #define VALUE_MASK      NKF_INT32_C(0x00FFFFFF)
419 #define UNICODE_BMP_MAX NKF_INT32_C(0x0000FFFF)
420 #define UNICODE_MAX     NKF_INT32_C(0x0010FFFF)
421 #define nkf_char_euc3_new(c) ((c) | PREFIX_EUCG3)
422 #define nkf_char_unicode_new(c) ((c) | CLASS_UNICODE)
423 #define nkf_char_unicode_p(c) ((c & CLASS_MASK) == CLASS_UNICODE)
424 #define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= UNICODE_BMP_MAX)
425 #define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= UNICODE_MAX)
426
427 #ifdef NUMCHAR_OPTION
428 static int numchar_f = FALSE;
429 static nkf_char (*i_ngetc)(FILE *) = std_getc; /* input of ugetc */
430 static nkf_char (*i_nungetc)(nkf_char c ,FILE *f) = std_ungetc;
431 #endif
432
433 #ifdef CHECK_OPTION
434 static int noout_f = FALSE;
435 static void no_putc(nkf_char c);
436 static int debug_f = FALSE;
437 static void debug(const char *str);
438 static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0;
439 #endif
440
441 static int guess_f = 0; /* 0: OFF, 1: ON, 2: VERBOSE */
442 static  void    set_input_codename(const char *codename);
443
444 #ifdef EXEC_IO
445 static int exec_f = 0;
446 #endif
447
448 #ifdef SHIFTJIS_CP932
449 /* invert IBM extended characters to others */
450 static int cp51932_f = FALSE;
451
452 /* invert NEC-selected IBM extended characters to IBM extended characters */
453 static int cp932inv_f = TRUE;
454
455 /* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */
456 #endif /* SHIFTJIS_CP932 */
457
458 static int x0212_f = FALSE;
459 static int x0213_f = FALSE;
460
461 static unsigned char prefix_table[256];
462
463 static void e_status(struct input_code *, nkf_char);
464 static void s_status(struct input_code *, nkf_char);
465
466 struct input_code input_code_list[] = {
467     {"EUC-JP",    0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
468     {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
469 #ifdef UTF8_INPUT_ENABLE
470     {"UTF-8",     0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
471     {"UTF-16",     0, 0, 0, {0, 0, 0}, NULL, w_iconv16, 0},
472     {"UTF-32",     0, 0, 0, {0, 0, 0}, NULL, w_iconv32, 0},
473 #endif
474     {0}
475 };
476
477 static int              mimeout_mode = 0; /* 0, -1, 'Q', 'B', 1, 2 */
478 static int              base64_count = 0;
479
480 /* X0208 -> ASCII converter */
481
482 /* fold parameter */
483 static int             f_line = 0;    /* chars in line */
484 static int             f_prev = 0;
485 static int             fold_preserve_f = FALSE; /* preserve new lines */
486 static int             fold_f  = FALSE;
487 static int             fold_len  = 0;
488
489 /* options */
490 static unsigned char   kanji_intro = DEFAULT_J;
491 static unsigned char   ascii_intro = DEFAULT_R;
492
493 /* Folding */
494
495 #define FOLD_MARGIN  10
496 #define DEFAULT_FOLD 60
497
498 static int             fold_margin  = FOLD_MARGIN;
499
500 /* process default */
501
502 static nkf_char
503 no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
504 {
505     fprintf(stderr,"nkf internal module connection failure.\n");
506     exit(EXIT_FAILURE);
507     return 0; /* LINT */
508 }
509
510 static void
511 no_connection(nkf_char c2, nkf_char c1)
512 {
513     no_connection2(c2,c1,0);
514 }
515
516 static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2;
517 static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection;
518
519 static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection;
520 static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection;
521 static void (*o_eol_conv)(nkf_char c2,nkf_char c1) = no_connection;
522 static void (*o_rot_conv)(nkf_char c2,nkf_char c1) = no_connection;
523 static void (*o_hira_conv)(nkf_char c2,nkf_char c1) = no_connection;
524 static void (*o_base64conv)(nkf_char c2,nkf_char c1) = no_connection;
525 static void (*o_iso2022jp_check_conv)(nkf_char c2,nkf_char c1) = no_connection;
526
527 /* static redirections */
528
529 static  void   (*o_putc)(nkf_char c) = std_putc;
530
531 static  nkf_char    (*i_getc)(FILE *f) = std_getc; /* general input */
532 static  nkf_char    (*i_ungetc)(nkf_char c,FILE *f) =std_ungetc;
533
534 static  nkf_char    (*i_bgetc)(FILE *) = std_getc; /* input of mgetc */
535 static  nkf_char    (*i_bungetc)(nkf_char c ,FILE *f) = std_ungetc;
536
537 static  void   (*o_mputc)(nkf_char c) = std_putc ; /* output of mputc */
538
539 static  nkf_char    (*i_mgetc)(FILE *) = std_getc; /* input of mgetc */
540 static  nkf_char    (*i_mungetc)(nkf_char c ,FILE *f) = std_ungetc;
541
542 /* for strict mime */
543 static  nkf_char    (*i_mgetc_buf)(FILE *) = std_getc; /* input of mgetc_buf */
544 static  nkf_char    (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc;
545
546 /* Global states */
547 static int output_mode = ASCII;    /* output kanji mode */
548 static int input_mode =  ASCII;    /* input kanji mode */
549 static int mime_decode_mode =   FALSE;    /* MIME mode B base64, Q hex */
550
551 /* X0201 / X0208 conversion tables */
552
553 /* X0201 kana conversion table */
554 /* 90-9F A0-DF */
555 static const unsigned char cv[]= {
556     0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
557     0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
558     0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
559     0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
560     0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
561     0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
562     0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
563     0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
564     0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
565     0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
566     0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
567     0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
568     0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
569     0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
570     0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
571     0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
572     0x00,0x00};
573
574
575 /* X0201 kana conversion table for daguten */
576 /* 90-9F A0-DF */
577 static const unsigned char dv[]= {
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,0x00,0x00,0x00,0x00,0x00,0x00,
582     0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74,
583     0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
584     0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
585     0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
586     0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
587     0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
588     0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
589     0x25,0x56,0x25,0x59,0x25,0x5c,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};
595
596 /* X0201 kana conversion table for han-daguten */
597 /* 90-9F A0-DF */
598 static const unsigned char ev[]= {
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,0x00,0x00,0x00,0x00,0x00,0x00,
603     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
604     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
605     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
606     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
607     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
608     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
609     0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
610     0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
611     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
612     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
613     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
614     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
615     0x00,0x00};
616
617
618 /* X0208 kigou conversion table */
619 /* 0x8140 - 0x819e */
620 static const unsigned char fv[] = {
621
622     0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
623     0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
624     0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
625     0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
626     0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
627     0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
628     0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
629     0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
630     0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
631     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
632     0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
633     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
634 } ;
635
636
637
638 static int option_mode = 0;
639 static int             file_out_f = FALSE;
640 #ifdef OVERWRITE
641 static int             overwrite_f = FALSE;
642 static int             preserve_time_f = FALSE;
643 static int             backup_f = FALSE;
644 static char            *backup_suffix = "";
645 #endif
646
647 static int eolmode_f = 0;   /* CR, LF, CRLF */
648 static int input_eol = 0; /* 0: unestablished, EOF: MIXED */
649 static nkf_char prev_cr = 0; /* CR or 0 */
650 #ifdef EASYWIN /*Easy Win */
651 static int             end_check;
652 #endif /*Easy Win */
653
654 static void *
655 nkf_xmalloc(size_t size)
656 {
657     void *ptr;
658
659     if (size == 0) size = 1;
660
661     ptr = malloc(size);
662     if (ptr == NULL) {
663         perror("can't malloc");
664         exit(EXIT_FAILURE);
665     }
666
667     return ptr;
668 }
669
670 static void *
671 nkf_xrealloc(void *ptr, size_t size)
672 {
673     if (size == 0) size = 1;
674
675     ptr = realloc(ptr, size);
676     if (ptr == NULL) {
677         perror("can't realloc");
678         exit(EXIT_FAILURE);
679     }
680
681     return ptr;
682 }
683
684 #define nkf_xfree(ptr) free(ptr)
685
686 static int
687 nkf_str_caseeql(const char *src, const char *target)
688 {
689     int i;
690     for (i = 0; src[i] && target[i]; i++) {
691         if (nkf_toupper(src[i]) != nkf_toupper(target[i])) return FALSE;
692     }
693     if (src[i] || target[i]) return FALSE;
694     else return TRUE;
695 }
696
697 static nkf_encoding*
698 nkf_enc_from_index(int idx)
699 {
700     if (idx < 0 || NKF_ENCODING_TABLE_SIZE <= idx) {
701         return 0;
702     }
703     return &nkf_encoding_table[idx];
704 }
705
706 static int
707 nkf_enc_find_index(const char *name)
708 {
709     int i;
710     if (name[0] == 'X' && *(name+1) == '-') name += 2;
711     for (i = 0; encoding_name_to_id_table[i].id >= 0; i++) {
712         if (nkf_str_caseeql(encoding_name_to_id_table[i].name, name)) {
713             return encoding_name_to_id_table[i].id;
714         }
715     }
716     return -1;
717 }
718
719 static nkf_encoding*
720 nkf_enc_find(const char *name)
721 {
722     int idx = -1;
723     idx = nkf_enc_find_index(name);
724     if (idx < 0) return 0;
725     return nkf_enc_from_index(idx);
726 }
727
728 #define nkf_enc_name(enc) (enc)->name
729 #define nkf_enc_to_index(enc) (enc)->id
730 #define nkf_enc_to_base_encoding(enc) (enc)->base_encoding
731 #define nkf_enc_to_iconv(enc) nkf_enc_to_base_encoding(enc)->iconv
732 #define nkf_enc_to_oconv(enc) nkf_enc_to_base_encoding(enc)->oconv
733 #define nkf_enc_asciicompat(enc) (\
734                                   nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\
735                                   nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP)
736 #define nkf_enc_unicode_p(enc) (\
737                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\
738                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\
739                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32)
740 #define nkf_enc_cp5022x_p(enc) (\
741                                 nkf_enc_to_index(enc) == CP50220 ||\
742                                 nkf_enc_to_index(enc) == CP50221 ||\
743                                 nkf_enc_to_index(enc) == CP50222)
744
745 #ifdef DEFAULT_CODE_LOCALE
746 static const char*
747 nkf_locale_charmap()
748 {
749 #ifdef HAVE_LANGINFO_H
750     return nl_langinfo(CODESET);
751 #elif defined(__WIN32__)
752     static char buf[16];
753     sprintf(buf, "CP%d", GetACP());
754     return buf;
755 #elif defined(__OS2__)
756 # if defined(INT_IS_SHORT)
757     /* OS/2 1.x */
758     return NULL;
759 # else
760     /* OS/2 32bit */
761     static char buf[16];
762     ULONG ulCP[1], ulncp;
763     DosQueryCp(sizeof(ulCP), ulCP, &ulncp);
764     if (ulCP[0] == 932 || ulCP[0] == 943)
765         strcpy(buf, "Shift_JIS");
766     else
767         sprintf(buf, "CP%lu", ulCP[0]);
768     return buf;
769 # endif
770 #endif
771     return NULL;
772 }
773
774 static nkf_encoding*
775 nkf_locale_encoding()
776 {
777     nkf_encoding *enc = 0;
778     const char *encname = nkf_locale_charmap();
779     if (encname)
780         enc = nkf_enc_find(encname);
781     return enc;
782 }
783 #endif /* DEFAULT_CODE_LOCALE */
784
785 static nkf_encoding*
786 nkf_utf8_encoding()
787 {
788     return &nkf_encoding_table[UTF_8];
789 }
790
791 static nkf_encoding*
792 nkf_default_encoding()
793 {
794     nkf_encoding *enc = 0;
795 #ifdef DEFAULT_CODE_LOCALE
796     enc = nkf_locale_encoding();
797 #elif defined(DEFAULT_ENCIDX)
798     enc = nkf_enc_from_index(DEFAULT_ENCIDX);
799 #endif
800     if (!enc) enc = nkf_utf8_encoding();
801     return enc;
802 }
803
804 typedef struct {
805     long capa;
806     long len;
807     nkf_char *ptr;
808 } nkf_buf_t;
809
810 static nkf_buf_t *
811 nkf_buf_new(int length)
812 {
813     nkf_buf_t *buf = nkf_xmalloc(sizeof(nkf_buf_t));
814     buf->ptr = nkf_xmalloc(length);
815     buf->capa = length;
816     buf->len = 0;
817     return buf;
818
819
820 #if 0
821 static void
822 nkf_buf_dispose(nkf_buf_t *buf)
823 {
824     nkf_xfree(buf->ptr);
825     nkf_xfree(buf);
826 }
827 #endif
828
829 #define nkf_buf_length(buf) ((buf)->len)
830 #define nkf_buf_empty_p(buf) ((buf)->len == 0)
831
832 static unsigned char
833 nkf_buf_at(nkf_buf_t *buf, int index)
834 {
835     assert(index <= buf->len);
836     return buf->ptr[index];
837 }
838
839 static void
840 nkf_buf_clear(nkf_buf_t *buf)
841 {
842     buf->len = 0;
843 }
844
845 static void
846 nkf_buf_push(nkf_buf_t *buf, nkf_char c)
847 {
848     if (buf->capa <= buf->len) {
849         exit(EXIT_FAILURE);
850     }
851     buf->ptr[buf->len++] = c;
852 }
853
854 static unsigned char
855 nkf_buf_pop(nkf_buf_t *buf)
856 {
857     assert(!nkf_buf_empty_p(buf));
858     return buf->ptr[--buf->len];
859 }
860
861 /* Normalization Form C */
862 #ifndef PERL_XS
863 #ifdef WIN32DLL
864 #define fprintf dllprintf
865 #endif
866
867 static void
868 version(void)
869 {
870     fprintf(HELP_OUTPUT,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n");
871 }
872
873 static void
874 usage(void)
875 {
876     fprintf(HELP_OUTPUT,
877             "Usage:  nkf -[flags] [--] [in file] .. [out file for -O flag]\n"
878 #ifdef UTF8_OUTPUT_ENABLE
879             " j/s/e/w  Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
880             "          UTF options is -w[8[0],{16,32}[{B,L}[0]]]\n"
881 #else
882 #endif
883 #ifdef UTF8_INPUT_ENABLE
884             " J/S/E/W  Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
885             "          UTF option is -W[8,[16,32][B,L]]\n"
886 #else
887             " J/S/E    Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
888 #endif
889             );
890     fprintf(HELP_OUTPUT,
891             " m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:nonstrict,0:no decode]\n"
892             " M[BQ]    MIME encode [B:base64 Q:quoted]\n"
893             " f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n"
894             );
895     fprintf(HELP_OUTPUT,
896             " Z[0-4]   Default/0: Convert JISX0208 Alphabet to ASCII\n"
897             "          1: Kankaku to one space  2: to two spaces  3: HTML Entity\n"
898             "          4: JISX0208 Katakana to JISX0201 Katakana\n"
899             " X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n"
900             );
901     fprintf(HELP_OUTPUT,
902             " O        Output to File (DEFAULT 'nkf.out')\n"
903             " L[uwm]   Line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n"
904             );
905     fprintf(HELP_OUTPUT,
906             " --ic=<encoding>        Specify the input encoding\n"
907             " --oc=<encoding>        Specify the output encoding\n"
908             " --hiragana --katakana  Hiragana/Katakana Conversion\n"
909             " --katakana-hiragana    Converts each other\n"
910             );
911     fprintf(HELP_OUTPUT,
912 #ifdef INPUT_OPTION
913             " --{cap, url}-input     Convert hex after ':' or '%%'\n"
914 #endif
915 #ifdef NUMCHAR_OPTION
916             " --numchar-input        Convert Unicode Character Reference\n"
917 #endif
918 #ifdef UTF8_INPUT_ENABLE
919             " --fb-{skip, html, xml, perl, java, subchar}\n"
920             "                        Specify unassigned character's replacement\n"
921 #endif
922             );
923     fprintf(HELP_OUTPUT,
924 #ifdef OVERWRITE
925             " --in-place[=SUF]       Overwrite original files\n"
926             " --overwrite[=SUF]      Preserve timestamp of original files\n"
927 #endif
928             " -g --guess             Guess the input code\n"
929             " -v --version           Print the version\n"
930             " --help/-V              Print this help / configuration\n"
931             );
932     version();
933 }
934
935 static void
936 show_configuration(void)
937 {
938     fprintf(HELP_OUTPUT,
939             "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n"
940             "  Compile-time options:\n"
941             "    Compiled at:                 " __DATE__ " " __TIME__ "\n"
942            );
943     fprintf(HELP_OUTPUT,
944             "    Default output encoding:     "
945 #ifdef DEFAULT_CODE_LOCALE
946             "LOCALE (%s)\n", nkf_enc_name(nkf_default_encoding())
947 #elif defined(DEFAULT_ENCIDX)
948             "CONFIG (%s)\n", nkf_enc_name(nkf_default_encoding())
949 #else
950             "NONE\n"
951 #endif
952            );
953     fprintf(HELP_OUTPUT,
954             "    Default output end of line:  "
955 #if DEFAULT_NEWLINE == CR
956             "CR"
957 #elif DEFAULT_NEWLINE == CRLF
958             "CRLF"
959 #else
960             "LF"
961 #endif
962             "\n"
963             "    Decode MIME encoded string:  "
964 #if MIME_DECODE_DEFAULT
965             "ON"
966 #else
967             "OFF"
968 #endif
969             "\n"
970             "    Convert JIS X 0201 Katakana: "
971 #if X0201_DEFAULT
972             "ON"
973 #else
974             "OFF"
975 #endif
976             "\n"
977             "    --help, --version output:    "
978 #if HELP_OUTPUT_HELP_OUTPUT
979             "HELP_OUTPUT"
980 #else
981             "STDOUT"
982 #endif
983             "\n");
984 }
985 #endif /*PERL_XS*/
986
987 #ifdef OVERWRITE
988 static char*
989 get_backup_filename(const char *suffix, const char *filename)
990 {
991     char *backup_filename;
992     int asterisk_count = 0;
993     int i, j;
994     int filename_length = strlen(filename);
995
996     for(i = 0; suffix[i]; i++){
997         if(suffix[i] == '*') asterisk_count++;
998     }
999
1000     if(asterisk_count){
1001         backup_filename = nkf_xmalloc(strlen(suffix) + (asterisk_count * (filename_length - 1)) + 1);
1002         for(i = 0, j = 0; suffix[i];){
1003             if(suffix[i] == '*'){
1004                 backup_filename[j] = '\0';
1005                 strncat(backup_filename, filename, filename_length);
1006                 i++;
1007                 j += filename_length;
1008             }else{
1009                 backup_filename[j++] = suffix[i++];
1010             }
1011         }
1012         backup_filename[j] = '\0';
1013     }else{
1014         j = filename_length + strlen(suffix);
1015         backup_filename = nkf_xmalloc(j + 1);
1016         strcpy(backup_filename, filename);
1017         strcat(backup_filename, suffix);
1018         backup_filename[j] = '\0';
1019     }
1020     return backup_filename;
1021 }
1022 #endif
1023
1024 #ifdef UTF8_INPUT_ENABLE
1025 static void
1026 nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
1027 {
1028     int shift = 20;
1029     c &= VALUE_MASK;
1030     while(shift >= 0){
1031         if(c >= 1<<shift){
1032             while(shift >= 0){
1033                 (*f)(0, bin2hex(c>>shift));
1034                 shift -= 4;
1035             }
1036         }else{
1037             shift -= 4;
1038         }
1039     }
1040     return;
1041 }
1042
1043 static void
1044 encode_fallback_html(nkf_char c)
1045 {
1046     (*oconv)(0, '&');
1047     (*oconv)(0, '#');
1048     c &= VALUE_MASK;
1049     if(c >= NKF_INT32_C(1000000))
1050         (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10);
1051     if(c >= NKF_INT32_C(100000))
1052         (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10);
1053     if(c >= 10000)
1054         (*oconv)(0, 0x30+(c/10000  )%10);
1055     if(c >= 1000)
1056         (*oconv)(0, 0x30+(c/1000   )%10);
1057     if(c >= 100)
1058         (*oconv)(0, 0x30+(c/100    )%10);
1059     if(c >= 10)
1060         (*oconv)(0, 0x30+(c/10     )%10);
1061     if(c >= 0)
1062         (*oconv)(0, 0x30+ c         %10);
1063     (*oconv)(0, ';');
1064     return;
1065 }
1066
1067 static void
1068 encode_fallback_xml(nkf_char c)
1069 {
1070     (*oconv)(0, '&');
1071     (*oconv)(0, '#');
1072     (*oconv)(0, 'x');
1073     nkf_each_char_to_hex(oconv, c);
1074     (*oconv)(0, ';');
1075     return;
1076 }
1077
1078 static void
1079 encode_fallback_java(nkf_char c)
1080 {
1081     (*oconv)(0, '\\');
1082     c &= VALUE_MASK;
1083     if(!nkf_char_unicode_bmp_p(c)){
1084         (*oconv)(0, 'U');
1085         (*oconv)(0, '0');
1086         (*oconv)(0, '0');
1087         (*oconv)(0, bin2hex(c>>20));
1088         (*oconv)(0, bin2hex(c>>16));
1089     }else{
1090         (*oconv)(0, 'u');
1091     }
1092     (*oconv)(0, bin2hex(c>>12));
1093     (*oconv)(0, bin2hex(c>> 8));
1094     (*oconv)(0, bin2hex(c>> 4));
1095     (*oconv)(0, bin2hex(c    ));
1096     return;
1097 }
1098
1099 static void
1100 encode_fallback_perl(nkf_char c)
1101 {
1102     (*oconv)(0, '\\');
1103     (*oconv)(0, 'x');
1104     (*oconv)(0, '{');
1105     nkf_each_char_to_hex(oconv, c);
1106     (*oconv)(0, '}');
1107     return;
1108 }
1109
1110 static void
1111 encode_fallback_subchar(nkf_char c)
1112 {
1113     c = unicode_subchar;
1114     (*oconv)((c>>8)&0xFF, c&0xFF);
1115     return;
1116 }
1117 #endif
1118
1119 static const struct {
1120     const char *name;
1121     const char *alias;
1122 } long_option[] = {
1123     {"ic=", ""},
1124     {"oc=", ""},
1125     {"base64","jMB"},
1126     {"euc","e"},
1127     {"euc-input","E"},
1128     {"fj","jm"},
1129     {"help",""},
1130     {"jis","j"},
1131     {"jis-input","J"},
1132     {"mac","sLm"},
1133     {"mime","jM"},
1134     {"mime-input","m"},
1135     {"msdos","sLw"},
1136     {"sjis","s"},
1137     {"sjis-input","S"},
1138     {"unix","eLu"},
1139     {"version","v"},
1140     {"windows","sLw"},
1141     {"hiragana","h1"},
1142     {"katakana","h2"},
1143     {"katakana-hiragana","h3"},
1144     {"guess=", ""},
1145     {"guess", "g2"},
1146     {"cp932", ""},
1147     {"no-cp932", ""},
1148 #ifdef X0212_ENABLE
1149     {"x0212", ""},
1150 #endif
1151 #ifdef UTF8_OUTPUT_ENABLE
1152     {"utf8", "w"},
1153     {"utf16", "w16"},
1154     {"ms-ucs-map", ""},
1155     {"fb-skip", ""},
1156     {"fb-html", ""},
1157     {"fb-xml", ""},
1158     {"fb-perl", ""},
1159     {"fb-java", ""},
1160     {"fb-subchar", ""},
1161     {"fb-subchar=", ""},
1162 #endif
1163 #ifdef UTF8_INPUT_ENABLE
1164     {"utf8-input", "W"},
1165     {"utf16-input", "W16"},
1166     {"no-cp932ext", ""},
1167     {"no-best-fit-chars",""},
1168 #endif
1169 #ifdef UNICODE_NORMALIZATION
1170     {"utf8mac-input", ""},
1171 #endif
1172 #ifdef OVERWRITE
1173     {"overwrite", ""},
1174     {"overwrite=", ""},
1175     {"in-place", ""},
1176     {"in-place=", ""},
1177 #endif
1178 #ifdef INPUT_OPTION
1179     {"cap-input", ""},
1180     {"url-input", ""},
1181 #endif
1182 #ifdef NUMCHAR_OPTION
1183     {"numchar-input", ""},
1184 #endif
1185 #ifdef CHECK_OPTION
1186     {"no-output", ""},
1187     {"debug", ""},
1188 #endif
1189 #ifdef SHIFTJIS_CP932
1190     {"cp932inv", ""},
1191 #endif
1192 #ifdef EXEC_IO
1193     {"exec-in", ""},
1194     {"exec-out", ""},
1195 #endif
1196     {"prefix=", ""},
1197 };
1198
1199 static void
1200 set_input_encoding(nkf_encoding *enc)
1201 {
1202     switch (nkf_enc_to_index(enc)) {
1203     case ISO_8859_1:
1204         iso8859_f = TRUE;
1205         break;
1206     case CP50220:
1207     case CP50221:
1208     case CP50222:
1209         x0201_f = TRUE;
1210 #ifdef SHIFTJIS_CP932
1211         cp51932_f = TRUE;
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         x0212_f = TRUE;
1219         break;
1220     case ISO_2022_JP_3:
1221         x0212_f = TRUE;
1222         x0213_f = TRUE;
1223         break;
1224     case ISO_2022_JP_2004:
1225         x0212_f = TRUE;
1226         x0213_f = TRUE;
1227         break;
1228     case SHIFT_JIS:
1229         break;
1230     case WINDOWS_31J:
1231         x0201_f = TRUE;
1232 #ifdef SHIFTJIS_CP932
1233         cp51932_f = TRUE;
1234 #endif
1235 #ifdef UTF8_OUTPUT_ENABLE
1236         ms_ucs_map_f = UCS_MAP_CP932;
1237 #endif
1238         break;
1239         break;
1240     case CP10001:
1241 #ifdef SHIFTJIS_CP932
1242         cp51932_f = TRUE;
1243 #endif
1244 #ifdef UTF8_OUTPUT_ENABLE
1245         ms_ucs_map_f = UCS_MAP_CP10001;
1246 #endif
1247         break;
1248     case EUC_JP:
1249         break;
1250     case EUCJP_NKF:
1251         break;
1252     case CP51932:
1253         x0201_f = TRUE;
1254 #ifdef SHIFTJIS_CP932
1255         cp51932_f = TRUE;
1256 #endif
1257 #ifdef UTF8_OUTPUT_ENABLE
1258         ms_ucs_map_f = UCS_MAP_CP932;
1259 #endif
1260         break;
1261     case EUCJP_MS:
1262 #ifdef SHIFTJIS_CP932
1263         cp51932_f = FALSE;
1264 #endif
1265 #ifdef UTF8_OUTPUT_ENABLE
1266         ms_ucs_map_f = UCS_MAP_MS;
1267 #endif
1268         break;
1269     case EUCJP_ASCII:
1270 #ifdef SHIFTJIS_CP932
1271         cp51932_f = FALSE;
1272 #endif
1273 #ifdef UTF8_OUTPUT_ENABLE
1274         ms_ucs_map_f = UCS_MAP_ASCII;
1275 #endif
1276         break;
1277     case SHIFT_JISX0213:
1278     case SHIFT_JIS_2004:
1279         x0213_f = TRUE;
1280 #ifdef SHIFTJIS_CP932
1281         cp51932_f = FALSE;
1282 #endif
1283         break;
1284     case EUC_JISX0213:
1285     case EUC_JIS_2004:
1286         x0213_f = TRUE;
1287 #ifdef SHIFTJIS_CP932
1288         cp51932_f = FALSE;
1289 #endif
1290         break;
1291 #ifdef UTF8_INPUT_ENABLE
1292 #ifdef UNICODE_NORMALIZATION
1293     case UTF8_MAC:
1294         nfc_f = TRUE;
1295         break;
1296 #endif
1297     case UTF_16:
1298     case UTF_16BE:
1299     case UTF_16BE_BOM:
1300         input_endian = ENDIAN_BIG;
1301         break;
1302     case UTF_16LE:
1303     case UTF_16LE_BOM:
1304         input_endian = ENDIAN_LITTLE;
1305         break;
1306     case UTF_32:
1307     case UTF_32BE:
1308     case UTF_32BE_BOM:
1309         input_endian = ENDIAN_BIG;
1310         break;
1311     case UTF_32LE:
1312     case UTF_32LE_BOM:
1313         input_endian = ENDIAN_LITTLE;
1314         break;
1315 #endif
1316     }
1317 }
1318
1319 static void
1320 set_output_encoding(nkf_encoding *enc)
1321 {
1322     switch (nkf_enc_to_index(enc)) {
1323     case CP50220:
1324         x0201_f = TRUE;
1325 #ifdef SHIFTJIS_CP932
1326         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1327 #endif
1328 #ifdef UTF8_OUTPUT_ENABLE
1329         ms_ucs_map_f = UCS_MAP_CP932;
1330 #endif
1331         break;
1332     case CP50221:
1333         x0201_f = TRUE;
1334 #ifdef SHIFTJIS_CP932
1335         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1336 #endif
1337 #ifdef UTF8_OUTPUT_ENABLE
1338         ms_ucs_map_f = UCS_MAP_CP932;
1339 #endif
1340         break;
1341     case ISO_2022_JP:
1342 #ifdef SHIFTJIS_CP932
1343         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1344 #endif
1345         break;
1346     case ISO_2022_JP_1:
1347         x0212_f = TRUE;
1348 #ifdef SHIFTJIS_CP932
1349         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1350 #endif
1351         break;
1352     case ISO_2022_JP_3:
1353         x0212_f = TRUE;
1354         x0213_f = TRUE;
1355 #ifdef SHIFTJIS_CP932
1356         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1357 #endif
1358         break;
1359     case SHIFT_JIS:
1360         break;
1361     case WINDOWS_31J:
1362         x0201_f = TRUE;
1363 #ifdef UTF8_OUTPUT_ENABLE
1364         ms_ucs_map_f = UCS_MAP_CP932;
1365 #endif
1366         break;
1367     case CP10001:
1368 #ifdef UTF8_OUTPUT_ENABLE
1369         ms_ucs_map_f = UCS_MAP_CP10001;
1370 #endif
1371         break;
1372     case EUC_JP:
1373         x0212_f = TRUE;
1374 #ifdef SHIFTJIS_CP932
1375         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1376 #endif
1377 #ifdef UTF8_OUTPUT_ENABLE
1378         ms_ucs_map_f = UCS_MAP_ASCII;
1379 #endif
1380         break;
1381     case EUCJP_NKF:
1382         x0212_f = FALSE;
1383 #ifdef SHIFTJIS_CP932
1384         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1385 #endif
1386 #ifdef UTF8_OUTPUT_ENABLE
1387         ms_ucs_map_f = UCS_MAP_ASCII;
1388 #endif
1389         break;
1390     case CP51932:
1391         x0201_f = TRUE;
1392 #ifdef SHIFTJIS_CP932
1393         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1394 #endif
1395 #ifdef UTF8_OUTPUT_ENABLE
1396         ms_ucs_map_f = UCS_MAP_CP932;
1397 #endif
1398         break;
1399     case EUCJP_MS:
1400         x0212_f = TRUE;
1401 #ifdef UTF8_OUTPUT_ENABLE
1402         ms_ucs_map_f = UCS_MAP_MS;
1403 #endif
1404         break;
1405     case EUCJP_ASCII:
1406         x0212_f = TRUE;
1407 #ifdef UTF8_OUTPUT_ENABLE
1408         ms_ucs_map_f = UCS_MAP_ASCII;
1409 #endif
1410         break;
1411     case SHIFT_JISX0213:
1412     case SHIFT_JIS_2004:
1413         x0213_f = TRUE;
1414 #ifdef SHIFTJIS_CP932
1415         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1416 #endif
1417         break;
1418     case EUC_JISX0213:
1419     case EUC_JIS_2004:
1420         x0212_f = TRUE;
1421         x0213_f = TRUE;
1422 #ifdef SHIFTJIS_CP932
1423         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1424 #endif
1425         break;
1426 #ifdef UTF8_OUTPUT_ENABLE
1427     case UTF_8_BOM:
1428         output_bom_f = TRUE;
1429         break;
1430     case UTF_16:
1431     case UTF_16BE_BOM:
1432         output_bom_f = TRUE;
1433         break;
1434     case UTF_16LE:
1435         output_endian = ENDIAN_LITTLE;
1436         output_bom_f = FALSE;
1437         break;
1438     case UTF_16LE_BOM:
1439         output_endian = ENDIAN_LITTLE;
1440         output_bom_f = TRUE;
1441         break;
1442     case UTF_32:
1443     case UTF_32BE_BOM:
1444         output_bom_f = TRUE;
1445         break;
1446     case UTF_32LE:
1447         output_endian = ENDIAN_LITTLE;
1448         output_bom_f = FALSE;
1449         break;
1450     case UTF_32LE_BOM:
1451         output_endian = ENDIAN_LITTLE;
1452         output_bom_f = TRUE;
1453         break;
1454 #endif
1455     }
1456 }
1457
1458 static struct input_code*
1459 find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
1460 {
1461     if (iconv_func){
1462         struct input_code *p = input_code_list;
1463         while (p->name){
1464             if (iconv_func == p->iconv_func){
1465                 return p;
1466             }
1467             p++;
1468         }
1469     }
1470     return 0;
1471 }
1472
1473 static void
1474 set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
1475 {
1476 #ifdef INPUT_CODE_FIX
1477     if (f || !input_encoding)
1478 #endif
1479         if (estab_f != f){
1480             estab_f = f;
1481         }
1482
1483     if (iconv_func
1484 #ifdef INPUT_CODE_FIX
1485         && (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */
1486 #endif
1487        ){
1488         iconv = iconv_func;
1489     }
1490 #ifdef CHECK_OPTION
1491     if (estab_f && iconv_for_check != iconv){
1492         struct input_code *p = find_inputcode_byfunc(iconv);
1493         if (p){
1494             set_input_codename(p->name);
1495             debug(p->name);
1496         }
1497         iconv_for_check = iconv;
1498     }
1499 #endif
1500 }
1501
1502 #ifdef X0212_ENABLE
1503 static nkf_char
1504 x0212_shift(nkf_char c)
1505 {
1506     nkf_char ret = c;
1507     c &= 0x7f;
1508     if (is_eucg3(ret)){
1509         if (0x75 <= c && c <= 0x7f){
1510             ret = c + (0x109 - 0x75);
1511         }
1512     }else{
1513         if (0x75 <= c && c <= 0x7f){
1514             ret = c + (0x113 - 0x75);
1515         }
1516     }
1517     return ret;
1518 }
1519
1520
1521 static nkf_char
1522 x0212_unshift(nkf_char c)
1523 {
1524     nkf_char ret = c;
1525     if (0x7f <= c && c <= 0x88){
1526         ret = c + (0x75 - 0x7f);
1527     }else if (0x89 <= c && c <= 0x92){
1528         ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
1529     }
1530     return ret;
1531 }
1532 #endif /* X0212_ENABLE */
1533
1534 static nkf_char
1535 e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
1536 {
1537     nkf_char ndx;
1538     if (is_eucg3(c2)){
1539         ndx = c2 & 0x7f;
1540         if (x0213_f){
1541             if((0x21 <= ndx && ndx <= 0x2F)){
1542                 if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3;
1543                 if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1544                 return 0;
1545             }else if(0x6E <= ndx && ndx <= 0x7E){
1546                 if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe;
1547                 if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1548                 return 0;
1549             }
1550             return 1;
1551         }
1552 #ifdef X0212_ENABLE
1553         else if(nkf_isgraph(ndx)){
1554             nkf_char val = 0;
1555             const unsigned short *ptr;
1556             ptr = x0212_shiftjis[ndx - 0x21];
1557             if (ptr){
1558                 val = ptr[(c1 & 0x7f) - 0x21];
1559             }
1560             if (val){
1561                 c2 = val >> 8;
1562                 c1 = val & 0xff;
1563                 if (p2) *p2 = c2;
1564                 if (p1) *p1 = c1;
1565                 return 0;
1566             }
1567             c2 = x0212_shift(c2);
1568         }
1569 #endif /* X0212_ENABLE */
1570     }
1571     if(0x7F < c2) return 1;
1572     if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
1573     if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1574     return 0;
1575 }
1576
1577 static nkf_char
1578 s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
1579 {
1580 #if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
1581     nkf_char val;
1582 #endif
1583     static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
1584     if (0xFC < c1) return 1;
1585 #ifdef SHIFTJIS_CP932
1586     if (!cp932inv_f && is_ibmext_in_sjis(c2)){
1587         val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
1588         if (val){
1589             c2 = val >> 8;
1590             c1 = val & 0xff;
1591         }
1592     }
1593     if (cp932inv_f
1594         && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
1595         val = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
1596         if (val){
1597             c2 = val >> 8;
1598             c1 = val & 0xff;
1599         }
1600     }
1601 #endif /* SHIFTJIS_CP932 */
1602 #ifdef X0212_ENABLE
1603     if (!x0213_f && is_ibmext_in_sjis(c2)){
1604         val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
1605         if (val){
1606             if (val > 0x7FFF){
1607                 c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f);
1608                 c1 = val & 0xff;
1609             }else{
1610                 c2 = val >> 8;
1611                 c1 = val & 0xff;
1612             }
1613             if (p2) *p2 = c2;
1614             if (p1) *p1 = c1;
1615             return 0;
1616         }
1617     }
1618 #endif
1619     if(c2 >= 0x80){
1620         if(x0213_f && c2 >= 0xF0){
1621             if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */
1622                 c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1];
1623             }else{ /* 78<=k<=94 */
1624                 c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B);
1625                 if (0x9E < c1) c2++;
1626             }
1627         }else{
1628 #define         SJ0162  0x00e1          /* 01 - 62 ku offset */
1629 #define         SJ6394  0x0161          /* 63 - 94 ku offset */
1630             c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394);
1631             if (0x9E < c1) c2++;
1632         }
1633         if (c1 < 0x9F)
1634             c1 = c1 - ((c1 > DEL) ? SP : 0x1F);
1635         else {
1636             c1 = c1 - 0x7E;
1637         }
1638     }
1639
1640 #ifdef X0212_ENABLE
1641     c2 = x0212_unshift(c2);
1642 #endif
1643     if (p2) *p2 = c2;
1644     if (p1) *p1 = c1;
1645     return 0;
1646 }
1647
1648 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
1649 static void
1650 nkf_unicode_to_utf8(nkf_char val, nkf_char *p1, nkf_char *p2, nkf_char *p3, nkf_char *p4)
1651 {
1652     val &= VALUE_MASK;
1653     if (val < 0x80){
1654         *p1 = val;
1655         *p2 = 0;
1656         *p3 = 0;
1657         *p4 = 0;
1658     }else if (val < 0x800){
1659         *p1 = 0xc0 | (val >> 6);
1660         *p2 = 0x80 | (val & 0x3f);
1661         *p3 = 0;
1662         *p4 = 0;
1663     } else if (nkf_char_unicode_bmp_p(val)) {
1664         *p1 = 0xe0 |  (val >> 12);
1665         *p2 = 0x80 | ((val >>  6) & 0x3f);
1666         *p3 = 0x80 | ( val        & 0x3f);
1667         *p4 = 0;
1668     } else if (nkf_char_unicode_value_p(val)) {
1669         *p1 = 0xf0 |  (val >> 18);
1670         *p2 = 0x80 | ((val >> 12) & 0x3f);
1671         *p3 = 0x80 | ((val >>  6) & 0x3f);
1672         *p4 = 0x80 | ( val        & 0x3f);
1673     } else {
1674         *p1 = 0;
1675         *p2 = 0;
1676         *p3 = 0;
1677         *p4 = 0;
1678     }
1679 }
1680
1681 static nkf_char
1682 nkf_utf8_to_unicode(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
1683 {
1684     nkf_char wc;
1685     if (c1 <= 0x7F) {
1686         /* single byte */
1687         wc = c1;
1688     }
1689     else if (c1 <= 0xC3) {
1690         /* trail byte or invalid */
1691         return -1;
1692     }
1693     else if (c1 <= 0xDF) {
1694         /* 2 bytes */
1695         wc  = (c1 & 0x1F) << 6;
1696         wc |= (c2 & 0x3F);
1697     }
1698     else if (c1 <= 0xEF) {
1699         /* 3 bytes */
1700         wc  = (c1 & 0x0F) << 12;
1701         wc |= (c2 & 0x3F) << 6;
1702         wc |= (c3 & 0x3F);
1703     }
1704     else if (c2 <= 0xF4) {
1705         /* 4 bytes */
1706         wc  = (c1 & 0x0F) << 18;
1707         wc |= (c2 & 0x3F) << 12;
1708         wc |= (c3 & 0x3F) << 6;
1709         wc |= (c4 & 0x3F);
1710     }
1711     else {
1712         return -1;
1713     }
1714     return wc;
1715 }
1716 #endif
1717
1718 #ifdef UTF8_INPUT_ENABLE
1719 static int
1720 unicode_to_jis_common2(nkf_char c1, nkf_char c0,
1721                        const unsigned short *const *pp, nkf_char psize,
1722                        nkf_char *p2, nkf_char *p1)
1723 {
1724     nkf_char c2;
1725     const unsigned short *p;
1726     unsigned short val;
1727
1728     if (pp == 0) return 1;
1729
1730     c1 -= 0x80;
1731     if (c1 < 0 || psize <= c1) return 1;
1732     p = pp[c1];
1733     if (p == 0)  return 1;
1734
1735     c0 -= 0x80;
1736     if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1;
1737     val = p[c0];
1738     if (val == 0) return 1;
1739     if (no_cp932ext_f && (
1740                           (val>>8) == 0x2D || /* NEC special characters */
1741                           val > NKF_INT32_C(0xF300) /* IBM extended characters */
1742                          )) return 1;
1743
1744     c2 = val >> 8;
1745     if (val > 0x7FFF){
1746         c2 &= 0x7f;
1747         c2 |= PREFIX_EUCG3;
1748     }
1749     if (c2 == SO) c2 = JIS_X_0201_1976_K;
1750     c1 = val & 0xFF;
1751     if (p2) *p2 = c2;
1752     if (p1) *p1 = c1;
1753     return 0;
1754 }
1755
1756 static int
1757 unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
1758 {
1759     const unsigned short *const *pp;
1760     const unsigned short *const *const *ppp;
1761     static const char no_best_fit_chars_table_C2[] =
1762     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1763         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1764         1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2,
1765         0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1};
1766     static const char no_best_fit_chars_table_C2_ms[] =
1767     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1768         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1769         1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,
1770         0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0};
1771     static const char no_best_fit_chars_table_932_C2[] =
1772     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1773         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1774         1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1775         0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0};
1776     static const char no_best_fit_chars_table_932_C3[] =
1777     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1778         1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1779         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1780         1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1};
1781     nkf_char ret = 0;
1782
1783     if(c2 < 0x80){
1784         *p2 = 0;
1785         *p1 = c2;
1786     }else if(c2 < 0xe0){
1787         if(no_best_fit_chars_f){
1788             if(ms_ucs_map_f == UCS_MAP_CP932){
1789                 switch(c2){
1790                 case 0xC2:
1791                     if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1;
1792                     break;
1793                 case 0xC3:
1794                     if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
1795                     break;
1796                 }
1797             }else if(!cp932inv_f){
1798                 switch(c2){
1799                 case 0xC2:
1800                     if(no_best_fit_chars_table_C2[c1&0x3F]) return 1;
1801                     break;
1802                 case 0xC3:
1803                     if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
1804                     break;
1805                 }
1806             }else if(ms_ucs_map_f == UCS_MAP_MS){
1807                 if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1;
1808             }else if(ms_ucs_map_f == UCS_MAP_CP10001){
1809                 switch(c2){
1810                 case 0xC2:
1811                     switch(c1){
1812                     case 0xA2:
1813                     case 0xA3:
1814                     case 0xA5:
1815                     case 0xA6:
1816                     case 0xAC:
1817                     case 0xAF:
1818                     case 0xB8:
1819                         return 1;
1820                     }
1821                     break;
1822                 }
1823             }
1824         }
1825         pp =
1826             ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 :
1827             ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms :
1828             ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_2bytes_mac :
1829             utf8_to_euc_2bytes;
1830         ret =  unicode_to_jis_common2(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
1831     }else if(c0 < 0xF0){
1832         if(no_best_fit_chars_f){
1833             if(ms_ucs_map_f == UCS_MAP_CP932){
1834                 if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1;
1835             }else if(ms_ucs_map_f == UCS_MAP_MS){
1836                 switch(c2){
1837                 case 0xE2:
1838                     switch(c1){
1839                     case 0x80:
1840                         if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1;
1841                         break;
1842                     case 0x88:
1843                         if(c0 == 0x92) return 1;
1844                         break;
1845                     }
1846                     break;
1847                 case 0xE3:
1848                     if(c1 == 0x80 || c0 == 0x9C) return 1;
1849                     break;
1850                 }
1851             }else if(ms_ucs_map_f == UCS_MAP_CP10001){
1852                 switch(c2){
1853                 case 0xE3:
1854                     switch(c1){
1855                     case 0x82:
1856                         if(c0 == 0x94) return 1;
1857                         break;
1858                     case 0x83:
1859                         if(c0 == 0xBB) return 1;
1860                         break;
1861                     }
1862                     break;
1863                 }
1864             }else{
1865                 switch(c2){
1866                 case 0xE2:
1867                     switch(c1){
1868                     case 0x80:
1869                         if(c0 == 0x95) return 1;
1870                         break;
1871                     case 0x88:
1872                         if(c0 == 0xA5) return 1;
1873                         break;
1874                     }
1875                     break;
1876                 case 0xEF:
1877                     switch(c1){
1878                     case 0xBC:
1879                         if(c0 == 0x8D) return 1;
1880                         break;
1881                     case 0xBD:
1882                         if(c0 == 0x9E && !cp932inv_f) return 1;
1883                         break;
1884                     case 0xBF:
1885                         if(0xA0 <= c0 && c0 <= 0xA5) return 1;
1886                         break;
1887                     }
1888                     break;
1889                 }
1890             }
1891         }
1892         ppp =
1893             ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 :
1894             ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms :
1895             ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_3bytes_mac :
1896             utf8_to_euc_3bytes;
1897         ret = unicode_to_jis_common2(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
1898     }else return -1;
1899 #ifdef SHIFTJIS_CP932
1900     if (!ret && !cp932inv_f && is_eucg3(*p2)) {
1901         nkf_char s2, s1;
1902         if (e2s_conv(*p2, *p1, &s2, &s1) == 0) {
1903             s2e_conv(s2, s1, p2, p1);
1904         }else{
1905             ret = 1;
1906         }
1907     }
1908 #endif
1909     return ret;
1910 }
1911
1912 #ifdef UTF8_OUTPUT_ENABLE
1913 static nkf_char
1914 e2w_conv(nkf_char c2, nkf_char c1)
1915 {
1916     const unsigned short *p;
1917
1918     if (c2 == JIS_X_0201_1976_K) {
1919         if (ms_ucs_map_f == UCS_MAP_CP10001) {
1920             switch (c1) {
1921             case 0x20:
1922                 return 0xA0;
1923             case 0x7D:
1924                 return 0xA9;
1925             }
1926         }
1927         p = euc_to_utf8_1byte;
1928 #ifdef X0212_ENABLE
1929     } else if (is_eucg3(c2)){
1930         if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){
1931             return 0xA6;
1932         }
1933         c2 = (c2&0x7f) - 0x21;
1934         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
1935             p = x0212_to_utf8_2bytes[c2];
1936         else
1937             return 0;
1938 #endif
1939     } else {
1940         c2 &= 0x7f;
1941         c2 = (c2&0x7f) - 0x21;
1942         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
1943             p =
1944                 ms_ucs_map_f == UCS_MAP_ASCII ? euc_to_utf8_2bytes[c2] :
1945                 ms_ucs_map_f == UCS_MAP_CP10001 ? euc_to_utf8_2bytes_mac[c2] :
1946                 euc_to_utf8_2bytes_ms[c2];
1947         else
1948             return 0;
1949     }
1950     if (!p) return 0;
1951     c1 = (c1 & 0x7f) - 0x21;
1952     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
1953         return p[c1];
1954     return 0;
1955 }
1956 #endif
1957
1958 static nkf_char
1959 w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
1960 {
1961     nkf_char ret = 0;
1962
1963     if (!c1){
1964         *p2 = 0;
1965         *p1 = c2;
1966     }else if (0xc0 <= c2 && c2 <= 0xef) {
1967         ret =  unicode_to_jis_common(c2, c1, c0, p2, p1);
1968 #ifdef NUMCHAR_OPTION
1969         if (ret > 0){
1970             if (p2) *p2 = 0;
1971             if (p1) *p1 = nkf_char_unicode_new(nkf_utf8_to_unicode(c2, c1, c0, 0));
1972             ret = 0;
1973         }
1974 #endif
1975     }
1976     return ret;
1977 }
1978
1979 #ifdef UTF8_INPUT_ENABLE
1980 static nkf_char
1981 w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
1982 {
1983     nkf_char c1, c2, c3, c4;
1984     nkf_char ret = 0;
1985     val &= VALUE_MASK;
1986     if (val < 0x80) {
1987         *p2 = 0;
1988         *p1 = val;
1989     }
1990     else if (nkf_char_unicode_bmp_p(val)){
1991         nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
1992         ret =  unicode_to_jis_common(c1, c2, c3, p2, p1);
1993         if (ret > 0){
1994             *p2 = 0;
1995             *p1 = nkf_char_unicode_new(val);
1996             ret = 0;
1997         }
1998     }
1999     else {
2000         *p2 = 0;
2001         *p1 = nkf_char_unicode_new(val);
2002     }
2003     return ret;
2004 }
2005 #endif
2006
2007 static nkf_char
2008 e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
2009 {
2010     if (c2 == JIS_X_0201_1976_K || c2 == SS2){
2011         if (iso2022jp_f && !x0201_f) {
2012             c2 = GETA1; c1 = GETA2;
2013         } else {
2014             c2 = JIS_X_0201_1976_K;
2015             c1 &= 0x7f;
2016         }
2017 #ifdef X0212_ENABLE
2018     }else if (c2 == 0x8f){
2019         if (c0 == 0){
2020             return -1;
2021         }
2022         if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) {
2023             /* encoding is eucJP-ms, so invert to Unicode Private User Area */
2024             c1 = nkf_char_unicode_new((c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC);
2025             c2 = 0;
2026         } else {
2027             c2 = (c2 << 8) | (c1 & 0x7f);
2028             c1 = c0 & 0x7f;
2029 #ifdef SHIFTJIS_CP932
2030             if (cp51932_f){
2031                 nkf_char s2, s1;
2032                 if (e2s_conv(c2, c1, &s2, &s1) == 0){
2033                     s2e_conv(s2, s1, &c2, &c1);
2034                     if (c2 < 0x100){
2035                         c1 &= 0x7f;
2036                         c2 &= 0x7f;
2037                     }
2038                 }
2039             }
2040 #endif /* SHIFTJIS_CP932 */
2041         }
2042 #endif /* X0212_ENABLE */
2043     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP || c2 == ISO_8859_1) {
2044         /* NOP */
2045     } else {
2046         if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) {
2047             /* encoding is eucJP-ms, so invert to Unicode Private User Area */
2048             c1 = nkf_char_unicode_new((c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000);
2049             c2 = 0;
2050         } else {
2051             c1 &= 0x7f;
2052             c2 &= 0x7f;
2053 #ifdef SHIFTJIS_CP932
2054             if (cp51932_f && 0x79 <= c2 && c2 <= 0x7c){
2055                 nkf_char s2, s1;
2056                 if (e2s_conv(c2, c1, &s2, &s1) == 0){
2057                     s2e_conv(s2, s1, &c2, &c1);
2058                     if (c2 < 0x100){
2059                         c1 &= 0x7f;
2060                         c2 &= 0x7f;
2061                     }
2062                 }
2063             }
2064 #endif /* SHIFTJIS_CP932 */
2065         }
2066     }
2067     (*oconv)(c2, c1);
2068     return 0;
2069 }
2070
2071 static nkf_char
2072 s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
2073 {
2074     if (c2 == JIS_X_0201_1976_K || (0xA1 <= c2 && c2 <= 0xDF)) {
2075         if (iso2022jp_f && !x0201_f) {
2076             c2 = GETA1; c1 = GETA2;
2077         } else {
2078             c1 &= 0x7f;
2079         }
2080     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) {
2081         /* NOP */
2082     } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) {
2083         /* CP932 UDC */
2084         if(c1 == 0x7F) return 0;
2085         c1 = nkf_char_unicode_new((c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000);
2086         c2 = 0;
2087     } else {
2088         nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
2089         if (ret) return ret;
2090     }
2091     (*oconv)(c2, c1);
2092     return 0;
2093 }
2094
2095 static nkf_char
2096 w_iconv(nkf_char c1, nkf_char c2, nkf_char c3)
2097 {
2098     nkf_char ret = 0, c4 = 0;
2099     static const char w_iconv_utf8_1st_byte[] =
2100     { /* 0xC0 - 0xFF */
2101         20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
2102         21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
2103         30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33,
2104         40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70};
2105
2106     if (c3 > 0xFF) {
2107         c4 = c3 & 0xFF;
2108         c3 >>= 8;
2109     }
2110
2111     if (c1 < 0 || 0xff < c1) {
2112     }else if (c1 == 0) { /* 0 : 1 byte*/
2113         c3 = 0;
2114     } else if ((c1 & 0xC0) == 0x80) { /* 0x80-0xbf : trail byte */
2115         return 0;
2116     } else{
2117         switch (w_iconv_utf8_1st_byte[c1 - 0xC0]) {
2118         case 21:
2119             if (c2 < 0x80 || 0xBF < c2) return 0;
2120             break;
2121         case 30:
2122             if (c3 == 0) return -1;
2123             if (c2 < 0xA0 || 0xBF < c2 || (c3 & 0xC0) != 0x80)
2124                 return 0;
2125             break;
2126         case 31:
2127         case 33:
2128             if (c3 == 0) return -1;
2129             if ((c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80)
2130                 return 0;
2131             break;
2132         case 32:
2133             if (c3 == 0) return -1;
2134             if (c2 < 0x80 || 0x9F < c2 || (c3 & 0xC0) != 0x80)
2135                 return 0;
2136             break;
2137         case 40:
2138             if (c3 == 0) return -2;
2139             if (c2 < 0x90 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2140                 return 0;
2141             break;
2142         case 41:
2143             if (c3 == 0) return -2;
2144             if (c2 < 0x80 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2145                 return 0;
2146             break;
2147         case 42:
2148             if (c3 == 0) return -2;
2149             if (c2 < 0x80 || 0x8F < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2150                 return 0;
2151             break;
2152         default:
2153             return 0;
2154             break;
2155         }
2156     }
2157     if (c1 == 0 || c1 == EOF){
2158     } else if ((c1 & 0xf8) == 0xf0) { /* 4 bytes */
2159         c2 = nkf_char_unicode_new(nkf_utf8_to_unicode(c1, c2, c3, c4));
2160         c1 = 0;
2161     } else {
2162         ret = w2e_conv(c1, c2, c3, &c1, &c2);
2163     }
2164     if (ret == 0){
2165         (*oconv)(c1, c2);
2166     }
2167     return ret;
2168 }
2169
2170 #define NKF_ICONV_INVALID_CODE_RANGE -13
2171 static size_t
2172 unicode_iconv(nkf_char wc)
2173 {
2174     nkf_char c1, c2;
2175     int ret = 0;
2176
2177     if (wc < 0x80) {
2178         c2 = 0;
2179         c1 = wc;
2180     }else if ((wc>>11) == 27) {
2181         /* unpaired surrogate */
2182         return NKF_ICONV_INVALID_CODE_RANGE;
2183     }else if (wc < 0xFFFF) {
2184         ret = w16e_conv(wc, &c2, &c1);
2185         if (ret) return ret;
2186     }else if (wc < 0x10FFFF) {
2187         c2 = 0;
2188         c1 = nkf_char_unicode_new(wc);
2189     } else {
2190         return NKF_ICONV_INVALID_CODE_RANGE;
2191     }
2192     (*oconv)(c2, c1);
2193     return 0;
2194 }
2195
2196 #define NKF_ICONV_NEED_ONE_MORE_BYTE -1
2197 #define NKF_ICONV_NEED_TWO_MORE_BYTES -2
2198 #define UTF16_TO_UTF32(lead, trail) (((lead) << 10) + (trail) - NKF_INT32_C(0x35FDC00))
2199 static size_t
2200 nkf_iconv_utf_16(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
2201 {
2202     nkf_char wc;
2203
2204     if (c1 == EOF) {
2205         (*oconv)(EOF, 0);
2206         return 0;
2207     }
2208
2209     if (input_endian == ENDIAN_BIG) {
2210         if (0xD8 <= c1 && c1 <= 0xDB) {
2211             if (0xDC <= c3 && c3 <= 0xDF) {
2212                 wc = UTF16_TO_UTF32(c1 << 8 | c2, c3 << 8 | c4);
2213             } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
2214         } else {
2215             wc = c1 << 8 | c2;
2216         }
2217     } else {
2218         if (0xD8 <= c2 && c2 <= 0xDB) {
2219             if (0xDC <= c4 && c4 <= 0xDF) {
2220                 wc = UTF16_TO_UTF32(c2 << 8 | c1, c4 << 8 | c3);
2221             } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
2222         } else {
2223             wc = c2 << 8 | c1;
2224         }
2225     }
2226
2227     return (*unicode_iconv)(wc);
2228 }
2229
2230 static nkf_char
2231 w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
2232 {
2233     return 0;
2234 }
2235
2236 static nkf_char
2237 w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
2238 {
2239     return 0;
2240 }
2241
2242 static size_t
2243 nkf_iconv_utf_32(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
2244 {
2245     nkf_char wc;
2246
2247     if (c1 == EOF) {
2248         (*oconv)(EOF, 0);
2249         return 0;
2250     }
2251
2252     switch(input_endian){
2253     case ENDIAN_BIG:
2254         wc = c2 << 16 | c3 << 8 | c4;
2255         break;
2256     case ENDIAN_LITTLE:
2257         wc = c3 << 16 | c2 << 8 | c1;
2258         break;
2259     case ENDIAN_2143:
2260         wc = c1 << 16 | c4 << 8 | c3;
2261         break;
2262     case ENDIAN_3412:
2263         wc = c4 << 16 | c1 << 8 | c2;
2264         break;
2265     default:
2266         return NKF_ICONV_INVALID_CODE_RANGE;
2267     }
2268
2269     return (*unicode_iconv)(wc);
2270 }
2271 #endif
2272
2273 #define output_ascii_escape_sequence(mode) do { \
2274             if (output_mode != ASCII && output_mode != ISO_8859_1) { \
2275                     (*o_putc)(ESC); \
2276                     (*o_putc)('('); \
2277                     (*o_putc)(ascii_intro); \
2278                     output_mode = mode; \
2279             } \
2280     } while (0)
2281
2282 static void
2283 output_escape_sequence(int mode)
2284 {
2285     if (output_mode == mode)
2286         return;
2287     switch(mode) {
2288     case ISO_8859_1:
2289         (*o_putc)(ESC);
2290         (*o_putc)('.');
2291         (*o_putc)('A');
2292         break;
2293     case JIS_X_0201_1976_K:
2294         (*o_putc)(ESC);
2295         (*o_putc)('(');
2296         (*o_putc)('I');
2297         break;
2298     case JIS_X_0208:
2299         (*o_putc)(ESC);
2300         (*o_putc)('$');
2301         (*o_putc)(kanji_intro);
2302         break;
2303     case JIS_X_0212:
2304         (*o_putc)(ESC);
2305         (*o_putc)('$');
2306         (*o_putc)('(');
2307         (*o_putc)('D');
2308         break;
2309     case JIS_X_0213_1:
2310         (*o_putc)(ESC);
2311         (*o_putc)('$');
2312         (*o_putc)('(');
2313         (*o_putc)('Q');
2314         break;
2315     case JIS_X_0213_2:
2316         (*o_putc)(ESC);
2317         (*o_putc)('$');
2318         (*o_putc)('(');
2319         (*o_putc)('P');
2320         break;
2321     }
2322     output_mode = mode;
2323 }
2324
2325 static void
2326 j_oconv(nkf_char c2, nkf_char c1)
2327 {
2328 #ifdef NUMCHAR_OPTION
2329     if (c2 == 0 && nkf_char_unicode_p(c1)){
2330         w16e_conv(c1, &c2, &c1);
2331         if (c2 == 0 && nkf_char_unicode_p(c1)){
2332             c2 = c1 & VALUE_MASK;
2333             if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) {
2334                 /* CP5022x UDC */
2335                 c1 &= 0xFFF;
2336                 c2 = 0x7F + c1 / 94;
2337                 c1 = 0x21 + c1 % 94;
2338             } else {
2339                 if (encode_fallback) (*encode_fallback)(c1);
2340                 return;
2341             }
2342         }
2343     }
2344 #endif
2345     if (c2 == 0) {
2346         output_ascii_escape_sequence(ASCII);
2347         (*o_putc)(c1);
2348     }
2349     else if (c2 == EOF) {
2350         output_ascii_escape_sequence(ASCII);
2351         (*o_putc)(EOF);
2352     }
2353     else if (c2 == ISO_8859_1) {
2354         output_ascii_escape_sequence(ISO_8859_1);
2355         (*o_putc)(c1|0x80);
2356     }
2357     else if (c2 == JIS_X_0201_1976_K) {
2358         output_escape_sequence(JIS_X_0201_1976_K);
2359         (*o_putc)(c1);
2360 #ifdef X0212_ENABLE
2361     } else if (is_eucg3(c2)){
2362         output_escape_sequence(x0213_f ? JIS_X_0213_2 : JIS_X_0212);
2363         (*o_putc)(c2 & 0x7f);
2364         (*o_putc)(c1);
2365 #endif
2366     } else {
2367         if(ms_ucs_map_f
2368            ? c2<0x20 || 0x92<c2 || c1<0x20 || 0x7e<c1
2369            : c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
2370         output_escape_sequence(x0213_f ? JIS_X_0213_1 : JIS_X_0208);
2371         (*o_putc)(c2);
2372         (*o_putc)(c1);
2373     }
2374 }
2375
2376 static void
2377 e_oconv(nkf_char c2, nkf_char c1)
2378 {
2379     if (c2 == 0 && nkf_char_unicode_p(c1)){
2380         w16e_conv(c1, &c2, &c1);
2381         if (c2 == 0 && nkf_char_unicode_p(c1)){
2382             c2 = c1 & VALUE_MASK;
2383             if (x0212_f && 0xE000 <= c2 && c2 <= 0xE757) {
2384                 /* eucJP-ms UDC */
2385                 c1 &= 0xFFF;
2386                 c2 = c1 / 94;
2387                 c2 += c2 < 10 ? 0x75 : 0x8FEB;
2388                 c1 = 0x21 + c1 % 94;
2389                 if (is_eucg3(c2)){
2390                     (*o_putc)(0x8f);
2391                     (*o_putc)((c2 & 0x7f) | 0x080);
2392                     (*o_putc)(c1 | 0x080);
2393                 }else{
2394                     (*o_putc)((c2 & 0x7f) | 0x080);
2395                     (*o_putc)(c1 | 0x080);
2396                 }
2397                 return;
2398             } else {
2399                 if (encode_fallback) (*encode_fallback)(c1);
2400                 return;
2401             }
2402         }
2403     }
2404
2405     if (c2 == EOF) {
2406         (*o_putc)(EOF);
2407     } else if (c2 == 0) {
2408         output_mode = ASCII;
2409         (*o_putc)(c1);
2410     } else if (c2 == JIS_X_0201_1976_K) {
2411         output_mode = EUC_JP;
2412         (*o_putc)(SS2); (*o_putc)(c1|0x80);
2413     } else if (c2 == ISO_8859_1) {
2414         output_mode = ISO_8859_1;
2415         (*o_putc)(c1 | 0x080);
2416 #ifdef X0212_ENABLE
2417     } else if (is_eucg3(c2)){
2418         output_mode = EUC_JP;
2419 #ifdef SHIFTJIS_CP932
2420         if (!cp932inv_f){
2421             nkf_char s2, s1;
2422             if (e2s_conv(c2, c1, &s2, &s1) == 0){
2423                 s2e_conv(s2, s1, &c2, &c1);
2424             }
2425         }
2426 #endif
2427         if (c2 == 0) {
2428             output_mode = ASCII;
2429             (*o_putc)(c1);
2430         }else if (is_eucg3(c2)){
2431             if (x0212_f){
2432                 (*o_putc)(0x8f);
2433                 (*o_putc)((c2 & 0x7f) | 0x080);
2434                 (*o_putc)(c1 | 0x080);
2435             }
2436         }else{
2437             (*o_putc)((c2 & 0x7f) | 0x080);
2438             (*o_putc)(c1 | 0x080);
2439         }
2440 #endif
2441     } else {
2442         if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
2443             set_iconv(FALSE, 0);
2444             return; /* too late to rescue this char */
2445         }
2446         output_mode = EUC_JP;
2447         (*o_putc)(c2 | 0x080);
2448         (*o_putc)(c1 | 0x080);
2449     }
2450 }
2451
2452 static void
2453 s_oconv(nkf_char c2, nkf_char c1)
2454 {
2455 #ifdef NUMCHAR_OPTION
2456     if (c2 == 0 && nkf_char_unicode_p(c1)){
2457         w16e_conv(c1, &c2, &c1);
2458         if (c2 == 0 && nkf_char_unicode_p(c1)){
2459             c2 = c1 & VALUE_MASK;
2460             if (!x0213_f && 0xE000 <= c2 && c2 <= 0xE757) {
2461                 /* CP932 UDC */
2462                 c1 &= 0xFFF;
2463                 c2 = c1 / 188 + (cp932inv_f ? 0xF0 : 0xEB);
2464                 c1 = c1 % 188;
2465                 c1 += 0x40 + (c1 > 0x3e);
2466                 (*o_putc)(c2);
2467                 (*o_putc)(c1);
2468                 return;
2469             } else {
2470                 if(encode_fallback)(*encode_fallback)(c1);
2471                 return;
2472             }
2473         }
2474     }
2475 #endif
2476     if (c2 == EOF) {
2477         (*o_putc)(EOF);
2478         return;
2479     } else if (c2 == 0) {
2480         output_mode = ASCII;
2481         (*o_putc)(c1);
2482     } else if (c2 == JIS_X_0201_1976_K) {
2483         output_mode = SHIFT_JIS;
2484         (*o_putc)(c1|0x80);
2485     } else if (c2 == ISO_8859_1) {
2486         output_mode = ISO_8859_1;
2487         (*o_putc)(c1 | 0x080);
2488 #ifdef X0212_ENABLE
2489     } else if (is_eucg3(c2)){
2490         output_mode = SHIFT_JIS;
2491         if (e2s_conv(c2, c1, &c2, &c1) == 0){
2492             (*o_putc)(c2);
2493             (*o_putc)(c1);
2494         }
2495 #endif
2496     } else {
2497         if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
2498             set_iconv(FALSE, 0);
2499             return; /* too late to rescue this char */
2500         }
2501         output_mode = SHIFT_JIS;
2502         e2s_conv(c2, c1, &c2, &c1);
2503
2504 #ifdef SHIFTJIS_CP932
2505         if (cp932inv_f
2506             && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
2507             nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
2508             if (c){
2509                 c2 = c >> 8;
2510                 c1 = c & 0xff;
2511             }
2512         }
2513 #endif /* SHIFTJIS_CP932 */
2514
2515         (*o_putc)(c2);
2516         if (prefix_table[(unsigned char)c1]){
2517             (*o_putc)(prefix_table[(unsigned char)c1]);
2518         }
2519         (*o_putc)(c1);
2520     }
2521 }
2522
2523 #ifdef UTF8_OUTPUT_ENABLE
2524 static void
2525 w_oconv(nkf_char c2, nkf_char c1)
2526 {
2527     nkf_char c3, c4;
2528     nkf_char val;
2529
2530     if (output_bom_f) {
2531         output_bom_f = FALSE;
2532         (*o_putc)('\357');
2533         (*o_putc)('\273');
2534         (*o_putc)('\277');
2535     }
2536
2537     if (c2 == EOF) {
2538         (*o_putc)(EOF);
2539         return;
2540     }
2541
2542     if (c2 == 0 && nkf_char_unicode_p(c1)){
2543         val = c1 & VALUE_MASK;
2544         nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
2545         (*o_putc)(c1);
2546         if (c2) (*o_putc)(c2);
2547         if (c3) (*o_putc)(c3);
2548         if (c4) (*o_putc)(c4);
2549         return;
2550     }
2551
2552     if (c2 == 0) {
2553         (*o_putc)(c1);
2554     } else {
2555         val = e2w_conv(c2, c1);
2556         if (val){
2557             nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
2558             (*o_putc)(c1);
2559             if (c2) (*o_putc)(c2);
2560             if (c3) (*o_putc)(c3);
2561             if (c4) (*o_putc)(c4);
2562         }
2563     }
2564 }
2565
2566 static void
2567 w_oconv16(nkf_char c2, nkf_char c1)
2568 {
2569     if (output_bom_f) {
2570         output_bom_f = FALSE;
2571         if (output_endian == ENDIAN_LITTLE){
2572             (*o_putc)(0xFF);
2573             (*o_putc)(0xFE);
2574         }else{
2575             (*o_putc)(0xFE);
2576             (*o_putc)(0xFF);
2577         }
2578     }
2579
2580     if (c2 == EOF) {
2581         (*o_putc)(EOF);
2582         return;
2583     }
2584
2585     if (c2 == 0 && nkf_char_unicode_p(c1)) {
2586         if (nkf_char_unicode_bmp_p(c1)) {
2587             c2 = (c1 >> 8) & 0xff;
2588             c1 &= 0xff;
2589         } else {
2590             c1 &= VALUE_MASK;
2591             if (c1 <= UNICODE_MAX) {
2592                 c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0);   /* high surrogate */
2593                 c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
2594                 if (output_endian == ENDIAN_LITTLE){
2595                     (*o_putc)(c2 & 0xff);
2596                     (*o_putc)((c2 >> 8) & 0xff);
2597                     (*o_putc)(c1 & 0xff);
2598                     (*o_putc)((c1 >> 8) & 0xff);
2599                 }else{
2600                     (*o_putc)((c2 >> 8) & 0xff);
2601                     (*o_putc)(c2 & 0xff);
2602                     (*o_putc)((c1 >> 8) & 0xff);
2603                     (*o_putc)(c1 & 0xff);
2604                 }
2605             }
2606             return;
2607         }
2608     } else if (c2) {
2609         nkf_char val = e2w_conv(c2, c1);
2610         c2 = (val >> 8) & 0xff;
2611         c1 = val & 0xff;
2612         if (!val) return;
2613     }
2614
2615     if (output_endian == ENDIAN_LITTLE){
2616         (*o_putc)(c1);
2617         (*o_putc)(c2);
2618     }else{
2619         (*o_putc)(c2);
2620         (*o_putc)(c1);
2621     }
2622 }
2623
2624 static void
2625 w_oconv32(nkf_char c2, nkf_char c1)
2626 {
2627     if (output_bom_f) {
2628         output_bom_f = FALSE;
2629         if (output_endian == ENDIAN_LITTLE){
2630             (*o_putc)(0xFF);
2631             (*o_putc)(0xFE);
2632             (*o_putc)(0);
2633             (*o_putc)(0);
2634         }else{
2635             (*o_putc)(0);
2636             (*o_putc)(0);
2637             (*o_putc)(0xFE);
2638             (*o_putc)(0xFF);
2639         }
2640     }
2641
2642     if (c2 == EOF) {
2643         (*o_putc)(EOF);
2644         return;
2645     }
2646
2647     if (c2 == ISO_8859_1) {
2648         c1 |= 0x80;
2649     } else if (c2 == 0 && nkf_char_unicode_p(c1)) {
2650         c1 &= VALUE_MASK;
2651     } else if (c2) {
2652         c1 = e2w_conv(c2, c1);
2653         if (!c1) return;
2654     }
2655     if (output_endian == ENDIAN_LITTLE){
2656         (*o_putc)( c1        & 0xFF);
2657         (*o_putc)((c1 >>  8) & 0xFF);
2658         (*o_putc)((c1 >> 16) & 0xFF);
2659         (*o_putc)(0);
2660     }else{
2661         (*o_putc)(0);
2662         (*o_putc)((c1 >> 16) & 0xFF);
2663         (*o_putc)((c1 >>  8) & 0xFF);
2664         (*o_putc)( c1        & 0xFF);
2665     }
2666 }
2667 #endif
2668
2669 #define SCORE_L2       (1)                   /* Kanji Level 2 */
2670 #define SCORE_KANA     (SCORE_L2 << 1)       /* Halfwidth Katakana */
2671 #define SCORE_DEPEND   (SCORE_KANA << 1)     /* MD Characters */
2672 #define SCORE_CP932    (SCORE_DEPEND << 1)   /* IBM extended characters */
2673 #define SCORE_X0212    (SCORE_CP932 << 1)    /* JIS X 0212 */
2674 #define SCORE_NO_EXIST (SCORE_X0212 << 1)    /* Undefined Characters */
2675 #define SCORE_iMIME    (SCORE_NO_EXIST << 1) /* MIME selected */
2676 #define SCORE_ERROR    (SCORE_iMIME << 1) /* Error */
2677
2678 #define SCORE_INIT (SCORE_iMIME)
2679
2680 static const nkf_char score_table_A0[] = {
2681     0, 0, 0, 0,
2682     0, 0, 0, 0,
2683     0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
2684     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
2685 };
2686
2687 static const nkf_char score_table_F0[] = {
2688     SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
2689     SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
2690     SCORE_DEPEND, SCORE_DEPEND, SCORE_CP932, SCORE_CP932,
2691     SCORE_CP932, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
2692 };
2693
2694 static void
2695 set_code_score(struct input_code *ptr, nkf_char score)
2696 {
2697     if (ptr){
2698         ptr->score |= score;
2699     }
2700 }
2701
2702 static void
2703 clr_code_score(struct input_code *ptr, nkf_char score)
2704 {
2705     if (ptr){
2706         ptr->score &= ~score;
2707     }
2708 }
2709
2710 static void
2711 code_score(struct input_code *ptr)
2712 {
2713     nkf_char c2 = ptr->buf[0];
2714 #ifdef UTF8_OUTPUT_ENABLE
2715     nkf_char c1 = ptr->buf[1];
2716 #endif
2717     if (c2 < 0){
2718         set_code_score(ptr, SCORE_ERROR);
2719     }else if (c2 == SS2){
2720         set_code_score(ptr, SCORE_KANA);
2721     }else if (c2 == 0x8f){
2722         set_code_score(ptr, SCORE_X0212);
2723 #ifdef UTF8_OUTPUT_ENABLE
2724     }else if (!e2w_conv(c2, c1)){
2725         set_code_score(ptr, SCORE_NO_EXIST);
2726 #endif
2727     }else if ((c2 & 0x70) == 0x20){
2728         set_code_score(ptr, score_table_A0[c2 & 0x0f]);
2729     }else if ((c2 & 0x70) == 0x70){
2730         set_code_score(ptr, score_table_F0[c2 & 0x0f]);
2731     }else if ((c2 & 0x70) >= 0x50){
2732         set_code_score(ptr, SCORE_L2);
2733     }
2734 }
2735
2736 static void
2737 status_disable(struct input_code *ptr)
2738 {
2739     ptr->stat = -1;
2740     ptr->buf[0] = -1;
2741     code_score(ptr);
2742     if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
2743 }
2744
2745 static void
2746 status_push_ch(struct input_code *ptr, nkf_char c)
2747 {
2748     ptr->buf[ptr->index++] = c;
2749 }
2750
2751 static void
2752 status_clear(struct input_code *ptr)
2753 {
2754     ptr->stat = 0;
2755     ptr->index = 0;
2756 }
2757
2758 static void
2759 status_reset(struct input_code *ptr)
2760 {
2761     status_clear(ptr);
2762     ptr->score = SCORE_INIT;
2763 }
2764
2765 static void
2766 status_reinit(struct input_code *ptr)
2767 {
2768     status_reset(ptr);
2769     ptr->_file_stat = 0;
2770 }
2771
2772 static void
2773 status_check(struct input_code *ptr, nkf_char c)
2774 {
2775     if (c <= DEL && estab_f){
2776         status_reset(ptr);
2777     }
2778 }
2779
2780 static void
2781 s_status(struct input_code *ptr, nkf_char c)
2782 {
2783     switch(ptr->stat){
2784     case -1:
2785         status_check(ptr, c);
2786         break;
2787     case 0:
2788         if (c <= DEL){
2789             break;
2790         }else if (nkf_char_unicode_p(c)){
2791             break;
2792         }else if (0xa1 <= c && c <= 0xdf){
2793             status_push_ch(ptr, SS2);
2794             status_push_ch(ptr, c);
2795             code_score(ptr);
2796             status_clear(ptr);
2797         }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xea)){
2798             ptr->stat = 1;
2799             status_push_ch(ptr, c);
2800         }else if (0xed <= c && c <= 0xee){
2801             ptr->stat = 3;
2802             status_push_ch(ptr, c);
2803 #ifdef SHIFTJIS_CP932
2804         }else if (is_ibmext_in_sjis(c)){
2805             ptr->stat = 2;
2806             status_push_ch(ptr, c);
2807 #endif /* SHIFTJIS_CP932 */
2808 #ifdef X0212_ENABLE
2809         }else if (0xf0 <= c && c <= 0xfc){
2810             ptr->stat = 1;
2811             status_push_ch(ptr, c);
2812 #endif /* X0212_ENABLE */
2813         }else{
2814             status_disable(ptr);
2815         }
2816         break;
2817     case 1:
2818         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
2819             status_push_ch(ptr, c);
2820             s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
2821             code_score(ptr);
2822             status_clear(ptr);
2823         }else{
2824             status_disable(ptr);
2825         }
2826         break;
2827     case 2:
2828 #ifdef SHIFTJIS_CP932
2829         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)) {
2830             status_push_ch(ptr, c);
2831             if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0) {
2832                 set_code_score(ptr, SCORE_CP932);
2833                 status_clear(ptr);
2834                 break;
2835             }
2836         }
2837 #endif /* SHIFTJIS_CP932 */
2838         status_disable(ptr);
2839         break;
2840     case 3:
2841         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
2842             status_push_ch(ptr, c);
2843             s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
2844             set_code_score(ptr, SCORE_CP932);
2845             status_clear(ptr);
2846         }else{
2847             status_disable(ptr);
2848         }
2849         break;
2850     }
2851 }
2852
2853 static void
2854 e_status(struct input_code *ptr, nkf_char c)
2855 {
2856     switch (ptr->stat){
2857     case -1:
2858         status_check(ptr, c);
2859         break;
2860     case 0:
2861         if (c <= DEL){
2862             break;
2863         }else if (nkf_char_unicode_p(c)){
2864             break;
2865         }else if (SS2 == c || (0xa1 <= c && c <= 0xfe)){
2866             ptr->stat = 1;
2867             status_push_ch(ptr, c);
2868 #ifdef X0212_ENABLE
2869         }else if (0x8f == c){
2870             ptr->stat = 2;
2871             status_push_ch(ptr, c);
2872 #endif /* X0212_ENABLE */
2873         }else{
2874             status_disable(ptr);
2875         }
2876         break;
2877     case 1:
2878         if (0xa1 <= c && c <= 0xfe){
2879             status_push_ch(ptr, c);
2880             code_score(ptr);
2881             status_clear(ptr);
2882         }else{
2883             status_disable(ptr);
2884         }
2885         break;
2886 #ifdef X0212_ENABLE
2887     case 2:
2888         if (0xa1 <= c && c <= 0xfe){
2889             ptr->stat = 1;
2890             status_push_ch(ptr, c);
2891         }else{
2892             status_disable(ptr);
2893         }
2894 #endif /* X0212_ENABLE */
2895     }
2896 }
2897
2898 #ifdef UTF8_INPUT_ENABLE
2899 static void
2900 w_status(struct input_code *ptr, nkf_char c)
2901 {
2902     switch (ptr->stat){
2903     case -1:
2904         status_check(ptr, c);
2905         break;
2906     case 0:
2907         if (c <= DEL){
2908             break;
2909         }else if (nkf_char_unicode_p(c)){
2910             break;
2911         }else if (0xc0 <= c && c <= 0xdf){
2912             ptr->stat = 1;
2913             status_push_ch(ptr, c);
2914         }else if (0xe0 <= c && c <= 0xef){
2915             ptr->stat = 2;
2916             status_push_ch(ptr, c);
2917         }else if (0xf0 <= c && c <= 0xf4){
2918             ptr->stat = 3;
2919             status_push_ch(ptr, c);
2920         }else{
2921             status_disable(ptr);
2922         }
2923         break;
2924     case 1:
2925     case 2:
2926         if (0x80 <= c && c <= 0xbf){
2927             status_push_ch(ptr, c);
2928             if (ptr->index > ptr->stat){
2929                 int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
2930                            && ptr->buf[2] == 0xbf);
2931                 w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
2932                          &ptr->buf[0], &ptr->buf[1]);
2933                 if (!bom){
2934                     code_score(ptr);
2935                 }
2936                 status_clear(ptr);
2937             }
2938         }else{
2939             status_disable(ptr);
2940         }
2941         break;
2942     case 3:
2943         if (0x80 <= c && c <= 0xbf){
2944             if (ptr->index < ptr->stat){
2945                 status_push_ch(ptr, c);
2946             } else {
2947                 status_clear(ptr);
2948             }
2949         }else{
2950             status_disable(ptr);
2951         }
2952         break;
2953     }
2954 }
2955 #endif
2956
2957 static void
2958 code_status(nkf_char c)
2959 {
2960     int action_flag = 1;
2961     struct input_code *result = 0;
2962     struct input_code *p = input_code_list;
2963     while (p->name){
2964         if (!p->status_func) {
2965             ++p;
2966             continue;
2967         }
2968         if (!p->status_func)
2969             continue;
2970         (p->status_func)(p, c);
2971         if (p->stat > 0){
2972             action_flag = 0;
2973         }else if(p->stat == 0){
2974             if (result){
2975                 action_flag = 0;
2976             }else{
2977                 result = p;
2978             }
2979         }
2980         ++p;
2981     }
2982
2983     if (action_flag){
2984         if (result && !estab_f){
2985             set_iconv(TRUE, result->iconv_func);
2986         }else if (c <= DEL){
2987             struct input_code *ptr = input_code_list;
2988             while (ptr->name){
2989                 status_reset(ptr);
2990                 ++ptr;
2991             }
2992         }
2993     }
2994 }
2995
2996 typedef struct {
2997     nkf_buf_t *std_gc_buf;
2998     nkf_char broken_state;
2999     nkf_buf_t *broken_buf;
3000     nkf_char mimeout_state;
3001     nkf_buf_t *nfc_buf;
3002 } nkf_state_t;
3003
3004 static nkf_state_t *nkf_state = NULL;
3005
3006 #define STD_GC_BUFSIZE (256)
3007
3008 static void
3009 nkf_state_init(void)
3010 {
3011     if (nkf_state) {
3012         nkf_buf_clear(nkf_state->std_gc_buf);
3013         nkf_buf_clear(nkf_state->broken_buf);
3014         nkf_buf_clear(nkf_state->nfc_buf);
3015     }
3016     else {
3017         nkf_state = nkf_xmalloc(sizeof(nkf_state_t));
3018         nkf_state->std_gc_buf = nkf_buf_new(STD_GC_BUFSIZE);
3019         nkf_state->broken_buf = nkf_buf_new(3);
3020         nkf_state->nfc_buf = nkf_buf_new(9);
3021     }
3022     nkf_state->broken_state = 0;
3023     nkf_state->mimeout_state = 0;
3024 }
3025
3026 #ifndef WIN32DLL
3027 static nkf_char
3028 std_getc(FILE *f)
3029 {
3030     if (!nkf_buf_empty_p(nkf_state->std_gc_buf)){
3031         return nkf_buf_pop(nkf_state->std_gc_buf);
3032     }
3033     return getc(f);
3034 }
3035 #endif /*WIN32DLL*/
3036
3037 static nkf_char
3038 std_ungetc(nkf_char c, FILE *f)
3039 {
3040     nkf_buf_push(nkf_state->std_gc_buf, c);
3041     return c;
3042 }
3043
3044 #ifndef WIN32DLL
3045 static void
3046 std_putc(nkf_char c)
3047 {
3048     if(c!=EOF)
3049         putchar(c);
3050 }
3051 #endif /*WIN32DLL*/
3052
3053 static unsigned char   hold_buf[HOLD_SIZE*2];
3054 static int             hold_count = 0;
3055 static nkf_char
3056 push_hold_buf(nkf_char c2)
3057 {
3058     if (hold_count >= HOLD_SIZE*2)
3059         return (EOF);
3060     hold_buf[hold_count++] = (unsigned char)c2;
3061     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
3062 }
3063
3064 static int
3065 h_conv(FILE *f, int c1, int c2)
3066 {
3067     int ret, c4, c3;
3068     int hold_index;
3069
3070
3071     /** it must NOT be in the kanji shifte sequence      */
3072     /** it must NOT be written in JIS7                   */
3073     /** and it must be after 2 byte 8bit code            */
3074
3075     hold_count = 0;
3076     push_hold_buf(c1);
3077     push_hold_buf(c2);
3078
3079     while ((c2 = (*i_getc)(f)) != EOF) {
3080         if (c2 == ESC){
3081             (*i_ungetc)(c2,f);
3082             break;
3083         }
3084         code_status(c2);
3085         if (push_hold_buf(c2) == EOF || estab_f) {
3086             break;
3087         }
3088     }
3089
3090     if (!estab_f) {
3091         struct input_code *p = input_code_list;
3092         struct input_code *result = p;
3093         if (c2 == EOF) {
3094             code_status(c2);
3095         }
3096         while (p->name) {
3097             if (p->status_func && p->score < result->score) {
3098                 result = p;
3099             }
3100             p++;
3101         }
3102         set_iconv(TRUE, result->iconv_func);
3103     }
3104
3105
3106     /** now,
3107      ** 1) EOF is detected, or
3108      ** 2) Code is established, or
3109      ** 3) Buffer is FULL (but last word is pushed)
3110      **
3111      ** in 1) and 3) cases, we continue to use
3112      ** Kanji codes by oconv and leave estab_f unchanged.
3113      **/
3114
3115     ret = c2;
3116     hold_index = 0;
3117     while (hold_index < hold_count){
3118         c1 = hold_buf[hold_index++];
3119         if (c1 <= DEL){
3120             (*iconv)(0, c1, 0);
3121             continue;
3122         }else if (iconv == s_iconv && 0xa1 <= c1 && c1 <= 0xdf){
3123             (*iconv)(JIS_X_0201_1976_K, c1, 0);
3124             continue;
3125         }
3126         if (hold_index < hold_count){
3127             c2 = hold_buf[hold_index++];
3128         }else{
3129             c2 = (*i_getc)(f);
3130             if (c2 == EOF){
3131                 c4 = EOF;
3132                 break;
3133             }
3134             code_status(c2);
3135         }
3136         c3 = 0;
3137         switch ((*iconv)(c1, c2, 0)) {  /* can be EUC/SJIS/UTF-8 */
3138         case -2:
3139             /* 4 bytes UTF-8 */
3140             if (hold_index < hold_count){
3141                 c3 = hold_buf[hold_index++];
3142             } else if ((c3 = (*i_getc)(f)) == EOF) {
3143                 ret = EOF;
3144                 break;
3145             }
3146             code_status(c3);
3147             if (hold_index < hold_count){
3148                 c4 = hold_buf[hold_index++];
3149             } else if ((c4 = (*i_getc)(f)) == EOF) {
3150                 c3 = ret = EOF;
3151                 break;
3152             }
3153             code_status(c4);
3154             (*iconv)(c1, c2, (c3<<8)|c4);
3155             break;
3156         case -1:
3157             /* 3 bytes EUC or UTF-8 */
3158             if (hold_index < hold_count){
3159                 c3 = hold_buf[hold_index++];
3160             } else if ((c3 = (*i_getc)(f)) == EOF) {
3161                 ret = EOF;
3162                 break;
3163             } else {
3164                 code_status(c3);
3165             }
3166             (*iconv)(c1, c2, c3);
3167             break;
3168         }
3169         if (c3 == EOF) break;
3170     }
3171     return ret;
3172 }
3173
3174 /*
3175  * Check and Ignore BOM
3176  */
3177 static void
3178 check_bom(FILE *f)
3179 {
3180     int c2;
3181     switch(c2 = (*i_getc)(f)){
3182     case 0x00:
3183         if((c2 = (*i_getc)(f)) == 0x00){
3184             if((c2 = (*i_getc)(f)) == 0xFE){
3185                 if((c2 = (*i_getc)(f)) == 0xFF){
3186                     if(!input_encoding){
3187                         set_iconv(TRUE, w_iconv32);
3188                     }
3189                     if (iconv == w_iconv32) {
3190                         input_endian = ENDIAN_BIG;
3191                         return;
3192                     }
3193                     (*i_ungetc)(0xFF,f);
3194                 }else (*i_ungetc)(c2,f);
3195                 (*i_ungetc)(0xFE,f);
3196             }else if(c2 == 0xFF){
3197                 if((c2 = (*i_getc)(f)) == 0xFE){
3198                     if(!input_encoding){
3199                         set_iconv(TRUE, w_iconv32);
3200                     }
3201                     if (iconv == w_iconv32) {
3202                         input_endian = ENDIAN_2143;
3203                         return;
3204                     }
3205                     (*i_ungetc)(0xFF,f);
3206                 }else (*i_ungetc)(c2,f);
3207                 (*i_ungetc)(0xFF,f);
3208             }else (*i_ungetc)(c2,f);
3209             (*i_ungetc)(0x00,f);
3210         }else (*i_ungetc)(c2,f);
3211         (*i_ungetc)(0x00,f);
3212         break;
3213     case 0xEF:
3214         if((c2 = (*i_getc)(f)) == 0xBB){
3215             if((c2 = (*i_getc)(f)) == 0xBF){
3216                 if(!input_encoding){
3217                     set_iconv(TRUE, w_iconv);
3218                 }
3219                 if (iconv == w_iconv) {
3220                     return;
3221                 }
3222                 (*i_ungetc)(0xBF,f);
3223             }else (*i_ungetc)(c2,f);
3224             (*i_ungetc)(0xBB,f);
3225         }else (*i_ungetc)(c2,f);
3226         (*i_ungetc)(0xEF,f);
3227         break;
3228     case 0xFE:
3229         if((c2 = (*i_getc)(f)) == 0xFF){
3230             if((c2 = (*i_getc)(f)) == 0x00){
3231                 if((c2 = (*i_getc)(f)) == 0x00){
3232                     if(!input_encoding){
3233                         set_iconv(TRUE, w_iconv32);
3234                     }
3235                     if (iconv == w_iconv32) {
3236                         input_endian = ENDIAN_3412;
3237                         return;
3238                     }
3239                     (*i_ungetc)(0x00,f);
3240                 }else (*i_ungetc)(c2,f);
3241                 (*i_ungetc)(0x00,f);
3242             }else (*i_ungetc)(c2,f);
3243             if(!input_encoding){
3244                 set_iconv(TRUE, w_iconv16);
3245             }
3246             if (iconv == w_iconv16) {
3247                 input_endian = ENDIAN_BIG;
3248                 return;
3249             }
3250             (*i_ungetc)(0xFF,f);
3251         }else (*i_ungetc)(c2,f);
3252         (*i_ungetc)(0xFE,f);
3253         break;
3254     case 0xFF:
3255         if((c2 = (*i_getc)(f)) == 0xFE){
3256             if((c2 = (*i_getc)(f)) == 0x00){
3257                 if((c2 = (*i_getc)(f)) == 0x00){
3258                     if(!input_encoding){
3259                         set_iconv(TRUE, w_iconv32);
3260                     }
3261                     if (iconv == w_iconv32) {
3262                         input_endian = ENDIAN_LITTLE;
3263                         return;
3264                     }
3265                     (*i_ungetc)(0x00,f);
3266                 }else (*i_ungetc)(c2,f);
3267                 (*i_ungetc)(0x00,f);
3268             }else (*i_ungetc)(c2,f);
3269             if(!input_encoding){
3270                 set_iconv(TRUE, w_iconv16);
3271             }
3272             if (iconv == w_iconv16) {
3273                 input_endian = ENDIAN_LITTLE;
3274                 return;
3275             }
3276             (*i_ungetc)(0xFE,f);
3277         }else (*i_ungetc)(c2,f);
3278         (*i_ungetc)(0xFF,f);
3279         break;
3280     default:
3281         (*i_ungetc)(c2,f);
3282         break;
3283     }
3284 }
3285
3286 static nkf_char
3287 broken_getc(FILE *f)
3288 {
3289     nkf_char c, c1;
3290
3291     if (!nkf_buf_empty_p(nkf_state->broken_buf)) {
3292         return nkf_buf_pop(nkf_state->broken_buf);
3293     }
3294     c = (*i_bgetc)(f);
3295     if (c=='$' && nkf_state->broken_state != ESC
3296         && (input_mode == ASCII || input_mode == JIS_X_0201_1976_K)) {
3297         c1= (*i_bgetc)(f);
3298         nkf_state->broken_state = 0;
3299         if (c1=='@'|| c1=='B') {
3300             nkf_buf_push(nkf_state->broken_buf, c1);
3301             nkf_buf_push(nkf_state->broken_buf, c);
3302             return ESC;
3303         } else {
3304             (*i_bungetc)(c1,f);
3305             return c;
3306         }
3307     } else if (c=='(' && nkf_state->broken_state != ESC
3308                && (input_mode == JIS_X_0208 || input_mode == JIS_X_0201_1976_K)) {
3309         c1= (*i_bgetc)(f);
3310         nkf_state->broken_state = 0;
3311         if (c1=='J'|| c1=='B') {
3312             nkf_buf_push(nkf_state->broken_buf, c1);
3313             nkf_buf_push(nkf_state->broken_buf, c);
3314             return ESC;
3315         } else {
3316             (*i_bungetc)(c1,f);
3317             return c;
3318         }
3319     } else {
3320         nkf_state->broken_state = c;
3321         return c;
3322     }
3323 }
3324
3325 static nkf_char
3326 broken_ungetc(nkf_char c, FILE *f)
3327 {
3328     if (nkf_buf_length(nkf_state->broken_buf) < 2)
3329         nkf_buf_push(nkf_state->broken_buf, c);
3330     return c;
3331 }
3332
3333 static void
3334 eol_conv(nkf_char c2, nkf_char c1)
3335 {
3336     if (guess_f && input_eol != EOF) {
3337         if (c2 == 0 && c1 == LF) {
3338             if (!input_eol) input_eol = prev_cr ? CRLF : LF;
3339             else if (input_eol != (prev_cr ? CRLF : LF)) input_eol = EOF;
3340         } else if (c2 == 0 && c1 == CR && input_eol == LF) input_eol = EOF;
3341         else if (!prev_cr);
3342         else if (!input_eol) input_eol = CR;
3343         else if (input_eol != CR) input_eol = EOF;
3344     }
3345     if (prev_cr || (c2 == 0 && c1 == LF)) {
3346         prev_cr = 0;
3347         if (eolmode_f != LF) (*o_eol_conv)(0, CR);
3348         if (eolmode_f != CR) (*o_eol_conv)(0, LF);
3349     }
3350     if (c2 == 0 && c1 == CR) prev_cr = CR;
3351     else if (c2 != 0 || c1 != LF) (*o_eol_conv)(c2, c1);
3352 }
3353
3354 /*
3355    Return value of fold_conv()
3356
3357    LF  add newline  and output char
3358    CR  add newline  and output nothing
3359    SP  space
3360    0   skip
3361    1   (or else) normal output
3362
3363    fold state in prev (previous character)
3364
3365    >0x80 Japanese (X0208/X0201)
3366    <0x80 ASCII
3367    LF    new line
3368    SP    space
3369
3370    This fold algorthm does not preserve heading space in a line.
3371    This is the main difference from fmt.
3372  */
3373
3374 #define char_size(c2,c1) (c2?2:1)
3375
3376 static void
3377 fold_conv(nkf_char c2, nkf_char c1)
3378 {
3379     nkf_char prev0;
3380     nkf_char fold_state;
3381
3382     if (c1== CR && !fold_preserve_f) {
3383         fold_state=0;  /* ignore cr */
3384     }else if (c1== LF&&f_prev==CR && fold_preserve_f) {
3385         f_prev = LF;
3386         fold_state=0;  /* ignore cr */
3387     } else if (c1== BS) {
3388         if (f_line>0) f_line--;
3389         fold_state =  1;
3390     } else if (c2==EOF && f_line != 0) {    /* close open last line */
3391         fold_state = LF;
3392     } else if ((c1==LF && !fold_preserve_f)
3393                || ((c1==CR||(c1==LF&&f_prev!=CR))
3394                    && fold_preserve_f)) {
3395         /* new line */
3396         if (fold_preserve_f) {
3397             f_prev = c1;
3398             f_line = 0;
3399             fold_state =  CR;
3400         } else if ((f_prev == c1 && !fold_preserve_f)
3401                    || (f_prev == LF && fold_preserve_f)
3402                   ) {        /* duplicate newline */
3403             if (f_line) {
3404                 f_line = 0;
3405                 fold_state =  LF;    /* output two newline */
3406             } else {
3407                 f_line = 0;
3408                 fold_state =  1;
3409             }
3410         } else  {
3411             if (f_prev&0x80) {     /* Japanese? */
3412                 f_prev = c1;
3413                 fold_state =  0;       /* ignore given single newline */
3414             } else if (f_prev==SP) {
3415                 fold_state =  0;
3416             } else {
3417                 f_prev = c1;
3418                 if (++f_line<=fold_len)
3419                     fold_state =  SP;
3420                 else {
3421                     f_line = 0;
3422                     fold_state =  CR;        /* fold and output nothing */
3423                 }
3424             }
3425         }
3426     } else if (c1=='\f') {
3427         f_prev = LF;
3428         f_line = 0;
3429         fold_state =  LF;            /* output newline and clear */
3430     } else if ((c2==0 && nkf_isblank(c1)) || (c2 == '!' && c1 == '!')) {
3431         /* X0208 kankaku or ascii space */
3432         if (f_prev == SP) {
3433             fold_state = 0;         /* remove duplicate spaces */
3434         } else {
3435             f_prev = SP;
3436             if (++f_line<=fold_len)
3437                 fold_state = SP;         /* output ASCII space only */
3438             else {
3439                 f_prev = SP; f_line = 0;
3440                 fold_state = CR;        /* fold and output nothing */
3441             }
3442         }
3443     } else {
3444         prev0 = f_prev; /* we still need this one... , but almost done */
3445         f_prev = c1;
3446         if (c2 || c2 == JIS_X_0201_1976_K)
3447             f_prev |= 0x80;  /* this is Japanese */
3448         f_line += char_size(c2,c1);
3449         if (f_line<=fold_len) {   /* normal case */
3450             fold_state = 1;
3451         } else {
3452             if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
3453                 f_line = char_size(c2,c1);
3454                 fold_state =  LF;       /* We can't wait, do fold now */
3455             } else if (c2 == JIS_X_0201_1976_K) {
3456                 /* simple kinsoku rules  return 1 means no folding  */
3457                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
3458                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
3459                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
3460                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
3461                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
3462                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
3463                 else if (SP<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
3464                     f_line = 1;
3465                     fold_state = LF;/* add one new f_line before this character */
3466                 } else {
3467                     f_line = 1;
3468                     fold_state = LF;/* add one new f_line before this character */
3469                 }
3470             } else if (c2==0) {
3471                 /* kinsoku point in ASCII */
3472                 if (  c1==')'||    /* { [ ( */
3473                     c1==']'||
3474                     c1=='}'||
3475                     c1=='.'||
3476                     c1==','||
3477                     c1=='!'||
3478                     c1=='?'||
3479                     c1=='/'||
3480                     c1==':'||
3481                     c1==';') {
3482                     fold_state = 1;
3483                     /* just after special */
3484                 } else if (!is_alnum(prev0)) {
3485                     f_line = char_size(c2,c1);
3486                     fold_state = LF;
3487                 } else if ((prev0==SP) ||   /* ignored new f_line */
3488                            (prev0==LF)||        /* ignored new f_line */
3489                            (prev0&0x80)) {        /* X0208 - ASCII */
3490                     f_line = char_size(c2,c1);
3491                     fold_state = LF;/* add one new f_line before this character */
3492                 } else {
3493                     fold_state = 1;  /* default no fold in ASCII */
3494                 }
3495             } else {
3496                 if (c2=='!') {
3497                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
3498                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
3499                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
3500                     else if (c1=='K')  fold_state = 1; /* \e$B!K\e(B */
3501                     else if (c1=='$')  fold_state = 1; /* \e$B!$\e(B */
3502                     else if (c1=='%')  fold_state = 1; /* \e$B!%\e(B */
3503                     else if (c1=='\'') fold_state = 1; /* \e$B!\\e(B */
3504                     else if (c1=='(')  fold_state = 1; /* \e$B!(\e(B */
3505                     else if (c1==')')  fold_state = 1; /* \e$B!)\e(B */
3506                     else if (c1=='*')  fold_state = 1; /* \e$B!*\e(B */
3507                     else if (c1=='+')  fold_state = 1; /* \e$B!+\e(B */
3508                     else if (c1==',')  fold_state = 1; /* \e$B!,\e(B */
3509                     /* default no fold in kinsoku */
3510                     else {
3511                         fold_state = LF;
3512                         f_line = char_size(c2,c1);
3513                         /* add one new f_line before this character */
3514                     }
3515                 } else {
3516                     f_line = char_size(c2,c1);
3517                     fold_state = LF;
3518                     /* add one new f_line before this character */
3519                 }
3520             }
3521         }
3522     }
3523     /* terminator process */
3524     switch(fold_state) {
3525     case LF:
3526         OCONV_NEWLINE((*o_fconv));
3527         (*o_fconv)(c2,c1);
3528         break;
3529     case 0:
3530         return;
3531     case CR:
3532         OCONV_NEWLINE((*o_fconv));
3533         break;
3534     case TAB:
3535     case SP:
3536         (*o_fconv)(0,SP);
3537         break;
3538     default:
3539         (*o_fconv)(c2,c1);
3540     }
3541 }
3542
3543 static nkf_char z_prev2=0,z_prev1=0;
3544
3545 static void
3546 z_conv(nkf_char c2, nkf_char c1)
3547 {
3548
3549     /* if (c2) c1 &= 0x7f; assertion */
3550
3551     if (c2 == JIS_X_0201_1976_K && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) {
3552         (*o_zconv)(c2,c1);
3553         return;
3554     }
3555
3556     if (x0201_f) {
3557         if (z_prev2 == JIS_X_0201_1976_K) {
3558             if (c2 == JIS_X_0201_1976_K) {
3559                 if (c1 == (0xde&0x7f)) { /* \e$BByE@\e(B */
3560                     z_prev2 = 0;
3561                     (*o_zconv)(dv[(z_prev1-SP)*2], dv[(z_prev1-SP)*2+1]);
3562                     return;
3563                 } else if (c1 == (0xdf&0x7f) && ev[(z_prev1-SP)*2]) {  /* \e$BH>ByE@\e(B */
3564                     z_prev2 = 0;
3565                     (*o_zconv)(ev[(z_prev1-SP)*2], ev[(z_prev1-SP)*2+1]);
3566                     return;
3567                 }
3568             }
3569             z_prev2 = 0;
3570             (*o_zconv)(cv[(z_prev1-SP)*2], cv[(z_prev1-SP)*2+1]);
3571         }
3572         if (c2 == JIS_X_0201_1976_K) {
3573             if (dv[(c1-SP)*2] || ev[(c1-SP)*2]) {
3574                 /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
3575                 z_prev1 = c1;
3576                 z_prev2 = c2;
3577                 return;
3578             } else {
3579                 (*o_zconv)(cv[(c1-SP)*2], cv[(c1-SP)*2+1]);
3580                 return;
3581             }
3582         }
3583     }
3584
3585     if (c2 == EOF) {
3586         (*o_zconv)(c2, c1);
3587         return;
3588     }
3589
3590     if (alpha_f&1 && c2 == 0x23) {
3591         /* JISX0208 Alphabet */
3592         c2 = 0;
3593     } else if (c2 == 0x21) {
3594         /* JISX0208 Kigou */
3595         if (0x21==c1) {
3596             if (alpha_f&2) {
3597                 c2 = 0;
3598                 c1 = SP;
3599             } else if (alpha_f&4) {
3600                 (*o_zconv)(0, SP);
3601                 (*o_zconv)(0, SP);
3602                 return;
3603             }
3604         } else if (alpha_f&1 && 0x20<c1 && c1<0x7f && fv[c1-0x20]) {
3605             c2 =  0;
3606             c1 = fv[c1-0x20];
3607         }
3608     }
3609
3610     if (alpha_f&8 && c2 == 0) {
3611         /* HTML Entity */
3612         const char *entity = 0;
3613         switch (c1){
3614         case '>': entity = "&gt;"; break;
3615         case '<': entity = "&lt;"; break;
3616         case '\"': entity = "&quot;"; break;
3617         case '&': entity = "&amp;"; break;
3618         }
3619         if (entity){
3620             while (*entity) (*o_zconv)(0, *entity++);
3621             return;
3622         }
3623     }
3624
3625     if (alpha_f & 16) {
3626         /* JIS X 0208 Katakana to JIS X 0201 Katakana */
3627         if (c2 == 0x21) {
3628             nkf_char c = 0;
3629             switch (c1) {
3630             case 0x23:
3631                 /* U+3002 (0x8142) Ideographic Full Stop -> U+FF61 (0xA1) Halfwidth Ideographic Full Stop */
3632                 c = 0xA1;
3633                 break;
3634             case 0x56:
3635                 /* U+300C (0x8175) Left Corner Bracket -> U+FF62 (0xA2) Halfwidth Left Corner Bracket */
3636                 c = 0xA2;
3637                 break;
3638             case 0x57:
3639                 /* U+300D (0x8176) Right Corner Bracket -> U+FF63 (0xA3) Halfwidth Right Corner Bracket */
3640                 c = 0xA3;
3641                 break;
3642             case 0x22:
3643                 /* U+3001 (0x8141) Ideographic Comma -> U+FF64 (0xA4) Halfwidth Ideographic Comma */
3644                 c = 0xA4;
3645                 break;
3646             case 0x26:
3647                 /* U+30FB (0x8145) Katakana Middle Dot -> U+FF65 (0xA5) Halfwidth Katakana Middle Dot */
3648                 c = 0xA5;
3649                 break;
3650             case 0x3C:
3651                 /* U+30FC (0x815B) Katakana-Hiragana Prolonged Sound Mark -> U+FF70 (0xB0) Halfwidth Katakana-Hiragana Prolonged Sound Mark */
3652                 c = 0xB0;
3653                 break;
3654             case 0x2B:
3655                 /* U+309B (0x814A) Katakana-Hiragana Voiced Sound Mark -> U+FF9E (0xDE) Halfwidth Katakana Voiced Sound Mark */
3656                 c = 0xDE;
3657                 break;
3658             case 0x2C:
3659                 /* U+309C (0x814B) Katakana-Hiragana Semi-Voiced Sound Mark -> U+FF9F (0xDF) Halfwidth Katakana Semi-Voiced Sound Mark */
3660                 c = 0xDF;
3661                 break;
3662             }
3663             if (c) {
3664                 (*o_zconv)(JIS_X_0201_1976_K, c);
3665                 return;
3666             }
3667         } else if (c2 == 0x25) {
3668             /* JISX0208 Katakana */
3669             static const int fullwidth_to_halfwidth[] =
3670             {
3671                 0x0000, 0x2700, 0x3100, 0x2800, 0x3200, 0x2900, 0x3300, 0x2A00,
3672                 0x3400, 0x2B00, 0x3500, 0x3600, 0x365E, 0x3700, 0x375E, 0x3800,
3673                 0x385E, 0x3900, 0x395E, 0x3A00, 0x3A5E, 0x3B00, 0x3B5E, 0x3C00,
3674                 0x3C5E, 0x3D00, 0x3D5E, 0x3E00, 0x3E5E, 0x3F00, 0x3F5E, 0x4000,
3675                 0x405E, 0x4100, 0x415E, 0x2F00, 0x4200, 0x425E, 0x4300, 0x435E,
3676                 0x4400, 0x445E, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00,
3677                 0x4A5E, 0x4A5F, 0x4B00, 0x4B5E, 0x4B5F, 0x4C00, 0x4C5E, 0x4C5F,
3678                 0x4D00, 0x4D5E, 0x4D5F, 0x4E00, 0x4E5E, 0x4E5F, 0x4F00, 0x5000,
3679                 0x5100, 0x5200, 0x5300, 0x2C00, 0x5400, 0x2D00, 0x5500, 0x2E00,
3680                 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x0000, 0x5C00,
3681                 0x0000, 0x0000, 0x2600, 0x5D00, 0x335E, 0x0000, 0x0000, 0x0000,
3682                 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
3683             };
3684             if (fullwidth_to_halfwidth[c1-0x20]){
3685                 c2 = fullwidth_to_halfwidth[c1-0x20];
3686                 (*o_zconv)(JIS_X_0201_1976_K, c2>>8);
3687                 if (c2 & 0xFF) {
3688                     (*o_zconv)(JIS_X_0201_1976_K, c2&0xFF);
3689                 }
3690                 return;
3691             }
3692         }
3693     }
3694     (*o_zconv)(c2,c1);
3695 }
3696
3697
3698 #define rot13(c)  ( \
3699                    ( c < 'A') ? c: \
3700                    (c <= 'M')  ? (c + 13): \
3701                    (c <= 'Z')  ? (c - 13): \
3702                    (c < 'a')   ? (c): \
3703                    (c <= 'm')  ? (c + 13): \
3704                    (c <= 'z')  ? (c - 13): \
3705                    (c) \
3706                   )
3707
3708 #define  rot47(c) ( \
3709                    ( c < '!') ? c: \
3710                    ( c <= 'O') ? (c + 47) : \
3711                    ( c <= '~') ?  (c - 47) : \
3712                    c \
3713                   )
3714
3715 static void
3716 rot_conv(nkf_char c2, nkf_char c1)
3717 {
3718     if (c2 == 0 || c2 == JIS_X_0201_1976_K || c2 == ISO_8859_1) {
3719         c1 = rot13(c1);
3720     } else if (c2) {
3721         c1 = rot47(c1);
3722         c2 = rot47(c2);
3723     }
3724     (*o_rot_conv)(c2,c1);
3725 }
3726
3727 static void
3728 hira_conv(nkf_char c2, nkf_char c1)
3729 {
3730     if (hira_f & 1) {
3731         if (c2 == 0x25) {
3732             if (0x20 < c1 && c1 < 0x74) {
3733                 c2 = 0x24;
3734                 (*o_hira_conv)(c2,c1);
3735                 return;
3736             } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) {
3737                 c2 = 0;
3738                 c1 = nkf_char_unicode_new(0x3094);
3739                 (*o_hira_conv)(c2,c1);
3740                 return;
3741             }
3742         } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
3743             c1 += 2;
3744             (*o_hira_conv)(c2,c1);
3745             return;
3746         }
3747     }
3748     if (hira_f & 2) {
3749         if (c2 == 0 && c1 == nkf_char_unicode_new(0x3094)) {
3750             c2 = 0x25;
3751             c1 = 0x74;
3752         } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
3753             c2 = 0x25;
3754         } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
3755             c1 -= 2;
3756         }
3757     }
3758     (*o_hira_conv)(c2,c1);
3759 }
3760
3761
3762 static void
3763 iso2022jp_check_conv(nkf_char c2, nkf_char c1)
3764 {
3765 #define RANGE_NUM_MAX 18
3766     static const nkf_char range[RANGE_NUM_MAX][2] = {
3767         {0x222f, 0x2239,},
3768         {0x2242, 0x2249,},
3769         {0x2251, 0x225b,},
3770         {0x226b, 0x2271,},
3771         {0x227a, 0x227d,},
3772         {0x2321, 0x232f,},
3773         {0x233a, 0x2340,},
3774         {0x235b, 0x2360,},
3775         {0x237b, 0x237e,},
3776         {0x2474, 0x247e,},
3777         {0x2577, 0x257e,},
3778         {0x2639, 0x2640,},
3779         {0x2659, 0x267e,},
3780         {0x2742, 0x2750,},
3781         {0x2772, 0x277e,},
3782         {0x2841, 0x287e,},
3783         {0x4f54, 0x4f7e,},
3784         {0x7425, 0x747e},
3785     };
3786     nkf_char i;
3787     nkf_char start, end, c;
3788
3789     if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
3790         c2 = GETA1;
3791         c1 = GETA2;
3792     }
3793     if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
3794         c2 = GETA1;
3795         c1 = GETA2;
3796     }
3797
3798     for (i = 0; i < RANGE_NUM_MAX; i++) {
3799         start = range[i][0];
3800         end   = range[i][1];
3801         c     = (c2 << 8) + c1;
3802         if (c >= start && c <= end) {
3803             c2 = GETA1;
3804             c1 = GETA2;
3805         }
3806     }
3807     (*o_iso2022jp_check_conv)(c2,c1);
3808 }
3809
3810
3811 /* This converts  =?ISO-2022-JP?B?HOGE HOGE?= */
3812
3813 static const unsigned char *mime_pattern[] = {
3814     (const unsigned char *)"\075?EUC-JP?B?",
3815     (const unsigned char *)"\075?SHIFT_JIS?B?",
3816     (const unsigned char *)"\075?ISO-8859-1?Q?",
3817     (const unsigned char *)"\075?ISO-8859-1?B?",
3818     (const unsigned char *)"\075?ISO-2022-JP?B?",
3819     (const unsigned char *)"\075?ISO-2022-JP?Q?",
3820 #if defined(UTF8_INPUT_ENABLE)
3821     (const unsigned char *)"\075?UTF-8?B?",
3822     (const unsigned char *)"\075?UTF-8?Q?",
3823 #endif
3824     (const unsigned char *)"\075?US-ASCII?Q?",
3825     NULL
3826 };
3827
3828
3829 /* \e$B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u\e(B */
3830 nkf_char (*mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
3831     e_iconv, s_iconv, 0, 0, 0, 0,
3832 #if defined(UTF8_INPUT_ENABLE)
3833     w_iconv, w_iconv,
3834 #endif
3835     0,
3836 };
3837
3838 static const nkf_char mime_encode[] = {
3839     EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201_1976_K,
3840 #if defined(UTF8_INPUT_ENABLE)
3841     UTF_8, UTF_8,
3842 #endif
3843     ASCII,
3844     0
3845 };
3846
3847 static const nkf_char mime_encode_method[] = {
3848     'B', 'B','Q', 'B', 'B', 'Q',
3849 #if defined(UTF8_INPUT_ENABLE)
3850     'B', 'Q',
3851 #endif
3852     'Q',
3853     0
3854 };
3855
3856
3857 /* MIME preprocessor fifo */
3858
3859 #define MIME_BUF_SIZE   (1024)    /* 2^n ring buffer */
3860 #define MIME_BUF_MASK   (MIME_BUF_SIZE-1)
3861 #define mime_input_buf(n)        mime_input_state.buf[(n)&MIME_BUF_MASK]
3862 static struct {
3863     unsigned char buf[MIME_BUF_SIZE];
3864     unsigned int  top;
3865     unsigned int  last;  /* decoded */
3866     unsigned int  input; /* undecoded */
3867 } mime_input_state;
3868 static nkf_char (*mime_iconv_back)(nkf_char c2,nkf_char c1,nkf_char c0) = NULL;
3869
3870 #define MAXRECOVER 20
3871
3872 static void
3873 mime_input_buf_unshift(nkf_char c)
3874 {
3875     mime_input_buf(--mime_input_state.top) = (unsigned char)c;
3876 }
3877
3878 static nkf_char
3879 mime_ungetc(nkf_char c, FILE *f)
3880 {
3881     mime_input_buf_unshift(c);
3882     return c;
3883 }
3884
3885 static nkf_char
3886 mime_ungetc_buf(nkf_char c, FILE *f)
3887 {
3888     if (mimebuf_f)
3889         (*i_mungetc_buf)(c,f);
3890     else
3891         mime_input_buf(--mime_input_state.input) = (unsigned char)c;
3892     return c;
3893 }
3894
3895 static nkf_char
3896 mime_getc_buf(FILE *f)
3897 {
3898     /* we don't keep eof of mime_input_buf, becase it contains ?= as
3899        a terminator. It was checked in mime_integrity. */
3900     return ((mimebuf_f)?
3901             (*i_mgetc_buf)(f):mime_input_buf(mime_input_state.input++));
3902 }
3903
3904 static void
3905 switch_mime_getc(void)
3906 {
3907     if (i_getc!=mime_getc) {
3908         i_mgetc = i_getc; i_getc = mime_getc;
3909         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
3910         if(mime_f==STRICT_MIME) {
3911             i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
3912             i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
3913         }
3914     }
3915 }
3916
3917 static void
3918 unswitch_mime_getc(void)
3919 {
3920     if(mime_f==STRICT_MIME) {
3921         i_mgetc = i_mgetc_buf;
3922         i_mungetc = i_mungetc_buf;
3923     }
3924     i_getc = i_mgetc;
3925     i_ungetc = i_mungetc;
3926     if(mime_iconv_back)set_iconv(FALSE, mime_iconv_back);
3927     mime_iconv_back = NULL;
3928 }
3929
3930 static nkf_char
3931 mime_integrity(FILE *f, const unsigned char *p)
3932 {
3933     nkf_char c,d;
3934     unsigned int q;
3935     /* In buffered mode, read until =? or NL or buffer full
3936      */
3937     mime_input_state.input = mime_input_state.top;
3938     mime_input_state.last = mime_input_state.top;
3939
3940     while(*p) mime_input_buf(mime_input_state.input++) = *p++;
3941     d = 0;
3942     q = mime_input_state.input;
3943     while((c=(*i_getc)(f))!=EOF) {
3944         if (((mime_input_state.input-mime_input_state.top)&MIME_BUF_MASK)==0) {
3945             break;   /* buffer full */
3946         }
3947         if (c=='=' && d=='?') {
3948             /* checked. skip header, start decode */
3949             mime_input_buf(mime_input_state.input++) = (unsigned char)c;
3950             /* mime_last_input = mime_input_state.input; */
3951             mime_input_state.input = q;
3952             switch_mime_getc();
3953             return 1;
3954         }
3955         if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
3956             break;
3957         /* Should we check length mod 4? */
3958         mime_input_buf(mime_input_state.input++) = (unsigned char)c;
3959         d=c;
3960     }
3961     /* In case of Incomplete MIME, no MIME decode  */
3962     mime_input_buf(mime_input_state.input++) = (unsigned char)c;
3963     mime_input_state.last = mime_input_state.input;     /* point undecoded buffer */
3964     mime_decode_mode = 1;              /* no decode on mime_input_buf last in mime_getc */
3965     switch_mime_getc();         /* anyway we need buffered getc */
3966     return 1;
3967 }
3968
3969 static nkf_char
3970 mime_begin_strict(FILE *f)
3971 {
3972     nkf_char c1 = 0;
3973     int i,j,k;
3974     const unsigned char *p,*q;
3975     nkf_char r[MAXRECOVER];    /* recovery buffer, max mime pattern length */
3976
3977     mime_decode_mode = FALSE;
3978     /* =? has been checked */
3979     j = 0;
3980     p = mime_pattern[j];
3981     r[0]='='; r[1]='?';
3982
3983     for(i=2;p[i]>SP;i++) {                   /* start at =? */
3984         if (((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i]) {
3985             /* pattern fails, try next one */
3986             q = p;
3987             while (mime_pattern[++j]) {
3988                 p = mime_pattern[j];
3989                 for(k=2;k<i;k++)              /* assume length(p) > i */
3990                     if (p[k]!=q[k]) break;
3991                 if (k==i && nkf_toupper(c1)==p[k]) break;
3992             }
3993             p = mime_pattern[j];
3994             if (p) continue;  /* found next one, continue */
3995             /* all fails, output from recovery buffer */
3996             (*i_ungetc)(c1,f);
3997             for(j=0;j<i;j++) {
3998                 (*oconv)(0,r[j]);
3999             }
4000             return c1;
4001         }
4002     }
4003     mime_decode_mode = p[i-2];
4004
4005     mime_iconv_back = iconv;
4006     set_iconv(FALSE, mime_priority_func[j]);
4007     clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
4008
4009     if (mime_decode_mode=='B') {
4010         mimebuf_f = unbuf_f;
4011         if (!unbuf_f) {
4012             /* do MIME integrity check */
4013             return mime_integrity(f,mime_pattern[j]);
4014         }
4015     }
4016     switch_mime_getc();
4017     mimebuf_f = TRUE;
4018     return c1;
4019 }
4020
4021 static nkf_char
4022 mime_begin(FILE *f)
4023 {
4024     nkf_char c1;
4025     int i,k;
4026
4027     /* In NONSTRICT mode, only =? is checked. In case of failure, we  */
4028     /* re-read and convert again from mime_buffer.  */
4029
4030     /* =? has been checked */
4031     k = mime_input_state.last;
4032     mime_input_buf(mime_input_state.last++)='='; mime_input_buf(mime_input_state.last++)='?';
4033     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
4034         /* We accept any character type even if it is breaked by new lines */
4035         c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
4036         if (c1==LF||c1==SP||c1==CR||
4037             c1=='-'||c1=='_'||is_alnum(c1)) continue;
4038         if (c1=='=') {
4039             /* Failed. But this could be another MIME preemble */
4040             (*i_ungetc)(c1,f);
4041             mime_input_state.last--;
4042             break;
4043         }
4044         if (c1!='?') break;
4045         else {
4046             /* c1=='?' */
4047             c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
4048             if (!(++i<MAXRECOVER) || c1==EOF) break;
4049             if (c1=='b'||c1=='B') {
4050                 mime_decode_mode = 'B';
4051             } else if (c1=='q'||c1=='Q') {
4052                 mime_decode_mode = 'Q';
4053             } else {
4054                 break;
4055             }
4056             c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
4057             if (!(++i<MAXRECOVER) || c1==EOF) break;
4058             if (c1!='?') {
4059                 mime_decode_mode = FALSE;
4060             }
4061             break;
4062         }
4063     }
4064     switch_mime_getc();
4065     if (!mime_decode_mode) {
4066         /* false MIME premble, restart from mime_buffer */
4067         mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
4068         /* Since we are in MIME mode until buffer becomes empty,    */
4069         /* we never go into mime_begin again for a while.           */
4070         return c1;
4071     }
4072     /* discard mime preemble, and goto MIME mode */
4073     mime_input_state.last = k;
4074     /* do no MIME integrity check */
4075     return c1;   /* used only for checking EOF */
4076 }
4077
4078 #ifdef CHECK_OPTION
4079 static void
4080 no_putc(nkf_char c)
4081 {
4082     ;
4083 }
4084
4085 static void
4086 debug(const char *str)
4087 {
4088     if (debug_f){
4089         fprintf(stderr, "%s\n", str ? str : "NULL");
4090     }
4091 }
4092 #endif
4093
4094 static void
4095 set_input_codename(const char *codename)
4096 {
4097     if (!input_codename) {
4098         input_codename = codename;
4099     } else if (strcmp(codename, input_codename) != 0) {
4100         input_codename = "";
4101     }
4102 }
4103
4104 static const char*
4105 get_guessed_code(void)
4106 {
4107     if (input_codename && !*input_codename) {
4108         input_codename = "BINARY";
4109     } else {
4110         struct input_code *p = find_inputcode_byfunc(iconv);
4111         if (!input_codename) {
4112             input_codename = "ASCII";
4113         } else if (strcmp(input_codename, "Shift_JIS") == 0) {
4114             if (p->score & (SCORE_DEPEND|SCORE_CP932))
4115                 input_codename = "CP932";
4116         } else if (strcmp(input_codename, "EUC-JP") == 0) {
4117             if (p->score & (SCORE_X0212))
4118                 input_codename = "EUCJP-MS";
4119             else if (p->score & (SCORE_DEPEND|SCORE_CP932))
4120                 input_codename = "CP51932";
4121         } else if (strcmp(input_codename, "ISO-2022-JP") == 0) {
4122             if (p->score & (SCORE_KANA))
4123                 input_codename = "CP50221";
4124             else if (p->score & (SCORE_DEPEND|SCORE_CP932))
4125                 input_codename = "CP50220";
4126         }
4127     }
4128     return input_codename;
4129 }
4130
4131 #if !defined(PERL_XS) && !defined(WIN32DLL)
4132 static void
4133 print_guessed_code(char *filename)
4134 {
4135     if (filename != NULL) printf("%s: ", filename);
4136     if (input_codename && !*input_codename) {
4137         printf("BINARY\n");
4138     } else {
4139         input_codename = get_guessed_code();
4140         if (guess_f == 1) {
4141             printf("%s\n", input_codename);
4142         } else {
4143             printf("%s%s\n",
4144                    input_codename,
4145                    input_eol == CR   ? " (CR)" :
4146                    input_eol == LF   ? " (LF)" :
4147                    input_eol == CRLF ? " (CRLF)" :
4148                    input_eol == EOF  ? " (MIXED NL)" :
4149                    "");
4150         }
4151     }
4152 }
4153 #endif /*WIN32DLL*/
4154
4155 #ifdef INPUT_OPTION
4156
4157 static nkf_char
4158 hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f))
4159 {
4160     nkf_char c1, c2, c3;
4161     c1 = (*g)(f);
4162     if (c1 != ch){
4163         return c1;
4164     }
4165     c2 = (*g)(f);
4166     if (!nkf_isxdigit(c2)){
4167         (*u)(c2, f);
4168         return c1;
4169     }
4170     c3 = (*g)(f);
4171     if (!nkf_isxdigit(c3)){
4172         (*u)(c2, f);
4173         (*u)(c3, f);
4174         return c1;
4175     }
4176     return (hex2bin(c2) << 4) | hex2bin(c3);
4177 }
4178
4179 static nkf_char
4180 cap_getc(FILE *f)
4181 {
4182     return hex_getc(':', f, i_cgetc, i_cungetc);
4183 }
4184
4185 static nkf_char
4186 cap_ungetc(nkf_char c, FILE *f)
4187 {
4188     return (*i_cungetc)(c, f);
4189 }
4190
4191 static nkf_char
4192 url_getc(FILE *f)
4193 {
4194     return hex_getc('%', f, i_ugetc, i_uungetc);
4195 }
4196
4197 static nkf_char
4198 url_ungetc(nkf_char c, FILE *f)
4199 {
4200     return (*i_uungetc)(c, f);
4201 }
4202 #endif
4203
4204 #ifdef NUMCHAR_OPTION
4205 static nkf_char
4206 numchar_getc(FILE *f)
4207 {
4208     nkf_char (*g)(FILE *) = i_ngetc;
4209     nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc;
4210     int i = 0, j;
4211     nkf_char buf[12];
4212     long c = -1;
4213
4214     buf[i] = (*g)(f);
4215     if (buf[i] == '&'){
4216         buf[++i] = (*g)(f);
4217         if (buf[i] == '#'){
4218             c = 0;
4219             buf[++i] = (*g)(f);
4220             if (buf[i] == 'x' || buf[i] == 'X'){
4221                 for (j = 0; j < 7; j++){
4222                     buf[++i] = (*g)(f);
4223                     if (!nkf_isxdigit(buf[i])){
4224                         if (buf[i] != ';'){
4225                             c = -1;
4226                         }
4227                         break;
4228                     }
4229                     c <<= 4;
4230                     c |= hex2bin(buf[i]);
4231                 }
4232             }else{
4233                 for (j = 0; j < 8; j++){
4234                     if (j){
4235                         buf[++i] = (*g)(f);
4236                     }
4237                     if (!nkf_isdigit(buf[i])){
4238                         if (buf[i] != ';'){
4239                             c = -1;
4240                         }
4241                         break;
4242                     }
4243                     c *= 10;
4244                     c += hex2bin(buf[i]);
4245                 }
4246             }
4247         }
4248     }
4249     if (c != -1){
4250         return nkf_char_unicode_new(c);
4251     }
4252     while (i > 0){
4253         (*u)(buf[i], f);
4254         --i;
4255     }
4256     return buf[0];
4257 }
4258
4259 static nkf_char
4260 numchar_ungetc(nkf_char c, FILE *f)
4261 {
4262     return (*i_nungetc)(c, f);
4263 }
4264 #endif
4265
4266 #ifdef UNICODE_NORMALIZATION
4267
4268 static nkf_char
4269 nfc_getc(FILE *f)
4270 {
4271     nkf_char (*g)(FILE *f) = i_nfc_getc;
4272     nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
4273     nkf_buf_t *buf = nkf_state->nfc_buf;
4274     const unsigned char *array;
4275     int lower=0, upper=NORMALIZATION_TABLE_LENGTH-1;
4276     nkf_char c = (*g)(f);
4277
4278     if (c == EOF || c > 0xFF || (c & 0xc0) == 0x80) return c;
4279
4280     nkf_buf_push(buf, c);
4281     do {
4282         while (lower <= upper) {
4283             int mid = (lower+upper) / 2;
4284             int len;
4285             array = normalization_table[mid].nfd;
4286             for (len=0; len < NORMALIZATION_TABLE_NFD_LENGTH && array[len]; len++) {
4287                 if (len >= nkf_buf_length(buf)) {
4288                     c = (*g)(f);
4289                     if (c == EOF) {
4290                         len = 0;
4291                         lower = 1, upper = 0;
4292                         break;
4293                     }
4294                     nkf_buf_push(buf, c);
4295                 }
4296                 if (array[len] != nkf_buf_at(buf, len)) {
4297                     if (array[len] < nkf_buf_at(buf, len)) lower = mid + 1;
4298                     else  upper = mid - 1;
4299                     len = 0;
4300                     break;
4301                 }
4302             }
4303             if (len > 0) {
4304                 int i;
4305                 array = normalization_table[mid].nfc;
4306                 nkf_buf_clear(buf);
4307                 for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++)
4308                     nkf_buf_push(buf, array[i]);
4309                 break;
4310             }
4311         }
4312     } while (lower <= upper);
4313
4314     while (nkf_buf_length(buf) > 1) (*u)(nkf_buf_pop(buf), f);
4315     c = nkf_buf_pop(buf);
4316
4317     return c;
4318 }
4319
4320 static nkf_char
4321 nfc_ungetc(nkf_char c, FILE *f)
4322 {
4323     return (*i_nfc_ungetc)(c, f);
4324 }
4325 #endif /* UNICODE_NORMALIZATION */
4326
4327
4328 static nkf_char
4329 base64decode(nkf_char c)
4330 {
4331     int             i;
4332     if (c > '@') {
4333         if (c < '[') {
4334             i = c - 'A';                        /* A..Z 0-25 */
4335         } else if (c == '_') {
4336             i = '?'         /* 63 */ ;          /* _  63 */
4337         } else {
4338             i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
4339         }
4340     } else if (c > '/') {
4341         i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
4342     } else if (c == '+' || c == '-') {
4343         i = '>'             /* 62 */ ;          /* + and -  62 */
4344     } else {
4345         i = '?'             /* 63 */ ;          /* / 63 */
4346     }
4347     return (i);
4348 }
4349
4350 static nkf_char
4351 mime_getc(FILE *f)
4352 {
4353     nkf_char c1, c2, c3, c4, cc;
4354     nkf_char t1, t2, t3, t4, mode, exit_mode;
4355     nkf_char lwsp_count;
4356     char *lwsp_buf;
4357     char *lwsp_buf_new;
4358     nkf_char lwsp_size = 128;
4359
4360     if (mime_input_state.top != mime_input_state.last) {  /* Something is in FIFO */
4361         return  mime_input_buf(mime_input_state.top++);
4362     }
4363     if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
4364         mime_decode_mode=FALSE;
4365         unswitch_mime_getc();
4366         return (*i_getc)(f);
4367     }
4368
4369     if (mimebuf_f == FIXED_MIME)
4370         exit_mode = mime_decode_mode;
4371     else
4372         exit_mode = FALSE;
4373     if (mime_decode_mode == 'Q') {
4374         if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
4375       restart_mime_q:
4376         if (c1=='_' && mimebuf_f != FIXED_MIME) return SP;
4377         if (c1<=SP || DEL<=c1) {
4378             mime_decode_mode = exit_mode; /* prepare for quit */
4379             return c1;
4380         }
4381         if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) {
4382             return c1;
4383         }
4384
4385         mime_decode_mode = exit_mode; /* prepare for quit */
4386         if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
4387         if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
4388             /* end Q encoding */
4389             input_mode = exit_mode;
4390             lwsp_count = 0;
4391             lwsp_buf = nkf_xmalloc((lwsp_size+5)*sizeof(char));
4392             while ((c1=(*i_getc)(f))!=EOF) {
4393                 switch (c1) {
4394                 case LF:
4395                 case CR:
4396                     if (c1==LF) {
4397                         if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) {
4398                             i_ungetc(SP,f);
4399                             continue;
4400                         } else {
4401                             i_ungetc(c1,f);
4402                         }
4403                         c1 = LF;
4404                     } else {
4405                         if ((c1=(*i_getc)(f))!=EOF && c1 == LF) {
4406                             if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) {
4407                                 i_ungetc(SP,f);
4408                                 continue;
4409                             } else {
4410                                 i_ungetc(c1,f);
4411                             }
4412                             i_ungetc(LF,f);
4413                         } else {
4414                             i_ungetc(c1,f);
4415                         }
4416                         c1 = CR;
4417                     }
4418                     break;
4419                 case SP:
4420                 case TAB:
4421                     lwsp_buf[lwsp_count] = (unsigned char)c1;
4422                     if (lwsp_count++>lwsp_size){
4423                         lwsp_size <<= 1;
4424                         lwsp_buf_new = nkf_xrealloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
4425                         lwsp_buf = lwsp_buf_new;
4426                     }
4427                     continue;
4428                 }
4429                 break;
4430             }
4431             if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SP && lwsp_buf[lwsp_count-1] != TAB))) {
4432                 i_ungetc(c1,f);
4433                 for(lwsp_count--;lwsp_count>0;lwsp_count--)
4434                     i_ungetc(lwsp_buf[lwsp_count],f);
4435                 c1 = lwsp_buf[0];
4436             }
4437             nkf_xfree(lwsp_buf);
4438             return c1;
4439         }
4440         if (c1=='='&&c2<SP) { /* this is soft wrap */
4441             while((c1 =  (*i_mgetc)(f)) <=SP) {
4442                 if (c1 == EOF) return (EOF);
4443             }
4444             mime_decode_mode = 'Q'; /* still in MIME */
4445             goto restart_mime_q;
4446         }
4447         if (c1=='?') {
4448             mime_decode_mode = 'Q'; /* still in MIME */
4449             (*i_mungetc)(c2,f);
4450             return c1;
4451         }
4452         if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
4453         if (c2<=SP) return c2;
4454         mime_decode_mode = 'Q'; /* still in MIME */
4455         return ((hex2bin(c2)<<4) + hex2bin(c3));
4456     }
4457
4458     if (mime_decode_mode != 'B') {
4459         mime_decode_mode = FALSE;
4460         return (*i_mgetc)(f);
4461     }
4462
4463
4464     /* Base64 encoding */
4465     /*
4466        MIME allows line break in the middle of
4467        Base64, but we are very pessimistic in decoding
4468        in unbuf mode because MIME encoded code may broken by
4469        less or editor's control sequence (such as ESC-[-K in unbuffered
4470        mode. ignore incomplete MIME.
4471      */
4472     mode = mime_decode_mode;
4473     mime_decode_mode = exit_mode;  /* prepare for quit */
4474
4475     while ((c1 = (*i_mgetc)(f))<=SP) {
4476         if (c1==EOF)
4477             return (EOF);
4478     }
4479   mime_c2_retry:
4480     if ((c2 = (*i_mgetc)(f))<=SP) {
4481         if (c2==EOF)
4482             return (EOF);
4483         if (mime_f != STRICT_MIME) goto mime_c2_retry;
4484         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
4485         return c2;
4486     }
4487     if ((c1 == '?') && (c2 == '=')) {
4488         input_mode = ASCII;
4489         lwsp_count = 0;
4490         lwsp_buf = nkf_xmalloc((lwsp_size+5)*sizeof(char));
4491         while ((c1=(*i_getc)(f))!=EOF) {
4492             switch (c1) {
4493             case LF:
4494             case CR:
4495                 if (c1==LF) {
4496                     if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) {
4497                         i_ungetc(SP,f);
4498                         continue;
4499                     } else {
4500                         i_ungetc(c1,f);
4501                     }
4502                     c1 = LF;
4503                 } else {
4504                     if ((c1=(*i_getc)(f))!=EOF) {
4505                         if (c1==SP) {
4506                             i_ungetc(SP,f);
4507                             continue;
4508                         } else if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) {
4509                             i_ungetc(SP,f);
4510                             continue;
4511                         } else {
4512                             i_ungetc(c1,f);
4513                         }
4514                         i_ungetc(LF,f);
4515                     } else {
4516                         i_ungetc(c1,f);
4517                     }
4518                     c1 = CR;
4519                 }
4520                 break;
4521             case SP:
4522             case TAB:
4523                 lwsp_buf[lwsp_count] = (unsigned char)c1;
4524                 if (lwsp_count++>lwsp_size){
4525                     lwsp_size <<= 1;
4526                     lwsp_buf_new = nkf_xrealloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
4527                     lwsp_buf = lwsp_buf_new;
4528                 }
4529                 continue;
4530             }
4531             break;
4532         }
4533         if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SP && lwsp_buf[lwsp_count-1] != TAB))) {
4534             i_ungetc(c1,f);
4535             for(lwsp_count--;lwsp_count>0;lwsp_count--)
4536                 i_ungetc(lwsp_buf[lwsp_count],f);
4537             c1 = lwsp_buf[0];
4538         }
4539         nkf_xfree(lwsp_buf);
4540         return c1;
4541     }
4542   mime_c3_retry:
4543     if ((c3 = (*i_mgetc)(f))<=SP) {
4544         if (c3==EOF)
4545             return (EOF);
4546         if (mime_f != STRICT_MIME) goto mime_c3_retry;
4547         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
4548         return c3;
4549     }
4550   mime_c4_retry:
4551     if ((c4 = (*i_mgetc)(f))<=SP) {
4552         if (c4==EOF)
4553             return (EOF);
4554         if (mime_f != STRICT_MIME) goto mime_c4_retry;
4555         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
4556         return c4;
4557     }
4558
4559     mime_decode_mode = mode; /* still in MIME sigh... */
4560
4561     /* BASE 64 decoding */
4562
4563     t1 = 0x3f & base64decode(c1);
4564     t2 = 0x3f & base64decode(c2);
4565     t3 = 0x3f & base64decode(c3);
4566     t4 = 0x3f & base64decode(c4);
4567     cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
4568     if (c2 != '=') {
4569         mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
4570         cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
4571         if (c3 != '=') {
4572             mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
4573             cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
4574             if (c4 != '=')
4575                 mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
4576         }
4577     } else {
4578         return c1;
4579     }
4580     return  mime_input_buf(mime_input_state.top++);
4581 }
4582
4583 static const char basis_64[] =
4584     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4585
4586 #define MIMEOUT_BUF_LENGTH 74
4587 static struct {
4588     char buf[MIMEOUT_BUF_LENGTH+1];
4589     int count;
4590 } mimeout_state;
4591
4592 /*nkf_char mime_lastchar2, mime_lastchar1;*/
4593
4594 static void
4595 open_mime(nkf_char mode)
4596 {
4597     const unsigned char *p;
4598     int i;
4599     int j;
4600     p  = mime_pattern[0];
4601     for(i=0;mime_pattern[i];i++) {
4602         if (mode == mime_encode[i]) {
4603             p = mime_pattern[i];
4604             break;
4605         }
4606     }
4607     mimeout_mode = mime_encode_method[i];
4608     i = 0;
4609     if (base64_count>45) {
4610         if (mimeout_state.count>0 && nkf_isblank(mimeout_state.buf[i])){
4611             (*o_mputc)(mimeout_state.buf[i]);
4612             i++;
4613         }
4614         PUT_NEWLINE((*o_mputc));
4615         (*o_mputc)(SP);
4616         base64_count = 1;
4617         if (mimeout_state.count>0 && nkf_isspace(mimeout_state.buf[i])) {
4618             i++;
4619         }
4620     }
4621     for (;i<mimeout_state.count;i++) {
4622         if (nkf_isspace(mimeout_state.buf[i])) {
4623             (*o_mputc)(mimeout_state.buf[i]);
4624             base64_count ++;
4625         } else {
4626             break;
4627         }
4628     }
4629     while(*p) {
4630         (*o_mputc)(*p++);
4631         base64_count ++;
4632     }
4633     j = mimeout_state.count;
4634     mimeout_state.count = 0;
4635     for (;i<j;i++) {
4636         mime_putc(mimeout_state.buf[i]);
4637     }
4638 }
4639
4640 static void
4641 mime_prechar(nkf_char c2, nkf_char c1)
4642 {
4643     if (mimeout_mode > 0){
4644         if (c2 == EOF){
4645             if (base64_count + mimeout_state.count/3*4> 73){
4646                 (*o_base64conv)(EOF,0);
4647                 OCONV_NEWLINE((*o_base64conv));
4648                 (*o_base64conv)(0,SP);
4649                 base64_count = 1;
4650             }
4651         } else {
4652             if (!(c2 == 0 && (c1 == CR || c1 == LF)) &&
4653                     base64_count + mimeout_state.count/3*4> 66) {
4654                 (*o_base64conv)(EOF,0);
4655                 OCONV_NEWLINE((*o_base64conv));
4656                 (*o_base64conv)(0,SP);
4657                 base64_count = 1;
4658                 mimeout_mode = -1;
4659             }
4660         }
4661     } else if (c2) {
4662         if (c2 != EOF && base64_count + mimeout_state.count/3*4> 60) {
4663             mimeout_mode =  (output_mode==ASCII ||output_mode == ISO_8859_1) ? 'Q' : 'B';
4664             open_mime(output_mode);
4665             (*o_base64conv)(EOF,0);
4666             OCONV_NEWLINE((*o_base64conv));
4667             (*o_base64conv)(0,SP);
4668             base64_count = 1;
4669             mimeout_mode = -1;
4670         }
4671     }
4672 }
4673
4674 static void
4675 close_mime(void)
4676 {
4677     (*o_mputc)('?');
4678     (*o_mputc)('=');
4679     base64_count += 2;
4680     mimeout_mode = 0;
4681 }
4682
4683 static void
4684 eof_mime(void)
4685 {
4686     switch(mimeout_mode) {
4687     case 'Q':
4688     case 'B':
4689         break;
4690     case 2:
4691         (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4)]);
4692         (*o_mputc)('=');
4693         (*o_mputc)('=');
4694         base64_count += 3;
4695         break;
4696     case 1:
4697         (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2)]);
4698         (*o_mputc)('=');
4699         base64_count += 2;
4700         break;
4701     }
4702     if (mimeout_mode > 0) {
4703         if (mimeout_f!=FIXED_MIME) {
4704             close_mime();
4705         } else if (mimeout_mode != 'Q')
4706             mimeout_mode = 'B';
4707     }
4708 }
4709
4710 static void
4711 mimeout_addchar(nkf_char c)
4712 {
4713     switch(mimeout_mode) {
4714     case 'Q':
4715         if (c==CR||c==LF) {
4716             (*o_mputc)(c);
4717             base64_count = 0;
4718         } else if(!nkf_isalnum(c)) {
4719             (*o_mputc)('=');
4720             (*o_mputc)(bin2hex(((c>>4)&0xf)));
4721             (*o_mputc)(bin2hex((c&0xf)));
4722             base64_count += 3;
4723         } else {
4724             (*o_mputc)(c);
4725             base64_count++;
4726         }
4727         break;
4728     case 'B':
4729         nkf_state->mimeout_state=c;
4730         (*o_mputc)(basis_64[c>>2]);
4731         mimeout_mode=2;
4732         base64_count ++;
4733         break;
4734     case 2:
4735         (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
4736         nkf_state->mimeout_state=c;
4737         mimeout_mode=1;
4738         base64_count ++;
4739         break;
4740     case 1:
4741         (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2) | ((c & 0xC0) >>6)]);
4742         (*o_mputc)(basis_64[c & 0x3F]);
4743         mimeout_mode='B';
4744         base64_count += 2;
4745         break;
4746     default:
4747         (*o_mputc)(c);
4748         base64_count++;
4749         break;
4750     }
4751 }
4752
4753 static void
4754 mime_putc(nkf_char c)
4755 {
4756     int i, j;
4757     nkf_char lastchar;
4758
4759     if (mimeout_f == FIXED_MIME){
4760         if (mimeout_mode == 'Q'){
4761             if (base64_count > 71){
4762                 if (c!=CR && c!=LF) {
4763                     (*o_mputc)('=');
4764                     PUT_NEWLINE((*o_mputc));
4765                 }
4766                 base64_count = 0;
4767             }
4768         }else{
4769             if (base64_count > 71){
4770                 eof_mime();
4771                 PUT_NEWLINE((*o_mputc));
4772                 base64_count = 0;
4773             }
4774             if (c == EOF) { /* c==EOF */
4775                 eof_mime();
4776             }
4777         }
4778         if (c != EOF) { /* c==EOF */
4779             mimeout_addchar(c);
4780         }
4781         return;
4782     }
4783
4784     /* mimeout_f != FIXED_MIME */
4785
4786     if (c == EOF) { /* c==EOF */
4787         if (mimeout_mode == -1 && mimeout_state.count > 1) open_mime(output_mode);
4788         j = mimeout_state.count;
4789         mimeout_state.count = 0;
4790         i = 0;
4791         if (mimeout_mode > 0) {
4792             if (!nkf_isblank(mimeout_state.buf[j-1])) {
4793                 for (;i<j;i++) {
4794                     if (nkf_isspace(mimeout_state.buf[i]) && base64_count < 71){
4795                         break;
4796                     }
4797                     mimeout_addchar(mimeout_state.buf[i]);
4798                 }
4799                 eof_mime();
4800                 for (;i<j;i++) {
4801                     mimeout_addchar(mimeout_state.buf[i]);
4802                 }
4803             } else {
4804                 for (;i<j;i++) {
4805                     mimeout_addchar(mimeout_state.buf[i]);
4806                 }
4807                 eof_mime();
4808             }
4809         } else {
4810             for (;i<j;i++) {
4811                 mimeout_addchar(mimeout_state.buf[i]);
4812             }
4813         }
4814         return;
4815     }
4816
4817     if (mimeout_state.count > 0){
4818         lastchar = mimeout_state.buf[mimeout_state.count - 1];
4819     }else{
4820         lastchar = -1;
4821     }
4822
4823     if (mimeout_mode=='Q') {
4824         if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
4825             if (c == CR || c == LF) {
4826                 close_mime();
4827                 (*o_mputc)(c);
4828                 base64_count = 0;
4829                 return;
4830             } else if (c <= SP) {
4831                 close_mime();
4832                 if (base64_count > 70) {
4833                     PUT_NEWLINE((*o_mputc));
4834                     base64_count = 0;
4835                 }
4836                 if (!nkf_isblank(c)) {
4837                     (*o_mputc)(SP);
4838                     base64_count++;
4839                 }
4840             } else {
4841                 if (base64_count > 70) {
4842                     close_mime();
4843                     PUT_NEWLINE((*o_mputc));
4844                     (*o_mputc)(SP);
4845                     base64_count = 1;
4846                     open_mime(output_mode);
4847                 }
4848                 if (!nkf_noescape_mime(c)) {
4849                     mimeout_addchar(c);
4850                     return;
4851                 }
4852             }
4853             if (c != 0x1B) {
4854                 (*o_mputc)(c);
4855                 base64_count++;
4856                 return;
4857             }
4858         }
4859     }
4860
4861     if (mimeout_mode <= 0) {
4862         if (c <= DEL && (output_mode==ASCII || output_mode == ISO_8859_1 ||
4863                     output_mode == UTF_8)) {
4864             if (nkf_isspace(c)) {
4865                 int flag = 0;
4866                 if (mimeout_mode == -1) {
4867                     flag = 1;
4868                 }
4869                 if (c==CR || c==LF) {
4870                     if (flag) {
4871                         open_mime(output_mode);
4872                         output_mode = 0;
4873                     } else {
4874                         base64_count = 0;
4875                     }
4876                 }
4877                 for (i=0;i<mimeout_state.count;i++) {
4878                     (*o_mputc)(mimeout_state.buf[i]);
4879                     if (mimeout_state.buf[i] == CR || mimeout_state.buf[i] == LF){
4880                         base64_count = 0;
4881                     }else{
4882                         base64_count++;
4883                     }
4884                 }
4885                 if (flag) {
4886                     eof_mime();
4887                     base64_count = 0;
4888                     mimeout_mode = 0;
4889                 }
4890                 mimeout_state.buf[0] = (char)c;
4891                 mimeout_state.count = 1;
4892             }else{
4893                 if (base64_count > 1
4894                     && base64_count + mimeout_state.count > 76
4895                     && mimeout_state.buf[0] != CR && mimeout_state.buf[0] != LF){
4896                     static const char *str = "boundary=\"";
4897                     static int len = 10;
4898                     i = 0;
4899
4900                     for (; i < mimeout_state.count - len; ++i) {
4901                         if (!strncmp(mimeout_state.buf+i, str, len)) {
4902                             i += len - 2;
4903                             break;
4904                         }
4905                     }
4906
4907                     if (i == 0 || i == mimeout_state.count - len) {
4908                         PUT_NEWLINE((*o_mputc));
4909                         base64_count = 0;
4910                         if (!nkf_isspace(mimeout_state.buf[0])){
4911                             (*o_mputc)(SP);
4912                             base64_count++;
4913                         }
4914                     }
4915                     else {
4916                         int j;
4917                         for (j = 0; j <= i; ++j) {
4918                             (*o_mputc)(mimeout_state.buf[j]);
4919                         }
4920                         PUT_NEWLINE((*o_mputc));
4921                         base64_count = 1;
4922                         for (; j <= mimeout_state.count; ++j) {
4923                             mimeout_state.buf[j - i] = mimeout_state.buf[j];
4924                         }
4925                         mimeout_state.count -= i;
4926                     }
4927                 }
4928                 mimeout_state.buf[mimeout_state.count++] = (char)c;
4929                 if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
4930                     open_mime(output_mode);
4931                 }
4932             }
4933             return;
4934         }else{
4935             if (lastchar==CR || lastchar == LF){
4936                 for (i=0;i<mimeout_state.count;i++) {
4937                     (*o_mputc)(mimeout_state.buf[i]);
4938                 }
4939                 base64_count = 0;
4940                 mimeout_state.count = 0;
4941             }
4942             if (lastchar==SP) {
4943                 for (i=0;i<mimeout_state.count-1;i++) {
4944                     (*o_mputc)(mimeout_state.buf[i]);
4945                     base64_count++;
4946                 }
4947                 mimeout_state.buf[0] = SP;
4948                 mimeout_state.count = 1;
4949             }
4950             open_mime(output_mode);
4951         }
4952     }else{
4953         /* mimeout_mode == 'B', 1, 2 */
4954         if (c <= DEL && (output_mode==ASCII || output_mode == ISO_8859_1 ||
4955                     output_mode == UTF_8)) {
4956             if (lastchar == CR || lastchar == LF){
4957                 if (nkf_isblank(c)) {
4958                     for (i=0;i<mimeout_state.count;i++) {
4959                         mimeout_addchar(mimeout_state.buf[i]);
4960                     }
4961                     mimeout_state.count = 0;
4962                 } else {
4963                     eof_mime();
4964                     for (i=0;i<mimeout_state.count;i++) {
4965                         (*o_mputc)(mimeout_state.buf[i]);
4966                     }
4967                     base64_count = 0;
4968                     mimeout_state.count = 0;
4969                 }
4970                 mimeout_state.buf[mimeout_state.count++] = (char)c;
4971                 return;
4972             }
4973             if (nkf_isspace(c)) {
4974                 for (i=0;i<mimeout_state.count;i++) {
4975                     if (SP<mimeout_state.buf[i] && mimeout_state.buf[i]<DEL) {
4976                         eof_mime();
4977                         for (i=0;i<mimeout_state.count;i++) {
4978                             (*o_mputc)(mimeout_state.buf[i]);
4979                             base64_count++;
4980                         }
4981                         mimeout_state.count = 0;
4982                     }
4983                 }
4984                 mimeout_state.buf[mimeout_state.count++] = (char)c;
4985                 if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
4986                     eof_mime();
4987                     for (i=0;i<mimeout_state.count;i++) {
4988                         (*o_mputc)(mimeout_state.buf[i]);
4989                         base64_count++;
4990                     }
4991                     mimeout_state.count = 0;
4992                 }
4993                 return;
4994             }
4995             if (mimeout_state.count>0 && SP<c && c!='=') {
4996                 mimeout_state.buf[mimeout_state.count++] = (char)c;
4997                 if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
4998                     j = mimeout_state.count;
4999                     mimeout_state.count = 0;
5000                     for (i=0;i<j;i++) {
5001                         mimeout_addchar(mimeout_state.buf[i]);
5002                     }
5003                 }
5004                 return;
5005             }
5006         }
5007     }
5008     if (mimeout_state.count>0) {
5009         j = mimeout_state.count;
5010         mimeout_state.count = 0;
5011         for (i=0;i<j;i++) {
5012             if (mimeout_state.buf[i]==CR || mimeout_state.buf[i]==LF)
5013                 break;
5014             mimeout_addchar(mimeout_state.buf[i]);
5015         }
5016         if (i<j) {
5017             eof_mime();
5018             base64_count=0;
5019             for (;i<j;i++) {
5020                 (*o_mputc)(mimeout_state.buf[i]);
5021             }
5022             open_mime(output_mode);
5023         }
5024     }
5025     mimeout_addchar(c);
5026 }
5027
5028 static void
5029 base64_conv(nkf_char c2, nkf_char c1)
5030 {
5031     mime_prechar(c2, c1);
5032     (*o_base64conv)(c2,c1);
5033 }
5034
5035 #ifdef HAVE_ICONV_H
5036 typedef struct nkf_iconv_t {
5037     iconv_t cd;
5038     char *input_buffer;
5039     size_t input_buffer_size;
5040     char *output_buffer;
5041     size_t output_buffer_size;
5042 }
5043
5044 static nkf_iconv_t
5045 nkf_iconv_new(char *tocode, char *fromcode)
5046 {
5047     nkf_iconv_t converter;
5048
5049     converter->input_buffer_size = IOBUF_SIZE;
5050     converter->input_buffer = nkf_xmalloc(converter->input_buffer_size);
5051     converter->output_buffer_size = IOBUF_SIZE * 2;
5052     converter->output_buffer = nkf_xmalloc(converter->output_buffer_size);
5053     converter->cd = iconv_open(tocode, fromcode);
5054     if (converter->cd == (iconv_t)-1)
5055     {
5056         switch (errno) {
5057         case EINVAL:
5058             perror(fprintf("iconv doesn't support %s to %s conversion.", fromcode, tocode));
5059             return -1;
5060         default:
5061             perror("can't iconv_open");
5062         }
5063     }
5064 }
5065
5066 static size_t
5067 nkf_iconv_convert(nkf_iconv_t *converter, FILE *input)
5068 {
5069     size_t invalid = (size_t)0;
5070     char *input_buffer = converter->input_buffer;
5071     size_t input_length = (size_t)0;
5072     char *output_buffer = converter->output_buffer;
5073     size_t output_length = converter->output_buffer_size;
5074     int c;
5075
5076     do {
5077         if (c != EOF) {
5078             while ((c = (*i_getc)(f)) != EOF) {
5079                 input_buffer[input_length++] = c;
5080                 if (input_length < converter->input_buffer_size) break;
5081             }
5082         }
5083
5084         size_t ret = iconv(converter->cd, &input_buffer, &input_length, &output_buffer, &output_length);
5085         while (output_length-- > 0) {
5086             (*o_putc)(output_buffer[converter->output_buffer_size-output_length]);
5087         }
5088         if (ret == (size_t) - 1) {
5089             switch (errno) {
5090             case EINVAL:
5091                 if (input_buffer != converter->input_buffer)
5092                     memmove(converter->input_buffer, input_buffer, input_length);
5093                 break;
5094             case E2BIG:
5095                 converter->output_buffer_size *= 2;
5096                 output_buffer = realloc(converter->outbuf, converter->output_buffer_size);
5097                 if (output_buffer == NULL) {
5098                     perror("can't realloc");
5099                     return -1;
5100                 }
5101                 converter->output_buffer = output_buffer;
5102                 break;
5103             default:
5104                 perror("can't iconv");
5105                 return -1;
5106             }
5107         } else {
5108             invalid += ret;
5109         }
5110     } while (1);
5111
5112     return invalid;
5113 }
5114
5115
5116 static void
5117 nkf_iconv_close(nkf_iconv_t *convert)
5118 {
5119     nkf_xfree(converter->inbuf);
5120     nkf_xfree(converter->outbuf);
5121     iconv_close(converter->cd);
5122 }
5123 #endif
5124
5125
5126 static void
5127 reinit(void)
5128 {
5129     {
5130         struct input_code *p = input_code_list;
5131         while (p->name){
5132             status_reinit(p++);
5133         }
5134     }
5135     unbuf_f = FALSE;
5136     estab_f = FALSE;
5137     nop_f = FALSE;
5138     binmode_f = TRUE;
5139     rot_f = FALSE;
5140     hira_f = FALSE;
5141     alpha_f = FALSE;
5142     mime_f = MIME_DECODE_DEFAULT;
5143     mime_decode_f = FALSE;
5144     mimebuf_f = FALSE;
5145     broken_f = FALSE;
5146     iso8859_f = FALSE;
5147     mimeout_f = FALSE;
5148     x0201_f = X0201_DEFAULT;
5149     iso2022jp_f = FALSE;
5150 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
5151     ms_ucs_map_f = UCS_MAP_ASCII;
5152 #endif
5153 #ifdef UTF8_INPUT_ENABLE
5154     no_cp932ext_f = FALSE;
5155     no_best_fit_chars_f = FALSE;
5156     encode_fallback = NULL;
5157     unicode_subchar  = '?';
5158     input_endian = ENDIAN_BIG;
5159 #endif
5160 #ifdef UTF8_OUTPUT_ENABLE
5161     output_bom_f = FALSE;
5162     output_endian = ENDIAN_BIG;
5163 #endif
5164 #ifdef UNICODE_NORMALIZATION
5165     nfc_f = FALSE;
5166 #endif
5167 #ifdef INPUT_OPTION
5168     cap_f = FALSE;
5169     url_f = FALSE;
5170     numchar_f = FALSE;
5171 #endif
5172 #ifdef CHECK_OPTION
5173     noout_f = FALSE;
5174     debug_f = FALSE;
5175 #endif
5176     guess_f = 0;
5177 #ifdef EXEC_IO
5178     exec_f = 0;
5179 #endif
5180 #ifdef SHIFTJIS_CP932
5181     cp51932_f = TRUE;
5182     cp932inv_f = TRUE;
5183 #endif
5184 #ifdef X0212_ENABLE
5185     x0212_f = FALSE;
5186     x0213_f = FALSE;
5187 #endif
5188     {
5189         int i;
5190         for (i = 0; i < 256; i++){
5191             prefix_table[i] = 0;
5192         }
5193     }
5194     hold_count = 0;
5195     mimeout_state.count = 0;
5196     mimeout_mode = 0;
5197     base64_count = 0;
5198     f_line = 0;
5199     f_prev = 0;
5200     fold_preserve_f = FALSE;
5201     fold_f = FALSE;
5202     fold_len = 0;
5203     kanji_intro = DEFAULT_J;
5204     ascii_intro = DEFAULT_R;
5205     fold_margin  = FOLD_MARGIN;
5206     o_zconv = no_connection;
5207     o_fconv = no_connection;
5208     o_eol_conv = no_connection;
5209     o_rot_conv = no_connection;
5210     o_hira_conv = no_connection;
5211     o_base64conv = no_connection;
5212     o_iso2022jp_check_conv = no_connection;
5213     o_putc = std_putc;
5214     i_getc = std_getc;
5215     i_ungetc = std_ungetc;
5216     i_bgetc = std_getc;
5217     i_bungetc = std_ungetc;
5218     o_mputc = std_putc;
5219     i_mgetc = std_getc;
5220     i_mungetc  = std_ungetc;
5221     i_mgetc_buf = std_getc;
5222     i_mungetc_buf = std_ungetc;
5223     output_mode = ASCII;
5224     input_mode =  ASCII;
5225     mime_decode_mode = FALSE;
5226     file_out_f = FALSE;
5227     eolmode_f = 0;
5228     input_eol = 0;
5229     prev_cr = 0;
5230     option_mode = 0;
5231     z_prev2=0,z_prev1=0;
5232 #ifdef CHECK_OPTION
5233     iconv_for_check = 0;
5234 #endif
5235     input_codename = NULL;
5236     input_encoding = NULL;
5237     output_encoding = NULL;
5238     nkf_state_init();
5239 #ifdef WIN32DLL
5240     reinitdll();
5241 #endif /*WIN32DLL*/
5242 }
5243
5244 static int
5245 module_connection(void)
5246 {
5247     if (input_encoding) set_input_encoding(input_encoding);
5248     if (!output_encoding) {
5249         output_encoding = nkf_default_encoding();
5250     }
5251     if (!output_encoding) {
5252         if (noout_f || guess_f) output_encoding = nkf_enc_from_index(ISO_2022_JP);
5253         else return -1;
5254     }
5255     set_output_encoding(output_encoding);
5256     oconv = nkf_enc_to_oconv(output_encoding);
5257     o_putc = std_putc;
5258     if (nkf_enc_unicode_p(output_encoding))
5259         output_mode = UTF_8;
5260
5261     /* replace continucation module, from output side */
5262
5263     /* output redicrection */
5264 #ifdef CHECK_OPTION
5265     if (noout_f || guess_f){
5266         o_putc = no_putc;
5267     }
5268 #endif
5269     if (mimeout_f) {
5270         o_mputc = o_putc;
5271         o_putc = mime_putc;
5272         if (mimeout_f == TRUE) {
5273             o_base64conv = oconv; oconv = base64_conv;
5274         }
5275         /* base64_count = 0; */
5276     }
5277
5278     if (eolmode_f || guess_f) {
5279         o_eol_conv = oconv; oconv = eol_conv;
5280     }
5281     if (rot_f) {
5282         o_rot_conv = oconv; oconv = rot_conv;
5283     }
5284     if (iso2022jp_f) {
5285         o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
5286     }
5287     if (hira_f) {
5288         o_hira_conv = oconv; oconv = hira_conv;
5289     }
5290     if (fold_f) {
5291         o_fconv = oconv; oconv = fold_conv;
5292         f_line = 0;
5293     }
5294     if (alpha_f || x0201_f) {
5295         o_zconv = oconv; oconv = z_conv;
5296     }
5297
5298     i_getc = std_getc;
5299     i_ungetc = std_ungetc;
5300     /* input redicrection */
5301 #ifdef INPUT_OPTION
5302     if (cap_f){
5303         i_cgetc = i_getc; i_getc = cap_getc;
5304         i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
5305     }
5306     if (url_f){
5307         i_ugetc = i_getc; i_getc = url_getc;
5308         i_uungetc = i_ungetc; i_ungetc= url_ungetc;
5309     }
5310 #endif
5311 #ifdef NUMCHAR_OPTION
5312     if (numchar_f){
5313         i_ngetc = i_getc; i_getc = numchar_getc;
5314         i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
5315     }
5316 #endif
5317 #ifdef UNICODE_NORMALIZATION
5318     if (nfc_f){
5319         i_nfc_getc = i_getc; i_getc = nfc_getc;
5320         i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
5321     }
5322 #endif
5323     if (mime_f && mimebuf_f==FIXED_MIME) {
5324         i_mgetc = i_getc; i_getc = mime_getc;
5325         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
5326     }
5327     if (broken_f & 1) {
5328         i_bgetc = i_getc; i_getc = broken_getc;
5329         i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
5330     }
5331     if (input_encoding) {
5332         set_iconv(-TRUE, nkf_enc_to_iconv(input_encoding));
5333     } else {
5334         set_iconv(FALSE, e_iconv);
5335     }
5336
5337     {
5338         struct input_code *p = input_code_list;
5339         while (p->name){
5340             status_reinit(p++);
5341         }
5342     }
5343     return 0;
5344 }
5345
5346 /*
5347    Conversion main loop. Code detection only.
5348  */
5349
5350 #if !defined(PERL_XS) && !defined(WIN32DLL)
5351 static nkf_char
5352 noconvert(FILE *f)
5353 {
5354     nkf_char    c;
5355
5356     if (nop_f == 2)
5357         module_connection();
5358     while ((c = (*i_getc)(f)) != EOF)
5359         (*o_putc)(c);
5360     (*o_putc)(EOF);
5361     return 1;
5362 }
5363 #endif
5364
5365 #define NEXT continue        /* no output, get next */
5366 #define SKIP c2=0;continue        /* no output, get next */
5367 #define MORE c2=c1;continue  /* need one more byte */
5368 #define SEND ;               /* output c1 and c2, get next */
5369 #define LAST break           /* end of loop, go closing  */
5370 #define set_input_mode(mode) do { \
5371     input_mode = mode; \
5372     shift_mode = 0; \
5373     set_input_codename("ISO-2022-JP"); \
5374     debug("ISO-2022-JP"); \
5375 } while (0)
5376
5377 static int
5378 kanji_convert(FILE *f)
5379 {
5380     nkf_char c1=0, c2=0, c3=0, c4=0;
5381     int shift_mode = 0; /* 0, 1, 2, 3 */
5382     int g2 = 0;
5383     int is_8bit = FALSE;
5384
5385     if (input_encoding && !nkf_enc_asciicompat(input_encoding)) {
5386         is_8bit = TRUE;
5387     }
5388
5389     input_mode = ASCII;
5390     output_mode = ASCII;
5391
5392     if (module_connection() < 0) {
5393 #if !defined(PERL_XS) && !defined(WIN32DLL)
5394         fprintf(stderr, "no output encoding given\n");
5395 #endif
5396         return -1;
5397     }
5398     check_bom(f);
5399
5400 #ifdef UTF8_INPUT_ENABLE
5401     if(iconv == w_iconv32){
5402         while ((c1 = (*i_getc)(f)) != EOF &&
5403                (c2 = (*i_getc)(f)) != EOF &&
5404                (c3 = (*i_getc)(f)) != EOF &&
5405                (c4 = (*i_getc)(f)) != EOF) {
5406             nkf_iconv_utf_32(c1, c2, c3, c4);
5407         }
5408         (*i_ungetc)(EOF, f);
5409     }
5410     else if (iconv == w_iconv16) {
5411         while ((c1 = (*i_getc)(f)) != EOF &&
5412                (c2 = (*i_getc)(f)) != EOF) {
5413             if (nkf_iconv_utf_16(c1, c2, 0, 0) == -2 &&
5414                 (c3 = (*i_getc)(f)) != EOF &&
5415                 (c4 = (*i_getc)(f)) != EOF) {
5416                 nkf_iconv_utf_16(c1, c2, c3, c4);
5417             }
5418         }
5419         (*i_ungetc)(EOF, f);
5420     }
5421 #endif
5422
5423     while ((c1 = (*i_getc)(f)) != EOF) {
5424 #ifdef INPUT_CODE_FIX
5425         if (!input_encoding)
5426 #endif
5427             code_status(c1);
5428         if (c2) {
5429             /* second byte */
5430             if (c2 > DEL) {
5431                 /* in case of 8th bit is on */
5432                 if (!estab_f&&!mime_decode_mode) {
5433                     /* in case of not established yet */
5434                     /* It is still ambiguious */
5435                     if (h_conv(f, c2, c1)==EOF) {
5436                         LAST;
5437                     }
5438                     else {
5439                         SKIP;
5440                     }
5441                 }
5442                 else {
5443                     /* in case of already established */
5444                     if (c1 < 0x40) {
5445                         /* ignore bogus code */
5446                         SKIP;
5447                     } else {
5448                         SEND;
5449                     }
5450                 }
5451             }
5452             else {
5453                 /* 2nd byte of 7 bit code or SJIS */
5454                 SEND;
5455             }
5456         }
5457         else if (nkf_char_unicode_p(c1)) {
5458             (*oconv)(0, c1);
5459             NEXT;
5460         }
5461         else {
5462             /* first byte */
5463             if (input_mode == JIS_X_0208 && DEL <= c1 && c1 < 0x92) {
5464                 /* CP5022x */
5465                 MORE;
5466             }else if (input_codename && input_codename[0] == 'I' &&
5467                     0xA1 <= c1 && c1 <= 0xDF) {
5468                 /* JIS X 0201 Katakana in 8bit JIS */
5469                 c2 = JIS_X_0201_1976_K;
5470                 c1 &= 0x7f;
5471                 SEND;
5472             } else if (c1 > DEL) {
5473                 /* 8 bit code */
5474                 if (!estab_f && !iso8859_f) {
5475                     /* not established yet */
5476                     MORE;
5477                 } else { /* estab_f==TRUE */
5478                     if (iso8859_f) {
5479                         c2 = ISO_8859_1;
5480                         c1 &= 0x7f;
5481                         SEND;
5482                     }
5483                     else if ((iconv == s_iconv && 0xA0 <= c1 && c1 <= 0xDF) ||
5484                              (ms_ucs_map_f == UCS_MAP_CP10001 && (c1 == 0xFD || c1 == 0xFE))) {
5485                         /* JIS X 0201 */
5486                         c2 = JIS_X_0201_1976_K;
5487                         c1 &= 0x7f;
5488                         SEND;
5489                     }
5490                     else {
5491                         /* already established */
5492                         MORE;
5493                     }
5494                 }
5495             } else if (SP < c1 && c1 < DEL) {
5496                 /* in case of Roman characters */
5497                 if (shift_mode) {
5498                     /* output 1 shifted byte */
5499                     if (iso8859_f) {
5500                         c2 = ISO_8859_1;
5501                         SEND;
5502                     } else if (nkf_byte_jisx0201_katakana_p(c1)){
5503                         /* output 1 shifted byte */
5504                         c2 = JIS_X_0201_1976_K;
5505                         SEND;
5506                     } else {
5507                         /* look like bogus code */
5508                         SKIP;
5509                     }
5510                 } else if (input_mode == JIS_X_0208 || input_mode == JIS_X_0212 ||
5511                            input_mode == JIS_X_0213_1 || input_mode == JIS_X_0213_2) {
5512                     /* in case of Kanji shifted */
5513                     MORE;
5514                 } else if (c1 == '=' && mime_f && !mime_decode_mode) {
5515                     /* Check MIME code */
5516                     if ((c1 = (*i_getc)(f)) == EOF) {
5517                         (*oconv)(0, '=');
5518                         LAST;
5519                     } else if (c1 == '?') {
5520                         /* =? is mime conversion start sequence */
5521                         if(mime_f == STRICT_MIME) {
5522                             /* check in real detail */
5523                             if (mime_begin_strict(f) == EOF)
5524                                 LAST;
5525                             SKIP;
5526                         } else if (mime_begin(f) == EOF)
5527                             LAST;
5528                         SKIP;
5529                     } else {
5530                         (*oconv)(0, '=');
5531                         (*i_ungetc)(c1,f);
5532                         SKIP;
5533                     }
5534                 } else {
5535                     /* normal ASCII code */
5536                     SEND;
5537                 }
5538             } else if (c1 == SI && (!is_8bit || mime_decode_mode)) {
5539                 shift_mode = 0;
5540                 SKIP;
5541             } else if (c1 == SO && (!is_8bit || mime_decode_mode)) {
5542                 shift_mode = 1;
5543                 SKIP;
5544             } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) {
5545                 if ((c1 = (*i_getc)(f)) == EOF) {
5546                     (*oconv)(0, ESC);
5547                     LAST;
5548                 }
5549                 else if (c1 == '&') {
5550                     /* IRR */
5551                     if ((c1 = (*i_getc)(f)) == EOF) {
5552                         LAST;
5553                     } else {
5554                         SKIP;
5555                     }
5556                 }
5557                 else if (c1 == '$') {
5558                     /* GZDMx */
5559                     if ((c1 = (*i_getc)(f)) == EOF) {
5560                         /* don't send bogus code
5561                            (*oconv)(0, ESC);
5562                            (*oconv)(0, '$'); */
5563                         LAST;
5564                     } else if (c1 == '@' || c1 == 'B') {
5565                         /* JIS X 0208 */
5566                         set_input_mode(JIS_X_0208);
5567                         SKIP;
5568                     } else if (c1 == '(') {
5569                         /* GZDM4 */
5570                         if ((c1 = (*i_getc)(f)) == EOF) {
5571                             /* don't send bogus code
5572                                (*oconv)(0, ESC);
5573                                (*oconv)(0, '$');
5574                                (*oconv)(0, '(');
5575                              */
5576                             LAST;
5577                         } else if (c1 == '@'|| c1 == 'B') {
5578                             /* JIS X 0208 */
5579                             set_input_mode(JIS_X_0208);
5580                             SKIP;
5581 #ifdef X0212_ENABLE
5582                         } else if (c1 == 'D'){
5583                             set_input_mode(JIS_X_0212);
5584                             SKIP;
5585 #endif /* X0212_ENABLE */
5586                         } else if (c1 == 'O' || c1 == 'Q'){
5587                             set_input_mode(JIS_X_0213_1);
5588                             SKIP;
5589                         } else if (c1 == 'P'){
5590                             set_input_mode(JIS_X_0213_2);
5591                             SKIP;
5592                         } else {
5593                             /* could be some special code */
5594                             (*oconv)(0, ESC);
5595                             (*oconv)(0, '$');
5596                             (*oconv)(0, '(');
5597                             (*oconv)(0, c1);
5598                             SKIP;
5599                         }
5600                     } else if (broken_f&0x2) {
5601                         /* accept any ESC-(-x as broken code ... */
5602                         input_mode = JIS_X_0208;
5603                         shift_mode = 0;
5604                         SKIP;
5605                     } else {
5606                         (*oconv)(0, ESC);
5607                         (*oconv)(0, '$');
5608                         (*oconv)(0, c1);
5609                         SKIP;
5610                     }
5611                 } else if (c1 == '(') {
5612                     /* GZD4 */
5613                     if ((c1 = (*i_getc)(f)) == EOF) {
5614                         /* don't send bogus code
5615                            (*oconv)(0, ESC);
5616                            (*oconv)(0, '('); */
5617                         LAST;
5618                     }
5619                     else if (c1 == 'I') {
5620                         /* JIS X 0201 Katakana */
5621                         set_input_mode(JIS_X_0201_1976_K);
5622                         SKIP;
5623                     }
5624                     else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
5625                         /* ISO-646IRV:1983 or JIS X 0201 Roman or JUNET */
5626                         set_input_mode(ASCII);
5627                         SKIP;
5628                     }
5629                     else if (broken_f&0x2) {
5630                         set_input_mode(ASCII);
5631                         SKIP;
5632                     }
5633                     else {
5634                         (*oconv)(0, ESC);
5635                         (*oconv)(0, '(');
5636                         SEND;
5637                     }
5638                 }
5639                 else if (c1 == '.') {
5640                     /* G2D6 */
5641                     if ((c1 = (*i_getc)(f)) == EOF) {
5642                         LAST;
5643                     }
5644                     else if (c1 == 'A') {
5645                         /* ISO-8859-1 */
5646                         g2 = ISO_8859_1;
5647                         SKIP;
5648                     }
5649                     else {
5650                         (*oconv)(0, ESC);
5651                         (*oconv)(0, '.');
5652                         SEND;
5653                     }
5654                 }
5655                 else if (c1 == 'N') {
5656                     /* SS2 */
5657                     c1 = (*i_getc)(f);
5658                     if (g2 == ISO_8859_1) {
5659                         c2 = ISO_8859_1;
5660                         SEND;
5661                     }else{
5662                         (*i_ungetc)(c1, f);
5663                         /* lonely ESC  */
5664                         (*oconv)(0, ESC);
5665                         SEND;
5666                     }
5667                 }
5668                 else {
5669                     /* lonely ESC  */
5670                     (*oconv)(0, ESC);
5671                     SEND;
5672                 }
5673             } else if (c1 == ESC && iconv == s_iconv) {
5674                 /* ESC in Shift_JIS */
5675                 if ((c1 = (*i_getc)(f)) == EOF) {
5676                     (*oconv)(0, ESC);
5677                     LAST;
5678                 } else if (c1 == '$') {
5679                     /* J-PHONE emoji */
5680                     if ((c1 = (*i_getc)(f)) == EOF) {
5681                         LAST;
5682                     } else if (('E' <= c1 && c1 <= 'G') ||
5683                                ('O' <= c1 && c1 <= 'Q')) {
5684                         /*
5685                            NUM : 0 1 2 3 4 5
5686                            BYTE: G E F O P Q
5687                            C%7 : 1 6 0 2 3 4
5688                            C%7 : 0 1 2 3 4 5 6
5689                            NUM : 2 0 3 4 5 X 1
5690                          */
5691                         static const nkf_char jphone_emoji_first_table[7] =
5692                         {0xE1E0, 0xDFE0, 0xE2E0, 0xE3E0, 0xE4E0, 0xDFE0, 0xE0E0};
5693                         c3 = nkf_char_unicode_new(jphone_emoji_first_table[c1 % 7]);
5694                         if ((c1 = (*i_getc)(f)) == EOF) LAST;
5695                         while (SP <= c1 && c1 <= 'z') {
5696                             (*oconv)(0, c1 + c3);
5697                             if ((c1 = (*i_getc)(f)) == EOF) LAST;
5698                         }
5699                         SKIP;
5700                     }
5701                     else {
5702                         (*oconv)(0, ESC);
5703                         (*oconv)(0, '$');
5704                         SEND;
5705                     }
5706                 }
5707                 else {
5708                     /* lonely ESC  */
5709                     (*oconv)(0, ESC);
5710                     SEND;
5711                 }
5712             } else if (c1 == LF || c1 == CR) {
5713                 if (broken_f&4) {
5714                     input_mode = ASCII; set_iconv(FALSE, 0);
5715                     SEND;
5716                 } else if (mime_decode_f && !mime_decode_mode){
5717                     if (c1 == LF) {
5718                         if ((c1=(*i_getc)(f))!=EOF && c1 == SP) {
5719                             i_ungetc(SP,f);
5720                             continue;
5721                         } else {
5722                             i_ungetc(c1,f);
5723                         }
5724                         c1 = LF;
5725                         SEND;
5726                     } else  { /* if (c1 == CR)*/
5727                         if ((c1=(*i_getc)(f))!=EOF) {
5728                             if (c1==SP) {
5729                                 i_ungetc(SP,f);
5730                                 continue;
5731                             } else if (c1 == LF && (c1=(*i_getc)(f))!=EOF && c1 == SP) {
5732                                 i_ungetc(SP,f);
5733                                 continue;
5734                             } else {
5735                                 i_ungetc(c1,f);
5736                             }
5737                             i_ungetc(LF,f);
5738                         } else {
5739                             i_ungetc(c1,f);
5740                         }
5741                         c1 = CR;
5742                         SEND;
5743                     }
5744                 }
5745             } else
5746                 SEND;
5747         }
5748         /* send: */
5749         switch(input_mode){
5750         case ASCII:
5751             switch ((*iconv)(c2, c1, 0)) {  /* can be EUC / SJIS / UTF-8 */
5752             case -2:
5753                 /* 4 bytes UTF-8 */
5754                 if ((c3 = (*i_getc)(f)) != EOF) {
5755                     code_status(c3);
5756                     c3 <<= 8;
5757                     if ((c4 = (*i_getc)(f)) != EOF) {
5758                         code_status(c4);
5759                         (*iconv)(c2, c1, c3|c4);
5760                     }
5761                 }
5762                 break;
5763             case -1:
5764                 /* 3 bytes EUC or UTF-8 */
5765                 if ((c3 = (*i_getc)(f)) != EOF) {
5766                     code_status(c3);
5767                     (*iconv)(c2, c1, c3);
5768                 }
5769                 break;
5770             }
5771             break;
5772         case JIS_X_0208:
5773         case JIS_X_0213_1:
5774             if (ms_ucs_map_f &&
5775                 0x7F <= c2 && c2 <= 0x92 &&
5776                 0x21 <= c1 && c1 <= 0x7E) {
5777                 /* CP932 UDC */
5778                 c1 = nkf_char_unicode_new((c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000);
5779                 c2 = 0;
5780             }
5781             (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
5782             break;
5783 #ifdef X0212_ENABLE
5784         case JIS_X_0212:
5785             (*oconv)(PREFIX_EUCG3 | c2, c1);
5786             break;
5787 #endif /* X0212_ENABLE */
5788         case JIS_X_0213_2:
5789             (*oconv)(PREFIX_EUCG3 | c2, c1);
5790             break;
5791         default:
5792             (*oconv)(input_mode, c1);  /* other special case */
5793         }
5794
5795         c2 = 0;
5796         c3 = 0;
5797         continue;
5798         /* goto next_word */
5799     }
5800
5801     /* epilogue */
5802     (*iconv)(EOF, 0, 0);
5803     if (!input_codename)
5804     {
5805         if (is_8bit) {
5806             struct input_code *p = input_code_list;
5807             struct input_code *result = p;
5808             while (p->name){
5809                 if (p->score < result->score) result = p;
5810                 ++p;
5811             }
5812             set_input_codename(result->name);
5813 #ifdef CHECK_OPTION
5814             debug(result->name);
5815 #endif
5816         }
5817     }
5818     return 0;
5819 }
5820
5821 /*
5822  * int options(unsigned char *cp)
5823  * 
5824  * return values:
5825  *    0: success
5826  *   -1: ArgumentError
5827  */
5828 static int
5829 options(unsigned char *cp)
5830 {
5831     nkf_char i, j;
5832     unsigned char *p;
5833     unsigned char *cp_back = NULL;
5834     nkf_encoding *enc;
5835
5836     if (option_mode==1)
5837         return 0;
5838     while(*cp && *cp++!='-');
5839     while (*cp || cp_back) {
5840         if(!*cp){
5841             cp = cp_back;
5842             cp_back = NULL;
5843             continue;
5844         }
5845         p = 0;
5846         switch (*cp++) {
5847         case '-':  /* literal options */
5848             if (!*cp || *cp == SP) {        /* ignore the rest of arguments */
5849                 option_mode = 1;
5850                 return 0;
5851             }
5852             for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
5853                 p = (unsigned char *)long_option[i].name;
5854                 for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
5855                 if (*p == cp[j] || cp[j] == SP){
5856                     p = &cp[j] + 1;
5857                     break;
5858                 }
5859                 p = 0;
5860             }
5861             if (p == 0) {
5862 #if !defined(PERL_XS) && !defined(WIN32DLL)
5863                 fprintf(stderr, "unknown long option: --%s\n", cp);
5864 #endif
5865                 return -1;
5866             }
5867             while(*cp && *cp != SP && cp++);
5868             if (long_option[i].alias[0]){
5869                 cp_back = cp;
5870                 cp = (unsigned char *)long_option[i].alias;
5871             }else{
5872 #ifndef PERL_XS
5873                 if (strcmp(long_option[i].name, "help") == 0){
5874                     usage();
5875                     exit(EXIT_SUCCESS);
5876                 }
5877 #endif
5878                 if (strcmp(long_option[i].name, "ic=") == 0){
5879                     enc = nkf_enc_find((char *)p);
5880                     if (!enc) continue;
5881                     input_encoding = enc;
5882                     continue;
5883                 }
5884                 if (strcmp(long_option[i].name, "oc=") == 0){
5885                     enc = nkf_enc_find((char *)p);
5886                     /* if (enc <= 0) continue; */
5887                     if (!enc) continue;
5888                     output_encoding = enc;
5889                     continue;
5890                 }
5891                 if (strcmp(long_option[i].name, "guess=") == 0){
5892                     if (p[0] == '0' || p[0] == '1') {
5893                         guess_f = 1;
5894                     } else {
5895                         guess_f = 2;
5896                     }
5897                     continue;
5898                 }
5899 #ifdef OVERWRITE
5900                 if (strcmp(long_option[i].name, "overwrite") == 0){
5901                     file_out_f = TRUE;
5902                     overwrite_f = TRUE;
5903                     preserve_time_f = TRUE;
5904                     continue;
5905                 }
5906                 if (strcmp(long_option[i].name, "overwrite=") == 0){
5907                     file_out_f = TRUE;
5908                     overwrite_f = TRUE;
5909                     preserve_time_f = TRUE;
5910                     backup_f = TRUE;
5911                     backup_suffix = (char *)p;
5912                     continue;
5913                 }
5914                 if (strcmp(long_option[i].name, "in-place") == 0){
5915                     file_out_f = TRUE;
5916                     overwrite_f = TRUE;
5917                     preserve_time_f = FALSE;
5918                     continue;
5919                 }
5920                 if (strcmp(long_option[i].name, "in-place=") == 0){
5921                     file_out_f = TRUE;
5922                     overwrite_f = TRUE;
5923                     preserve_time_f = FALSE;
5924                     backup_f = TRUE;
5925                     backup_suffix = (char *)p;
5926                     continue;
5927                 }
5928 #endif
5929 #ifdef INPUT_OPTION
5930                 if (strcmp(long_option[i].name, "cap-input") == 0){
5931                     cap_f = TRUE;
5932                     continue;
5933                 }
5934                 if (strcmp(long_option[i].name, "url-input") == 0){
5935                     url_f = TRUE;
5936                     continue;
5937                 }
5938 #endif
5939 #ifdef NUMCHAR_OPTION
5940                 if (strcmp(long_option[i].name, "numchar-input") == 0){
5941                     numchar_f = TRUE;
5942                     continue;
5943                 }
5944 #endif
5945 #ifdef CHECK_OPTION
5946                 if (strcmp(long_option[i].name, "no-output") == 0){
5947                     noout_f = TRUE;
5948                     continue;
5949                 }
5950                 if (strcmp(long_option[i].name, "debug") == 0){
5951                     debug_f = TRUE;
5952                     continue;
5953                 }
5954 #endif
5955                 if (strcmp(long_option[i].name, "cp932") == 0){
5956 #ifdef SHIFTJIS_CP932
5957                     cp51932_f = TRUE;
5958                     cp932inv_f = -TRUE;
5959 #endif
5960 #ifdef UTF8_OUTPUT_ENABLE
5961                     ms_ucs_map_f = UCS_MAP_CP932;
5962 #endif
5963                     continue;
5964                 }
5965                 if (strcmp(long_option[i].name, "no-cp932") == 0){
5966 #ifdef SHIFTJIS_CP932
5967                     cp51932_f = FALSE;
5968                     cp932inv_f = FALSE;
5969 #endif
5970 #ifdef UTF8_OUTPUT_ENABLE
5971                     ms_ucs_map_f = UCS_MAP_ASCII;
5972 #endif
5973                     continue;
5974                 }
5975 #ifdef SHIFTJIS_CP932
5976                 if (strcmp(long_option[i].name, "cp932inv") == 0){
5977                     cp932inv_f = -TRUE;
5978                     continue;
5979                 }
5980 #endif
5981
5982 #ifdef X0212_ENABLE
5983                 if (strcmp(long_option[i].name, "x0212") == 0){
5984                     x0212_f = TRUE;
5985                     continue;
5986                 }
5987 #endif
5988
5989 #ifdef EXEC_IO
5990                 if (strcmp(long_option[i].name, "exec-in") == 0){
5991                     exec_f = 1;
5992                     return 0;
5993                 }
5994                 if (strcmp(long_option[i].name, "exec-out") == 0){
5995                     exec_f = -1;
5996                     return 0;
5997                 }
5998 #endif
5999 #if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
6000                 if (strcmp(long_option[i].name, "no-cp932ext") == 0){
6001                     no_cp932ext_f = TRUE;
6002                     continue;
6003                 }
6004                 if (strcmp(long_option[i].name, "no-best-fit-chars") == 0){
6005                     no_best_fit_chars_f = TRUE;
6006                     continue;
6007                 }
6008                 if (strcmp(long_option[i].name, "fb-skip") == 0){
6009                     encode_fallback = NULL;
6010                     continue;
6011                 }
6012                 if (strcmp(long_option[i].name, "fb-html") == 0){
6013                     encode_fallback = encode_fallback_html;
6014                     continue;
6015                 }
6016                 if (strcmp(long_option[i].name, "fb-xml") == 0){
6017                     encode_fallback = encode_fallback_xml;
6018                     continue;
6019                 }
6020                 if (strcmp(long_option[i].name, "fb-java") == 0){
6021                     encode_fallback = encode_fallback_java;
6022                     continue;
6023                 }
6024                 if (strcmp(long_option[i].name, "fb-perl") == 0){
6025                     encode_fallback = encode_fallback_perl;
6026                     continue;
6027                 }
6028                 if (strcmp(long_option[i].name, "fb-subchar") == 0){
6029                     encode_fallback = encode_fallback_subchar;
6030                     continue;
6031                 }
6032                 if (strcmp(long_option[i].name, "fb-subchar=") == 0){
6033                     encode_fallback = encode_fallback_subchar;
6034                     unicode_subchar = 0;
6035                     if (p[0] != '0'){
6036                         /* decimal number */
6037                         for (i = 0; i < 7 && nkf_isdigit(p[i]); i++){
6038                             unicode_subchar *= 10;
6039                             unicode_subchar += hex2bin(p[i]);
6040                         }
6041                     }else if(p[1] == 'x' || p[1] == 'X'){
6042                         /* hexadecimal number */
6043                         for (i = 2; i < 8 && nkf_isxdigit(p[i]); i++){
6044                             unicode_subchar <<= 4;
6045                             unicode_subchar |= hex2bin(p[i]);
6046                         }
6047                     }else{
6048                         /* octal number */
6049                         for (i = 1; i < 8 && nkf_isoctal(p[i]); i++){
6050                             unicode_subchar *= 8;
6051                             unicode_subchar += hex2bin(p[i]);
6052                         }
6053                     }
6054                     w16e_conv(unicode_subchar, &i, &j);
6055                     unicode_subchar = i<<8 | j;
6056                     continue;
6057                 }
6058 #endif
6059 #ifdef UTF8_OUTPUT_ENABLE
6060                 if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
6061                     ms_ucs_map_f = UCS_MAP_MS;
6062                     continue;
6063                 }
6064 #endif
6065 #ifdef UNICODE_NORMALIZATION
6066                 if (strcmp(long_option[i].name, "utf8mac-input") == 0){
6067                     nfc_f = TRUE;
6068                     continue;
6069                 }
6070 #endif
6071                 if (strcmp(long_option[i].name, "prefix=") == 0){
6072                     if (nkf_isgraph(p[0])){
6073                         for (i = 1; nkf_isgraph(p[i]); i++){
6074                             prefix_table[p[i]] = p[0];
6075                         }
6076                     }
6077                     continue;
6078                 }
6079 #if !defined(PERL_XS) && !defined(WIN32DLL)
6080                 fprintf(stderr, "unsupported long option: --%s\n", long_option[i].name);
6081 #endif
6082                 return -1;
6083             }
6084             continue;
6085         case 'b':           /* buffered mode */
6086             unbuf_f = FALSE;
6087             continue;
6088         case 'u':           /* non bufferd mode */
6089             unbuf_f = TRUE;
6090             continue;
6091         case 't':           /* transparent mode */
6092             if (*cp=='1') {
6093                 /* alias of -t */
6094                 cp++;
6095                 nop_f = TRUE;
6096             } else if (*cp=='2') {
6097                 /*
6098                  * -t with put/get
6099                  *
6100                  * nkf -t2MB hoge.bin | nkf -t2mB | diff -s - hoge.bin
6101                  *
6102                  */
6103                 cp++;
6104                 nop_f = 2;
6105             } else
6106                 nop_f = TRUE;
6107             continue;
6108         case 'j':           /* JIS output */
6109         case 'n':
6110             output_encoding = nkf_enc_from_index(ISO_2022_JP);
6111             continue;
6112         case 'e':           /* AT&T EUC output */
6113             output_encoding = nkf_enc_from_index(EUCJP_NKF);
6114             continue;
6115         case 's':           /* SJIS output */
6116             output_encoding = nkf_enc_from_index(SHIFT_JIS);
6117             continue;
6118         case 'l':           /* ISO8859 Latin-1 support, no conversion */
6119             iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
6120             input_encoding = nkf_enc_from_index(ISO_8859_1);
6121             continue;
6122         case 'i':           /* Kanji IN ESC-$-@/B */
6123             if (*cp=='@'||*cp=='B')
6124                 kanji_intro = *cp++;
6125             continue;
6126         case 'o':           /* ASCII IN ESC-(-J/B/H */
6127             /* ESC ( H was used in initial JUNET messages */
6128             if (*cp=='J'||*cp=='B'||*cp=='H')
6129                 ascii_intro = *cp++;
6130             continue;
6131         case 'h':
6132             /*
6133                bit:1   katakana->hiragana
6134                bit:2   hiragana->katakana
6135              */
6136             if ('9'>= *cp && *cp>='0')
6137                 hira_f |= (*cp++ -'0');
6138             else
6139                 hira_f |= 1;
6140             continue;
6141         case 'r':
6142             rot_f = TRUE;
6143             continue;
6144 #if defined(MSDOS) || defined(__OS2__)
6145         case 'T':
6146             binmode_f = FALSE;
6147             continue;
6148 #endif
6149 #ifndef PERL_XS
6150         case 'V':
6151             show_configuration();
6152             exit(EXIT_SUCCESS);
6153             break;
6154         case 'v':
6155             version();
6156             exit(EXIT_SUCCESS);
6157             break;
6158 #endif
6159 #ifdef UTF8_OUTPUT_ENABLE
6160         case 'w':           /* UTF-8 output */
6161             if (cp[0] == '8') {
6162                 cp++;
6163                 if (cp[0] == '0'){
6164                     cp++;
6165                     output_encoding = nkf_enc_from_index(UTF_8N);
6166                 } else {
6167                     output_bom_f = TRUE;
6168                     output_encoding = nkf_enc_from_index(UTF_8_BOM);
6169                 }
6170             } else {
6171                 int enc_idx;
6172                 if ('1'== cp[0] && '6'==cp[1]) {
6173                     cp += 2;
6174                     enc_idx = UTF_16;
6175                 } else if ('3'== cp[0] && '2'==cp[1]) {
6176                     cp += 2;
6177                     enc_idx = UTF_32;
6178                 } else {
6179                     output_encoding = nkf_enc_from_index(UTF_8);
6180                     continue;
6181                 }
6182                 if (cp[0]=='L') {
6183                     cp++;
6184                     output_endian = ENDIAN_LITTLE;
6185                 } else if (cp[0] == 'B') {
6186                     cp++;
6187                 }
6188                 if (cp[0] == '0'){
6189                     cp++;
6190                     enc_idx = enc_idx == UTF_16
6191                         ? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
6192                         : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
6193                 } else {
6194                     output_bom_f = TRUE;
6195                     enc_idx = enc_idx == UTF_16
6196                         ? (output_endian == ENDIAN_LITTLE ? UTF_16LE_BOM : UTF_16BE_BOM)
6197                         : (output_endian == ENDIAN_LITTLE ? UTF_32LE_BOM : UTF_32BE_BOM);
6198                 }
6199                 output_encoding = nkf_enc_from_index(enc_idx);
6200             }
6201             continue;
6202 #endif
6203 #ifdef UTF8_INPUT_ENABLE
6204         case 'W':           /* UTF input */
6205             if (cp[0] == '8') {
6206                 cp++;
6207                 input_encoding = nkf_enc_from_index(UTF_8);
6208             }else{
6209                 int enc_idx;
6210                 if ('1'== cp[0] && '6'==cp[1]) {
6211                     cp += 2;
6212                     input_endian = ENDIAN_BIG;
6213                     enc_idx = UTF_16;
6214                 } else if ('3'== cp[0] && '2'==cp[1]) {
6215                     cp += 2;
6216                     input_endian = ENDIAN_BIG;
6217                     enc_idx = UTF_32;
6218                 } else {
6219                     input_encoding = nkf_enc_from_index(UTF_8);
6220                     continue;
6221                 }
6222                 if (cp[0]=='L') {
6223                     cp++;
6224                     input_endian = ENDIAN_LITTLE;
6225                 } else if (cp[0] == 'B') {
6226                     cp++;
6227                     input_endian = ENDIAN_BIG;
6228                 }
6229                 enc_idx = (enc_idx == UTF_16
6230                     ? (input_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
6231                     : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE));
6232                 input_encoding = nkf_enc_from_index(enc_idx);
6233             }
6234             continue;
6235 #endif
6236             /* Input code assumption */
6237         case 'J':   /* ISO-2022-JP input */
6238             input_encoding = nkf_enc_from_index(ISO_2022_JP);
6239             continue;
6240         case 'E':   /* EUC-JP input */
6241             input_encoding = nkf_enc_from_index(EUCJP_NKF);
6242             continue;
6243         case 'S':   /* Shift_JIS input */
6244             input_encoding = nkf_enc_from_index(SHIFT_JIS);
6245             continue;
6246         case 'Z':   /* Convert X0208 alphabet to asii */
6247             /* alpha_f
6248                bit:0   Convert JIS X 0208 Alphabet to ASCII
6249                bit:1   Convert Kankaku to one space
6250                bit:2   Convert Kankaku to two spaces
6251                bit:3   Convert HTML Entity
6252                bit:4   Convert JIS X 0208 Katakana to JIS X 0201 Katakana
6253              */
6254             while ('0'<= *cp && *cp <='4') {
6255                 alpha_f |= 1 << (*cp++ - '0');
6256             }
6257             alpha_f |= 1;
6258             continue;
6259         case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
6260             x0201_f = FALSE;    /* No X0201->X0208 conversion */
6261             /* accept  X0201
6262                ESC-(-I     in JIS, EUC, MS Kanji
6263                SI/SO       in JIS, EUC, MS Kanji
6264                SS2         in EUC, JIS, not in MS Kanji
6265                MS Kanji (0xa0-0xdf)
6266                output  X0201
6267                ESC-(-I     in JIS (0x20-0x5f)
6268                SS2         in EUC (0xa0-0xdf)
6269                0xa0-0xd    in MS Kanji (0xa0-0xdf)
6270              */
6271             continue;
6272         case 'X':   /* Convert X0201 kana to X0208 */
6273             x0201_f = TRUE;
6274             continue;
6275         case 'F':   /* prserve new lines */
6276             fold_preserve_f = TRUE;
6277         case 'f':   /* folding -f60 or -f */
6278             fold_f = TRUE;
6279             fold_len = 0;
6280             while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
6281                 fold_len *= 10;
6282                 fold_len += *cp++ - '0';
6283             }
6284             if (!(0<fold_len && fold_len<BUFSIZ))
6285                 fold_len = DEFAULT_FOLD;
6286             if (*cp=='-') {
6287                 fold_margin = 0;
6288                 cp++;
6289                 while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
6290                     fold_margin *= 10;
6291                     fold_margin += *cp++ - '0';
6292                 }
6293             }
6294             continue;
6295         case 'm':   /* MIME support */
6296             /* mime_decode_f = TRUE; */ /* this has too large side effects... */
6297             if (*cp=='B'||*cp=='Q') {
6298                 mime_decode_mode = *cp++;
6299                 mimebuf_f = FIXED_MIME;
6300             } else if (*cp=='N') {
6301                 mime_f = TRUE; cp++;
6302             } else if (*cp=='S') {
6303                 mime_f = STRICT_MIME; cp++;
6304             } else if (*cp=='0') {
6305                 mime_decode_f = FALSE;
6306                 mime_f = FALSE; cp++;
6307             } else {
6308                 mime_f = STRICT_MIME;
6309             }
6310             continue;
6311         case 'M':   /* MIME output */
6312             if (*cp=='B') {
6313                 mimeout_mode = 'B';
6314                 mimeout_f = FIXED_MIME; cp++;
6315             } else if (*cp=='Q') {
6316                 mimeout_mode = 'Q';
6317                 mimeout_f = FIXED_MIME; cp++;
6318             } else {
6319                 mimeout_f = TRUE;
6320             }
6321             continue;
6322         case 'B':   /* Broken JIS support */
6323             /*  bit:0   no ESC JIS
6324                bit:1   allow any x on ESC-(-x or ESC-$-x
6325                bit:2   reset to ascii on NL
6326              */
6327             if ('9'>= *cp && *cp>='0')
6328                 broken_f |= 1<<(*cp++ -'0');
6329             else
6330                 broken_f |= TRUE;
6331             continue;
6332 #ifndef PERL_XS
6333         case 'O':/* for Output file */
6334             file_out_f = TRUE;
6335             continue;
6336 #endif
6337         case 'c':/* add cr code */
6338             eolmode_f = CRLF;
6339             continue;
6340         case 'd':/* delete cr code */
6341             eolmode_f = LF;
6342             continue;
6343         case 'I':   /* ISO-2022-JP output */
6344             iso2022jp_f = TRUE;
6345             continue;
6346         case 'L':  /* line mode */
6347             if (*cp=='u') {         /* unix */
6348                 eolmode_f = LF; cp++;
6349             } else if (*cp=='m') { /* mac */
6350                 eolmode_f = CR; cp++;
6351             } else if (*cp=='w') { /* windows */
6352                 eolmode_f = CRLF; cp++;
6353             } else if (*cp=='0') { /* no conversion  */
6354                 eolmode_f = 0; cp++;
6355             }
6356             continue;
6357 #ifndef PERL_XS
6358         case 'g':
6359             if ('2' <= *cp && *cp <= '9') {
6360                 guess_f = 2;
6361                 cp++;
6362             } else if (*cp == '0' || *cp == '1') {
6363                 guess_f = 1;
6364                 cp++;
6365             } else {
6366                 guess_f = 1;
6367             }
6368             continue;
6369 #endif
6370         case SP:
6371             /* module muliple options in a string are allowed for Perl moudle  */
6372             while(*cp && *cp++!='-');
6373             continue;
6374         default:
6375 #if !defined(PERL_XS) && !defined(WIN32DLL)
6376             fprintf(stderr, "unknown option: -%c\n", *(cp-1));
6377 #endif
6378             /* bogus option but ignored */
6379             return -1;
6380         }
6381     }
6382     return 0;
6383 }
6384
6385 #ifdef WIN32DLL
6386 #include "nkf32dll.c"
6387 #elif defined(PERL_XS)
6388 #else /* WIN32DLL */
6389 int
6390 main(int argc, char **argv)
6391 {
6392     FILE  *fin;
6393     unsigned char  *cp;
6394
6395     char *outfname = NULL;
6396     char *origfname;
6397
6398 #ifdef EASYWIN /*Easy Win */
6399     _BufferSize.y = 400;/*Set Scroll Buffer Size*/
6400 #endif
6401 #ifdef DEFAULT_CODE_LOCALE
6402     setlocale(LC_CTYPE, "");
6403 #endif
6404     nkf_state_init();
6405
6406     for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
6407         cp = (unsigned char *)*argv;
6408         options(cp);
6409 #ifdef EXEC_IO
6410         if (exec_f){
6411             int fds[2], pid;
6412             if (pipe(fds) < 0 || (pid = fork()) < 0){
6413                 abort();
6414             }
6415             if (pid == 0){
6416                 if (exec_f > 0){
6417                     close(fds[0]);
6418                     dup2(fds[1], 1);
6419                 }else{
6420                     close(fds[1]);
6421                     dup2(fds[0], 0);
6422                 }
6423                 execvp(argv[1], &argv[1]);
6424             }
6425             if (exec_f > 0){
6426                 close(fds[1]);
6427                 dup2(fds[0], 0);
6428             }else{
6429                 close(fds[0]);
6430                 dup2(fds[1], 1);
6431             }
6432             argc = 0;
6433             break;
6434         }
6435 #endif
6436     }
6437
6438     if (guess_f) {
6439 #ifdef CHECK_OPTION
6440         int debug_f_back = debug_f;
6441 #endif
6442 #ifdef EXEC_IO
6443         int exec_f_back = exec_f;
6444 #endif
6445 #ifdef X0212_ENABLE
6446         int x0212_f_back = x0212_f;
6447 #endif
6448         int x0213_f_back = x0213_f;
6449         int guess_f_back = guess_f;
6450         reinit();
6451         guess_f = guess_f_back;
6452         mime_f = FALSE;
6453 #ifdef CHECK_OPTION
6454         debug_f = debug_f_back;
6455 #endif
6456 #ifdef EXEC_IO
6457         exec_f = exec_f_back;
6458 #endif
6459         x0212_f = x0212_f_back;
6460         x0213_f = x0213_f_back;
6461     }
6462
6463     if (binmode_f == TRUE)
6464 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
6465         if (freopen("","wb",stdout) == NULL)
6466             return (-1);
6467 #else
6468     setbinmode(stdout);
6469 #endif
6470
6471     if (unbuf_f)
6472         setbuf(stdout, (char *) NULL);
6473     else
6474         setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE);
6475
6476     if (argc == 0) {
6477         if (binmode_f == TRUE)
6478 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
6479             if (freopen("","rb",stdin) == NULL) return (-1);
6480 #else
6481         setbinmode(stdin);
6482 #endif
6483         setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE);
6484         if (nop_f)
6485             noconvert(stdin);
6486         else {
6487             kanji_convert(stdin);
6488             if (guess_f) print_guessed_code(NULL);
6489         }
6490     } else {
6491         int nfiles = argc;
6492         int is_argument_error = FALSE;
6493         while (argc--) {
6494             input_codename = NULL;
6495             input_eol = 0;
6496 #ifdef CHECK_OPTION
6497             iconv_for_check = 0;
6498 #endif
6499             if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
6500                 perror(*(argv-1));
6501                 is_argument_error = TRUE;
6502                 continue;
6503             } else {
6504 #ifdef OVERWRITE
6505                 int fd = 0;
6506                 int fd_backup = 0;
6507 #endif
6508
6509                 /* reopen file for stdout */
6510                 if (file_out_f == TRUE) {
6511 #ifdef OVERWRITE
6512                     if (overwrite_f){
6513                         outfname = nkf_xmalloc(strlen(origfname)
6514                                           + strlen(".nkftmpXXXXXX")
6515                                           + 1);
6516                         strcpy(outfname, origfname);
6517 #ifdef MSDOS
6518                         {
6519                             int i;
6520                             for (i = strlen(outfname); i; --i){
6521                                 if (outfname[i - 1] == '/'
6522                                     || outfname[i - 1] == '\\'){
6523                                     break;
6524                                 }
6525                             }
6526                             outfname[i] = '\0';
6527                         }
6528                         strcat(outfname, "ntXXXXXX");
6529                         mktemp(outfname);
6530                         fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
6531                                   S_IREAD | S_IWRITE);
6532 #else
6533                         strcat(outfname, ".nkftmpXXXXXX");
6534                         fd = mkstemp(outfname);
6535 #endif
6536                         if (fd < 0
6537                             || (fd_backup = dup(fileno(stdout))) < 0
6538                             || dup2(fd, fileno(stdout)) < 0
6539                            ){
6540                             perror(origfname);
6541                             return -1;
6542                         }
6543                     }else
6544 #endif
6545                     if(argc == 1) {
6546                         outfname = *argv++;
6547                         argc--;
6548                     } else {
6549                         outfname = "nkf.out";
6550                     }
6551
6552                     if(freopen(outfname, "w", stdout) == NULL) {
6553                         perror (outfname);
6554                         return (-1);
6555                     }
6556                     if (binmode_f == TRUE) {
6557 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
6558                         if (freopen("","wb",stdout) == NULL)
6559                             return (-1);
6560 #else
6561                         setbinmode(stdout);
6562 #endif
6563                     }
6564                 }
6565                 if (binmode_f == TRUE)
6566 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
6567                     if (freopen("","rb",fin) == NULL)
6568                         return (-1);
6569 #else
6570                 setbinmode(fin);
6571 #endif
6572                 setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE);
6573                 if (nop_f)
6574                     noconvert(fin);
6575                 else {
6576                     char *filename = NULL;
6577                     kanji_convert(fin);
6578                     if (nfiles > 1) filename = origfname;
6579                     if (guess_f) print_guessed_code(filename);
6580                 }
6581                 fclose(fin);
6582 #ifdef OVERWRITE
6583                 if (overwrite_f) {
6584                     struct stat     sb;
6585 #if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
6586                     time_t tb[2];
6587 #else
6588                     struct utimbuf  tb;
6589 #endif
6590
6591                     fflush(stdout);
6592                     close(fd);
6593                     if (dup2(fd_backup, fileno(stdout)) < 0){
6594                         perror("dup2");
6595                     }
6596                     if (stat(origfname, &sb)) {
6597                         fprintf(stderr, "Can't stat %s\n", origfname);
6598                     }
6599                     /* \e$B%Q!<%_%C%7%g%s$rI|85\e(B */
6600                     if (chmod(outfname, sb.st_mode)) {
6601                         fprintf(stderr, "Can't set permission %s\n", outfname);
6602                     }
6603
6604                     /* \e$B%?%$%`%9%?%s%W$rI|85\e(B */
6605                     if(preserve_time_f){
6606 #if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
6607                         tb[0] = tb[1] = sb.st_mtime;
6608                         if (utime(outfname, tb)) {
6609                             fprintf(stderr, "Can't set timestamp %s\n", outfname);
6610                         }
6611 #else
6612                         tb.actime  = sb.st_atime;
6613                         tb.modtime = sb.st_mtime;
6614                         if (utime(outfname, &tb)) {
6615                             fprintf(stderr, "Can't set timestamp %s\n", outfname);
6616                         }
6617 #endif
6618                     }
6619                     if(backup_f){
6620                         char *backup_filename = get_backup_filename(backup_suffix, origfname);
6621 #ifdef MSDOS
6622                         unlink(backup_filename);
6623 #endif
6624                         if (rename(origfname, backup_filename)) {
6625                             perror(backup_filename);
6626                             fprintf(stderr, "Can't rename %s to %s\n",
6627                                     origfname, backup_filename);
6628                         }
6629                         nkf_xfree(backup_filename);
6630                     }else{
6631 #ifdef MSDOS
6632                         if (unlink(origfname)){
6633                             perror(origfname);
6634                         }
6635 #endif
6636                     }
6637                     if (rename(outfname, origfname)) {
6638                         perror(origfname);
6639                         fprintf(stderr, "Can't rename %s to %s\n",
6640                                 outfname, origfname);
6641                     }
6642                     nkf_xfree(outfname);
6643                 }
6644 #endif
6645             }
6646         }
6647         if (is_argument_error)
6648             return(-1);
6649     }
6650 #ifdef EASYWIN /*Easy Win */
6651     if (file_out_f == FALSE)
6652         scanf("%d",&end_check);
6653     else
6654         fclose(stdout);
6655 #else /* for Other OS */
6656     if (file_out_f == TRUE)
6657         fclose(stdout);
6658 #endif /*Easy Win */
6659     return (0);
6660 }
6661 #endif /* WIN32DLL */