OSDN Git Service

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