OSDN Git Service

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