OSDN Git Service

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