OSDN Git Service

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