OSDN Git Service

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