OSDN Git Service

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