OSDN Git Service

* EOF problem
[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.110 2006/09/15 11:04:36 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                     if (iconv == w_iconv32) {
2423                         input_endian = ENDIAN_BIG;
2424                         return;
2425                     }
2426                     (*i_ungetc)(0xFF,f);
2427                 }else (*i_ungetc)(c2,f);
2428                 (*i_ungetc)(0xFE,f);
2429             }else if(c2 == 0xFF){
2430                 if((c2 = (*i_getc)(f)) == 0xFE){
2431                     if(!input_f){
2432                         set_iconv(TRUE, w_iconv32);
2433                     }
2434                     if (iconv == w_iconv32) {
2435                         input_endian = ENDIAN_2143;
2436                         return;
2437                     }
2438                     (*i_ungetc)(0xFF,f);
2439                 }else (*i_ungetc)(c2,f);
2440                 (*i_ungetc)(0xFF,f);
2441             }else (*i_ungetc)(c2,f);
2442             (*i_ungetc)(0x00,f);
2443         }else (*i_ungetc)(c2,f);
2444         (*i_ungetc)(0x00,f);
2445         break;
2446     case 0xEF:
2447         if((c2 = (*i_getc)(f)) == 0xBB){
2448             if((c2 = (*i_getc)(f)) == 0xBF){
2449                 if(!input_f){
2450                     set_iconv(TRUE, w_iconv);
2451                 }
2452                 if (iconv == w_iconv) {
2453                     return;
2454                 }
2455                 (*i_ungetc)(0xBF,f);
2456             }else (*i_ungetc)(c2,f);
2457             (*i_ungetc)(0xBB,f);
2458         }else (*i_ungetc)(c2,f);
2459         (*i_ungetc)(0xEF,f);
2460         break;
2461     case 0xFE:
2462         if((c2 = (*i_getc)(f)) == 0xFF){
2463             if((c2 = (*i_getc)(f)) == 0x00){
2464                 if((c2 = (*i_getc)(f)) == 0x00){
2465                     if(!input_f){
2466                         set_iconv(TRUE, w_iconv32);
2467                     }
2468                     if (iconv == w_iconv32) {
2469                         input_endian = ENDIAN_3412;
2470                         return;
2471                     }
2472                     (*i_ungetc)(0x00,f);
2473                 }else (*i_ungetc)(c2,f);
2474                 (*i_ungetc)(0x00,f);
2475             }else (*i_ungetc)(c2,f);
2476             if(!input_f){
2477                 set_iconv(TRUE, w_iconv16);
2478             }
2479             if (iconv == w_iconv16) {
2480                 input_endian = ENDIAN_BIG;
2481                 return;
2482             }
2483             (*i_ungetc)(0xFF,f);
2484         }else (*i_ungetc)(c2,f);
2485         (*i_ungetc)(0xFE,f);
2486         break;
2487     case 0xFF:
2488         if((c2 = (*i_getc)(f)) == 0xFE){
2489             if((c2 = (*i_getc)(f)) == 0x00){
2490                 if((c2 = (*i_getc)(f)) == 0x00){
2491                     if(!input_f){
2492                         set_iconv(TRUE, w_iconv32);
2493                     }
2494                     if (iconv == w_iconv32) {
2495                         input_endian = ENDIAN_LITTLE;
2496                         return;
2497                     }
2498                     (*i_ungetc)(0x00,f);
2499                 }else (*i_ungetc)(c2,f);
2500                 (*i_ungetc)(0x00,f);
2501             }else (*i_ungetc)(c2,f);
2502             if(!input_f){
2503                 set_iconv(TRUE, w_iconv16);
2504             }
2505             if (iconv == w_iconv16) {
2506                 input_endian = ENDIAN_LITTLE;
2507                 return;
2508             }
2509             (*i_ungetc)(0xFE,f);
2510         }else (*i_ungetc)(c2,f);
2511         (*i_ungetc)(0xFF,f);
2512         break;
2513     default:
2514         (*i_ungetc)(c2,f);
2515         break;
2516     }
2517 }
2518
2519 /*
2520    Conversion main loop. Code detection only. 
2521  */
2522
2523 nkf_char kanji_convert(FILE *f)
2524 {
2525     nkf_char    c3, c2=0, c1, c0=0;
2526     int is_8bit = FALSE;
2527
2528     if(input_f == SJIS_INPUT || input_f == EUC_INPUT
2529 #ifdef UTF8_INPUT_ENABLE
2530        || input_f == UTF8_INPUT || input_f == UTF16_INPUT
2531 #endif
2532       ){
2533         is_8bit = TRUE;
2534     }
2535
2536     input_mode = ASCII;
2537     output_mode = ASCII;
2538     shift_mode = FALSE;
2539
2540 #define NEXT continue      /* no output, get next */
2541 #define SEND ;             /* output c1 and c2, get next */
2542 #define LAST break         /* end of loop, go closing  */
2543
2544     module_connection();
2545     check_bom(f);
2546
2547     while ((c1 = (*i_getc)(f)) != EOF) {
2548 #ifdef INPUT_CODE_FIX
2549         if (!input_f)
2550 #endif
2551             code_status(c1);
2552         if (c2) {
2553             /* second byte */
2554             if (c2 > DEL) {
2555                 /* in case of 8th bit is on */
2556                 if (!estab_f&&!mime_decode_mode) {
2557                     /* in case of not established yet */
2558                     /* It is still ambiguious */
2559                     if (h_conv(f, c2, c1)==EOF) 
2560                         LAST;
2561                     else 
2562                         c2 = 0;
2563                     NEXT;
2564                 } else
2565                     /* in case of already established */
2566                     if (c1 < AT) {
2567                         /* ignore bogus code */
2568                         c2 = 0;
2569                         NEXT;
2570                     } else
2571                         SEND;
2572             } else
2573                 /* second byte, 7 bit code */
2574                 /* it might be kanji shitfted */
2575                 if ((c1 == DEL) || (c1 <= SPACE)) {
2576                     /* ignore bogus first code */
2577                     c2 = 0;
2578                     NEXT;
2579                 } else
2580                     SEND;
2581         } else {
2582             /* first byte */
2583 #ifdef UTF8_INPUT_ENABLE
2584             if (iconv == w_iconv16) {
2585                 if (input_endian == ENDIAN_BIG) {
2586                     c2 = c1;
2587                     if ((c1 = (*i_getc)(f)) != EOF) {
2588                         if (0xD8 <= c2 && c2 <= 0xDB) {
2589                             if ((c0 = (*i_getc)(f)) != EOF) {
2590                                 c0 <<= 8;
2591                                 if ((c3 = (*i_getc)(f)) != EOF) {
2592                                     c0 |= c3;
2593                                 } else c2 = EOF;
2594                             } else c2 = EOF;
2595                         }
2596                     } else c2 = EOF;
2597                 } else {
2598                     if ((c2 = (*i_getc)(f)) != EOF) {
2599                         if (0xD8 <= c2 && c2 <= 0xDB) {
2600                             if ((c3 = (*i_getc)(f)) != EOF) {
2601                                 if ((c0 = (*i_getc)(f)) != EOF) {
2602                                     c0 <<= 8;
2603                                     c0 |= c3;
2604                                 } else c2 = EOF;
2605                             } else c2 = EOF;
2606                         }
2607                     } else c2 = EOF;
2608                 }
2609                 SEND;
2610             } else if(iconv == w_iconv32){
2611                 int c3 = c1;
2612                 if((c2 = (*i_getc)(f)) != EOF &&
2613                    (c1 = (*i_getc)(f)) != EOF &&
2614                    (c0 = (*i_getc)(f)) != EOF){
2615                     switch(input_endian){
2616                     case ENDIAN_BIG:
2617                         c1 = (c2&0xFF)<<16 | (c1&0xFF)<<8 | (c0&0xFF);
2618                         break;
2619                     case ENDIAN_LITTLE:
2620                         c1 = (c3&0xFF) | (c2&0xFF)<<8 | (c1&0xFF)<<16;
2621                         break;
2622                     case ENDIAN_2143:
2623                         c1 = (c3&0xFF)<<16 | (c1&0xFF) | (c0&0xFF)<<8;
2624                         break;
2625                     case ENDIAN_3412:
2626                         c1 = (c3&0xFF)<<8 | (c2&0xFF) | (c0&0xFF)<<16;
2627                         break;
2628                     }
2629                     c2 = 0;
2630                 }else{
2631                     c2 = EOF;
2632                 }
2633                 SEND;
2634             } else
2635 #endif
2636 #ifdef NUMCHAR_OPTION
2637             if (is_unicode_capsule(c1)){
2638                 SEND;
2639             } else
2640 #endif
2641             if (c1 > DEL) {
2642                 /* 8 bit code */
2643                 if (!estab_f && !iso8859_f) {
2644                     /* not established yet */
2645                     c2 = c1;
2646                     NEXT;
2647                 } else { /* estab_f==TRUE */
2648                     if (iso8859_f) {
2649                         c2 = ISO8859_1;
2650                         c1 &= 0x7f;
2651                         SEND;
2652                     } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
2653                         /* SJIS X0201 Case... */
2654                         if(iso2022jp_f && x0201_f==NO_X0201) {
2655                             (*oconv)(GETA1, GETA2);
2656                             NEXT;
2657                         } else {
2658                             c2 = X0201;
2659                             c1 &= 0x7f;
2660                             SEND;
2661                         }
2662                     } else if (c1==SSO && iconv != s_iconv) {
2663                         /* EUC X0201 Case */
2664                         c1 = (*i_getc)(f);  /* skip SSO */
2665                         code_status(c1);
2666                         if (SSP<=c1 && c1<0xe0) {
2667                             if(iso2022jp_f &&  x0201_f==NO_X0201) {
2668                                 (*oconv)(GETA1, GETA2);
2669                                 NEXT;
2670                             } else {
2671                                 c2 = X0201;
2672                                 c1 &= 0x7f;
2673                                 SEND;
2674                             }
2675                         } else  { /* bogus code, skip SSO and one byte */
2676                             NEXT;
2677                         }
2678                     } else {
2679                        /* already established */
2680                        c2 = c1;
2681                        NEXT;
2682                     }
2683                 }
2684             } else if ((c1 > SPACE) && (c1 != DEL)) {
2685                 /* in case of Roman characters */
2686                 if (shift_mode) { 
2687                     /* output 1 shifted byte */
2688                     if (iso8859_f) {
2689                         c2 = ISO8859_1;
2690                         SEND;
2691                     } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
2692                       /* output 1 shifted byte */
2693                         if(iso2022jp_f && x0201_f==NO_X0201) {
2694                             (*oconv)(GETA1, GETA2);
2695                             NEXT;
2696                         } else {
2697                             c2 = X0201;
2698                             SEND;
2699                         }
2700                     } else {
2701                         /* look like bogus code */
2702                         NEXT;
2703                     }
2704                 } else if (input_mode == X0208 || input_mode == X0212 ||
2705                            input_mode == X0213_1 || input_mode == X0213_2) {
2706                     /* in case of Kanji shifted */
2707                     c2 = c1;
2708                     NEXT;
2709                 } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
2710                     /* Check MIME code */
2711                     if ((c1 = (*i_getc)(f)) == EOF) {
2712                         (*oconv)(0, '=');
2713                         LAST;
2714                     } else if (c1 == '?') {
2715                         /* =? is mime conversion start sequence */
2716                         if(mime_f == STRICT_MIME) {
2717                             /* check in real detail */
2718                             if (mime_begin_strict(f) == EOF) 
2719                                 LAST;
2720                             else
2721                                 NEXT;
2722                         } else if (mime_begin(f) == EOF) 
2723                             LAST;
2724                         else
2725                             NEXT;
2726                     } else {
2727                         (*oconv)(0, '=');
2728                         (*i_ungetc)(c1,f);
2729                         NEXT;
2730                     }
2731                 } else {
2732                     /* normal ASCII code */ 
2733                     SEND;
2734                 }
2735             } else if (!is_8bit && c1 == SI) {
2736                 shift_mode = FALSE; 
2737                 NEXT;
2738             } else if (!is_8bit && c1 == SO) {
2739                 shift_mode = TRUE; 
2740                 NEXT;
2741             } else if (!is_8bit && c1 == ESC ) {
2742                 if ((c1 = (*i_getc)(f)) == EOF) {
2743                     /*  (*oconv)(0, ESC); don't send bogus code */
2744                     LAST;
2745                 } else if (c1 == '$') {
2746                     if ((c1 = (*i_getc)(f)) == EOF) {
2747                         /*
2748                         (*oconv)(0, ESC); don't send bogus code 
2749                         (*oconv)(0, '$'); */
2750                         LAST;
2751                     } else if (c1 == '@'|| c1 == 'B') {
2752                         /* This is kanji introduction */
2753                         input_mode = X0208;
2754                         shift_mode = FALSE;
2755                         set_input_codename("ISO-2022-JP");
2756 #ifdef CHECK_OPTION
2757                         debug(input_codename);
2758 #endif
2759                         NEXT;
2760                     } else if (c1 == '(') {
2761                         if ((c1 = (*i_getc)(f)) == EOF) {
2762                             /* don't send bogus code 
2763                             (*oconv)(0, ESC);
2764                             (*oconv)(0, '$');
2765                             (*oconv)(0, '(');
2766                                 */
2767                             LAST;
2768                         } else if (c1 == '@'|| c1 == 'B') {
2769                             /* This is kanji introduction */
2770                             input_mode = X0208;
2771                             shift_mode = FALSE;
2772                             NEXT;
2773 #ifdef X0212_ENABLE
2774                         } else if (c1 == 'D'){
2775                             input_mode = X0212;
2776                             shift_mode = FALSE;
2777                             NEXT;
2778 #endif /* X0212_ENABLE */
2779                         } else if (c1 == (X0213_1&0x7F)){
2780                             input_mode = X0213_1;
2781                             shift_mode = FALSE;
2782                             NEXT;
2783                         } else if (c1 == (X0213_2&0x7F)){
2784                             input_mode = X0213_2;
2785                             shift_mode = FALSE;
2786                             NEXT;
2787                         } else {
2788                             /* could be some special code */
2789                             (*oconv)(0, ESC);
2790                             (*oconv)(0, '$');
2791                             (*oconv)(0, '(');
2792                             (*oconv)(0, c1);
2793                             NEXT;
2794                         }
2795                     } else if (broken_f&0x2) {
2796                         /* accept any ESC-(-x as broken code ... */
2797                         input_mode = X0208;
2798                         shift_mode = FALSE;
2799                         NEXT;
2800                     } else {
2801                         (*oconv)(0, ESC);
2802                         (*oconv)(0, '$');
2803                         (*oconv)(0, c1);
2804                         NEXT;
2805                     }
2806                 } else if (c1 == '(') {
2807                     if ((c1 = (*i_getc)(f)) == EOF) {
2808                         /* don't send bogus code 
2809                         (*oconv)(0, ESC);
2810                         (*oconv)(0, '('); */
2811                         LAST;
2812                     } else {
2813                         if (c1 == 'I') {
2814                             /* This is X0201 kana introduction */
2815                             input_mode = X0201; shift_mode = X0201;
2816                             NEXT;
2817                         } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
2818                             /* This is X0208 kanji introduction */
2819                             input_mode = ASCII; shift_mode = FALSE;
2820                             NEXT;
2821                         } else if (broken_f&0x2) {
2822                             input_mode = ASCII; shift_mode = FALSE;
2823                             NEXT;
2824                         } else {
2825                             (*oconv)(0, ESC);
2826                             (*oconv)(0, '(');
2827                             /* maintain various input_mode here */
2828                             SEND;
2829                         }
2830                     }
2831                } else if ( c1 == 'N' || c1 == 'n' ){
2832                    /* SS2 */
2833                    c3 = (*i_getc)(f);  /* skip SS2 */
2834                    if ( (SPACE<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
2835                        c1 = c3;
2836                        c2 = X0201;
2837                        SEND;
2838                    }else{
2839                        (*i_ungetc)(c3, f);
2840                        /* lonely ESC  */
2841                        (*oconv)(0, ESC);
2842                        SEND;
2843                    }
2844                 } else {
2845                     /* lonely ESC  */
2846                     (*oconv)(0, ESC);
2847                     SEND;
2848                 }
2849             } else if ((c1 == NL || c1 == CR) && broken_f&4) {
2850                 input_mode = ASCII; set_iconv(FALSE, 0);
2851                 SEND;
2852             } else if (c1 == NL && mime_decode_f && !mime_decode_mode ) {
2853                 if ((c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
2854                     i_ungetc(SPACE,f);
2855                     continue;
2856                 } else {
2857                     i_ungetc(c1,f);
2858                 }
2859                 c1 = NL;
2860                 SEND;
2861             } else if (c1 == CR && mime_decode_f && !mime_decode_mode ) {
2862                 if ((c1=(*i_getc)(f))!=EOF) {
2863                     if (c1==SPACE) {
2864                         i_ungetc(SPACE,f);
2865                         continue;
2866                     } else if (c1 == NL && (c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
2867                         i_ungetc(SPACE,f);
2868                         continue;
2869                     } else {
2870                         i_ungetc(c1,f);
2871                     }
2872                     i_ungetc(NL,f);
2873                 } else {
2874                     i_ungetc(c1,f);
2875                 }
2876                 c1 = CR;
2877                 SEND;
2878             } else 
2879                 SEND;
2880         }
2881         /* send: */
2882         switch(input_mode){
2883         case ASCII:
2884             switch ((*iconv)(c2, c1, c0)) {  /* can be EUC / SJIS / UTF-8 / UTF-16 */
2885             case -2:
2886                 /* 4 bytes UTF-8 */
2887                 if ((c0 = (*i_getc)(f)) != EOF) {
2888                     code_status(c0);
2889                     c0 <<= 8;
2890                     if ((c3 = (*i_getc)(f)) != EOF) {
2891                         code_status(c3);
2892                         (*iconv)(c2, c1, c0|c3);
2893                     }
2894                 }
2895                 break;
2896             case -1:
2897                 /* 3 bytes EUC or UTF-8 */
2898                 if ((c0 = (*i_getc)(f)) != EOF) {
2899                     code_status(c0);
2900                     (*iconv)(c2, c1, c0);
2901                 }
2902                 break;
2903             }
2904             break;
2905         case X0208:
2906         case X0213_1:
2907             (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
2908             break;
2909 #ifdef X0212_ENABLE
2910         case X0212:
2911             (*oconv)(PREFIX_EUCG3 | c2, c1);
2912             break;
2913 #endif /* X0212_ENABLE */
2914         case X0213_2:
2915             (*oconv)(PREFIX_EUCG3 | c2, c1);
2916             break;
2917         default:
2918             (*oconv)(input_mode, c1);  /* other special case */
2919         }
2920
2921         c2 = 0;
2922         c0 = 0;
2923         continue;
2924         /* goto next_word */
2925     }
2926
2927     /* epilogue */
2928     (*iconv)(EOF, 0, 0);
2929     if (!is_inputcode_set)
2930     {
2931         if (is_8bit) {
2932             struct input_code *p = input_code_list;
2933             struct input_code *result = p;
2934             while (p->name){
2935                 if (p->score < result->score) result = p;
2936                 ++p;
2937             }
2938             set_input_codename(result->name);
2939         }
2940     }
2941     return 1;
2942 }
2943
2944 nkf_char
2945 h_conv(FILE *f, nkf_char c2, nkf_char c1)
2946 {
2947     nkf_char ret, c3, c0;
2948     int hold_index;
2949
2950
2951     /** it must NOT be in the kanji shifte sequence      */
2952     /** it must NOT be written in JIS7                   */
2953     /** and it must be after 2 byte 8bit code            */
2954
2955     hold_count = 0;
2956     push_hold_buf(c2);
2957     push_hold_buf(c1);
2958
2959     while ((c1 = (*i_getc)(f)) != EOF) {
2960         if (c1 == ESC){
2961             (*i_ungetc)(c1,f);
2962             break;
2963         }
2964         code_status(c1);
2965         if (push_hold_buf(c1) == EOF || estab_f){
2966             break;
2967         }
2968     }
2969
2970     if (!estab_f){
2971         struct input_code *p = input_code_list;
2972         struct input_code *result = p;
2973         if (c1 == EOF){
2974             code_status(c1);
2975         }
2976         while (p->name){
2977             if (p->score < result->score){
2978                 result = p;
2979             }
2980             ++p;
2981         }
2982         set_iconv(FALSE, result->iconv_func);
2983     }
2984
2985
2986     /** now,
2987      ** 1) EOF is detected, or
2988      ** 2) Code is established, or
2989      ** 3) Buffer is FULL (but last word is pushed)
2990      **
2991      ** in 1) and 3) cases, we continue to use
2992      ** Kanji codes by oconv and leave estab_f unchanged.
2993      **/
2994
2995     ret = c1;
2996     hold_index = 0;
2997     while (hold_index < hold_count){
2998         c2 = hold_buf[hold_index++];
2999         if (c2 <= DEL
3000 #ifdef NUMCHAR_OPTION
3001             || is_unicode_capsule(c2)
3002 #endif
3003             ){
3004             (*iconv)(0, c2, 0);
3005             continue;
3006         }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
3007             (*iconv)(X0201, c2, 0);
3008             continue;
3009         }
3010         if (hold_index < hold_count){
3011             c1 = hold_buf[hold_index++];
3012         }else{
3013             c1 = (*i_getc)(f);
3014             if (c1 == EOF){
3015                 c3 = EOF;
3016                 break;
3017             }
3018             code_status(c1);
3019         }
3020         c0 = 0;
3021         switch ((*iconv)(c2, c1, 0)) {  /* can be EUC/SJIS/UTF-8 */
3022         case -2:
3023             /* 4 bytes 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                 c0 <<= 8;
3032                 if (hold_index < hold_count){
3033                     c3 = hold_buf[hold_index++];
3034                 } else if ((c3 = (*i_getc)(f)) == EOF) {
3035                     c0 = ret = EOF;
3036                     break;
3037                 } else {
3038                     code_status(c3);
3039                     (*iconv)(c2, c1, c0|c3);
3040                 }
3041             }
3042             break;
3043         case -1:
3044             /* 3 bytes EUC or UTF-8 */
3045             if (hold_index < hold_count){
3046                 c0 = hold_buf[hold_index++];
3047             } else if ((c0 = (*i_getc)(f)) == EOF) {
3048                 ret = EOF;
3049                 break;
3050             } else {
3051                 code_status(c0);
3052             }
3053             (*iconv)(c2, c1, c0);
3054             break;
3055         }
3056         if (c0 == EOF) break;
3057     }
3058     return ret;
3059 }
3060
3061 nkf_char push_hold_buf(nkf_char c2)
3062 {
3063     if (hold_count >= HOLD_SIZE*2)
3064         return (EOF);
3065     hold_buf[hold_count++] = (unsigned char)c2;
3066     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
3067 }
3068
3069 nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
3070 {
3071 #if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
3072     nkf_char val;
3073 #endif
3074     static const nkf_char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
3075 #ifdef SHIFTJIS_CP932
3076     if (cp51932_f && is_ibmext_in_sjis(c2)){
3077 #if 0
3078         extern const unsigned short shiftjis_cp932[3][189];
3079 #endif
3080         val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
3081         if (val){
3082             c2 = val >> 8;
3083             c1 = val & 0xff;
3084         }
3085     }
3086 #endif /* SHIFTJIS_CP932 */
3087 #ifdef X0212_ENABLE
3088     if (!x0213_f && is_ibmext_in_sjis(c2)){
3089 #if 0
3090         extern const unsigned short shiftjis_x0212[3][189];
3091 #endif
3092         val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
3093         if (val){
3094             if (val > 0x7FFF){
3095                 c2 = PREFIX_EUCG3 | (val >> 8);
3096                 c1 = val & 0xff;
3097             }else{
3098                 c2 = val >> 8;
3099                 c1 = val & 0xff;
3100             }
3101             if (p2) *p2 = c2;
3102             if (p1) *p1 = c1;
3103             return 0;
3104         }
3105     }
3106 #endif
3107     if(c2 >= 0x80){
3108         if(x0213_f && c2 >= 0xF0){
3109             if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */
3110                 c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1];
3111             }else{ /* 78<=k<=94 */
3112                 c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B);
3113                 if (0x9E < c1) c2++;
3114             }
3115         }else{
3116             c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394);
3117             if (0x9E < c1) c2++;
3118         }
3119         if (c1 < 0x9F)
3120             c1 = c1 - ((c1 > DEL) ? SPACE : 0x1F);
3121         else {
3122             c1 = c1 - 0x7E;
3123         }
3124     }
3125
3126 #ifdef X0212_ENABLE
3127     c2 = x0212_unshift(c2);
3128 #endif
3129     if (p2) *p2 = c2;
3130     if (p1) *p1 = c1;
3131     return 0;
3132 }
3133
3134 nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
3135 {
3136     if (c2 == X0201) {
3137         c1 &= 0x7f;
3138     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
3139         /* NOP */
3140     } else {
3141         nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
3142         if (ret) return ret;
3143     }
3144     (*oconv)(c2, c1);
3145     return 0;
3146 }
3147
3148 nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
3149 {
3150     if (c2 == X0201) {
3151         c1 &= 0x7f;
3152 #ifdef X0212_ENABLE
3153     }else if (c2 == 0x8f){
3154         if (c0 == 0){
3155             return -1;
3156         }
3157         c2 = (c2 << 8) | (c1 & 0x7f);
3158         c1 = c0 & 0x7f;
3159 #ifdef SHIFTJIS_CP932
3160         if (cp51932_f){
3161             nkf_char s2, s1;
3162             if (e2s_conv(c2, c1, &s2, &s1) == 0){
3163                 s2e_conv(s2, s1, &c2, &c1);
3164                 if (c2 < 0x100){
3165                     c1 &= 0x7f;
3166                     c2 &= 0x7f;
3167                 }
3168             }
3169         }
3170 #endif /* SHIFTJIS_CP932 */
3171 #endif /* X0212_ENABLE */
3172     } else if (c2 == SSO){
3173         c2 = X0201;
3174         c1 &= 0x7f;
3175     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
3176         /* NOP */
3177     } else {
3178         c1 &= 0x7f;
3179         c2 &= 0x7f;
3180     }
3181     (*oconv)(c2, c1);
3182     return 0;
3183 }
3184
3185 #ifdef UTF8_INPUT_ENABLE
3186 nkf_char w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
3187 {
3188     nkf_char ret = 0;
3189
3190     if (!c1){
3191         *p2 = 0;
3192         *p1 = c2;
3193     }else if (0xc0 <= c2 && c2 <= 0xef) {
3194         ret =  unicode_to_jis_common(c2, c1, c0, p2, p1);
3195 #ifdef NUMCHAR_OPTION
3196         if (ret > 0){
3197             if (p2) *p2 = 0;
3198             if (p1) *p1 = CLASS_UNICODE | ww16_conv(c2, c1, c0);
3199             ret = 0;
3200         }
3201 #endif
3202     }
3203     return ret;
3204 }
3205
3206 nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
3207 {
3208     nkf_char ret = 0;
3209     static const int w_iconv_utf8_1st_byte[] =
3210     { /* 0xC0 - 0xFF */
3211         20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
3212         21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
3213         30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33,
3214         40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70};
3215     
3216     if (c2 < 0 || 0xff < c2) {
3217     }else if (c2 == 0) { /* 0 : 1 byte*/
3218         c0 = 0;
3219     } else if ((c2 & 0xc0) == 0x80) { /* 0x80-0xbf : trail byte */
3220         return 0;
3221     } else{
3222         switch (w_iconv_utf8_1st_byte[c2 - 0xC0]) {
3223         case 21:
3224             if (c1 < 0x80 || 0xBF < c1) return 0;
3225             break;
3226         case 30:
3227             if (c0 == 0) return -1;
3228             if (c1 < 0xA0 || 0xBF < c1 || (c0 & 0xc0) != 0x80)
3229                 return 0;
3230             break;
3231         case 31:
3232         case 33:
3233             if (c0 == 0) return -1;
3234             if ((c1 & 0xc0) != 0x80 || (c0 & 0xc0) != 0x80)
3235                 return 0;
3236             break;
3237         case 32:
3238             if (c0 == 0) return -1;
3239             if (c1 < 0x80 || 0x9F < c1 || (c0 & 0xc0) != 0x80)
3240                 return 0;
3241             break;
3242         case 40:
3243             if (c0 == 0) return -2;
3244             if (c1 < 0x90 || 0xBF < c1 || (c0 & 0xc0c0) != 0x8080)
3245                 return 0;
3246             break;
3247         case 41:
3248             if (c0 == 0) return -2;
3249             if (c1 < 0x80 || 0xBF < c1 || (c0 & 0xc0c0) != 0x8080)
3250                 return 0;
3251             break;
3252         case 42:
3253             if (c0 == 0) return -2;
3254             if (c1 < 0x80 || 0x8F < c1 || (c0 & 0xc0c0) != 0x8080)
3255                 return 0;
3256             break;
3257         default:
3258             return 0;
3259             break;
3260         }
3261     }
3262     if (c2 == 0 || c2 == EOF){
3263     } else if ((c2 & 0xf8) == 0xf0) { /* 4 bytes */
3264         c1 = CLASS_UNICODE | ww16_conv(c2, c1, c0);
3265         c2 = 0;
3266     } else {
3267         ret = w2e_conv(c2, c1, c0, &c2, &c1);
3268     }
3269     if (ret == 0){
3270         (*oconv)(c2, c1);
3271     }
3272     return ret;
3273 }
3274 #endif
3275
3276 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3277 void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0)
3278 {
3279     val &= VALUE_MASK;
3280     if (val < 0x80){
3281         *p2 = val;
3282         *p1 = 0;
3283         *p0 = 0;
3284     }else if (val < 0x800){
3285         *p2 = 0xc0 | (val >> 6);
3286         *p1 = 0x80 | (val & 0x3f);
3287         *p0 = 0;
3288     } else if (val <= NKF_INT32_C(0xFFFF)) {
3289         *p2 = 0xe0 | (val >> 12);
3290         *p1 = 0x80 | ((val >> 6) & 0x3f);
3291         *p0 = 0x80 | (val        & 0x3f);
3292     } else if (val <= NKF_INT32_C(0x10FFFF)) {
3293         *p2 = 0xe0 |  (val >> 16);
3294         *p1 = 0x80 | ((val >> 12) & 0x3f);
3295         *p0 = 0x8080 | ((val << 2) & 0x3f00)| (val & 0x3f);
3296     } else {
3297         *p2 = 0;
3298         *p1 = 0;
3299         *p0 = 0;
3300     }
3301 }
3302 #endif
3303
3304 #ifdef UTF8_INPUT_ENABLE
3305 nkf_char ww16_conv(nkf_char c2, nkf_char c1, nkf_char c0)
3306 {
3307     nkf_char val;
3308     if (c2 >= 0xf8) {
3309         val = -1;
3310     } else if (c2 >= 0xf0){
3311         /* c2: 1st, c1: 2nd, c0: 3rd/4th */
3312         val = (c2 & 0x0f) << 18;
3313         val |= (c1 & 0x3f) << 12;
3314         val |= (c0 & 0x3f00) >> 2;
3315         val |= (c0 & 0x3f);
3316     }else if (c2 >= 0xe0){
3317         val = (c2 & 0x0f) << 12;
3318         val |= (c1 & 0x3f) << 6;
3319         val |= (c0 & 0x3f);
3320     }else if (c2 >= 0xc0){
3321         val = (c2 & 0x1f) << 6;
3322         val |= (c1 & 0x3f);
3323     }else{
3324         val = c2;
3325     }
3326     return val;
3327 }
3328
3329 nkf_char w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
3330 {
3331     nkf_char c2, c1, c0;
3332     nkf_char ret = 0;
3333     val &= VALUE_MASK;
3334     if (val < 0x80){
3335         *p2 = 0;
3336         *p1 = val;
3337     }else{
3338         w16w_conv(val, &c2, &c1, &c0);
3339         ret =  unicode_to_jis_common(c2, c1, c0, p2, p1);
3340 #ifdef NUMCHAR_OPTION
3341         if (ret > 0){
3342             *p2 = 0;
3343             *p1 = CLASS_UNICODE | val;
3344             ret = 0;
3345         }
3346 #endif
3347     }
3348     return ret;
3349 }
3350 #endif
3351
3352 #ifdef UTF8_INPUT_ENABLE
3353 nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
3354 {
3355     nkf_char ret = 0;
3356     if ((c2==0 && c1 < 0x80) || c2==EOF) {
3357         (*oconv)(c2, c1);
3358         return 0;
3359     }else if (0xD8 <= c2 && c2 <= 0xDB) {
3360         if (c0 < NKF_INT32_C(0xDC00) || NKF_INT32_C(0xDFFF) < c0)
3361             return -2;
3362         c1 =  CLASS_UNICODE | ((c2 << 18) + (c1 << 10) + c0 - NKF_INT32_C(0x35FDC00));
3363         c2 = 0;
3364     }else if ((c2>>3) == 27) { /* unpaired surrogate */
3365         /*
3366            return 2;
3367         */
3368         return 1;
3369     }else ret = w16e_conv(((c2 & 0xff)<<8) + c1, &c2, &c1);
3370     if (ret) return ret;
3371     (*oconv)(c2, c1);
3372     return 0;
3373 }
3374
3375 nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
3376 {
3377     int ret = 0;
3378
3379     if ((c2 == 0 && c1 < 0x80) || c2==EOF) {
3380     } else if (is_unicode_bmp(c1)) {
3381         ret = w16e_conv(c1, &c2, &c1);
3382     } else {
3383         c2 = 0;
3384         c1 =  CLASS_UNICODE | c1;
3385     }
3386     if (ret) return ret;
3387     (*oconv)(c2, c1);
3388     return 0;
3389 }
3390
3391 nkf_char unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
3392 {
3393 #if 0
3394     extern const unsigned short *const utf8_to_euc_2bytes[];
3395     extern const unsigned short *const utf8_to_euc_2bytes_ms[];
3396     extern const unsigned short *const utf8_to_euc_2bytes_932[];
3397     extern const unsigned short *const *const utf8_to_euc_3bytes[];
3398     extern const unsigned short *const *const utf8_to_euc_3bytes_ms[];
3399     extern const unsigned short *const *const utf8_to_euc_3bytes_932[];
3400 #endif
3401     const unsigned short *const *pp;
3402     const unsigned short *const *const *ppp;
3403     static const int no_best_fit_chars_table_C2[] =
3404     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3405         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3406         1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2,
3407         0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1};
3408     static const int no_best_fit_chars_table_C2_ms[] =
3409     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3410         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3411         1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,
3412         0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0};
3413     static const int no_best_fit_chars_table_932_C2[] =
3414     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3415         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3416         1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
3417         0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0};
3418     static const int no_best_fit_chars_table_932_C3[] =
3419     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3420         1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
3421         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3422         1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1};
3423     nkf_char ret = 0;
3424
3425     if(c2 < 0x80){
3426         *p2 = 0;
3427         *p1 = c2;
3428     }else if(c2 < 0xe0){
3429         if(no_best_fit_chars_f){
3430             if(ms_ucs_map_f == UCS_MAP_CP932){
3431                 switch(c2){
3432                 case 0xC2:
3433                     if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1;
3434                     break;
3435                 case 0xC3:
3436                     if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
3437                     break;
3438                 }
3439             }else if(cp51932_f){
3440                 switch(c2){
3441                 case 0xC2:
3442                     if(no_best_fit_chars_table_C2[c1&0x3F]) return 1;
3443                     break;
3444                 case 0xC3:
3445                     if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
3446                     break;
3447                 }
3448             }else if(ms_ucs_map_f == UCS_MAP_MS){
3449                 if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1;
3450             }
3451         }
3452         pp =
3453             ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 :
3454             ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms :
3455             utf8_to_euc_2bytes;
3456         ret =  w_iconv_common(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
3457     }else if(c0 < 0xF0){
3458         if(no_best_fit_chars_f){
3459             if(ms_ucs_map_f == UCS_MAP_CP932){
3460                 if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1;
3461             }else if(ms_ucs_map_f == UCS_MAP_MS){
3462                 switch(c2){
3463                 case 0xE2:
3464                     switch(c1){
3465                     case 0x80:
3466                         if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1;
3467                         break;
3468                     case 0x88:
3469                         if(c0 == 0x92) return 1;
3470                         break;
3471                     }
3472                     break;
3473                 case 0xE3:
3474                     if(c1 == 0x80 || c0 == 0x9C) return 1;
3475                     break;
3476                 }
3477             }else{
3478                 switch(c2){
3479                 case 0xE2:
3480                     switch(c1){
3481                     case 0x80:
3482                         if(c0 == 0x95) return 1;
3483                         break;
3484                     case 0x88:
3485                         if(c0 == 0xA5) return 1;
3486                         break;
3487                     }
3488                     break;
3489                 case 0xEF:
3490                     switch(c1){
3491                     case 0xBC:
3492                         if(c0 == 0x8D) return 1;
3493                         break;
3494                     case 0xBD:
3495                         if(c0 == 0x9E && cp51932_f) return 1;
3496                         break;
3497                     case 0xBF:
3498                         if(0xA0 <= c0 && c0 <= 0xA5) return 1;
3499                         break;
3500                     }
3501                     break;
3502                 }
3503             }
3504         }
3505         ppp =
3506             ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 :
3507             ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms :
3508             utf8_to_euc_3bytes;
3509         ret = w_iconv_common(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
3510     }else return -1;
3511 #ifdef SHIFTJIS_CP932
3512     if (!ret && cp51932_f && is_eucg3(*p2)) {
3513         nkf_char s2, s1;
3514         if (e2s_conv(*p2, *p1, &s2, &s1) == 0) {
3515             s2e_conv(s2, s1, p2, p1);
3516         }else{
3517             ret = 1;
3518         }
3519     }
3520 #endif
3521     return ret;
3522 }
3523
3524 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)
3525 {
3526     nkf_char c2;
3527     const unsigned short *p;
3528     unsigned short val;
3529
3530     if (pp == 0) return 1;
3531
3532     c1 -= 0x80;
3533     if (c1 < 0 || psize <= c1) return 1;
3534     p = pp[c1];
3535     if (p == 0)  return 1;
3536
3537     c0 -= 0x80;
3538     if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1;
3539     val = p[c0];
3540     if (val == 0) return 1;
3541     if (no_cp932ext_f && (
3542         (val>>8) == 0x2D || /* NEC special characters */
3543         val > NKF_INT32_C(0xF300) /* IBM extended characters */
3544         )) return 1;
3545
3546     c2 = val >> 8;
3547    if (val > 0x7FFF){
3548         c2 &= 0x7f;
3549         c2 |= PREFIX_EUCG3;
3550     }
3551     if (c2 == SO) c2 = X0201;
3552     c1 = val & 0x7f;
3553     if (p2) *p2 = c2;
3554     if (p1) *p1 = c1;
3555     return 0;
3556 }
3557
3558 void nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
3559 {
3560     const char *hex = "0123456789ABCDEF";
3561     int shift = 20;
3562     c &= VALUE_MASK;
3563     while(shift >= 0){
3564         if(c >= 1<<shift){
3565             while(shift >= 0){
3566                 (*f)(0, hex[(c>>shift)&0xF]);
3567                 shift -= 4;
3568             }
3569         }else{
3570             shift -= 4;
3571         }
3572     }
3573     return;
3574 }
3575
3576 void encode_fallback_html(nkf_char c)
3577 {
3578     (*oconv)(0, '&');
3579     (*oconv)(0, '#');
3580     c &= VALUE_MASK;
3581     if(c >= NKF_INT32_C(1000000))
3582         (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10);
3583     if(c >= NKF_INT32_C(100000))
3584         (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10);
3585     if(c >= 10000)
3586         (*oconv)(0, 0x30+(c/10000  )%10);
3587     if(c >= 1000)
3588         (*oconv)(0, 0x30+(c/1000   )%10);
3589     if(c >= 100)
3590         (*oconv)(0, 0x30+(c/100    )%10);
3591     if(c >= 10)
3592         (*oconv)(0, 0x30+(c/10     )%10);
3593     if(c >= 0)
3594         (*oconv)(0, 0x30+ c         %10);
3595     (*oconv)(0, ';');
3596     return;
3597 }
3598
3599 void encode_fallback_xml(nkf_char c)
3600 {
3601     (*oconv)(0, '&');
3602     (*oconv)(0, '#');
3603     (*oconv)(0, 'x');
3604     nkf_each_char_to_hex(oconv, c);
3605     (*oconv)(0, ';');
3606     return;
3607 }
3608
3609 void encode_fallback_java(nkf_char c)
3610 {
3611     const char *hex = "0123456789ABCDEF";
3612     (*oconv)(0, '\\');
3613     c &= VALUE_MASK;
3614     if(!is_unicode_bmp(c)){
3615         (*oconv)(0, 'U');
3616         (*oconv)(0, '0');
3617         (*oconv)(0, '0');
3618         (*oconv)(0, hex[(c>>20)&0xF]);
3619         (*oconv)(0, hex[(c>>16)&0xF]);
3620     }else{
3621         (*oconv)(0, 'u');
3622     }
3623     (*oconv)(0, hex[(c>>12)&0xF]);
3624     (*oconv)(0, hex[(c>> 8)&0xF]);
3625     (*oconv)(0, hex[(c>> 4)&0xF]);
3626     (*oconv)(0, hex[ c     &0xF]);
3627     return;
3628 }
3629
3630 void encode_fallback_perl(nkf_char c)
3631 {
3632     (*oconv)(0, '\\');
3633     (*oconv)(0, 'x');
3634     (*oconv)(0, '{');
3635     nkf_each_char_to_hex(oconv, c);
3636     (*oconv)(0, '}');
3637     return;
3638 }
3639
3640 void encode_fallback_subchar(nkf_char c)
3641 {
3642     c = unicode_subchar;
3643     (*oconv)((c>>8)&0xFF, c&0xFF);
3644     return;
3645 }
3646 #endif
3647
3648 #ifdef UTF8_OUTPUT_ENABLE
3649 nkf_char e2w_conv(nkf_char c2, nkf_char c1)
3650 {
3651 #if 0
3652     extern const unsigned short euc_to_utf8_1byte[];
3653     extern const unsigned short *const euc_to_utf8_2bytes[];
3654     extern const unsigned short *const euc_to_utf8_2bytes_ms[];
3655     extern const unsigned short *const x0212_to_utf8_2bytes[];
3656 #endif
3657     const unsigned short *p;
3658
3659     if (c2 == X0201) {
3660         p = euc_to_utf8_1byte;
3661 #ifdef X0212_ENABLE
3662     } else if (is_eucg3(c2)){
3663         if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){
3664             return 0xA6;
3665         }
3666         c2 = (c2&0x7f) - 0x21;
3667         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
3668             p = x0212_to_utf8_2bytes[c2];
3669         else
3670             return 0;
3671 #endif
3672     } else {
3673         c2 &= 0x7f;
3674         c2 = (c2&0x7f) - 0x21;
3675         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
3676             p = ms_ucs_map_f != UCS_MAP_ASCII ? euc_to_utf8_2bytes_ms[c2] : euc_to_utf8_2bytes[c2];
3677         else
3678             return 0;
3679     }
3680     if (!p) return 0;
3681     c1 = (c1 & 0x7f) - 0x21;
3682     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
3683         return p[c1];
3684     return 0;
3685 }
3686
3687 void w_oconv(nkf_char c2, nkf_char c1)
3688 {
3689     nkf_char c0;
3690     nkf_char val;
3691
3692     if (output_bom_f) {
3693         output_bom_f = FALSE;
3694         (*o_putc)('\357');
3695         (*o_putc)('\273');
3696         (*o_putc)('\277');
3697     }
3698
3699     if (c2 == EOF) {
3700         (*o_putc)(EOF);
3701         return;
3702     }
3703
3704 #ifdef NUMCHAR_OPTION
3705     if (c2 == 0 && is_unicode_capsule(c1)){
3706         val = c1 & VALUE_MASK;
3707         if (val < 0x80){
3708             (*o_putc)(val);
3709         }else if (val < 0x800){
3710             (*o_putc)(0xC0 | (val >> 6));
3711             (*o_putc)(0x80 | (val & 0x3f));
3712         } else if (val <= NKF_INT32_C(0xFFFF)) {
3713             (*o_putc)(0xE0 | (val >> 12));
3714             (*o_putc)(0x80 | ((val >> 6) & 0x3f));
3715             (*o_putc)(0x80 | (val        & 0x3f));
3716         } else if (val <= NKF_INT32_C(0x10FFFF)) {
3717             (*o_putc)(0xF0 | ( val>>18));
3718             (*o_putc)(0x80 | ((val>>12) & 0x3f));
3719             (*o_putc)(0x80 | ((val>> 6) & 0x3f));
3720             (*o_putc)(0x80 | ( val      & 0x3f));
3721         }
3722         return;
3723     }
3724 #endif
3725
3726     if (c2 == 0) { 
3727         output_mode = ASCII;
3728         (*o_putc)(c1);
3729     } else if (c2 == ISO8859_1) {
3730         output_mode = ISO8859_1;
3731         (*o_putc)(c1 | 0x080);
3732     } else {
3733         output_mode = UTF8;
3734         val = e2w_conv(c2, c1);
3735         if (val){
3736             w16w_conv(val, &c2, &c1, &c0);
3737             (*o_putc)(c2);
3738             if (c1){
3739                 (*o_putc)(c1);
3740                 if (c0) (*o_putc)(c0);
3741             }
3742         }
3743     }
3744 }
3745
3746 void w_oconv16(nkf_char c2, nkf_char c1)
3747 {
3748     if (output_bom_f) {
3749         output_bom_f = FALSE;
3750         if (output_endian == ENDIAN_LITTLE){
3751             (*o_putc)((unsigned char)'\377');
3752             (*o_putc)('\376');
3753         }else{
3754             (*o_putc)('\376');
3755             (*o_putc)((unsigned char)'\377');
3756         }
3757     }
3758
3759     if (c2 == EOF) {
3760         (*o_putc)(EOF);
3761         return;
3762     }
3763
3764     if (c2 == ISO8859_1) {
3765         c2 = 0;
3766         c1 |= 0x80;
3767 #ifdef NUMCHAR_OPTION
3768     } else if (c2 == 0 && is_unicode_capsule(c1)) {
3769         if (is_unicode_bmp(c1)) {
3770             c2 = (c1 >> 8) & 0xff;
3771             c1 &= 0xff;
3772         } else {
3773             c1 &= VALUE_MASK;
3774             if (c1 <= UNICODE_MAX) {
3775                 c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0);   /* high surrogate */
3776                 c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
3777                 if (output_endian == ENDIAN_LITTLE){
3778                     (*o_putc)(c2 & 0xff);
3779                     (*o_putc)((c2 >> 8) & 0xff);
3780                     (*o_putc)(c1 & 0xff);
3781                     (*o_putc)((c1 >> 8) & 0xff);
3782                 }else{
3783                     (*o_putc)((c2 >> 8) & 0xff);
3784                     (*o_putc)(c2 & 0xff);
3785                     (*o_putc)((c1 >> 8) & 0xff);
3786                     (*o_putc)(c1 & 0xff);
3787                 }
3788             }
3789             return;
3790         }
3791 #endif
3792     } else if (c2) {
3793         nkf_char val = e2w_conv(c2, c1);
3794         c2 = (val >> 8) & 0xff;
3795         c1 = val & 0xff;
3796     }
3797     if (output_endian == ENDIAN_LITTLE){
3798         (*o_putc)(c1);
3799         (*o_putc)(c2);
3800     }else{
3801         (*o_putc)(c2);
3802         (*o_putc)(c1);
3803     }
3804 }
3805
3806 void w_oconv32(nkf_char c2, nkf_char c1)
3807 {
3808     if (output_bom_f) {
3809         output_bom_f = FALSE;
3810         if (output_endian == ENDIAN_LITTLE){
3811             (*o_putc)((unsigned char)'\377');
3812             (*o_putc)('\376');
3813             (*o_putc)('\000');
3814             (*o_putc)('\000');
3815         }else{
3816             (*o_putc)('\000');
3817             (*o_putc)('\000');
3818             (*o_putc)('\376');
3819             (*o_putc)((unsigned char)'\377');
3820         }
3821     }
3822
3823     if (c2 == EOF) {
3824         (*o_putc)(EOF);
3825         return;
3826     }
3827
3828     if (c2 == ISO8859_1) {
3829         c1 |= 0x80;
3830 #ifdef NUMCHAR_OPTION
3831     } else if (c2 == 0 && is_unicode_capsule(c1)) {
3832         c1 &= VALUE_MASK;
3833 #endif
3834     } else if (c2) {
3835         c1 = e2w_conv(c2, c1);
3836     }
3837     if (output_endian == ENDIAN_LITTLE){
3838         (*o_putc)( c1 & NKF_INT32_C(0x000000FF));
3839         (*o_putc)((c1 & NKF_INT32_C(0x0000FF00)) >>  8);
3840         (*o_putc)((c1 & NKF_INT32_C(0x00FF0000)) >> 16);
3841         (*o_putc)('\000');
3842     }else{
3843         (*o_putc)('\000');
3844         (*o_putc)((c1 & NKF_INT32_C(0x00FF0000)) >> 16);
3845         (*o_putc)((c1 & NKF_INT32_C(0x0000FF00)) >>  8);
3846         (*o_putc)( c1 & NKF_INT32_C(0x000000FF));
3847     }
3848 }
3849 #endif
3850
3851 void e_oconv(nkf_char c2, nkf_char c1)
3852 {
3853 #ifdef NUMCHAR_OPTION
3854     if (c2 == 0 && is_unicode_capsule(c1)){
3855         w16e_conv(c1, &c2, &c1);
3856         if (c2 == 0 && is_unicode_capsule(c1)){
3857             if(encode_fallback)(*encode_fallback)(c1);
3858             return;
3859         }
3860     }
3861 #endif
3862     if (c2 == EOF) {
3863         (*o_putc)(EOF);
3864         return;
3865     } else if (c2 == 0) { 
3866         output_mode = ASCII;
3867         (*o_putc)(c1);
3868     } else if (c2 == X0201) {
3869         output_mode = JAPANESE_EUC;
3870         (*o_putc)(SSO); (*o_putc)(c1|0x80);
3871     } else if (c2 == ISO8859_1) {
3872         output_mode = ISO8859_1;
3873         (*o_putc)(c1 | 0x080);
3874 #ifdef X0212_ENABLE
3875     } else if (is_eucg3(c2)){
3876         output_mode = JAPANESE_EUC;
3877 #ifdef SHIFTJIS_CP932
3878         if (cp51932_f){
3879             nkf_char s2, s1;
3880             if (e2s_conv(c2, c1, &s2, &s1) == 0){
3881                 s2e_conv(s2, s1, &c2, &c1);
3882             }
3883         }
3884 #endif
3885         if (c2 == 0) {
3886             output_mode = ASCII;
3887             (*o_putc)(c1);
3888         }else if (is_eucg3(c2)){
3889             if (x0212_f){
3890                 (*o_putc)(0x8f);
3891                 (*o_putc)((c2 & 0x7f) | 0x080);
3892                 (*o_putc)(c1 | 0x080);
3893             }
3894         }else{
3895             (*o_putc)((c2 & 0x7f) | 0x080);
3896             (*o_putc)(c1 | 0x080);
3897         }
3898 #endif
3899     } else {
3900         if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
3901             set_iconv(FALSE, 0);
3902             return; /* too late to rescue this char */
3903         }
3904         output_mode = JAPANESE_EUC;
3905         (*o_putc)(c2 | 0x080);
3906         (*o_putc)(c1 | 0x080);
3907     }
3908 }
3909
3910 #ifdef X0212_ENABLE
3911 nkf_char x0212_shift(nkf_char c)
3912 {
3913     nkf_char ret = c;
3914     c &= 0x7f;
3915     if (is_eucg3(ret)){
3916         if (0x75 <= c && c <= 0x7f){
3917             ret = c + (0x109 - 0x75);
3918         }
3919     }else{
3920         if (0x75 <= c && c <= 0x7f){
3921             ret = c + (0x113 - 0x75);
3922         }
3923     }
3924     return ret;
3925 }
3926
3927
3928 nkf_char x0212_unshift(nkf_char c)
3929 {
3930     nkf_char ret = c;
3931     if (0x7f <= c && c <= 0x88){
3932         ret = c + (0x75 - 0x7f);
3933     }else if (0x89 <= c && c <= 0x92){
3934         ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
3935     }
3936     return ret;
3937 }
3938 #endif /* X0212_ENABLE */
3939
3940 nkf_char e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
3941 {
3942     nkf_char ndx;
3943     if (is_eucg3(c2)){
3944         ndx = c2 & 0xff;
3945         if (x0213_f){
3946             if((0x21 <= ndx && ndx <= 0x2F)){
3947                 if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3;
3948                 if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
3949                 return 0;
3950             }else if(0x6E <= ndx && ndx <= 0x7E){
3951                 if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe;
3952                 if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
3953                 return 0;
3954             }
3955             return 1;
3956         }
3957 #ifdef X0212_ENABLE
3958         else if(nkf_isgraph(ndx)){
3959             nkf_char val = 0;
3960             const unsigned short *ptr;
3961 #if 0
3962             extern const unsigned short *const x0212_shiftjis[];
3963 #endif
3964             ptr = x0212_shiftjis[ndx - 0x21];
3965             if (ptr){
3966                 val = ptr[(c1 & 0x7f) - 0x21];
3967             }
3968             if (val){
3969                 c2 = val >> 8;
3970                 c1 = val & 0xff;
3971                 if (p2) *p2 = c2;
3972                 if (p1) *p1 = c1;
3973                 return 0;
3974             }
3975             c2 = x0212_shift(c2);
3976         }
3977 #endif /* X0212_ENABLE */
3978     }
3979     if(0x7F < c2) return 1;
3980     if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
3981     if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
3982     return 0;
3983 }
3984
3985 void s_oconv(nkf_char c2, nkf_char c1)
3986 {
3987 #ifdef NUMCHAR_OPTION
3988     if (c2 == 0 && is_unicode_capsule(c1)){
3989         w16e_conv(c1, &c2, &c1);
3990         if (c2 == 0 && is_unicode_capsule(c1)){
3991             if(encode_fallback)(*encode_fallback)(c1);
3992             return;
3993         }
3994     }
3995 #endif
3996     if (c2 == EOF) {
3997         (*o_putc)(EOF);
3998         return;
3999     } else if (c2 == 0) {
4000         output_mode = ASCII;
4001         (*o_putc)(c1);
4002     } else if (c2 == X0201) {
4003         output_mode = SHIFT_JIS;
4004         (*o_putc)(c1|0x80);
4005     } else if (c2 == ISO8859_1) {
4006         output_mode = ISO8859_1;
4007         (*o_putc)(c1 | 0x080);
4008 #ifdef X0212_ENABLE
4009     } else if (is_eucg3(c2)){
4010         output_mode = SHIFT_JIS;
4011         if (e2s_conv(c2, c1, &c2, &c1) == 0){
4012             (*o_putc)(c2);
4013             (*o_putc)(c1);
4014         }
4015 #endif
4016     } else {
4017         if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
4018             set_iconv(FALSE, 0);
4019             return; /* too late to rescue this char */
4020         }
4021         output_mode = SHIFT_JIS;
4022         e2s_conv(c2, c1, &c2, &c1);
4023
4024 #ifdef SHIFTJIS_CP932
4025         if (cp932inv_f
4026             && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
4027 #if 0
4028             extern const unsigned short cp932inv[2][189];
4029 #endif
4030             nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
4031             if (c){
4032                 c2 = c >> 8;
4033                 c1 = c & 0xff;
4034             }
4035         }
4036 #endif /* SHIFTJIS_CP932 */
4037
4038         (*o_putc)(c2);
4039         if (prefix_table[(unsigned char)c1]){
4040             (*o_putc)(prefix_table[(unsigned char)c1]);
4041         }
4042         (*o_putc)(c1);
4043     }
4044 }
4045
4046 void j_oconv(nkf_char c2, nkf_char c1)
4047 {
4048 #ifdef NUMCHAR_OPTION
4049     if (c2 == 0 && is_unicode_capsule(c1)){
4050         w16e_conv(c1, &c2, &c1);
4051         if (c2 == 0 && is_unicode_capsule(c1)){
4052             if(encode_fallback)(*encode_fallback)(c1);
4053             return;
4054         }
4055     }
4056 #endif
4057     if (c2 == EOF) {
4058         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
4059             (*o_putc)(ESC);
4060             (*o_putc)('(');
4061             (*o_putc)(ascii_intro);
4062             output_mode = ASCII;
4063         }
4064         (*o_putc)(EOF);
4065 #ifdef X0212_ENABLE
4066     } else if (is_eucg3(c2)){
4067         if(x0213_f){
4068             if(output_mode!=X0213_2){
4069                 output_mode = X0213_2;
4070                 (*o_putc)(ESC);
4071                 (*o_putc)('$');
4072                 (*o_putc)('(');
4073                 (*o_putc)(X0213_2&0x7F);
4074             }
4075         }else{
4076             if(output_mode!=X0212){
4077                 output_mode = X0212;
4078                 (*o_putc)(ESC);
4079                 (*o_putc)('$');
4080                 (*o_putc)('(');
4081                 (*o_putc)(X0212&0x7F);
4082             }
4083         }
4084         (*o_putc)(c2 & 0x7f);
4085         (*o_putc)(c1);
4086 #endif
4087     } else if (c2==X0201) {
4088         if (output_mode!=X0201) {
4089             output_mode = X0201;
4090             (*o_putc)(ESC);
4091             (*o_putc)('(');
4092             (*o_putc)('I');
4093         }
4094         (*o_putc)(c1);
4095     } else if (c2==ISO8859_1) {
4096             /* iso8859 introduction, or 8th bit on */
4097             /* Can we convert in 7bit form using ESC-'-'-A ? 
4098                Is this popular? */
4099         output_mode = ISO8859_1;
4100         (*o_putc)(c1|0x80);
4101     } else if (c2 == 0) {
4102         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
4103             (*o_putc)(ESC);
4104             (*o_putc)('(');
4105             (*o_putc)(ascii_intro);
4106             output_mode = ASCII;
4107         }
4108         (*o_putc)(c1);
4109     } else {
4110         if(c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
4111         if(x0213_f){
4112             if (output_mode!=X0213_1) {
4113                 output_mode = X0213_1;
4114                 (*o_putc)(ESC);
4115                 (*o_putc)('$');
4116                 (*o_putc)('(');
4117                 (*o_putc)(X0213_1&0x7F);
4118             }
4119         }else if (output_mode != X0208) {
4120             output_mode = X0208;
4121             (*o_putc)(ESC);
4122             (*o_putc)('$');
4123             (*o_putc)(kanji_intro);
4124         }
4125         (*o_putc)(c2);
4126         (*o_putc)(c1);
4127     }
4128 }
4129
4130 void base64_conv(nkf_char c2, nkf_char c1)
4131 {
4132     mime_prechar(c2, c1);
4133     (*o_base64conv)(c2,c1);
4134 }
4135
4136
4137 static nkf_char broken_buf[3];
4138 static int broken_counter = 0;
4139 static int broken_last = 0;
4140 nkf_char broken_getc(FILE *f)
4141 {
4142     nkf_char c,c1;
4143
4144     if (broken_counter>0) {
4145         return broken_buf[--broken_counter];
4146     }
4147     c= (*i_bgetc)(f);
4148     if (c=='$' && broken_last != ESC 
4149             && (input_mode==ASCII || input_mode==X0201)) {
4150         c1= (*i_bgetc)(f);
4151         broken_last = 0;
4152         if (c1=='@'|| c1=='B') {
4153             broken_buf[0]=c1; broken_buf[1]=c; 
4154             broken_counter=2;
4155             return ESC;
4156         } else {
4157             (*i_bungetc)(c1,f);
4158             return c;
4159         }
4160     } else if (c=='(' && broken_last != ESC 
4161             && (input_mode==X0208 || input_mode==X0201)) { /* ) */
4162         c1= (*i_bgetc)(f);
4163         broken_last = 0;
4164         if (c1=='J'|| c1=='B') {
4165             broken_buf[0]=c1; broken_buf[1]=c;
4166             broken_counter=2;
4167             return ESC;
4168         } else {
4169             (*i_bungetc)(c1,f);
4170             return c;
4171         }
4172     } else {
4173         broken_last = c;
4174         return c;
4175     }
4176 }
4177
4178 nkf_char broken_ungetc(nkf_char c, FILE *f)
4179 {
4180     if (broken_counter<2)
4181         broken_buf[broken_counter++]=c;
4182     return c;
4183 }
4184
4185 static nkf_char prev_cr = 0;
4186
4187 void cr_conv(nkf_char c2, nkf_char c1)
4188 {
4189     if (prev_cr) {
4190         prev_cr = 0;
4191         if (! (c2==0&&c1==NL) ) {
4192             cr_conv(0,'\n');
4193         }
4194     }
4195     if (c2) {
4196         (*o_crconv)(c2,c1);
4197     } else if (c1=='\r') {
4198         prev_cr = c1;
4199     } else if (c1=='\n') {
4200         if (crmode_f==CRLF) {
4201             (*o_crconv)(0,'\r');
4202         } else if (crmode_f==CR) {
4203             (*o_crconv)(0,'\r');
4204             return;
4205         } 
4206         (*o_crconv)(0,NL);
4207     } else if (c1!='\032' || crmode_f!=NL){
4208         (*o_crconv)(c2,c1);
4209     }
4210 }
4211
4212 /* 
4213   Return value of fold_conv()
4214
4215        \n  add newline  and output char
4216        \r  add newline  and output nothing
4217        ' ' space
4218        0   skip  
4219        1   (or else) normal output 
4220
4221   fold state in prev (previous character)
4222
4223       >0x80 Japanese (X0208/X0201)
4224       <0x80 ASCII
4225       \n    new line 
4226       ' '   space
4227
4228   This fold algorthm does not preserve heading space in a line.
4229   This is the main difference from fmt.
4230 */
4231
4232 #define char_size(c2,c1) (c2?2:1)
4233
4234 void fold_conv(nkf_char c2, nkf_char c1)
4235
4236     nkf_char prev0;
4237     nkf_char fold_state;
4238
4239     if (c1== '\r' && !fold_preserve_f) {
4240         fold_state=0;  /* ignore cr */
4241     }else if (c1== '\n'&&f_prev=='\r' && fold_preserve_f) {
4242         f_prev = '\n';
4243         fold_state=0;  /* ignore cr */
4244     } else if (c1== BS) {
4245         if (f_line>0) f_line--;
4246         fold_state =  1;
4247     } else if (c2==EOF && f_line != 0) {    /* close open last line */
4248             fold_state = '\n';
4249     } else if ((c1=='\n' && !fold_preserve_f)
4250                || ((c1=='\r'||(c1=='\n'&&f_prev!='\r'))
4251                    && fold_preserve_f)) {
4252         /* new line */
4253         if (fold_preserve_f) { 
4254             f_prev = c1;
4255             f_line = 0;
4256             fold_state =  '\r';
4257         } else if ((f_prev == c1 && !fold_preserve_f)
4258                    || (f_prev == '\n' && fold_preserve_f)
4259                    ) {        /* duplicate newline */
4260             if (f_line) {
4261                 f_line = 0;
4262                 fold_state =  '\n';    /* output two newline */
4263             } else {
4264                 f_line = 0;
4265                 fold_state =  1;
4266             }
4267         } else  {
4268             if (f_prev&0x80) {     /* Japanese? */
4269                 f_prev = c1;
4270                 fold_state =  0;       /* ignore given single newline */
4271             } else if (f_prev==' ') {
4272                 fold_state =  0;
4273             } else {
4274                 f_prev = c1;
4275                 if (++f_line<=fold_len) 
4276                     fold_state =  ' ';
4277                 else {
4278                     f_line = 0;
4279                     fold_state =  '\r';        /* fold and output nothing */
4280                 }
4281             }
4282         }
4283     } else if (c1=='\f') {
4284         f_prev = '\n';
4285         f_line = 0;
4286         fold_state =  '\n';            /* output newline and clear */
4287     } else if ( (c2==0  && c1==' ')||
4288                (c2==0  && c1=='\t')||
4289                (c2=='!'&& c1=='!')) {
4290         /* X0208 kankaku or ascii space */
4291             if (f_prev == ' ') {
4292                 fold_state = 0;         /* remove duplicate spaces */
4293             } else {
4294                 f_prev = ' ';    
4295                 if (++f_line<=fold_len) 
4296                     fold_state = ' ';         /* output ASCII space only */
4297                 else {
4298                     f_prev = ' '; f_line = 0;
4299                     fold_state = '\r';        /* fold and output nothing */
4300                 }
4301             }
4302     } else {
4303         prev0 = f_prev; /* we still need this one... , but almost done */
4304         f_prev = c1;
4305         if (c2 || c2==X0201) 
4306             f_prev |= 0x80;  /* this is Japanese */
4307         f_line += char_size(c2,c1);
4308         if (f_line<=fold_len) {   /* normal case */
4309             fold_state = 1;
4310         } else {
4311             if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
4312                 f_line = char_size(c2,c1);
4313                 fold_state =  '\n';       /* We can't wait, do fold now */
4314             } else if (c2==X0201) {
4315             /* simple kinsoku rules  return 1 means no folding  */
4316                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
4317                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
4318                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
4319                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
4320                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
4321                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
4322                 else if (SPACE<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
4323                     f_line = 1;
4324                     fold_state = '\n';/* add one new f_line before this character */
4325                 } else {
4326                     f_line = 1;
4327                     fold_state = '\n';/* add one new f_line before this character */
4328                 }
4329             } else if (c2==0) {
4330                 /* kinsoku point in ASCII */ 
4331                 if (  c1==')'||    /* { [ ( */
4332                      c1==']'||
4333                      c1=='}'||
4334                      c1=='.'||
4335                      c1==','||
4336                      c1=='!'||
4337                      c1=='?'||
4338                      c1=='/'||
4339                      c1==':'||
4340                      c1==';' ) {
4341                     fold_state = 1;
4342                 /* just after special */
4343                 } else if (!is_alnum(prev0)) {
4344                     f_line = char_size(c2,c1);
4345                     fold_state = '\n';
4346                 } else if ((prev0==' ') ||   /* ignored new f_line */
4347                       (prev0=='\n')||        /* ignored new f_line */
4348                       (prev0&0x80)) {        /* X0208 - ASCII */
4349                     f_line = char_size(c2,c1);
4350                     fold_state = '\n';/* add one new f_line before this character */
4351                 } else {
4352                     fold_state = 1;  /* default no fold in ASCII */
4353                 }
4354             } else {
4355                 if (c2=='!') {
4356                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
4357                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
4358                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
4359                     else if (c1=='K')  fold_state = 1; /* \e$B!K\e(B */
4360                     else if (c1=='$')  fold_state = 1; /* \e$B!$\e(B */
4361                     else if (c1=='%')  fold_state = 1; /* \e$B!%\e(B */
4362                     else if (c1=='\'') fold_state = 1; /* \e$B!\\e(B */
4363                     else if (c1=='(')  fold_state = 1; /* \e$B!(\e(B */
4364                     else if (c1==')')  fold_state = 1; /* \e$B!)\e(B */
4365                     else if (c1=='*')  fold_state = 1; /* \e$B!*\e(B */
4366                     else if (c1=='+')  fold_state = 1; /* \e$B!+\e(B */
4367                     else if (c1==',')  fold_state = 1; /* \e$B!,\e(B */
4368                          /* default no fold in kinsoku */
4369                     else { 
4370                         fold_state = '\n';
4371                         f_line = char_size(c2,c1);
4372                         /* add one new f_line before this character */
4373                     }
4374                 } else {
4375                     f_line = char_size(c2,c1);
4376                     fold_state = '\n'; 
4377                     /* add one new f_line before this character */
4378                 }
4379             }
4380         }
4381     }
4382     /* terminator process */
4383     switch(fold_state) {
4384         case '\n': 
4385             (*o_fconv)(0,'\n');
4386             (*o_fconv)(c2,c1);
4387             break;
4388         case 0:    
4389             return;
4390         case '\r': 
4391             (*o_fconv)(0,'\n');
4392             break;
4393         case '\t': 
4394         case ' ': 
4395             (*o_fconv)(0,' ');
4396             break;
4397         default:
4398             (*o_fconv)(c2,c1);
4399     }
4400 }
4401
4402 nkf_char z_prev2=0,z_prev1=0;
4403
4404 void z_conv(nkf_char c2, nkf_char c1)
4405 {
4406
4407     /* if (c2) c1 &= 0x7f; assertion */
4408
4409     if (x0201_f && z_prev2==X0201) {  /* X0201 */
4410         if (c1==(0xde&0x7f)) { /* \e$BByE@\e(B */
4411             z_prev2=0;
4412             (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
4413             return;
4414         } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) {  /* \e$BH>ByE@\e(B */
4415             z_prev2=0;
4416             (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
4417             return;
4418         } else {
4419             z_prev2=0;
4420             (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
4421         }
4422     }
4423
4424     if (c2==EOF) {
4425         (*o_zconv)(c2,c1);
4426         return;
4427     }
4428
4429     if (x0201_f && c2==X0201) {
4430         if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
4431             /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
4432             z_prev1 = c1; z_prev2 = c2;
4433             return;
4434         } else {
4435             (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
4436             return;
4437         }
4438     }
4439
4440     /* JISX0208 Alphabet */
4441     if (alpha_f && c2 == 0x23 ) {
4442         c2 = 0;
4443     } else if (alpha_f && c2 == 0x21 ) { 
4444     /* JISX0208 Kigou */
4445        if (0x21==c1) {
4446            if (alpha_f&0x2) {
4447                c1 = ' ';
4448                c2 = 0;
4449            } else if (alpha_f&0x4) {
4450                 (*o_zconv)(0,' ');
4451                 (*o_zconv)(0,' ');
4452                 return;
4453            } 
4454        } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
4455            c1 = fv[c1-0x20];
4456            c2 =  0;
4457            if (alpha_f&0x8) {
4458                char *entity = 0;
4459                switch (c1){
4460                  case '>': entity = "&gt;"; break;
4461                  case '<': entity = "&lt;"; break;
4462                  case '\"': entity = "&quot;"; break;
4463                  case '&': entity = "&amp;"; break;
4464                }
4465                if (entity){
4466                    while (*entity) (*o_zconv)(0, *entity++);
4467                    return;
4468                }
4469            }
4470        } 
4471     }
4472     (*o_zconv)(c2,c1);
4473 }
4474
4475
4476 #define rot13(c)  ( \
4477       ( c < 'A' ) ? c: \
4478       (c <= 'M')  ? (c + 13): \
4479       (c <= 'Z')  ? (c - 13): \
4480       (c < 'a')   ? (c): \
4481       (c <= 'm')  ? (c + 13): \
4482       (c <= 'z')  ? (c - 13): \
4483       (c) \
4484 )
4485
4486 #define  rot47(c) ( \
4487       ( c < '!' ) ? c: \
4488       ( c <= 'O' ) ? (c + 47) : \
4489       ( c <= '~' ) ?  (c - 47) : \
4490       c \
4491 )
4492
4493 void rot_conv(nkf_char c2, nkf_char c1)
4494 {
4495     if (c2==0 || c2==X0201 || c2==ISO8859_1) {
4496         c1 = rot13(c1);
4497     } else if (c2) {
4498         c1 = rot47(c1);
4499         c2 = rot47(c2);
4500     }
4501     (*o_rot_conv)(c2,c1);
4502 }
4503
4504 void hira_conv(nkf_char c2, nkf_char c1)
4505 {
4506     if (hira_f & 1) {
4507         if (c2 == 0x25) {
4508             if (0x20 < c1 && c1 < 0x74) {
4509                 c2 = 0x24;
4510                 (*o_hira_conv)(c2,c1);
4511                 return;
4512             } else if (c1 == 0x74 && (output_conv == w_oconv || output_conv == w_oconv16)) {
4513                 c2 = 0;
4514                 c1 = CLASS_UNICODE | 0x3094;
4515                 (*o_hira_conv)(c2,c1);
4516                 return;
4517             }
4518         } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
4519             c1 += 2;
4520             (*o_hira_conv)(c2,c1);
4521             return;
4522         }
4523     }
4524     if (hira_f & 2) {
4525         if (c2 == 0 && c1 == (CLASS_UNICODE | 0x3094)) {
4526             c2 = 0x25;
4527             c1 = 0x74;
4528         } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
4529             c2 = 0x25;
4530         } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
4531             c1 -= 2;
4532         }
4533     }
4534     (*o_hira_conv)(c2,c1);
4535 }
4536
4537
4538 void iso2022jp_check_conv(nkf_char c2, nkf_char c1)
4539 {
4540     static const nkf_char range[RANGE_NUM_MAX][2] = {
4541         {0x222f, 0x2239,},
4542         {0x2242, 0x2249,},
4543         {0x2251, 0x225b,},
4544         {0x226b, 0x2271,},
4545         {0x227a, 0x227d,},
4546         {0x2321, 0x232f,},
4547         {0x233a, 0x2340,},
4548         {0x235b, 0x2360,},
4549         {0x237b, 0x237e,},
4550         {0x2474, 0x247e,},
4551         {0x2577, 0x257e,},
4552         {0x2639, 0x2640,},
4553         {0x2659, 0x267e,},
4554         {0x2742, 0x2750,},
4555         {0x2772, 0x277e,},
4556         {0x2841, 0x287e,},
4557         {0x4f54, 0x4f7e,},
4558         {0x7425, 0x747e},
4559     };
4560     nkf_char i;
4561     nkf_char start, end, c;
4562
4563     if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
4564         c2 = GETA1;
4565         c1 = GETA2;
4566     }
4567     if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
4568         c2 = GETA1;
4569         c1 = GETA2;
4570     }
4571
4572     for (i = 0; i < RANGE_NUM_MAX; i++) {
4573         start = range[i][0];
4574         end   = range[i][1];
4575         c     = (c2 << 8) + c1;
4576         if (c >= start && c <= end) {
4577             c2 = GETA1;
4578             c1 = GETA2;
4579         }
4580     }
4581     (*o_iso2022jp_check_conv)(c2,c1);
4582 }
4583
4584
4585 /* This converts  =?ISO-2022-JP?B?HOGE HOGE?= */
4586
4587 const unsigned char *mime_pattern[] = {
4588     (const unsigned char *)"\075?EUC-JP?B?",
4589     (const unsigned char *)"\075?SHIFT_JIS?B?",
4590     (const unsigned char *)"\075?ISO-8859-1?Q?",
4591     (const unsigned char *)"\075?ISO-8859-1?B?",
4592     (const unsigned char *)"\075?ISO-2022-JP?B?",
4593     (const unsigned char *)"\075?ISO-2022-JP?Q?",
4594 #if defined(UTF8_INPUT_ENABLE)
4595     (const unsigned char *)"\075?UTF-8?B?",
4596     (const unsigned char *)"\075?UTF-8?Q?",
4597 #endif
4598     (const unsigned char *)"\075?US-ASCII?Q?",
4599     NULL
4600 };
4601
4602
4603 /* \e$B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u\e(B */
4604 nkf_char (*mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
4605     e_iconv, s_iconv, 0, 0, 0, 0,
4606 #if defined(UTF8_INPUT_ENABLE)
4607     w_iconv, w_iconv,
4608 #endif
4609     0,
4610 };
4611
4612 const nkf_char mime_encode[] = {
4613     JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
4614 #if defined(UTF8_INPUT_ENABLE)
4615     UTF8, UTF8,
4616 #endif
4617     ASCII,
4618     0
4619 };
4620
4621 const nkf_char mime_encode_method[] = {
4622     'B', 'B','Q', 'B', 'B', 'Q',
4623 #if defined(UTF8_INPUT_ENABLE)
4624     'B', 'Q',
4625 #endif
4626     'Q',
4627     0
4628 };
4629
4630
4631 #define MAXRECOVER 20
4632
4633 void switch_mime_getc(void)
4634 {
4635     if (i_getc!=mime_getc) {
4636         i_mgetc = i_getc; i_getc = mime_getc;
4637         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
4638         if(mime_f==STRICT_MIME) {
4639             i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
4640             i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
4641         }
4642     }
4643 }
4644
4645 void unswitch_mime_getc(void)
4646 {
4647     if(mime_f==STRICT_MIME) {
4648         i_mgetc = i_mgetc_buf;
4649         i_mungetc = i_mungetc_buf;
4650     }
4651     i_getc = i_mgetc;
4652     i_ungetc = i_mungetc;
4653     if(mime_iconv_back)set_iconv(FALSE, mime_iconv_back);
4654     mime_iconv_back = NULL;
4655 }
4656
4657 nkf_char mime_begin_strict(FILE *f)
4658 {
4659     nkf_char c1 = 0;
4660     int i,j,k;
4661     const unsigned char *p,*q;
4662     nkf_char r[MAXRECOVER];    /* recovery buffer, max mime pattern length */
4663
4664     mime_decode_mode = FALSE;
4665     /* =? has been checked */
4666     j = 0;
4667     p = mime_pattern[j];
4668     r[0]='='; r[1]='?';
4669
4670     for(i=2;p[i]>' ';i++) {                   /* start at =? */
4671         if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
4672             /* pattern fails, try next one */
4673             q = p;
4674             while (mime_pattern[++j]) {
4675                 p = mime_pattern[j];
4676                 for(k=2;k<i;k++)              /* assume length(p) > i */
4677                     if (p[k]!=q[k]) break;
4678                 if (k==i && nkf_toupper(c1)==p[k]) break;
4679             }
4680             p = mime_pattern[j];
4681             if (p) continue;  /* found next one, continue */
4682             /* all fails, output from recovery buffer */
4683             (*i_ungetc)(c1,f);
4684             for(j=0;j<i;j++) {
4685                 (*oconv)(0,r[j]);
4686             }
4687             return c1;
4688         }
4689     }
4690     mime_decode_mode = p[i-2];
4691
4692     mime_iconv_back = iconv;
4693     set_iconv(FALSE, mime_priority_func[j]);
4694     clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
4695
4696     if (mime_decode_mode=='B') {
4697         mimebuf_f = unbuf_f;
4698         if (!unbuf_f) {
4699             /* do MIME integrity check */
4700             return mime_integrity(f,mime_pattern[j]);
4701         } 
4702     }
4703     switch_mime_getc();
4704     mimebuf_f = TRUE;
4705     return c1;
4706 }
4707
4708 nkf_char mime_getc_buf(FILE *f)
4709 {
4710     /* we don't keep eof of Fifo, becase it contains ?= as
4711        a terminator. It was checked in mime_integrity. */
4712     return ((mimebuf_f)?
4713         (*i_mgetc_buf)(f):Fifo(mime_input++));
4714 }
4715
4716 nkf_char mime_ungetc_buf(nkf_char c, FILE *f)
4717 {
4718     if (mimebuf_f)
4719         (*i_mungetc_buf)(c,f);
4720     else 
4721         Fifo(--mime_input) = (unsigned char)c;
4722     return c;
4723 }
4724
4725 nkf_char mime_begin(FILE *f)
4726 {
4727     nkf_char c1;
4728     int i,k;
4729
4730     /* In NONSTRICT mode, only =? is checked. In case of failure, we  */
4731     /* re-read and convert again from mime_buffer.  */
4732
4733     /* =? has been checked */
4734     k = mime_last;
4735     Fifo(mime_last++)='='; Fifo(mime_last++)='?';
4736     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
4737         /* We accept any character type even if it is breaked by new lines */
4738         c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
4739         if (c1=='\n'||c1==' '||c1=='\r'||
4740                 c1=='-'||c1=='_'||is_alnum(c1) ) continue;
4741         if (c1=='=') {
4742             /* Failed. But this could be another MIME preemble */
4743             (*i_ungetc)(c1,f);
4744             mime_last--;
4745             break;
4746         }
4747         if (c1!='?') break;
4748         else {
4749             /* c1=='?' */
4750             c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
4751             if (!(++i<MAXRECOVER) || c1==EOF) break;
4752             if (c1=='b'||c1=='B') {
4753                 mime_decode_mode = 'B';
4754             } else if (c1=='q'||c1=='Q') {
4755                 mime_decode_mode = 'Q';
4756             } else {
4757                 break;
4758             }
4759             c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
4760             if (!(++i<MAXRECOVER) || c1==EOF) break;
4761             if (c1!='?') {
4762                 mime_decode_mode = FALSE;
4763             }
4764             break;
4765         }
4766     }
4767     switch_mime_getc();
4768     if (!mime_decode_mode) {
4769         /* false MIME premble, restart from mime_buffer */
4770         mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
4771         /* Since we are in MIME mode until buffer becomes empty,    */
4772         /* we never go into mime_begin again for a while.           */
4773         return c1;
4774     }
4775     /* discard mime preemble, and goto MIME mode */
4776     mime_last = k;
4777     /* do no MIME integrity check */
4778     return c1;   /* used only for checking EOF */
4779 }
4780
4781 #ifdef CHECK_OPTION
4782 void no_putc(nkf_char c)
4783 {
4784     ;
4785 }
4786
4787 void debug(const char *str)
4788 {
4789     if (debug_f){
4790         fprintf(stderr, "%s\n", str);
4791     }
4792 }
4793 #endif
4794
4795 void set_input_codename(char *codename)
4796 {
4797     if (guess_f && 
4798         is_inputcode_set &&
4799         strcmp(codename, "") != 0 && 
4800         strcmp(codename, input_codename) != 0)
4801     {
4802         is_inputcode_mixed = TRUE;
4803     }
4804     input_codename = codename;
4805     is_inputcode_set = TRUE;
4806 }
4807
4808 #if !defined(PERL_XS) && !defined(WIN32DLL)
4809 void print_guessed_code(char *filename)
4810 {
4811     char *codename = "BINARY";
4812     if (!is_inputcode_mixed) {
4813         if (strcmp(input_codename, "") == 0) {
4814             codename = "ASCII";
4815         } else {
4816             codename = input_codename;
4817         }
4818     }
4819     if (filename != NULL) printf("%s:", filename);
4820     printf("%s\n", codename);
4821 }
4822 #endif /*WIN32DLL*/
4823
4824 #ifdef INPUT_OPTION 
4825
4826 nkf_char hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f))
4827 {
4828     nkf_char c1, c2, c3;
4829     c1 = (*g)(f);
4830     if (c1 != ch){
4831         return c1;
4832     }
4833     c2 = (*g)(f);
4834     if (!nkf_isxdigit(c2)){
4835         (*u)(c2, f);
4836         return c1;
4837     }
4838     c3 = (*g)(f);
4839     if (!nkf_isxdigit(c3)){
4840         (*u)(c2, f);
4841         (*u)(c3, f);
4842         return c1;
4843     }
4844     return (hex2bin(c2) << 4) | hex2bin(c3);
4845 }
4846
4847 nkf_char cap_getc(FILE *f)
4848 {
4849     return hex_getc(':', f, i_cgetc, i_cungetc);
4850 }
4851
4852 nkf_char cap_ungetc(nkf_char c, FILE *f)
4853 {
4854     return (*i_cungetc)(c, f);
4855 }
4856
4857 nkf_char url_getc(FILE *f)
4858 {
4859     return hex_getc('%', f, i_ugetc, i_uungetc);
4860 }
4861
4862 nkf_char url_ungetc(nkf_char c, FILE *f)
4863 {
4864     return (*i_uungetc)(c, f);
4865 }
4866 #endif
4867
4868 #ifdef NUMCHAR_OPTION
4869 nkf_char numchar_getc(FILE *f)
4870 {
4871     nkf_char (*g)(FILE *) = i_ngetc;
4872     nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc;
4873     int i = 0, j;
4874     nkf_char buf[8];
4875     long c = -1;
4876
4877     buf[i] = (*g)(f);
4878     if (buf[i] == '&'){
4879         buf[++i] = (*g)(f);
4880         if (buf[i] == '#'){
4881             c = 0;
4882             buf[++i] = (*g)(f);
4883             if (buf[i] == 'x' || buf[i] == 'X'){
4884                 for (j = 0; j < 7; j++){
4885                     buf[++i] = (*g)(f);
4886                     if (!nkf_isxdigit(buf[i])){
4887                         if (buf[i] != ';'){
4888                             c = -1;
4889                         }
4890                         break;
4891                     }
4892                     c <<= 4;
4893                     c |= hex2bin(buf[i]);
4894                 }
4895             }else{
4896                 for (j = 0; j < 8; j++){
4897                     if (j){
4898                         buf[++i] = (*g)(f);
4899                     }
4900                     if (!nkf_isdigit(buf[i])){
4901                         if (buf[i] != ';'){
4902                             c = -1;
4903                         }
4904                         break;
4905                     }
4906                     c *= 10;
4907                     c += hex2bin(buf[i]);
4908                 }
4909             }
4910         }
4911     }
4912     if (c != -1){
4913         return CLASS_UNICODE | c;
4914     }
4915     while (i > 0){
4916         (*u)(buf[i], f);
4917         --i;
4918     }
4919     return buf[0];
4920 }
4921
4922 nkf_char numchar_ungetc(nkf_char c, FILE *f)
4923 {
4924     return (*i_nungetc)(c, f);
4925 }
4926 #endif
4927
4928 #ifdef UNICODE_NORMALIZATION
4929
4930 /* Normalization Form C */
4931 nkf_char nfc_getc(FILE *f)
4932 {
4933     nkf_char (*g)(FILE *f) = i_nfc_getc;
4934     nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
4935     int i=0, j, k=1, lower, upper;
4936     nkf_char buf[9];
4937     const nkf_nfchar *array;
4938 #if 0
4939     extern const struct normalization_pair normalization_table[];
4940 #endif
4941     
4942     buf[i] = (*g)(f);
4943     while (k > 0 && ((buf[i] & 0xc0) != 0x80)){
4944         lower=0, upper=NORMALIZATION_TABLE_LENGTH-1;
4945         while (upper >= lower) {
4946             j = (lower+upper) / 2;
4947             array = normalization_table[j].nfd;
4948             for (k=0; k < NORMALIZATION_TABLE_NFD_LENGTH && array[k]; k++){
4949                 if (array[k] != buf[k]){
4950                     array[k] < buf[k] ? (lower = j + 1) : (upper = j - 1);
4951                     k = 0;
4952                     break;
4953                 } else if (k >= i)
4954                     buf[++i] = (*g)(f);
4955             }
4956             if (k > 0){
4957                 array = normalization_table[j].nfc;
4958                 for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++)
4959                     buf[i] = (nkf_char)(array[i]);
4960                 i--;
4961                 break;
4962             }
4963         }
4964         while (i > 0)
4965             (*u)(buf[i--], f);
4966     }
4967     return buf[0];
4968 }
4969
4970 nkf_char nfc_ungetc(nkf_char c, FILE *f)
4971 {
4972     return (*i_nfc_ungetc)(c, f);
4973 }
4974 #endif /* UNICODE_NORMALIZATION */
4975
4976
4977 nkf_char 
4978 mime_getc(FILE *f)
4979 {
4980     nkf_char c1, c2, c3, c4, cc;
4981     nkf_char t1, t2, t3, t4, mode, exit_mode;
4982     nkf_char lwsp_count;
4983     char *lwsp_buf;
4984     char *lwsp_buf_new;
4985     nkf_char lwsp_size = 128;
4986
4987     if (mime_top != mime_last) {  /* Something is in FIFO */
4988         return  Fifo(mime_top++);
4989     }
4990     if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
4991         mime_decode_mode=FALSE;
4992         unswitch_mime_getc();
4993         return (*i_getc)(f);
4994     }
4995
4996     if (mimebuf_f == FIXED_MIME)
4997         exit_mode = mime_decode_mode;
4998     else
4999         exit_mode = FALSE;
5000     if (mime_decode_mode == 'Q') {
5001         if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
5002 restart_mime_q:
5003         if (c1=='_' && mimebuf_f != FIXED_MIME) return ' ';
5004         if (c1<=' ' || DEL<=c1) {
5005             mime_decode_mode = exit_mode; /* prepare for quit */
5006             return c1;
5007         }
5008         if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) {
5009             return c1;
5010         }
5011                 
5012         mime_decode_mode = exit_mode; /* prepare for quit */
5013         if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
5014         if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
5015             /* end Q encoding */
5016             input_mode = exit_mode;
5017             lwsp_count = 0;
5018             lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
5019             if (lwsp_buf==NULL) {
5020                 perror("can't malloc");
5021                 return -1;
5022             }
5023             while ((c1=(*i_getc)(f))!=EOF) {
5024                 switch (c1) {
5025                 case NL:
5026                 case CR:
5027                     if (c1==NL) {
5028                         if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
5029                             i_ungetc(SPACE,f);
5030                             continue;
5031                         } else {
5032                             i_ungetc(c1,f);
5033                         }
5034                         c1 = NL;
5035                     } else {
5036                         if ((c1=(*i_getc)(f))!=EOF && c1 == NL) {
5037                             if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
5038                                 i_ungetc(SPACE,f);
5039                                 continue;
5040                             } else {
5041                                 i_ungetc(c1,f);
5042                             }
5043                             i_ungetc(NL,f);
5044                         } else {
5045                             i_ungetc(c1,f);
5046                         }
5047                         c1 = CR;
5048                     }
5049                     break;
5050                 case SPACE:
5051                 case TAB:
5052                     lwsp_buf[lwsp_count] = (unsigned char)c1;
5053                     if (lwsp_count++>lwsp_size){
5054                         lwsp_size <<= 1;
5055                         lwsp_buf_new = realloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
5056                         if (lwsp_buf_new==NULL) {
5057                             free(lwsp_buf);
5058                             perror("can't realloc");
5059                             return -1;
5060                         }
5061                         lwsp_buf = lwsp_buf_new;
5062                     }
5063                     continue;
5064                 }
5065                 break;
5066             }
5067             if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SPACE && lwsp_buf[lwsp_count-1] != TAB))) {
5068                 i_ungetc(c1,f);
5069                 for(lwsp_count--;lwsp_count>0;lwsp_count--)
5070                     i_ungetc(lwsp_buf[lwsp_count],f);
5071                 c1 = lwsp_buf[0];
5072             }
5073             free(lwsp_buf);
5074             return c1;
5075         }
5076         if (c1=='='&&c2<' ') { /* this is soft wrap */
5077             while((c1 =  (*i_mgetc)(f)) <=' ') {
5078                 if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
5079             }
5080             mime_decode_mode = 'Q'; /* still in MIME */
5081             goto restart_mime_q;
5082         }
5083         if (c1=='?') {
5084             mime_decode_mode = 'Q'; /* still in MIME */
5085             (*i_mungetc)(c2,f);
5086             return c1;
5087         }
5088         if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
5089         if (c2<=' ') return c2;
5090         mime_decode_mode = 'Q'; /* still in MIME */
5091         return ((hex2bin(c2)<<4) + hex2bin(c3));
5092     }
5093
5094     if (mime_decode_mode != 'B') {
5095         mime_decode_mode = FALSE;
5096         return (*i_mgetc)(f);
5097     }
5098
5099
5100     /* Base64 encoding */
5101     /* 
5102         MIME allows line break in the middle of 
5103         Base64, but we are very pessimistic in decoding
5104         in unbuf mode because MIME encoded code may broken by 
5105         less or editor's control sequence (such as ESC-[-K in unbuffered
5106         mode. ignore incomplete MIME.
5107     */
5108     mode = mime_decode_mode;
5109     mime_decode_mode = exit_mode;  /* prepare for quit */
5110
5111     while ((c1 = (*i_mgetc)(f))<=' ') {
5112         if (c1==EOF)
5113             return (EOF);
5114     }
5115 mime_c2_retry:
5116     if ((c2 = (*i_mgetc)(f))<=' ') {
5117         if (c2==EOF)
5118             return (EOF);
5119         if (mime_f != STRICT_MIME) goto mime_c2_retry;
5120         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
5121         return c2;
5122     }
5123     if ((c1 == '?') && (c2 == '=')) {
5124         input_mode = ASCII;
5125         lwsp_count = 0;
5126         lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
5127         if (lwsp_buf==NULL) {
5128             perror("can't malloc");
5129             return -1;
5130         }
5131         while ((c1=(*i_getc)(f))!=EOF) {
5132             switch (c1) {
5133             case NL:
5134             case CR:
5135                 if (c1==NL) {
5136                     if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
5137                         i_ungetc(SPACE,f);
5138                         continue;
5139                     } else {
5140                         i_ungetc(c1,f);
5141                     }
5142                     c1 = NL;
5143                 } else {
5144                     if ((c1=(*i_getc)(f))!=EOF) {
5145                         if (c1==SPACE) {
5146                             i_ungetc(SPACE,f);
5147                             continue;
5148                         } else if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
5149                             i_ungetc(SPACE,f);
5150                             continue;
5151                         } else {
5152                             i_ungetc(c1,f);
5153                         }
5154                         i_ungetc(NL,f);
5155                     } else {
5156                         i_ungetc(c1,f);
5157                     }
5158                     c1 = CR;
5159                 }
5160                 break;
5161             case SPACE:
5162             case TAB:
5163                 lwsp_buf[lwsp_count] = (unsigned char)c1;
5164                 if (lwsp_count++>lwsp_size){
5165                     lwsp_size <<= 1;
5166                     lwsp_buf_new = realloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
5167                     if (lwsp_buf_new==NULL) {
5168                         free(lwsp_buf);
5169                         perror("can't realloc");
5170                         return -1;
5171                     }
5172                     lwsp_buf = lwsp_buf_new;
5173                 }
5174                 continue;
5175             }
5176             break;
5177         }
5178         if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SPACE && lwsp_buf[lwsp_count-1] != TAB))) {
5179             i_ungetc(c1,f);
5180             for(lwsp_count--;lwsp_count>0;lwsp_count--)
5181                 i_ungetc(lwsp_buf[lwsp_count],f);
5182             c1 = lwsp_buf[0];
5183         }
5184         free(lwsp_buf);
5185         return c1;
5186     }
5187 mime_c3_retry:
5188     if ((c3 = (*i_mgetc)(f))<=' ') {
5189         if (c3==EOF)
5190             return (EOF);
5191         if (mime_f != STRICT_MIME) goto mime_c3_retry;
5192         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
5193         return c3;
5194     }
5195 mime_c4_retry:
5196     if ((c4 = (*i_mgetc)(f))<=' ') {
5197         if (c4==EOF)
5198             return (EOF);
5199         if (mime_f != STRICT_MIME) goto mime_c4_retry;
5200         if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
5201         return c4;
5202     }
5203
5204     mime_decode_mode = mode; /* still in MIME sigh... */
5205
5206     /* BASE 64 decoding */
5207
5208     t1 = 0x3f & base64decode(c1);
5209     t2 = 0x3f & base64decode(c2);
5210     t3 = 0x3f & base64decode(c3);
5211     t4 = 0x3f & base64decode(c4);
5212     cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
5213     if (c2 != '=') {
5214         Fifo(mime_last++) = (unsigned char)cc;
5215         cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
5216         if (c3 != '=') {
5217             Fifo(mime_last++) = (unsigned char)cc;
5218             cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
5219             if (c4 != '=') 
5220                 Fifo(mime_last++) = (unsigned char)cc;
5221         }
5222     } else {
5223         return c1;
5224     }
5225     return  Fifo(mime_top++);
5226 }
5227
5228 nkf_char mime_ungetc(nkf_char c, FILE *f)
5229 {
5230     Fifo(--mime_top) = (unsigned char)c;
5231     return c;
5232 }
5233
5234 nkf_char mime_integrity(FILE *f, const unsigned char *p)
5235 {
5236     nkf_char c,d;
5237     unsigned int q;
5238     /* In buffered mode, read until =? or NL or buffer full
5239      */
5240     mime_input = mime_top;
5241     mime_last = mime_top;
5242     
5243     while(*p) Fifo(mime_input++) = *p++;
5244     d = 0;
5245     q = mime_input;
5246     while((c=(*i_getc)(f))!=EOF) {
5247         if (((mime_input-mime_top)&MIME_BUF_MASK)==0) {
5248             break;   /* buffer full */
5249         }
5250         if (c=='=' && d=='?') {
5251             /* checked. skip header, start decode */
5252             Fifo(mime_input++) = (unsigned char)c;
5253             /* mime_last_input = mime_input; */
5254             mime_input = q; 
5255             switch_mime_getc();
5256             return 1;
5257         }
5258         if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
5259             break;
5260         /* Should we check length mod 4? */
5261         Fifo(mime_input++) = (unsigned char)c;
5262         d=c;
5263     }
5264     /* In case of Incomplete MIME, no MIME decode  */
5265     Fifo(mime_input++) = (unsigned char)c;
5266     mime_last = mime_input;     /* point undecoded buffer */
5267     mime_decode_mode = 1;              /* no decode on Fifo last in mime_getc */
5268     switch_mime_getc();         /* anyway we need buffered getc */
5269     return 1;
5270 }
5271
5272 nkf_char base64decode(nkf_char c)
5273 {
5274     int             i;
5275     if (c > '@') {
5276         if (c < '[') {
5277             i = c - 'A';                        /* A..Z 0-25 */
5278         } else {
5279             i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
5280         }
5281     } else if (c > '/') {
5282         i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
5283     } else if (c == '+') {
5284         i = '>'             /* 62 */ ;          /* +  62 */
5285     } else {
5286         i = '?'             /* 63 */ ;          /* / 63 */
5287     }
5288     return (i);
5289 }
5290
5291 static const char basis_64[] =
5292    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5293
5294 static nkf_char b64c;
5295 #define MIMEOUT_BUF_LENGTH (60)
5296 char mimeout_buf[MIMEOUT_BUF_LENGTH+1];
5297 int mimeout_buf_count = 0;
5298 int mimeout_preserve_space = 0;
5299 #define itoh4(c)   (c>=10?c+'A'-10:c+'0')
5300
5301 void open_mime(nkf_char mode)
5302 {
5303     const unsigned char *p;
5304     int i;
5305     int j;
5306     p  = mime_pattern[0];
5307     for(i=0;mime_encode[i];i++) {
5308         if (mode == mime_encode[i]) {
5309             p = mime_pattern[i];
5310             break;
5311         }
5312     }
5313     mimeout_mode = mime_encode_method[i];
5314     
5315     i = 0;
5316     if (base64_count>45) {
5317         if (mimeout_buf_count>0 && nkf_isblank(mimeout_buf[i])){
5318             (*o_mputc)(mimeout_buf[i]);
5319             i++;
5320         }
5321         (*o_mputc)(NL);
5322         (*o_mputc)(SPACE);
5323         base64_count = 1;
5324         if (!mimeout_preserve_space && mimeout_buf_count>0
5325             && (mimeout_buf[i]==SPACE || mimeout_buf[i]==TAB
5326                 || mimeout_buf[i]==CR || mimeout_buf[i]==NL )) {
5327             i++;
5328         }
5329     }
5330     if (!mimeout_preserve_space) {
5331         for (;i<mimeout_buf_count;i++) {
5332             if (mimeout_buf[i]==SPACE || mimeout_buf[i]==TAB
5333                 || mimeout_buf[i]==CR || mimeout_buf[i]==NL ) {
5334                 (*o_mputc)(mimeout_buf[i]);
5335                 base64_count ++;
5336             } else {
5337                 break;
5338             }
5339         }
5340     }
5341     mimeout_preserve_space = FALSE;
5342     
5343     while(*p) {
5344         (*o_mputc)(*p++);
5345         base64_count ++;
5346     }
5347     j = mimeout_buf_count;
5348     mimeout_buf_count = 0;
5349     for (;i<j;i++) {
5350         mime_putc(mimeout_buf[i]);
5351     }
5352 }
5353
5354 void close_mime(void)
5355 {
5356     (*o_mputc)('?');
5357     (*o_mputc)('=');
5358     base64_count += 2;
5359     mimeout_mode = 0;
5360 }
5361
5362 void eof_mime(void)
5363 {
5364     switch(mimeout_mode) {
5365     case 'Q':
5366     case 'B':
5367         break;
5368     case 2:
5369         (*o_mputc)(basis_64[((b64c & 0x3)<< 4)]);
5370         (*o_mputc)('=');
5371         (*o_mputc)('=');
5372         base64_count += 3;
5373         break;
5374     case 1:
5375         (*o_mputc)(basis_64[((b64c & 0xF) << 2)]);
5376         (*o_mputc)('=');
5377         base64_count += 2;
5378         break;
5379     }
5380     if (mimeout_mode) {
5381         if (mimeout_f!=FIXED_MIME) {
5382             close_mime(); 
5383         } else if (mimeout_mode != 'Q')
5384             mimeout_mode = 'B';
5385     }
5386 }
5387
5388 void mimeout_addchar(nkf_char c)
5389 {
5390     switch(mimeout_mode) {
5391     case 'Q':
5392         if (c==CR||c==NL) {
5393             (*o_mputc)(c);
5394             base64_count = 0;
5395         } else if(!nkf_isalnum(c)) {
5396             (*o_mputc)('=');
5397             (*o_mputc)(itoh4(((c>>4)&0xf)));
5398             (*o_mputc)(itoh4((c&0xf)));
5399             base64_count += 3;
5400         } else {
5401             (*o_mputc)(c);
5402             base64_count++;
5403         }
5404         break;
5405     case 'B':
5406         b64c=c;
5407         (*o_mputc)(basis_64[c>>2]);
5408         mimeout_mode=2;
5409         base64_count ++;
5410         break;
5411     case 2:
5412         (*o_mputc)(basis_64[((b64c & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
5413         b64c=c;
5414         mimeout_mode=1;
5415         base64_count ++;
5416         break;
5417     case 1:
5418         (*o_mputc)(basis_64[((b64c & 0xF) << 2) | ((c & 0xC0) >>6)]);
5419         (*o_mputc)(basis_64[c & 0x3F]);
5420         mimeout_mode='B';
5421         base64_count += 2;
5422         break;
5423     default:
5424         (*o_mputc)(c);
5425         base64_count++;
5426         break;
5427     }
5428 }
5429
5430 nkf_char mime_lastchar2, mime_lastchar1;
5431
5432 void mime_prechar(nkf_char c2, nkf_char c1)
5433 {
5434     if (mimeout_mode){
5435         if (c2){
5436             if (base64_count + mimeout_buf_count/3*4> 66){
5437                 (*o_base64conv)(EOF,0);
5438                 (*o_base64conv)(0,NL);
5439                 (*o_base64conv)(0,SPACE);
5440             }
5441         }/*else if (mime_lastchar2){
5442             if (c1 <=DEL && !nkf_isspace(c1)){
5443                 (*o_base64conv)(0,SPACE);
5444             }
5445         }*/
5446     }/*else{
5447         if (c2 && mime_lastchar2 == 0
5448             && mime_lastchar1 && !nkf_isspace(mime_lastchar1)){
5449             (*o_base64conv)(0,SPACE);
5450         }
5451     }*/
5452     mime_lastchar2 = c2;
5453     mime_lastchar1 = c1;
5454 }
5455
5456 void mime_putc(nkf_char c)
5457 {
5458     int i, j;
5459     nkf_char lastchar;
5460
5461     if (mimeout_f == FIXED_MIME){
5462         if (mimeout_mode == 'Q'){
5463             if (base64_count > 71){
5464                 if (c!=CR && c!=NL) {
5465                     (*o_mputc)('=');
5466                     (*o_mputc)(NL);
5467                 }
5468                 base64_count = 0;
5469             }
5470         }else{
5471             if (base64_count > 71){
5472                 eof_mime();
5473                 (*o_mputc)(NL);
5474                 base64_count = 0;
5475             }
5476             if (c == EOF) { /* c==EOF */
5477                 eof_mime();
5478             }
5479         }
5480         if (c != EOF) { /* c==EOF */
5481             mimeout_addchar(c);
5482         }
5483         return;
5484     }
5485     
5486     /* mimeout_f != FIXED_MIME */
5487
5488     if (c == EOF) { /* c==EOF */
5489         j = mimeout_buf_count;
5490         mimeout_buf_count = 0;
5491         i = 0;
5492         if (mimeout_mode) {
5493             for (;i<j;i++) {
5494                 if (nkf_isspace(mimeout_buf[i]) && base64_count < 71){
5495                     break;
5496                 }
5497                 mimeout_addchar(mimeout_buf[i]);
5498             }
5499             eof_mime();
5500             for (;i<j;i++) {
5501                 mimeout_addchar(mimeout_buf[i]);
5502             }
5503         } else {
5504             for (;i<j;i++) {
5505                 mimeout_addchar(mimeout_buf[i]);
5506             }
5507         }
5508         return;
5509     }
5510
5511     if (mimeout_mode=='Q') {
5512         if (c <= DEL && (output_mode==ASCII ||output_mode == ISO8859_1 ) ) {
5513             if (c <= SPACE) {
5514                 close_mime();
5515                 (*o_mputc)(SPACE);
5516                 base64_count++;
5517             }
5518             (*o_mputc)(c);
5519             base64_count++;
5520         }
5521         return;
5522     }
5523
5524     if (mimeout_buf_count > 0){
5525         lastchar = mimeout_buf[mimeout_buf_count - 1];
5526     }else{
5527         lastchar = -1;
5528     }
5529
5530     if (!mimeout_mode) {
5531         if (c <= DEL && (output_mode==ASCII ||output_mode == ISO8859_1)) {
5532             if (nkf_isspace(c)) {
5533                 if (c==CR || c==NL) {
5534                     base64_count=0;
5535                 }
5536                 for (i=0;i<mimeout_buf_count;i++) {
5537                     (*o_mputc)(mimeout_buf[i]);
5538                     if (mimeout_buf[i] == CR || mimeout_buf[i] == NL){
5539                         base64_count = 0;
5540                     }else{
5541                         base64_count++;
5542                     }
5543                 }
5544                 mimeout_buf[0] = (char)c;
5545                 mimeout_buf_count = 1;
5546             }else{
5547                 if (base64_count > 1
5548                     && base64_count + mimeout_buf_count > 76){
5549                     (*o_mputc)(NL);
5550                     base64_count = 0;
5551                     if (!nkf_isspace(mimeout_buf[0])){
5552                         (*o_mputc)(SPACE);
5553                         base64_count++;
5554                     }
5555                 }
5556                 mimeout_buf[mimeout_buf_count++] = (char)c;
5557                 if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
5558                     open_mime(output_mode);
5559                 }
5560             }
5561             return;
5562         }else{
5563             if (lastchar==CR || lastchar == NL){
5564                 for (i=0;i<mimeout_buf_count;i++) {
5565                     (*o_mputc)(mimeout_buf[i]);
5566                 }
5567                 base64_count = 0;
5568                 mimeout_buf_count = 0;
5569             }
5570             if (lastchar==SPACE) {
5571                 for (i=0;i<mimeout_buf_count-1;i++) {
5572                     (*o_mputc)(mimeout_buf[i]);
5573                     base64_count++;
5574                 }
5575                 mimeout_buf[0] = SPACE;
5576                 mimeout_buf_count = 1;
5577             }
5578             open_mime(output_mode);
5579         }
5580     }else{
5581         /* mimeout_mode == 'B', 1, 2 */
5582         if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO8859_1 ) ) {
5583             if (lastchar == CR || lastchar == NL){
5584                 if (nkf_isblank(c)) {
5585                     for (i=0;i<mimeout_buf_count;i++) {
5586                         mimeout_addchar(mimeout_buf[i]);
5587                     }
5588                     mimeout_buf_count = 0;
5589                 } else if (SPACE<c && c<DEL) {
5590                     eof_mime();
5591                     for (i=0;i<mimeout_buf_count;i++) {
5592                         (*o_mputc)(mimeout_buf[i]);
5593                     }
5594                     base64_count = 0;
5595                     mimeout_buf_count = 0;
5596                 }
5597             }
5598             if (c==SPACE || c==TAB || c==CR || c==NL) {
5599                 for (i=0;i<mimeout_buf_count;i++) {
5600                     if (SPACE<mimeout_buf[i] && mimeout_buf[i]<DEL) {
5601                         eof_mime();
5602                         for (i=0;i<mimeout_buf_count;i++) {
5603                             (*o_mputc)(mimeout_buf[i]);
5604                             base64_count++;
5605                         }
5606                         mimeout_buf_count = 0;
5607                     }
5608                 }
5609                 mimeout_buf[mimeout_buf_count++] = (char)c;
5610                 if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
5611                     eof_mime();
5612                     for (i=0;i<mimeout_buf_count;i++) {
5613                         (*o_mputc)(mimeout_buf[i]);
5614                         base64_count++;
5615                     }
5616                     mimeout_buf_count = 0;
5617                 }
5618                 return;
5619             }
5620             if (mimeout_buf_count>0 && SPACE<c && c!='=') {
5621                 mimeout_buf[mimeout_buf_count++] = (char)c;
5622                 if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
5623                     j = mimeout_buf_count;
5624                     mimeout_buf_count = 0;
5625                     for (i=0;i<j;i++) {
5626                         mimeout_addchar(mimeout_buf[i]);
5627                     }
5628                 }
5629                 return;
5630             }
5631         }
5632     }
5633     if (mimeout_buf_count>0) {
5634         j = mimeout_buf_count;
5635         mimeout_buf_count = 0;
5636         for (i=0;i<j;i++) {
5637             if (mimeout_buf[i]==CR || mimeout_buf[i]==NL)
5638                 break;
5639             mimeout_addchar(mimeout_buf[i]);
5640         }
5641         if (i<j) {
5642             eof_mime();
5643             base64_count=0;
5644             for (;i<j;i++) {
5645                 (*o_mputc)(mimeout_buf[i]);
5646             }
5647             open_mime(output_mode);
5648         }
5649     }
5650     mimeout_addchar(c);
5651 }
5652
5653
5654 #if defined(PERL_XS) || defined(WIN32DLL)
5655 void reinit(void)
5656 {
5657     {
5658         struct input_code *p = input_code_list;
5659         while (p->name){
5660             status_reinit(p++);
5661         }
5662     }
5663     unbuf_f = FALSE;
5664     estab_f = FALSE;
5665     nop_f = FALSE;
5666     binmode_f = TRUE;
5667     rot_f = FALSE;
5668     hira_f = FALSE;
5669     input_f = FALSE;
5670     alpha_f = FALSE;
5671     mime_f = STRICT_MIME;
5672     mime_decode_f = FALSE;
5673     mimebuf_f = FALSE;
5674     broken_f = FALSE;
5675     iso8859_f = FALSE;
5676     mimeout_f = FALSE;
5677 #if defined(MSDOS) || defined(__OS2__)
5678      x0201_f = TRUE;
5679 #else
5680      x0201_f = NO_X0201;
5681 #endif
5682     iso2022jp_f = FALSE;
5683 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
5684     ms_ucs_map_f = UCS_MAP_ASCII;
5685 #endif
5686 #ifdef UTF8_INPUT_ENABLE
5687     no_cp932ext_f = FALSE;
5688     no_best_fit_chars_f = FALSE;
5689     encode_fallback = NULL;
5690     unicode_subchar  = '?';
5691     input_endian = ENDIAN_BIG;
5692 #endif
5693 #ifdef UTF8_OUTPUT_ENABLE
5694     output_bom_f = FALSE;
5695     output_endian = ENDIAN_BIG;
5696 #endif
5697 #ifdef UNICODE_NORMALIZATION
5698     nfc_f = FALSE;
5699 #endif
5700 #ifdef INPUT_OPTION
5701     cap_f = FALSE;
5702     url_f = FALSE;
5703     numchar_f = FALSE;
5704 #endif
5705 #ifdef CHECK_OPTION
5706     noout_f = FALSE;
5707     debug_f = FALSE;
5708 #endif
5709     guess_f = FALSE;
5710     is_inputcode_mixed = FALSE;
5711     is_inputcode_set   = FALSE;
5712 #ifdef EXEC_IO
5713     exec_f = 0;
5714 #endif
5715 #ifdef SHIFTJIS_CP932
5716     cp51932_f = TRUE;
5717     cp932inv_f = TRUE;
5718 #endif
5719 #ifdef X0212_ENABLE
5720     x0212_f = FALSE;
5721     x0213_f = FALSE;
5722 #endif
5723     {
5724         int i;
5725         for (i = 0; i < 256; i++){
5726             prefix_table[i] = 0;
5727         }
5728     }
5729     hold_count = 0;
5730     mimeout_buf_count = 0;
5731     mimeout_mode = 0;
5732     base64_count = 0;
5733     f_line = 0;
5734     f_prev = 0;
5735     fold_preserve_f = FALSE;
5736     fold_f = FALSE;
5737     fold_len = 0;
5738     kanji_intro = DEFAULT_J;
5739     ascii_intro = DEFAULT_R;
5740     fold_margin  = FOLD_MARGIN;
5741     output_conv = DEFAULT_CONV;
5742     oconv = DEFAULT_CONV;
5743     o_zconv = no_connection;
5744     o_fconv = no_connection;
5745     o_crconv = no_connection;
5746     o_rot_conv = no_connection;
5747     o_hira_conv = no_connection;
5748     o_base64conv = no_connection;
5749     o_iso2022jp_check_conv = no_connection;
5750     o_putc = std_putc;
5751     i_getc = std_getc;
5752     i_ungetc = std_ungetc;
5753     i_bgetc = std_getc;
5754     i_bungetc = std_ungetc;
5755     o_mputc = std_putc;
5756     i_mgetc = std_getc;
5757     i_mungetc  = std_ungetc;
5758     i_mgetc_buf = std_getc;
5759     i_mungetc_buf = std_ungetc;
5760     output_mode = ASCII;
5761     input_mode =  ASCII;
5762     shift_mode =  FALSE;
5763     mime_decode_mode = FALSE;
5764     file_out_f = FALSE;
5765     crmode_f = 0;
5766     option_mode = 0;
5767     broken_counter = 0;
5768     broken_last = 0;
5769     z_prev2=0,z_prev1=0;
5770 #ifdef CHECK_OPTION
5771     iconv_for_check = 0;
5772 #endif
5773     input_codename = "";
5774 #ifdef WIN32DLL
5775     reinitdll();
5776 #endif /*WIN32DLL*/
5777 }
5778 #endif
5779
5780 void no_connection(nkf_char c2, nkf_char c1)
5781 {
5782     no_connection2(c2,c1,0);
5783 }
5784
5785 nkf_char no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
5786 {
5787     fprintf(stderr,"nkf internal module connection failure.\n");
5788     exit(1);
5789     return 0; /* LINT */
5790 }
5791
5792 #ifndef PERL_XS
5793 #ifdef WIN32DLL
5794 #define fprintf dllprintf
5795 #endif
5796 void usage(void)
5797 {
5798     fprintf(stderr,"USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
5799     fprintf(stderr,"Flags:\n");
5800     fprintf(stderr,"b,u      Output is buffered (DEFAULT),Output is unbuffered\n");
5801 #ifdef DEFAULT_CODE_SJIS
5802     fprintf(stderr,"j,s,e,w  Output code is JIS 7 bit, Shift_JIS (DEFAULT), EUC-JP, UTF-8N\n");
5803 #endif
5804 #ifdef DEFAULT_CODE_JIS
5805     fprintf(stderr,"j,s,e,w  Output code is JIS 7 bit (DEFAULT), Shift JIS, EUC-JP, UTF-8N\n");
5806 #endif
5807 #ifdef DEFAULT_CODE_EUC
5808     fprintf(stderr,"j,s,e,w  Output code is JIS 7 bit, Shift JIS, EUC-JP (DEFAULT), UTF-8N\n");
5809 #endif
5810 #ifdef DEFAULT_CODE_UTF8
5811     fprintf(stderr,"j,s,e,w  Output code is JIS 7 bit, Shift JIS, EUC-JP, UTF-8N (DEFAULT)\n");
5812 #endif
5813 #ifdef UTF8_OUTPUT_ENABLE
5814     fprintf(stderr,"         After 'w' you can add more options. -w[ 8 [0], 16 [[BL] [0]] ]\n");
5815 #endif
5816     fprintf(stderr,"J,S,E,W  Input assumption is JIS 7 bit , Shift JIS, EUC-JP, UTF-8\n");
5817 #ifdef UTF8_INPUT_ENABLE
5818     fprintf(stderr,"         After 'W' you can add more options. -W[ 8, 16 [BL] ] \n");
5819 #endif
5820     fprintf(stderr,"t        no conversion\n");
5821     fprintf(stderr,"i[@B]    Specify the Esc Seq for JIS X 0208-1978/83 (DEFAULT B)\n");
5822     fprintf(stderr,"o[BJH]   Specify the Esc Seq for ASCII/Roman        (DEFAULT B)\n");
5823     fprintf(stderr,"r        {de/en}crypt ROT13/47\n");
5824     fprintf(stderr,"h        1 katakana->hiragana, 2 hiragana->katakana, 3 both\n");
5825     fprintf(stderr,"v        Show this usage. V: show version\n");
5826     fprintf(stderr,"m[BQN0]  MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
5827     fprintf(stderr,"M[BQ]    MIME encode [B:base64 Q:quoted]\n");
5828     fprintf(stderr,"l        ISO8859-1 (Latin-1) support\n");
5829     fprintf(stderr,"f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
5830     fprintf(stderr,"Z[0-3]   Convert X0208 alphabet to ASCII\n");
5831     fprintf(stderr,"         1: Kankaku to 1 space  2: to 2 spaces  3: Convert to HTML Entity\n");
5832     fprintf(stderr,"X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
5833     fprintf(stderr,"B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
5834 #ifdef MSDOS
5835     fprintf(stderr,"T        Text mode output\n");
5836 #endif
5837     fprintf(stderr,"O        Output to File (DEFAULT 'nkf.out')\n");
5838     fprintf(stderr,"I        Convert non ISO-2022-JP charactor to GETA\n");
5839     fprintf(stderr,"d,c      Convert line breaks  -d: LF  -c: CRLF\n");
5840     fprintf(stderr,"-L[uwm]  line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
5841     fprintf(stderr,"\n");
5842     fprintf(stderr,"Long name options\n");
5843     fprintf(stderr," --ic=<input codeset>  --oc=<output codeset>\n");
5844     fprintf(stderr,"                   Specify the input or output codeset\n");
5845     fprintf(stderr," --fj  --unix --mac  --windows\n");
5846     fprintf(stderr," --jis  --euc  --sjis  --utf8  --utf16  --mime  --base64\n");
5847     fprintf(stderr,"                   Convert for the system or code\n");
5848     fprintf(stderr," --hiragana  --katakana  --katakana-hiragana\n");
5849     fprintf(stderr,"                   To Hiragana/Katakana Conversion\n");
5850     fprintf(stderr," --prefix=         Insert escape before troublesome characters of Shift_JIS\n");
5851 #ifdef INPUT_OPTION
5852     fprintf(stderr," --cap-input, --url-input  Convert hex after ':' or '%%'\n");
5853 #endif
5854 #ifdef NUMCHAR_OPTION
5855     fprintf(stderr," --numchar-input   Convert Unicode Character Reference\n");
5856 #endif
5857 #ifdef UTF8_INPUT_ENABLE
5858     fprintf(stderr," --fb-{skip, html, xml, perl, java, subchar}\n");
5859     fprintf(stderr,"                   Specify how nkf handles unassigned characters\n");
5860 #endif
5861 #ifdef OVERWRITE
5862     fprintf(stderr," --in-place[=SUFFIX]  --overwrite[=SUFFIX]\n");
5863     fprintf(stderr,"                   Overwrite original listed files by filtered result\n");
5864     fprintf(stderr,"                   --overwrite preserves timestamp of original files\n");
5865 #endif
5866     fprintf(stderr," -g  --guess       Guess the input code\n");
5867     fprintf(stderr," --help  --version Show this help/the version\n");
5868     fprintf(stderr,"                   For more information, see also man nkf\n");
5869     fprintf(stderr,"\n");
5870     version();
5871 }
5872
5873 void version(void)
5874 {
5875     fprintf(stderr,"Network Kanji Filter Version %s (%s) "
5876 #if defined(MSDOS) && !defined(__WIN32__) && !defined(__WIN16__) && !defined(__OS2__)
5877                   "for DOS"
5878 #endif
5879 #if defined(MSDOS) && defined(__WIN16__)
5880                   "for Win16"
5881 #endif
5882 #if defined(MSDOS) && defined(__WIN32__)
5883                   "for Win32"
5884 #endif
5885 #ifdef __OS2__
5886                   "for OS/2"
5887 #endif
5888                   ,NKF_VERSION,NKF_RELEASE_DATE);
5889     fprintf(stderr,"\n%s\n",CopyRight);
5890 }
5891 #endif /*PERL_XS*/
5892
5893 /**
5894  ** \e$B%Q%C%A@):n<T\e(B
5895  **  void@merope.pleiades.or.jp (Kusakabe Youichi)
5896  **  NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
5897  **  ohta@src.ricoh.co.jp (Junn Ohta)
5898  **  inouet@strl.nhk.or.jp (Tomoyuki Inoue)
5899  **  kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
5900  **  Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
5901  **  a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
5902  **  kono@ie.u-ryukyu.ac.jp (Shinji Kono)
5903  **  GHG00637@nifty-serve.or.jp (COW)
5904  **
5905  **/
5906
5907 /* end */