OSDN Git Service

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