OSDN Git Service

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