OSDN Git Service

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