OSDN Git Service

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