OSDN Git Service

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