OSDN Git Service

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