OSDN Git Service

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