OSDN Git Service

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