OSDN Git Service

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