OSDN Git Service

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