OSDN Git Service

Show "(BOM)" if the byte sequence has BOM.
[nkf/nkf.git] / nkf.c
1 /*
2  * Copyright (c) 1987, Fujitsu LTD. (Itaru ICHIKAWA).
3  * Copyright (c) 1996-2010, The nkf Project.
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  *
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  * misrepresented as being the original software.
20  *
21  * 3. This notice may not be removed or altered from any source distribution.
22  */
23 #define NKF_VERSION "2.1.3"
24 #define NKF_RELEASE_DATE "2012-03-17"
25 #define COPY_RIGHT \
26     "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).\n" \
27     "Copyright (C) 1996-2012, The nkf Project."
28
29 #include "config.h"
30 #include "nkf.h"
31 #include "utf8tbl.h"
32 #ifdef __WIN32__
33 #include <windows.h>
34 #include <locale.h>
35 #endif
36 #if defined(__OS2__)
37 # define INCL_DOS
38 # define INCL_DOSERRORS
39 # include <os2.h>
40 #endif
41 #include <assert.h>
42
43
44 /* state of output_mode and input_mode
45
46    c2           0 means ASCII
47    JIS_X_0201_1976_K
48    ISO_8859_1
49    JIS_X_0208
50    EOF      all termination
51    c1           32bit data
52
53  */
54
55 /* MIME ENCODE */
56
57 #define         FIXED_MIME      7
58 #define         STRICT_MIME     8
59
60 /* byte order */
61 enum byte_order {
62     ENDIAN_BIG    = 1,
63     ENDIAN_LITTLE = 2,
64     ENDIAN_2143   = 3,
65     ENDIAN_3412   = 4
66 };
67
68 /* ASCII CODE */
69
70 #define         BS      0x08
71 #define         TAB     0x09
72 #define         LF      0x0a
73 #define         CR      0x0d
74 #define         ESC     0x1b
75 #define         SP      0x20
76 #define         DEL     0x7f
77 #define         SI      0x0f
78 #define         SO      0x0e
79 #define         SS2     0x8e
80 #define         SS3     0x8f
81 #define         CRLF    0x0D0A
82
83
84 /* encodings */
85
86 enum nkf_encodings {
87     ASCII,
88     ISO_8859_1,
89     ISO_2022_JP,
90     CP50220,
91     CP50221,
92     CP50222,
93     ISO_2022_JP_1,
94     ISO_2022_JP_3,
95     ISO_2022_JP_2004,
96     SHIFT_JIS,
97     WINDOWS_31J,
98     CP10001,
99     EUC_JP,
100     EUCJP_NKF,
101     CP51932,
102     EUCJP_MS,
103     EUCJP_ASCII,
104     SHIFT_JISX0213,
105     SHIFT_JIS_2004,
106     EUC_JISX0213,
107     EUC_JIS_2004,
108     UTF_8,
109     UTF_8N,
110     UTF_8_BOM,
111     UTF8_MAC,
112     UTF_16,
113     UTF_16BE,
114     UTF_16BE_BOM,
115     UTF_16LE,
116     UTF_16LE_BOM,
117     UTF_32,
118     UTF_32BE,
119     UTF_32BE_BOM,
120     UTF_32LE,
121     UTF_32LE_BOM,
122     BINARY,
123     NKF_ENCODING_TABLE_SIZE,
124     JIS_X_0201_1976_K = 0x1013, /* I */ /* JIS C 6220-1969 */
125     /* JIS_X_0201_1976_R = 0x1014, */ /* J */ /* JIS C 6220-1969 */
126     /* JIS_X_0208_1978   = 0x1040, */ /* @ */ /* JIS C 6226-1978 */
127     /* JIS_X_0208_1983   = 0x1087, */ /* B */ /* JIS C 6226-1983 */
128     JIS_X_0208        = 0x1168, /* @B */
129     JIS_X_0212        = 0x1159, /* D */
130     /* JIS_X_0213_2000_1 = 0x1228, */ /* O */
131     JIS_X_0213_2 = 0x1229, /* P */
132     JIS_X_0213_1 = 0x1233 /* Q */
133 };
134
135 static nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
136 static nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
137 static nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
138 static nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0);
139 static nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0);
140 static void j_oconv(nkf_char c2, nkf_char c1);
141 static void s_oconv(nkf_char c2, nkf_char c1);
142 static void e_oconv(nkf_char c2, nkf_char c1);
143 static void w_oconv(nkf_char c2, nkf_char c1);
144 static void w_oconv16(nkf_char c2, nkf_char c1);
145 static void w_oconv32(nkf_char c2, nkf_char c1);
146
147 typedef struct {
148     const char *name;
149     nkf_char (*iconv)(nkf_char c2, nkf_char c1, nkf_char c0);
150     void (*oconv)(nkf_char c2, nkf_char c1);
151 } nkf_native_encoding;
152
153 nkf_native_encoding NkfEncodingASCII =          { "ASCII", e_iconv, e_oconv };
154 nkf_native_encoding NkfEncodingISO_2022_JP =    { "ISO-2022-JP", e_iconv, j_oconv };
155 nkf_native_encoding NkfEncodingShift_JIS =      { "Shift_JIS", s_iconv, s_oconv };
156 nkf_native_encoding NkfEncodingEUC_JP =         { "EUC-JP", e_iconv, e_oconv };
157 nkf_native_encoding NkfEncodingUTF_8 =          { "UTF-8", w_iconv, w_oconv };
158 nkf_native_encoding NkfEncodingUTF_16 =         { "UTF-16", w_iconv16, w_oconv16 };
159 nkf_native_encoding NkfEncodingUTF_32 =         { "UTF-32", w_iconv32, w_oconv32 };
160
161 typedef struct {
162     const int id;
163     const char *name;
164     const nkf_native_encoding *base_encoding;
165 } nkf_encoding;
166
167 nkf_encoding nkf_encoding_table[] = {
168     {ASCII,             "US-ASCII",             &NkfEncodingASCII},
169     {ISO_8859_1,        "ISO-8859-1",           &NkfEncodingASCII},
170     {ISO_2022_JP,       "ISO-2022-JP",          &NkfEncodingISO_2022_JP},
171     {CP50220,           "CP50220",              &NkfEncodingISO_2022_JP},
172     {CP50221,           "CP50221",              &NkfEncodingISO_2022_JP},
173     {CP50222,           "CP50222",              &NkfEncodingISO_2022_JP},
174     {ISO_2022_JP_1,     "ISO-2022-JP-1",        &NkfEncodingISO_2022_JP},
175     {ISO_2022_JP_3,     "ISO-2022-JP-3",        &NkfEncodingISO_2022_JP},
176     {ISO_2022_JP_2004,  "ISO-2022-JP-2004",     &NkfEncodingISO_2022_JP},
177     {SHIFT_JIS,         "Shift_JIS",            &NkfEncodingShift_JIS},
178     {WINDOWS_31J,       "Windows-31J",          &NkfEncodingShift_JIS},
179     {CP10001,           "CP10001",              &NkfEncodingShift_JIS},
180     {EUC_JP,            "EUC-JP",               &NkfEncodingEUC_JP},
181     {EUCJP_NKF,         "eucJP-nkf",            &NkfEncodingEUC_JP},
182     {CP51932,           "CP51932",              &NkfEncodingEUC_JP},
183     {EUCJP_MS,          "eucJP-MS",             &NkfEncodingEUC_JP},
184     {EUCJP_ASCII,       "eucJP-ASCII",          &NkfEncodingEUC_JP},
185     {SHIFT_JISX0213,    "Shift_JISX0213",       &NkfEncodingShift_JIS},
186     {SHIFT_JIS_2004,    "Shift_JIS-2004",       &NkfEncodingShift_JIS},
187     {EUC_JISX0213,      "EUC-JISX0213",         &NkfEncodingEUC_JP},
188     {EUC_JIS_2004,      "EUC-JIS-2004",         &NkfEncodingEUC_JP},
189     {UTF_8,             "UTF-8",                &NkfEncodingUTF_8},
190     {UTF_8N,            "UTF-8N",               &NkfEncodingUTF_8},
191     {UTF_8_BOM,         "UTF-8-BOM",            &NkfEncodingUTF_8},
192     {UTF8_MAC,          "UTF8-MAC",             &NkfEncodingUTF_8},
193     {UTF_16,            "UTF-16",               &NkfEncodingUTF_16},
194     {UTF_16BE,          "UTF-16BE",             &NkfEncodingUTF_16},
195     {UTF_16BE_BOM,      "UTF-16BE-BOM",         &NkfEncodingUTF_16},
196     {UTF_16LE,          "UTF-16LE",             &NkfEncodingUTF_16},
197     {UTF_16LE_BOM,      "UTF-16LE-BOM",         &NkfEncodingUTF_16},
198     {UTF_32,            "UTF-32",               &NkfEncodingUTF_32},
199     {UTF_32BE,          "UTF-32BE",             &NkfEncodingUTF_32},
200     {UTF_32BE_BOM,      "UTF-32BE-BOM",         &NkfEncodingUTF_32},
201     {UTF_32LE,          "UTF-32LE",             &NkfEncodingUTF_32},
202     {UTF_32LE_BOM,      "UTF-32LE-BOM",         &NkfEncodingUTF_32},
203     {BINARY,            "BINARY",               &NkfEncodingASCII},
204     {-1,                NULL,                   NULL}
205 };
206
207 struct {
208     const char *name;
209     const int id;
210 } encoding_name_to_id_table[] = {
211     {"US-ASCII",                ASCII},
212     {"ASCII",                   ASCII},
213     {"646",                     ASCII},
214     {"ROMAN8",                  ASCII},
215     {"ISO-2022-JP",             ISO_2022_JP},
216     {"ISO2022JP-CP932",         CP50220},
217     {"CP50220",                 CP50220},
218     {"CP50221",                 CP50221},
219     {"CSISO2022JP",             CP50221},
220     {"CP50222",                 CP50222},
221     {"ISO-2022-JP-1",           ISO_2022_JP_1},
222     {"ISO-2022-JP-3",           ISO_2022_JP_3},
223     {"ISO-2022-JP-2004",        ISO_2022_JP_2004},
224     {"SHIFT_JIS",               SHIFT_JIS},
225     {"SJIS",                    SHIFT_JIS},
226     {"MS_Kanji",                SHIFT_JIS},
227     {"PCK",                     SHIFT_JIS},
228     {"WINDOWS-31J",             WINDOWS_31J},
229     {"CSWINDOWS31J",            WINDOWS_31J},
230     {"CP932",                   WINDOWS_31J},
231     {"MS932",                   WINDOWS_31J},
232     {"CP10001",                 CP10001},
233     {"EUCJP",                   EUC_JP},
234     {"EUC-JP",                  EUC_JP},
235     {"EUCJP-NKF",               EUCJP_NKF},
236     {"CP51932",                 CP51932},
237     {"EUC-JP-MS",               EUCJP_MS},
238     {"EUCJP-MS",                EUCJP_MS},
239     {"EUCJPMS",                 EUCJP_MS},
240     {"EUC-JP-ASCII",            EUCJP_ASCII},
241     {"EUCJP-ASCII",             EUCJP_ASCII},
242     {"SHIFT_JISX0213",          SHIFT_JISX0213},
243     {"SHIFT_JIS-2004",          SHIFT_JIS_2004},
244     {"EUC-JISX0213",            EUC_JISX0213},
245     {"EUC-JIS-2004",            EUC_JIS_2004},
246     {"UTF-8",                   UTF_8},
247     {"UTF-8N",                  UTF_8N},
248     {"UTF-8-BOM",               UTF_8_BOM},
249     {"UTF8-MAC",                UTF8_MAC},
250     {"UTF-8-MAC",               UTF8_MAC},
251     {"UTF-16",                  UTF_16},
252     {"UTF-16BE",                UTF_16BE},
253     {"UTF-16BE-BOM",            UTF_16BE_BOM},
254     {"UTF-16LE",                UTF_16LE},
255     {"UTF-16LE-BOM",            UTF_16LE_BOM},
256     {"UTF-32",                  UTF_32},
257     {"UTF-32BE",                UTF_32BE},
258     {"UTF-32BE-BOM",            UTF_32BE_BOM},
259     {"UTF-32LE",                UTF_32LE},
260     {"UTF-32LE-BOM",            UTF_32LE_BOM},
261     {"BINARY",                  BINARY},
262     {NULL,                      -1}
263 };
264
265 #if defined(DEFAULT_CODE_JIS)
266 #define     DEFAULT_ENCIDX ISO_2022_JP
267 #elif defined(DEFAULT_CODE_SJIS)
268 #define     DEFAULT_ENCIDX SHIFT_JIS
269 #elif defined(DEFAULT_CODE_WINDOWS_31J)
270 #define     DEFAULT_ENCIDX WINDOWS_31J
271 #elif defined(DEFAULT_CODE_EUC)
272 #define     DEFAULT_ENCIDX EUC_JP
273 #elif defined(DEFAULT_CODE_UTF8)
274 #define     DEFAULT_ENCIDX UTF_8
275 #endif
276
277
278 #define         is_alnum(c)  \
279     (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
280
281 /* I don't trust portablity of toupper */
282 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
283 #define nkf_isoctal(c)  ('0'<=c && c<='7')
284 #define nkf_isdigit(c)  ('0'<=c && c<='9')
285 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
286 #define nkf_isblank(c) (c == SP || c == TAB)
287 #define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == LF)
288 #define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
289 #define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c))
290 #define nkf_isprint(c) (SP<=c && c<='~')
291 #define nkf_isgraph(c) ('!'<=c && c<='~')
292 #define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \
293                     ('A'<=c&&c<='F') ? (c-'A'+10) : \
294                     ('a'<=c&&c<='f') ? (c-'a'+10) : 0)
295 #define bin2hex(c) ("0123456789ABCDEF"[c&15])
296 #define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3)
297 #define nkf_noescape_mime(c) ((c == CR) || (c == LF) || \
298                               ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \
299                                && (c != '(') && (c != ')') && (c != '.') && (c != 0x22)))
300
301 #define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END)
302 #define nkf_byte_jisx0201_katakana_p(c) (SP <= c && c <= 0x5F)
303
304 #define         HOLD_SIZE       1024
305 #if defined(INT_IS_SHORT)
306 #define         IOBUF_SIZE      2048
307 #else
308 #define         IOBUF_SIZE      16384
309 #endif
310
311 #define         DEFAULT_J       'B'
312 #define         DEFAULT_R       'B'
313
314
315 #define         GETA1   0x22
316 #define         GETA2   0x2e
317
318
319 /* MIME preprocessor */
320
321 #ifdef EASYWIN /*Easy Win */
322 extern POINT _BufferSize;
323 #endif
324
325 struct input_code{
326     const char *name;
327     nkf_char stat;
328     nkf_char score;
329     nkf_char index;
330     nkf_char buf[3];
331     void (*status_func)(struct input_code *, nkf_char);
332     nkf_char (*iconv_func)(nkf_char c2, nkf_char c1, nkf_char c0);
333     int _file_stat;
334 };
335
336 static const char *input_codename = NULL; /* NULL: unestablished, "": BINARY */
337 static nkf_encoding *input_encoding = NULL;
338 static nkf_encoding *output_encoding = NULL;
339
340 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
341 /* UCS Mapping
342  * 0: Shift_JIS, eucJP-ascii
343  * 1: eucJP-ms
344  * 2: CP932, CP51932
345  * 3: CP10001
346  */
347 #define UCS_MAP_ASCII   0
348 #define UCS_MAP_MS      1
349 #define UCS_MAP_CP932   2
350 #define UCS_MAP_CP10001 3
351 static int ms_ucs_map_f = UCS_MAP_ASCII;
352 #endif
353 #ifdef UTF8_INPUT_ENABLE
354 /* no NEC special, NEC-selected IBM extended and IBM extended characters */
355 static  int     no_cp932ext_f = FALSE;
356 /* ignore ZERO WIDTH NO-BREAK SPACE */
357 static  int     no_best_fit_chars_f = FALSE;
358 static  int     input_endian = ENDIAN_BIG;
359 static  int     input_bom_f = FALSE;
360 static  nkf_char     unicode_subchar = '?'; /* the regular substitution character */
361 static  void    (*encode_fallback)(nkf_char c) = NULL;
362 static  void    w_status(struct input_code *, nkf_char);
363 #endif
364 #ifdef UTF8_OUTPUT_ENABLE
365 static  int     output_bom_f = FALSE;
366 static  int     output_endian = ENDIAN_BIG;
367 #endif
368
369 static  void    std_putc(nkf_char c);
370 static  nkf_char     std_getc(FILE *f);
371 static  nkf_char     std_ungetc(nkf_char c,FILE *f);
372
373 static  nkf_char     broken_getc(FILE *f);
374 static  nkf_char     broken_ungetc(nkf_char c,FILE *f);
375
376 static  nkf_char     mime_getc(FILE *f);
377
378 static void mime_putc(nkf_char c);
379
380 /* buffers */
381
382 #if !defined(PERL_XS) && !defined(WIN32DLL)
383 static unsigned char   stdibuf[IOBUF_SIZE];
384 static unsigned char   stdobuf[IOBUF_SIZE];
385 #endif
386
387 #define NKF_UNSPECIFIED (-TRUE)
388
389 /* flags */
390 static int             unbuf_f = FALSE;
391 static int             estab_f = FALSE;
392 static int             nop_f = FALSE;
393 static int             binmode_f = TRUE;       /* binary mode */
394 static int             rot_f = FALSE;          /* rot14/43 mode */
395 static int             hira_f = FALSE;          /* hira/kata henkan */
396 static int             alpha_f = FALSE;        /* convert JIx0208 alphbet to ASCII */
397 static int             mime_f = MIME_DECODE_DEFAULT;   /* convert MIME B base64 or Q */
398 static int             mime_decode_f = FALSE;  /* mime decode is explicitly on */
399 static int             mimebuf_f = FALSE;      /* MIME buffered input */
400 static int             broken_f = FALSE;       /* convert ESC-less broken JIS */
401 static int             iso8859_f = FALSE;      /* ISO8859 through */
402 static int             mimeout_f = FALSE;       /* base64 mode */
403 static int             x0201_f = NKF_UNSPECIFIED;   /* convert JIS X 0201 */
404 static int             iso2022jp_f = FALSE;    /* replace non ISO-2022-JP with GETA */
405
406 #ifdef UNICODE_NORMALIZATION
407 static int nfc_f = FALSE;
408 static nkf_char (*i_nfc_getc)(FILE *) = std_getc; /* input of ugetc */
409 static nkf_char (*i_nfc_ungetc)(nkf_char c ,FILE *f) = std_ungetc;
410 #endif
411
412 #ifdef INPUT_OPTION
413 static int cap_f = FALSE;
414 static nkf_char (*i_cgetc)(FILE *) = std_getc; /* input of cgetc */
415 static nkf_char (*i_cungetc)(nkf_char c ,FILE *f) = std_ungetc;
416
417 static int url_f = FALSE;
418 static nkf_char (*i_ugetc)(FILE *) = std_getc; /* input of ugetc */
419 static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc;
420 #endif
421
422 #define PREFIX_EUCG3    NKF_INT32_C(0x8F00)
423 #define CLASS_MASK      NKF_INT32_C(0xFF000000)
424 #define CLASS_UNICODE   NKF_INT32_C(0x01000000)
425 #define VALUE_MASK      NKF_INT32_C(0x00FFFFFF)
426 #define UNICODE_BMP_MAX NKF_INT32_C(0x0000FFFF)
427 #define UNICODE_MAX     NKF_INT32_C(0x0010FFFF)
428 #define nkf_char_euc3_new(c) ((c) | PREFIX_EUCG3)
429 #define nkf_char_unicode_new(c) ((c) | CLASS_UNICODE)
430 #define nkf_char_unicode_p(c) ((c & CLASS_MASK) == CLASS_UNICODE)
431 #define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= UNICODE_BMP_MAX)
432 #define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= UNICODE_MAX)
433
434 #ifdef NUMCHAR_OPTION
435 static int numchar_f = FALSE;
436 static nkf_char (*i_ngetc)(FILE *) = std_getc; /* input of ugetc */
437 static nkf_char (*i_nungetc)(nkf_char c ,FILE *f) = std_ungetc;
438 #endif
439
440 #ifdef CHECK_OPTION
441 static int noout_f = FALSE;
442 static void no_putc(nkf_char c);
443 static int debug_f = FALSE;
444 static void debug(const char *str);
445 static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0;
446 #endif
447
448 static int guess_f = 0; /* 0: OFF, 1: ON, 2: VERBOSE */
449 static  void    set_input_codename(const char *codename);
450
451 #ifdef EXEC_IO
452 static int exec_f = 0;
453 #endif
454
455 #ifdef SHIFTJIS_CP932
456 /* invert IBM extended characters to others */
457 static int cp51932_f = FALSE;
458
459 /* invert NEC-selected IBM extended characters to IBM extended characters */
460 static int cp932inv_f = TRUE;
461
462 /* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */
463 #endif /* SHIFTJIS_CP932 */
464
465 static int x0212_f = FALSE;
466 static int x0213_f = FALSE;
467
468 static unsigned char prefix_table[256];
469
470 static void e_status(struct input_code *, nkf_char);
471 static void s_status(struct input_code *, nkf_char);
472
473 struct input_code input_code_list[] = {
474     {"EUC-JP",    0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
475     {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
476 #ifdef UTF8_INPUT_ENABLE
477     {"UTF-8",     0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
478     {"UTF-16",     0, 0, 0, {0, 0, 0}, NULL, w_iconv16, 0},
479     {"UTF-32",     0, 0, 0, {0, 0, 0}, NULL, w_iconv32, 0},
480 #endif
481     {NULL,        0, 0, 0, {0, 0, 0}, NULL, NULL, 0}
482 };
483
484 static int              mimeout_mode = 0; /* 0, -1, 'Q', 'B', 1, 2 */
485 static int              base64_count = 0;
486
487 /* X0208 -> ASCII converter */
488
489 /* fold parameter */
490 static int             f_line = 0;    /* chars in line */
491 static int             f_prev = 0;
492 static int             fold_preserve_f = FALSE; /* preserve new lines */
493 static int             fold_f  = FALSE;
494 static int             fold_len  = 0;
495
496 /* options */
497 static unsigned char   kanji_intro = DEFAULT_J;
498 static unsigned char   ascii_intro = DEFAULT_R;
499
500 /* Folding */
501
502 #define FOLD_MARGIN  10
503 #define DEFAULT_FOLD 60
504
505 static int             fold_margin  = FOLD_MARGIN;
506
507 /* process default */
508
509 static nkf_char
510 no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
511 {
512     fprintf(stderr,"nkf internal module connection failure.\n");
513     exit(EXIT_FAILURE);
514     return 0; /* LINT */
515 }
516
517 static void
518 no_connection(nkf_char c2, nkf_char c1)
519 {
520     no_connection2(c2,c1,0);
521 }
522
523 static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2;
524 static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection;
525
526 static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection;
527 static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection;
528 static void (*o_eol_conv)(nkf_char c2,nkf_char c1) = no_connection;
529 static void (*o_rot_conv)(nkf_char c2,nkf_char c1) = no_connection;
530 static void (*o_hira_conv)(nkf_char c2,nkf_char c1) = no_connection;
531 static void (*o_base64conv)(nkf_char c2,nkf_char c1) = no_connection;
532 static void (*o_iso2022jp_check_conv)(nkf_char c2,nkf_char c1) = no_connection;
533
534 /* static redirections */
535
536 static  void   (*o_putc)(nkf_char c) = std_putc;
537
538 static  nkf_char    (*i_getc)(FILE *f) = std_getc; /* general input */
539 static  nkf_char    (*i_ungetc)(nkf_char c,FILE *f) =std_ungetc;
540
541 static  nkf_char    (*i_bgetc)(FILE *) = std_getc; /* input of mgetc */
542 static  nkf_char    (*i_bungetc)(nkf_char c ,FILE *f) = std_ungetc;
543
544 static  void   (*o_mputc)(nkf_char c) = std_putc ; /* output of mputc */
545
546 static  nkf_char    (*i_mgetc)(FILE *) = std_getc; /* input of mgetc */
547 static  nkf_char    (*i_mungetc)(nkf_char c ,FILE *f) = std_ungetc;
548
549 /* for strict mime */
550 static  nkf_char    (*i_mgetc_buf)(FILE *) = std_getc; /* input of mgetc_buf */
551 static  nkf_char    (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc;
552
553 /* Global states */
554 static int output_mode = ASCII;    /* output kanji mode */
555 static int input_mode =  ASCII;    /* input kanji mode */
556 static int mime_decode_mode =   FALSE;    /* MIME mode B base64, Q hex */
557
558 /* X0201 / X0208 conversion tables */
559
560 /* X0201 kana conversion table */
561 /* 90-9F A0-DF */
562 static const unsigned char cv[]= {
563     0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
564     0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
565     0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
566     0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
567     0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
568     0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
569     0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
570     0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
571     0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
572     0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
573     0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
574     0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
575     0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
576     0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
577     0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
578     0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
579     0x00,0x00};
580
581
582 /* X0201 kana conversion table for daguten */
583 /* 90-9F A0-DF */
584 static const unsigned char dv[]= {
585     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
586     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
587     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
588     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
589     0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74,
590     0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
591     0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
592     0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
593     0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
594     0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
595     0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
596     0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
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};
602
603 /* X0201 kana conversion table for han-daguten */
604 /* 90-9F A0-DF */
605 static const unsigned char ev[]= {
606     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
607     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
608     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
609     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
610     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
611     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
612     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
613     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
614     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
615     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
616     0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
617     0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
618     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
619     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
620     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
621     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
622     0x00,0x00};
623
624
625 /* X0208 kigou conversion table */
626 /* 0x8140 - 0x819e */
627 static const unsigned char fv[] = {
628
629     0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
630     0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
631     0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
632     0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
633     0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
634     0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
635     0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
636     0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
637     0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
638     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
639     0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
640     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
641 } ;
642
643
644
645 static int option_mode = 0;
646 static int             file_out_f = FALSE;
647 #ifdef OVERWRITE
648 static int             overwrite_f = FALSE;
649 static int             preserve_time_f = FALSE;
650 static int             backup_f = FALSE;
651 static char            *backup_suffix = "";
652 #endif
653
654 static int eolmode_f = 0;   /* CR, LF, CRLF */
655 static int input_eol = 0; /* 0: unestablished, EOF: MIXED */
656 static nkf_char prev_cr = 0; /* CR or 0 */
657 #ifdef EASYWIN /*Easy Win */
658 static int             end_check;
659 #endif /*Easy Win */
660
661 static void *
662 nkf_xmalloc(size_t size)
663 {
664     void *ptr;
665
666     if (size == 0) size = 1;
667
668     ptr = malloc(size);
669     if (ptr == NULL) {
670         perror("can't malloc");
671         exit(EXIT_FAILURE);
672     }
673
674     return ptr;
675 }
676
677 static void *
678 nkf_xrealloc(void *ptr, size_t size)
679 {
680     if (size == 0) size = 1;
681
682     ptr = realloc(ptr, size);
683     if (ptr == NULL) {
684         perror("can't realloc");
685         exit(EXIT_FAILURE);
686     }
687
688     return ptr;
689 }
690
691 #define nkf_xfree(ptr) free(ptr)
692
693 static int
694 nkf_str_caseeql(const char *src, const char *target)
695 {
696     int i;
697     for (i = 0; src[i] && target[i]; i++) {
698         if (nkf_toupper(src[i]) != nkf_toupper(target[i])) return FALSE;
699     }
700     if (src[i] || target[i]) return FALSE;
701     else return TRUE;
702 }
703
704 static nkf_encoding*
705 nkf_enc_from_index(int idx)
706 {
707     if (idx < 0 || NKF_ENCODING_TABLE_SIZE <= idx) {
708         return 0;
709     }
710     return &nkf_encoding_table[idx];
711 }
712
713 static int
714 nkf_enc_find_index(const char *name)
715 {
716     int i;
717     if (name[0] == 'X' && *(name+1) == '-') name += 2;
718     for (i = 0; encoding_name_to_id_table[i].id >= 0; i++) {
719         if (nkf_str_caseeql(encoding_name_to_id_table[i].name, name)) {
720             return encoding_name_to_id_table[i].id;
721         }
722     }
723     return -1;
724 }
725
726 static nkf_encoding*
727 nkf_enc_find(const char *name)
728 {
729     int idx = -1;
730     idx = nkf_enc_find_index(name);
731     if (idx < 0) return 0;
732     return nkf_enc_from_index(idx);
733 }
734
735 #define nkf_enc_name(enc) (enc)->name
736 #define nkf_enc_to_index(enc) (enc)->id
737 #define nkf_enc_to_base_encoding(enc) (enc)->base_encoding
738 #define nkf_enc_to_iconv(enc) nkf_enc_to_base_encoding(enc)->iconv
739 #define nkf_enc_to_oconv(enc) nkf_enc_to_base_encoding(enc)->oconv
740 #define nkf_enc_asciicompat(enc) (\
741                                   nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\
742                                   nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP)
743 #define nkf_enc_unicode_p(enc) (\
744                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\
745                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\
746                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32)
747 #define nkf_enc_cp5022x_p(enc) (\
748                                 nkf_enc_to_index(enc) == CP50220 ||\
749                                 nkf_enc_to_index(enc) == CP50221 ||\
750                                 nkf_enc_to_index(enc) == CP50222)
751
752 #ifdef DEFAULT_CODE_LOCALE
753 static const char*
754 nkf_locale_charmap()
755 {
756 #ifdef HAVE_LANGINFO_H
757     return nl_langinfo(CODESET);
758 #elif defined(__WIN32__)
759     static char buf[16];
760     sprintf(buf, "CP%d", GetACP());
761     return buf;
762 #elif defined(__OS2__)
763 # if defined(INT_IS_SHORT)
764     /* OS/2 1.x */
765     return NULL;
766 # else
767     /* OS/2 32bit */
768     static char buf[16];
769     ULONG ulCP[1], ulncp;
770     DosQueryCp(sizeof(ulCP), ulCP, &ulncp);
771     if (ulCP[0] == 932 || ulCP[0] == 943)
772         strcpy(buf, "Shift_JIS");
773     else
774         sprintf(buf, "CP%lu", ulCP[0]);
775     return buf;
776 # endif
777 #endif
778     return NULL;
779 }
780
781 static nkf_encoding*
782 nkf_locale_encoding()
783 {
784     nkf_encoding *enc = 0;
785     const char *encname = nkf_locale_charmap();
786     if (encname)
787         enc = nkf_enc_find(encname);
788     return enc;
789 }
790 #endif /* DEFAULT_CODE_LOCALE */
791
792 static nkf_encoding*
793 nkf_utf8_encoding()
794 {
795     return &nkf_encoding_table[UTF_8];
796 }
797
798 static nkf_encoding*
799 nkf_default_encoding()
800 {
801     nkf_encoding *enc = 0;
802 #ifdef DEFAULT_CODE_LOCALE
803     enc = nkf_locale_encoding();
804 #elif defined(DEFAULT_ENCIDX)
805     enc = nkf_enc_from_index(DEFAULT_ENCIDX);
806 #endif
807     if (!enc) enc = nkf_utf8_encoding();
808     return enc;
809 }
810
811 typedef struct {
812     long capa;
813     long len;
814     nkf_char *ptr;
815 } nkf_buf_t;
816
817 static nkf_buf_t *
818 nkf_buf_new(int length)
819 {
820     nkf_buf_t *buf = nkf_xmalloc(sizeof(nkf_buf_t));
821     buf->ptr = nkf_xmalloc(sizeof(nkf_char) * length);
822     buf->capa = length;
823     buf->len = 0;
824     return buf;
825 }
826
827 #if 0
828 static void
829 nkf_buf_dispose(nkf_buf_t *buf)
830 {
831     nkf_xfree(buf->ptr);
832     nkf_xfree(buf);
833 }
834 #endif
835
836 #define nkf_buf_length(buf) ((buf)->len)
837 #define nkf_buf_empty_p(buf) ((buf)->len == 0)
838
839 static nkf_char
840 nkf_buf_at(nkf_buf_t *buf, int index)
841 {
842     assert(index <= buf->len);
843     return buf->ptr[index];
844 }
845
846 static void
847 nkf_buf_clear(nkf_buf_t *buf)
848 {
849     buf->len = 0;
850 }
851
852 static void
853 nkf_buf_push(nkf_buf_t *buf, nkf_char c)
854 {
855     if (buf->capa <= buf->len) {
856         exit(EXIT_FAILURE);
857     }
858     buf->ptr[buf->len++] = c;
859 }
860
861 static nkf_char
862 nkf_buf_pop(nkf_buf_t *buf)
863 {
864     assert(!nkf_buf_empty_p(buf));
865     return buf->ptr[--buf->len];
866 }
867
868 /* Normalization Form C */
869 #ifndef PERL_XS
870 #ifdef WIN32DLL
871 #define fprintf dllprintf
872 #endif
873
874 static void
875 version(void)
876 {
877     fprintf(HELP_OUTPUT,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n");
878 }
879
880 static void
881 usage(void)
882 {
883     fprintf(HELP_OUTPUT,
884             "Usage:  nkf -[flags] [--] [in file] .. [out file for -O flag]\n"
885 #ifdef UTF8_OUTPUT_ENABLE
886             " j/s/e/w  Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
887             "          UTF options is -w[8[0],{16,32}[{B,L}[0]]]\n"
888 #else
889 #endif
890 #ifdef UTF8_INPUT_ENABLE
891             " J/S/E/W  Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
892             "          UTF option is -W[8,[16,32][B,L]]\n"
893 #else
894             " J/S/E    Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
895 #endif
896             );
897     fprintf(HELP_OUTPUT,
898             " m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:nonstrict,0:no decode]\n"
899             " M[BQ]    MIME encode [B:base64 Q:quoted]\n"
900             " f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n"
901             );
902     fprintf(HELP_OUTPUT,
903             " Z[0-4]   Default/0: Convert JISX0208 Alphabet to ASCII\n"
904             "          1: Kankaku to one space  2: to two spaces  3: HTML Entity\n"
905             "          4: JISX0208 Katakana to JISX0201 Katakana\n"
906             " X,x      Convert Halfwidth Katakana to Fullwidth or preserve it\n"
907             );
908     fprintf(HELP_OUTPUT,
909             " O        Output to File (DEFAULT 'nkf.out')\n"
910             " L[uwm]   Line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n"
911             );
912     fprintf(HELP_OUTPUT,
913             " --ic=<encoding>        Specify the input encoding\n"
914             " --oc=<encoding>        Specify the output encoding\n"
915             " --hiragana --katakana  Hiragana/Katakana Conversion\n"
916             " --katakana-hiragana    Converts each other\n"
917             );
918     fprintf(HELP_OUTPUT,
919 #ifdef INPUT_OPTION
920             " --{cap, url}-input     Convert hex after ':' or '%%'\n"
921 #endif
922 #ifdef NUMCHAR_OPTION
923             " --numchar-input        Convert Unicode Character Reference\n"
924 #endif
925 #ifdef UTF8_INPUT_ENABLE
926             " --fb-{skip, html, xml, perl, java, subchar}\n"
927             "                        Specify unassigned character's replacement\n"
928 #endif
929             );
930     fprintf(HELP_OUTPUT,
931 #ifdef OVERWRITE
932             " --in-place[=SUF]       Overwrite original files\n"
933             " --overwrite[=SUF]      Preserve timestamp of original files\n"
934 #endif
935             " -g --guess             Guess the input code\n"
936             " -v --version           Print the version\n"
937             " --help/-V              Print this help / configuration\n"
938             );
939     version();
940 }
941
942 static void
943 show_configuration(void)
944 {
945     fprintf(HELP_OUTPUT,
946             "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n"
947             "  Compile-time options:\n"
948             "    Compiled at:                 " __DATE__ " " __TIME__ "\n"
949            );
950     fprintf(HELP_OUTPUT,
951             "    Default output encoding:     "
952 #ifdef DEFAULT_CODE_LOCALE
953             "LOCALE (%s)\n", nkf_enc_name(nkf_default_encoding())
954 #elif defined(DEFAULT_ENCIDX)
955             "CONFIG (%s)\n", nkf_enc_name(nkf_default_encoding())
956 #else
957             "NONE\n"
958 #endif
959            );
960     fprintf(HELP_OUTPUT,
961             "    Default output end of line:  "
962 #if DEFAULT_NEWLINE == CR
963             "CR"
964 #elif DEFAULT_NEWLINE == CRLF
965             "CRLF"
966 #else
967             "LF"
968 #endif
969             "\n"
970             "    Decode MIME encoded string:  "
971 #if MIME_DECODE_DEFAULT
972             "ON"
973 #else
974             "OFF"
975 #endif
976             "\n"
977             "    Convert JIS X 0201 Katakana: "
978 #if X0201_DEFAULT
979             "ON"
980 #else
981             "OFF"
982 #endif
983             "\n"
984             "    --help, --version output:    "
985 #if HELP_OUTPUT_HELP_OUTPUT
986             "HELP_OUTPUT"
987 #else
988             "STDOUT"
989 #endif
990             "\n");
991 }
992 #endif /*PERL_XS*/
993
994 #ifdef OVERWRITE
995 static char*
996 get_backup_filename(const char *suffix, const char *filename)
997 {
998     char *backup_filename;
999     int asterisk_count = 0;
1000     int i, j;
1001     int filename_length = strlen(filename);
1002
1003     for(i = 0; suffix[i]; i++){
1004         if(suffix[i] == '*') asterisk_count++;
1005     }
1006
1007     if(asterisk_count){
1008         backup_filename = nkf_xmalloc(strlen(suffix) + (asterisk_count * (filename_length - 1)) + 1);
1009         for(i = 0, j = 0; suffix[i];){
1010             if(suffix[i] == '*'){
1011                 backup_filename[j] = '\0';
1012                 strncat(backup_filename, filename, filename_length);
1013                 i++;
1014                 j += filename_length;
1015             }else{
1016                 backup_filename[j++] = suffix[i++];
1017             }
1018         }
1019         backup_filename[j] = '\0';
1020     }else{
1021         j = filename_length + strlen(suffix);
1022         backup_filename = nkf_xmalloc(j + 1);
1023         strcpy(backup_filename, filename);
1024         strcat(backup_filename, suffix);
1025         backup_filename[j] = '\0';
1026     }
1027     return backup_filename;
1028 }
1029 #endif
1030
1031 #ifdef UTF8_INPUT_ENABLE
1032 static void
1033 nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
1034 {
1035     int shift = 20;
1036     c &= VALUE_MASK;
1037     while(shift >= 0){
1038         if(c >= NKF_INT32_C(1)<<shift){
1039             while(shift >= 0){
1040                 (*f)(0, bin2hex(c>>shift));
1041                 shift -= 4;
1042             }
1043         }else{
1044             shift -= 4;
1045         }
1046     }
1047     return;
1048 }
1049
1050 static void
1051 encode_fallback_html(nkf_char c)
1052 {
1053     (*oconv)(0, '&');
1054     (*oconv)(0, '#');
1055     c &= VALUE_MASK;
1056     if(c >= NKF_INT32_C(1000000))
1057         (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10);
1058     if(c >= NKF_INT32_C(100000))
1059         (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10);
1060     if(c >= 10000)
1061         (*oconv)(0, 0x30+(c/10000  )%10);
1062     if(c >= 1000)
1063         (*oconv)(0, 0x30+(c/1000   )%10);
1064     if(c >= 100)
1065         (*oconv)(0, 0x30+(c/100    )%10);
1066     if(c >= 10)
1067         (*oconv)(0, 0x30+(c/10     )%10);
1068     if(c >= 0)
1069         (*oconv)(0, 0x30+ c         %10);
1070     (*oconv)(0, ';');
1071     return;
1072 }
1073
1074 static void
1075 encode_fallback_xml(nkf_char c)
1076 {
1077     (*oconv)(0, '&');
1078     (*oconv)(0, '#');
1079     (*oconv)(0, 'x');
1080     nkf_each_char_to_hex(oconv, c);
1081     (*oconv)(0, ';');
1082     return;
1083 }
1084
1085 static void
1086 encode_fallback_java(nkf_char c)
1087 {
1088     (*oconv)(0, '\\');
1089     c &= VALUE_MASK;
1090     if(!nkf_char_unicode_bmp_p(c)){
1091         (*oconv)(0, 'U');
1092         (*oconv)(0, '0');
1093         (*oconv)(0, '0');
1094         (*oconv)(0, bin2hex(c>>20));
1095         (*oconv)(0, bin2hex(c>>16));
1096     }else{
1097         (*oconv)(0, 'u');
1098     }
1099     (*oconv)(0, bin2hex(c>>12));
1100     (*oconv)(0, bin2hex(c>> 8));
1101     (*oconv)(0, bin2hex(c>> 4));
1102     (*oconv)(0, bin2hex(c    ));
1103     return;
1104 }
1105
1106 static void
1107 encode_fallback_perl(nkf_char c)
1108 {
1109     (*oconv)(0, '\\');
1110     (*oconv)(0, 'x');
1111     (*oconv)(0, '{');
1112     nkf_each_char_to_hex(oconv, c);
1113     (*oconv)(0, '}');
1114     return;
1115 }
1116
1117 static void
1118 encode_fallback_subchar(nkf_char c)
1119 {
1120     c = unicode_subchar;
1121     (*oconv)((c>>8)&0xFF, c&0xFF);
1122     return;
1123 }
1124 #endif
1125
1126 static const struct {
1127     const char *name;
1128     const char *alias;
1129 } long_option[] = {
1130     {"ic=", ""},
1131     {"oc=", ""},
1132     {"base64","jMB"},
1133     {"euc","e"},
1134     {"euc-input","E"},
1135     {"fj","jm"},
1136     {"help",""},
1137     {"jis","j"},
1138     {"jis-input","J"},
1139     {"mac","sLm"},
1140     {"mime","jM"},
1141     {"mime-input","m"},
1142     {"msdos","sLw"},
1143     {"sjis","s"},
1144     {"sjis-input","S"},
1145     {"unix","eLu"},
1146     {"version","v"},
1147     {"windows","sLw"},
1148     {"hiragana","h1"},
1149     {"katakana","h2"},
1150     {"katakana-hiragana","h3"},
1151     {"guess=", ""},
1152     {"guess", "g2"},
1153     {"cp932", ""},
1154     {"no-cp932", ""},
1155 #ifdef X0212_ENABLE
1156     {"x0212", ""},
1157 #endif
1158 #ifdef UTF8_OUTPUT_ENABLE
1159     {"utf8", "w"},
1160     {"utf16", "w16"},
1161     {"ms-ucs-map", ""},
1162     {"fb-skip", ""},
1163     {"fb-html", ""},
1164     {"fb-xml", ""},
1165     {"fb-perl", ""},
1166     {"fb-java", ""},
1167     {"fb-subchar", ""},
1168     {"fb-subchar=", ""},
1169 #endif
1170 #ifdef UTF8_INPUT_ENABLE
1171     {"utf8-input", "W"},
1172     {"utf16-input", "W16"},
1173     {"no-cp932ext", ""},
1174     {"no-best-fit-chars",""},
1175 #endif
1176 #ifdef UNICODE_NORMALIZATION
1177     {"utf8mac-input", ""},
1178 #endif
1179 #ifdef OVERWRITE
1180     {"overwrite", ""},
1181     {"overwrite=", ""},
1182     {"in-place", ""},
1183     {"in-place=", ""},
1184 #endif
1185 #ifdef INPUT_OPTION
1186     {"cap-input", ""},
1187     {"url-input", ""},
1188 #endif
1189 #ifdef NUMCHAR_OPTION
1190     {"numchar-input", ""},
1191 #endif
1192 #ifdef CHECK_OPTION
1193     {"no-output", ""},
1194     {"debug", ""},
1195 #endif
1196 #ifdef SHIFTJIS_CP932
1197     {"cp932inv", ""},
1198 #endif
1199 #ifdef EXEC_IO
1200     {"exec-in", ""},
1201     {"exec-out", ""},
1202 #endif
1203     {"prefix=", ""},
1204 };
1205
1206 static void
1207 set_input_encoding(nkf_encoding *enc)
1208 {
1209     switch (nkf_enc_to_index(enc)) {
1210     case ISO_8859_1:
1211         iso8859_f = TRUE;
1212         break;
1213     case CP50221:
1214     case CP50222:
1215         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1216     case CP50220:
1217 #ifdef SHIFTJIS_CP932
1218         cp51932_f = TRUE;
1219 #endif
1220 #ifdef UTF8_OUTPUT_ENABLE
1221         ms_ucs_map_f = UCS_MAP_CP932;
1222 #endif
1223         break;
1224     case ISO_2022_JP_1:
1225         x0212_f = TRUE;
1226         break;
1227     case ISO_2022_JP_3:
1228         x0212_f = TRUE;
1229         x0213_f = TRUE;
1230         break;
1231     case ISO_2022_JP_2004:
1232         x0212_f = TRUE;
1233         x0213_f = TRUE;
1234         break;
1235     case SHIFT_JIS:
1236         break;
1237     case WINDOWS_31J:
1238         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1239 #ifdef SHIFTJIS_CP932
1240         cp51932_f = TRUE;
1241 #endif
1242 #ifdef UTF8_OUTPUT_ENABLE
1243         ms_ucs_map_f = UCS_MAP_CP932;
1244 #endif
1245         break;
1246         break;
1247     case CP10001:
1248 #ifdef SHIFTJIS_CP932
1249         cp51932_f = TRUE;
1250 #endif
1251 #ifdef UTF8_OUTPUT_ENABLE
1252         ms_ucs_map_f = UCS_MAP_CP10001;
1253 #endif
1254         break;
1255     case EUC_JP:
1256         break;
1257     case EUCJP_NKF:
1258         break;
1259     case CP51932:
1260         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1261 #ifdef SHIFTJIS_CP932
1262         cp51932_f = TRUE;
1263 #endif
1264 #ifdef UTF8_OUTPUT_ENABLE
1265         ms_ucs_map_f = UCS_MAP_CP932;
1266 #endif
1267         break;
1268     case EUCJP_MS:
1269         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1270 #ifdef SHIFTJIS_CP932
1271         cp51932_f = FALSE;
1272 #endif
1273 #ifdef UTF8_OUTPUT_ENABLE
1274         ms_ucs_map_f = UCS_MAP_MS;
1275 #endif
1276         break;
1277     case EUCJP_ASCII:
1278         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1279 #ifdef SHIFTJIS_CP932
1280         cp51932_f = FALSE;
1281 #endif
1282 #ifdef UTF8_OUTPUT_ENABLE
1283         ms_ucs_map_f = UCS_MAP_ASCII;
1284 #endif
1285         break;
1286     case SHIFT_JISX0213:
1287     case SHIFT_JIS_2004:
1288         x0213_f = TRUE;
1289 #ifdef SHIFTJIS_CP932
1290         cp51932_f = FALSE;
1291 #endif
1292         break;
1293     case EUC_JISX0213:
1294     case EUC_JIS_2004:
1295         x0213_f = TRUE;
1296 #ifdef SHIFTJIS_CP932
1297         cp51932_f = FALSE;
1298 #endif
1299         break;
1300 #ifdef UTF8_INPUT_ENABLE
1301 #ifdef UNICODE_NORMALIZATION
1302     case UTF8_MAC:
1303         nfc_f = TRUE;
1304         break;
1305 #endif
1306     case UTF_16:
1307     case UTF_16BE:
1308     case UTF_16BE_BOM:
1309         input_endian = ENDIAN_BIG;
1310         break;
1311     case UTF_16LE:
1312     case UTF_16LE_BOM:
1313         input_endian = ENDIAN_LITTLE;
1314         break;
1315     case UTF_32:
1316     case UTF_32BE:
1317     case UTF_32BE_BOM:
1318         input_endian = ENDIAN_BIG;
1319         break;
1320     case UTF_32LE:
1321     case UTF_32LE_BOM:
1322         input_endian = ENDIAN_LITTLE;
1323         break;
1324 #endif
1325     }
1326 }
1327
1328 static void
1329 set_output_encoding(nkf_encoding *enc)
1330 {
1331     switch (nkf_enc_to_index(enc)) {
1332     case CP50220:
1333 #ifdef SHIFTJIS_CP932
1334         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1335 #endif
1336 #ifdef UTF8_OUTPUT_ENABLE
1337         ms_ucs_map_f = UCS_MAP_CP932;
1338 #endif
1339         break;
1340     case CP50221:
1341         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1342 #ifdef SHIFTJIS_CP932
1343         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1344 #endif
1345 #ifdef UTF8_OUTPUT_ENABLE
1346         ms_ucs_map_f = UCS_MAP_CP932;
1347 #endif
1348         break;
1349     case ISO_2022_JP:
1350 #ifdef SHIFTJIS_CP932
1351         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1352 #endif
1353         break;
1354     case ISO_2022_JP_1:
1355         x0212_f = TRUE;
1356 #ifdef SHIFTJIS_CP932
1357         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1358 #endif
1359         break;
1360     case ISO_2022_JP_3:
1361         x0212_f = TRUE;
1362         x0213_f = TRUE;
1363 #ifdef SHIFTJIS_CP932
1364         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1365 #endif
1366         break;
1367     case SHIFT_JIS:
1368         break;
1369     case WINDOWS_31J:
1370         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1371 #ifdef UTF8_OUTPUT_ENABLE
1372         ms_ucs_map_f = UCS_MAP_CP932;
1373 #endif
1374         break;
1375     case CP10001:
1376 #ifdef UTF8_OUTPUT_ENABLE
1377         ms_ucs_map_f = UCS_MAP_CP10001;
1378 #endif
1379         break;
1380     case EUC_JP:
1381         x0212_f = TRUE;
1382 #ifdef SHIFTJIS_CP932
1383         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1384 #endif
1385 #ifdef UTF8_OUTPUT_ENABLE
1386         ms_ucs_map_f = UCS_MAP_ASCII;
1387 #endif
1388         break;
1389     case EUCJP_NKF:
1390         x0212_f = FALSE;
1391 #ifdef SHIFTJIS_CP932
1392         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1393 #endif
1394 #ifdef UTF8_OUTPUT_ENABLE
1395         ms_ucs_map_f = UCS_MAP_ASCII;
1396 #endif
1397         break;
1398     case CP51932:
1399         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1400 #ifdef SHIFTJIS_CP932
1401         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1402 #endif
1403 #ifdef UTF8_OUTPUT_ENABLE
1404         ms_ucs_map_f = UCS_MAP_CP932;
1405 #endif
1406         break;
1407     case EUCJP_MS:
1408         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1409         x0212_f = TRUE;
1410 #ifdef UTF8_OUTPUT_ENABLE
1411         ms_ucs_map_f = UCS_MAP_MS;
1412 #endif
1413         break;
1414     case EUCJP_ASCII:
1415         if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE;        /* -x specified implicitly */
1416         x0212_f = TRUE;
1417 #ifdef UTF8_OUTPUT_ENABLE
1418         ms_ucs_map_f = UCS_MAP_ASCII;
1419 #endif
1420         break;
1421     case SHIFT_JISX0213:
1422     case SHIFT_JIS_2004:
1423         x0213_f = TRUE;
1424 #ifdef SHIFTJIS_CP932
1425         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1426 #endif
1427         break;
1428     case EUC_JISX0213:
1429     case EUC_JIS_2004:
1430         x0212_f = TRUE;
1431         x0213_f = TRUE;
1432 #ifdef SHIFTJIS_CP932
1433         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1434 #endif
1435         break;
1436 #ifdef UTF8_OUTPUT_ENABLE
1437     case UTF_8_BOM:
1438         output_bom_f = TRUE;
1439         break;
1440     case UTF_16:
1441     case UTF_16BE_BOM:
1442         output_bom_f = TRUE;
1443         break;
1444     case UTF_16LE:
1445         output_endian = ENDIAN_LITTLE;
1446         output_bom_f = FALSE;
1447         break;
1448     case UTF_16LE_BOM:
1449         output_endian = ENDIAN_LITTLE;
1450         output_bom_f = TRUE;
1451         break;
1452     case UTF_32:
1453     case UTF_32BE_BOM:
1454         output_bom_f = TRUE;
1455         break;
1456     case UTF_32LE:
1457         output_endian = ENDIAN_LITTLE;
1458         output_bom_f = FALSE;
1459         break;
1460     case UTF_32LE_BOM:
1461         output_endian = ENDIAN_LITTLE;
1462         output_bom_f = TRUE;
1463         break;
1464 #endif
1465     }
1466 }
1467
1468 static struct input_code*
1469 find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
1470 {
1471     if (iconv_func){
1472         struct input_code *p = input_code_list;
1473         while (p->name){
1474             if (iconv_func == p->iconv_func){
1475                 return p;
1476             }
1477             p++;
1478         }
1479     }
1480     return 0;
1481 }
1482
1483 static void
1484 set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
1485 {
1486 #ifdef INPUT_CODE_FIX
1487     if (f || !input_encoding)
1488 #endif
1489         if (estab_f != f){
1490             estab_f = f;
1491         }
1492
1493     if (iconv_func
1494 #ifdef INPUT_CODE_FIX
1495         && (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */
1496 #endif
1497        ){
1498         iconv = iconv_func;
1499     }
1500 #ifdef CHECK_OPTION
1501     if (estab_f && iconv_for_check != iconv){
1502         struct input_code *p = find_inputcode_byfunc(iconv);
1503         if (p){
1504             set_input_codename(p->name);
1505             debug(p->name);
1506         }
1507         iconv_for_check = iconv;
1508     }
1509 #endif
1510 }
1511
1512 #ifdef X0212_ENABLE
1513 static nkf_char
1514 x0212_shift(nkf_char c)
1515 {
1516     nkf_char ret = c;
1517     c &= 0x7f;
1518     if (is_eucg3(ret)){
1519         if (0x75 <= c && c <= 0x7f){
1520             ret = c + (0x109 - 0x75);
1521         }
1522     }else{
1523         if (0x75 <= c && c <= 0x7f){
1524             ret = c + (0x113 - 0x75);
1525         }
1526     }
1527     return ret;
1528 }
1529
1530
1531 static nkf_char
1532 x0212_unshift(nkf_char c)
1533 {
1534     nkf_char ret = c;
1535     if (0x7f <= c && c <= 0x88){
1536         ret = c + (0x75 - 0x7f);
1537     }else if (0x89 <= c && c <= 0x92){
1538         ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
1539     }
1540     return ret;
1541 }
1542 #endif /* X0212_ENABLE */
1543
1544 static nkf_char
1545 e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
1546 {
1547     nkf_char ndx;
1548     if (is_eucg3(c2)){
1549         ndx = c2 & 0x7f;
1550         if (x0213_f){
1551             if((0x21 <= ndx && ndx <= 0x2F)){
1552                 if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3;
1553                 if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1554                 return 0;
1555             }else if(0x6E <= ndx && ndx <= 0x7E){
1556                 if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe;
1557                 if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1558                 return 0;
1559             }
1560             return 1;
1561         }
1562 #ifdef X0212_ENABLE
1563         else if(nkf_isgraph(ndx)){
1564             nkf_char val = 0;
1565             const unsigned short *ptr;
1566             ptr = x0212_shiftjis[ndx - 0x21];
1567             if (ptr){
1568                 val = ptr[(c1 & 0x7f) - 0x21];
1569             }
1570             if (val){
1571                 c2 = val >> 8;
1572                 c1 = val & 0xff;
1573                 if (p2) *p2 = c2;
1574                 if (p1) *p1 = c1;
1575                 return 0;
1576             }
1577             c2 = x0212_shift(c2);
1578         }
1579 #endif /* X0212_ENABLE */
1580     }
1581     if(0x7F < c2) return 1;
1582     if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
1583     if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1584     return 0;
1585 }
1586
1587 static nkf_char
1588 s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
1589 {
1590 #if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
1591     nkf_char val;
1592 #endif
1593     static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
1594     if (0xFC < c1) return 1;
1595 #ifdef SHIFTJIS_CP932
1596     if (!cp932inv_f && is_ibmext_in_sjis(c2)){
1597         val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
1598         if (val){
1599             c2 = val >> 8;
1600             c1 = val & 0xff;
1601         }
1602     }
1603     if (cp932inv_f
1604         && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
1605         val = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
1606         if (val){
1607             c2 = val >> 8;
1608             c1 = val & 0xff;
1609         }
1610     }
1611 #endif /* SHIFTJIS_CP932 */
1612 #ifdef X0212_ENABLE
1613     if (!x0213_f && is_ibmext_in_sjis(c2)){
1614         val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
1615         if (val){
1616             if (val > 0x7FFF){
1617                 c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f);
1618                 c1 = val & 0xff;
1619             }else{
1620                 c2 = val >> 8;
1621                 c1 = val & 0xff;
1622             }
1623             if (p2) *p2 = c2;
1624             if (p1) *p1 = c1;
1625             return 0;
1626         }
1627     }
1628 #endif
1629     if(c2 >= 0x80){
1630         if(x0213_f && c2 >= 0xF0){
1631             if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */
1632                 c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1];
1633             }else{ /* 78<=k<=94 */
1634                 c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B);
1635                 if (0x9E < c1) c2++;
1636             }
1637         }else{
1638 #define         SJ0162  0x00e1          /* 01 - 62 ku offset */
1639 #define         SJ6394  0x0161          /* 63 - 94 ku offset */
1640             c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394);
1641             if (0x9E < c1) c2++;
1642         }
1643         if (c1 < 0x9F)
1644             c1 = c1 - ((c1 > DEL) ? SP : 0x1F);
1645         else {
1646             c1 = c1 - 0x7E;
1647         }
1648     }
1649
1650 #ifdef X0212_ENABLE
1651     c2 = x0212_unshift(c2);
1652 #endif
1653     if (p2) *p2 = c2;
1654     if (p1) *p1 = c1;
1655     return 0;
1656 }
1657
1658 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
1659 static void
1660 nkf_unicode_to_utf8(nkf_char val, nkf_char *p1, nkf_char *p2, nkf_char *p3, nkf_char *p4)
1661 {
1662     val &= VALUE_MASK;
1663     if (val < 0x80){
1664         *p1 = val;
1665         *p2 = 0;
1666         *p3 = 0;
1667         *p4 = 0;
1668     }else if (val < 0x800){
1669         *p1 = 0xc0 | (val >> 6);
1670         *p2 = 0x80 | (val & 0x3f);
1671         *p3 = 0;
1672         *p4 = 0;
1673     } else if (nkf_char_unicode_bmp_p(val)) {
1674         *p1 = 0xe0 |  (val >> 12);
1675         *p2 = 0x80 | ((val >>  6) & 0x3f);
1676         *p3 = 0x80 | ( val        & 0x3f);
1677         *p4 = 0;
1678     } else if (nkf_char_unicode_value_p(val)) {
1679         *p1 = 0xf0 |  (val >> 18);
1680         *p2 = 0x80 | ((val >> 12) & 0x3f);
1681         *p3 = 0x80 | ((val >>  6) & 0x3f);
1682         *p4 = 0x80 | ( val        & 0x3f);
1683     } else {
1684         *p1 = 0;
1685         *p2 = 0;
1686         *p3 = 0;
1687         *p4 = 0;
1688     }
1689 }
1690
1691 static nkf_char
1692 nkf_utf8_to_unicode(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
1693 {
1694     nkf_char wc;
1695     if (c1 <= 0x7F) {
1696         /* single byte */
1697         wc = c1;
1698     }
1699     else if (c1 <= 0xC3) {
1700         /* trail byte or invalid */
1701         return -1;
1702     }
1703     else if (c1 <= 0xDF) {
1704         /* 2 bytes */
1705         wc  = (c1 & 0x1F) << 6;
1706         wc |= (c2 & 0x3F);
1707     }
1708     else if (c1 <= 0xEF) {
1709         /* 3 bytes */
1710         wc  = (c1 & 0x0F) << 12;
1711         wc |= (c2 & 0x3F) << 6;
1712         wc |= (c3 & 0x3F);
1713     }
1714     else if (c2 <= 0xF4) {
1715         /* 4 bytes */
1716         wc  = (c1 & 0x0F) << 18;
1717         wc |= (c2 & 0x3F) << 12;
1718         wc |= (c3 & 0x3F) << 6;
1719         wc |= (c4 & 0x3F);
1720     }
1721     else {
1722         return -1;
1723     }
1724     return wc;
1725 }
1726 #endif
1727
1728 #ifdef UTF8_INPUT_ENABLE
1729 static int
1730 unicode_to_jis_common2(nkf_char c1, nkf_char c0,
1731                        const unsigned short *const *pp, nkf_char psize,
1732                        nkf_char *p2, nkf_char *p1)
1733 {
1734     nkf_char c2;
1735     const unsigned short *p;
1736     unsigned short val;
1737
1738     if (pp == 0) return 1;
1739
1740     c1 -= 0x80;
1741     if (c1 < 0 || psize <= c1) return 1;
1742     p = pp[c1];
1743     if (p == 0)  return 1;
1744
1745     c0 -= 0x80;
1746     if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1;
1747     val = p[c0];
1748     if (val == 0) return 1;
1749     if (no_cp932ext_f && (
1750                           (val>>8) == 0x2D || /* NEC special characters */
1751                           val > NKF_INT32_C(0xF300) /* IBM extended characters */
1752                          )) return 1;
1753
1754     c2 = val >> 8;
1755     if (val > 0x7FFF){
1756         c2 &= 0x7f;
1757         c2 |= PREFIX_EUCG3;
1758     }
1759     if (c2 == SO) c2 = JIS_X_0201_1976_K;
1760     c1 = val & 0xFF;
1761     if (p2) *p2 = c2;
1762     if (p1) *p1 = c1;
1763     return 0;
1764 }
1765
1766 static int
1767 unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
1768 {
1769     const unsigned short *const *pp;
1770     const unsigned short *const *const *ppp;
1771     static const char no_best_fit_chars_table_C2[] =
1772     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1773         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1774         1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2,
1775         0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1};
1776     static const char no_best_fit_chars_table_C2_ms[] =
1777     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1778         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1779         1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,
1780         0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0};
1781     static const char no_best_fit_chars_table_932_C2[] =
1782     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1783         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1784         1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1785         0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0};
1786     static const char no_best_fit_chars_table_932_C3[] =
1787     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1788         1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1789         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1790         1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1};
1791     nkf_char ret = 0;
1792
1793     if(c2 < 0x80){
1794         *p2 = 0;
1795         *p1 = c2;
1796     }else if(c2 < 0xe0){
1797         if(no_best_fit_chars_f){
1798             if(ms_ucs_map_f == UCS_MAP_CP932){
1799                 switch(c2){
1800                 case 0xC2:
1801                     if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1;
1802                     break;
1803                 case 0xC3:
1804                     if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
1805                     break;
1806                 }
1807             }else if(!cp932inv_f){
1808                 switch(c2){
1809                 case 0xC2:
1810                     if(no_best_fit_chars_table_C2[c1&0x3F]) return 1;
1811                     break;
1812                 case 0xC3:
1813                     if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
1814                     break;
1815                 }
1816             }else if(ms_ucs_map_f == UCS_MAP_MS){
1817                 if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1;
1818             }else if(ms_ucs_map_f == UCS_MAP_CP10001){
1819                 switch(c2){
1820                 case 0xC2:
1821                     switch(c1){
1822                     case 0xA2:
1823                     case 0xA3:
1824                     case 0xA5:
1825                     case 0xA6:
1826                     case 0xAC:
1827                     case 0xAF:
1828                     case 0xB8:
1829                         return 1;
1830                     }
1831                     break;
1832                 }
1833             }
1834         }
1835         pp =
1836             ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 :
1837             ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms :
1838             ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_2bytes_mac :
1839             utf8_to_euc_2bytes;
1840         ret =  unicode_to_jis_common2(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
1841     }else if(c0 < 0xF0){
1842         if(no_best_fit_chars_f){
1843             if(ms_ucs_map_f == UCS_MAP_CP932){
1844                 if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1;
1845             }else if(ms_ucs_map_f == UCS_MAP_MS){
1846                 switch(c2){
1847                 case 0xE2:
1848                     switch(c1){
1849                     case 0x80:
1850                         if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1;
1851                         break;
1852                     case 0x88:
1853                         if(c0 == 0x92) return 1;
1854                         break;
1855                     }
1856                     break;
1857                 case 0xE3:
1858                     if(c1 == 0x80 || c0 == 0x9C) return 1;
1859                     break;
1860                 }
1861             }else if(ms_ucs_map_f == UCS_MAP_CP10001){
1862                 switch(c2){
1863                 case 0xE3:
1864                     switch(c1){
1865                     case 0x82:
1866                         if(c0 == 0x94) return 1;
1867                         break;
1868                     case 0x83:
1869                         if(c0 == 0xBB) return 1;
1870                         break;
1871                     }
1872                     break;
1873                 }
1874             }else{
1875                 switch(c2){
1876                 case 0xE2:
1877                     switch(c1){
1878                     case 0x80:
1879                         if(c0 == 0x95) return 1;
1880                         break;
1881                     case 0x88:
1882                         if(c0 == 0xA5) return 1;
1883                         break;
1884                     }
1885                     break;
1886                 case 0xEF:
1887                     switch(c1){
1888                     case 0xBC:
1889                         if(c0 == 0x8D) return 1;
1890                         break;
1891                     case 0xBD:
1892                         if(c0 == 0x9E && !cp932inv_f) return 1;
1893                         break;
1894                     case 0xBF:
1895                         if(0xA0 <= c0 && c0 <= 0xA5) return 1;
1896                         break;
1897                     }
1898                     break;
1899                 }
1900             }
1901         }
1902         ppp =
1903             ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 :
1904             ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms :
1905             ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_3bytes_mac :
1906             utf8_to_euc_3bytes;
1907         ret = unicode_to_jis_common2(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
1908     }else return -1;
1909 #ifdef SHIFTJIS_CP932
1910     if (!ret && !cp932inv_f && is_eucg3(*p2)) {
1911         nkf_char s2, s1;
1912         if (e2s_conv(*p2, *p1, &s2, &s1) == 0) {
1913             s2e_conv(s2, s1, p2, p1);
1914         }else{
1915             ret = 1;
1916         }
1917     }
1918 #endif
1919     return ret;
1920 }
1921
1922 #ifdef UTF8_OUTPUT_ENABLE
1923 static nkf_char
1924 e2w_conv(nkf_char c2, nkf_char c1)
1925 {
1926     const unsigned short *p;
1927
1928     if (c2 == JIS_X_0201_1976_K) {
1929         if (ms_ucs_map_f == UCS_MAP_CP10001) {
1930             switch (c1) {
1931             case 0x20:
1932                 return 0xA0;
1933             case 0x7D:
1934                 return 0xA9;
1935             }
1936         }
1937         p = euc_to_utf8_1byte;
1938 #ifdef X0212_ENABLE
1939     } else if (is_eucg3(c2)){
1940         if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){
1941             return 0xA6;
1942         }
1943         c2 = (c2&0x7f) - 0x21;
1944         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
1945             p = x0212_to_utf8_2bytes[c2];
1946         else
1947             return 0;
1948 #endif
1949     } else {
1950         c2 &= 0x7f;
1951         c2 = (c2&0x7f) - 0x21;
1952         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
1953             p =
1954                 ms_ucs_map_f == UCS_MAP_ASCII ? euc_to_utf8_2bytes[c2] :
1955                 ms_ucs_map_f == UCS_MAP_CP10001 ? euc_to_utf8_2bytes_mac[c2] :
1956                 euc_to_utf8_2bytes_ms[c2];
1957         else
1958             return 0;
1959     }
1960     if (!p) return 0;
1961     c1 = (c1 & 0x7f) - 0x21;
1962     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
1963         return p[c1];
1964     return 0;
1965 }
1966 #endif
1967
1968 static nkf_char
1969 w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
1970 {
1971     nkf_char ret = 0;
1972
1973     if (!c1){
1974         *p2 = 0;
1975         *p1 = c2;
1976     }else if (0xc0 <= c2 && c2 <= 0xef) {
1977         ret =  unicode_to_jis_common(c2, c1, c0, p2, p1);
1978 #ifdef NUMCHAR_OPTION
1979         if (ret > 0){
1980             if (p2) *p2 = 0;
1981             if (p1) *p1 = nkf_char_unicode_new(nkf_utf8_to_unicode(c2, c1, c0, 0));
1982             ret = 0;
1983         }
1984 #endif
1985     }
1986     return ret;
1987 }
1988
1989 #ifdef UTF8_INPUT_ENABLE
1990 static nkf_char
1991 w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
1992 {
1993     nkf_char c1, c2, c3, c4;
1994     nkf_char ret = 0;
1995     val &= VALUE_MASK;
1996     if (val < 0x80) {
1997         *p2 = 0;
1998         *p1 = val;
1999     }
2000     else if (nkf_char_unicode_bmp_p(val)){
2001         nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
2002         ret =  unicode_to_jis_common(c1, c2, c3, p2, p1);
2003         if (ret > 0){
2004             *p2 = 0;
2005             *p1 = nkf_char_unicode_new(val);
2006             ret = 0;
2007         }
2008     }
2009     else {
2010         *p2 = 0;
2011         *p1 = nkf_char_unicode_new(val);
2012     }
2013     return ret;
2014 }
2015 #endif
2016
2017 static nkf_char
2018 e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
2019 {
2020     if (c2 == JIS_X_0201_1976_K || c2 == SS2){
2021         if (iso2022jp_f && !x0201_f) {
2022             c2 = GETA1; c1 = GETA2;
2023         } else {
2024             c2 = JIS_X_0201_1976_K;
2025             c1 &= 0x7f;
2026         }
2027 #ifdef X0212_ENABLE
2028     }else if (c2 == 0x8f){
2029         if (c0 == 0){
2030             return -1;
2031         }
2032         if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) {
2033             /* encoding is eucJP-ms, so invert to Unicode Private User Area */
2034             c1 = nkf_char_unicode_new((c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC);
2035             c2 = 0;
2036         } else {
2037             c2 = (c2 << 8) | (c1 & 0x7f);
2038             c1 = c0 & 0x7f;
2039 #ifdef SHIFTJIS_CP932
2040             if (cp51932_f){
2041                 nkf_char s2, s1;
2042                 if (e2s_conv(c2, c1, &s2, &s1) == 0){
2043                     s2e_conv(s2, s1, &c2, &c1);
2044                     if (c2 < 0x100){
2045                         c1 &= 0x7f;
2046                         c2 &= 0x7f;
2047                     }
2048                 }
2049             }
2050 #endif /* SHIFTJIS_CP932 */
2051         }
2052 #endif /* X0212_ENABLE */
2053     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP || c2 == ISO_8859_1) {
2054         /* NOP */
2055     } else {
2056         if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) {
2057             /* encoding is eucJP-ms, so invert to Unicode Private User Area */
2058             c1 = nkf_char_unicode_new((c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000);
2059             c2 = 0;
2060         } else {
2061             c1 &= 0x7f;
2062             c2 &= 0x7f;
2063 #ifdef SHIFTJIS_CP932
2064             if (cp51932_f && 0x79 <= c2 && c2 <= 0x7c){
2065                 nkf_char s2, s1;
2066                 if (e2s_conv(c2, c1, &s2, &s1) == 0){
2067                     s2e_conv(s2, s1, &c2, &c1);
2068                     if (c2 < 0x100){
2069                         c1 &= 0x7f;
2070                         c2 &= 0x7f;
2071                     }
2072                 }
2073             }
2074 #endif /* SHIFTJIS_CP932 */
2075         }
2076     }
2077     (*oconv)(c2, c1);
2078     return 0;
2079 }
2080
2081 static nkf_char
2082 s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
2083 {
2084     if (c2 == JIS_X_0201_1976_K || (0xA1 <= c2 && c2 <= 0xDF)) {
2085         if (iso2022jp_f && !x0201_f) {
2086             c2 = GETA1; c1 = GETA2;
2087         } else {
2088             c1 &= 0x7f;
2089         }
2090     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) {
2091         /* NOP */
2092     } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) {
2093         /* CP932 UDC */
2094         if(c1 == 0x7F) return 0;
2095         c1 = nkf_char_unicode_new((c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000);
2096         c2 = 0;
2097     } else {
2098         nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
2099         if (ret) return ret;
2100     }
2101     (*oconv)(c2, c1);
2102     return 0;
2103 }
2104
2105 static nkf_char
2106 w_iconv(nkf_char c1, nkf_char c2, nkf_char c3)
2107 {
2108     nkf_char ret = 0, c4 = 0;
2109     static const char w_iconv_utf8_1st_byte[] =
2110     { /* 0xC0 - 0xFF */
2111         20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
2112         21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
2113         30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33,
2114         40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70};
2115
2116     if (c3 > 0xFF) {
2117         c4 = c3 & 0xFF;
2118         c3 >>= 8;
2119     }
2120
2121     if (c1 < 0 || 0xff < c1) {
2122     }else if (c1 == 0) { /* 0 : 1 byte*/
2123         c3 = 0;
2124     } else if ((c1 & 0xC0) == 0x80) { /* 0x80-0xbf : trail byte */
2125         return 0;
2126     } else{
2127         switch (w_iconv_utf8_1st_byte[c1 - 0xC0]) {
2128         case 21:
2129             if (c2 < 0x80 || 0xBF < c2) return 0;
2130             break;
2131         case 30:
2132             if (c3 == 0) return -1;
2133             if (c2 < 0xA0 || 0xBF < c2 || (c3 & 0xC0) != 0x80)
2134                 return 0;
2135             break;
2136         case 31:
2137         case 33:
2138             if (c3 == 0) return -1;
2139             if ((c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80)
2140                 return 0;
2141             break;
2142         case 32:
2143             if (c3 == 0) return -1;
2144             if (c2 < 0x80 || 0x9F < c2 || (c3 & 0xC0) != 0x80)
2145                 return 0;
2146             break;
2147         case 40:
2148             if (c3 == 0) return -2;
2149             if (c2 < 0x90 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2150                 return 0;
2151             break;
2152         case 41:
2153             if (c3 == 0) return -2;
2154             if (c2 < 0x80 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2155                 return 0;
2156             break;
2157         case 42:
2158             if (c3 == 0) return -2;
2159             if (c2 < 0x80 || 0x8F < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2160                 return 0;
2161             break;
2162         default:
2163             return 0;
2164             break;
2165         }
2166     }
2167     if (c1 == 0 || c1 == EOF){
2168     } else if ((c1 & 0xf8) == 0xf0) { /* 4 bytes */
2169         c2 = nkf_char_unicode_new(nkf_utf8_to_unicode(c1, c2, c3, c4));
2170         c1 = 0;
2171     } else {
2172         ret = w2e_conv(c1, c2, c3, &c1, &c2);
2173     }
2174     if (ret == 0){
2175         (*oconv)(c1, c2);
2176     }
2177     return ret;
2178 }
2179
2180 #define NKF_ICONV_INVALID_CODE_RANGE -13
2181 static size_t
2182 unicode_iconv(nkf_char wc)
2183 {
2184     nkf_char c1, c2;
2185     int ret = 0;
2186
2187     if (wc < 0x80) {
2188         c2 = 0;
2189         c1 = wc;
2190     }else if ((wc>>11) == 27) {
2191         /* unpaired surrogate */
2192         return NKF_ICONV_INVALID_CODE_RANGE;
2193     }else if (wc < 0xFFFF) {
2194         ret = w16e_conv(wc, &c2, &c1);
2195         if (ret) return ret;
2196     }else if (wc < 0x10FFFF) {
2197         c2 = 0;
2198         c1 = nkf_char_unicode_new(wc);
2199     } else {
2200         return NKF_ICONV_INVALID_CODE_RANGE;
2201     }
2202     (*oconv)(c2, c1);
2203     return 0;
2204 }
2205
2206 #define NKF_ICONV_NEED_ONE_MORE_BYTE (size_t)-1
2207 #define NKF_ICONV_NEED_TWO_MORE_BYTES (size_t)-2
2208 #define UTF16_TO_UTF32(lead, trail) (((lead) << 10) + (trail) - NKF_INT32_C(0x35FDC00))
2209 static size_t
2210 nkf_iconv_utf_16(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
2211 {
2212     nkf_char wc;
2213
2214     if (c1 == EOF) {
2215         (*oconv)(EOF, 0);
2216         return 0;
2217     }
2218
2219     if (input_endian == ENDIAN_BIG) {
2220         if (0xD8 <= c1 && c1 <= 0xDB) {
2221             if (0xDC <= c3 && c3 <= 0xDF) {
2222                 wc = UTF16_TO_UTF32(c1 << 8 | c2, c3 << 8 | c4);
2223             } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
2224         } else {
2225             wc = c1 << 8 | c2;
2226         }
2227     } else {
2228         if (0xD8 <= c2 && c2 <= 0xDB) {
2229             if (0xDC <= c4 && c4 <= 0xDF) {
2230                 wc = UTF16_TO_UTF32(c2 << 8 | c1, c4 << 8 | c3);
2231             } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
2232         } else {
2233             wc = c2 << 8 | c1;
2234         }
2235     }
2236
2237     return (*unicode_iconv)(wc);
2238 }
2239
2240 static nkf_char
2241 w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
2242 {
2243     (*oconv)(c2, c1);
2244     return 16; /* different from w_iconv32 */
2245 }
2246
2247 static nkf_char
2248 w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
2249 {
2250     (*oconv)(c2, c1);
2251     return 32; /* different from w_iconv16 */
2252 }
2253
2254 static size_t
2255 nkf_iconv_utf_32(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
2256 {
2257     nkf_char wc;
2258
2259     if (c1 == EOF) {
2260         (*oconv)(EOF, 0);
2261         return 0;
2262     }
2263
2264     switch(input_endian){
2265     case ENDIAN_BIG:
2266         wc = c2 << 16 | c3 << 8 | c4;
2267         break;
2268     case ENDIAN_LITTLE:
2269         wc = c3 << 16 | c2 << 8 | c1;
2270         break;
2271     case ENDIAN_2143:
2272         wc = c1 << 16 | c4 << 8 | c3;
2273         break;
2274     case ENDIAN_3412:
2275         wc = c4 << 16 | c1 << 8 | c2;
2276         break;
2277     default:
2278         return NKF_ICONV_INVALID_CODE_RANGE;
2279     }
2280
2281     return (*unicode_iconv)(wc);
2282 }
2283 #endif
2284
2285 #define output_ascii_escape_sequence(mode) do { \
2286             if (output_mode != ASCII && output_mode != ISO_8859_1) { \
2287                     (*o_putc)(ESC); \
2288                     (*o_putc)('('); \
2289                     (*o_putc)(ascii_intro); \
2290                     output_mode = mode; \
2291             } \
2292     } while (0)
2293
2294 static void
2295 output_escape_sequence(int mode)
2296 {
2297     if (output_mode == mode)
2298         return;
2299     switch(mode) {
2300     case ISO_8859_1:
2301         (*o_putc)(ESC);
2302         (*o_putc)('.');
2303         (*o_putc)('A');
2304         break;
2305     case JIS_X_0201_1976_K:
2306         (*o_putc)(ESC);
2307         (*o_putc)('(');
2308         (*o_putc)('I');
2309         break;
2310     case JIS_X_0208:
2311         (*o_putc)(ESC);
2312         (*o_putc)('$');
2313         (*o_putc)(kanji_intro);
2314         break;
2315     case JIS_X_0212:
2316         (*o_putc)(ESC);
2317         (*o_putc)('$');
2318         (*o_putc)('(');
2319         (*o_putc)('D');
2320         break;
2321     case JIS_X_0213_1:
2322         (*o_putc)(ESC);
2323         (*o_putc)('$');
2324         (*o_putc)('(');
2325         (*o_putc)('Q');
2326         break;
2327     case JIS_X_0213_2:
2328         (*o_putc)(ESC);
2329         (*o_putc)('$');
2330         (*o_putc)('(');
2331         (*o_putc)('P');
2332         break;
2333     }
2334     output_mode = mode;
2335 }
2336
2337 static void
2338 j_oconv(nkf_char c2, nkf_char c1)
2339 {
2340 #ifdef NUMCHAR_OPTION
2341     if (c2 == 0 && nkf_char_unicode_p(c1)){
2342         w16e_conv(c1, &c2, &c1);
2343         if (c2 == 0 && nkf_char_unicode_p(c1)){
2344             c2 = c1 & VALUE_MASK;
2345             if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) {
2346                 /* CP5022x UDC */
2347                 c1 &= 0xFFF;
2348                 c2 = 0x7F + c1 / 94;
2349                 c1 = 0x21 + c1 % 94;
2350             } else {
2351                 if (encode_fallback) (*encode_fallback)(c1);
2352                 return;
2353             }
2354         }
2355     }
2356 #endif
2357     if (c2 == 0) {
2358         output_ascii_escape_sequence(ASCII);
2359         (*o_putc)(c1);
2360     }
2361     else if (c2 == EOF) {
2362         output_ascii_escape_sequence(ASCII);
2363         (*o_putc)(EOF);
2364     }
2365     else if (c2 == ISO_8859_1) {
2366         output_ascii_escape_sequence(ISO_8859_1);
2367         (*o_putc)(c1|0x80);
2368     }
2369     else if (c2 == JIS_X_0201_1976_K) {
2370         output_escape_sequence(JIS_X_0201_1976_K);
2371         (*o_putc)(c1);
2372 #ifdef X0212_ENABLE
2373     } else if (is_eucg3(c2)){
2374         output_escape_sequence(x0213_f ? JIS_X_0213_2 : JIS_X_0212);
2375         (*o_putc)(c2 & 0x7f);
2376         (*o_putc)(c1);
2377 #endif
2378     } else {
2379         if(ms_ucs_map_f
2380            ? c2<0x20 || 0x92<c2 || c1<0x20 || 0x7e<c1
2381            : c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
2382         output_escape_sequence(x0213_f ? JIS_X_0213_1 : JIS_X_0208);
2383         (*o_putc)(c2);
2384         (*o_putc)(c1);
2385     }
2386 }
2387
2388 static void
2389 e_oconv(nkf_char c2, nkf_char c1)
2390 {
2391     if (c2 == 0 && nkf_char_unicode_p(c1)){
2392         w16e_conv(c1, &c2, &c1);
2393         if (c2 == 0 && nkf_char_unicode_p(c1)){
2394             c2 = c1 & VALUE_MASK;
2395             if (x0212_f && 0xE000 <= c2 && c2 <= 0xE757) {
2396                 /* eucJP-ms UDC */
2397                 c1 &= 0xFFF;
2398                 c2 = c1 / 94;
2399                 c2 += c2 < 10 ? 0x75 : 0x8FEB;
2400                 c1 = 0x21 + c1 % 94;
2401                 if (is_eucg3(c2)){
2402                     (*o_putc)(0x8f);
2403                     (*o_putc)((c2 & 0x7f) | 0x080);
2404                     (*o_putc)(c1 | 0x080);
2405                 }else{
2406                     (*o_putc)((c2 & 0x7f) | 0x080);
2407                     (*o_putc)(c1 | 0x080);
2408                 }
2409                 return;
2410             } else {
2411                 if (encode_fallback) (*encode_fallback)(c1);
2412                 return;
2413             }
2414         }
2415     }
2416
2417     if (c2 == EOF) {
2418         (*o_putc)(EOF);
2419     } else if (c2 == 0) {
2420         output_mode = ASCII;
2421         (*o_putc)(c1);
2422     } else if (c2 == JIS_X_0201_1976_K) {
2423         output_mode = EUC_JP;
2424         (*o_putc)(SS2); (*o_putc)(c1|0x80);
2425     } else if (c2 == ISO_8859_1) {
2426         output_mode = ISO_8859_1;
2427         (*o_putc)(c1 | 0x080);
2428 #ifdef X0212_ENABLE
2429     } else if (is_eucg3(c2)){
2430         output_mode = EUC_JP;
2431 #ifdef SHIFTJIS_CP932
2432         if (!cp932inv_f){
2433             nkf_char s2, s1;
2434             if (e2s_conv(c2, c1, &s2, &s1) == 0){
2435                 s2e_conv(s2, s1, &c2, &c1);
2436             }
2437         }
2438 #endif
2439         if (c2 == 0) {
2440             output_mode = ASCII;
2441             (*o_putc)(c1);
2442         }else if (is_eucg3(c2)){
2443             if (x0212_f){
2444                 (*o_putc)(0x8f);
2445                 (*o_putc)((c2 & 0x7f) | 0x080);
2446                 (*o_putc)(c1 | 0x080);
2447             }
2448         }else{
2449             (*o_putc)((c2 & 0x7f) | 0x080);
2450             (*o_putc)(c1 | 0x080);
2451         }
2452 #endif
2453     } else {
2454         if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
2455             set_iconv(FALSE, 0);
2456             return; /* too late to rescue this char */
2457         }
2458         output_mode = EUC_JP;
2459         (*o_putc)(c2 | 0x080);
2460         (*o_putc)(c1 | 0x080);
2461     }
2462 }
2463
2464 static void
2465 s_oconv(nkf_char c2, nkf_char c1)
2466 {
2467 #ifdef NUMCHAR_OPTION
2468     if (c2 == 0 && nkf_char_unicode_p(c1)){
2469         w16e_conv(c1, &c2, &c1);
2470         if (c2 == 0 && nkf_char_unicode_p(c1)){
2471             c2 = c1 & VALUE_MASK;
2472             if (!x0213_f && 0xE000 <= c2 && c2 <= 0xE757) {
2473                 /* CP932 UDC */
2474                 c1 &= 0xFFF;
2475                 c2 = c1 / 188 + (cp932inv_f ? 0xF0 : 0xEB);
2476                 c1 = c1 % 188;
2477                 c1 += 0x40 + (c1 > 0x3e);
2478                 (*o_putc)(c2);
2479                 (*o_putc)(c1);
2480                 return;
2481             } else {
2482                 if(encode_fallback)(*encode_fallback)(c1);
2483                 return;
2484             }
2485         }
2486     }
2487 #endif
2488     if (c2 == EOF) {
2489         (*o_putc)(EOF);
2490         return;
2491     } else if (c2 == 0) {
2492         output_mode = ASCII;
2493         (*o_putc)(c1);
2494     } else if (c2 == JIS_X_0201_1976_K) {
2495         output_mode = SHIFT_JIS;
2496         (*o_putc)(c1|0x80);
2497     } else if (c2 == ISO_8859_1) {
2498         output_mode = ISO_8859_1;
2499         (*o_putc)(c1 | 0x080);
2500 #ifdef X0212_ENABLE
2501     } else if (is_eucg3(c2)){
2502         output_mode = SHIFT_JIS;
2503         if (e2s_conv(c2, c1, &c2, &c1) == 0){
2504             (*o_putc)(c2);
2505             (*o_putc)(c1);
2506         }
2507 #endif
2508     } else {
2509         if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
2510             set_iconv(FALSE, 0);
2511             return; /* too late to rescue this char */
2512         }
2513         output_mode = SHIFT_JIS;
2514         e2s_conv(c2, c1, &c2, &c1);
2515
2516 #ifdef SHIFTJIS_CP932
2517         if (cp932inv_f
2518             && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
2519             nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
2520             if (c){
2521                 c2 = c >> 8;
2522                 c1 = c & 0xff;
2523             }
2524         }
2525 #endif /* SHIFTJIS_CP932 */
2526
2527         (*o_putc)(c2);
2528         if (prefix_table[(unsigned char)c1]){
2529             (*o_putc)(prefix_table[(unsigned char)c1]);
2530         }
2531         (*o_putc)(c1);
2532     }
2533 }
2534
2535 #ifdef UTF8_OUTPUT_ENABLE
2536 static void
2537 w_oconv(nkf_char c2, nkf_char c1)
2538 {
2539     nkf_char c3, c4;
2540     nkf_char val;
2541
2542     if (output_bom_f) {
2543         output_bom_f = FALSE;
2544         (*o_putc)('\357');
2545         (*o_putc)('\273');
2546         (*o_putc)('\277');
2547     }
2548
2549     if (c2 == EOF) {
2550         (*o_putc)(EOF);
2551         return;
2552     }
2553
2554     if (c2 == 0 && nkf_char_unicode_p(c1)){
2555         val = c1 & VALUE_MASK;
2556         nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
2557         (*o_putc)(c1);
2558         if (c2) (*o_putc)(c2);
2559         if (c3) (*o_putc)(c3);
2560         if (c4) (*o_putc)(c4);
2561         return;
2562     }
2563
2564     if (c2 == 0) {
2565         (*o_putc)(c1);
2566     } else {
2567         val = e2w_conv(c2, c1);
2568         if (val){
2569             nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
2570             (*o_putc)(c1);
2571             if (c2) (*o_putc)(c2);
2572             if (c3) (*o_putc)(c3);
2573             if (c4) (*o_putc)(c4);
2574         }
2575     }
2576 }
2577
2578 static void
2579 w_oconv16(nkf_char c2, nkf_char c1)
2580 {
2581     if (output_bom_f) {
2582         output_bom_f = FALSE;
2583         if (output_endian == ENDIAN_LITTLE){
2584             (*o_putc)(0xFF);
2585             (*o_putc)(0xFE);
2586         }else{
2587             (*o_putc)(0xFE);
2588             (*o_putc)(0xFF);
2589         }
2590     }
2591
2592     if (c2 == EOF) {
2593         (*o_putc)(EOF);
2594         return;
2595     }
2596
2597     if (c2 == 0 && nkf_char_unicode_p(c1)) {
2598         if (nkf_char_unicode_bmp_p(c1)) {
2599             c2 = (c1 >> 8) & 0xff;
2600             c1 &= 0xff;
2601         } else {
2602             c1 &= VALUE_MASK;
2603             if (c1 <= UNICODE_MAX) {
2604                 c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0);   /* high surrogate */
2605                 c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
2606                 if (output_endian == ENDIAN_LITTLE){
2607                     (*o_putc)(c2 & 0xff);
2608                     (*o_putc)((c2 >> 8) & 0xff);
2609                     (*o_putc)(c1 & 0xff);
2610                     (*o_putc)((c1 >> 8) & 0xff);
2611                 }else{
2612                     (*o_putc)((c2 >> 8) & 0xff);
2613                     (*o_putc)(c2 & 0xff);
2614                     (*o_putc)((c1 >> 8) & 0xff);
2615                     (*o_putc)(c1 & 0xff);
2616                 }
2617             }
2618             return;
2619         }
2620     } else if (c2) {
2621         nkf_char val = e2w_conv(c2, c1);
2622         c2 = (val >> 8) & 0xff;
2623         c1 = val & 0xff;
2624         if (!val) return;
2625     }
2626
2627     if (output_endian == ENDIAN_LITTLE){
2628         (*o_putc)(c1);
2629         (*o_putc)(c2);
2630     }else{
2631         (*o_putc)(c2);
2632         (*o_putc)(c1);
2633     }
2634 }
2635
2636 static void
2637 w_oconv32(nkf_char c2, nkf_char c1)
2638 {
2639     if (output_bom_f) {
2640         output_bom_f = FALSE;
2641         if (output_endian == ENDIAN_LITTLE){
2642             (*o_putc)(0xFF);
2643             (*o_putc)(0xFE);
2644             (*o_putc)(0);
2645             (*o_putc)(0);
2646         }else{
2647             (*o_putc)(0);
2648             (*o_putc)(0);
2649             (*o_putc)(0xFE);
2650             (*o_putc)(0xFF);
2651         }
2652     }
2653
2654     if (c2 == EOF) {
2655         (*o_putc)(EOF);
2656         return;
2657     }
2658
2659     if (c2 == ISO_8859_1) {
2660         c1 |= 0x80;
2661     } else if (c2 == 0 && nkf_char_unicode_p(c1)) {
2662         c1 &= VALUE_MASK;
2663     } else if (c2) {
2664         c1 = e2w_conv(c2, c1);
2665         if (!c1) return;
2666     }
2667     if (output_endian == ENDIAN_LITTLE){
2668         (*o_putc)( c1        & 0xFF);
2669         (*o_putc)((c1 >>  8) & 0xFF);
2670         (*o_putc)((c1 >> 16) & 0xFF);
2671         (*o_putc)(0);
2672     }else{
2673         (*o_putc)(0);
2674         (*o_putc)((c1 >> 16) & 0xFF);
2675         (*o_putc)((c1 >>  8) & 0xFF);
2676         (*o_putc)( c1        & 0xFF);
2677     }
2678 }
2679 #endif
2680
2681 #define SCORE_L2       (1)                   /* Kanji Level 2 */
2682 #define SCORE_KANA     (SCORE_L2 << 1)       /* Halfwidth Katakana */
2683 #define SCORE_DEPEND   (SCORE_KANA << 1)     /* MD Characters */
2684 #define SCORE_CP932    (SCORE_DEPEND << 1)   /* IBM extended characters */
2685 #define SCORE_X0212    (SCORE_CP932 << 1)    /* JIS X 0212 */
2686 #define SCORE_NO_EXIST (SCORE_X0212 << 1)    /* Undefined Characters */
2687 #define SCORE_iMIME    (SCORE_NO_EXIST << 1) /* MIME selected */
2688 #define SCORE_ERROR    (SCORE_iMIME << 1) /* Error */
2689
2690 #define SCORE_INIT (SCORE_iMIME)
2691
2692 static const nkf_char score_table_A0[] = {
2693     0, 0, 0, 0,
2694     0, 0, 0, 0,
2695     0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
2696     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
2697 };
2698
2699 static const nkf_char score_table_F0[] = {
2700     SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
2701     SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
2702     SCORE_DEPEND, SCORE_DEPEND, SCORE_CP932, SCORE_CP932,
2703     SCORE_CP932, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
2704 };
2705
2706 static void
2707 set_code_score(struct input_code *ptr, nkf_char score)
2708 {
2709     if (ptr){
2710         ptr->score |= score;
2711     }
2712 }
2713
2714 static void
2715 clr_code_score(struct input_code *ptr, nkf_char score)
2716 {
2717     if (ptr){
2718         ptr->score &= ~score;
2719     }
2720 }
2721
2722 static void
2723 code_score(struct input_code *ptr)
2724 {
2725     nkf_char c2 = ptr->buf[0];
2726 #ifdef UTF8_OUTPUT_ENABLE
2727     nkf_char c1 = ptr->buf[1];
2728 #endif
2729     if (c2 < 0){
2730         set_code_score(ptr, SCORE_ERROR);
2731     }else if (c2 == SS2){
2732         set_code_score(ptr, SCORE_KANA);
2733     }else if (c2 == 0x8f){
2734         set_code_score(ptr, SCORE_X0212);
2735 #ifdef UTF8_OUTPUT_ENABLE
2736     }else if (!e2w_conv(c2, c1)){
2737         set_code_score(ptr, SCORE_NO_EXIST);
2738 #endif
2739     }else if ((c2 & 0x70) == 0x20){
2740         set_code_score(ptr, score_table_A0[c2 & 0x0f]);
2741     }else if ((c2 & 0x70) == 0x70){
2742         set_code_score(ptr, score_table_F0[c2 & 0x0f]);
2743     }else if ((c2 & 0x70) >= 0x50){
2744         set_code_score(ptr, SCORE_L2);
2745     }
2746 }
2747
2748 static void
2749 status_disable(struct input_code *ptr)
2750 {
2751     ptr->stat = -1;
2752     ptr->buf[0] = -1;
2753     code_score(ptr);
2754     if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
2755 }
2756
2757 static void
2758 status_push_ch(struct input_code *ptr, nkf_char c)
2759 {
2760     ptr->buf[ptr->index++] = c;
2761 }
2762
2763 static void
2764 status_clear(struct input_code *ptr)
2765 {
2766     ptr->stat = 0;
2767     ptr->index = 0;
2768 }
2769
2770 static void
2771 status_reset(struct input_code *ptr)
2772 {
2773     status_clear(ptr);
2774     ptr->score = SCORE_INIT;
2775 }
2776
2777 static void
2778 status_reinit(struct input_code *ptr)
2779 {
2780     status_reset(ptr);
2781     ptr->_file_stat = 0;
2782 }
2783
2784 static void
2785 status_check(struct input_code *ptr, nkf_char c)
2786 {
2787     if (c <= DEL && estab_f){
2788         status_reset(ptr);
2789     }
2790 }
2791
2792 static void
2793 s_status(struct input_code *ptr, nkf_char c)
2794 {
2795     switch(ptr->stat){
2796     case -1:
2797         status_check(ptr, c);
2798         break;
2799     case 0:
2800         if (c <= DEL){
2801             break;
2802         }else if (nkf_char_unicode_p(c)){
2803             break;
2804         }else if (0xa1 <= c && c <= 0xdf){
2805             status_push_ch(ptr, SS2);
2806             status_push_ch(ptr, c);
2807             code_score(ptr);
2808             status_clear(ptr);
2809         }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xea)){
2810             ptr->stat = 1;
2811             status_push_ch(ptr, c);
2812         }else if (0xed <= c && c <= 0xee){
2813             ptr->stat = 3;
2814             status_push_ch(ptr, c);
2815 #ifdef SHIFTJIS_CP932
2816         }else if (is_ibmext_in_sjis(c)){
2817             ptr->stat = 2;
2818             status_push_ch(ptr, c);
2819 #endif /* SHIFTJIS_CP932 */
2820 #ifdef X0212_ENABLE
2821         }else if (0xf0 <= c && c <= 0xfc){
2822             ptr->stat = 1;
2823             status_push_ch(ptr, c);
2824 #endif /* X0212_ENABLE */
2825         }else{
2826             status_disable(ptr);
2827         }
2828         break;
2829     case 1:
2830         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
2831             status_push_ch(ptr, c);
2832             s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
2833             code_score(ptr);
2834             status_clear(ptr);
2835         }else{
2836             status_disable(ptr);
2837         }
2838         break;
2839     case 2:
2840 #ifdef SHIFTJIS_CP932
2841         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)) {
2842             status_push_ch(ptr, c);
2843             if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0) {
2844                 set_code_score(ptr, SCORE_CP932);
2845                 status_clear(ptr);
2846                 break;
2847             }
2848         }
2849 #endif /* SHIFTJIS_CP932 */
2850         status_disable(ptr);
2851         break;
2852     case 3:
2853         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
2854             status_push_ch(ptr, c);
2855             s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
2856             set_code_score(ptr, SCORE_CP932);
2857             status_clear(ptr);
2858         }else{
2859             status_disable(ptr);
2860         }
2861         break;
2862     }
2863 }
2864
2865 static void
2866 e_status(struct input_code *ptr, nkf_char c)
2867 {
2868     switch (ptr->stat){
2869     case -1:
2870         status_check(ptr, c);
2871         break;
2872     case 0:
2873         if (c <= DEL){
2874             break;
2875         }else if (nkf_char_unicode_p(c)){
2876             break;
2877         }else if (SS2 == c || (0xa1 <= c && c <= 0xfe)){
2878             ptr->stat = 1;
2879             status_push_ch(ptr, c);
2880 #ifdef X0212_ENABLE
2881         }else if (0x8f == c){
2882             ptr->stat = 2;
2883             status_push_ch(ptr, c);
2884 #endif /* X0212_ENABLE */
2885         }else{
2886             status_disable(ptr);
2887         }
2888         break;
2889     case 1:
2890         if (0xa1 <= c && c <= 0xfe){
2891             status_push_ch(ptr, c);
2892             code_score(ptr);
2893             status_clear(ptr);
2894         }else{
2895             status_disable(ptr);
2896         }
2897         break;
2898 #ifdef X0212_ENABLE
2899     case 2:
2900         if (0xa1 <= c && c <= 0xfe){
2901             ptr->stat = 1;
2902             status_push_ch(ptr, c);
2903         }else{
2904             status_disable(ptr);
2905         }
2906 #endif /* X0212_ENABLE */
2907     }
2908 }
2909
2910 #ifdef UTF8_INPUT_ENABLE
2911 static void
2912 w_status(struct input_code *ptr, nkf_char c)
2913 {
2914     switch (ptr->stat){
2915     case -1:
2916         status_check(ptr, c);
2917         break;
2918     case 0:
2919         if (c <= DEL){
2920             break;
2921         }else if (nkf_char_unicode_p(c)){
2922             break;
2923         }else if (0xc0 <= c && c <= 0xdf){
2924             ptr->stat = 1;
2925             status_push_ch(ptr, c);
2926         }else if (0xe0 <= c && c <= 0xef){
2927             ptr->stat = 2;
2928             status_push_ch(ptr, c);
2929         }else if (0xf0 <= c && c <= 0xf4){
2930             ptr->stat = 3;
2931             status_push_ch(ptr, c);
2932         }else{
2933             status_disable(ptr);
2934         }
2935         break;
2936     case 1:
2937     case 2:
2938         if (0x80 <= c && c <= 0xbf){
2939             status_push_ch(ptr, c);
2940             if (ptr->index > ptr->stat){
2941                 int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
2942                            && ptr->buf[2] == 0xbf);
2943                 w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
2944                          &ptr->buf[0], &ptr->buf[1]);
2945                 if (!bom){
2946                     code_score(ptr);
2947                 }
2948                 status_clear(ptr);
2949             }
2950         }else{
2951             status_disable(ptr);
2952         }
2953         break;
2954     case 3:
2955         if (0x80 <= c && c <= 0xbf){
2956             if (ptr->index < ptr->stat){
2957                 status_push_ch(ptr, c);
2958             } else {
2959                 status_clear(ptr);
2960             }
2961         }else{
2962             status_disable(ptr);
2963         }
2964         break;
2965     }
2966 }
2967 #endif
2968
2969 static void
2970 code_status(nkf_char c)
2971 {
2972     int action_flag = 1;
2973     struct input_code *result = 0;
2974     struct input_code *p = input_code_list;
2975     while (p->name){
2976         if (!p->status_func) {
2977             ++p;
2978             continue;
2979         }
2980         if (!p->status_func)
2981             continue;
2982         (p->status_func)(p, c);
2983         if (p->stat > 0){
2984             action_flag = 0;
2985         }else if(p->stat == 0){
2986             if (result){
2987                 action_flag = 0;
2988             }else{
2989                 result = p;
2990             }
2991         }
2992         ++p;
2993     }
2994
2995     if (action_flag){
2996         if (result && !estab_f){
2997             set_iconv(TRUE, result->iconv_func);
2998         }else if (c <= DEL){
2999             struct input_code *ptr = input_code_list;
3000             while (ptr->name){
3001                 status_reset(ptr);
3002                 ++ptr;
3003             }
3004         }
3005     }
3006 }
3007
3008 typedef struct {
3009     nkf_buf_t *std_gc_buf;
3010     nkf_char broken_state;
3011     nkf_buf_t *broken_buf;
3012     nkf_char mimeout_state;
3013     nkf_buf_t *nfc_buf;
3014 } nkf_state_t;
3015
3016 static nkf_state_t *nkf_state = NULL;
3017
3018 #define STD_GC_BUFSIZE (256)
3019
3020 static void
3021 nkf_state_init(void)
3022 {
3023     if (nkf_state) {
3024         nkf_buf_clear(nkf_state->std_gc_buf);
3025         nkf_buf_clear(nkf_state->broken_buf);
3026         nkf_buf_clear(nkf_state->nfc_buf);
3027     }
3028     else {
3029         nkf_state = nkf_xmalloc(sizeof(nkf_state_t));
3030         nkf_state->std_gc_buf = nkf_buf_new(STD_GC_BUFSIZE);
3031         nkf_state->broken_buf = nkf_buf_new(3);
3032         nkf_state->nfc_buf = nkf_buf_new(9);
3033     }
3034     nkf_state->broken_state = 0;
3035     nkf_state->mimeout_state = 0;
3036 }
3037
3038 #ifndef WIN32DLL
3039 static nkf_char
3040 std_getc(FILE *f)
3041 {
3042     if (!nkf_buf_empty_p(nkf_state->std_gc_buf)){
3043         return nkf_buf_pop(nkf_state->std_gc_buf);
3044     }
3045     return getc(f);
3046 }
3047 #endif /*WIN32DLL*/
3048
3049 static nkf_char
3050 std_ungetc(nkf_char c, FILE *f)
3051 {
3052     nkf_buf_push(nkf_state->std_gc_buf, c);
3053     return c;
3054 }
3055
3056 #ifndef WIN32DLL
3057 static void
3058 std_putc(nkf_char c)
3059 {
3060     if(c!=EOF)
3061         putchar(c);
3062 }
3063 #endif /*WIN32DLL*/
3064
3065 static nkf_char   hold_buf[HOLD_SIZE*2];
3066 static int             hold_count = 0;
3067 static nkf_char
3068 push_hold_buf(nkf_char c2)
3069 {
3070     if (hold_count >= HOLD_SIZE*2)
3071         return (EOF);
3072     hold_buf[hold_count++] = c2;
3073     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
3074 }
3075
3076 static int
3077 h_conv(FILE *f, nkf_char c1, nkf_char c2)
3078 {
3079     int ret;
3080     int hold_index;
3081     nkf_char c3, c4;
3082
3083     /** it must NOT be in the kanji shifte sequence      */
3084     /** it must NOT be written in JIS7                   */
3085     /** and it must be after 2 byte 8bit code            */
3086
3087     hold_count = 0;
3088     push_hold_buf(c1);
3089     push_hold_buf(c2);
3090
3091     while ((c2 = (*i_getc)(f)) != EOF) {
3092         if (c2 == ESC){
3093             (*i_ungetc)(c2,f);
3094             break;
3095         }
3096         code_status(c2);
3097         if (push_hold_buf(c2) == EOF || estab_f) {
3098             break;
3099         }
3100     }
3101
3102     if (!estab_f) {
3103         struct input_code *p = input_code_list;
3104         struct input_code *result = p;
3105         if (c2 == EOF) {
3106             code_status(c2);
3107         }
3108         while (p->name) {
3109             if (p->status_func && p->score < result->score) {
3110                 result = p;
3111             }
3112             p++;
3113         }
3114         set_iconv(TRUE, result->iconv_func);
3115     }
3116
3117
3118     /** now,
3119      ** 1) EOF is detected, or
3120      ** 2) Code is established, or
3121      ** 3) Buffer is FULL (but last word is pushed)
3122      **
3123      ** in 1) and 3) cases, we continue to use
3124      ** Kanji codes by oconv and leave estab_f unchanged.
3125      **/
3126
3127     ret = c2;
3128     hold_index = 0;
3129     while (hold_index < hold_count){
3130         c1 = hold_buf[hold_index++];
3131         if (nkf_char_unicode_p(c1)) {
3132             (*oconv)(0, c1);
3133             continue;
3134         }
3135         else if (c1 <= DEL){
3136             (*iconv)(0, c1, 0);
3137             continue;
3138         }else if (iconv == s_iconv && 0xa1 <= c1 && c1 <= 0xdf){
3139             (*iconv)(JIS_X_0201_1976_K, c1, 0);
3140             continue;
3141         }
3142         if (hold_index < hold_count){
3143             c2 = hold_buf[hold_index++];
3144         }else{
3145             c2 = (*i_getc)(f);
3146             if (c2 == EOF){
3147                 c4 = EOF;
3148                 break;
3149             }
3150             code_status(c2);
3151         }
3152         c3 = 0;
3153         switch ((*iconv)(c1, c2, 0)) {  /* can be EUC/SJIS/UTF-8 */
3154         case -2:
3155             /* 4 bytes UTF-8 */
3156             if (hold_index < hold_count){
3157                 c3 = hold_buf[hold_index++];
3158             } else if ((c3 = (*i_getc)(f)) == EOF) {
3159                 ret = EOF;
3160                 break;
3161             }
3162             code_status(c3);
3163             if (hold_index < hold_count){
3164                 c4 = hold_buf[hold_index++];
3165             } else if ((c4 = (*i_getc)(f)) == EOF) {
3166                 c3 = ret = EOF;
3167                 break;
3168             }
3169             code_status(c4);
3170             (*iconv)(c1, c2, (c3<<8)|c4);
3171             break;
3172         case -1:
3173             /* 3 bytes EUC or UTF-8 */
3174             if (hold_index < hold_count){
3175                 c3 = hold_buf[hold_index++];
3176             } else if ((c3 = (*i_getc)(f)) == EOF) {
3177                 ret = EOF;
3178                 break;
3179             } else {
3180                 code_status(c3);
3181             }
3182             (*iconv)(c1, c2, c3);
3183             break;
3184         }
3185         if (c3 == EOF) break;
3186     }
3187     return ret;
3188 }
3189
3190 /*
3191  * Check and Ignore BOM
3192  */
3193 static void
3194 check_bom(FILE *f)
3195 {
3196     int c2;
3197     switch(c2 = (*i_getc)(f)){
3198     case 0x00:
3199         if((c2 = (*i_getc)(f)) == 0x00){
3200             if((c2 = (*i_getc)(f)) == 0xFE){
3201                 if((c2 = (*i_getc)(f)) == 0xFF){
3202                     if(!input_encoding){
3203                         set_iconv(TRUE, w_iconv32);
3204                     }
3205                     if (iconv == w_iconv32) {
3206                         input_bom_f = TRUE;
3207                         input_endian = ENDIAN_BIG;
3208                         return;
3209                     }
3210                     (*i_ungetc)(0xFF,f);
3211                 }else (*i_ungetc)(c2,f);
3212                 (*i_ungetc)(0xFE,f);
3213             }else if(c2 == 0xFF){
3214                 if((c2 = (*i_getc)(f)) == 0xFE){
3215                     if(!input_encoding){
3216                         set_iconv(TRUE, w_iconv32);
3217                     }
3218                     if (iconv == w_iconv32) {
3219                         input_endian = ENDIAN_2143;
3220                         return;
3221                     }
3222                     (*i_ungetc)(0xFF,f);
3223                 }else (*i_ungetc)(c2,f);
3224                 (*i_ungetc)(0xFF,f);
3225             }else (*i_ungetc)(c2,f);
3226             (*i_ungetc)(0x00,f);
3227         }else (*i_ungetc)(c2,f);
3228         (*i_ungetc)(0x00,f);
3229         break;
3230     case 0xEF:
3231         if((c2 = (*i_getc)(f)) == 0xBB){
3232             if((c2 = (*i_getc)(f)) == 0xBF){
3233                 if(!input_encoding){
3234                     set_iconv(TRUE, w_iconv);
3235                 }
3236                 if (iconv == w_iconv) {
3237                     input_bom_f = TRUE;
3238                     return;
3239                 }
3240                 (*i_ungetc)(0xBF,f);
3241             }else (*i_ungetc)(c2,f);
3242             (*i_ungetc)(0xBB,f);
3243         }else (*i_ungetc)(c2,f);
3244         (*i_ungetc)(0xEF,f);
3245         break;
3246     case 0xFE:
3247         if((c2 = (*i_getc)(f)) == 0xFF){
3248             if((c2 = (*i_getc)(f)) == 0x00){
3249                 if((c2 = (*i_getc)(f)) == 0x00){
3250                     if(!input_encoding){
3251                         set_iconv(TRUE, w_iconv32);
3252                     }
3253                     if (iconv == w_iconv32) {
3254                         input_endian = ENDIAN_3412;
3255                         return;
3256                     }
3257                     (*i_ungetc)(0x00,f);
3258                 }else (*i_ungetc)(c2,f);
3259                 (*i_ungetc)(0x00,f);
3260             }else (*i_ungetc)(c2,f);
3261             if(!input_encoding){
3262                 set_iconv(TRUE, w_iconv16);
3263             }
3264             if (iconv == w_iconv16) {
3265                 input_endian = ENDIAN_BIG;
3266                 input_bom_f = TRUE;
3267                 return;
3268             }
3269             (*i_ungetc)(0xFF,f);
3270         }else (*i_ungetc)(c2,f);
3271         (*i_ungetc)(0xFE,f);
3272         break;
3273     case 0xFF:
3274         if((c2 = (*i_getc)(f)) == 0xFE){
3275             if((c2 = (*i_getc)(f)) == 0x00){
3276                 if((c2 = (*i_getc)(f)) == 0x00){
3277                     if(!input_encoding){
3278                         set_iconv(TRUE, w_iconv32);
3279                     }
3280                     if (iconv == w_iconv32) {
3281                         input_endian = ENDIAN_LITTLE;
3282                         input_bom_f = TRUE;
3283                         return;
3284                     }
3285                     (*i_ungetc)(0x00,f);
3286                 }else (*i_ungetc)(c2,f);
3287                 (*i_ungetc)(0x00,f);
3288             }else (*i_ungetc)(c2,f);
3289             if(!input_encoding){
3290                 set_iconv(TRUE, w_iconv16);
3291             }
3292             if (iconv == w_iconv16) {
3293                 input_endian = ENDIAN_LITTLE;
3294                 input_bom_f = TRUE;
3295                 return;
3296             }
3297             (*i_ungetc)(0xFE,f);
3298         }else (*i_ungetc)(c2,f);
3299         (*i_ungetc)(0xFF,f);
3300         break;
3301     default:
3302         (*i_ungetc)(c2,f);
3303         break;
3304     }
3305 }
3306
3307 static nkf_char
3308 broken_getc(FILE *f)
3309 {
3310     nkf_char c, c1;
3311
3312     if (!nkf_buf_empty_p(nkf_state->broken_buf)) {
3313         return nkf_buf_pop(nkf_state->broken_buf);
3314     }
3315     c = (*i_bgetc)(f);
3316     if (c=='$' && nkf_state->broken_state != ESC
3317         && (input_mode == ASCII || input_mode == JIS_X_0201_1976_K)) {
3318         c1= (*i_bgetc)(f);
3319         nkf_state->broken_state = 0;
3320         if (c1=='@'|| c1=='B') {
3321             nkf_buf_push(nkf_state->broken_buf, c1);
3322             nkf_buf_push(nkf_state->broken_buf, c);
3323             return ESC;
3324         } else {
3325             (*i_bungetc)(c1,f);
3326             return c;
3327         }
3328     } else if (c=='(' && nkf_state->broken_state != ESC
3329                && (input_mode == JIS_X_0208 || input_mode == JIS_X_0201_1976_K)) {
3330         c1= (*i_bgetc)(f);
3331         nkf_state->broken_state = 0;
3332         if (c1=='J'|| c1=='B') {
3333             nkf_buf_push(nkf_state->broken_buf, c1);
3334             nkf_buf_push(nkf_state->broken_buf, c);
3335             return ESC;
3336         } else {
3337             (*i_bungetc)(c1,f);
3338             return c;
3339         }
3340     } else {
3341         nkf_state->broken_state = c;
3342         return c;
3343     }
3344 }
3345
3346 static nkf_char
3347 broken_ungetc(nkf_char c, FILE *f)
3348 {
3349     if (nkf_buf_length(nkf_state->broken_buf) < 2)
3350         nkf_buf_push(nkf_state->broken_buf, c);
3351     return c;
3352 }
3353
3354 static void
3355 eol_conv(nkf_char c2, nkf_char c1)
3356 {
3357     if (guess_f && input_eol != EOF) {
3358         if (c2 == 0 && c1 == LF) {
3359             if (!input_eol) input_eol = prev_cr ? CRLF : LF;
3360             else if (input_eol != (prev_cr ? CRLF : LF)) input_eol = EOF;
3361         } else if (c2 == 0 && c1 == CR && input_eol == LF) input_eol = EOF;
3362         else if (!prev_cr);
3363         else if (!input_eol) input_eol = CR;
3364         else if (input_eol != CR) input_eol = EOF;
3365     }
3366     if (prev_cr || (c2 == 0 && c1 == LF)) {
3367         prev_cr = 0;
3368         if (eolmode_f != LF) (*o_eol_conv)(0, CR);
3369         if (eolmode_f != CR) (*o_eol_conv)(0, LF);
3370     }
3371     if (c2 == 0 && c1 == CR) prev_cr = CR;
3372     else if (c2 != 0 || c1 != LF) (*o_eol_conv)(c2, c1);
3373 }
3374
3375 static void
3376 put_newline(void (*func)(nkf_char))
3377 {
3378     switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) {
3379       case CRLF:
3380         (*func)(0x0D);
3381         (*func)(0x0A);
3382         break;
3383       case CR:
3384         (*func)(0x0D);
3385         break;
3386       case LF:
3387         (*func)(0x0A);
3388         break;
3389     }
3390 }
3391
3392 static void
3393 oconv_newline(void (*func)(nkf_char, nkf_char))
3394 {
3395     switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) {
3396       case CRLF:
3397         (*func)(0, 0x0D);
3398         (*func)(0, 0x0A);
3399         break;
3400       case CR:
3401         (*func)(0, 0x0D);
3402         break;
3403       case LF:
3404         (*func)(0, 0x0A);
3405         break;
3406     }
3407 }
3408
3409 /*
3410    Return value of fold_conv()
3411
3412    LF  add newline  and output char
3413    CR  add newline  and output nothing
3414    SP  space
3415    0   skip
3416    1   (or else) normal output
3417
3418    fold state in prev (previous character)
3419
3420    >0x80 Japanese (X0208/X0201)
3421    <0x80 ASCII
3422    LF    new line
3423    SP    space
3424
3425    This fold algorthm does not preserve heading space in a line.
3426    This is the main difference from fmt.
3427  */
3428
3429 #define char_size(c2,c1) (c2?2:1)
3430
3431 static void
3432 fold_conv(nkf_char c2, nkf_char c1)
3433 {
3434     nkf_char prev0;
3435     nkf_char fold_state;
3436
3437     if (c1== CR && !fold_preserve_f) {
3438         fold_state=0;  /* ignore cr */
3439     }else if (c1== LF&&f_prev==CR && fold_preserve_f) {
3440         f_prev = LF;
3441         fold_state=0;  /* ignore cr */
3442     } else if (c1== BS) {
3443         if (f_line>0) f_line--;
3444         fold_state =  1;
3445     } else if (c2==EOF && f_line != 0) {    /* close open last line */
3446         fold_state = LF;
3447     } else if ((c1==LF && !fold_preserve_f)
3448                || ((c1==CR||(c1==LF&&f_prev!=CR))
3449                    && fold_preserve_f)) {
3450         /* new line */
3451         if (fold_preserve_f) {
3452             f_prev = c1;
3453             f_line = 0;
3454             fold_state =  CR;
3455         } else if ((f_prev == c1 && !fold_preserve_f)
3456                    || (f_prev == LF && fold_preserve_f)
3457                   ) {        /* duplicate newline */
3458             if (f_line) {
3459                 f_line = 0;
3460                 fold_state =  LF;    /* output two newline */
3461             } else {
3462                 f_line = 0;
3463                 fold_state =  1;
3464             }
3465         } else  {
3466             if (f_prev&0x80) {     /* Japanese? */
3467                 f_prev = c1;
3468                 fold_state =  0;       /* ignore given single newline */
3469             } else if (f_prev==SP) {
3470                 fold_state =  0;
3471             } else {
3472                 f_prev = c1;
3473                 if (++f_line<=fold_len)
3474                     fold_state =  SP;
3475                 else {
3476                     f_line = 0;
3477                     fold_state =  CR;        /* fold and output nothing */
3478                 }
3479             }
3480         }
3481     } else if (c1=='\f') {
3482         f_prev = LF;
3483         f_line = 0;
3484         fold_state =  LF;            /* output newline and clear */
3485     } else if ((c2==0 && nkf_isblank(c1)) || (c2 == '!' && c1 == '!')) {
3486         /* X0208 kankaku or ascii space */
3487         if (f_prev == SP) {
3488             fold_state = 0;         /* remove duplicate spaces */
3489         } else {
3490             f_prev = SP;
3491             if (++f_line<=fold_len)
3492                 fold_state = SP;         /* output ASCII space only */
3493             else {
3494                 f_prev = SP; f_line = 0;
3495                 fold_state = CR;        /* fold and output nothing */
3496             }
3497         }
3498     } else {
3499         prev0 = f_prev; /* we still need this one... , but almost done */
3500         f_prev = c1;
3501         if (c2 || c2 == JIS_X_0201_1976_K)
3502             f_prev |= 0x80;  /* this is Japanese */
3503         f_line += char_size(c2,c1);
3504         if (f_line<=fold_len) {   /* normal case */
3505             fold_state = 1;
3506         } else {
3507             if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
3508                 f_line = char_size(c2,c1);
3509                 fold_state =  LF;       /* We can't wait, do fold now */
3510             } else if (c2 == JIS_X_0201_1976_K) {
3511                 /* simple kinsoku rules  return 1 means no folding  */
3512                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
3513                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
3514                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
3515                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
3516                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
3517                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
3518                 else if (SP<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
3519                     f_line = 1;
3520                     fold_state = LF;/* add one new f_line before this character */
3521                 } else {
3522                     f_line = 1;
3523                     fold_state = LF;/* add one new f_line before this character */
3524                 }
3525             } else if (c2==0) {
3526                 /* kinsoku point in ASCII */
3527                 if (  c1==')'||    /* { [ ( */
3528                     c1==']'||
3529                     c1=='}'||
3530                     c1=='.'||
3531                     c1==','||
3532                     c1=='!'||
3533                     c1=='?'||
3534                     c1=='/'||
3535                     c1==':'||
3536                     c1==';') {
3537                     fold_state = 1;
3538                     /* just after special */
3539                 } else if (!is_alnum(prev0)) {
3540                     f_line = char_size(c2,c1);
3541                     fold_state = LF;
3542                 } else if ((prev0==SP) ||   /* ignored new f_line */
3543                            (prev0==LF)||        /* ignored new f_line */
3544                            (prev0&0x80)) {        /* X0208 - ASCII */
3545                     f_line = char_size(c2,c1);
3546                     fold_state = LF;/* add one new f_line before this character */
3547                 } else {
3548                     fold_state = 1;  /* default no fold in ASCII */
3549                 }
3550             } else {
3551                 if (c2=='!') {
3552                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
3553                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
3554                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
3555                     else if (c1=='K')  fold_state = 1; /* \e$B!K\e(B */
3556                     else if (c1=='$')  fold_state = 1; /* \e$B!$\e(B */
3557                     else if (c1=='%')  fold_state = 1; /* \e$B!%\e(B */
3558                     else if (c1=='\'') fold_state = 1; /* \e$B!\\e(B */
3559                     else if (c1=='(')  fold_state = 1; /* \e$B!(\e(B */
3560                     else if (c1==')')  fold_state = 1; /* \e$B!)\e(B */
3561                     else if (c1=='*')  fold_state = 1; /* \e$B!*\e(B */
3562                     else if (c1=='+')  fold_state = 1; /* \e$B!+\e(B */
3563                     else if (c1==',')  fold_state = 1; /* \e$B!,\e(B */
3564                     /* default no fold in kinsoku */
3565                     else {
3566                         fold_state = LF;
3567                         f_line = char_size(c2,c1);
3568                         /* add one new f_line before this character */
3569                     }
3570                 } else {
3571                     f_line = char_size(c2,c1);
3572                     fold_state = LF;
3573                     /* add one new f_line before this character */
3574                 }
3575             }
3576         }
3577     }
3578     /* terminator process */
3579     switch(fold_state) {
3580     case LF:
3581         oconv_newline(o_fconv);
3582         (*o_fconv)(c2,c1);
3583         break;
3584     case 0:
3585         return;
3586     case CR:
3587         oconv_newline(o_fconv);
3588         break;
3589     case TAB:
3590     case SP:
3591         (*o_fconv)(0,SP);
3592         break;
3593     default:
3594         (*o_fconv)(c2,c1);
3595     }
3596 }
3597
3598 static nkf_char z_prev2=0,z_prev1=0;
3599
3600 static void
3601 z_conv(nkf_char c2, nkf_char c1)
3602 {
3603
3604     /* if (c2) c1 &= 0x7f; assertion */
3605
3606     if (c2 == JIS_X_0201_1976_K && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) {
3607         (*o_zconv)(c2,c1);
3608         return;
3609     }
3610
3611     if (x0201_f) {
3612         if (z_prev2 == JIS_X_0201_1976_K) {
3613             if (c2 == JIS_X_0201_1976_K) {
3614                 if (c1 == (0xde&0x7f)) { /* \e$BByE@\e(B */
3615                     z_prev2 = 0;
3616                     (*o_zconv)(dv[(z_prev1-SP)*2], dv[(z_prev1-SP)*2+1]);
3617                     return;
3618                 } else if (c1 == (0xdf&0x7f) && ev[(z_prev1-SP)*2]) {  /* \e$BH>ByE@\e(B */
3619                     z_prev2 = 0;
3620                     (*o_zconv)(ev[(z_prev1-SP)*2], ev[(z_prev1-SP)*2+1]);
3621                     return;
3622                 }
3623             }
3624             z_prev2 = 0;
3625             (*o_zconv)(cv[(z_prev1-SP)*2], cv[(z_prev1-SP)*2+1]);
3626         }
3627         if (c2 == JIS_X_0201_1976_K) {
3628             if (dv[(c1-SP)*2] || ev[(c1-SP)*2]) {
3629                 /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
3630                 z_prev1 = c1;
3631                 z_prev2 = c2;
3632                 return;
3633             } else {
3634                 (*o_zconv)(cv[(c1-SP)*2], cv[(c1-SP)*2+1]);
3635                 return;
3636             }
3637         }
3638     }
3639
3640     if (c2 == EOF) {
3641         (*o_zconv)(c2, c1);
3642         return;
3643     }
3644
3645     if (alpha_f&1 && c2 == 0x23) {
3646         /* JISX0208 Alphabet */
3647         c2 = 0;
3648     } else if (c2 == 0x21) {
3649         /* JISX0208 Kigou */
3650         if (0x21==c1) {
3651             if (alpha_f&2) {
3652                 c2 = 0;
3653                 c1 = SP;
3654             } else if (alpha_f&4) {
3655                 (*o_zconv)(0, SP);
3656                 (*o_zconv)(0, SP);
3657                 return;
3658             }
3659         } else if (alpha_f&1 && 0x20<c1 && c1<0x7f && fv[c1-0x20]) {
3660             c2 =  0;
3661             c1 = fv[c1-0x20];
3662         }
3663     }
3664
3665     if (alpha_f&8 && c2 == 0) {
3666         /* HTML Entity */
3667         const char *entity = 0;
3668         switch (c1){
3669         case '>': entity = "&gt;"; break;
3670         case '<': entity = "&lt;"; break;
3671         case '\"': entity = "&quot;"; break;
3672         case '&': entity = "&amp;"; break;
3673         }
3674         if (entity){
3675             while (*entity) (*o_zconv)(0, *entity++);
3676             return;
3677         }
3678     }
3679
3680     if (alpha_f & 16) {
3681         /* JIS X 0208 Katakana to JIS X 0201 Katakana */
3682         if (c2 == 0x21) {
3683             nkf_char c = 0;
3684             switch (c1) {
3685             case 0x23:
3686                 /* U+3002 (0x8142) Ideographic Full Stop -> U+FF61 (0xA1) Halfwidth Ideographic Full Stop */
3687                 c = 0xA1;
3688                 break;
3689             case 0x56:
3690                 /* U+300C (0x8175) Left Corner Bracket -> U+FF62 (0xA2) Halfwidth Left Corner Bracket */
3691                 c = 0xA2;
3692                 break;
3693             case 0x57:
3694                 /* U+300D (0x8176) Right Corner Bracket -> U+FF63 (0xA3) Halfwidth Right Corner Bracket */
3695                 c = 0xA3;
3696                 break;
3697             case 0x22:
3698                 /* U+3001 (0x8141) Ideographic Comma -> U+FF64 (0xA4) Halfwidth Ideographic Comma */
3699                 c = 0xA4;
3700                 break;
3701             case 0x26:
3702                 /* U+30FB (0x8145) Katakana Middle Dot -> U+FF65 (0xA5) Halfwidth Katakana Middle Dot */
3703                 c = 0xA5;
3704                 break;
3705             case 0x3C:
3706                 /* U+30FC (0x815B) Katakana-Hiragana Prolonged Sound Mark -> U+FF70 (0xB0) Halfwidth Katakana-Hiragana Prolonged Sound Mark */
3707                 c = 0xB0;
3708                 break;
3709             case 0x2B:
3710                 /* U+309B (0x814A) Katakana-Hiragana Voiced Sound Mark -> U+FF9E (0xDE) Halfwidth Katakana Voiced Sound Mark */
3711                 c = 0xDE;
3712                 break;
3713             case 0x2C:
3714                 /* U+309C (0x814B) Katakana-Hiragana Semi-Voiced Sound Mark -> U+FF9F (0xDF) Halfwidth Katakana Semi-Voiced Sound Mark */
3715                 c = 0xDF;
3716                 break;
3717             }
3718             if (c) {
3719                 (*o_zconv)(JIS_X_0201_1976_K, c);
3720                 return;
3721             }
3722         } else if (c2 == 0x25) {
3723             /* JISX0208 Katakana */
3724             static const int fullwidth_to_halfwidth[] =
3725             {
3726                 0x0000, 0x2700, 0x3100, 0x2800, 0x3200, 0x2900, 0x3300, 0x2A00,
3727                 0x3400, 0x2B00, 0x3500, 0x3600, 0x365E, 0x3700, 0x375E, 0x3800,
3728                 0x385E, 0x3900, 0x395E, 0x3A00, 0x3A5E, 0x3B00, 0x3B5E, 0x3C00,
3729                 0x3C5E, 0x3D00, 0x3D5E, 0x3E00, 0x3E5E, 0x3F00, 0x3F5E, 0x4000,
3730                 0x405E, 0x4100, 0x415E, 0x2F00, 0x4200, 0x425E, 0x4300, 0x435E,
3731                 0x4400, 0x445E, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00,
3732                 0x4A5E, 0x4A5F, 0x4B00, 0x4B5E, 0x4B5F, 0x4C00, 0x4C5E, 0x4C5F,
3733                 0x4D00, 0x4D5E, 0x4D5F, 0x4E00, 0x4E5E, 0x4E5F, 0x4F00, 0x5000,
3734                 0x5100, 0x5200, 0x5300, 0x2C00, 0x5400, 0x2D00, 0x5500, 0x2E00,
3735                 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x0000, 0x5C00,
3736                 0x0000, 0x0000, 0x2600, 0x5D00, 0x335E, 0x0000, 0x0000, 0x0000,
3737                 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
3738             };
3739             if (fullwidth_to_halfwidth[c1-0x20]){
3740                 c2 = fullwidth_to_halfwidth[c1-0x20];
3741                 (*o_zconv)(JIS_X_0201_1976_K, c2>>8);
3742                 if (c2 & 0xFF) {
3743                     (*o_zconv)(JIS_X_0201_1976_K, c2&0xFF);
3744                 }
3745                 return;
3746             }
3747         }
3748     }
3749     (*o_zconv)(c2,c1);
3750 }
3751
3752
3753 #define rot13(c)  ( \
3754                    ( c < 'A') ? c: \
3755                    (c <= 'M')  ? (c + 13): \
3756                    (c <= 'Z')  ? (c - 13): \
3757                    (c < 'a')   ? (c): \
3758                    (c <= 'm')  ? (c + 13): \
3759                    (c <= 'z')  ? (c - 13): \
3760                    (c) \
3761                   )
3762
3763 #define  rot47(c) ( \
3764                    ( c < '!') ? c: \
3765                    ( c <= 'O') ? (c + 47) : \
3766                    ( c <= '~') ?  (c - 47) : \
3767                    c \
3768                   )
3769
3770 static void
3771 rot_conv(nkf_char c2, nkf_char c1)
3772 {
3773     if (c2 == 0 || c2 == JIS_X_0201_1976_K || c2 == ISO_8859_1) {
3774         c1 = rot13(c1);
3775     } else if (c2) {
3776         c1 = rot47(c1);
3777         c2 = rot47(c2);
3778     }
3779     (*o_rot_conv)(c2,c1);
3780 }
3781
3782 static void
3783 hira_conv(nkf_char c2, nkf_char c1)
3784 {
3785     if (hira_f & 1) {
3786         if (c2 == 0x25) {
3787             if (0x20 < c1 && c1 < 0x74) {
3788                 c2 = 0x24;
3789                 (*o_hira_conv)(c2,c1);
3790                 return;
3791             } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) {
3792                 c2 = 0;
3793                 c1 = nkf_char_unicode_new(0x3094);
3794                 (*o_hira_conv)(c2,c1);
3795                 return;
3796             }
3797         } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
3798             c1 += 2;
3799             (*o_hira_conv)(c2,c1);
3800             return;
3801         }
3802     }
3803     if (hira_f & 2) {
3804         if (c2 == 0 && c1 == nkf_char_unicode_new(0x3094)) {
3805             c2 = 0x25;
3806             c1 = 0x74;
3807         } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
3808             c2 = 0x25;
3809         } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
3810             c1 -= 2;
3811         }
3812     }
3813     (*o_hira_conv)(c2,c1);
3814 }
3815
3816
3817 static void
3818 iso2022jp_check_conv(nkf_char c2, nkf_char c1)
3819 {
3820 #define RANGE_NUM_MAX 18
3821     static const nkf_char range[RANGE_NUM_MAX][2] = {
3822         {0x222f, 0x2239,},