OSDN Git Service

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