OSDN Git Service

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