OSDN Git Service

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