OSDN Git Service

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