OSDN Git Service

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