OSDN Git Service

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