OSDN Git Service

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