OSDN Git Service

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