OSDN Git Service

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