OSDN Git Service

Release 2.1.0.
[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 (base64_count + mimeout_state.count/3*4> 66) {
4653                 (*o_base64conv)(EOF,0);
4654                 OCONV_NEWLINE((*o_base64conv));
4655                 (*o_base64conv)(0,SP);
4656                 base64_count = 1;
4657                 mimeout_mode = -1;
4658             }
4659         }
4660     } else if (c2) {
4661         if (c2 != EOF && base64_count + mimeout_state.count/3*4> 60) {
4662             mimeout_mode =  (output_mode==ASCII ||output_mode == ISO_8859_1) ? 'Q' : 'B';
4663             open_mime(output_mode);
4664             (*o_base64conv)(EOF,0);
4665             OCONV_NEWLINE((*o_base64conv));
4666             (*o_base64conv)(0,SP);
4667             base64_count = 1;
4668             mimeout_mode = -1;
4669         }
4670     }
4671 }
4672
4673 static void
4674 close_mime(void)
4675 {
4676     (*o_mputc)('?');
4677     (*o_mputc)('=');
4678     base64_count += 2;
4679     mimeout_mode = 0;
4680 }
4681
4682 static void
4683 eof_mime(void)
4684 {
4685     switch(mimeout_mode) {
4686     case 'Q':
4687     case 'B':
4688         break;
4689     case 2:
4690         (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4)]);
4691         (*o_mputc)('=');
4692         (*o_mputc)('=');
4693         base64_count += 3;
4694         break;
4695     case 1:
4696         (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2)]);
4697         (*o_mputc)('=');
4698         base64_count += 2;
4699         break;
4700     }
4701     if (mimeout_mode > 0) {
4702         if (mimeout_f!=FIXED_MIME) {
4703             close_mime();
4704         } else if (mimeout_mode != 'Q')
4705             mimeout_mode = 'B';
4706     }
4707 }
4708
4709 static void
4710 mimeout_addchar(nkf_char c)
4711 {
4712     switch(mimeout_mode) {
4713     case 'Q':
4714         if (c==CR||c==LF) {
4715             (*o_mputc)(c);
4716             base64_count = 0;
4717         } else if(!nkf_isalnum(c)) {
4718             (*o_mputc)('=');
4719             (*o_mputc)(bin2hex(((c>>4)&0xf)));
4720             (*o_mputc)(bin2hex((c&0xf)));
4721             base64_count += 3;
4722         } else {
4723             (*o_mputc)(c);
4724             base64_count++;
4725         }
4726         break;
4727     case 'B':
4728         nkf_state->mimeout_state=c;
4729         (*o_mputc)(basis_64[c>>2]);
4730         mimeout_mode=2;
4731         base64_count ++;
4732         break;
4733     case 2:
4734         (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
4735         nkf_state->mimeout_state=c;
4736         mimeout_mode=1;
4737         base64_count ++;
4738         break;
4739     case 1:
4740         (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2) | ((c & 0xC0) >>6)]);
4741         (*o_mputc)(basis_64[c & 0x3F]);
4742         mimeout_mode='B';
4743         base64_count += 2;
4744         break;
4745     default:
4746         (*o_mputc)(c);
4747         base64_count++;
4748         break;
4749     }
4750 }
4751
4752 static void
4753 mime_putc(nkf_char c)
4754 {
4755     int i, j;
4756     nkf_char lastchar;
4757
4758     if (mimeout_f == FIXED_MIME){
4759         if (mimeout_mode == 'Q'){
4760             if (base64_count > 71){
4761                 if (c!=CR && c!=LF) {
4762                     (*o_mputc)('=');
4763                     PUT_NEWLINE((*o_mputc));
4764                 }
4765                 base64_count = 0;
4766             }
4767         }else{
4768             if (base64_count > 71){
4769                 eof_mime();
4770                 PUT_NEWLINE((*o_mputc));
4771                 base64_count = 0;
4772             }
4773             if (c == EOF) { /* c==EOF */
4774                 eof_mime();
4775             }
4776         }
4777         if (c != EOF) { /* c==EOF */
4778             mimeout_addchar(c);
4779         }
4780         return;
4781     }
4782
4783     /* mimeout_f != FIXED_MIME */
4784
4785     if (c == EOF) { /* c==EOF */
4786         if (mimeout_mode == -1 && mimeout_state.count > 1) open_mime(output_mode);
4787         j = mimeout_state.count;
4788         mimeout_state.count = 0;
4789         i = 0;
4790         if (mimeout_mode > 0) {
4791             if (!nkf_isblank(mimeout_state.buf[j-1])) {
4792                 for (;i<j;i++) {
4793                     if (nkf_isspace(mimeout_state.buf[i]) && base64_count < 71){
4794                         break;
4795                     }
4796                     mimeout_addchar(mimeout_state.buf[i]);
4797                 }
4798                 eof_mime();
4799                 for (;i<j;i++) {
4800                     mimeout_addchar(mimeout_state.buf[i]);
4801                 }
4802             } else {
4803                 for (;i<j;i++) {
4804                     mimeout_addchar(mimeout_state.buf[i]);
4805                 }
4806                 eof_mime();
4807             }
4808         } else {
4809             for (;i<j;i++) {
4810                 mimeout_addchar(mimeout_state.buf[i]);
4811             }
4812         }
4813         return;
4814     }
4815
4816     if (mimeout_state.count > 0){
4817         lastchar = mimeout_state.buf[mimeout_state.count - 1];
4818     }else{
4819         lastchar = -1;
4820     }
4821
4822     if (mimeout_mode=='Q') {
4823         if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
4824             if (c == CR || c == LF) {
4825                 close_mime();
4826                 (*o_mputc)(c);
4827                 base64_count = 0;
4828                 return;
4829             } else if (c <= SP) {
4830                 close_mime();
4831                 if (base64_count > 70) {
4832                     PUT_NEWLINE((*o_mputc));
4833                     base64_count = 0;
4834                 }
4835                 if (!nkf_isblank(c)) {
4836                     (*o_mputc)(SP);
4837                     base64_count++;
4838                 }
4839             } else {
4840                 if (base64_count > 70) {
4841                     close_mime();
4842                     PUT_NEWLINE((*o_mputc));
4843                     (*o_mputc)(SP);
4844                     base64_count = 1;
4845                     open_mime(output_mode);
4846                 }
4847                 if (!nkf_noescape_mime(c)) {
4848                     mimeout_addchar(c);
4849                     return;
4850                 }
4851             }
4852             (*o_mputc)(c);
4853             base64_count++;
4854         }
4855         return;
4856     }
4857
4858     if (mimeout_mode <= 0) {
4859         if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
4860             if (nkf_isspace(c)) {
4861                 int flag = 0;
4862                 if (mimeout_mode == -1) {
4863                     flag = 1;
4864                 }
4865                 if (c==CR || c==LF) {
4866                     if (flag) {
4867                         open_mime(output_mode);
4868                         output_mode = 0;
4869                     } else {
4870                         base64_count = 0;
4871                     }
4872                 }
4873                 for (i=0;i<mimeout_state.count;i++) {
4874                     (*o_mputc)(mimeout_state.buf[i]);
4875                     if (mimeout_state.buf[i] == CR || mimeout_state.buf[i] == LF){
4876                         base64_count = 0;
4877                     }else{
4878                         base64_count++;
4879                     }
4880                 }
4881                 if (flag) {
4882                     eof_mime();
4883                     base64_count = 0;
4884                     mimeout_mode = 0;
4885                 }
4886                 mimeout_state.buf[0] = (char)c;
4887                 mimeout_state.count = 1;
4888             }else{
4889                 if (base64_count > 1
4890                     && base64_count + mimeout_state.count > 76
4891                     && mimeout_state.buf[0] != CR && mimeout_state.buf[0] != LF){
4892                     static const char *str = "boundary=\"";
4893                     static int len = 10;
4894                     i = 0;
4895
4896                     for (; i < mimeout_state.count - len; ++i) {
4897                         if (!strncmp(mimeout_state.buf+i, str, len)) {
4898                             i += len - 2;
4899                             break;
4900                         }
4901                     }
4902
4903                     if (i == 0 || i == mimeout_state.count - len) {
4904                         PUT_NEWLINE((*o_mputc));
4905                         base64_count = 0;
4906                         if (!nkf_isspace(mimeout_state.buf[0])){
4907                             (*o_mputc)(SP);
4908                             base64_count++;
4909                         }
4910                     }
4911                     else {
4912                         int j;
4913                         for (j = 0; j <= i; ++j) {
4914                             (*o_mputc)(mimeout_state.buf[j]);
4915                         }
4916                         PUT_NEWLINE((*o_mputc));
4917                         base64_count = 1;
4918                         for (; j <= mimeout_state.count; ++j) {
4919                             mimeout_state.buf[j - i] = mimeout_state.buf[j];
4920                         }
4921                         mimeout_state.count -= i;
4922                     }
4923                 }
4924                 mimeout_state.buf[mimeout_state.count++] = (char)c;
4925                 if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
4926                     open_mime(output_mode);
4927                 }
4928             }
4929             return;
4930         }else{
4931             if (lastchar==CR || lastchar == LF){
4932                 for (i=0;i<mimeout_state.count;i++) {
4933                     (*o_mputc)(mimeout_state.buf[i]);
4934                 }
4935                 base64_count = 0;
4936                 mimeout_state.count = 0;
4937             }
4938             if (lastchar==SP) {
4939                 for (i=0;i<mimeout_state.count-1;i++) {
4940                     (*o_mputc)(mimeout_state.buf[i]);
4941                     base64_count++;
4942                 }
4943                 mimeout_state.buf[0] = SP;
4944                 mimeout_state.count = 1;
4945             }
4946             open_mime(output_mode);
4947         }
4948     }else{
4949         /* mimeout_mode == 'B', 1, 2 */
4950         if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
4951             if (lastchar == CR || lastchar == LF){
4952                 if (nkf_isblank(c)) {
4953                     for (i=0;i<mimeout_state.count;i++) {
4954                         mimeout_addchar(mimeout_state.buf[i]);
4955                     }
4956                     mimeout_state.count = 0;
4957                 } else if (SP<c && c<DEL) {
4958                     eof_mime();
4959                     for (i=0;i<mimeout_state.count;i++) {
4960                         (*o_mputc)(mimeout_state.buf[i]);
4961                     }
4962                     base64_count = 0;
4963                     mimeout_state.count = 0;
4964                 }
4965                 mimeout_state.buf[mimeout_state.count++] = (char)c;
4966                 return;
4967             }
4968             if (nkf_isspace(c)) {
4969                 for (i=0;i<mimeout_state.count;i++) {
4970                     if (SP<mimeout_state.buf[i] && mimeout_state.buf[i]<DEL) {
4971                         eof_mime();
4972                         for (i=0;i<mimeout_state.count;i++) {
4973                             (*o_mputc)(mimeout_state.buf[i]);
4974                             base64_count++;
4975                         }
4976                         mimeout_state.count = 0;
4977                     }
4978                 }
4979                 mimeout_state.buf[mimeout_state.count++] = (char)c;
4980                 if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
4981                     eof_mime();
4982                     for (i=0;i<mimeout_state.count;i++) {
4983                         (*o_mputc)(mimeout_state.buf[i]);
4984                         base64_count++;
4985                     }
4986                     mimeout_state.count = 0;
4987                 }
4988                 return;
4989             }
4990             if (mimeout_state.count>0 && SP<c && c!='=') {
4991                 mimeout_state.buf[mimeout_state.count++] = (char)c;
4992                 if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
4993                     j = mimeout_state.count;
4994                     mimeout_state.count = 0;
4995                     for (i=0;i<j;i++) {
4996                         mimeout_addchar(mimeout_state.buf[i]);
4997                     }
4998                 }
4999                 return;
5000             }
5001         }
5002     }
5003     if (mimeout_state.count>0) {
5004         j = mimeout_state.count;
5005         mimeout_state.count = 0;
5006         for (i=0;i<j;i++) {
5007             if (mimeout_state.buf[i]==CR || mimeout_state.buf[i]==LF)
5008                 break;
5009             mimeout_addchar(mimeout_state.buf[i]);
5010         }
5011         if (i<j) {
5012             eof_mime();
5013             base64_count=0;
5014             for (;i<j;i++) {
5015                 (*o_mputc)(mimeout_state.buf[i]);
5016             }
5017             open_mime(output_mode);
5018         }
5019     }
5020     mimeout_addchar(c);
5021 }
5022
5023 static void
5024 base64_conv(nkf_char c2, nkf_char c1)
5025 {
5026     mime_prechar(c2, c1);
5027     (*o_base64conv)(c2,c1);
5028 }
5029
5030 #ifdef HAVE_ICONV_H
5031 typedef struct nkf_iconv_t {
5032     iconv_t cd;
5033     char *input_buffer;
5034     size_t input_buffer_size;
5035     char *output_buffer;
5036     size_t output_buffer_size;
5037 }
5038
5039 static nkf_iconv_t
5040 nkf_iconv_new(char *tocode, char *fromcode)
5041 {
5042     nkf_iconv_t converter;
5043
5044     converter->input_buffer_size = IOBUF_SIZE;
5045     converter->input_buffer = nkf_xmalloc(converter->input_buffer_size);
5046     converter->output_buffer_size = IOBUF_SIZE * 2;
5047     converter->output_buffer = nkf_xmalloc(converter->output_buffer_size);
5048     converter->cd = iconv_open(tocode, fromcode);
5049     if (converter->cd == (iconv_t)-1)
5050     {
5051         switch (errno) {
5052         case EINVAL:
5053             perror(fprintf("iconv doesn't support %s to %s conversion.", fromcode, tocode));
5054             return -1;
5055         default:
5056             perror("can't iconv_open");
5057         }
5058     }
5059 }
5060
5061 static size_t
5062 nkf_iconv_convert(nkf_iconv_t *converter, FILE *input)
5063 {
5064     size_t invalid = (size_t)0;
5065     char *input_buffer = converter->input_buffer;
5066     size_t input_length = (size_t)0;
5067     char *output_buffer = converter->output_buffer;
5068     size_t output_length = converter->output_buffer_size;
5069     int c;
5070
5071     do {
5072         if (c != EOF) {
5073             while ((c = (*i_getc)(f)) != EOF) {
5074                 input_buffer[input_length++] = c;
5075                 if (input_length < converter->input_buffer_size) break;
5076             }
5077         }
5078
5079         size_t ret = iconv(converter->cd, &input_buffer, &input_length, &output_buffer, &output_length);
5080         while (output_length-- > 0) {
5081             (*o_putc)(output_buffer[converter->output_buffer_size-output_length]);
5082         }
5083         if (ret == (size_t) - 1) {
5084             switch (errno) {
5085             case EINVAL:
5086                 if (input_buffer != converter->input_buffer)
5087                     memmove(converter->input_buffer, input_buffer, input_length);
5088                 break;
5089             case E2BIG:
5090                 converter->output_buffer_size *= 2;
5091                 output_buffer = realloc(converter->outbuf, converter->output_buffer_size);
5092                 if (output_buffer == NULL) {
5093                     perror("can't realloc");
5094                     return -1;
5095                 }
5096                 converter->output_buffer = output_buffer;
5097                 break;
5098             default:
5099                 perror("can't iconv");
5100                 return -1;
5101             }
5102         } else {
5103             invalid += ret;
5104         }
5105     } while (1);
5106
5107     return invalid;
5108 }
5109
5110
5111 static void
5112 nkf_iconv_close(nkf_iconv_t *convert)
5113 {
5114     nkf_xfree(converter->inbuf);
5115     nkf_xfree(converter->outbuf);
5116     iconv_close(converter->cd);
5117 }
5118 #endif
5119
5120
5121 static void
5122 reinit(void)
5123 {
5124     {
5125         struct input_code *p = input_code_list;
5126         while (p->name){
5127             status_reinit(p++);
5128         }
5129     }
5130     unbuf_f = FALSE;
5131     estab_f = FALSE;
5132     nop_f = FALSE;
5133     binmode_f = TRUE;
5134     rot_f = FALSE;
5135     hira_f = FALSE;
5136     alpha_f = FALSE;
5137     mime_f = MIME_DECODE_DEFAULT;
5138     mime_decode_f = FALSE;
5139     mimebuf_f = FALSE;
5140     broken_f = FALSE;
5141     iso8859_f = FALSE;
5142     mimeout_f = FALSE;
5143     x0201_f = X0201_DEFAULT;
5144     iso2022jp_f = FALSE;
5145 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
5146     ms_ucs_map_f = UCS_MAP_ASCII;
5147 #endif
5148 #ifdef UTF8_INPUT_ENABLE
5149     no_cp932ext_f = FALSE;
5150     no_best_fit_chars_f = FALSE;
5151     encode_fallback = NULL;
5152     unicode_subchar  = '?';
5153     input_endian = ENDIAN_BIG;
5154 #endif
5155 #ifdef UTF8_OUTPUT_ENABLE
5156     output_bom_f = FALSE;
5157     output_endian = ENDIAN_BIG;
5158 #endif
5159 #ifdef UNICODE_NORMALIZATION
5160     nfc_f = FALSE;
5161 #endif
5162 #ifdef INPUT_OPTION
5163     cap_f = FALSE;
5164     url_f = FALSE;
5165     numchar_f = FALSE;
5166 #endif
5167 #ifdef CHECK_OPTION
5168     noout_f = FALSE;
5169     debug_f = FALSE;
5170 #endif
5171     guess_f = 0;
5172 #ifdef EXEC_IO
5173     exec_f = 0;
5174 #endif
5175 #ifdef SHIFTJIS_CP932
5176     cp51932_f = TRUE;
5177     cp932inv_f = TRUE;
5178 #endif
5179 #ifdef X0212_ENABLE
5180     x0212_f = FALSE;
5181     x0213_f = FALSE;
5182 #endif
5183     {
5184         int i;
5185         for (i = 0; i < 256; i++){
5186             prefix_table[i] = 0;
5187         }
5188     }
5189     hold_count = 0;
5190     mimeout_state.count = 0;
5191     mimeout_mode = 0;
5192     base64_count = 0;
5193     f_line = 0;
5194     f_prev = 0;
5195     fold_preserve_f = FALSE;
5196     fold_f = FALSE;
5197     fold_len = 0;
5198     kanji_intro = DEFAULT_J;
5199     ascii_intro = DEFAULT_R;
5200     fold_margin  = FOLD_MARGIN;
5201     o_zconv = no_connection;
5202     o_fconv = no_connection;
5203     o_eol_conv = no_connection;
5204     o_rot_conv = no_connection;
5205     o_hira_conv = no_connection;
5206     o_base64conv = no_connection;
5207     o_iso2022jp_check_conv = no_connection;
5208     o_putc = std_putc;
5209     i_getc = std_getc;
5210     i_ungetc = std_ungetc;
5211     i_bgetc = std_getc;
5212     i_bungetc = std_ungetc;
5213     o_mputc = std_putc;
5214     i_mgetc = std_getc;
5215     i_mungetc  = std_ungetc;
5216     i_mgetc_buf = std_getc;
5217     i_mungetc_buf = std_ungetc;
5218     output_mode = ASCII;
5219     input_mode =  ASCII;
5220     mime_decode_mode = FALSE;
5221     file_out_f = FALSE;
5222     eolmode_f = 0;
5223     input_eol = 0;
5224     prev_cr = 0;
5225     option_mode = 0;
5226     z_prev2=0,z_prev1=0;
5227 #ifdef CHECK_OPTION
5228     iconv_for_check = 0;
5229 #endif
5230     input_codename = NULL;
5231     input_encoding = NULL;
5232     output_encoding = NULL;
5233     nkf_state_init();
5234 #ifdef WIN32DLL
5235     reinitdll();
5236 #endif /*WIN32DLL*/
5237 }
5238
5239 static int
5240 module_connection(void)
5241 {
5242     if (input_encoding) set_input_encoding(input_encoding);
5243     if (!output_encoding) {
5244         output_encoding = nkf_default_encoding();
5245     }
5246     if (!output_encoding) {
5247         if (noout_f || guess_f) output_encoding = nkf_enc_from_index(ISO_2022_JP);
5248         else return -1;
5249     }
5250     set_output_encoding(output_encoding);
5251     oconv = nkf_enc_to_oconv(output_encoding);
5252     o_putc = std_putc;
5253
5254     /* replace continucation module, from output side */
5255
5256     /* output redicrection */
5257 #ifdef CHECK_OPTION
5258     if (noout_f || guess_f){
5259         o_putc = no_putc;
5260     }
5261 #endif
5262     if (mimeout_f) {
5263         o_mputc = o_putc;
5264         o_putc = mime_putc;
5265         if (mimeout_f == TRUE) {
5266             o_base64conv = oconv; oconv = base64_conv;
5267         }
5268         /* base64_count = 0; */
5269     }
5270
5271     if (eolmode_f || guess_f) {
5272         o_eol_conv = oconv; oconv = eol_conv;
5273     }
5274     if (rot_f) {
5275         o_rot_conv = oconv; oconv = rot_conv;
5276     }
5277     if (iso2022jp_f) {
5278         o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
5279     }
5280     if (hira_f) {
5281         o_hira_conv = oconv; oconv = hira_conv;
5282     }
5283     if (fold_f) {
5284         o_fconv = oconv; oconv = fold_conv;
5285         f_line = 0;
5286     }
5287     if (alpha_f || x0201_f) {
5288         o_zconv = oconv; oconv = z_conv;
5289     }
5290
5291     i_getc = std_getc;
5292     i_ungetc = std_ungetc;
5293     /* input redicrection */
5294 #ifdef INPUT_OPTION
5295     if (cap_f){
5296         i_cgetc = i_getc; i_getc = cap_getc;
5297         i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
5298     }
5299     if (url_f){
5300         i_ugetc = i_getc; i_getc = url_getc;
5301         i_uungetc = i_ungetc; i_ungetc= url_ungetc;
5302     }
5303 #endif
5304 #ifdef NUMCHAR_OPTION
5305     if (numchar_f){
5306         i_ngetc = i_getc; i_getc = numchar_getc;
5307         i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
5308     }
5309 #endif
5310 #ifdef UNICODE_NORMALIZATION
5311     if (nfc_f){
5312         i_nfc_getc = i_getc; i_getc = nfc_getc;
5313         i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
5314     }
5315 #endif
5316     if (mime_f && mimebuf_f==FIXED_MIME) {
5317         i_mgetc = i_getc; i_getc = mime_getc;
5318         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
5319     }
5320     if (broken_f & 1) {
5321         i_bgetc = i_getc; i_getc = broken_getc;
5322         i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
5323     }
5324     if (input_encoding) {
5325         set_iconv(-TRUE, nkf_enc_to_iconv(input_encoding));
5326     } else {
5327         set_iconv(FALSE, e_iconv);
5328     }
5329
5330     {
5331         struct input_code *p = input_code_list;
5332         while (p->name){
5333             status_reinit(p++);
5334         }
5335     }
5336     return 0;
5337 }
5338
5339 /*
5340    Conversion main loop. Code detection only.
5341  */
5342
5343 #if !defined(PERL_XS) && !defined(WIN32DLL)
5344 static nkf_char
5345 noconvert(FILE *f)
5346 {
5347     nkf_char    c;
5348
5349     if (nop_f == 2)
5350         module_connection();
5351     while ((c = (*i_getc)(f)) != EOF)
5352         (*o_putc)(c);
5353     (*o_putc)(EOF);
5354     return 1;
5355 }
5356 #endif
5357
5358 #define NEXT continue        /* no output, get next */
5359 #define SKIP c2=0;continue        /* no output, get next */
5360 #define MORE c2=c1;continue  /* need one more byte */
5361 #define SEND ;               /* output c1 and c2, get next */
5362 #define LAST break           /* end of loop, go closing  */
5363 #define set_input_mode(mode) do { \
5364     input_mode = mode; \
5365     shift_mode = 0; \
5366     set_input_codename("ISO-2022-JP"); \
5367     debug("ISO-2022-JP"); \
5368 } while (0)
5369
5370 static int
5371 kanji_convert(FILE *f)
5372 {
5373     nkf_char c1=0, c2=0, c3=0, c4=0;
5374     int shift_mode = 0; /* 0, 1, 2, 3 */
5375     int g2 = 0;
5376     int is_8bit = FALSE;
5377
5378     if (input_encoding && !nkf_enc_asciicompat(input_encoding)) {
5379         is_8bit = TRUE;
5380     }
5381
5382     input_mode = ASCII;
5383     output_mode = ASCII;
5384
5385     if (module_connection() < 0) {
5386 #if !defined(PERL_XS) && !defined(WIN32DLL)
5387         fprintf(stderr, "no output encoding given\n");
5388 #endif
5389         return -1;
5390     }
5391     check_bom(f);
5392
5393 #ifdef UTF8_INPUT_ENABLE
5394     if(iconv == w_iconv32){
5395         while ((c1 = (*i_getc)(f)) != EOF &&
5396                (c2 = (*i_getc)(f)) != EOF &&
5397                (c3 = (*i_getc)(f)) != EOF &&
5398                (c4 = (*i_getc)(f)) != EOF) {
5399             nkf_iconv_utf_32(c1, c2, c3, c4);
5400         }
5401         (*i_ungetc)(EOF, f);
5402     }
5403     else if (iconv == w_iconv16) {
5404         while ((c1 = (*i_getc)(f)) != EOF &&
5405                (c2 = (*i_getc)(f)) != EOF) {
5406             if (nkf_iconv_utf_16(c1, c2, 0, 0) == -2 &&
5407                 (c3 = (*i_getc)(f)) != EOF &&
5408                 (c4 = (*i_getc)(f)) != EOF) {
5409                 nkf_iconv_utf_16(c1, c2, c3, c4);
5410             }
5411         }
5412         (*i_ungetc)(EOF, f);
5413     }
5414 #endif
5415
5416     while ((c1 = (*i_getc)(f)) != EOF) {
5417 #ifdef INPUT_CODE_FIX
5418         if (!input_encoding)
5419 #endif
5420             code_status(c1);
5421         if (c2) {
5422             /* second byte */
5423             if (c2 > DEL) {
5424                 /* in case of 8th bit is on */
5425                 if (!estab_f&&!mime_decode_mode) {
5426                     /* in case of not established yet */
5427                     /* It is still ambiguious */
5428                     if (h_conv(f, c2, c1)==EOF) {
5429                         LAST;
5430                     }
5431                     else {
5432                         SKIP;
5433                     }
5434                 }
5435                 else {
5436                     /* in case of already established */
5437                     if (c1 < 0x40) {
5438                         /* ignore bogus code */
5439                         SKIP;
5440                     } else {
5441                         SEND;
5442                     }
5443                 }
5444             }
5445             else {
5446                 /* 2nd byte of 7 bit code or SJIS */
5447                 SEND;
5448             }
5449         }
5450         else if (nkf_char_unicode_p(c1)) {
5451             (*oconv)(0, c1);
5452             NEXT;
5453         }
5454         else {
5455             /* first byte */
5456             if (input_mode == JIS_X_0208 && DEL <= c1 && c1 < 0x92) {
5457                 /* CP5022x */
5458                 MORE;
5459             }else if (input_codename && input_codename[0] == 'I' &&
5460                     0xA1 <= c1 && c1 <= 0xDF) {
5461                 /* JIS X 0201 Katakana in 8bit JIS */
5462                 c2 = JIS_X_0201_1976_K;
5463                 c1 &= 0x7f;
5464                 SEND;
5465             } else if (c1 > DEL) {
5466                 /* 8 bit code */
5467                 if (!estab_f && !iso8859_f) {
5468                     /* not established yet */
5469                     MORE;
5470                 } else { /* estab_f==TRUE */
5471                     if (iso8859_f) {
5472                         c2 = ISO_8859_1;
5473                         c1 &= 0x7f;
5474                         SEND;
5475                     }
5476                     else if ((iconv == s_iconv && 0xA0 <= c1 && c1 <= 0xDF) ||
5477                              (ms_ucs_map_f == UCS_MAP_CP10001 && (c1 == 0xFD || c1 == 0xFE))) {
5478                         /* JIS X 0201 */
5479                         c2 = JIS_X_0201_1976_K;
5480                         c1 &= 0x7f;
5481                         SEND;
5482                     }
5483                     else {
5484                         /* already established */
5485                         MORE;
5486                     }
5487                 }
5488             } else if (SP < c1 && c1 < DEL) {
5489                 /* in case of Roman characters */
5490                 if (shift_mode) {
5491                     /* output 1 shifted byte */
5492                     if (iso8859_f) {
5493                         c2 = ISO_8859_1;
5494                         SEND;
5495                     } else if (nkf_byte_jisx0201_katakana_p(c1)){
5496                         /* output 1 shifted byte */
5497                         c2 = JIS_X_0201_1976_K;
5498                         SEND;
5499                     } else {
5500                         /* look like bogus code */
5501                         SKIP;
5502                     }
5503                 } else if (input_mode == JIS_X_0208 || input_mode == JIS_X_0212 ||
5504                            input_mode == JIS_X_0213_1 || input_mode == JIS_X_0213_2) {
5505                     /* in case of Kanji shifted */
5506                     MORE;
5507                 } else if (c1 == '=' && mime_f && !mime_decode_mode) {
5508                     /* Check MIME code */
5509                     if ((c1 = (*i_getc)(f)) == EOF) {
5510                         (*oconv)(0, '=');
5511                         LAST;
5512                     } else if (c1 == '?') {
5513                         /* =? is mime conversion start sequence */
5514                         if(mime_f == STRICT_MIME) {
5515                             /* check in real detail */
5516                             if (mime_begin_strict(f) == EOF)
5517                                 LAST;
5518                             SKIP;
5519                         } else if (mime_begin(f) == EOF)
5520                             LAST;
5521                         SKIP;
5522                     } else {
5523                         (*oconv)(0, '=');
5524                         (*i_ungetc)(c1,f);
5525                         SKIP;
5526                     }
5527                 } else {
5528                     /* normal ASCII code */
5529                     SEND;
5530                 }
5531             } else if (c1 == SI && (!is_8bit || mime_decode_mode)) {
5532                 shift_mode = 0;
5533                 SKIP;
5534             } else if (c1 == SO && (!is_8bit || mime_decode_mode)) {
5535                 shift_mode = 1;
5536                 SKIP;
5537             } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) {
5538                 if ((c1 = (*i_getc)(f)) == EOF) {
5539                     (*oconv)(0, ESC);
5540                     LAST;
5541                 }
5542                 else if (c1 == '&') {
5543                     /* IRR */
5544                     if ((c1 = (*i_getc)(f)) == EOF) {
5545                         LAST;
5546                     } else {
5547                         SKIP;
5548                     }
5549                 }
5550                 else if (c1 == '$') {
5551                     /* GZDMx */
5552                     if ((c1 = (*i_getc)(f)) == EOF) {
5553                         /* don't send bogus code
5554                            (*oconv)(0, ESC);
5555                            (*oconv)(0, '$'); */
5556                         LAST;
5557                     } else if (c1 == '@' || c1 == 'B') {
5558                         /* JIS X 0208 */
5559                         set_input_mode(JIS_X_0208);
5560                         SKIP;
5561                     } else if (c1 == '(') {
5562                         /* GZDM4 */
5563                         if ((c1 = (*i_getc)(f)) == EOF) {
5564                             /* don't send bogus code
5565                                (*oconv)(0, ESC);
5566                                (*oconv)(0, '$');
5567                                (*oconv)(0, '(');
5568                              */
5569                             LAST;
5570                         } else if (c1 == '@'|| c1 == 'B') {
5571                             /* JIS X 0208 */
5572                             set_input_mode(JIS_X_0208);
5573                             SKIP;
5574 #ifdef X0212_ENABLE
5575                         } else if (c1 == 'D'){
5576                             set_input_mode(JIS_X_0212);
5577                             SKIP;
5578 #endif /* X0212_ENABLE */
5579                         } else if (c1 == 'O' || c1 == 'Q'){
5580                             set_input_mode(JIS_X_0213_1);
5581                             SKIP;
5582                         } else if (c1 == 'P'){
5583                             set_input_mode(JIS_X_0213_2);
5584                             SKIP;
5585                         } else {
5586                             /* could be some special code */
5587                             (*oconv)(0, ESC);
5588                             (*oconv)(0, '$');
5589                             (*oconv)(0, '(');
5590                             (*oconv)(0, c1);
5591                             SKIP;
5592                         }
5593                     } else if (broken_f&0x2) {
5594                         /* accept any ESC-(-x as broken code ... */
5595                         input_mode = JIS_X_0208;
5596                         shift_mode = 0;
5597                         SKIP;
5598                     } else {
5599                         (*oconv)(0, ESC);
5600                         (*oconv)(0, '$');
5601                         (*oconv)(0, c1);
5602                         SKIP;
5603                     }
5604                 } else if (c1 == '(') {
5605                     /* GZD4 */
5606                     if ((c1 = (*i_getc)(f)) == EOF) {
5607                         /* don't send bogus code
5608                            (*oconv)(0, ESC);
5609                            (*oconv)(0, '('); */
5610                         LAST;
5611                     }
5612                     else if (c1 == 'I') {
5613                         /* JIS X 0201 Katakana */
5614                         set_input_mode(JIS_X_0201_1976_K);
5615                         SKIP;
5616                     }
5617                     else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
5618                         /* ISO-646IRV:1983 or JIS X 0201 Roman or JUNET */
5619                         set_input_mode(ASCII);
5620                         SKIP;
5621                     }
5622                     else if (broken_f&0x2) {
5623                         set_input_mode(ASCII);
5624                         SKIP;
5625                     }
5626                     else {
5627                         (*oconv)(0, ESC);
5628                         (*oconv)(0, '(');
5629                         SEND;
5630                     }
5631                 }
5632                 else if (c1 == '.') {
5633                     /* G2D6 */
5634                     if ((c1 = (*i_getc)(f)) == EOF) {
5635                         LAST;
5636                     }
5637                     else if (c1 == 'A') {
5638                         /* ISO-8859-1 */
5639                         g2 = ISO_8859_1;
5640                         SKIP;
5641                     }
5642                     else {
5643                         (*oconv)(0, ESC);
5644                         (*oconv)(0, '.');
5645                         SEND;
5646                     }
5647                 }
5648                 else if (c1 == 'N') {
5649                     /* SS2 */
5650                     c1 = (*i_getc)(f);
5651                     if (g2 == ISO_8859_1) {
5652                         c2 = ISO_8859_1;
5653                         SEND;
5654                     }else{
5655                         (*i_ungetc)(c1, f);
5656                         /* lonely ESC  */
5657                         (*oconv)(0, ESC);
5658                         SEND;
5659                     }
5660                 }
5661                 else {
5662                     /* lonely ESC  */
5663                     (*oconv)(0, ESC);
5664                     SEND;
5665                 }
5666             } else if (c1 == ESC && iconv == s_iconv) {
5667                 /* ESC in Shift_JIS */
5668                 if ((c1 = (*i_getc)(f)) == EOF) {
5669                     (*oconv)(0, ESC);
5670                     LAST;
5671                 } else if (c1 == '$') {
5672                     /* J-PHONE emoji */
5673                     if ((c1 = (*i_getc)(f)) == EOF) {
5674                         LAST;
5675                     } else if (('E' <= c1 && c1 <= 'G') ||
5676                                ('O' <= c1 && c1 <= 'Q')) {
5677                         /*
5678                            NUM : 0 1 2 3 4 5
5679                            BYTE: G E F O P Q
5680                            C%7 : 1 6 0 2 3 4
5681                            C%7 : 0 1 2 3 4 5 6
5682                            NUM : 2 0 3 4 5 X 1
5683                          */
5684                         static const nkf_char jphone_emoji_first_table[7] =
5685                         {0xE1E0, 0xDFE0, 0xE2E0, 0xE3E0, 0xE4E0, 0xDFE0, 0xE0E0};
5686                         c3 = nkf_char_unicode_new(jphone_emoji_first_table[c1 % 7]);
5687                         if ((c1 = (*i_getc)(f)) == EOF) LAST;
5688                         while (SP <= c1 && c1 <= 'z') {
5689                             (*oconv)(0, c1 + c3);
5690                             if ((c1 = (*i_getc)(f)) == EOF) LAST;
5691                         }
5692                         SKIP;
5693                     }
5694                     else {
5695                         (*oconv)(0, ESC);
5696                         (*oconv)(0, '$');
5697                         SEND;
5698                     }
5699                 }
5700                 else {
5701                     /* lonely ESC  */
5702                     (*oconv)(0, ESC);
5703                     SEND;
5704                 }
5705             } else if (c1 == LF || c1 == CR) {
5706                 if (broken_f&4) {
5707                     input_mode = ASCII; set_iconv(FALSE, 0);
5708                     SEND;
5709                 } else if (mime_decode_f && !mime_decode_mode){
5710                     if (c1 == LF) {
5711                         if ((c1=(*i_getc)(f))!=EOF && c1 == SP) {
5712                             i_ungetc(SP,f);
5713                             continue;
5714                         } else {
5715                             i_ungetc(c1,f);
5716                         }
5717                         c1 = LF;
5718                         SEND;
5719                     } else  { /* if (c1 == CR)*/
5720                         if ((c1=(*i_getc)(f))!=EOF) {
5721                             if (c1==SP) {
5722                                 i_ungetc(SP,f);
5723                                 continue;
5724                             } else if (c1 == LF && (c1=(*i_getc)(f))!=EOF && c1 == SP) {
5725                                 i_ungetc(SP,f);
5726                                 continue;
5727                             } else {
5728                                 i_ungetc(c1,f);
5729                             }
5730                             i_ungetc(LF,f);
5731                         } else {
5732                             i_ungetc(c1,f);
5733                         }
5734                         c1 = CR;
5735                         SEND;
5736                     }
5737                 }
5738             } else
5739                 SEND;
5740         }
5741         /* send: */
5742         switch(input_mode){
5743         case ASCII:
5744             switch ((*iconv)(c2, c1, 0)) {  /* can be EUC / SJIS / UTF-8 */
5745             case -2:
5746                 /* 4 bytes UTF-8 */
5747                 if ((c3 = (*i_getc)(f)) != EOF) {
5748                     code_status(c3);
5749                     c3 <<= 8;
5750                     if ((c4 = (*i_getc)(f)) != EOF) {
5751                         code_status(c4);
5752                         (*iconv)(c2, c1, c3|c4);
5753                     }
5754                 }
5755                 break;
5756             case -1:
5757                 /* 3 bytes EUC or UTF-8 */
5758                 if ((c3 = (*i_getc)(f)) != EOF) {
5759                     code_status(c3);
5760                     (*iconv)(c2, c1, c3);
5761                 }
5762                 break;
5763             }
5764             break;
5765         case JIS_X_0208:
5766         case JIS_X_0213_1:
5767             if (ms_ucs_map_f &&
5768                 0x7F <= c2 && c2 <= 0x92 &&
5769                 0x21 <= c1 && c1 <= 0x7E) {
5770                 /* CP932 UDC */
5771                 c1 = nkf_char_unicode_new((c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000);
5772                 c2 = 0;
5773             }
5774             (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
5775             break;
5776 #ifdef X0212_ENABLE
5777         case JIS_X_0212:
5778             (*oconv)(PREFIX_EUCG3 | c2, c1);
5779             break;
5780 #endif /* X0212_ENABLE */
5781         case JIS_X_0213_2:
5782             (*oconv)(PREFIX_EUCG3 | c2, c1);
5783             break;
5784         default:
5785             (*oconv)(input_mode, c1);  /* other special case */
5786         }
5787
5788         c2 = 0;
5789         c3 = 0;
5790         continue;
5791         /* goto next_word */
5792     }
5793
5794     /* epilogue */
5795     (*iconv)(EOF, 0, 0);
5796     if (!input_codename)
5797     {
5798         if (is_8bit) {
5799             struct input_code *p = input_code_list;
5800             struct input_code *result = p;
5801             while (p->name){
5802                 if (p->score < result->score) result = p;
5803                 ++p;
5804             }
5805             set_input_codename(result->name);
5806 #ifdef CHECK_OPTION
5807             debug(result->name);
5808 #endif
5809         }
5810     }
5811     return 0;
5812 }
5813
5814 /*
5815  * int options(unsigned char *cp)
5816  * 
5817  * return values:
5818  *    0: success
5819  *   -1: ArgumentError
5820  */
5821 static int
5822 options(unsigned char *cp)
5823 {
5824     nkf_char i, j;
5825     unsigned char *p;
5826     unsigned char *cp_back = NULL;
5827     nkf_encoding *enc;
5828
5829     if (option_mode==1)
5830         return 0;
5831     while(*cp && *cp++!='-');
5832     while (*cp || cp_back) {
5833         if(!*cp){
5834             cp = cp_back;
5835             cp_back = NULL;
5836             continue;
5837         }
5838         p = 0;
5839         switch (*cp++) {
5840         case '-':  /* literal options */
5841             if (!*cp || *cp == SP) {        /* ignore the rest of arguments */
5842                 option_mode = 1;
5843                 return 0;
5844             }
5845             for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
5846                 p = (unsigned char *)long_option[i].name;
5847                 for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
5848                 if (*p == cp[j] || cp[j] == SP){
5849                     p = &cp[j] + 1;
5850                     break;
5851                 }
5852                 p = 0;
5853             }
5854             if (p == 0) {
5855 #if !defined(PERL_XS) && !defined(WIN32DLL)
5856                 fprintf(stderr, "unknown long option: --%s\n", cp);
5857 #endif
5858                 return -1;
5859             }
5860             while(*cp && *cp != SP && cp++);
5861             if (long_option[i].alias[0]){
5862                 cp_back = cp;
5863                 cp = (unsigned char *)long_option[i].alias;
5864             }else{
5865 #ifndef PERL_XS
5866                 if (strcmp(long_option[i].name, "help") == 0){
5867                     usage();
5868                     exit(EXIT_SUCCESS);
5869                 }
5870 #endif
5871                 if (strcmp(long_option[i].name, "ic=") == 0){
5872                     enc = nkf_enc_find((char *)p);
5873                     if (!enc) continue;
5874                     input_encoding = enc;
5875                     continue;
5876                 }
5877                 if (strcmp(long_option[i].name, "oc=") == 0){
5878                     enc = nkf_enc_find((char *)p);
5879                     /* if (enc <= 0) continue; */
5880                     if (!enc) continue;
5881                     output_encoding = enc;
5882                     continue;
5883                 }
5884                 if (strcmp(long_option[i].name, "guess=") == 0){
5885                     if (p[0] == '0' || p[0] == '1') {
5886                         guess_f = 1;
5887                     } else {
5888                         guess_f = 2;
5889                     }
5890                     continue;
5891                 }
5892 #ifdef OVERWRITE
5893                 if (strcmp(long_option[i].name, "overwrite") == 0){
5894                     file_out_f = TRUE;
5895                     overwrite_f = TRUE;
5896                     preserve_time_f = TRUE;
5897                     continue;
5898                 }
5899                 if (strcmp(long_option[i].name, "overwrite=") == 0){
5900                     file_out_f = TRUE;
5901                     overwrite_f = TRUE;
5902                     preserve_time_f = TRUE;
5903                     backup_f = TRUE;
5904                     backup_suffix = (char *)p;
5905                     continue;
5906                 }
5907                 if (strcmp(long_option[i].name, "in-place") == 0){
5908                     file_out_f = TRUE;
5909                     overwrite_f = TRUE;
5910                     preserve_time_f = FALSE;
5911                     continue;
5912                 }
5913                 if (strcmp(long_option[i].name, "in-place=") == 0){
5914                     file_out_f = TRUE;
5915                     overwrite_f = TRUE;
5916                     preserve_time_f = FALSE;
5917                     backup_f = TRUE;
5918                     backup_suffix = (char *)p;
5919                     continue;
5920                 }
5921 #endif
5922 #ifdef INPUT_OPTION
5923                 if (strcmp(long_option[i].name, "cap-input") == 0){
5924                     cap_f = TRUE;
5925                     continue;
5926                 }
5927                 if (strcmp(long_option[i].name, "url-input") == 0){
5928                     url_f = TRUE;
5929                     continue;
5930                 }
5931 #endif
5932 #ifdef NUMCHAR_OPTION
5933                 if (strcmp(long_option[i].name, "numchar-input") == 0){
5934                     numchar_f = TRUE;
5935                     continue;
5936                 }
5937 #endif
5938 #ifdef CHECK_OPTION
5939                 if (strcmp(long_option[i].name, "no-output") == 0){
5940                     noout_f = TRUE;
5941                     continue;
5942                 }
5943                 if (strcmp(long_option[i].name, "debug") == 0){
5944                     debug_f = TRUE;
5945                     continue;
5946                 }
5947 #endif
5948                 if (strcmp(long_option[i].name, "cp932") == 0){
5949 #ifdef SHIFTJIS_CP932
5950                     cp51932_f = TRUE;
5951                     cp932inv_f = -TRUE;
5952 #endif
5953 #ifdef UTF8_OUTPUT_ENABLE
5954                     ms_ucs_map_f = UCS_MAP_CP932;
5955 #endif
5956                     continue;
5957                 }
5958                 if (strcmp(long_option[i].name, "no-cp932") == 0){
5959 #ifdef SHIFTJIS_CP932
5960                     cp51932_f = FALSE;
5961                     cp932inv_f = FALSE;
5962 #endif
5963 #ifdef UTF8_OUTPUT_ENABLE
5964                     ms_ucs_map_f = UCS_MAP_ASCII;
5965 #endif
5966                     continue;
5967                 }
5968 #ifdef SHIFTJIS_CP932
5969                 if (strcmp(long_option[i].name, "cp932inv") == 0){
5970                     cp932inv_f = -TRUE;
5971                     continue;
5972                 }
5973 #endif
5974
5975 #ifdef X0212_ENABLE
5976                 if (strcmp(long_option[i].name, "x0212") == 0){
5977                     x0212_f = TRUE;
5978                     continue;
5979                 }
5980 #endif
5981
5982 #ifdef EXEC_IO
5983                 if (strcmp(long_option[i].name, "exec-in") == 0){
5984                     exec_f = 1;
5985                     return 0;
5986                 }
5987                 if (strcmp(long_option[i].name, "exec-out") == 0){
5988                     exec_f = -1;
5989                     return 0;
5990                 }
5991 #endif
5992 #if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
5993                 if (strcmp(long_option[i].name, "no-cp932ext") == 0){
5994                     no_cp932ext_f = TRUE;
5995                     continue;
5996                 }
5997                 if (strcmp(long_option[i].name, "no-best-fit-chars") == 0){
5998                     no_best_fit_chars_f = TRUE;
5999                     continue;
6000                 }
6001                 if (strcmp(long_option[i].name, "fb-skip") == 0){
6002                     encode_fallback = NULL;
6003                     continue;
6004                 }
6005                 if (strcmp(long_option[i].name, "fb-html") == 0){
6006                     encode_fallback = encode_fallback_html;
6007                     continue;
6008                 }
6009                 if (strcmp(long_option[i].name, "fb-xml") == 0){
6010                     encode_fallback = encode_fallback_xml;
6011                     continue;
6012                 }
6013                 if (strcmp(long_option[i].name, "fb-java") == 0){
6014                     encode_fallback = encode_fallback_java;
6015                     continue;
6016                 }
6017                 if (strcmp(long_option[i].name, "fb-perl") == 0){
6018                     encode_fallback = encode_fallback_perl;
6019                     continue;
6020                 }
6021                 if (strcmp(long_option[i].name, "fb-subchar") == 0){
6022                     encode_fallback = encode_fallback_subchar;
6023                     continue;
6024                 }
6025                 if (strcmp(long_option[i].name, "fb-subchar=") == 0){
6026                     encode_fallback = encode_fallback_subchar;
6027                     unicode_subchar = 0;
6028                     if (p[0] != '0'){
6029                         /* decimal number */
6030                         for (i = 0; i < 7 && nkf_isdigit(p[i]); i++){
6031                             unicode_subchar *= 10;
6032                             unicode_subchar += hex2bin(p[i]);
6033                         }
6034                     }else if(p[1] == 'x' || p[1] == 'X'){
6035                         /* hexadecimal number */
6036                         for (i = 2; i < 8 && nkf_isxdigit(p[i]); i++){
6037                             unicode_subchar <<= 4;
6038                             unicode_subchar |= hex2bin(p[i]);
6039                         }
6040                     }else{
6041                         /* octal number */
6042                         for (i = 1; i < 8 && nkf_isoctal(p[i]); i++){
6043                             unicode_subchar *= 8;
6044                             unicode_subchar += hex2bin(p[i]);
6045                         }
6046                     }
6047                     w16e_conv(unicode_subchar, &i, &j);
6048                     unicode_subchar = i<<8 | j;
6049                     continue;
6050                 }
6051 #endif
6052 #ifdef UTF8_OUTPUT_ENABLE
6053                 if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
6054                     ms_ucs_map_f = UCS_MAP_MS;
6055                     continue;
6056                 }
6057 #endif
6058 #ifdef UNICODE_NORMALIZATION
6059                 if (strcmp(long_option[i].name, "utf8mac-input") == 0){
6060                     nfc_f = TRUE;
6061                     continue;
6062                 }
6063 #endif
6064                 if (strcmp(long_option[i].name, "prefix=") == 0){
6065                     if (nkf_isgraph(p[0])){
6066                         for (i = 1; nkf_isgraph(p[i]); i++){
6067                             prefix_table[p[i]] = p[0];
6068                         }
6069                     }
6070                     continue;
6071                 }
6072 #if !defined(PERL_XS) && !defined(WIN32DLL)
6073                 fprintf(stderr, "unsupported long option: --%s\n", long_option[i].name);
6074 #endif
6075                 return -1;
6076             }
6077             continue;
6078         case 'b':           /* buffered mode */
6079             unbuf_f = FALSE;
6080             continue;
6081         case 'u':           /* non bufferd mode */
6082             unbuf_f = TRUE;
6083             continue;
6084         case 't':           /* transparent mode */
6085             if (*cp=='1') {
6086                 /* alias of -t */
6087                 cp++;
6088                 nop_f = TRUE;
6089             } else if (*cp=='2') {
6090                 /*
6091                  * -t with put/get
6092                  *
6093                  * nkf -t2MB hoge.bin | nkf -t2mB | diff -s - hoge.bin
6094                  *
6095                  */
6096                 cp++;
6097                 nop_f = 2;
6098             } else
6099                 nop_f = TRUE;
6100             continue;
6101         case 'j':           /* JIS output */
6102         case 'n':
6103             output_encoding = nkf_enc_from_index(ISO_2022_JP);
6104             continue;
6105         case 'e':           /* AT&T EUC output */
6106             output_encoding = nkf_enc_from_index(EUCJP_NKF);
6107             continue;
6108         case 's':           /* SJIS output */
6109             output_encoding = nkf_enc_from_index(SHIFT_JIS);
6110             continue;
6111         case 'l':           /* ISO8859 Latin-1 support, no conversion */
6112             iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
6113             input_encoding = nkf_enc_from_index(ISO_8859_1);
6114             continue;
6115         case 'i':           /* Kanji IN ESC-$-@/B */
6116             if (*cp=='@'||*cp=='B')
6117                 kanji_intro = *cp++;
6118             continue;
6119         case 'o':           /* ASCII IN ESC-(-J/B/H */
6120             /* ESC ( H was used in initial JUNET messages */
6121             if (*cp=='J'||*cp=='B'||*cp=='H')
6122                 ascii_intro = *cp++;
6123             continue;
6124         case 'h':
6125             /*
6126                bit:1   katakana->hiragana
6127                bit:2   hiragana->katakana
6128              */
6129             if ('9'>= *cp && *cp>='0')
6130                 hira_f |= (*cp++ -'0');
6131             else
6132                 hira_f |= 1;
6133             continue;
6134         case 'r':
6135             rot_f = TRUE;
6136             continue;
6137 #if defined(MSDOS) || defined(__OS2__)
6138         case 'T':
6139             binmode_f = FALSE;
6140             continue;
6141 #endif
6142 #ifndef PERL_XS
6143         case 'V':
6144             show_configuration();
6145             exit(EXIT_SUCCESS);
6146             break;
6147         case 'v':
6148             version();
6149             exit(EXIT_SUCCESS);
6150             break;
6151 #endif
6152 #ifdef UTF8_OUTPUT_ENABLE
6153         case 'w':           /* UTF-8 output */
6154             if (cp[0] == '8') {
6155                 cp++;
6156                 if (cp[0] == '0'){
6157                     cp++;
6158                     output_encoding = nkf_enc_from_index(UTF_8N);
6159                 } else {
6160                     output_bom_f = TRUE;
6161                     output_encoding = nkf_enc_from_index(UTF_8_BOM);
6162                 }
6163             } else {
6164                 int enc_idx;
6165                 if ('1'== cp[0] && '6'==cp[1]) {
6166                     cp += 2;
6167                     enc_idx = UTF_16;
6168                 } else if ('3'== cp[0] && '2'==cp[1]) {
6169                     cp += 2;
6170                     enc_idx = UTF_32;
6171                 } else {
6172                     output_encoding = nkf_enc_from_index(UTF_8);
6173                     continue;
6174                 }
6175                 if (cp[0]=='L') {
6176                     cp++;
6177                     output_endian = ENDIAN_LITTLE;
6178                 } else if (cp[0] == 'B') {
6179                     cp++;
6180                 }
6181                 if (cp[0] == '0'){
6182                     cp++;
6183                     enc_idx = enc_idx == UTF_16
6184                         ? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
6185                         : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
6186                 } else {
6187                     output_bom_f = TRUE;
6188                     enc_idx = enc_idx == UTF_16
6189                         ? (output_endian == ENDIAN_LITTLE ? UTF_16LE_BOM : UTF_16BE_BOM)
6190                         : (output_endian == ENDIAN_LITTLE ? UTF_32LE_BOM : UTF_32BE_BOM);
6191                 }
6192                 output_encoding = nkf_enc_from_index(enc_idx);
6193             }
6194             continue;
6195 #endif
6196 #ifdef UTF8_INPUT_ENABLE
6197         case 'W':           /* UTF input */
6198             if (cp[0] == '8') {
6199                 cp++;
6200                 input_encoding = nkf_enc_from_index(UTF_8);
6201             }else{
6202                 int enc_idx;
6203                 if ('1'== cp[0] && '6'==cp[1]) {
6204                     cp += 2;
6205                     input_endian = ENDIAN_BIG;
6206                     enc_idx = UTF_16;
6207                 } else if ('3'== cp[0] && '2'==cp[1]) {
6208                     cp += 2;
6209                     input_endian = ENDIAN_BIG;
6210                     enc_idx = UTF_32;
6211                 } else {
6212                     input_encoding = nkf_enc_from_index(UTF_8);
6213                     continue;
6214                 }
6215                 if (cp[0]=='L') {
6216                     cp++;
6217                     input_endian = ENDIAN_LITTLE;
6218                 } else if (cp[0] == 'B') {
6219                     cp++;
6220                     input_endian = ENDIAN_BIG;
6221                 }
6222                 enc_idx = (enc_idx == UTF_16
6223                     ? (input_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
6224                     : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE));
6225                 input_encoding = nkf_enc_from_index(enc_idx);
6226             }
6227             continue;
6228 #endif
6229             /* Input code assumption */
6230         case 'J':   /* ISO-2022-JP input */
6231             input_encoding = nkf_enc_from_index(ISO_2022_JP);
6232             continue;
6233         case 'E':   /* EUC-JP input */
6234             input_encoding = nkf_enc_from_index(EUCJP_NKF);
6235             continue;
6236         case 'S':   /* Shift_JIS input */
6237             input_encoding = nkf_enc_from_index(SHIFT_JIS);
6238             continue;
6239         case 'Z':   /* Convert X0208 alphabet to asii */
6240             /* alpha_f
6241                bit:0   Convert JIS X 0208 Alphabet to ASCII
6242                bit:1   Convert Kankaku to one space
6243                bit:2   Convert Kankaku to two spaces
6244                bit:3   Convert HTML Entity
6245                bit:4   Convert JIS X 0208 Katakana to JIS X 0201 Katakana
6246              */
6247             while ('0'<= *cp && *cp <='4') {
6248                 alpha_f |= 1 << (*cp++ - '0');
6249             }
6250             alpha_f |= 1;
6251             continue;
6252         case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
6253             x0201_f = FALSE;    /* No X0201->X0208 conversion */
6254             /* accept  X0201
6255                ESC-(-I     in JIS, EUC, MS Kanji
6256                SI/SO       in JIS, EUC, MS Kanji
6257                SS2         in EUC, JIS, not in MS Kanji
6258                MS Kanji (0xa0-0xdf)
6259                output  X0201
6260                ESC-(-I     in JIS (0x20-0x5f)
6261                SS2         in EUC (0xa0-0xdf)
6262                0xa0-0xd    in MS Kanji (0xa0-0xdf)
6263              */
6264             continue;
6265         case 'X':   /* Convert X0201 kana to X0208 */
6266             x0201_f = TRUE;
6267             continue;
6268         case 'F':   /* prserve new lines */
6269             fold_preserve_f = TRUE;
6270         case 'f':   /* folding -f60 or -f */
6271             fold_f = TRUE;
6272             fold_len = 0;
6273             while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
6274                 fold_len *= 10;
6275                 fold_len += *cp++ - '0';
6276             }
6277             if (!(0<fold_len && fold_len<BUFSIZ))
6278                 fold_len = DEFAULT_FOLD;
6279             if (*cp=='-') {
6280                 fold_margin = 0;
6281                 cp++;
6282                 while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
6283                     fold_margin *= 10;
6284                     fold_margin += *cp++ - '0';
6285                 }
6286             }
6287             continue;
6288         case 'm':   /* MIME support */
6289             /* mime_decode_f = TRUE; */ /* this has too large side effects... */
6290             if (*cp=='B'||*cp=='Q') {
6291                 mime_decode_mode = *cp++;
6292                 mimebuf_f = FIXED_MIME;
6293             } else if (*cp=='N') {
6294                 mime_f = TRUE; cp++;
6295             } else if (*cp=='S') {
6296                 mime_f = STRICT_MIME; cp++;
6297             } else if (*cp=='0') {
6298                 mime_decode_f = FALSE;
6299                 mime_f = FALSE; cp++;
6300             } else {
6301                 mime_f = STRICT_MIME;
6302             }
6303             continue;
6304         case 'M':   /* MIME output */
6305             if (*cp=='B') {
6306                 mimeout_mode = 'B';
6307                 mimeout_f = FIXED_MIME; cp++;
6308             } else if (*cp=='Q') {
6309                 mimeout_mode = 'Q';
6310                 mimeout_f = FIXED_MIME; cp++;
6311             } else {
6312                 mimeout_f = TRUE;
6313             }
6314             continue;
6315         case 'B':   /* Broken JIS support */
6316             /*  bit:0   no ESC JIS
6317                bit:1   allow any x on ESC-(-x or ESC-$-x
6318                bit:2   reset to ascii on NL
6319              */
6320             if ('9'>= *cp && *cp>='0')
6321                 broken_f |= 1<<(*cp++ -'0');
6322             else
6323                 broken_f |= TRUE;
6324             continue;
6325 #ifndef PERL_XS
6326         case 'O':/* for Output file */
6327             file_out_f = TRUE;
6328             continue;
6329 #endif
6330         case 'c':/* add cr code */
6331             eolmode_f = CRLF;
6332             continue;
6333         case 'd':/* delete cr code */
6334             eolmode_f = LF;
6335             continue;
6336         case 'I':   /* ISO-2022-JP output */
6337             iso2022jp_f = TRUE;
6338             continue;
6339         case 'L':  /* line mode */
6340             if (*cp=='u') {         /* unix */
6341                 eolmode_f = LF; cp++;
6342             } else if (*cp=='m') { /* mac */
6343                 eolmode_f = CR; cp++;
6344             } else if (*cp=='w') { /* windows */
6345                 eolmode_f = CRLF; cp++;
6346             } else if (*cp=='0') { /* no conversion  */
6347                 eolmode_f = 0; cp++;
6348             }
6349             continue;
6350 #ifndef PERL_XS
6351         case 'g':
6352             if ('2' <= *cp && *cp <= '9') {
6353                 guess_f = 2;
6354                 cp++;
6355             } else if (*cp == '0' || *cp == '1') {
6356                 guess_f = 1;
6357                 cp++;
6358             } else {
6359                 guess_f = 1;
6360             }
6361             continue;
6362 #endif
6363         case SP:
6364             /* module muliple options in a string are allowed for Perl moudle  */
6365             while(*cp && *cp++!='-');
6366             continue;
6367         default:
6368 #if !defined(PERL_XS) && !defined(WIN32DLL)
6369             fprintf(stderr, "unknown option: -%c\n", *(cp-1));
6370 #endif
6371             /* bogus option but ignored */
6372             return -1;
6373         }
6374     }
6375     return 0;
6376 }
6377
6378 #ifdef WIN32DLL
6379 #include "nkf32dll.c"
6380 #elif defined(PERL_XS)
6381 #else /* WIN32DLL */
6382 int
6383 main(int argc, char **argv)
6384 {
6385     FILE  *fin;
6386     unsigned char  *cp;
6387
6388     char *outfname = NULL;
6389     char *origfname;
6390
6391 #ifdef EASYWIN /*Easy Win */
6392     _BufferSize.y = 400;/*Set Scroll Buffer Size*/
6393 #endif
6394 #ifdef DEFAULT_CODE_LOCALE
6395     setlocale(LC_CTYPE, "");
6396 #endif
6397     nkf_state_init();
6398
6399     for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
6400         cp = (unsigned char *)*argv;
6401         options(cp);
6402 #ifdef EXEC_IO
6403         if (exec_f){
6404             int fds[2], pid;
6405             if (pipe(fds) < 0 || (pid = fork()) < 0){
6406                 abort();
6407             }
6408             if (pid == 0){
6409                 if (exec_f > 0){
6410                     close(fds[0]);
6411                     dup2(fds[1], 1);
6412                 }else{
6413                     close(fds[1]);
6414                     dup2(fds[0], 0);
6415                 }
6416                 execvp(argv[1], &argv[1]);
6417             }
6418             if (exec_f > 0){
6419                 close(fds[1]);
6420                 dup2(fds[0], 0);
6421             }else{
6422                 close(fds[0]);
6423                 dup2(fds[1], 1);
6424             }
6425             argc = 0;
6426             break;
6427         }
6428 #endif
6429     }
6430
6431     if (guess_f) {
6432 #ifdef CHECK_OPTION
6433         int debug_f_back = debug_f;
6434 #endif
6435 #ifdef EXEC_IO
6436         int exec_f_back = exec_f;
6437 #endif
6438 #ifdef X0212_ENABLE
6439         int x0212_f_back = x0212_f;
6440 #endif
6441         int x0213_f_back = x0213_f;
6442         int guess_f_back = guess_f;
6443         reinit();
6444         guess_f = guess_f_back;
6445         mime_f = FALSE;
6446 #ifdef CHECK_OPTION
6447         debug_f = debug_f_back;
6448 #endif
6449 #ifdef EXEC_IO
6450         exec_f = exec_f_back;
6451 #endif
6452         x0212_f = x0212_f_back;
6453         x0213_f = x0213_f_back;
6454     }
6455
6456     if (binmode_f == TRUE)
6457 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
6458         if (freopen("","wb",stdout) == NULL)
6459             return (-1);
6460 #else
6461     setbinmode(stdout);
6462 #endif
6463
6464     if (unbuf_f)
6465         setbuf(stdout, (char *) NULL);
6466     else
6467         setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE);
6468
6469     if (argc == 0) {
6470         if (binmode_f == TRUE)
6471 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
6472             if (freopen("","rb",stdin) == NULL) return (-1);
6473 #else
6474         setbinmode(stdin);
6475 #endif
6476         setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE);
6477         if (nop_f)
6478             noconvert(stdin);
6479         else {
6480             kanji_convert(stdin);
6481             if (guess_f) print_guessed_code(NULL);
6482         }
6483     } else {
6484         int nfiles = argc;
6485         int is_argument_error = FALSE;
6486         while (argc--) {
6487             input_codename = NULL;
6488             input_eol = 0;
6489 #ifdef CHECK_OPTION
6490             iconv_for_check = 0;
6491 #endif
6492             if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
6493                 perror(*(argv-1));
6494                 is_argument_error = TRUE;
6495                 continue;
6496             } else {
6497 #ifdef OVERWRITE
6498                 int fd = 0;
6499                 int fd_backup = 0;
6500 #endif
6501
6502                 /* reopen file for stdout */
6503                 if (file_out_f == TRUE) {
6504 #ifdef OVERWRITE
6505                     if (overwrite_f){
6506                         outfname = nkf_xmalloc(strlen(origfname)
6507                                           + strlen(".nkftmpXXXXXX")
6508                                           + 1);
6509                         strcpy(outfname, origfname);
6510 #ifdef MSDOS
6511                         {
6512                             int i;
6513                             for (i = strlen(outfname); i; --i){
6514                                 if (outfname[i - 1] == '/'
6515                                     || outfname[i - 1] == '\\'){
6516                                     break;
6517                                 }
6518                             }
6519                             outfname[i] = '\0';
6520                         }
6521                         strcat(outfname, "ntXXXXXX");
6522                         mktemp(outfname);
6523                         fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
6524                                   S_IREAD | S_IWRITE);
6525 #else
6526                         strcat(outfname, ".nkftmpXXXXXX");
6527                         fd = mkstemp(outfname);
6528 #endif
6529                         if (fd < 0
6530                             || (fd_backup = dup(fileno(stdout))) < 0
6531                             || dup2(fd, fileno(stdout)) < 0
6532                            ){
6533                             perror(origfname);
6534                             return -1;
6535                         }
6536                     }else
6537 #endif
6538                     if(argc == 1) {
6539                         outfname = *argv++;
6540                         argc--;
6541                     } else {
6542                         outfname = "nkf.out";
6543                     }
6544
6545                     if(freopen(outfname, "w", stdout) == NULL) {
6546                         perror (outfname);
6547                         return (-1);
6548                     }
6549                     if (binmode_f == TRUE) {
6550 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
6551                         if (freopen("","wb",stdout) == NULL)
6552                             return (-1);
6553 #else
6554                         setbinmode(stdout);
6555 #endif
6556                     }
6557                 }
6558                 if (binmode_f == TRUE)
6559 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
6560                     if (freopen("","rb",fin) == NULL)
6561                         return (-1);
6562 #else
6563                 setbinmode(fin);
6564 #endif
6565                 setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE);
6566                 if (nop_f)
6567                     noconvert(fin);
6568                 else {
6569                     char *filename = NULL;
6570                     kanji_convert(fin);
6571                     if (nfiles > 1) filename = origfname;
6572                     if (guess_f) print_guessed_code(filename);
6573                 }
6574                 fclose(fin);
6575 #ifdef OVERWRITE
6576                 if (overwrite_f) {
6577                     struct stat     sb;
6578 #if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
6579                     time_t tb[2];
6580 #else
6581                     struct utimbuf  tb;
6582 #endif
6583
6584                     fflush(stdout);
6585                     close(fd);
6586                     if (dup2(fd_backup, fileno(stdout)) < 0){
6587                         perror("dup2");
6588                     }
6589                     if (stat(origfname, &sb)) {
6590                         fprintf(stderr, "Can't stat %s\n", origfname);
6591                     }
6592                     /* \e$B%Q!<%_%C%7%g%s$rI|85\e(B */
6593                     if (chmod(outfname, sb.st_mode)) {
6594                         fprintf(stderr, "Can't set permission %s\n", outfname);
6595                     }
6596
6597                     /* \e$B%?%$%`%9%?%s%W$rI|85\e(B */
6598                     if(preserve_time_f){
6599 #if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
6600                         tb[0] = tb[1] = sb.st_mtime;
6601                         if (utime(outfname, tb)) {
6602                             fprintf(stderr, "Can't set timestamp %s\n", outfname);
6603                         }
6604 #else
6605                         tb.actime  = sb.st_atime;
6606                         tb.modtime = sb.st_mtime;
6607                         if (utime(outfname, &tb)) {
6608                             fprintf(stderr, "Can't set timestamp %s\n", outfname);
6609                         }
6610 #endif
6611                     }
6612                     if(backup_f){
6613                         char *backup_filename = get_backup_filename(backup_suffix, origfname);
6614 #ifdef MSDOS
6615                         unlink(backup_filename);
6616 #endif
6617                         if (rename(origfname, backup_filename)) {
6618                             perror(backup_filename);
6619                             fprintf(stderr, "Can't rename %s to %s\n",
6620                                     origfname, backup_filename);
6621                         }
6622                         nkf_xfree(backup_filename);
6623                     }else{
6624 #ifdef MSDOS
6625                         if (unlink(origfname)){
6626                             perror(origfname);
6627                         }
6628 #endif
6629                     }
6630                     if (rename(outfname, origfname)) {
6631                         perror(origfname);
6632                         fprintf(stderr, "Can't rename %s to %s\n",
6633                                 outfname, origfname);
6634                     }
6635                     nkf_xfree(outfname);
6636                 }
6637 #endif
6638             }
6639         }
6640         if (is_argument_error)
6641             return(-1);
6642     }
6643 #ifdef EASYWIN /*Easy Win */
6644     if (file_out_f == FALSE)
6645         scanf("%d",&end_check);
6646     else
6647         fclose(stdout);
6648 #else /* for Other OS */
6649     if (file_out_f == TRUE)
6650         fclose(stdout);
6651 #endif /*Easy Win */
6652     return (0);
6653 }
6654 #endif /* WIN32DLL */