OSDN Git Service

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