OSDN Git Service

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