OSDN Git Service

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