OSDN Git Service

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