OSDN Git Service

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