OSDN Git Service

Patch by sava. [nkf-patch#13930]
[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.187 2008/11/07 02:37:21 naruse Exp $"
35 #define NKF_VERSION "2.0.8"
36 #define NKF_RELEASE_DATE "2008-10-28"
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
54 /* state of output_mode and input_mode
55
56    c2           0 means ASCII
57    JIS_X_0201_1976_K
58    ISO_8859_1
59    JIS_X_0208
60    EOF      all termination
61    c1           32bit data
62
63  */
64
65 /* MIME ENCODE */
66
67 #define         FIXED_MIME      7
68 #define         STRICT_MIME     8
69
70 /* byte order */
71 enum byte_order {
72     ENDIAN_BIG    = 1,
73     ENDIAN_LITTLE = 2,
74     ENDIAN_2143   = 3,
75     ENDIAN_3412   = 4
76 };
77
78 /* ASCII CODE */
79
80 #define         BS      0x08
81 #define         TAB     0x09
82 #define         LF      0x0a
83 #define         CR      0x0d
84 #define         ESC     0x1b
85 #define         SP      0x20
86 #define         DEL     0x7f
87 #define         SI      0x0f
88 #define         SO      0x0e
89 #define         SS2     0x8e
90 #define         SS3     0x8f
91 #define         CRLF    0x0D0A
92
93
94 /* encodings */
95
96 enum nkf_encodings {
97     ASCII,
98     ISO_8859_1,
99     ISO_2022_JP,
100     CP50220,
101     CP50221,
102     CP50222,
103     ISO_2022_JP_1,
104     ISO_2022_JP_3,
105     ISO_2022_JP_2004,
106     SHIFT_JIS,
107     WINDOWS_31J,
108     CP10001,
109     EUC_JP,
110     EUCJP_NKF,
111     CP51932,
112     EUCJP_MS,
113     EUCJP_ASCII,
114     SHIFT_JISX0213,
115     SHIFT_JIS_2004,
116     EUC_JISX0213,
117     EUC_JIS_2004,
118     UTF_8,
119     UTF_8N,
120     UTF_8_BOM,
121     UTF8_MAC,
122     UTF_16,
123     UTF_16BE,
124     UTF_16BE_BOM,
125     UTF_16LE,
126     UTF_16LE_BOM,
127     UTF_32,
128     UTF_32BE,
129     UTF_32BE_BOM,
130     UTF_32LE,
131     UTF_32LE_BOM,
132     BINARY,
133     NKF_ENCODING_TABLE_SIZE,
134     JIS_X_0201_1976_K = 0x1013, /* I */ /* JIS C 6220-1969 */
135     /* JIS_X_0201_1976_R = 0x1014, */ /* J */ /* JIS C 6220-1969 */
136     /* JIS_X_0208_1978   = 0x1040, */ /* @ */ /* JIS C 6226-1978 */
137     /* JIS_X_0208_1983   = 0x1087, */ /* B */ /* JIS C 6226-1983 */
138     JIS_X_0208        = 0x1168, /* @B */
139     JIS_X_0212        = 0x1159, /* D */
140     /* JIS_X_0213_2000_1 = 0x1228, */ /* O */
141     JIS_X_0213_2 = 0x1229, /* P */
142     JIS_X_0213_1 = 0x1233, /* Q */
143 };
144
145 static nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
146 static nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
147 static nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
148 static nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0);
149 static nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0);
150 static void j_oconv(nkf_char c2, nkf_char c1);
151 static void s_oconv(nkf_char c2, nkf_char c1);
152 static void e_oconv(nkf_char c2, nkf_char c1);
153 static void w_oconv(nkf_char c2, nkf_char c1);
154 static void w_oconv16(nkf_char c2, nkf_char c1);
155 static void w_oconv32(nkf_char c2, nkf_char c1);
156
157 typedef struct {
158     const char *name;
159     nkf_char (*iconv)(nkf_char c2, nkf_char c1, nkf_char c0);
160     void (*oconv)(nkf_char c2, nkf_char c1);
161 } nkf_native_encoding;
162
163 nkf_native_encoding NkfEncodingASCII =          { "ASCII", e_iconv, e_oconv };
164 nkf_native_encoding NkfEncodingISO_2022_JP =    { "ISO-2022-JP", e_iconv, j_oconv };
165 nkf_native_encoding NkfEncodingShift_JIS =      { "Shift_JIS", s_iconv, s_oconv };
166 nkf_native_encoding NkfEncodingEUC_JP =         { "EUC-JP", e_iconv, e_oconv };
167 nkf_native_encoding NkfEncodingUTF_8 =          { "UTF-8", w_iconv, w_oconv };
168 nkf_native_encoding NkfEncodingUTF_16 =         { "UTF-16", w_iconv16, w_oconv16 };
169 nkf_native_encoding NkfEncodingUTF_32 =         { "UTF-32", w_iconv32, w_oconv32 };
170
171 typedef struct {
172     const int id;
173     const char *name;
174     const nkf_native_encoding *base_encoding;
175 } nkf_encoding;
176
177 nkf_encoding nkf_encoding_table[] = {
178     {ASCII,             "US-ASCII",             &NkfEncodingASCII},
179     {ISO_8859_1,        "ISO-8859-1",           &NkfEncodingASCII},
180     {ISO_2022_JP,       "ISO-2022-JP",          &NkfEncodingISO_2022_JP},
181     {CP50220,           "CP50220",              &NkfEncodingISO_2022_JP},
182     {CP50221,           "CP50221",              &NkfEncodingISO_2022_JP},
183     {CP50222,           "CP50222",              &NkfEncodingISO_2022_JP},
184     {ISO_2022_JP_1,     "ISO-2022-JP-1",        &NkfEncodingISO_2022_JP},
185     {ISO_2022_JP_3,     "ISO-2022-JP-3",        &NkfEncodingISO_2022_JP},
186     {ISO_2022_JP_2004,  "ISO-2022-JP-2004",     &NkfEncodingISO_2022_JP},
187     {SHIFT_JIS,         "Shift_JIS",            &NkfEncodingShift_JIS},
188     {WINDOWS_31J,       "Windows-31J",          &NkfEncodingShift_JIS},
189     {CP10001,           "CP10001",              &NkfEncodingShift_JIS},
190     {EUC_JP,            "EUC-JP",               &NkfEncodingEUC_JP},
191     {EUCJP_NKF,         "eucJP-nkf",            &NkfEncodingEUC_JP},
192     {CP51932,           "CP51932",              &NkfEncodingEUC_JP},
193     {EUCJP_MS,          "eucJP-MS",             &NkfEncodingEUC_JP},
194     {EUCJP_ASCII,       "eucJP-ASCII",          &NkfEncodingEUC_JP},
195     {SHIFT_JISX0213,    "Shift_JISX0213",       &NkfEncodingShift_JIS},
196     {SHIFT_JIS_2004,    "Shift_JIS-2004",       &NkfEncodingShift_JIS},
197     {EUC_JISX0213,      "EUC-JISX0213",         &NkfEncodingEUC_JP},
198     {EUC_JIS_2004,      "EUC-JIS-2004",         &NkfEncodingEUC_JP},
199     {UTF_8,             "UTF-8",                &NkfEncodingUTF_8},
200     {UTF_8N,            "UTF-8N",               &NkfEncodingUTF_8},
201     {UTF_8_BOM,         "UTF-8-BOM",            &NkfEncodingUTF_8},
202     {UTF8_MAC,          "UTF8-MAC",             &NkfEncodingUTF_8},
203     {UTF_16,            "UTF-16",               &NkfEncodingUTF_16},
204     {UTF_16BE,          "UTF-16BE",             &NkfEncodingUTF_16},
205     {UTF_16BE_BOM,      "UTF-16BE-BOM",         &NkfEncodingUTF_16},
206     {UTF_16LE,          "UTF-16LE",             &NkfEncodingUTF_16},
207     {UTF_16LE_BOM,      "UTF-16LE-BOM",         &NkfEncodingUTF_16},
208     {UTF_32,            "UTF-32",               &NkfEncodingUTF_32},
209     {UTF_32BE,          "UTF-32BE",             &NkfEncodingUTF_32},
210     {UTF_32BE_BOM,      "UTF-32BE-BOM",         &NkfEncodingUTF_32},
211     {UTF_32LE,          "UTF-32LE",             &NkfEncodingUTF_32},
212     {UTF_32LE_BOM,      "UTF-32LE-BOM",         &NkfEncodingUTF_32},
213     {BINARY,            "BINARY",               &NkfEncodingASCII},
214     {-1,                NULL,                   NULL}
215 };
216
217 struct {
218     const char *name;
219     const int id;
220 } encoding_name_to_id_table[] = {
221     {"US-ASCII",                ASCII},
222     {"ASCII",                   ASCII},
223     {"ISO-2022-JP",             ISO_2022_JP},
224     {"ISO2022JP-CP932",         CP50220},
225     {"CP50220",                 CP50220},
226     {"CP50221",                 CP50221},
227     {"CSISO2022JP",             CP50221},
228     {"CP50222",                 CP50222},
229     {"ISO-2022-JP-1",           ISO_2022_JP_1},
230     {"ISO-2022-JP-3",           ISO_2022_JP_3},
231     {"ISO-2022-JP-2004",        ISO_2022_JP_2004},
232     {"SHIFT_JIS",               SHIFT_JIS},
233     {"SJIS",                    SHIFT_JIS},
234     {"WINDOWS-31J",             WINDOWS_31J},
235     {"CSWINDOWS31J",            WINDOWS_31J},
236     {"CP932",                   WINDOWS_31J},
237     {"MS932",                   WINDOWS_31J},
238     {"CP10001",                 CP10001},
239     {"EUCJP",                   EUC_JP},
240     {"EUC-JP",                  EUC_JP},
241     {"EUCJP-NKF",               EUCJP_NKF},
242     {"CP51932",                 CP51932},
243     {"EUC-JP-MS",               EUCJP_MS},
244     {"EUCJP-MS",                EUCJP_MS},
245     {"EUCJPMS",                 EUCJP_MS},
246     {"EUC-JP-ASCII",            EUCJP_ASCII},
247     {"EUCJP-ASCII",             EUCJP_ASCII},
248     {"SHIFT_JISX0213",          SHIFT_JISX0213},
249     {"SHIFT_JIS-2004",          SHIFT_JIS_2004},
250     {"EUC-JISX0213",            EUC_JISX0213},
251     {"EUC-JIS-2004",            EUC_JIS_2004},
252     {"UTF-8",                   UTF_8},
253     {"UTF-8N",                  UTF_8N},
254     {"UTF-8-BOM",               UTF_8_BOM},
255     {"UTF8-MAC",                UTF8_MAC},
256     {"UTF-8-MAC",               UTF8_MAC},
257     {"UTF-16",                  UTF_16},
258     {"UTF-16BE",                UTF_16BE},
259     {"UTF-16BE-BOM",            UTF_16BE_BOM},
260     {"UTF-16LE",                UTF_16LE},
261     {"UTF-16LE-BOM",            UTF_16LE_BOM},
262     {"UTF-32",                  UTF_32},
263     {"UTF-32BE",                UTF_32BE},
264     {"UTF-32BE-BOM",            UTF_32BE_BOM},
265     {"UTF-32LE",                UTF_32LE},
266     {"UTF-32LE-BOM",            UTF_32LE_BOM},
267     {"BINARY",                  BINARY},
268     {NULL,                      -1}
269 };
270
271 #if defined(DEFAULT_CODE_JIS)
272 #define     DEFAULT_ENCIDX ISO_2022_JP
273 #elif defined(DEFAULT_CODE_SJIS)
274 #define     DEFAULT_ENCIDX SHIFT_JIS
275 #elif defined(DEFAULT_CODE_WINDOWS_31J)
276 #define     DEFAULT_ENCIDX WINDOWS_31J
277 #elif defined(DEFAULT_CODE_EUC)
278 #define     DEFAULT_ENCIDX EUC_JP
279 #elif defined(DEFAULT_CODE_UTF8)
280 #define     DEFAULT_ENCIDX UTF_8
281 #endif
282
283
284 #define         is_alnum(c)  \
285     (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
286
287 /* I don't trust portablity of toupper */
288 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
289 #define nkf_isoctal(c)  ('0'<=c && c<='7')
290 #define nkf_isdigit(c)  ('0'<=c && c<='9')
291 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
292 #define nkf_isblank(c) (c == SP || c == TAB)
293 #define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == LF)
294 #define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
295 #define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c))
296 #define nkf_isprint(c) (SP<=c && c<='~')
297 #define nkf_isgraph(c) ('!'<=c && c<='~')
298 #define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \
299                     ('A'<=c&&c<='F') ? (c-'A'+10) : \
300                     ('a'<=c&&c<='f') ? (c-'a'+10) : 0)
301 #define bin2hex(c) ("0123456789ABCDEF"[c&15])
302 #define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3)
303 #define nkf_noescape_mime(c) ((c == CR) || (c == LF) || \
304                               ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \
305                                && (c != '(') && (c != ')') && (c != '.') && (c != 0x22)))
306
307 #define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END)
308 #define nkf_byte_jisx0201_katakana_p(c) (SP <= c && c < (0xE0&0x7F))
309
310 #define         HOLD_SIZE       1024
311 #if defined(INT_IS_SHORT)
312 #define         IOBUF_SIZE      2048
313 #else
314 #define         IOBUF_SIZE      16384
315 #endif
316
317 #define         DEFAULT_J       'B'
318 #define         DEFAULT_R       'B'
319
320
321 #define         GETA1   0x22
322 #define         GETA2   0x2e
323
324
325 /* MIME preprocessor */
326
327 #ifdef EASYWIN /*Easy Win */
328 extern POINT _BufferSize;
329 #endif
330
331 struct input_code{
332     const char *name;
333     nkf_char stat;
334     nkf_char score;
335     nkf_char index;
336     nkf_char buf[3];
337     void (*status_func)(struct input_code *, nkf_char);
338     nkf_char (*iconv_func)(nkf_char c2, nkf_char c1, nkf_char c0);
339     int _file_stat;
340 };
341
342 static const char *input_codename = NULL; /* NULL: unestablished, "": BINARY */
343 static nkf_encoding *input_encoding = NULL;
344 static nkf_encoding *output_encoding = NULL;
345
346 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
347 /* UCS Mapping
348  * 0: Shift_JIS, eucJP-ascii
349  * 1: eucJP-ms
350  * 2: CP932, CP51932
351  * 3: CP10001
352  */
353 #define UCS_MAP_ASCII   0
354 #define UCS_MAP_MS      1
355 #define UCS_MAP_CP932   2
356 #define UCS_MAP_CP10001 3
357 static int ms_ucs_map_f = UCS_MAP_ASCII;
358 #endif
359 #ifdef UTF8_INPUT_ENABLE
360 /* no NEC special, NEC-selected IBM extended and IBM extended characters */
361 static  int     no_cp932ext_f = FALSE;
362 /* ignore ZERO WIDTH NO-BREAK SPACE */
363 static  int     no_best_fit_chars_f = FALSE;
364 static  int     input_endian = ENDIAN_BIG;
365 static  nkf_char     unicode_subchar = '?'; /* the regular substitution character */
366 static  void    (*encode_fallback)(nkf_char c) = NULL;
367 static  void    w_status(struct input_code *, nkf_char);
368 #endif
369 #ifdef UTF8_OUTPUT_ENABLE
370 static  int     output_bom_f = FALSE;
371 static  int     output_endian = ENDIAN_BIG;
372 #endif
373
374 static  void    std_putc(nkf_char c);
375 static  nkf_char     std_getc(FILE *f);
376 static  nkf_char     std_ungetc(nkf_char c,FILE *f);
377
378 static  nkf_char     broken_getc(FILE *f);
379 static  nkf_char     broken_ungetc(nkf_char c,FILE *f);
380
381 static  nkf_char     mime_getc(FILE *f);
382
383 static void mime_putc(nkf_char c);
384
385 /* buffers */
386
387 #if !defined(PERL_XS) && !defined(WIN32DLL)
388 static unsigned char   stdibuf[IOBUF_SIZE];
389 static unsigned char   stdobuf[IOBUF_SIZE];
390 #endif
391
392 /* flags */
393 static int             unbuf_f = FALSE;
394 static int             estab_f = FALSE;
395 static int             nop_f = FALSE;
396 static int             binmode_f = TRUE;       /* binary mode */
397 static int             rot_f = FALSE;          /* rot14/43 mode */
398 static int             hira_f = FALSE;          /* hira/kata henkan */
399 static int             alpha_f = FALSE;        /* convert JIx0208 alphbet to ASCII */
400 static int             mime_f = MIME_DECODE_DEFAULT;   /* convert MIME B base64 or Q */
401 static int             mime_decode_f = FALSE;  /* mime decode is explicitly on */
402 static int             mimebuf_f = FALSE;      /* MIME buffered input */
403 static int             broken_f = FALSE;       /* convert ESC-less broken JIS */
404 static int             iso8859_f = FALSE;      /* ISO8859 through */
405 static int             mimeout_f = FALSE;       /* base64 mode */
406 static int             x0201_f = X0201_DEFAULT; /* convert JIS X 0201 */
407 static int             iso2022jp_f = FALSE;    /* replace non ISO-2022-JP with GETA */
408
409 #ifdef UNICODE_NORMALIZATION
410 static int nfc_f = FALSE;
411 static nkf_char (*i_nfc_getc)(FILE *) = std_getc; /* input of ugetc */
412 static nkf_char (*i_nfc_ungetc)(nkf_char c ,FILE *f) = std_ungetc;
413 #endif
414
415 #ifdef INPUT_OPTION
416 static int cap_f = FALSE;
417 static nkf_char (*i_cgetc)(FILE *) = std_getc; /* input of cgetc */
418 static nkf_char (*i_cungetc)(nkf_char c ,FILE *f) = std_ungetc;
419
420 static int url_f = FALSE;
421 static nkf_char (*i_ugetc)(FILE *) = std_getc; /* input of ugetc */
422 static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc;
423 #endif
424
425 #define PREFIX_EUCG3    NKF_INT32_C(0x8F00)
426 #define CLASS_MASK      NKF_INT32_C(0xFF000000)
427 #define CLASS_UNICODE   NKF_INT32_C(0x01000000)
428 #define VALUE_MASK      NKF_INT32_C(0x00FFFFFF)
429 #define UNICODE_BMP_MAX NKF_INT32_C(0x0000FFFF)
430 #define UNICODE_MAX     NKF_INT32_C(0x0010FFFF)
431 #define nkf_char_euc3_new(c) ((c) | PREFIX_EUCG3)
432 #define nkf_char_unicode_new(c) ((c) | CLASS_UNICODE)
433 #define nkf_char_unicode_p(c) ((c & CLASS_MASK) == CLASS_UNICODE)
434 #define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= UNICODE_BMP_MAX)
435 #define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= UNICODE_MAX)
436
437 #ifdef NUMCHAR_OPTION
438 static int numchar_f = FALSE;
439 static nkf_char (*i_ngetc)(FILE *) = std_getc; /* input of ugetc */
440 static nkf_char (*i_nungetc)(nkf_char c ,FILE *f) = std_ungetc;
441 #endif
442
443 #ifdef CHECK_OPTION
444 static int noout_f = FALSE;
445 static void no_putc(nkf_char c);
446 static int debug_f = FALSE;
447 static void debug(const char *str);
448 static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0;
449 #endif
450
451 static int guess_f = 0; /* 0: OFF, 1: ON, 2: VERBOSE */
452 static  void    set_input_codename(const char *codename);
453
454 #ifdef EXEC_IO
455 static int exec_f = 0;
456 #endif
457
458 #ifdef SHIFTJIS_CP932
459 /* invert IBM extended characters to others */
460 static int cp51932_f = FALSE;
461
462 /* invert NEC-selected IBM extended characters to IBM extended characters */
463 static int cp932inv_f = TRUE;
464
465 /* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */
466 #endif /* SHIFTJIS_CP932 */
467
468 static int x0212_f = FALSE;
469 static int x0213_f = FALSE;
470
471 static unsigned char prefix_table[256];
472
473 static void e_status(struct input_code *, nkf_char);
474 static void s_status(struct input_code *, nkf_char);
475
476 struct input_code input_code_list[] = {
477     {"EUC-JP",    0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
478     {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
479 #ifdef UTF8_INPUT_ENABLE
480     {"UTF-8",     0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
481 #endif
482     {0}
483 };
484
485 static int              mimeout_mode = 0; /* 0, -1, 'Q', 'B', 1, 2 */
486 static int              base64_count = 0;
487
488 /* X0208 -> ASCII converter */
489
490 /* fold parameter */
491 static int             f_line = 0;    /* chars in line */
492 static int             f_prev = 0;
493 static int             fold_preserve_f = FALSE; /* preserve new lines */
494 static int             fold_f  = FALSE;
495 static int             fold_len  = 0;
496
497 /* options */
498 static unsigned char   kanji_intro = DEFAULT_J;
499 static unsigned char   ascii_intro = DEFAULT_R;
500
501 /* Folding */
502
503 #define FOLD_MARGIN  10
504 #define DEFAULT_FOLD 60
505
506 static int             fold_margin  = FOLD_MARGIN;
507
508 /* process default */
509
510 static nkf_char
511 no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
512 {
513     fprintf(stderr,"nkf internal module connection failure.\n");
514     exit(1);
515     return 0; /* LINT */
516 }
517
518 static void
519 no_connection(nkf_char c2, nkf_char c1)
520 {
521     no_connection2(c2,c1,0);
522 }
523
524 static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2;
525 static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection;
526
527 static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection;
528 static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection;
529 static void (*o_eol_conv)(nkf_char c2,nkf_char c1) = no_connection;
530 static void (*o_rot_conv)(nkf_char c2,nkf_char c1) = no_connection;
531 static void (*o_hira_conv)(nkf_char c2,nkf_char c1) = no_connection;
532 static void (*o_base64conv)(nkf_char c2,nkf_char c1) = no_connection;
533 static void (*o_iso2022jp_check_conv)(nkf_char c2,nkf_char c1) = no_connection;
534
535 /* static redirections */
536
537 static  void   (*o_putc)(nkf_char c) = std_putc;
538
539 static  nkf_char    (*i_getc)(FILE *f) = std_getc; /* general input */
540 static  nkf_char    (*i_ungetc)(nkf_char c,FILE *f) =std_ungetc;
541
542 static  nkf_char    (*i_bgetc)(FILE *) = std_getc; /* input of mgetc */
543 static  nkf_char    (*i_bungetc)(nkf_char c ,FILE *f) = std_ungetc;
544
545 static  void   (*o_mputc)(nkf_char c) = std_putc ; /* output of mputc */
546
547 static  nkf_char    (*i_mgetc)(FILE *) = std_getc; /* input of mgetc */
548 static  nkf_char    (*i_mungetc)(nkf_char c ,FILE *f) = std_ungetc;
549
550 /* for strict mime */
551 static  nkf_char    (*i_mgetc_buf)(FILE *) = std_getc; /* input of mgetc_buf */
552 static  nkf_char    (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc;
553
554 /* Global states */
555 static int output_mode = ASCII;    /* output kanji mode */
556 static int input_mode =  ASCII;    /* input kanji mode */
557 static int mime_decode_mode =   FALSE;    /* MIME mode B base64, Q hex */
558
559 /* X0201 / X0208 conversion tables */
560
561 /* X0201 kana conversion table */
562 /* 90-9F A0-DF */
563 static const unsigned char cv[]= {
564     0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
565     0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
566     0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
567     0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
568     0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
569     0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
570     0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
571     0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
572     0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
573     0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
574     0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
575     0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
576     0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
577     0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
578     0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
579     0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
580     0x00,0x00};
581
582
583 /* X0201 kana conversion table for daguten */
584 /* 90-9F A0-DF */
585 static const unsigned char dv[]= {
586     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
587     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
588     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
589     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
590     0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74,
591     0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
592     0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
593     0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
594     0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
595     0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
596     0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
597     0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
598     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
599     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
600     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
601     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
602     0x00,0x00};
603
604 /* X0201 kana conversion table for han-daguten */
605 /* 90-9F A0-DF */
606 static const unsigned char ev[]= {
607     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
608     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
609     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
610     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
611     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
612     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
613     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
614     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
615     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
616     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
617     0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
618     0x25,0x57,0x25,0x5a,0x25,0x5d,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,0x00,0x00,0x00,0x00,
623     0x00,0x00};
624
625
626 /* X0208 kigou conversion table */
627 /* 0x8140 - 0x819e */
628 static const unsigned char fv[] = {
629
630     0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
631     0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
632     0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
633     0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
634     0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
635     0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
636     0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
637     0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
638     0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
639     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
640     0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
641     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
642 } ;
643
644
645
646 static int option_mode = 0;
647 static int             file_out_f = FALSE;
648 #ifdef OVERWRITE
649 static int             overwrite_f = FALSE;
650 static int             preserve_time_f = FALSE;
651 static int             backup_f = FALSE;
652 static char            *backup_suffix = "";
653 #endif
654
655 static int eolmode_f = 0;   /* CR, LF, CRLF */
656 static int input_eol = 0; /* 0: unestablished, EOF: MIXED */
657 static nkf_char prev_cr = 0; /* CR or 0 */
658 #ifdef EASYWIN /*Easy Win */
659 static int             end_check;
660 #endif /*Easy Win */
661
662 #define STD_GC_BUFSIZE (256)
663 nkf_char std_gc_buf[STD_GC_BUFSIZE];
664 nkf_char std_gc_ndx;
665
666 static int
667 nkf_str_caseeql(const char *src, const char *target)
668 {
669     int i;
670     for (i = 0; src[i] && target[i]; i++) {
671         if (nkf_toupper(src[i]) != nkf_toupper(target[i])) return FALSE;
672     }
673     if (src[i] || target[i]) return FALSE;
674     else return TRUE;
675 }
676
677 static nkf_encoding*
678 nkf_enc_from_index(int idx)
679 {
680     if (idx < 0 || NKF_ENCODING_TABLE_SIZE <= idx) {
681         return 0;
682     }
683     return &nkf_encoding_table[idx];
684 }
685
686 static int
687 nkf_enc_find_index(const char *name)
688 {
689     int i;
690     if (name[0] == 'X' && *(name+1) == '-') name += 2;
691     for (i = 0; encoding_name_to_id_table[i].id >= 0; i++) {
692         if (nkf_str_caseeql(encoding_name_to_id_table[i].name, name)) {
693             return encoding_name_to_id_table[i].id;
694         }
695     }
696     return -1;
697 }
698
699 static nkf_encoding*
700 nkf_enc_find(const char *name)
701 {
702     int idx = -1;
703     idx = nkf_enc_find_index(name);
704     if (idx < 0) return 0;
705     return nkf_enc_from_index(idx);
706 }
707
708 #define nkf_enc_name(enc) (enc)->name
709 #define nkf_enc_to_index(enc) (enc)->id
710 #define nkf_enc_to_base_encoding(enc) (enc)->base_encoding
711 #define nkf_enc_to_iconv(enc) nkf_enc_to_base_encoding(enc)->iconv
712 #define nkf_enc_to_oconv(enc) nkf_enc_to_base_encoding(enc)->oconv
713 #define nkf_enc_asciicompat(enc) (\
714                                   nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\
715                                   nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP)
716 #define nkf_enc_unicode_p(enc) (\
717                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\
718                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\
719                                 nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32)
720 #define nkf_enc_cp5022x_p(enc) (\
721                                 nkf_enc_to_index(enc) == CP50220 ||\
722                                 nkf_enc_to_index(enc) == CP50221 ||\
723                                 nkf_enc_to_index(enc) == CP50222)
724
725 #ifdef DEFAULT_CODE_LOCALE
726 static char*
727 nkf_locale_charmap()
728 {
729 #ifdef HAVE_LANGINFO_H
730     return nl_langinfo(CODESET);
731 #elif defined(__WIN32__)
732     char buf[16];
733     char *str;
734     int len = sprintf(buf, "CP%d", GetACP());
735     if (len > 0) {
736       str = malloc(len + 1);
737       strcpy(str, buf);
738       str[len] = '\0';
739       return str;
740     }
741     else return NULL;
742 #elif defined(__OS2__)
743 # if defined(INT_IS_SHORT)
744     /* OS/2 1.x */
745     return NULL;
746 # else
747     /* OS/2 32bit */
748     static char buf[16];
749     ULONG ulCP[1], ulncp;
750     DosQueryCp(sizeof(ulCP), ulCP, &ulncp);
751     if (ulCP[0] == 932 || ulCP[0] == 943)
752         strcpy(buf, "Shift_JIS");
753     else
754         sprintf(buf, "CP%lu", ulCP[0]);
755     return buf;
756 # endif
757 #else
758     return NULL;
759 #endif
760 }
761
762 static nkf_encoding*
763 nkf_locale_encoding()
764 {
765     nkf_encoding *enc = 0;
766     char *encname = nkf_locale_charmap();
767     if (encname)
768         enc = nkf_enc_find(encname);
769     return enc;
770 }
771 #endif /* DEFAULT_CODE_LOCALE */
772
773 static nkf_encoding*
774 nkf_utf8_encoding()
775 {
776     return &nkf_encoding_table[UTF_8];
777 }
778
779 static nkf_encoding*
780 nkf_default_encoding()
781 {
782     nkf_encoding *enc = 0;
783 #ifdef DEFAULT_CODE_LOCALE
784     enc = nkf_locale_encoding();
785 #elif defined(DEFAULT_ENCIDX)
786     enc = nkf_enc_from_index(DEFAULT_ENCIDX);
787 #endif
788     if (!enc) enc = nkf_utf8_encoding();
789     return enc;
790 }
791
792 #ifndef PERL_XS
793 #ifdef WIN32DLL
794 #define fprintf dllprintf
795 #endif
796
797 static void
798 version(void)
799 {
800     fprintf(HELP_OUTPUT,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n");
801 }
802
803 static void
804 usage(void)
805 {
806     fprintf(HELP_OUTPUT,
807             "USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n"
808             "Flags:\n"
809             "b,u      Output is buffered (DEFAULT),Output is unbuffered\n"
810             "j,s,e,w  Output code is ISO-2022-JP, Shift JIS, EUC-JP, UTF-8N\n"
811 #ifdef UTF8_OUTPUT_ENABLE
812             "         After 'w' you can add more options. -w[ 8 [0], 16 [[BL] [0]] ]\n"
813 #endif
814             "J,S,E,W  Input assumption is JIS 7 bit , Shift JIS, EUC-JP, UTF-8\n"
815 #ifdef UTF8_INPUT_ENABLE
816             "         After 'W' you can add more options. -W[ 8, 16 [BL] ] \n"
817 #endif
818             "t        no conversion\n"
819             "i[@B]    Specify the Esc Seq for JIS X 0208-1978/83 (DEFAULT B)\n"
820             "o[BJH]   Specify the Esc Seq for ASCII/Roman        (DEFAULT B)\n"
821             "r        {de/en}crypt ROT13/47\n"
822             "h        1 katakana->hiragana, 2 hiragana->katakana, 3 both\n"
823             "m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:non-strict,0:no decode]\n"
824             "M[BQ]    MIME encode [B:base64 Q:quoted]\n"
825             "l        ISO8859-1 (Latin-1) support\n"
826             "f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n"
827             "Z[0-4]   Default/0: Convert JISX0208 Alphabet to ASCII\n"
828             "         1: Kankaku to one space  2: to two spaces  3: HTML Entity\n"
829             "         4: JISX0208 Katakana to JISX0201 Katakana\n"
830             "X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n"
831             "B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n"
832 #ifdef MSDOS
833             "T        Text mode output\n"
834 #endif
835             "O        Output to File (DEFAULT 'nkf.out')\n"
836             "I        Convert non ISO-2022-JP charactor to GETA\n"
837             "d,c      Convert line breaks  -d: LF  -c: CRLF\n"
838             "-L[uwm]  line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n"
839             "v, V     Show this usage. V: show configuration\n"
840             "\n"
841             "Long name options\n"
842             " --ic=<input codeset>  --oc=<output codeset>\n"
843             "                   Specify the input or output codeset\n"
844             " --fj  --unix --mac  --windows\n"
845             " --jis  --euc  --sjis  --utf8  --utf16  --mime  --base64\n"
846             "                   Convert for the system or code\n"
847             " --hiragana  --katakana  --katakana-hiragana\n"
848             "                   To Hiragana/Katakana Conversion\n"
849             " --prefix=         Insert escape before troublesome characters of Shift_JIS\n"
850 #ifdef INPUT_OPTION
851             " --cap-input, --url-input  Convert hex after ':' or '%%'\n"
852 #endif
853 #ifdef NUMCHAR_OPTION
854             " --numchar-input   Convert Unicode Character Reference\n"
855 #endif
856 #ifdef UTF8_INPUT_ENABLE
857             " --fb-{skip, html, xml, perl, java, subchar}\n"
858             "                   Specify how nkf handles unassigned characters\n"
859 #endif
860 #ifdef OVERWRITE
861             " --in-place[=SUFFIX]  --overwrite[=SUFFIX]\n"
862             "                   Overwrite original listed files by filtered result\n"
863             "                   --overwrite preserves timestamp of original files\n"
864 #endif
865             " -g  --guess       Guess the input code\n"
866             " --help  --version Show this help/the version\n"
867             "                   For more information, see also man nkf\n"
868             "\n");
869     version();
870 }
871
872 static void
873 show_configuration(void)
874 {
875     fprintf(HELP_OUTPUT,
876             "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n"
877             "  nkf identity:\n"
878             "    " NKF_IDENT "\n"
879             "  Compile-time options:\n"
880             "    Compiled at:                 " __DATE__ " " __TIME__ "\n"
881            );
882     fprintf(HELP_OUTPUT,
883             "    Default output encoding:     "
884 #ifdef DEFAULT_CODE_LOCALE
885             "LOCALE (%s)\n", nkf_enc_name(nkf_default_encoding())
886 #elif defined(DEFAULT_ENCIDX)
887             "CONFIG (%s)\n", nkf_enc_name(nkf_default_encoding())
888 #else
889             "NONE\n"
890 #endif
891            );
892     fprintf(HELP_OUTPUT,
893             "    Default output end of line:  "
894 #if DEFAULT_NEWLINE == CR
895             "CR"
896 #elif DEFAULT_NEWLINE == CRLF
897             "CRLF"
898 #else
899             "LF"
900 #endif
901             "\n"
902             "    Decode MIME encoded string:  "
903 #if MIME_DECODE_DEFAULT
904             "ON"
905 #else
906             "OFF"
907 #endif
908             "\n"
909             "    Convert JIS X 0201 Katakana: "
910 #if X0201_DEFAULT
911             "ON"
912 #else
913             "OFF"
914 #endif
915             "\n"
916             "    --help, --version output:    "
917 #if HELP_OUTPUT_HELP_OUTPUT
918             "HELP_OUTPUT"
919 #else
920             "STDOUT"
921 #endif
922             "\n");
923 }
924 #endif /*PERL_XS*/
925
926 #ifdef OVERWRITE
927 static char*
928 get_backup_filename(const char *suffix, const char *filename)
929 {
930     char *backup_filename;
931     int asterisk_count = 0;
932     int i, j;
933     int filename_length = strlen(filename);
934
935     for(i = 0; suffix[i]; i++){
936         if(suffix[i] == '*') asterisk_count++;
937     }
938
939     if(asterisk_count){
940         backup_filename = malloc(strlen(suffix) + (asterisk_count * (filename_length - 1)) + 1);
941         if (!backup_filename){
942             perror("Can't malloc backup filename.");
943             return NULL;
944         }
945
946         for(i = 0, j = 0; suffix[i];){
947             if(suffix[i] == '*'){
948                 backup_filename[j] = '\0';
949                 strncat(backup_filename, filename, filename_length);
950                 i++;
951                 j += filename_length;
952             }else{
953                 backup_filename[j++] = suffix[i++];
954             }
955         }
956         backup_filename[j] = '\0';
957     }else{
958         j = filename_length + strlen(suffix);
959         backup_filename = malloc(j + 1);
960         strcpy(backup_filename, filename);
961         strcat(backup_filename, suffix);
962         backup_filename[j] = '\0';
963     }
964     return backup_filename;
965 }
966 #endif
967
968 #ifdef UTF8_INPUT_ENABLE
969 static void
970 nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
971 {
972     int shift = 20;
973     c &= VALUE_MASK;
974     while(shift >= 0){
975         if(c >= 1<<shift){
976             while(shift >= 0){
977                 (*f)(0, bin2hex(c>>shift));
978                 shift -= 4;
979             }
980         }else{
981             shift -= 4;
982         }
983     }
984     return;
985 }
986
987 static void
988 encode_fallback_html(nkf_char c)
989 {
990     (*oconv)(0, '&');
991     (*oconv)(0, '#');
992     c &= VALUE_MASK;
993     if(c >= NKF_INT32_C(1000000))
994         (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10);
995     if(c >= NKF_INT32_C(100000))
996         (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10);
997     if(c >= 10000)
998         (*oconv)(0, 0x30+(c/10000  )%10);
999     if(c >= 1000)
1000         (*oconv)(0, 0x30+(c/1000   )%10);
1001     if(c >= 100)
1002         (*oconv)(0, 0x30+(c/100    )%10);
1003     if(c >= 10)
1004         (*oconv)(0, 0x30+(c/10     )%10);
1005     if(c >= 0)
1006         (*oconv)(0, 0x30+ c         %10);
1007     (*oconv)(0, ';');
1008     return;
1009 }
1010
1011 static void
1012 encode_fallback_xml(nkf_char c)
1013 {
1014     (*oconv)(0, '&');
1015     (*oconv)(0, '#');
1016     (*oconv)(0, 'x');
1017     nkf_each_char_to_hex(oconv, c);
1018     (*oconv)(0, ';');
1019     return;
1020 }
1021
1022 static void
1023 encode_fallback_java(nkf_char c)
1024 {
1025     (*oconv)(0, '\\');
1026     c &= VALUE_MASK;
1027     if(!nkf_char_unicode_bmp_p(c)){
1028         (*oconv)(0, 'U');
1029         (*oconv)(0, '0');
1030         (*oconv)(0, '0');
1031         (*oconv)(0, bin2hex(c>>20));
1032         (*oconv)(0, bin2hex(c>>16));
1033     }else{
1034         (*oconv)(0, 'u');
1035     }
1036     (*oconv)(0, bin2hex(c>>12));
1037     (*oconv)(0, bin2hex(c>> 8));
1038     (*oconv)(0, bin2hex(c>> 4));
1039     (*oconv)(0, bin2hex(c    ));
1040     return;
1041 }
1042
1043 static void
1044 encode_fallback_perl(nkf_char c)
1045 {
1046     (*oconv)(0, '\\');
1047     (*oconv)(0, 'x');
1048     (*oconv)(0, '{');
1049     nkf_each_char_to_hex(oconv, c);
1050     (*oconv)(0, '}');
1051     return;
1052 }
1053
1054 static void
1055 encode_fallback_subchar(nkf_char c)
1056 {
1057     c = unicode_subchar;
1058     (*oconv)((c>>8)&0xFF, c&0xFF);
1059     return;
1060 }
1061 #endif
1062
1063 static const struct {
1064     const char *name;
1065     const char *alias;
1066 } long_option[] = {
1067     {"ic=", ""},
1068     {"oc=", ""},
1069     {"base64","jMB"},
1070     {"euc","e"},
1071     {"euc-input","E"},
1072     {"fj","jm"},
1073     {"help","v"},
1074     {"jis","j"},
1075     {"jis-input","J"},
1076     {"mac","sLm"},
1077     {"mime","jM"},
1078     {"mime-input","m"},
1079     {"msdos","sLw"},
1080     {"sjis","s"},
1081     {"sjis-input","S"},
1082     {"unix","eLu"},
1083     {"version","V"},
1084     {"windows","sLw"},
1085     {"hiragana","h1"},
1086     {"katakana","h2"},
1087     {"katakana-hiragana","h3"},
1088     {"guess=", ""},
1089     {"guess", "g2"},
1090     {"cp932", ""},
1091     {"no-cp932", ""},
1092 #ifdef X0212_ENABLE
1093     {"x0212", ""},
1094 #endif
1095 #ifdef UTF8_OUTPUT_ENABLE
1096     {"utf8", "w"},
1097     {"utf16", "w16"},
1098     {"ms-ucs-map", ""},
1099     {"fb-skip", ""},
1100     {"fb-html", ""},
1101     {"fb-xml", ""},
1102     {"fb-perl", ""},
1103     {"fb-java", ""},
1104     {"fb-subchar", ""},
1105     {"fb-subchar=", ""},
1106 #endif
1107 #ifdef UTF8_INPUT_ENABLE
1108     {"utf8-input", "W"},
1109     {"utf16-input", "W16"},
1110     {"no-cp932ext", ""},
1111     {"no-best-fit-chars",""},
1112 #endif
1113 #ifdef UNICODE_NORMALIZATION
1114     {"utf8mac-input", ""},
1115 #endif
1116 #ifdef OVERWRITE
1117     {"overwrite", ""},
1118     {"overwrite=", ""},
1119     {"in-place", ""},
1120     {"in-place=", ""},
1121 #endif
1122 #ifdef INPUT_OPTION
1123     {"cap-input", ""},
1124     {"url-input", ""},
1125 #endif
1126 #ifdef NUMCHAR_OPTION
1127     {"numchar-input", ""},
1128 #endif
1129 #ifdef CHECK_OPTION
1130     {"no-output", ""},
1131     {"debug", ""},
1132 #endif
1133 #ifdef SHIFTJIS_CP932
1134     {"cp932inv", ""},
1135 #endif
1136 #ifdef EXEC_IO
1137     {"exec-in", ""},
1138     {"exec-out", ""},
1139 #endif
1140     {"prefix=", ""},
1141 };
1142
1143 static void
1144 set_input_encoding(nkf_encoding *enc)
1145 {
1146     switch (nkf_enc_to_index(enc)) {
1147     case ISO_8859_1:
1148         iso8859_f = TRUE;
1149         break;
1150     case CP50220:
1151     case CP50221:
1152     case CP50222:
1153 #ifdef SHIFTJIS_CP932
1154         cp51932_f = TRUE;
1155 #endif
1156 #ifdef UTF8_OUTPUT_ENABLE
1157         ms_ucs_map_f = UCS_MAP_CP932;
1158 #endif
1159         break;
1160     case ISO_2022_JP_1:
1161         x0212_f = TRUE;
1162         break;
1163     case ISO_2022_JP_3:
1164         x0212_f = TRUE;
1165         x0213_f = TRUE;
1166         break;
1167     case ISO_2022_JP_2004:
1168         x0212_f = TRUE;
1169         x0213_f = TRUE;
1170         break;
1171     case SHIFT_JIS:
1172         break;
1173     case WINDOWS_31J:
1174 #ifdef SHIFTJIS_CP932
1175         cp51932_f = TRUE;
1176 #endif
1177 #ifdef UTF8_OUTPUT_ENABLE
1178         ms_ucs_map_f = UCS_MAP_CP932;
1179 #endif
1180         break;
1181         break;
1182     case CP10001:
1183 #ifdef SHIFTJIS_CP932
1184         cp51932_f = TRUE;
1185 #endif
1186 #ifdef UTF8_OUTPUT_ENABLE
1187         ms_ucs_map_f = UCS_MAP_CP10001;
1188 #endif
1189         break;
1190     case EUC_JP:
1191         break;
1192     case EUCJP_NKF:
1193         break;
1194     case CP51932:
1195 #ifdef SHIFTJIS_CP932
1196         cp51932_f = TRUE;
1197 #endif
1198 #ifdef UTF8_OUTPUT_ENABLE
1199         ms_ucs_map_f = UCS_MAP_CP932;
1200 #endif
1201         break;
1202     case EUCJP_MS:
1203 #ifdef SHIFTJIS_CP932
1204         cp51932_f = FALSE;
1205 #endif
1206 #ifdef UTF8_OUTPUT_ENABLE
1207         ms_ucs_map_f = UCS_MAP_MS;
1208 #endif
1209         break;
1210     case EUCJP_ASCII:
1211 #ifdef SHIFTJIS_CP932
1212         cp51932_f = FALSE;
1213 #endif
1214 #ifdef UTF8_OUTPUT_ENABLE
1215         ms_ucs_map_f = UCS_MAP_ASCII;
1216 #endif
1217         break;
1218     case SHIFT_JISX0213:
1219     case SHIFT_JIS_2004:
1220         x0213_f = TRUE;
1221 #ifdef SHIFTJIS_CP932
1222         cp51932_f = FALSE;
1223 #endif
1224         break;
1225     case EUC_JISX0213:
1226     case EUC_JIS_2004:
1227         x0213_f = TRUE;
1228 #ifdef SHIFTJIS_CP932
1229         cp51932_f = FALSE;
1230 #endif
1231         break;
1232 #ifdef UTF8_INPUT_ENABLE
1233 #ifdef UNICODE_NORMALIZATION
1234     case UTF8_MAC:
1235         nfc_f = TRUE;
1236         break;
1237 #endif
1238     case UTF_16:
1239     case UTF_16BE:
1240     case UTF_16BE_BOM:
1241         input_endian = ENDIAN_BIG;
1242         break;
1243     case UTF_16LE:
1244     case UTF_16LE_BOM:
1245         input_endian = ENDIAN_LITTLE;
1246         break;
1247     case UTF_32:
1248     case UTF_32BE:
1249     case UTF_32BE_BOM:
1250         input_endian = ENDIAN_BIG;
1251         break;
1252     case UTF_32LE:
1253     case UTF_32LE_BOM:
1254         input_endian = ENDIAN_LITTLE;
1255         break;
1256 #endif
1257     }
1258 }
1259
1260 static void
1261 set_output_encoding(nkf_encoding *enc)
1262 {
1263     switch (nkf_enc_to_index(enc)) {
1264     case CP50220:
1265         x0201_f = TRUE;
1266 #ifdef SHIFTJIS_CP932
1267         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1268 #endif
1269 #ifdef UTF8_OUTPUT_ENABLE
1270         ms_ucs_map_f = UCS_MAP_CP932;
1271 #endif
1272         break;
1273     case CP50221:
1274 #ifdef SHIFTJIS_CP932
1275         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1276 #endif
1277 #ifdef UTF8_OUTPUT_ENABLE
1278         ms_ucs_map_f = UCS_MAP_CP932;
1279 #endif
1280         break;
1281     case ISO_2022_JP_1:
1282         x0212_f = TRUE;
1283 #ifdef SHIFTJIS_CP932
1284         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1285 #endif
1286         break;
1287     case ISO_2022_JP_3:
1288         x0212_f = TRUE;
1289         x0213_f = TRUE;
1290 #ifdef SHIFTJIS_CP932
1291         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1292 #endif
1293         break;
1294     case SHIFT_JIS:
1295         break;
1296     case WINDOWS_31J:
1297 #ifdef UTF8_OUTPUT_ENABLE
1298         ms_ucs_map_f = UCS_MAP_CP932;
1299 #endif
1300         break;
1301     case CP10001:
1302 #ifdef UTF8_OUTPUT_ENABLE
1303         ms_ucs_map_f = UCS_MAP_CP10001;
1304 #endif
1305         break;
1306     case EUC_JP:
1307         x0212_f = TRUE;
1308 #ifdef SHIFTJIS_CP932
1309         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1310 #endif
1311 #ifdef UTF8_OUTPUT_ENABLE
1312         ms_ucs_map_f = UCS_MAP_ASCII;
1313 #endif
1314         break;
1315     case EUCJP_NKF:
1316         x0212_f = FALSE;
1317 #ifdef SHIFTJIS_CP932
1318         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1319 #endif
1320 #ifdef UTF8_OUTPUT_ENABLE
1321         ms_ucs_map_f = UCS_MAP_ASCII;
1322 #endif
1323         break;
1324     case CP51932:
1325 #ifdef SHIFTJIS_CP932
1326         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1327 #endif
1328 #ifdef UTF8_OUTPUT_ENABLE
1329         ms_ucs_map_f = UCS_MAP_CP932;
1330 #endif
1331         break;
1332     case EUCJP_MS:
1333         x0212_f = TRUE;
1334 #ifdef UTF8_OUTPUT_ENABLE
1335         ms_ucs_map_f = UCS_MAP_MS;
1336 #endif
1337         break;
1338     case EUCJP_ASCII:
1339         x0212_f = TRUE;
1340 #ifdef UTF8_OUTPUT_ENABLE
1341         ms_ucs_map_f = UCS_MAP_ASCII;
1342 #endif
1343         break;
1344     case SHIFT_JISX0213:
1345     case SHIFT_JIS_2004:
1346         x0213_f = TRUE;
1347 #ifdef SHIFTJIS_CP932
1348         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1349 #endif
1350         break;
1351     case EUC_JISX0213:
1352     case EUC_JIS_2004:
1353         x0212_f = TRUE;
1354         x0213_f = TRUE;
1355 #ifdef SHIFTJIS_CP932
1356         if (cp932inv_f == TRUE) cp932inv_f = FALSE;
1357 #endif
1358         break;
1359 #ifdef UTF8_OUTPUT_ENABLE
1360     case UTF_8_BOM:
1361         output_bom_f = TRUE;
1362         break;
1363     case UTF_16:
1364     case UTF_16BE_BOM:
1365         output_bom_f = TRUE;
1366         break;
1367     case UTF_16LE:
1368         output_endian = ENDIAN_LITTLE;
1369         output_bom_f = FALSE;
1370         break;
1371     case UTF_16LE_BOM:
1372         output_endian = ENDIAN_LITTLE;
1373         output_bom_f = TRUE;
1374         break;
1375     case UTF_32BE_BOM:
1376         output_bom_f = TRUE;
1377         break;
1378     case UTF_32LE:
1379         output_endian = ENDIAN_LITTLE;
1380         output_bom_f = FALSE;
1381         break;
1382     case UTF_32LE_BOM:
1383         output_endian = ENDIAN_LITTLE;
1384         output_bom_f = TRUE;
1385         break;
1386 #endif
1387     }
1388 }
1389
1390 static struct input_code*
1391 find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
1392 {
1393     if (iconv_func){
1394         struct input_code *p = input_code_list;
1395         while (p->name){
1396             if (iconv_func == p->iconv_func){
1397                 return p;
1398             }
1399             p++;
1400         }
1401     }
1402     return 0;
1403 }
1404
1405 static void
1406 set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
1407 {
1408 #ifdef INPUT_CODE_FIX
1409     if (f || !input_encoding)
1410 #endif
1411         if (estab_f != f){
1412             estab_f = f;
1413         }
1414
1415     if (iconv_func
1416 #ifdef INPUT_CODE_FIX
1417         && (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */
1418 #endif
1419        ){
1420         iconv = iconv_func;
1421     }
1422 #ifdef CHECK_OPTION
1423     if (estab_f && iconv_for_check != iconv){
1424         struct input_code *p = find_inputcode_byfunc(iconv);
1425         if (p){
1426             set_input_codename(p->name);
1427             debug(p->name);
1428         }
1429         iconv_for_check = iconv;
1430     }
1431 #endif
1432 }
1433
1434 #ifdef X0212_ENABLE
1435 static nkf_char
1436 x0212_shift(nkf_char c)
1437 {
1438     nkf_char ret = c;
1439     c &= 0x7f;
1440     if (is_eucg3(ret)){
1441         if (0x75 <= c && c <= 0x7f){
1442             ret = c + (0x109 - 0x75);
1443         }
1444     }else{
1445         if (0x75 <= c && c <= 0x7f){
1446             ret = c + (0x113 - 0x75);
1447         }
1448     }
1449     return ret;
1450 }
1451
1452
1453 static nkf_char
1454 x0212_unshift(nkf_char c)
1455 {
1456     nkf_char ret = c;
1457     if (0x7f <= c && c <= 0x88){
1458         ret = c + (0x75 - 0x7f);
1459     }else if (0x89 <= c && c <= 0x92){
1460         ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
1461     }
1462     return ret;
1463 }
1464 #endif /* X0212_ENABLE */
1465
1466 static nkf_char
1467 e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
1468 {
1469     nkf_char ndx;
1470     if (is_eucg3(c2)){
1471         ndx = c2 & 0x7f;
1472         if (x0213_f){
1473             if((0x21 <= ndx && ndx <= 0x2F)){
1474                 if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3;
1475                 if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1476                 return 0;
1477             }else if(0x6E <= ndx && ndx <= 0x7E){
1478                 if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe;
1479                 if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1480                 return 0;
1481             }
1482             return 1;
1483         }
1484 #ifdef X0212_ENABLE
1485         else if(nkf_isgraph(ndx)){
1486             nkf_char val = 0;
1487             const unsigned short *ptr;
1488             ptr = x0212_shiftjis[ndx - 0x21];
1489             if (ptr){
1490                 val = ptr[(c1 & 0x7f) - 0x21];
1491             }
1492             if (val){
1493                 c2 = val >> 8;
1494                 c1 = val & 0xff;
1495                 if (p2) *p2 = c2;
1496                 if (p1) *p1 = c1;
1497                 return 0;
1498             }
1499             c2 = x0212_shift(c2);
1500         }
1501 #endif /* X0212_ENABLE */
1502     }
1503     if(0x7F < c2) return 1;
1504     if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
1505     if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
1506     return 0;
1507 }
1508
1509 static nkf_char
1510 s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
1511 {
1512 #if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
1513     nkf_char val;
1514 #endif
1515     static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
1516     if (0xFC < c1) return 1;
1517 #ifdef SHIFTJIS_CP932
1518     if (!cp932inv_f && is_ibmext_in_sjis(c2)){
1519         val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
1520         if (val){
1521             c2 = val >> 8;
1522             c1 = val & 0xff;
1523         }
1524     }
1525     if (cp932inv_f
1526         && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
1527         val = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
1528         if (val){
1529             c2 = val >> 8;
1530             c1 = val & 0xff;
1531         }
1532     }
1533 #endif /* SHIFTJIS_CP932 */
1534 #ifdef X0212_ENABLE
1535     if (!x0213_f && is_ibmext_in_sjis(c2)){
1536         val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
1537         if (val){
1538             if (val > 0x7FFF){
1539                 c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f);
1540                 c1 = val & 0xff;
1541             }else{
1542                 c2 = val >> 8;
1543                 c1 = val & 0xff;
1544             }
1545             if (p2) *p2 = c2;
1546             if (p1) *p1 = c1;
1547             return 0;
1548         }
1549     }
1550 #endif
1551     if(c2 >= 0x80){
1552         if(x0213_f && c2 >= 0xF0){
1553             if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */
1554                 c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1];
1555             }else{ /* 78<=k<=94 */
1556                 c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B);
1557                 if (0x9E < c1) c2++;
1558             }
1559         }else{
1560 #define         SJ0162  0x00e1          /* 01 - 62 ku offset */
1561 #define         SJ6394  0x0161          /* 63 - 94 ku offset */
1562             c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394);
1563             if (0x9E < c1) c2++;
1564         }
1565         if (c1 < 0x9F)
1566             c1 = c1 - ((c1 > DEL) ? SP : 0x1F);
1567         else {
1568             c1 = c1 - 0x7E;
1569         }
1570     }
1571
1572 #ifdef X0212_ENABLE
1573     c2 = x0212_unshift(c2);
1574 #endif
1575     if (p2) *p2 = c2;
1576     if (p1) *p1 = c1;
1577     return 0;
1578 }
1579
1580 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
1581 static void
1582 nkf_unicode_to_utf8(nkf_char val, nkf_char *p1, nkf_char *p2, nkf_char *p3, nkf_char *p4)
1583 {
1584     val &= VALUE_MASK;
1585     if (val < 0x80){
1586         *p1 = val;
1587         *p2 = 0;
1588         *p3 = 0;
1589         *p4 = 0;
1590     }else if (val < 0x800){
1591         *p1 = 0xc0 | (val >> 6);
1592         *p2 = 0x80 | (val & 0x3f);
1593         *p3 = 0;
1594         *p4 = 0;
1595     } else if (nkf_char_unicode_bmp_p(val)) {
1596         *p1 = 0xe0 |  (val >> 12);
1597         *p2 = 0x80 | ((val >>  6) & 0x3f);
1598         *p3 = 0x80 | ( val        & 0x3f);
1599         *p4 = 0;
1600     } else if (nkf_char_unicode_value_p(val)) {
1601         *p1 = 0xe0 |  (val >> 16);
1602         *p2 = 0x80 | ((val >> 12) & 0x3f);
1603         *p3 = 0x80 | ((val >>  6) & 0x3f);
1604         *p4 = 0x80 | ( val        & 0x3f);
1605     } else {
1606         *p1 = 0;
1607         *p2 = 0;
1608         *p3 = 0;
1609         *p4 = 0;
1610     }
1611 }
1612
1613 static nkf_char
1614 nkf_utf8_to_unicode(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
1615 {
1616     nkf_char wc;
1617     if (c1 <= 0x7F) {
1618         /* single byte */
1619         wc = c1;
1620     }
1621     else if (c1 <= 0xC3) {
1622         /* trail byte or invalid */
1623         return -1;
1624     }
1625     else if (c1 <= 0xDF) {
1626         /* 2 bytes */
1627         wc  = (c1 & 0x1F) << 6;
1628         wc |= (c2 & 0x3F);
1629     }
1630     else if (c1 <= 0xEF) {
1631         /* 3 bytes */
1632         wc  = (c1 & 0x0F) << 12;
1633         wc |= (c2 & 0x3F) << 6;
1634         wc |= (c3 & 0x3F);
1635     }
1636     else if (c2 <= 0xF4) {
1637         /* 4 bytes */
1638         wc  = (c1 & 0x0F) << 18;
1639         wc |= (c2 & 0x3F) << 12;
1640         wc |= (c3 & 0x3F) << 6;
1641         wc |= (c4 & 0x3F);
1642     }
1643     else {
1644         return -1;
1645     }
1646     return wc;
1647 }
1648 #endif
1649
1650 #ifdef UTF8_INPUT_ENABLE
1651 static int
1652 unicode_to_jis_common2(nkf_char c1, nkf_char c0,
1653                        const unsigned short *const *pp, nkf_char psize,
1654                        nkf_char *p2, nkf_char *p1)
1655 {
1656     nkf_char c2;
1657     const unsigned short *p;
1658     unsigned short val;
1659
1660     if (pp == 0) return 1;
1661
1662     c1 -= 0x80;
1663     if (c1 < 0 || psize <= c1) return 1;
1664     p = pp[c1];
1665     if (p == 0)  return 1;
1666
1667     c0 -= 0x80;
1668     if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1;
1669     val = p[c0];
1670     if (val == 0) return 1;
1671     if (no_cp932ext_f && (
1672                           (val>>8) == 0x2D || /* NEC special characters */
1673                           val > NKF_INT32_C(0xF300) /* IBM extended characters */
1674                          )) return 1;
1675
1676     c2 = val >> 8;
1677     if (val > 0x7FFF){
1678         c2 &= 0x7f;
1679         c2 |= PREFIX_EUCG3;
1680     }
1681     if (c2 == SO) c2 = JIS_X_0201_1976_K;
1682     c1 = val & 0xFF;
1683     if (p2) *p2 = c2;
1684     if (p1) *p1 = c1;
1685     return 0;
1686 }
1687
1688 static int
1689 unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
1690 {
1691     const unsigned short *const *pp;
1692     const unsigned short *const *const *ppp;
1693     static const char no_best_fit_chars_table_C2[] =
1694     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1695         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1696         1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2,
1697         0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1};
1698     static const char no_best_fit_chars_table_C2_ms[] =
1699     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1700         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1701         1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,
1702         0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0};
1703     static const char no_best_fit_chars_table_932_C2[] =
1704     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1705         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1706         1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1707         0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0};
1708     static const char no_best_fit_chars_table_932_C3[] =
1709     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1710         1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1711         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1712         1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1};
1713     nkf_char ret = 0;
1714
1715     if(c2 < 0x80){
1716         *p2 = 0;
1717         *p1 = c2;
1718     }else if(c2 < 0xe0){
1719         if(no_best_fit_chars_f){
1720             if(ms_ucs_map_f == UCS_MAP_CP932){
1721                 switch(c2){
1722                 case 0xC2:
1723                     if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1;
1724                     break;
1725                 case 0xC3:
1726                     if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
1727                     break;
1728                 }
1729             }else if(!cp932inv_f){
1730                 switch(c2){
1731                 case 0xC2:
1732                     if(no_best_fit_chars_table_C2[c1&0x3F]) return 1;
1733                     break;
1734                 case 0xC3:
1735                     if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
1736                     break;
1737                 }
1738             }else if(ms_ucs_map_f == UCS_MAP_MS){
1739                 if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1;
1740             }else if(ms_ucs_map_f == UCS_MAP_CP10001){
1741                 switch(c2){
1742                 case 0xC2:
1743                     switch(c1){
1744                     case 0xA2:
1745                     case 0xA3:
1746                     case 0xA5:
1747                     case 0xA6:
1748                     case 0xAC:
1749                     case 0xAF:
1750                     case 0xB8:
1751                         return 1;
1752                     }
1753                     break;
1754                 }
1755             }
1756         }
1757         pp =
1758             ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 :
1759             ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms :
1760             ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_2bytes_mac :
1761             utf8_to_euc_2bytes;
1762         ret =  unicode_to_jis_common2(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
1763     }else if(c0 < 0xF0){
1764         if(no_best_fit_chars_f){
1765             if(ms_ucs_map_f == UCS_MAP_CP932){
1766                 if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1;
1767             }else if(ms_ucs_map_f == UCS_MAP_MS){
1768                 switch(c2){
1769                 case 0xE2:
1770                     switch(c1){
1771                     case 0x80:
1772                         if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1;
1773                         break;
1774                     case 0x88:
1775                         if(c0 == 0x92) return 1;
1776                         break;
1777                     }
1778                     break;
1779                 case 0xE3:
1780                     if(c1 == 0x80 || c0 == 0x9C) return 1;
1781                     break;
1782                 }
1783             }else if(ms_ucs_map_f == UCS_MAP_CP10001){
1784                 switch(c2){
1785                 case 0xE3:
1786                     switch(c1){
1787                     case 0x82:
1788                         if(c0 == 0x94) return 1;
1789                         break;
1790                     case 0x83:
1791                         if(c0 == 0xBB) return 1;
1792                         break;
1793                     }
1794                     break;
1795                 }
1796             }else{
1797                 switch(c2){
1798                 case 0xE2:
1799                     switch(c1){
1800                     case 0x80:
1801                         if(c0 == 0x95) return 1;
1802                         break;
1803                     case 0x88:
1804                         if(c0 == 0xA5) return 1;
1805                         break;
1806                     }
1807                     break;
1808                 case 0xEF:
1809                     switch(c1){
1810                     case 0xBC:
1811                         if(c0 == 0x8D) return 1;
1812                         break;
1813                     case 0xBD:
1814                         if(c0 == 0x9E && !cp932inv_f) return 1;
1815                         break;
1816                     case 0xBF:
1817                         if(0xA0 <= c0 && c0 <= 0xA5) return 1;
1818                         break;
1819                     }
1820                     break;
1821                 }
1822             }
1823         }
1824         ppp =
1825             ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 :
1826             ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms :
1827             ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_3bytes_mac :
1828             utf8_to_euc_3bytes;
1829         ret = unicode_to_jis_common2(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
1830     }else return -1;
1831 #ifdef SHIFTJIS_CP932
1832     if (!ret && !cp932inv_f && is_eucg3(*p2)) {
1833         nkf_char s2, s1;
1834         if (e2s_conv(*p2, *p1, &s2, &s1) == 0) {
1835             s2e_conv(s2, s1, p2, p1);
1836         }else{
1837             ret = 1;
1838         }
1839     }
1840 #endif
1841     return ret;
1842 }
1843
1844 #ifdef UTF8_OUTPUT_ENABLE
1845 static nkf_char
1846 e2w_conv(nkf_char c2, nkf_char c1)
1847 {
1848     const unsigned short *p;
1849
1850     if (c2 == JIS_X_0201_1976_K) {
1851         if (ms_ucs_map_f == UCS_MAP_CP10001) {
1852             switch (c1) {
1853             case 0x20:
1854                 return 0xA0;
1855             case 0x7D:
1856                 return 0xA9;
1857             }
1858         }
1859         p = euc_to_utf8_1byte;
1860 #ifdef X0212_ENABLE
1861     } else if (is_eucg3(c2)){
1862         if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){
1863             return 0xA6;
1864         }
1865         c2 = (c2&0x7f) - 0x21;
1866         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
1867             p = x0212_to_utf8_2bytes[c2];
1868         else
1869             return 0;
1870 #endif
1871     } else {
1872         c2 &= 0x7f;
1873         c2 = (c2&0x7f) - 0x21;
1874         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
1875             p =
1876                 ms_ucs_map_f == UCS_MAP_ASCII ? euc_to_utf8_2bytes[c2] :
1877                 ms_ucs_map_f == UCS_MAP_CP10001 ? euc_to_utf8_2bytes_mac[c2] :
1878                 euc_to_utf8_2bytes_ms[c2];
1879         else
1880             return 0;
1881     }
1882     if (!p) return 0;
1883     c1 = (c1 & 0x7f) - 0x21;
1884     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
1885         return p[c1];
1886     return 0;
1887 }
1888 #endif
1889
1890 static nkf_char
1891 w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
1892 {
1893     nkf_char ret = 0;
1894
1895     if (!c1){
1896         *p2 = 0;
1897         *p1 = c2;
1898     }else if (0xc0 <= c2 && c2 <= 0xef) {
1899         ret =  unicode_to_jis_common(c2, c1, c0, p2, p1);
1900 #ifdef NUMCHAR_OPTION
1901         if (ret > 0){
1902             if (p2) *p2 = 0;
1903             if (p1) *p1 = nkf_char_unicode_new(nkf_utf8_to_unicode(c2, c1, c0, 0));
1904             ret = 0;
1905         }
1906 #endif
1907     }
1908     return ret;
1909 }
1910
1911 #ifdef UTF8_INPUT_ENABLE
1912 static nkf_char
1913 w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
1914 {
1915     nkf_char c1, c2, c3, c4;
1916     nkf_char ret = 0;
1917     val &= VALUE_MASK;
1918     if (val < 0x80) {
1919         *p2 = 0;
1920         *p1 = val;
1921     }
1922     else if (nkf_char_unicode_bmp_p(val)){
1923         nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
1924         ret =  unicode_to_jis_common(c1, c2, c3, p2, p1);
1925         if (ret > 0){
1926             *p2 = 0;
1927             *p1 = nkf_char_unicode_new(val);
1928             ret = 0;
1929         }
1930     }
1931     else {
1932         *p2 = 0;
1933         *p1 = nkf_char_unicode_new(val);
1934     }
1935     return ret;
1936 }
1937 #endif
1938
1939 static nkf_char
1940 e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
1941 {
1942     if (c2 == JIS_X_0201_1976_K || c2 == SS2){
1943         if (iso2022jp_f && !x0201_f) {
1944             c2 = GETA1; c1 = GETA2;
1945         } else {
1946             c2 = JIS_X_0201_1976_K;
1947             c1 &= 0x7f;
1948         }
1949 #ifdef X0212_ENABLE
1950     }else if (c2 == 0x8f){
1951         if (c0 == 0){
1952             return -1;
1953         }
1954         if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) {
1955             /* encoding is eucJP-ms, so invert to Unicode Private User Area */
1956             c1 = nkf_char_unicode_new((c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC);
1957             c2 = 0;
1958         } else {
1959             c2 = (c2 << 8) | (c1 & 0x7f);
1960             c1 = c0 & 0x7f;
1961 #ifdef SHIFTJIS_CP932
1962             if (cp51932_f){
1963                 nkf_char s2, s1;
1964                 if (e2s_conv(c2, c1, &s2, &s1) == 0){
1965                     s2e_conv(s2, s1, &c2, &c1);
1966                     if (c2 < 0x100){
1967                         c1 &= 0x7f;
1968                         c2 &= 0x7f;
1969                     }
1970                 }
1971             }
1972 #endif /* SHIFTJIS_CP932 */
1973         }
1974 #endif /* X0212_ENABLE */
1975     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP || c2 == ISO_8859_1) {
1976         /* NOP */
1977     } else {
1978         if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) {
1979             /* encoding is eucJP-ms, so invert to Unicode Private User Area */
1980             c1 = nkf_char_unicode_new((c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000);
1981             c2 = 0;
1982         } else {
1983             c1 &= 0x7f;
1984             c2 &= 0x7f;
1985 #ifdef SHIFTJIS_CP932
1986             if (cp51932_f && 0x79 <= c2 && c2 <= 0x7c){
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     }
1999     (*oconv)(c2, c1);
2000     return 0;
2001 }
2002
2003 static nkf_char
2004 s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
2005 {
2006     if (c2 == JIS_X_0201_1976_K || (0xA1 <= c2 && c2 <= 0xDF)) {
2007         if (iso2022jp_f && !x0201_f) {
2008             c2 = GETA1; c1 = GETA2;
2009         } else {
2010             c1 &= 0x7f;
2011         }
2012     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) {
2013         /* NOP */
2014     } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) {
2015         /* CP932 UDC */
2016         if(c1 == 0x7F) return 0;
2017         c1 = nkf_char_unicode_new((c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000);
2018         c2 = 0;
2019     } else {
2020         nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
2021         if (ret) return ret;
2022     }
2023     (*oconv)(c2, c1);
2024     return 0;
2025 }
2026
2027 static nkf_char
2028 w_iconv(nkf_char c1, nkf_char c2, nkf_char c3)
2029 {
2030     nkf_char ret = 0, c4 = 0;
2031     static const char w_iconv_utf8_1st_byte[] =
2032     { /* 0xC0 - 0xFF */
2033         20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
2034         21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
2035         30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33,
2036         40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70};
2037
2038     if (c3 > 0xFF) {
2039         c4 = c3 & 0xFF;
2040         c3 >>= 8;
2041     }
2042
2043     if (c1 < 0 || 0xff < c1) {
2044     }else if (c1 == 0) { /* 0 : 1 byte*/
2045         c3 = 0;
2046     } else if ((c1 & 0xC0) == 0x80) { /* 0x80-0xbf : trail byte */
2047         return 0;
2048     } else{
2049         switch (w_iconv_utf8_1st_byte[c1 - 0xC0]) {
2050         case 21:
2051             if (c2 < 0x80 || 0xBF < c2) return 0;
2052             break;
2053         case 30:
2054             if (c3 == 0) return -1;
2055             if (c2 < 0xA0 || 0xBF < c2 || (c3 & 0xC0) != 0x80)
2056                 return 0;
2057             break;
2058         case 31:
2059         case 33:
2060             if (c3 == 0) return -1;
2061             if ((c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80)
2062                 return 0;
2063             break;
2064         case 32:
2065             if (c3 == 0) return -1;
2066             if (c2 < 0x80 || 0x9F < c2 || (c3 & 0xC0) != 0x80)
2067                 return 0;
2068             break;
2069         case 40:
2070             if (c3 == 0) return -2;
2071             if (c2 < 0x90 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2072                 return 0;
2073             break;
2074         case 41:
2075             if (c3 == 0) return -2;
2076             if (c2 < 0x80 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2077                 return 0;
2078             break;
2079         case 42:
2080             if (c3 == 0) return -2;
2081             if (c2 < 0x80 || 0x8F < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2082                 return 0;
2083             break;
2084         default:
2085             return 0;
2086             break;
2087         }
2088     }
2089     if (c1 == 0 || c1 == EOF){
2090     } else if ((c1 & 0xf8) == 0xf0) { /* 4 bytes */
2091         c2 = nkf_char_unicode_new(nkf_utf8_to_unicode(c1, c2, c3, c4));
2092         c1 = 0;
2093     } else {
2094         ret = w2e_conv(c1, c2, c3, &c1, &c2);
2095     }
2096     if (ret == 0){
2097         (*oconv)(c1, c2);
2098     }
2099     return ret;
2100 }
2101
2102 #define NKF_ICONV_INVALID_CODE_RANGE -13
2103 static size_t
2104 unicode_iconv(nkf_char wc)
2105 {
2106     nkf_char c1, c2;
2107     int ret = 0;
2108
2109     if (wc < 0x80) {
2110         c2 = 0;
2111         c1 = wc;
2112     }else if ((wc>>11) == 27) {
2113         /* unpaired surrogate */
2114         return NKF_ICONV_INVALID_CODE_RANGE;
2115     }else if (wc < 0xFFFF) {
2116         ret = w16e_conv(wc, &c2, &c1);
2117         if (ret) return ret;
2118     }else if (wc < 0x10FFFF) {
2119         c2 = 0;
2120         c1 = nkf_char_unicode_new(wc);
2121     } else {
2122         return NKF_ICONV_INVALID_CODE_RANGE;
2123     }
2124     (*oconv)(c2, c1);
2125     return 0;
2126 }
2127
2128 #define NKF_ICONV_NEED_ONE_MORE_BYTE -1
2129 #define NKF_ICONV_NEED_TWO_MORE_BYTES -2
2130 #define UTF16_TO_UTF32(lead, trail) (((lead) << 10) + (trail) - NKF_INT32_C(0x35FDC00))
2131 static size_t
2132 nkf_iconv_utf_16(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
2133 {
2134     nkf_char wc;
2135
2136     if (c1 == EOF) {
2137         (*oconv)(EOF, 0);
2138         return 0;
2139     }
2140
2141     if (input_endian == ENDIAN_BIG) {
2142         if (0xD8 <= c1 && c1 <= 0xDB) {
2143             if (0xDC <= c3 && c3 <= 0xDF) {
2144                 wc = UTF16_TO_UTF32(c1 << 8 | c2, c3 << 8 | c4);
2145             } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
2146         } else {
2147             wc = c1 << 8 | c2;
2148         }
2149     } else {
2150         if (0xD8 <= c2 && c2 <= 0xDB) {
2151             if (0xDC <= c4 && c4 <= 0xDF) {
2152                 wc = UTF16_TO_UTF32(c2 << 8 | c1, c4 << 8 | c3);
2153             } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
2154         } else {
2155             wc = c2 << 8 | c1;
2156         }
2157     }
2158
2159     return (*unicode_iconv)(wc);
2160 }
2161
2162 static nkf_char
2163 w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
2164 {
2165     return 0;
2166 }
2167
2168 static nkf_char
2169 w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
2170 {
2171     return 0;
2172 }
2173
2174 static size_t
2175 nkf_iconv_utf_32(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
2176 {
2177     nkf_char wc;
2178
2179     if (c1 == EOF) {
2180         (*oconv)(EOF, 0);
2181         return 0;
2182     }
2183
2184     switch(input_endian){
2185     case ENDIAN_BIG:
2186         wc = c2 << 16 | c3 << 8 | c4;
2187         break;
2188     case ENDIAN_LITTLE:
2189         wc = c3 << 16 | c2 << 8 | c1;
2190         break;
2191     case ENDIAN_2143:
2192         wc = c1 << 16 | c4 << 8 | c3;
2193         break;
2194     case ENDIAN_3412:
2195         wc = c4 << 16 | c1 << 8 | c2;
2196         break;
2197     default:
2198         return NKF_ICONV_INVALID_CODE_RANGE;
2199     }
2200
2201     return (*unicode_iconv)(wc);
2202 }
2203 #endif
2204
2205 #define output_ascii_escape_sequence(mode) do { \
2206             if (output_mode != ASCII && output_mode != ISO_8859_1) { \
2207                     (*o_putc)(ESC); \
2208                     (*o_putc)('('); \
2209                     (*o_putc)(ascii_intro); \
2210                     output_mode = mode; \
2211             } \
2212     } while (0)
2213
2214 static void
2215 output_escape_sequence(int mode)
2216 {
2217     if (output_mode == mode)
2218         return;
2219     switch(mode) {
2220     case ISO_8859_1:
2221         (*o_putc)(ESC);
2222         (*o_putc)('.');
2223         (*o_putc)('A');
2224         break;
2225     case JIS_X_0201_1976_K:
2226         (*o_putc)(ESC);
2227         (*o_putc)('(');
2228         (*o_putc)('I');
2229         break;
2230     case JIS_X_0208:
2231         (*o_putc)(ESC);
2232         (*o_putc)('$');
2233         (*o_putc)(kanji_intro);
2234         break;
2235     case JIS_X_0212:
2236         (*o_putc)(ESC);
2237         (*o_putc)('$');
2238         (*o_putc)('(');
2239         (*o_putc)('D');
2240         break;
2241     case JIS_X_0213_1:
2242         (*o_putc)(ESC);
2243         (*o_putc)('$');
2244         (*o_putc)('(');
2245         (*o_putc)('Q');
2246         break;
2247     case JIS_X_0213_2:
2248         (*o_putc)(ESC);
2249         (*o_putc)('$');
2250         (*o_putc)('(');
2251         (*o_putc)('P');
2252         break;
2253     }
2254     output_mode = mode;
2255 }
2256
2257 static void
2258 j_oconv(nkf_char c2, nkf_char c1)
2259 {
2260 #ifdef NUMCHAR_OPTION
2261     if (c2 == 0 && nkf_char_unicode_p(c1)){
2262         w16e_conv(c1, &c2, &c1);
2263         if (c2 == 0 && nkf_char_unicode_p(c1)){
2264             c2 = c1 & VALUE_MASK;
2265             if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) {
2266                 /* CP5022x UDC */
2267                 c1 &= 0xFFF;
2268                 c2 = 0x7F + c1 / 94;
2269                 c1 = 0x21 + c1 % 94;
2270             } else {
2271                 if (encode_fallback) (*encode_fallback)(c1);
2272                 return;
2273             }
2274         }
2275     }
2276 #endif
2277     if (c2 == 0) {
2278         output_ascii_escape_sequence(ASCII);
2279         (*o_putc)(c1);
2280     }
2281     else if (c2 == EOF) {
2282         output_ascii_escape_sequence(ASCII);
2283         (*o_putc)(EOF);
2284     }
2285     else if (c2 == ISO_8859_1) {
2286         output_ascii_escape_sequence(ISO_8859_1);
2287         (*o_putc)(c1|0x80);
2288     }
2289     else if (c2 == JIS_X_0201_1976_K) {
2290         output_escape_sequence(JIS_X_0201_1976_K);
2291         (*o_putc)(c1);
2292 #ifdef X0212_ENABLE
2293     } else if (is_eucg3(c2)){
2294         output_escape_sequence(x0213_f ? JIS_X_0213_2 : JIS_X_0212);
2295         (*o_putc)(c2 & 0x7f);
2296         (*o_putc)(c1);
2297 #endif
2298     } else {
2299         if(ms_ucs_map_f
2300            ? c2<0x20 || 0x92<c2 || c1<0x20 || 0x7e<c1
2301            : c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
2302         output_escape_sequence(x0213_f ? JIS_X_0213_1 : JIS_X_0208);
2303         (*o_putc)(c2);
2304         (*o_putc)(c1);
2305     }
2306 }
2307
2308 static void
2309 e_oconv(nkf_char c2, nkf_char c1)
2310 {
2311     if (c2 == 0 && nkf_char_unicode_p(c1)){
2312         w16e_conv(c1, &c2, &c1);
2313         if (c2 == 0 && nkf_char_unicode_p(c1)){
2314             c2 = c1 & VALUE_MASK;
2315             if (x0212_f && 0xE000 <= c2 && c2 <= 0xE757) {
2316                 /* eucJP-ms UDC */
2317                 c1 &= 0xFFF;
2318                 c2 = c1 / 94;
2319                 c2 += c2 < 10 ? 0x75 : 0x8FEB;
2320                 c1 = 0x21 + c1 % 94;
2321                 if (is_eucg3(c2)){
2322                     (*o_putc)(0x8f);
2323                     (*o_putc)((c2 & 0x7f) | 0x080);
2324                     (*o_putc)(c1 | 0x080);
2325                 }else{
2326                     (*o_putc)((c2 & 0x7f) | 0x080);
2327                     (*o_putc)(c1 | 0x080);
2328                 }
2329                 return;
2330             } else {
2331                 if (encode_fallback) (*encode_fallback)(c1);
2332                 return;
2333             }
2334         }
2335     }
2336
2337     if (c2 == EOF) {
2338         (*o_putc)(EOF);
2339     } else if (c2 == 0) {
2340         output_mode = ASCII;
2341         (*o_putc)(c1);
2342     } else if (c2 == JIS_X_0201_1976_K) {
2343         output_mode = EUC_JP;
2344         (*o_putc)(SS2); (*o_putc)(c1|0x80);
2345     } else if (c2 == ISO_8859_1) {
2346         output_mode = ISO_8859_1;
2347         (*o_putc)(c1 | 0x080);
2348 #ifdef X0212_ENABLE
2349     } else if (is_eucg3(c2)){
2350         output_mode = EUC_JP;
2351 #ifdef SHIFTJIS_CP932
2352         if (!cp932inv_f){
2353             nkf_char s2, s1;
2354             if (e2s_conv(c2, c1, &s2, &s1) == 0){
2355                 s2e_conv(s2, s1, &c2, &c1);
2356             }
2357         }
2358 #endif
2359         if (c2 == 0) {
2360             output_mode = ASCII;
2361             (*o_putc)(c1);
2362         }else if (is_eucg3(c2)){
2363             if (x0212_f){
2364                 (*o_putc)(0x8f);
2365                 (*o_putc)((c2 & 0x7f) | 0x080);
2366                 (*o_putc)(c1 | 0x080);
2367             }
2368         }else{
2369             (*o_putc)((c2 & 0x7f) | 0x080);
2370             (*o_putc)(c1 | 0x080);
2371         }
2372 #endif
2373     } else {
2374         if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
2375             set_iconv(FALSE, 0);
2376             return; /* too late to rescue this char */
2377         }
2378         output_mode = EUC_JP;
2379         (*o_putc)(c2 | 0x080);
2380         (*o_putc)(c1 | 0x080);
2381     }
2382 }
2383
2384 static void
2385 s_oconv(nkf_char c2, nkf_char c1)
2386 {
2387 #ifdef NUMCHAR_OPTION
2388     if (c2 == 0 && nkf_char_unicode_p(c1)){
2389         w16e_conv(c1, &c2, &c1);
2390         if (c2 == 0 && nkf_char_unicode_p(c1)){
2391             c2 = c1 & VALUE_MASK;
2392             if (!x0213_f && 0xE000 <= c2 && c2 <= 0xE757) {
2393                 /* CP932 UDC */
2394                 c1 &= 0xFFF;
2395                 c2 = c1 / 188 + (cp932inv_f ? 0xF0 : 0xEB);
2396                 c1 = c1 % 188;
2397                 c1 += 0x40 + (c1 > 0x3e);
2398                 (*o_putc)(c2);
2399                 (*o_putc)(c1);
2400                 return;
2401             } else {
2402                 if(encode_fallback)(*encode_fallback)(c1);
2403                 return;
2404             }
2405         }
2406     }
2407 #endif
2408     if (c2 == EOF) {
2409         (*o_putc)(EOF);
2410         return;
2411     } else if (c2 == 0) {
2412         output_mode = ASCII;
2413         (*o_putc)(c1);
2414     } else if (c2 == JIS_X_0201_1976_K) {
2415         output_mode = SHIFT_JIS;
2416         (*o_putc)(c1|0x80);
2417     } else if (c2 == ISO_8859_1) {
2418         output_mode = ISO_8859_1;
2419         (*o_putc)(c1 | 0x080);
2420 #ifdef X0212_ENABLE
2421     } else if (is_eucg3(c2)){
2422         output_mode = SHIFT_JIS;
2423         if (e2s_conv(c2, c1, &c2, &c1) == 0){
2424             (*o_putc)(c2);
2425             (*o_putc)(c1);
2426         }
2427 #endif
2428     } else {
2429         if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
2430             set_iconv(FALSE, 0);
2431             return; /* too late to rescue this char */
2432         }
2433         output_mode = SHIFT_JIS;
2434         e2s_conv(c2, c1, &c2, &c1);
2435
2436 #ifdef SHIFTJIS_CP932
2437         if (cp932inv_f
2438             && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
2439             nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
2440             if (c){
2441                 c2 = c >> 8;
2442                 c1 = c & 0xff;
2443             }
2444         }
2445 #endif /* SHIFTJIS_CP932 */
2446
2447         (*o_putc)(c2);
2448         if (prefix_table[(unsigned char)c1]){
2449             (*o_putc)(prefix_table[(unsigned char)c1]);
2450         }
2451         (*o_putc)(c1);
2452     }
2453 }
2454
2455 #ifdef UTF8_OUTPUT_ENABLE
2456 static void
2457 w_oconv(nkf_char c2, nkf_char c1)
2458 {
2459     nkf_char c3, c4;
2460     nkf_char val;
2461
2462     if (output_bom_f) {
2463         output_bom_f = FALSE;
2464         (*o_putc)('\357');
2465         (*o_putc)('\273');
2466         (*o_putc)('\277');
2467     }
2468
2469     if (c2 == EOF) {
2470         (*o_putc)(EOF);
2471         return;
2472     }
2473
2474     if (c2 == 0 && nkf_char_unicode_p(c1)){
2475         val = c1 & VALUE_MASK;
2476         nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
2477         (*o_putc)(c1);
2478         if (c2) (*o_putc)(c2);
2479         if (c3) (*o_putc)(c3);
2480         if (c4) (*o_putc)(c4);
2481         return;
2482     }
2483
2484     if (c2 == 0) {
2485         (*o_putc)(c1);
2486     } else {
2487         val = e2w_conv(c2, c1);
2488         if (val){
2489             nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
2490             (*o_putc)(c1);
2491             if (c2) (*o_putc)(c2);
2492             if (c3) (*o_putc)(c3);
2493             if (c4) (*o_putc)(c4);
2494         }
2495     }
2496 }
2497
2498 static void
2499 w_oconv16(nkf_char c2, nkf_char c1)
2500 {
2501     if (output_bom_f) {
2502         output_bom_f = FALSE;
2503         if (output_endian == ENDIAN_LITTLE){
2504             (*o_putc)(0xFF);
2505             (*o_putc)(0xFE);
2506         }else{
2507             (*o_putc)(0xFE);
2508             (*o_putc)(0xFF);
2509         }
2510     }
2511
2512     if (c2 == EOF) {
2513         (*o_putc)(EOF);
2514         return;
2515     }
2516
2517     if (c2 == 0 && nkf_char_unicode_p(c1)) {
2518         if (nkf_char_unicode_bmp_p(c1)) {
2519             c2 = (c1 >> 8) & 0xff;
2520             c1 &= 0xff;
2521         } else {
2522             c1 &= VALUE_MASK;
2523             if (c1 <= UNICODE_MAX) {
2524                 c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0);   /* high surrogate */
2525                 c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
2526                 if (output_endian == ENDIAN_LITTLE){
2527                     (*o_putc)(c2 & 0xff);
2528                     (*o_putc)((c2 >> 8) & 0xff);
2529                     (*o_putc)(c1 & 0xff);
2530                     (*o_putc)((c1 >> 8) & 0xff);
2531                 }else{
2532                     (*o_putc)((c2 >> 8) & 0xff);
2533                     (*o_putc)(c2 & 0xff);
2534                     (*o_putc)((c1 >> 8) & 0xff);
2535                     (*o_putc)(c1 & 0xff);
2536                 }
2537             }
2538             return;
2539         }
2540     } else if (c2) {
2541         nkf_char val = e2w_conv(c2, c1);
2542         c2 = (val >> 8) & 0xff;
2543         c1 = val & 0xff;
2544         if (!val) return;
2545     }
2546
2547     if (output_endian == ENDIAN_LITTLE){
2548         (*o_putc)(c1);
2549         (*o_putc)(c2);
2550     }else{
2551         (*o_putc)(c2);
2552         (*o_putc)(c1);
2553     }
2554 }
2555
2556 static void
2557 w_oconv32(nkf_char c2, nkf_char c1)
2558 {
2559     if (output_bom_f) {
2560         output_bom_f = FALSE;
2561         if (output_endian == ENDIAN_LITTLE){
2562             (*o_putc)(0xFF);
2563             (*o_putc)(0xFE);
2564             (*o_putc)(0);
2565             (*o_putc)(0);
2566         }else{
2567             (*o_putc)(0);
2568             (*o_putc)(0);
2569             (*o_putc)(0xFE);
2570             (*o_putc)(0xFF);
2571         }
2572     }
2573
2574     if (c2 == EOF) {
2575         (*o_putc)(EOF);
2576         return;
2577     }
2578
2579     if (c2 == ISO_8859_1) {
2580         c1 |= 0x80;
2581     } else if (c2 == 0 && nkf_char_unicode_p(c1)) {
2582         c1 &= VALUE_MASK;
2583     } else if (c2) {
2584         c1 = e2w_conv(c2, c1);
2585         if (!c1) return;
2586     }
2587     if (output_endian == ENDIAN_LITTLE){
2588         (*o_putc)( c1        & 0xFF);
2589         (*o_putc)((c1 >>  8) & 0xFF);
2590         (*o_putc)((c1 >> 16) & 0xFF);
2591         (*o_putc)(0);
2592     }else{
2593         (*o_putc)(0);
2594         (*o_putc)((c1 >> 16) & 0xFF);
2595         (*o_putc)((c1 >>  8) & 0xFF);
2596         (*o_putc)( c1        & 0xFF);
2597     }
2598 }
2599 #endif
2600
2601 #define SCORE_L2       (1)                   /* \e$BBh\e(B2\e$B?e=`4A;z\e(B */
2602 #define SCORE_KANA     (SCORE_L2 << 1)       /* \e$B$$$o$f$kH>3Q%+%J\e(B */
2603 #define SCORE_DEPEND   (SCORE_KANA << 1)     /* \e$B5!<o0MB8J8;z\e(B */
2604 #define SCORE_CP932    (SCORE_DEPEND << 1)   /* CP932 \e$B$K$h$kFI$_49$(\e(B (IBM extended characters) */
2605 #define SCORE_X0212    (SCORE_CP932 << 1)    /* JIS X 0212 */
2606 #define SCORE_NO_EXIST (SCORE_X0212 << 1)    /* \e$BB8:_$7$J$$J8;z\e(B */
2607 #define SCORE_iMIME    (SCORE_NO_EXIST << 1) /* MIME \e$B$K$h$k;XDj\e(B */
2608 #define SCORE_ERROR    (SCORE_iMIME << 1) /* \e$B%(%i!<\e(B */
2609
2610 #define SCORE_INIT (SCORE_iMIME)
2611
2612 static const char score_table_A0[] = {
2613     0, 0, 0, 0,
2614     0, 0, 0, 0,
2615     0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
2616     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
2617 };
2618
2619 static const char score_table_F0[] = {
2620     SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
2621     SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
2622     SCORE_DEPEND, SCORE_DEPEND, SCORE_CP932, SCORE_CP932,
2623     SCORE_CP932, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
2624 };
2625
2626 static void
2627 set_code_score(struct input_code *ptr, nkf_char score)
2628 {
2629     if (ptr){
2630         ptr->score |= score;
2631     }
2632 }
2633
2634 static void
2635 clr_code_score(struct input_code *ptr, nkf_char score)
2636 {
2637     if (ptr){
2638         ptr->score &= ~score;
2639     }
2640 }
2641
2642 static void
2643 code_score(struct input_code *ptr)
2644 {
2645     nkf_char c2 = ptr->buf[0];
2646 #ifdef UTF8_OUTPUT_ENABLE
2647     nkf_char c1 = ptr->buf[1];
2648 #endif
2649     if (c2 < 0){
2650         set_code_score(ptr, SCORE_ERROR);
2651     }else if (c2 == SS2){
2652         set_code_score(ptr, SCORE_KANA);
2653     }else if (c2 == 0x8f){
2654         set_code_score(ptr, SCORE_X0212);
2655 #ifdef UTF8_OUTPUT_ENABLE
2656     }else if (!e2w_conv(c2, c1)){
2657         set_code_score(ptr, SCORE_NO_EXIST);
2658 #endif
2659     }else if ((c2 & 0x70) == 0x20){
2660         set_code_score(ptr, score_table_A0[c2 & 0x0f]);
2661     }else if ((c2 & 0x70) == 0x70){
2662         set_code_score(ptr, score_table_F0[c2 & 0x0f]);
2663     }else if ((c2 & 0x70) >= 0x50){
2664         set_code_score(ptr, SCORE_L2);
2665     }
2666 }
2667
2668 static void
2669 status_disable(struct input_code *ptr)
2670 {
2671     ptr->stat = -1;
2672     ptr->buf[0] = -1;
2673     code_score(ptr);
2674     if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
2675 }
2676
2677 static void
2678 status_push_ch(struct input_code *ptr, nkf_char c)
2679 {
2680     ptr->buf[ptr->index++] = c;
2681 }
2682
2683 static void
2684 status_clear(struct input_code *ptr)
2685 {
2686     ptr->stat = 0;
2687     ptr->index = 0;
2688 }
2689
2690 static void
2691 status_reset(struct input_code *ptr)
2692 {
2693     status_clear(ptr);
2694     ptr->score = SCORE_INIT;
2695 }
2696
2697 static void
2698 status_reinit(struct input_code *ptr)
2699 {
2700     status_reset(ptr);
2701     ptr->_file_stat = 0;
2702 }
2703
2704 static void
2705 status_check(struct input_code *ptr, nkf_char c)
2706 {
2707     if (c <= DEL && estab_f){
2708         status_reset(ptr);
2709     }
2710 }
2711
2712 static void
2713 s_status(struct input_code *ptr, nkf_char c)
2714 {
2715     switch(ptr->stat){
2716     case -1:
2717         status_check(ptr, c);
2718         break;
2719     case 0:
2720         if (c <= DEL){
2721             break;
2722         }else if (nkf_char_unicode_p(c)){
2723             break;
2724         }else if (0xa1 <= c && c <= 0xdf){
2725             status_push_ch(ptr, SS2);
2726             status_push_ch(ptr, c);
2727             code_score(ptr);
2728             status_clear(ptr);
2729         }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xea)){
2730             ptr->stat = 1;
2731             status_push_ch(ptr, c);
2732         }else if (0xed <= c && c <= 0xee){
2733             ptr->stat = 3;
2734             status_push_ch(ptr, c);
2735 #ifdef SHIFTJIS_CP932
2736         }else if (is_ibmext_in_sjis(c)){
2737             ptr->stat = 2;
2738             status_push_ch(ptr, c);
2739 #endif /* SHIFTJIS_CP932 */
2740 #ifdef X0212_ENABLE
2741         }else if (0xf0 <= c && c <= 0xfc){
2742             ptr->stat = 1;
2743             status_push_ch(ptr, c);
2744 #endif /* X0212_ENABLE */
2745         }else{
2746             status_disable(ptr);
2747         }
2748         break;
2749     case 1:
2750         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
2751             status_push_ch(ptr, c);
2752             s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
2753             code_score(ptr);
2754             status_clear(ptr);
2755         }else{
2756             status_disable(ptr);
2757         }
2758         break;
2759     case 2:
2760 #ifdef SHIFTJIS_CP932
2761         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)) {
2762             status_push_ch(ptr, c);
2763             if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0) {
2764                 set_code_score(ptr, SCORE_CP932);
2765                 status_clear(ptr);
2766                 break;
2767             }
2768         }
2769 #endif /* SHIFTJIS_CP932 */
2770         status_disable(ptr);
2771         break;
2772     case 3:
2773         if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
2774             status_push_ch(ptr, c);
2775             s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
2776             set_code_score(ptr, SCORE_CP932);
2777             status_clear(ptr);
2778         }else{
2779             status_disable(ptr);
2780         }
2781         break;
2782     }
2783 }
2784
2785 static void
2786 e_status(struct input_code *ptr, nkf_char c)
2787 {
2788     switch (ptr->stat){
2789     case -1:
2790         status_check(ptr, c);
2791         break;
2792     case 0:
2793         if (c <= DEL){
2794             break;
2795         }else if (nkf_char_unicode_p(c)){
2796             break;
2797         }else if (SS2 == c || (0xa1 <= c && c <= 0xfe)){
2798             ptr->stat = 1;
2799             status_push_ch(ptr, c);
2800 #ifdef X0212_ENABLE
2801         }else if (0x8f == c){
2802             ptr->stat = 2;
2803             status_push_ch(ptr, c);
2804 #endif /* X0212_ENABLE */
2805         }else{
2806             status_disable(ptr);
2807         }
2808         break;
2809     case 1:
2810         if (0xa1 <= c && c <= 0xfe){
2811             status_push_ch(ptr, c);
2812             code_score(ptr);
2813             status_clear(ptr);
2814         }else{
2815             status_disable(ptr);
2816         }
2817         break;
2818 #ifdef X0212_ENABLE
2819     case 2:
2820         if (0xa1 <= c && c <= 0xfe){
2821             ptr->stat = 1;
2822             status_push_ch(ptr, c);
2823         }else{
2824             status_disable(ptr);
2825         }
2826 #endif /* X0212_ENABLE */
2827     }
2828 }
2829
2830 #ifdef UTF8_INPUT_ENABLE
2831 static void
2832 w_status(struct input_code *ptr, nkf_char c)
2833 {
2834     switch (ptr->stat){
2835     case -1:
2836         status_check(ptr, c);
2837         break;
2838     case 0:
2839         if (c <= DEL){
2840             break;
2841         }else if (nkf_char_unicode_p(c)){
2842             break;
2843         }else if (0xc0 <= c && c <= 0xdf){
2844             ptr->stat = 1;
2845             status_push_ch(ptr, c);
2846         }else if (0xe0 <= c && c <= 0xef){
2847             ptr->stat = 2;
2848             status_push_ch(ptr, c);
2849         }else if (0xf0 <= c && c <= 0xf4){
2850             ptr->stat = 3;
2851             status_push_ch(ptr, c);
2852         }else{
2853             status_disable(ptr);
2854         }
2855         break;
2856     case 1:
2857     case 2:
2858         if (0x80 <= c && c <= 0xbf){
2859             status_push_ch(ptr, c);
2860             if (ptr->index > ptr->stat){
2861                 int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
2862                            && ptr->buf[2] == 0xbf);
2863                 w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
2864                          &ptr->buf[0], &ptr->buf[1]);
2865                 if (!bom){
2866                     code_score(ptr);
2867                 }
2868                 status_clear(ptr);
2869             }
2870         }else{
2871             status_disable(ptr);
2872         }
2873         break;
2874     case 3:
2875         if (0x80 <= c && c <= 0xbf){
2876             if (ptr->index < ptr->stat){
2877                 status_push_ch(ptr, c);
2878             } else {
2879                 status_clear(ptr);
2880             }
2881         }else{
2882             status_disable(ptr);
2883         }
2884         break;
2885     }
2886 }
2887 #endif
2888
2889 static void
2890 code_status(nkf_char c)
2891 {
2892     int action_flag = 1;
2893     struct input_code *result = 0;
2894     struct input_code *p = input_code_list;
2895     while (p->name){
2896         if (!p->status_func) {
2897             ++p;
2898             continue;
2899         }
2900         if (!p->status_func)
2901             continue;
2902         (p->status_func)(p, c);
2903         if (p->stat > 0){
2904             action_flag = 0;
2905         }else if(p->stat == 0){
2906             if (result){
2907                 action_flag = 0;
2908             }else{
2909                 result = p;
2910             }
2911         }
2912         ++p;
2913     }
2914
2915     if (action_flag){
2916         if (result && !estab_f){
2917             set_iconv(TRUE, result->iconv_func);
2918         }else if (c <= DEL){
2919             struct input_code *ptr = input_code_list;
2920             while (ptr->name){
2921                 status_reset(ptr);
2922                 ++ptr;
2923             }
2924         }
2925     }
2926 }
2927
2928 #ifndef WIN32DLL
2929 static nkf_char
2930 std_getc(FILE *f)
2931 {
2932     if (std_gc_ndx){
2933         return std_gc_buf[--std_gc_ndx];
2934     }
2935     return getc(f);
2936 }
2937 #endif /*WIN32DLL*/
2938
2939 static nkf_char
2940 std_ungetc(nkf_char c, FILE *f)
2941 {
2942     if (std_gc_ndx == STD_GC_BUFSIZE){
2943         return EOF;
2944     }
2945     std_gc_buf[std_gc_ndx++] = c;
2946     return c;
2947 }
2948
2949 #ifndef WIN32DLL
2950 static void
2951 std_putc(nkf_char c)
2952 {
2953     if(c!=EOF)
2954         putchar(c);
2955 }
2956 #endif /*WIN32DLL*/
2957
2958 static unsigned char   hold_buf[HOLD_SIZE*2];
2959 static int             hold_count = 0;
2960 static nkf_char
2961 push_hold_buf(nkf_char c2)
2962 {
2963     if (hold_count >= HOLD_SIZE*2)
2964         return (EOF);
2965     hold_buf[hold_count++] = (unsigned char)c2;
2966     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
2967 }
2968
2969 static int
2970 h_conv(FILE *f, int c1, int c2)
2971 {
2972     int ret, c4, c3;
2973     int hold_index;
2974
2975
2976     /** it must NOT be in the kanji shifte sequence      */
2977     /** it must NOT be written in JIS7                   */
2978     /** and it must be after 2 byte 8bit code            */
2979
2980     hold_count = 0;
2981     push_hold_buf(c1);
2982     push_hold_buf(c2);
2983
2984     while ((c2 = (*i_getc)(f)) != EOF) {
2985         if (c2 == ESC){
2986             (*i_ungetc)(c2,f);
2987             break;
2988         }
2989         code_status(c2);
2990         if (push_hold_buf(c2) == EOF || estab_f) {
2991             break;
2992         }
2993     }
2994
2995     if (!estab_f) {
2996         struct input_code *p = input_code_list;
2997         struct input_code *result = p;
2998         if (c2 == EOF) {
2999             code_status(c2);
3000         }
3001         while (p->name) {
3002             if (p->status_func && p->score < result->score) {
3003                 result = p;
3004             }
3005             p++;
3006         }
3007         set_iconv(TRUE, result->iconv_func);
3008     }
3009
3010
3011     /** now,
3012      ** 1) EOF is detected, or
3013      ** 2) Code is established, or
3014      ** 3) Buffer is FULL (but last word is pushed)
3015      **
3016      ** in 1) and 3) cases, we continue to use
3017      ** Kanji codes by oconv and leave estab_f unchanged.
3018      **/
3019
3020     ret = c2;
3021     hold_index = 0;
3022     while (hold_index < hold_count){
3023         c1 = hold_buf[hold_index++];
3024         if (c1 <= DEL){
3025             (*iconv)(0, c1, 0);
3026             continue;
3027         }else if (iconv == s_iconv && 0xa1 <= c1 && c1 <= 0xdf){
3028             (*iconv)(JIS_X_0201_1976_K, c1, 0);
3029             continue;
3030         }
3031         if (hold_index < hold_count){
3032             c2 = hold_buf[hold_index++];
3033         }else{
3034             c2 = (*i_getc)(f);
3035             if (c2 == EOF){
3036                 c4 = EOF;
3037                 break;
3038             }
3039             code_status(c2);
3040         }
3041         c3 = 0;
3042         switch ((*iconv)(c1, c2, 0)) {  /* can be EUC/SJIS/UTF-8 */
3043         case -2:
3044             /* 4 bytes UTF-8 */
3045             if (hold_index < hold_count){
3046                 c3 = hold_buf[hold_index++];
3047             } else if ((c3 = (*i_getc)(f)) == EOF) {
3048                 ret = EOF;
3049                 break;
3050             } else {
3051                 code_status(c3);
3052                 if (hold_index < hold_count){
3053                     c4 = hold_buf[hold_index++];
3054                 } else if ((c4 = (*i_getc)(f)) == EOF) {
3055                     c3 = ret = EOF;
3056                     break;
3057                 } else {
3058                     code_status(c4);
3059                     (*iconv)(c1, c2, (c3<<8)|c4);
3060                 }
3061             }
3062             break;
3063         case -1:
3064             /* 3 bytes EUC or UTF-8 */
3065             if (hold_index < hold_count){
3066                 c3 = hold_buf[hold_index++];
3067             } else if ((c3 = (*i_getc)(f)) == EOF) {
3068                 ret = EOF;
3069                 break;
3070             } else {
3071                 code_status(c3);
3072             }
3073             (*iconv)(c1, c2, c3);
3074             break;
3075         }
3076         if (c3 == EOF) break;
3077     }
3078     return ret;
3079 }
3080
3081 /*
3082  * Check and Ignore BOM
3083  */
3084 static void
3085 check_bom(FILE *f)
3086 {
3087     int c2;
3088     switch(c2 = (*i_getc)(f)){
3089     case 0x00:
3090         if((c2 = (*i_getc)(f)) == 0x00){
3091             if((c2 = (*i_getc)(f)) == 0xFE){
3092                 if((c2 = (*i_getc)(f)) == 0xFF){
3093                     if(!input_encoding){
3094                         set_iconv(TRUE, w_iconv32);
3095                     }
3096                     if (iconv == w_iconv32) {
3097                         input_endian = ENDIAN_BIG;
3098                         return;
3099                     }
3100                     (*i_ungetc)(0xFF,f);
3101                 }else (*i_ungetc)(c2,f);
3102                 (*i_ungetc)(0xFE,f);
3103             }else if(c2 == 0xFF){
3104                 if((c2 = (*i_getc)(f)) == 0xFE){
3105                     if(!input_encoding){
3106                         set_iconv(TRUE, w_iconv32);
3107                     }
3108                     if (iconv == w_iconv32) {
3109                         input_endian = ENDIAN_2143;
3110                         return;
3111                     }
3112                     (*i_ungetc)(0xFF,f);
3113                 }else (*i_ungetc)(c2,f);
3114                 (*i_ungetc)(0xFF,f);
3115             }else (*i_ungetc)(c2,f);
3116             (*i_ungetc)(0x00,f);
3117         }else (*i_ungetc)(c2,f);
3118         (*i_ungetc)(0x00,f);
3119         break;
3120     case 0xEF:
3121         if((c2 = (*i_getc)(f)) == 0xBB){
3122             if((c2 = (*i_getc)(f)) == 0xBF){
3123                 if(!input_encoding){
3124                     set_iconv(TRUE, w_iconv);
3125                 }
3126                 if (iconv == w_iconv) {
3127                     return;
3128                 }
3129                 (*i_ungetc)(0xBF,f);
3130             }else (*i_ungetc)(c2,f);
3131             (*i_ungetc)(0xBB,f);
3132         }else (*i_ungetc)(c2,f);
3133         (*i_ungetc)(0xEF,f);
3134         break;
3135     case 0xFE:
3136         if((c2 = (*i_getc)(f)) == 0xFF){
3137             if((c2 = (*i_getc)(f)) == 0x00){
3138                 if((c2 = (*i_getc)(f)) == 0x00){
3139                     if(!input_encoding){
3140                         set_iconv(TRUE, w_iconv32);
3141                     }
3142                     if (iconv == w_iconv32) {
3143                         input_endian = ENDIAN_3412;
3144                         return;
3145                     }
3146                     (*i_ungetc)(0x00,f);
3147                 }else (*i_ungetc)(c2,f);
3148                 (*i_ungetc)(0x00,f);
3149             }else (*i_ungetc)(c2,f);
3150             if(!input_encoding){
3151                 set_iconv(TRUE, w_iconv16);
3152             }
3153             if (iconv == w_iconv16) {
3154                 input_endian = ENDIAN_BIG;
3155                 return;
3156             }
3157             (*i_ungetc)(0xFF,f);
3158         }else (*i_ungetc)(c2,f);
3159         (*i_ungetc)(0xFE,f);
3160         break;
3161     case 0xFF:
3162         if((c2 = (*i_getc)(f)) == 0xFE){
3163             if((c2 = (*i_getc)(f)) == 0x00){
3164                 if((c2 = (*i_getc)(f)) == 0x00){
3165                     if(!input_encoding){
3166                         set_iconv(TRUE, w_iconv32);
3167                     }
3168                     if (iconv == w_iconv32) {
3169                         input_endian = ENDIAN_LITTLE;
3170                         return;
3171                     }
3172                     (*i_ungetc)(0x00,f);
3173                 }else (*i_ungetc)(c2,f);
3174                 (*i_ungetc)(0x00,f);
3175             }else (*i_ungetc)(c2,f);
3176             if(!input_encoding){
3177                 set_iconv(TRUE, w_iconv16);
3178             }
3179             if (iconv == w_iconv16) {
3180                 input_endian = ENDIAN_LITTLE;
3181                 return;
3182             }
3183             (*i_ungetc)(0xFE,f);
3184         }else (*i_ungetc)(c2,f);
3185         (*i_ungetc)(0xFF,f);
3186         break;
3187     default:
3188         (*i_ungetc)(c2,f);
3189         break;
3190     }
3191 }
3192
3193 static struct {
3194     int count;
3195     nkf_char status;
3196     nkf_char buf[3];
3197 } broken_state;
3198
3199 static void
3200 init_broken_state(void)
3201 {
3202     memset(&broken_state, 0, sizeof(broken_state));
3203 }
3204
3205 static void
3206 push_broken_buf(c)
3207 {
3208     broken_state.buf[broken_state.count++] = c;
3209 }
3210
3211 static nkf_char
3212 pop_broken_buf(void)
3213 {
3214     return broken_state.buf[--broken_state.count];
3215 }
3216
3217 static nkf_char
3218 broken_getc(FILE *f)
3219 {
3220     nkf_char c, c1;
3221
3222     if (broken_state.count > 0) {
3223         return pop_broken_buf();
3224     }
3225     c = (*i_bgetc)(f);
3226     if (c=='$' && broken_state.status != ESC
3227         && (input_mode == ASCII || input_mode == JIS_X_0201_1976_K)) {
3228         c1= (*i_bgetc)(f);
3229         broken_state.status = 0;
3230         if (c1=='@'|| c1=='B') {
3231             push_broken_buf(c1);
3232             push_broken_buf(c);
3233             return ESC;
3234         } else {
3235             (*i_bungetc)(c1,f);
3236             return c;
3237         }
3238     } else if (c=='(' && broken_state.status != ESC
3239                && (input_mode == JIS_X_0208 || input_mode == JIS_X_0201_1976_K)) {
3240         c1= (*i_bgetc)(f);
3241         broken_state.status = 0;
3242         if (c1=='J'|| c1=='B') {
3243             push_broken_buf(c1);
3244             push_broken_buf(c);
3245             return ESC;
3246         } else {
3247             (*i_bungetc)(c1,f);
3248             return c;
3249         }
3250     } else {
3251         broken_state.status = c;
3252         return c;
3253     }
3254 }
3255
3256 static nkf_char
3257 broken_ungetc(nkf_char c, FILE *f)
3258 {
3259     if (broken_state.count < 2)
3260         push_broken_buf(c);
3261     return c;
3262 }
3263
3264 static void
3265 eol_conv(nkf_char c2, nkf_char c1)
3266 {
3267     if (guess_f && input_eol != EOF) {
3268         if (c2 == 0 && c1 == LF) {
3269             if (!input_eol) input_eol = prev_cr ? CRLF : LF;
3270             else if (input_eol != (prev_cr ? CRLF : LF)) input_eol = EOF;
3271         } else if (c2 == 0 && c1 == CR && input_eol == LF) input_eol = EOF;
3272         else if (!prev_cr);
3273         else if (!input_eol) input_eol = CR;
3274         else if (input_eol != CR) input_eol = EOF;
3275     }
3276     if (prev_cr || (c2 == 0 && c1 == LF)) {
3277         prev_cr = 0;
3278         if (eolmode_f != LF) (*o_eol_conv)(0, CR);
3279         if (eolmode_f != CR) (*o_eol_conv)(0, LF);
3280     }
3281     if (c2 == 0 && c1 == CR) prev_cr = CR;
3282     else if (c2 != 0 || c1 != LF) (*o_eol_conv)(c2, c1);
3283 }
3284
3285 /*
3286    Return value of fold_conv()
3287
3288    LF  add newline  and output char
3289    CR  add newline  and output nothing
3290    SP  space
3291    0   skip
3292    1   (or else) normal output
3293
3294    fold state in prev (previous character)
3295
3296    >0x80 Japanese (X0208/X0201)
3297    <0x80 ASCII
3298    LF    new line
3299    SP    space
3300
3301    This fold algorthm does not preserve heading space in a line.
3302    This is the main difference from fmt.
3303  */
3304
3305 #define char_size(c2,c1) (c2?2:1)
3306
3307 static void
3308 fold_conv(nkf_char c2, nkf_char c1)
3309 {
3310     nkf_char prev0;
3311     nkf_char fold_state;
3312
3313     if (c1== CR && !fold_preserve_f) {
3314         fold_state=0;  /* ignore cr */
3315     }else if (c1== LF&&f_prev==CR && fold_preserve_f) {
3316         f_prev = LF;
3317         fold_state=0;  /* ignore cr */
3318     } else if (c1== BS) {
3319         if (f_line>0) f_line--;
3320         fold_state =  1;
3321     } else if (c2==EOF && f_line != 0) {    /* close open last line */
3322         fold_state = LF;
3323     } else if ((c1==LF && !fold_preserve_f)
3324                || ((c1==CR||(c1==LF&&f_prev!=CR))
3325                    && fold_preserve_f)) {
3326         /* new line */
3327         if (fold_preserve_f) {
3328             f_prev = c1;
3329             f_line = 0;
3330             fold_state =  CR;
3331         } else if ((f_prev == c1 && !fold_preserve_f)
3332                    || (f_prev == LF && fold_preserve_f)
3333                   ) {        /* duplicate newline */
3334             if (f_line) {
3335                 f_line = 0;
3336                 fold_state =  LF;    /* output two newline */
3337             } else {
3338                 f_line = 0;
3339                 fold_state =  1;
3340             }
3341         } else  {
3342             if (f_prev&0x80) {     /* Japanese? */
3343                 f_prev = c1;
3344                 fold_state =  0;       /* ignore given single newline */
3345             } else if (f_prev==SP) {
3346                 fold_state =  0;
3347             } else {
3348                 f_prev = c1;
3349                 if (++f_line<=fold_len)
3350                     fold_state =  SP;
3351                 else {
3352                     f_line = 0;
3353                     fold_state =  CR;        /* fold and output nothing */
3354                 }
3355             }
3356         }
3357     } else if (c1=='\f') {
3358         f_prev = LF;
3359         f_line = 0;
3360         fold_state =  LF;            /* output newline and clear */
3361     } else if ( (c2==0  && c1==SP)||
3362                (c2==0  && c1==TAB)||
3363                (c2=='!'&& c1=='!')) {
3364         /* X0208 kankaku or ascii space */
3365         if (f_prev == SP) {
3366             fold_state = 0;         /* remove duplicate spaces */
3367         } else {
3368             f_prev = SP;
3369             if (++f_line<=fold_len)
3370                 fold_state = SP;         /* output ASCII space only */
3371             else {
3372                 f_prev = SP; f_line = 0;
3373                 fold_state = CR;        /* fold and output nothing */
3374             }
3375         }
3376     } else {
3377         prev0 = f_prev; /* we still need this one... , but almost done */
3378         f_prev = c1;
3379         if (c2 || c2 == JIS_X_0201_1976_K)
3380             f_prev |= 0x80;  /* this is Japanese */
3381         f_line += char_size(c2,c1);
3382         if (f_line<=fold_len) {   /* normal case */
3383             fold_state = 1;
3384         } else {
3385             if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
3386                 f_line = char_size(c2,c1);
3387                 fold_state =  LF;       /* We can't wait, do fold now */
3388             } else if (c2 == JIS_X_0201_1976_K) {
3389                 /* simple kinsoku rules  return 1 means no folding  */
3390                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
3391                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
3392                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
3393                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
3394                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
3395                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
3396                 else if (SP<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
3397                     f_line = 1;
3398                     fold_state = LF;/* add one new f_line before this character */
3399                 } else {
3400                     f_line = 1;
3401                     fold_state = LF;/* add one new f_line before this character */
3402                 }
3403             } else if (c2==0) {
3404                 /* kinsoku point in ASCII */
3405                 if (  c1==')'||    /* { [ ( */
3406                     c1==']'||
3407                     c1=='}'||
3408                     c1=='.'||
3409                     c1==','||
3410                     c1=='!'||
3411                     c1=='?'||
3412                     c1=='/'||
3413                     c1==':'||
3414                     c1==';') {
3415                     fold_state = 1;
3416                     /* just after special */
3417                 } else if (!is_alnum(prev0)) {
3418                     f_line = char_size(c2,c1);
3419                     fold_state = LF;
3420                 } else if ((prev0==SP) ||   /* ignored new f_line */
3421                            (prev0==LF)||        /* ignored new f_line */
3422                            (prev0&0x80)) {        /* X0208 - ASCII */
3423                     f_line = char_size(c2,c1);
3424                     fold_state = LF;/* add one new f_line before this character */
3425                 } else {
3426                     fold_state = 1;  /* default no fold in ASCII */
3427                 }
3428             } else {
3429                 if (c2=='!') {
3430                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
3431                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
3432                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
3433                     else if (c1=='K')  fold_state = 1; /* \e$B!K\e(B */
3434                     else if (c1=='$')  fold_state = 1; /* \e$B!$\e(B */
3435                     else if (c1=='%')  fold_state = 1; /* \e$B!%\e(B */
3436                     else if (c1=='\'') fold_state = 1; /* \e$B!\\e(B */
3437                     else if (c1=='(')  fold_state = 1; /* \e$B!(\e(B */
3438                     else if (c1==')')  fold_state = 1; /* \e$B!)\e(B */
3439                     else if (c1=='*')  fold_state = 1; /* \e$B!*\e(B */
3440                     else if (c1=='+')  fold_state = 1; /* \e$B!+\e(B */
3441                     else if (c1==',')  fold_state = 1; /* \e$B!,\e(B */
3442                     /* default no fold in kinsoku */
3443                     else {
3444                         fold_state = LF;
3445                         f_line = char_size(c2,c1);
3446                         /* add one new f_line before this character */
3447                     }
3448                 } else {
3449                     f_line = char_size(c2,c1);
3450                     fold_state = LF;
3451                     /* add one new f_line before this character */
3452                 }
3453             }
3454         }
3455     }
3456     /* terminator process */
3457     switch(fold_state) {
3458     case LF:
3459         OCONV_NEWLINE((*o_fconv));
3460         (*o_fconv)(c2,c1);
3461         break;
3462     case 0:
3463         return;
3464     case CR:
3465         OCONV_NEWLINE((*o_fconv));
3466         break;
3467     case TAB:
3468     case SP:
3469         (*o_fconv)(0,SP);
3470         break;
3471     default:
3472         (*o_fconv)(c2,c1);
3473     }
3474 }
3475
3476 static nkf_char z_prev2=0,z_prev1=0;
3477
3478 static void
3479 z_conv(nkf_char c2, nkf_char c1)
3480 {
3481
3482     /* if (c2) c1 &= 0x7f; assertion */
3483
3484     if (c2 == JIS_X_0201_1976_K && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) {
3485         (*o_zconv)(c2,c1);
3486         return;
3487     }
3488
3489     if (x0201_f) {
3490         if (z_prev2 == JIS_X_0201_1976_K) {
3491             if (c2 == JIS_X_0201_1976_K) {
3492                 if (c1 == (0xde&0x7f)) { /* \e$BByE@\e(B */
3493                     z_prev2 = 0;
3494                     (*o_zconv)(dv[(z_prev1-SP)*2], dv[(z_prev1-SP)*2+1]);
3495                     return;
3496                 } else if (c1 == (0xdf&0x7f) && ev[(z_prev1-SP)*2]) {  /* \e$BH>ByE@\e(B */
3497                     z_prev2 = 0;
3498                     (*o_zconv)(ev[(z_prev1-SP)*2], ev[(z_prev1-SP)*2+1]);
3499                     return;
3500                 }
3501             }
3502             z_prev2 = 0;
3503             (*o_zconv)(cv[(z_prev1-SP)*2], cv[(z_prev1-SP)*2+1]);
3504         }
3505         if (c2 == JIS_X_0201_1976_K) {
3506             if (dv[(c1-SP)*2] || ev[(c1-SP)*2]) {
3507                 /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
3508                 z_prev1 = c1;
3509                 z_prev2 = c2;
3510                 return;
3511             } else {
3512                 (*o_zconv)(cv[(c1-SP)*2], cv[(c1-SP)*2+1]);
3513                 return;
3514             }
3515         }
3516     }
3517
3518     if (c2 == EOF) {
3519         (*o_zconv)(c2, c1);
3520         return;
3521     }
3522
3523     if (alpha_f&1 && c2 == 0x23) {
3524         /* JISX0208 Alphabet */
3525         c2 = 0;
3526     } else if (c2 == 0x21) {
3527         /* JISX0208 Kigou */
3528         if (0x21==c1) {
3529             if (alpha_f&2) {
3530                 c2 = 0;
3531                 c1 = SP;
3532             } else if (alpha_f&4) {
3533                 (*o_zconv)(0, SP);
3534                 (*o_zconv)(0, SP);
3535                 return;
3536             }
3537         } else if (alpha_f&1 && 0x20<c1 && c1<0x7f && fv[c1-0x20]) {
3538             c2 =  0;
3539             c1 = fv[c1-0x20];
3540         }
3541     }
3542
3543     if (alpha_f&8 && c2 == 0) {
3544         /* HTML Entity */
3545         const char *entity = 0;
3546         switch (c1){
3547         case '>': entity = "&gt;"; break;
3548         case '<': entity = "&lt;"; break;
3549         case '\"': entity = "&quot;"; break;
3550         case '&': entity = "&amp;"; break;
3551         }
3552         if (entity){
3553             while (*entity) (*o_zconv)(0, *entity++);
3554             return;
3555         }
3556     }
3557
3558     if (alpha_f & 16) {
3559         /* JIS X 0208 Katakana to JIS X 0201 Katakana */
3560         if (c2 == 0x21) {
3561             char c = 0;
3562             switch (c1) {
3563             case 0x23:
3564                 /* U+3002 (0x8142) Ideographic Full Stop -> U+FF61 (0xA1) Halfwidth Ideographic Full Stop */
3565                 c = 0xA1;
3566                 break;
3567             case 0x56:
3568                 /* U+300C (0x8175) Left Corner Bracket -> U+FF62 (0xA2) Halfwidth Left Corner Bracket */
3569                 c = 0xA2;
3570                 break;
3571             case 0x57:
3572                 /* U+300D (0x8176) Right Corner Bracket -> U+FF63 (0xA3) Halfwidth Right Corner Bracket */
3573                 c = 0xA3;
3574                 break;
3575             case 0x22:
3576                 /* U+3001 (0x8141) Ideographic Comma -> U+FF64 (0xA4) Halfwidth Ideographic Comma */
3577                 c = 0xA4;
3578                 break;
3579             case 0x26:
3580                 /* U+30FB (0x8145) Katakana Middle Dot -> U+FF65 (0xA5) Halfwidth Katakana Middle Dot */
3581                 c = 0xA5;
3582                 break;
3583             case 0x3C:
3584                 /* U+30FC (0x815B) Katakana-Hiragana Prolonged Sound Mark -> U+FF70 (0xB0) Halfwidth Katakana-Hiragana Prolonged Sound Mark */
3585                 c = 0xB0;
3586                 break;
3587             case 0x2B:
3588                 /* U+309B (0x814A) Katakana-Hiragana Voiced Sound Mark -> U+FF9E (0xDE) Halfwidth Katakana Voiced Sound Mark */
3589                 c = 0xDE;
3590                 break;
3591             case 0x2C:
3592                 /* U+309C (0x814B) Katakana-Hiragana Semi-Voiced Sound Mark -> U+FF9F (0xDF) Halfwidth Katakana Semi-Voiced Sound Mark */
3593                 c = 0xDF;
3594                 break;
3595             }
3596             if (c) {
3597                 (*o_zconv)(JIS_X_0201_1976_K, c);
3598                 return;
3599             }
3600         } else if (c2 == 0x25) {
3601             /* JISX0208 Katakana */
3602             static const int fullwidth_to_halfwidth[] =
3603             {
3604                 0x0000, 0x2700, 0x3100, 0x2800, 0x3200, 0x2900, 0x3300, 0x2A00,
3605                 0x3400, 0x2B00, 0x3500, 0x3600, 0x365E, 0x3700, 0x375E, 0x3800,
3606                 0x385E, 0x3900, 0x395E, 0x3A00, 0x3A5E, 0x3B00, 0x3B5E, 0x3C00,
3607                 0x3C5E, 0x3D00, 0x3D5E, 0x3E00, 0x3E5E, 0x3F00, 0x3F5E, 0x4000,
3608                 0x405E, 0x4100, 0x415E, 0x2F00, 0x4200, 0x425E, 0x4300, 0x435E,
3609                 0x4400, 0x445E, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00,
3610                 0x4A5E, 0x4A5F, 0x4B00, 0x4B5E, 0x4B5F, 0x4C00, 0x4C5E, 0x4C5F,
3611                 0x4D00, 0x4D5E, 0x4D5F, 0x4E00, 0x4E5E, 0x4E5F, 0x4F00, 0x5000,
3612                 0x5100, 0x5200, 0x5300, 0x2C00, 0x5400, 0x2D00, 0x5500, 0x2E00,
3613                 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x0000, 0x5C00,
3614                 0x0000, 0x0000, 0x2600, 0x5D00, 0x335E, 0x0000, 0x0000, 0x0000,
3615                 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
3616             };
3617             if (fullwidth_to_halfwidth[c1-0x20]){
3618                 c2 = fullwidth_to_halfwidth[c1-0x20];
3619                 (*o_zconv)(JIS_X_0201_1976_K, c2>>8);
3620                 if (c2 & 0xFF) {
3621                     (*o_zconv)(JIS_X_0201_1976_K, c2&0xFF);
3622                 }
3623                 return;
3624             }
3625         }
3626     }
3627     (*o_zconv)(c2,c1);
3628 }
3629
3630
3631 #define rot13(c)  ( \
3632                    ( c < 'A') ? c: \
3633                    (c <= 'M')  ? (c + 13): \
3634                    (c <= 'Z')  ? (c - 13): \
3635                    (c < 'a')   ? (c): \
3636                    (c <= 'm')  ? (c + 13): \
3637                    (c <= 'z')  ? (c - 13): \
3638                    (c) \
3639                   )
3640
3641 #define  rot47(c) ( \
3642                    ( c < '!') ? c: \
3643                    ( c <= 'O') ? (c + 47) : \
3644                    ( c <= '~') ?  (c - 47) : \
3645                    c \
3646                   )
3647
3648 static void
3649 rot_conv(nkf_char c2, nkf_char c1)
3650 {
3651     if (c2 == 0 || c2 == JIS_X_0201_1976_K || c2 == ISO_8859_1) {
3652         c1 = rot13(c1);
3653     } else if (c2) {
3654         c1 = rot47(c1);
3655         c2 = rot47(c2);
3656     }
3657     (*o_rot_conv)(c2,c1);
3658 }
3659
3660 static void
3661 hira_conv(nkf_char c2, nkf_char c1)
3662 {
3663     if (hira_f & 1) {
3664         if (c2 == 0x25) {
3665             if (0x20 < c1 && c1 < 0x74) {
3666                 c2 = 0x24;
3667                 (*o_hira_conv)(c2,c1);
3668                 return;
3669             } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) {
3670                 c2 = 0;
3671                 c1 = nkf_char_unicode_new(0x3094);
3672                 (*o_hira_conv)(c2,c1);
3673                 return;
3674             }
3675         } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
3676             c1 += 2;
3677             (*o_hira_conv)(c2,c1);
3678             return;
3679         }
3680     }
3681     if (hira_f & 2) {
3682         if (c2 == 0 && c1 == nkf_char_unicode_new(0x3094)) {
3683             c2 = 0x25;
3684             c1 = 0x74;
3685         } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
3686             c2 = 0x25;
3687         } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
3688             c1 -= 2;
3689         }
3690     }
3691     (*o_hira_conv)(c2,c1);
3692 }
3693
3694
3695 static void
3696 iso2022jp_check_conv(nkf_char c2, nkf_char c1)
3697 {
3698 #define RANGE_NUM_MAX 18
3699     static const nkf_char range[RANGE_NUM_MAX][2] = {
3700         {0x222f, 0x2239,},
3701         {0x2242, 0x2249,},
3702         {0x2251, 0x225b,},
3703         {0x226b, 0x2271,},
3704         {0x227a, 0x227d,},
3705         {0x2321, 0x232f,},
3706         {0x233a, 0x2340,},
3707         {0x235b, 0x2360,},
3708         {0x237b, 0x237e,},
3709         {0x2474, 0x247e,},
3710         {0x2577, 0x257e,},
3711         {0x2639, 0x2640,},
3712         {0x2659, 0x267e,},
3713         {0x2742, 0x2750,},
3714         {0x2772, 0x277e,},
3715         {0x2841, 0x287e,},
3716         {0x4f54, 0x4f7e,},
3717         {0x7425, 0x747e},
3718     };
3719     nkf_char i;
3720     nkf_char start, end, c;
3721
3722     if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
3723         c2 = GETA1;
3724         c1 = GETA2;
3725     }
3726     if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
3727         c2 = GETA1;
3728         c1 = GETA2;
3729     }
3730
3731     for (i = 0; i < RANGE_NUM_MAX; i++) {
3732         start = range[i][0];
3733         end   = range[i][1];
3734         c     = (c2 << 8) + c1;
3735         if (c >= start && c <= end) {
3736             c2 = GETA1;
3737             c1 = GETA2;
3738         }
3739     }
3740     (*o_iso2022jp_check_conv)(c2,c1);
3741 }
3742
3743
3744 /* This converts  =?ISO-2022-JP?B?HOGE HOGE?= */
3745
3746 static const unsigned char *mime_pattern[] = {
3747     (const unsigned char *)"\075?EUC-JP?B?",
3748     (const unsigned char *)"\075?SHIFT_JIS?B?",
3749     (const unsigned char *)"\075?ISO-8859-1?Q?",
3750     (const unsigned char *)"\075?ISO-8859-1?B?",
3751     (const unsigned char *)"\075?ISO-2022-JP?B?",
3752     (const unsigned char *)"\075?ISO-2022-JP?Q?",
3753 #if defined(UTF8_INPUT_ENABLE)
3754     (const unsigned char *)"\075?UTF-8?B?",
3755     (const unsigned char *)"\075?UTF-8?Q?",
3756 #endif
3757     (const unsigned char *)"\075?US-ASCII?Q?",
3758     NULL
3759 };
3760
3761
3762 /* \e$B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u\e(B */
3763 nkf_char (*mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
3764     e_iconv, s_iconv, 0, 0, 0, 0,
3765 #if defined(UTF8_INPUT_ENABLE)
3766     w_iconv, w_iconv,
3767 #endif
3768     0,
3769 };
3770
3771 static const nkf_char mime_encode[] = {
3772     EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201_1976_K,
3773 #if defined(UTF8_INPUT_ENABLE)
3774     UTF_8, UTF_8,
3775 #endif
3776     ASCII,
3777     0
3778 };
3779
3780 static const nkf_char mime_encode_method[] = {
3781     'B', 'B','Q', 'B', 'B', 'Q',
3782 #if defined(UTF8_INPUT_ENABLE)
3783     'B', 'Q',
3784 #endif
3785     'Q',
3786     0
3787 };
3788
3789
3790 /* MIME preprocessor fifo */
3791
3792 #define MIME_BUF_SIZE   (1024)    /* 2^n ring buffer */
3793 #define MIME_BUF_MASK   (MIME_BUF_SIZE-1)
3794 #define mime_input_buf(n)        mime_input_state.buf[(n)&MIME_BUF_MASK]
3795 static struct {
3796     unsigned char buf[MIME_BUF_SIZE];
3797     unsigned int  top;
3798     unsigned int  last;  /* decoded */
3799     unsigned int  input; /* undecoded */
3800 } mime_input_state;
3801 static nkf_char (*mime_iconv_back)(nkf_char c2,nkf_char c1,nkf_char c0) = NULL;
3802
3803 #define MAXRECOVER 20
3804
3805 static void
3806 mime_input_buf_unshift(nkf_char c)
3807 {
3808     mime_input_buf(--mime_input_state.top) = (unsigned char)c;
3809 }
3810
3811 static nkf_char
3812 mime_ungetc(nkf_char c, FILE *f)
3813 {
3814     mime_input_buf_unshift(c);
3815     return c;
3816 }
3817
3818 static nkf_char
3819 mime_ungetc_buf(nkf_char c, FILE *f)
3820 {
3821     if (mimebuf_f)
3822         (*i_mungetc_buf)(c,f);
3823     else
3824         mime_input_buf(--mime_input_state.input) = (unsigned char)c;
3825     return c;
3826 }
3827
3828 static nkf_char
3829 mime_getc_buf(FILE *f)
3830 {
3831     /* we don't keep eof of mime_input_buf, becase it contains ?= as
3832        a terminator. It was checked in mime_integrity. */
3833     return ((mimebuf_f)?
3834             (*i_mgetc_buf)(f):mime_input_buf(mime_input_state.input++));
3835 }
3836
3837 static void
3838 switch_mime_getc(void)
3839 {
3840     if (i_getc!=mime_getc) {
3841         i_mgetc = i_getc; i_getc = mime_getc;
3842         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
3843         if(mime_f==STRICT_MIME) {
3844             i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
3845             i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
3846         }
3847     }
3848 }
3849
3850 static void
3851 unswitch_mime_getc(void)
3852 {
3853     if(mime_f==STRICT_MIME) {
3854         i_mgetc = i_mgetc_buf;
3855         i_mungetc = i_mungetc_buf;
3856     }
3857     i_getc = i_mgetc;
3858     i_ungetc = i_mungetc;
3859     if(mime_iconv_back)set_iconv(FALSE, mime_iconv_back);
3860     mime_iconv_back = NULL;
3861 }
3862
3863 static nkf_char
3864 mime_integrity(FILE *f, const unsigned char *p)
3865 {
3866     nkf_char c,d;
3867     unsigned int q;
3868     /* In buffered mode, read until =? or NL or buffer full
3869      */
3870     mime_input_state.input = mime_input_state.top;
3871     mime_input_state.last = mime_input_state.top;
3872
3873     while(*p) mime_input_buf(mime_input_state.input++) = *p++;
3874     d = 0;
3875     q = mime_input_state.input;
3876     while((c=(*i_getc)(f))!=EOF) {
3877         if (((mime_input_state.input-mime_input_state.top)&MIME_BUF_MASK)==0) {
3878             break;   /* buffer full */
3879         }
3880         if (c=='=' && d=='?') {
3881             /* checked. skip header, start decode */
3882             mime_input_buf(mime_input_state.input++) = (unsigned char)c;
3883             /* mime_last_input = mime_input_state.input; */
3884             mime_input_state.input = q;
3885             switch_mime_getc();
3886             return 1;
3887         }
3888         if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
3889             break;
3890         /* Should we check length mod 4? */
3891         mime_input_buf(mime_input_state.input++) = (unsigned char)c;
3892         d=c;
3893     }
3894     /* In case of Incomplete MIME, no MIME decode  */
3895     mime_input_buf(mime_input_state.input++) = (unsigned char)c;
3896     mime_input_state.last = mime_input_state.input;     /* point undecoded buffer */
3897     mime_decode_mode = 1;              /* no decode on mime_input_buf last in mime_getc */
3898     switch_mime_getc();         /* anyway we need buffered getc */
3899     return 1;
3900 }
3901
3902 static nkf_char
3903 mime_begin_strict(FILE *f)
3904 {
3905     nkf_char c1 = 0;
3906     int i,j,k;
3907     const unsigned char *p,*q;
3908     nkf_char r[MAXRECOVER];    /* recovery buffer, max mime pattern length */
3909
3910     mime_decode_mode = FALSE;
3911     /* =? has been checked */
3912     j = 0;
3913     p = mime_pattern[j];
3914     r[0]='='; r[1]='?';
3915
3916     for(i=2;p[i]>SP;i++) {                   /* start at =? */
3917         if (((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i]) {
3918             /* pattern fails, try next one */
3919             q = p;
3920             while (mime_pattern[++j]) {
3921                 p = mime_pattern[j];
3922                 for(k=2;k<i;k++)              /* assume length(p) > i */
3923                     if (p[k]!=q[k]) break;
3924                 if (k==i && nkf_toupper(c1)==p[k]) break;
3925             }
3926             p = mime_pattern[j];
3927             if (p) continue;  /* found next one, continue */
3928             /* all fails, output from recovery buffer */
3929             (*i_ungetc)(c1,f);
3930             for(j=0;j<i;j++) {
3931                 (*oconv)(0,r[j]);
3932             }
3933             return c1;
3934         }
3935     }
3936     mime_decode_mode = p[i-2];
3937
3938     mime_iconv_back = iconv;
3939     set_iconv(FALSE, mime_priority_func[j]);
3940     clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
3941
3942     if (mime_decode_mode=='B') {
3943         mimebuf_f = unbuf_f;
3944         if (!unbuf_f) {
3945             /* do MIME integrity check */
3946             return mime_integrity(f,mime_pattern[j]);
3947         }
3948     }
3949     switch_mime_getc();
3950     mimebuf_f = TRUE;
3951     return c1;
3952 }
3953
3954 static nkf_char
3955 mime_begin(FILE *f)
3956 {
3957     nkf_char c1;
3958     int i,k;
3959
3960     /* In NONSTRICT mode, only =? is checked. In case of failure, we  */
3961     /* re-read and convert again from mime_buffer.  */
3962
3963     /* =? has been checked */
3964     k = mime_input_state.last;
3965     mime_input_buf(mime_input_state.last++)='='; mime_input_buf(mime_input_state.last++)='?';
3966     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
3967         /* We accept any character type even if it is breaked by new lines */
3968         c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
3969         if (c1==LF||c1==SP||c1==CR||
3970             c1=='-'||c1=='_'||is_alnum(c1)) continue;
3971         if (c1=='=') {
3972             /* Failed. But this could be another MIME preemble */
3973             (*i_ungetc)(c1,f);
3974             mime_input_state.last--;
3975             break;
3976         }
3977         if (c1!='?') break;
3978         else {
3979             /* c1=='?' */
3980             c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
3981             if (!(++i<MAXRECOVER) || c1==EOF) break;
3982             if (c1=='b'||c1=='B') {
3983                 mime_decode_mode = 'B';
3984             } else if (c1=='q'||c1=='Q') {
3985                 mime_decode_mode = 'Q';
3986             } else {
3987                 break;
3988             }
3989             c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
3990             if (!(++i<MAXRECOVER) || c1==EOF) break;
3991             if (c1!='?') {
3992                 mime_decode_mode = FALSE;
3993             }
3994             break;
3995         }
3996     }
3997     switch_mime_getc();
3998     if (!mime_decode_mode) {
3999         /* false MIME premble, restart from mime_buffer */
4000         mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
4001         /* Since we are in MIME mode until buffer becomes empty,    */
4002         /* we never go into mime_begin again for a while.           */
4003         return c1;
4004     }
4005     /* discard mime preemble, and goto MIME mode */
4006     mime_input_state.last = k;
4007     /* do no MIME integrity check */
4008     return c1;   /* used only for checking EOF */
4009 }
4010
4011 #ifdef CHECK_OPTION
4012 static void
4013 no_putc(nkf_char c)
4014 {
4015     ;
4016 }
4017
4018 static void
4019 debug(const char *str)
4020 {
4021     if (debug_f){
4022         fprintf(stderr, "%s\n", str ? str : "NULL");
4023     }
4024 }
4025 #endif
4026
4027 static void
4028 set_input_codename(const char *codename)
4029 {
4030     if (!input_codename) {
4031         input_codename = codename;
4032     } else if (strcmp(codename, input_codename) != 0) {
4033         input_codename = "";
4034     }
4035 }
4036
4037 static const char*
4038 get_guessed_code(void)
4039 {
4040     if (input_codename && !*input_codename) {
4041         input_codename = "BINARY";
4042     } else {
4043         struct input_code *p = find_inputcode_byfunc(iconv);
4044         if (!input_codename) {
4045             input_codename = "ASCII";
4046         } else if (strcmp(input_codename, "Shift_JIS") == 0) {
4047             if (p->score & (SCORE_DEPEND|SCORE_CP932))
4048                 input_codename = "CP932";
4049         } else if (strcmp(input_codename, "EUC-JP") == 0) {
4050             if (p->score & (SCORE_X0212))
4051                 input_codename = "EUCJP-MS";
4052             else if (p->score & (SCORE_DEPEND|SCORE_CP932))
4053                 input_codename = "CP51932";
4054         } else if (strcmp(input_codename, "ISO-2022-JP") == 0) {
4055             if (p->score & (SCORE_KANA))
4056                 input_codename = "CP50221";
4057             else if (p->score & (SCORE_DEPEND|SCORE_CP932))
4058                 input_codename = "CP50220";
4059         }
4060     }
4061     return input_codename;
4062 }
4063
4064 #if !defined(PERL_XS) && !defined(WIN32DLL)
4065 static void
4066 print_guessed_code(char *filename)
4067 {
4068     if (filename != NULL) printf("%s: ", filename);
4069     if (input_codename && !*input_codename) {
4070         printf("BINARY\n");
4071     } else {
4072         input_codename = get_guessed_code();
4073         if (guess_f == 1) {
4074             printf("%s\n", input_codename);
4075         } else {
4076             printf("%s%s\n",
4077                    input_codename,
4078                    input_eol == CR   ? " (CR)" :
4079                    input_eol == LF   ? " (LF)" :
4080                    input_eol == CRLF ? " (CRLF)" :
4081                    input_eol == EOF  ? " (MIXED NL)" :
4082                    "");
4083         }
4084     }
4085 }
4086 #endif /*WIN32DLL*/
4087
4088 #ifdef INPUT_OPTION
4089
4090 static nkf_char
4091 hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f))
4092 {
4093     nkf_char c1, c2, c3;
4094     c1 = (*g)(f);
4095     if (c1 != ch){
4096         return c1;
4097     }
4098     c2 = (*g)(f);
4099     if (!nkf_isxdigit(c2)){
4100         (*u)(c2, f);
4101         return c1;
4102     }
4103     c3 = (*g)(f);
4104     if (!nkf_isxdigit(c3)){
4105         (*u)(c2, f);
4106         (*u)(c3, f);
4107         return c1;
4108     }
4109     return (hex2bin(c2) << 4) | hex2bin(c3);
4110 }
4111
4112 static nkf_char
4113 cap_getc(FILE *f)
4114 {
4115     return hex_getc(':', f, i_cgetc, i_cungetc);
4116 }
4117
4118 static nkf_char
4119 cap_ungetc(nkf_char c, FILE *f)
4120 {
4121     return (*i_cungetc)(c, f);
4122 }
4123
4124 static nkf_char
4125 url_getc(FILE *f)
4126 {
4127     return hex_getc('%', f, i_ugetc, i_uungetc);
4128 }
4129
4130 static nkf_char
4131 url_ungetc(nkf_char c, FILE *f)
4132 {
4133     return (*i_uungetc)(c, f);
4134 }
4135 #endif
4136
4137 #ifdef NUMCHAR_OPTION
4138 static nkf_char
4139 numchar_getc(FILE *f)
4140 {
4141     nkf_char (*g)(FILE *) = i_ngetc;
4142     nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc;
4143     int i = 0, j;
4144     nkf_char buf[12];
4145     long c = -1;
4146
4147     buf[i] = (*g)(f);
4148     if (buf[i] == '&'){
4149         buf[++i] = (*g)(f);
4150         if (buf[i] == '#'){
4151             c = 0;
4152             buf[++i] = (*g)(f);
4153             if (buf[i] == 'x' || buf[i] == 'X'){
4154                 for (j = 0; j < 7; j++){
4155                     buf[++i] = (*g)(f);
4156                     if (!nkf_isxdigit(buf[i])){
4157                         if (buf[i] != ';'){
4158                             c = -1;
4159                         }
4160                         break;
4161                     }
4162                     c <<= 4;
4163                     c |= hex2bin(buf[i]);
4164                 }
4165             }else{
4166                 for (j = 0; j < 8; j++){
4167                     if (j){
4168                         buf[++i] = (*g)(f);
4169                     }
4170                     if (!nkf_isdigit(buf[i])){
4171                         if (buf[i] != ';'){
4172                             c = -1;
4173                         }
4174                         break;
4175                     }
4176                     c *= 10;
4177                     c += hex2bin(buf[i]);
4178                 }
4179             }
4180         }
4181     }
4182     if (c != -1){
4183         return nkf_char_unicode_new(c);
4184     }
4185     while (i > 0){
4186         (*u)(buf[i], f);
4187         --i;
4188     }
4189     return buf[0];
4190 }
4191
4192 static nkf_char
4193 numchar_ungetc(nkf_char c, FILE *f)
4194 {
4195     return (*i_nungetc)(c, f);
4196 }
4197 #endif
4198
4199 #ifdef UNICODE_NORMALIZATION
4200
4201 /* Normalization Form C */
4202 static nkf_char
4203 nfc_getc(FILE *f)
4204 {
4205     nkf_char (*g)(FILE *f) = i_nfc_getc;
4206     nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
4207     int i=0, j, k=1, lower, upper;
4208     nkf_char buf[9];
4209     const unsigned char *array;
4210
4211     buf[i] = (*g)(f);
4212     while (k > 0 && ((buf[i] & 0xc0) != 0x80)){
4213         lower=0, upper=NORMALIZATION_TABLE_LENGTH-1;
4214         while (upper >= lower) {
4215             j = (lower+upper) / 2;
4216             array = normalization_table[j].nfd;
4217             for (k=0; k < NORMALIZATION_TABLE_NFD_LENGTH && array[k]; k++){
4218                 if (array[k] != buf[k]){
4219                     array[k] < buf[k] ? (lower = j + 1) : (upper = j - 1);
4220                     k = 0;
4221                     break;
4222                 } else if (k >= i)
4223                     buf[++i] = (*g)(f);
4224             }
4225             if (k > 0){
4226                 array = normalization_table[j].nfc;
4227                 for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++)
4228                     buf[i] = (nkf_char)(array[i]);
4229                 i--;
4230                 break;
4231             }
4232         }
4233         while (i > 0)
4234             (*u)(buf[i--], f);
4235     }
4236     return buf[0];
4237 }
4238
4239 static nkf_char
4240 nfc_ungetc(nkf_char c, FILE *f)
4241 {
4242     return (*i_nfc_ungetc)(c, f);
4243 }
4244 #endif /* UNICODE_NORMALIZATION */
4245
4246
4247 static nkf_char
4248 base64decode(nkf_char c)
4249 {
4250     int             i;
4251     if (c > '@') {
4252         if (c < '[') {
4253             i = c - 'A';                        /* A..Z 0-25 */
4254         } else if (c == '_') {
4255             i = '?'         /* 63 */ ;          /* _  63 */
4256         } else {
4257             i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
4258         }
4259     } else if (c > '/') {
4260         i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
4261     } else if (c == '+' || c == '-') {
4262         i = '>'             /* 62 */ ;          /* + and -  62 */
4263     } else {
4264         i = '?'             /* 63 */ ;          /* / 63 */
4265     }
4266     return (i);
4267 }
4268
4269 static nkf_char
4270 mime_getc(FILE *f)
4271 {
4272     nkf_char c1, c2, c3, c4, cc;
4273     nkf_char t1, t2, t3, t4, mode, exit_mode;
4274     nkf_char lwsp_count;
4275     char *lwsp_buf;
4276     char *lwsp_buf_new;
4277     nkf_char lwsp_size = 128;
4278
4279     if (mime_input_state.top != mime_input_state.last) {  /* Something is in FIFO */
4280         return  mime_input_buf(mime_input_state.top++);
4281     }
4282     if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
4283         mime_decode_mode=FALSE;
4284         unswitch_mime_getc();
4285         return (*i_getc)(f);
4286     }
4287
4288     if (mimebuf_f == FIXED_MIME)
4289         exit_mode = mime_decode_mode;
4290     else
4291         exit_mode = FALSE;
4292     if (mime_decode_mode == 'Q') {
4293         if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
4294       restart_mime_q:
4295         if (c1=='_' && mimebuf_f != FIXED_MIME) return SP;
4296         if (c1<=SP || DEL<=c1) {
4297             mime_decode_mode = exit_mode; /* prepare for quit */
4298             return c1;
4299         }
4300         if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) {
4301             return c1;
4302         }
4303
4304         mime_decode_mode = exit_mode; /* prepare for quit */
4305         if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
4306         if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
4307             /* end Q encoding */
4308             input_mode = exit_mode;
4309             lwsp_count = 0;
4310             lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
4311             if (lwsp_buf==NULL) {
4312                 perror("can't malloc");
4313                 return -1;
4314             }
4315             while ((c1=(*i_getc)(f))!=EOF) {
4316                 switch (c1) {
4317                 case LF:
4318                 case CR:
4319                     if (c1==LF) {
4320                         if ((c1=(*i_getc)(f))!=EOF && (c1==SP||c1==TAB)) {
4321                             i_ungetc(SP,f);
4322                             continue;
4323                         } else {
4324                             i_ungetc(c1,f);
4325                         }
4326                         c1 = LF;
4327                     } else {
4328                         if ((c1=(*i_getc)(f))!=EOF && c1 == LF) {
4329                             if ((c1=(*i_getc)(f))!=EOF && (c1==SP||c1==TAB)) {
4330                                 i_ungetc(SP,f);
4331                                 continue;
4332                             } else {
4333                                 i_ungetc(c1,f);
4334                             }
4335                             i_ungetc(LF,f);
4336                         } else {
4337                             i_ungetc(c1,f);
4338                         }
4339                         c1 = CR;
4340                     }
4341                     break;
4342                 case SP:
4343                 case TAB:
4344                     lwsp_buf[lwsp_count] = (unsigned char)c1;
4345                     if (lwsp_count++>lwsp_size){
4346                         lwsp_size <<= 1;
4347                         lwsp_buf_new = realloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
4348                         if (lwsp_buf_new==NULL) {
4349                             free(lwsp_buf);
4350                             perror("can't realloc");
4351                             return -1;
4352                         }
4353                         lwsp_buf = lwsp_buf_new;
4354                     }
4355                     continue;
4356                 }
4357                 break;
4358             }
4359             if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SP && lwsp_buf[lwsp_count-1] != TAB))) {
4360                 i_ungetc(c1,f);
4361                 for(lwsp_count--;lwsp_count>0;lwsp_count--)
4362                     i_ungetc(lwsp_buf[lwsp_count],f);
4363                 c1 = lwsp_buf[0];
4364             }
4365             free(lwsp_buf);
4366             return c1;
4367         }
4368         if (c1=='='&&c2<SP) { /* this is soft wrap */
4369             while((c1 =  (*i_mgetc)(f)) <=SP) {
4370                 if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
4371             }
4372             mime_decode_mode = 'Q'; /* still in MIME */
4373             goto restart_mime_q;
4374         }
4375         if (c1=='?') {
4376             mime_decode_mode = 'Q'; /* still in MIME */
4377             (*i_mungetc)(c2,f);
4378             return c1;
4379         }
4380         if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
4381         if (c2<=SP) return c2;
4382         mime_decode_mode = 'Q'; /* still in MIME */
4383         return ((hex2bin(c2)<<4) + hex2bin(c3));
4384     }
4385
4386     if (mime_decode_mode != 'B') {
4387         mime_decode_mode = FALSE;
4388         return (*i_mgetc)(f);
4389     }
4390
4391
4392     /* Base64 encoding */
4393     /*
4394        MIME allows line break in the middle of
4395        Base64, but we are very pessimistic in decoding
4396        in unbuf mode because MIME encoded code may broken by
4397        less or editor's control sequence (such as ESC-[-K in unbuffered
4398        mode. ignore incomplete MIME.
4399      */
4400     mode = mime_decode_mode;
4401     mime_decode_mode = exit_mode;  /* prepare for quit */
4402
4403     while ((c1 = (*i_mgetc)(f))<=SP) {
4404         if (c1==EOF)
4405             return (EOF);
4406     }
4407   mime_c2_retry:
4408     if ((c2 = (*i_mgetc)(f))<=SP) {
4409         if (c2==EOF)
4410             return (EOF);
4411         if (mime_f != STRICT_MIME) goto mime_c2_retry;
4412         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
4413         return c2;
4414     }
4415     if ((c1 == '?') && (c2 == '=')) {
4416         input_mode = ASCII;
4417         lwsp_count = 0;
4418         lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
4419         if (lwsp_buf==NULL) {
4420             perror("can't malloc");
4421             return -1;
4422         }
4423         while ((c1=(*i_getc)(f))!=EOF) {
4424             switch (c1) {
4425             case LF:
4426             case CR:
4427                 if (c1==LF) {
4428                     if ((c1=(*i_getc)(f))!=EOF && (c1==SP||c1==TAB)) {
4429                         i_ungetc(SP,f);
4430                         continue;
4431                     } else {
4432                         i_ungetc(c1,f);
4433                     }
4434                     c1 = LF;
4435                 } else {
4436                     if ((c1=(*i_getc)(f))!=EOF) {
4437                         if (c1==SP) {
4438                             i_ungetc(SP,f);
4439                             continue;
4440                         } else if ((c1=(*i_getc)(f))!=EOF && (c1==SP||c1==TAB)) {
4441                             i_ungetc(SP,f);
4442                             continue;
4443                         } else {
4444                             i_ungetc(c1,f);
4445                         }
4446                         i_ungetc(LF,f);
4447                     } else {
4448                         i_ungetc(c1,f);
4449                     }
4450                     c1 = CR;
4451                 }
4452                 break;
4453             case SP:
4454             case TAB:
4455                 lwsp_buf[lwsp_count] = (unsigned char)c1;
4456                 if (lwsp_count++>lwsp_size){
4457                     lwsp_size <<= 1;
4458                     lwsp_buf_new = realloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
4459                     if (lwsp_buf_new==NULL) {
4460                         free(lwsp_buf);
4461                         perror("can't realloc");
4462                         return -1;
4463                     }
4464                     lwsp_buf = lwsp_buf_new;
4465                 }
4466                 continue;
4467             }
4468             break;
4469         }
4470         if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SP && lwsp_buf[lwsp_count-1] != TAB))) {
4471             i_ungetc(c1,f);
4472             for(lwsp_count--;lwsp_count>0;lwsp_count--)
4473                 i_ungetc(lwsp_buf[lwsp_count],f);
4474             c1 = lwsp_buf[0];
4475         }
4476         free(lwsp_buf);
4477         return c1;
4478     }
4479   mime_c3_retry:
4480     if ((c3 = (*i_mgetc)(f))<=SP) {
4481         if (c3==EOF)
4482             return (EOF);
4483         if (mime_f != STRICT_MIME) goto mime_c3_retry;
4484         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
4485         return c3;
4486     }
4487   mime_c4_retry:
4488     if ((c4 = (*i_mgetc)(f))<=SP) {
4489         if (c4==EOF)
4490