OSDN Git Service

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