OSDN Git Service

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