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