OSDN Git Service

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