OSDN Git Service

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