OSDN Git Service

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