OSDN Git Service

* new long option: --fb-{skip, html, xml, perl, java, subchar}
[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.80 2005/11/06 20:11:27 naruse Exp $ */
43 #define NKF_VERSION "2.0.5"
44 #define NKF_RELEASE_DATE "2005-11-07"
45 #include "config.h"
46
47 #define COPY_RIGHT \
48     "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW, 2002-2005 Kono, Furukawa, Naruse"
49
50
51 /*
52 **
53 **
54 **
55 ** USAGE:       nkf [flags] [file] 
56 **
57 ** Flags:
58 ** b    Output is buffered             (DEFAULT)
59 ** u    Output is unbuffered
60 **
61 ** t    no operation
62 **
63 ** j    Outout code is JIS 7 bit        (DEFAULT SELECT) 
64 ** s    Output code is MS Kanji         (DEFAULT SELECT) 
65 ** e    Output code is AT&T JIS         (DEFAULT SELECT) 
66 ** w    Output code is AT&T JIS         (DEFAULT SELECT) 
67 ** l    Output code is JIS 7bit and ISO8859-1 Latin-1
68 **
69 ** m    MIME conversion for ISO-2022-JP
70 ** I    Convert non ISO-2022-JP charactor to GETA by Pekoe <pekoe@lair.net>
71 ** i_ Output sequence to designate JIS-kanji (DEFAULT_J)
72 ** o_ Output sequence to designate single-byte roman characters (DEFAULT_R)
73 ** M    MIME output conversion 
74 **
75 ** r  {de/en}crypt ROT13/47
76 **
77 ** v  display Version
78 **
79 ** T  Text mode output        (for MS-DOS)
80 **
81 ** x    Do not convert X0201 kana into X0208
82 ** Z    Convert X0208 alphabet to ASCII
83 **
84 ** f60  fold option
85 **
86 ** m    MIME decode
87 ** B    try to fix broken JIS, missing Escape
88 ** B[1-9]  broken level
89 **
90 ** O   Output to 'nkf.out' file or last file name
91 ** d   Delete \r in line feed 
92 ** c   Add \r in line feed 
93 ** -- other long option
94 ** -- ignore following option (don't use with -O )
95 **
96 **/
97
98 #if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || defined(__MINGW32__)) && !defined(MSDOS)
99 #define MSDOS
100 #if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
101 #define __WIN32__
102 #endif
103 #endif
104
105 #ifdef PERL_XS
106 #undef OVERWRITE
107 #endif
108
109 #ifndef PERL_XS
110 #include <stdio.h>
111 #endif
112
113 #include <stdlib.h>
114 #include <string.h>
115
116 #if defined(MSDOS) || defined(__OS2__) 
117 #include <fcntl.h>
118 #include <io.h>
119 #endif
120
121 #ifdef MSDOS
122 #ifdef LSI_C
123 #define setbinmode(fp) fsetbin(fp)
124 #else /* Microsoft C, Turbo C */
125 #define setbinmode(fp) setmode(fileno(fp), O_BINARY)
126 #endif
127 #else /* UNIX,OS/2 */
128 #define setbinmode(fp)
129 #endif
130
131 #ifdef _IOFBF /* SysV and MSDOS, Windows */
132 #define       setvbuffer(fp, buf, size)       setvbuf(fp, buf, _IOFBF, size)
133 #else /* BSD */
134 #define       setvbuffer(fp, buf, size)       setbuffer(fp, buf, size)
135 #endif
136
137 /*Borland C++ 4.5 EasyWin*/
138 #if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
139 #define         EASYWIN
140 #ifndef __WIN16__
141 #define __WIN16__
142 #endif
143 #include <windows.h>
144 #endif
145
146 #ifdef OVERWRITE
147 /* added by satoru@isoternet.org */
148 #include <sys/stat.h>
149 #ifndef MSDOS /* UNIX, OS/2 */
150 #include <unistd.h>
151 #include <utime.h>
152 #else /* defined(MSDOS) */
153 #ifdef __WIN32__
154 #ifdef __BORLANDC__ /* BCC32 */
155 #include <utime.h>
156 #else /* !defined(__BORLANDC__) */
157 #include <sys/utime.h>
158 #endif /* (__BORLANDC__) */
159 #else /* !defined(__WIN32__) */
160 #if defined(_MSC_VER) || defined(__MINGW32__) /* VC++, MinGW */
161 #include <sys/utime.h>
162 #elif defined(__TURBOC__) /* BCC */
163 #include <utime.h>
164 #elif defined(LSI_C) /* LSI C */
165 #endif /* (__WIN32__) */
166 #endif
167 #endif
168 #endif 
169
170 #ifdef INT_IS_SHORT
171 #define int long
172 #endif
173
174 #define         FALSE   0
175 #define         TRUE    1
176
177 /* state of output_mode and input_mode  
178
179    c2           0 means ASCII
180                 X0201
181                 ISO8859_1
182                 X0208
183                 EOF      all termination
184    c1           32bit data
185
186  */
187
188 #define         ASCII           0
189 #define         X0208           1
190 #define         X0201           2
191 #define         ISO8859_1       8
192 #define         NO_X0201        3
193 #define         X0212           16
194
195 /* Input Assumption */
196
197 #define         JIS_INPUT       4
198 #define         SJIS_INPUT      5
199 #define         LATIN1_INPUT    6
200 #define         FIXED_MIME      7
201 #define         STRICT_MIME     8
202
203 /* MIME ENCODE */
204
205 #define         ISO2022JP       9
206 #define         JAPANESE_EUC   10
207 #define         SHIFT_JIS      11
208
209 #define         UTF8           12
210 #define         UTF8_INPUT     13
211 #define         UTF16BE_INPUT  14
212 #define         UTF16LE_INPUT  15
213
214 #define         WISH_TRUE      15
215
216 /* ASCII CODE */
217
218 #define         BS      0x08
219 #define         TAB     0x09
220 #define         NL      0x0a
221 #define         CR      0x0d
222 #define         ESC     0x1b
223 #define         SPACE   0x20
224 #define         AT      0x40
225 #define         SSP     0xa0
226 #define         DEL     0x7f
227 #define         SI      0x0f
228 #define         SO      0x0e
229 #define         SSO     0x8e
230 #define         SS3     0x8f
231
232 #define         is_alnum(c)  \
233             (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
234
235 /* I don't trust portablity of toupper */
236 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
237 #define nkf_isoctal(c)  ('0'<=c && c<='7')
238 #define nkf_isdigit(c)  ('0'<=c && c<='9')
239 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
240 #define nkf_isblank(c) (c == SPACE || c == TAB)
241 #define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == NL)
242 #define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
243 #define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c))
244 #define hex2bin(x)     ( nkf_isdigit(x) ? x - '0' : nkf_toupper(x) - 'A' + 10)
245
246 #define         HOLD_SIZE       1024
247 #define         IOBUF_SIZE      16384
248
249 #define         DEFAULT_J       'B'
250 #define         DEFAULT_R       'B'
251
252 #define         SJ0162  0x00e1          /* 01 - 62 ku offset */
253 #define         SJ6394  0x0161          /* 63 - 94 ku offset */
254
255 #define         RANGE_NUM_MAX   18
256 #define         GETA1   0x22
257 #define         GETA2   0x2e
258
259
260 #if defined(UTF8_OUTPUT_ENABLE) || defined(UTF8_INPUT_ENABLE)
261 #define sizeof_euc_utf8 94
262 #define sizeof_euc_to_utf8_1byte 94
263 #define sizeof_euc_to_utf8_2bytes 94
264 #define sizeof_utf8_to_euc_C2 64
265 #define sizeof_utf8_to_euc_E5B8 64
266 #define sizeof_utf8_to_euc_2bytes 112
267 #define sizeof_utf8_to_euc_3bytes 112
268 #endif
269
270 /* MIME preprocessor */
271
272 #ifdef EASYWIN /*Easy Win */
273 extern POINT _BufferSize;
274 #endif
275
276 /*      function prototype  */
277
278 #ifdef ANSI_C_PROTOTYPE
279 #define PROTO(x)  x 
280 #define STATIC static
281 #define CONST const
282 #else
283 #define PROTO(x)  ()
284 #define STATIC
285 #define CONST
286 #endif
287
288 struct input_code{
289     char *name;
290     int stat;
291     int score;
292     int index;
293     int buf[3];
294     void (*status_func)PROTO((struct input_code *, int));
295     int (*iconv_func)PROTO((int c2, int c1, int c0));
296     int _file_stat;
297 };
298
299 STATIC char *input_codename = "";
300
301 #ifndef PERL_XS
302 STATIC const char *CopyRight = COPY_RIGHT;
303 #endif
304 #if !defined(PERL_XS) && !defined(WIN32DLL)
305 STATIC  int     noconvert PROTO((FILE *f));
306 #endif
307 STATIC  int     kanji_convert PROTO((FILE *f));
308 STATIC  int     h_conv PROTO((FILE *f,int c2,int c1));
309 STATIC  int     push_hold_buf PROTO((int c2));
310 STATIC  void    set_iconv PROTO((int f, int (*iconv_func)(int c2,int c1,int c0)));
311 STATIC  int     s_iconv PROTO((int c2,int c1,int c0));
312 STATIC  int     s2e_conv PROTO((int c2, int c1, int *p2, int *p1));
313 STATIC  int     e_iconv PROTO((int c2,int c1,int c0));
314 #ifdef UTF8_INPUT_ENABLE
315 STATIC  void    encode_fallback_html PROTO((int c));
316 STATIC  void    encode_fallback_xml PROTO((int c));
317 STATIC  void    encode_fallback_java PROTO((int c));
318 STATIC  void    encode_fallback_perl PROTO((int c));
319 STATIC  void    encode_fallback_subchar PROTO((int c));
320 STATIC  void    (*encode_fallback)PROTO((int c)) = NULL;
321 STATIC  int     w2e_conv PROTO((int c2,int c1,int c0,int *p2,int *p1));
322 STATIC  int     w_iconv PROTO((int c2,int c1,int c0));
323 STATIC  int     w_iconv16 PROTO((int c2,int c1,int c0));
324 STATIC  int     w_iconv_common PROTO((int c1,int c0,const unsigned short *const *pp,int psize,int *p2,int *p1));
325 STATIC  int     ww16_conv PROTO((int c2, int c1, int c0));
326 STATIC  int     w16e_conv PROTO((unsigned short val,int *p2,int *p1));
327 #endif
328 #ifdef UTF8_OUTPUT_ENABLE
329 STATIC  int     e2w_conv PROTO((int c2,int c1));
330 STATIC  void    w_oconv PROTO((int c2,int c1));
331 STATIC  void    w_oconv16 PROTO((int c2,int c1));
332 #endif
333 STATIC  void    e_oconv PROTO((int c2,int c1));
334 STATIC  int     e2s_conv PROTO((int c2, int c1, int *p2, int *p1));
335 STATIC  void    s_oconv PROTO((int c2,int c1));
336 STATIC  void    j_oconv PROTO((int c2,int c1));
337 STATIC  void    fold_conv PROTO((int c2,int c1));
338 STATIC  void    cr_conv PROTO((int c2,int c1));
339 STATIC  void    z_conv PROTO((int c2,int c1));
340 STATIC  void    rot_conv PROTO((int c2,int c1));
341 STATIC  void    hira_conv PROTO((int c2,int c1));
342 STATIC  void    base64_conv PROTO((int c2,int c1));
343 STATIC  void    iso2022jp_check_conv PROTO((int c2,int c1));
344 STATIC  void    no_connection PROTO((int c2,int c1));
345 STATIC  int     no_connection2 PROTO((int c2,int c1,int c0));
346
347 STATIC  void    code_score PROTO((struct input_code *ptr));
348 STATIC  void    code_status PROTO((int c));
349
350 STATIC  void    std_putc PROTO((int c));
351 STATIC  int     std_getc PROTO((FILE *f));
352 STATIC  int     std_ungetc PROTO((int c,FILE *f));
353
354 STATIC  int     broken_getc PROTO((FILE *f));
355 STATIC  int     broken_ungetc PROTO((int c,FILE *f));
356
357 STATIC  int     mime_begin PROTO((FILE *f));
358 STATIC  int     mime_getc PROTO((FILE *f));
359 STATIC  int     mime_ungetc PROTO((int c,FILE *f));
360
361 STATIC  int     mime_begin_strict PROTO((FILE *f));
362 STATIC  int     mime_getc_buf PROTO((FILE *f));
363 STATIC  int     mime_ungetc_buf  PROTO((int c,FILE *f));
364 STATIC  int     mime_integrity PROTO((FILE *f,const unsigned char *p));
365
366 STATIC  int     base64decode PROTO((int c));
367 STATIC  void    mime_prechar PROTO((int c2, int c1));
368 STATIC  void    mime_putc PROTO((int c));
369 STATIC  void    open_mime PROTO((int c));
370 STATIC  void    close_mime PROTO(());
371 #ifndef PERL_XS
372 STATIC  void    usage PROTO(());
373 STATIC  void    version PROTO(());
374 #endif
375 STATIC  void    options PROTO((unsigned char *c));
376 #if defined(PERL_XS) || defined(WIN32DLL)
377 STATIC  void    reinit PROTO(());
378 #endif
379
380 /* buffers */
381
382 #if !defined(PERL_XS) && !defined(WIN32DLL)
383 STATIC unsigned char   stdibuf[IOBUF_SIZE];
384 STATIC unsigned char   stdobuf[IOBUF_SIZE];
385 #endif
386 STATIC unsigned char   hold_buf[HOLD_SIZE*2];
387 STATIC int             hold_count;
388
389 /* MIME preprocessor fifo */
390
391 #define MIME_BUF_SIZE   (1024)    /* 2^n ring buffer */
392 #define MIME_BUF_MASK   (MIME_BUF_SIZE-1)   
393 #define Fifo(n)         mime_buf[(n)&MIME_BUF_MASK]
394 STATIC unsigned char           mime_buf[MIME_BUF_SIZE];
395 STATIC unsigned int            mime_top = 0;
396 STATIC unsigned int            mime_last = 0;  /* decoded */
397 STATIC unsigned int            mime_input = 0; /* undecoded */
398 STATIC int (*mime_iconv_back)PROTO((int c2,int c1,int c0)) = NULL;
399
400 /* flags */
401 STATIC int             unbuf_f = FALSE;
402 STATIC int             estab_f = FALSE;
403 STATIC int             nop_f = FALSE;
404 STATIC int             binmode_f = TRUE;       /* binary mode */
405 STATIC int             rot_f = FALSE;          /* rot14/43 mode */
406 STATIC int             hira_f = FALSE;          /* hira/kata henkan */
407 STATIC int             input_f = FALSE;        /* non fixed input code  */
408 STATIC int             alpha_f = FALSE;        /* convert JIx0208 alphbet to ASCII */
409 STATIC int             mime_f = STRICT_MIME;   /* convert MIME B base64 or Q */
410 STATIC int             mime_decode_f = FALSE;  /* mime decode is explicitly on */
411 STATIC int             mimebuf_f = FALSE;      /* MIME buffered input */
412 STATIC int             broken_f = FALSE;       /* convert ESC-less broken JIS */
413 STATIC int             iso8859_f = FALSE;      /* ISO8859 through */
414 STATIC int             mimeout_f = FALSE;       /* base64 mode */
415 #if defined(MSDOS) || defined(__OS2__) 
416 STATIC int             x0201_f = TRUE;         /* Assume JISX0201 kana */
417 #else
418 STATIC int             x0201_f = NO_X0201;     /* Assume NO JISX0201 */
419 #endif
420 STATIC int             iso2022jp_f = FALSE;    /* convert ISO-2022-JP */
421 #if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
422 STATIC int             internal_unicode_f = FALSE;   /* Internal Unicode Processing */
423 #endif
424 #ifdef UTF8_OUTPUT_ENABLE
425 STATIC int             unicode_bom_f= 0;   /* Output Unicode BOM */
426 STATIC int             w_oconv16_LE = 0;   /* utf-16 little endian */
427 STATIC int             ms_ucs_map_f = FALSE;   /* Microsoft UCS Mapping Compatible */
428 STATIC int             unicode_subchar = '?'; /* the regular substitution character */
429 #endif
430
431 #ifdef UNICODE_NORMALIZATION
432 STATIC int nfc_f = FALSE;
433 STATIC int (*i_nfc_getc)PROTO((FILE *)) = std_getc; /* input of ugetc */
434 STATIC int (*i_nfc_ungetc)PROTO((int c ,FILE *f)) = std_ungetc;
435 STATIC int nfc_getc PROTO((FILE *f));
436 STATIC int nfc_ungetc PROTO((int c,FILE *f));
437 #endif
438
439 #ifdef INPUT_OPTION
440 STATIC int cap_f = FALSE;
441 STATIC int (*i_cgetc)PROTO((FILE *)) = std_getc; /* input of cgetc */
442 STATIC int (*i_cungetc)PROTO((int c ,FILE *f)) = std_ungetc;
443 STATIC int cap_getc PROTO((FILE *f));
444 STATIC int cap_ungetc PROTO((int c,FILE *f));
445
446 STATIC int url_f = FALSE;
447 STATIC int (*i_ugetc)PROTO((FILE *)) = std_getc; /* input of ugetc */
448 STATIC int (*i_uungetc)PROTO((int c ,FILE *f)) = std_ungetc;
449 STATIC int url_getc PROTO((FILE *f));
450 STATIC int url_ungetc PROTO((int c,FILE *f));
451 #endif
452
453 #ifdef NUMCHAR_OPTION
454 #define CLASS_MASK  0x0f000000
455 #define CLASS_UTF16 0x01000000
456 STATIC int numchar_f = FALSE;
457 STATIC int (*i_ngetc)PROTO((FILE *)) = std_getc; /* input of ugetc */
458 STATIC int (*i_nungetc)PROTO((int c ,FILE *f)) = std_ungetc;
459 STATIC int numchar_getc PROTO((FILE *f));
460 STATIC int numchar_ungetc PROTO((int c,FILE *f));
461 #endif
462
463 #ifdef CHECK_OPTION
464 STATIC int noout_f = FALSE;
465 STATIC void no_putc PROTO((int c));
466 STATIC int debug_f = FALSE;
467 STATIC void debug PROTO((const char *str));
468 STATIC int (*iconv_for_check)() = 0;
469 #endif
470
471 STATIC int guess_f = FALSE;
472 #if !defined PERL_XS
473 STATIC  void    print_guessed_code PROTO((char *filename));
474 #endif
475 STATIC  void    set_input_codename PROTO((char *codename));
476 STATIC int is_inputcode_mixed = FALSE;
477 STATIC int is_inputcode_set   = FALSE;
478
479 #ifdef EXEC_IO
480 STATIC int exec_f = 0;
481 #endif
482
483 #ifdef SHIFTJIS_CP932
484 /* invert IBM extended characters to others and controls some UCS mapping */
485 STATIC int cp51932_f = TRUE;
486 #define CP932_TABLE_BEGIN (0xfa)
487 #define CP932_TABLE_END   (0xfc)
488
489 /* invert NEC-selected IBM extended characters to IBM extended characters */
490 STATIC int cp932inv_f = TRUE;
491 #define CP932INV_TABLE_BEGIN (0xed)
492 #define CP932INV_TABLE_END   (0xee)
493
494 /* STATIC int cp932_conv PROTO((int c2, int c1)); */
495 #endif /* SHIFTJIS_CP932 */
496
497 #ifdef X0212_ENABLE
498 STATIC int x0212_f = FALSE;
499 STATIC int x0212_shift PROTO((int c));
500 STATIC int x0212_unshift PROTO((int c));
501 #endif
502
503 STATIC unsigned char prefix_table[256];
504
505 STATIC void e_status PROTO((struct input_code *, int));
506 STATIC void s_status PROTO((struct input_code *, int));
507
508 #ifdef UTF8_INPUT_ENABLE
509 STATIC void w_status PROTO((struct input_code *, int));
510 STATIC void w16_status PROTO((struct input_code *, int));
511 STATIC int             utf16_mode = UTF16BE_INPUT;
512 #endif
513
514 struct input_code input_code_list[] = {
515     {"EUC-JP",    0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
516     {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
517 #ifdef UTF8_INPUT_ENABLE
518     {"UTF-8",     0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
519     {"UTF-16",    0, 0, 0, {0, 0, 0}, w16_status, w_iconv16, 0},
520 #endif
521     {0}
522 };
523
524 STATIC int              mimeout_mode = 0;
525 STATIC int              base64_count = 0;
526
527 /* X0208 -> ASCII converter */
528
529 /* fold parameter */
530 STATIC int             f_line = 0;    /* chars in line */
531 STATIC int             f_prev = 0;
532 STATIC int             fold_preserve_f = FALSE; /* preserve new lines */
533 STATIC int             fold_f  = FALSE;
534 STATIC int             fold_len  = 0;
535
536 /* options */
537 STATIC unsigned char   kanji_intro = DEFAULT_J;
538 STATIC unsigned char   ascii_intro = DEFAULT_R;
539
540 /* Folding */
541
542 #define FOLD_MARGIN  10
543 #define DEFAULT_FOLD 60
544
545 STATIC int             fold_margin  = FOLD_MARGIN;
546
547 /* converters */
548
549 #ifdef DEFAULT_CODE_JIS
550 #   define  DEFAULT_CONV j_oconv
551 #endif
552 #ifdef DEFAULT_CODE_SJIS
553 #   define  DEFAULT_CONV s_oconv
554 #endif
555 #ifdef DEFAULT_CODE_EUC
556 #   define  DEFAULT_CONV e_oconv
557 #endif
558 #ifdef DEFAULT_CODE_UTF8
559 #   define  DEFAULT_CONV w_oconv
560 #endif
561
562 /* process default */
563 STATIC void (*output_conv)PROTO((int c2,int c1)) = DEFAULT_CONV;   
564
565 STATIC void (*oconv)PROTO((int c2,int c1)) = no_connection; 
566 /* s_iconv or oconv */
567 STATIC int (*iconv)PROTO((int c2,int c1,int c0)) = no_connection2;   
568
569 STATIC void (*o_zconv)PROTO((int c2,int c1)) = no_connection; 
570 STATIC void (*o_fconv)PROTO((int c2,int c1)) = no_connection; 
571 STATIC void (*o_crconv)PROTO((int c2,int c1)) = no_connection; 
572 STATIC void (*o_rot_conv)PROTO((int c2,int c1)) = no_connection; 
573 STATIC void (*o_hira_conv)PROTO((int c2,int c1)) = no_connection; 
574 STATIC void (*o_base64conv)PROTO((int c2,int c1)) = no_connection;
575 STATIC void (*o_iso2022jp_check_conv)PROTO((int c2,int c1)) = no_connection;
576
577 /* STATIC redirections */
578
579 STATIC  void   (*o_putc)PROTO((int c)) = std_putc;
580
581 STATIC  int    (*i_getc)PROTO((FILE *f)) = std_getc; /* general input */
582 STATIC  int    (*i_ungetc)PROTO((int c,FILE *f)) =std_ungetc;
583
584 STATIC  int    (*i_bgetc)PROTO((FILE *)) = std_getc; /* input of mgetc */
585 STATIC  int    (*i_bungetc)PROTO((int c ,FILE *f)) = std_ungetc;
586
587 STATIC  void   (*o_mputc)PROTO((int c)) = std_putc ; /* output of mputc */
588
589 STATIC  int    (*i_mgetc)PROTO((FILE *)) = std_getc; /* input of mgetc */
590 STATIC  int    (*i_mungetc)PROTO((int c ,FILE *f)) = std_ungetc;
591
592 /* for strict mime */
593 STATIC  int    (*i_mgetc_buf)PROTO((FILE *)) = std_getc; /* input of mgetc_buf */
594 STATIC  int    (*i_mungetc_buf)PROTO((int c,FILE *f)) = std_ungetc;
595
596 /* Global states */
597 STATIC int output_mode = ASCII,    /* output kanji mode */
598            input_mode =  ASCII,    /* input kanji mode */
599            shift_mode =  FALSE;    /* TRUE shift out, or X0201  */
600 STATIC int mime_decode_mode =   FALSE;    /* MIME mode B base64, Q hex */
601
602 /* X0201 / X0208 conversion tables */
603
604 /* X0201 kana conversion table */
605 /* 90-9F A0-DF */
606 STATIC const
607 unsigned char cv[]= {
608     0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
609     0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
610     0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
611     0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
612     0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
613     0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
614     0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
615     0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
616     0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
617     0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
618     0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
619     0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
620     0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
621     0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
622     0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
623     0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
624     0x00,0x00};
625
626
627 /* X0201 kana conversion table for daguten */
628 /* 90-9F A0-DF */
629 STATIC const
630 unsigned char dv[]= { 
631     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
632     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
633     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
634     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
635     0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74,
636     0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
637     0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
638     0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
639     0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
640     0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
641     0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
642     0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
643     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
644     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
645     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
646     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
647     0x00,0x00};
648
649 /* X0201 kana conversion table for han-daguten */
650 /* 90-9F A0-DF */
651 STATIC const
652 unsigned char ev[]= { 
653     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
654     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
655     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
656     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
657     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
658     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
659     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
660     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
661     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
662     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
663     0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
664     0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
665     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
666     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
667     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
668     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
669     0x00,0x00};
670
671
672 /* X0208 kigou conversion table */
673 /* 0x8140 - 0x819e */
674 STATIC const
675 unsigned char fv[] = {
676
677     0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
678     0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
679     0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
680     0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
681     0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
682     0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
683     0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
684     0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
685     0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
686     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
687     0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
688     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
689 } ;
690
691
692 #define    CRLF      1
693
694 STATIC int             file_out = FALSE;
695 #ifdef OVERWRITE
696 STATIC int             overwrite = FALSE;
697 #endif
698
699 STATIC int             crmode_f = 0;   /* CR, NL, CRLF */
700 #ifdef EASYWIN /*Easy Win */
701 STATIC int             end_check;
702 #endif /*Easy Win */
703
704 #define STD_GC_BUFSIZE (256)
705 int std_gc_buf[STD_GC_BUFSIZE];
706 int std_gc_ndx;
707
708 #ifdef WIN32DLL
709 #include "nkf32dll.c"
710 #elif defined(PERL_XS)
711 #else /* WIN32DLL */
712 int
713 main(argc, argv)
714     int             argc;
715     char          **argv;
716 {
717     FILE  *fin;
718     unsigned char  *cp;
719
720     char *outfname = NULL;
721     char *origfname;
722
723 #ifdef EASYWIN /*Easy Win */
724     _BufferSize.y = 400;/*Set Scroll Buffer Size*/
725 #endif
726
727     for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
728         cp = (unsigned char *)*argv;
729         options(cp);
730 #ifdef EXEC_IO
731         if (exec_f){
732             int fds[2], pid;
733             if (pipe(fds) < 0 || (pid = fork()) < 0){
734                 abort();
735             }
736             if (pid == 0){
737                 if (exec_f > 0){
738                     close(fds[0]);
739                     dup2(fds[1], 1);
740                 }else{
741                     close(fds[1]);
742                     dup2(fds[0], 0);
743                 }
744                 execvp(argv[1], &argv[1]);
745             }
746             if (exec_f > 0){
747                 close(fds[1]);
748                 dup2(fds[0], 0);
749             }else{
750                 close(fds[0]);
751                 dup2(fds[1], 1);
752             }
753             argc = 0;
754             break;
755         }
756 #endif
757     }
758     if(x0201_f == WISH_TRUE)
759          x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
760
761     if (binmode_f == TRUE)
762 #ifdef __OS2__
763     if (freopen("","wb",stdout) == NULL) 
764         return (-1);
765 #else
766     setbinmode(stdout);
767 #endif
768
769     if (unbuf_f)
770       setbuf(stdout, (char *) NULL);
771     else
772       setvbuffer(stdout, stdobuf, IOBUF_SIZE);
773
774     if (argc == 0) {
775       if (binmode_f == TRUE)
776 #ifdef __OS2__
777       if (freopen("","rb",stdin) == NULL) return (-1);
778 #else
779       setbinmode(stdin);
780 #endif
781       setvbuffer(stdin, stdibuf, IOBUF_SIZE);
782       if (nop_f)
783           noconvert(stdin);
784       else {
785           kanji_convert(stdin);
786           if (guess_f) print_guessed_code(NULL);
787       }
788     } else {
789       int nfiles = argc;
790       while (argc--) {
791             is_inputcode_mixed = FALSE;
792             is_inputcode_set   = FALSE;
793             input_codename = "";
794 #ifdef CHECK_OPTION
795             iconv_for_check = 0;
796 #endif
797           if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
798               perror(*--argv);
799               return(-1);
800           } else {
801 #ifdef OVERWRITE
802               int fd = 0;
803               int fd_backup = 0;
804 #endif
805
806 /* reopen file for stdout */
807               if (file_out == TRUE) {
808 #ifdef OVERWRITE
809                   if (overwrite){
810                       outfname = malloc(strlen(origfname)
811                                         + strlen(".nkftmpXXXXXX")
812                                         + 1);
813                       if (!outfname){
814                           perror(origfname);
815                           return -1;
816                       }
817                       strcpy(outfname, origfname);
818 #ifdef MSDOS
819                       {
820                           int i;
821                           for (i = strlen(outfname); i; --i){
822                               if (outfname[i - 1] == '/'
823                                   || outfname[i - 1] == '\\'){
824                                   break;
825                               }
826                           }
827                           outfname[i] = '\0';
828                       }
829                       strcat(outfname, "ntXXXXXX");
830                       mktemp(outfname);
831                       fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC,
832                                 S_IREAD | S_IWRITE);
833 #else
834                       strcat(outfname, ".nkftmpXXXXXX");
835                       fd = mkstemp(outfname);
836 #endif
837                       if (fd < 0
838                           || (fd_backup = dup(fileno(stdout))) < 0
839                           || dup2(fd, fileno(stdout)) < 0
840                           ){
841                           perror(origfname);
842                           return -1;
843                       }
844                   }else
845 #endif
846                   if(argc == 1 ) {
847                       outfname = *argv++;
848                       argc--;
849                   } else {
850                       outfname = "nkf.out";
851                   }
852
853                   if(freopen(outfname, "w", stdout) == NULL) {
854                       perror (outfname);
855                       return (-1);
856                   }
857                   if (binmode_f == TRUE) {
858 #ifdef __OS2__
859                       if (freopen("","wb",stdout) == NULL) 
860                            return (-1);
861 #else
862                       setbinmode(stdout);
863 #endif
864                   }
865               }
866               if (binmode_f == TRUE)
867 #ifdef __OS2__
868                  if (freopen("","rb",fin) == NULL) 
869                     return (-1);
870 #else
871                  setbinmode(fin);
872 #endif 
873               setvbuffer(fin, stdibuf, IOBUF_SIZE);
874               if (nop_f)
875                   noconvert(fin);
876               else {
877                   char *filename = NULL;
878                   kanji_convert(fin);
879                   if (nfiles > 1) filename = origfname;
880                   if (guess_f) print_guessed_code(filename);
881               }
882               fclose(fin);
883 #ifdef OVERWRITE
884               if (overwrite) {
885                   struct stat     sb;
886 #if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__)
887                   time_t tb[2];
888 #else
889                   struct utimbuf  tb;
890 #endif
891
892                   fflush(stdout);
893                   close(fd);
894                   if (dup2(fd_backup, fileno(stdout)) < 0){
895                       perror("dup2");
896                   }
897                   if (stat(origfname, &sb)) {
898                       fprintf(stderr, "Can't stat %s\n", origfname);
899                   }
900                   /* \e$B%Q!<%_%C%7%g%s$rI|85\e(B */
901                   if (chmod(outfname, sb.st_mode)) {
902                       fprintf(stderr, "Can't set permission %s\n", outfname);
903                   }
904
905                   /* \e$B%?%$%`%9%?%s%W$rI|85\e(B */
906 #if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__)
907                   tb[0] = tb[1] = sb.st_mtime;
908                   if (utime(outfname, tb)) {
909                       fprintf(stderr, "Can't set timestamp %s\n", outfname);
910                   }
911 #else
912                   tb.actime  = sb.st_atime;
913                   tb.modtime = sb.st_mtime;
914                   if (utime(outfname, &tb)) {
915                       fprintf(stderr, "Can't set timestamp %s\n", outfname);
916                   }
917 #endif
918 #ifdef MSDOS
919                   if (unlink(origfname)){
920                       perror(origfname);
921                   }
922 #endif
923                   if (rename(outfname, origfname)) {
924                       perror(origfname);
925                       fprintf(stderr, "Can't rename %s to %s\n",
926                               outfname, origfname);
927                   }
928                   free(outfname);
929               }
930 #endif
931           }
932       }
933     }
934 #ifdef EASYWIN /*Easy Win */
935     if (file_out == FALSE) 
936         scanf("%d",&end_check);
937     else 
938         fclose(stdout);
939 #else /* for Other OS */
940     if (file_out == TRUE) 
941         fclose(stdout);
942 #endif /*Easy Win */
943     return (0);
944 }
945 #endif /* WIN32DLL */
946
947 STATIC const
948 struct {
949     const char *name;
950     const char *alias;
951 } long_option[] = {
952     {"base64","jMB"},
953     {"euc","e"},
954     {"euc-input","E"},
955     {"fj","jm"},
956     {"help","v"},
957     {"jis","j"},
958     {"jis-input","J"},
959     {"mac","sLm"},
960     {"mime","jM"},
961     {"mime-input","m"},
962     {"msdos","sLw"},
963     {"sjis","s"},
964     {"sjis-input","S"},
965     {"unix","eLu"},
966     {"version","V"},
967     {"windows","sLw"},
968     {"hiragana","h1"},
969     {"katakana","h2"},
970     {"katakana-hiragana","h3"},
971     {"guess", "g"},
972     {"cp932", ""},
973     {"no-cp932", ""},
974 #ifdef X0212_ENABLE
975     {"x0212", ""},
976 #endif
977 #if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
978     {"internal-unicode", ""},
979 #endif
980 #ifdef UTF8_OUTPUT_ENABLE
981     {"utf8", "w"},
982     {"utf16", "w16"},
983     {"ms-ucs-map", ""},
984     {"fb-skip", ""},
985     {"fb-html", ""},
986     {"fb-xml", ""},
987     {"fb-perl", ""},
988     {"fb-java", ""},
989     {"fb-subchar", ""},
990     {"fb-subchar=", ""},
991 #endif
992 #ifdef UTF8_INPUT_ENABLE
993     {"utf8-input", "W"},
994     {"utf16-input", "W16"},
995 #endif
996 #ifdef UNICODE_NORMALIZATION
997     {"utf8mac-input", ""},
998 #endif
999 #ifdef OVERWRITE
1000     {"overwrite", ""},
1001 #endif
1002 #ifdef INPUT_OPTION
1003     {"cap-input", ""},
1004     {"url-input", ""},
1005 #endif
1006 #ifdef NUMCHAR_OPTION
1007     {"numchar-input", ""},
1008 #endif
1009 #ifdef CHECK_OPTION
1010     {"no-output", ""},
1011     {"debug", ""},
1012 #endif
1013 #ifdef SHIFTJIS_CP932
1014     {"cp932inv", ""},
1015 #endif
1016 #ifdef EXEC_IO
1017     {"exec-in", ""},
1018     {"exec-out", ""},
1019 #endif
1020     {"prefix=", ""},
1021 };
1022
1023 STATIC int option_mode = 0;
1024
1025 void
1026 options(cp) 
1027      unsigned char *cp;
1028 {
1029     int i, j;
1030     unsigned char *p = NULL;
1031     unsigned char *cp_back = NULL;
1032
1033     if (option_mode==1)
1034         return;
1035     while(*cp && *cp++!='-');
1036     while (*cp || cp_back) {
1037         if(!*cp){
1038             cp = cp_back;
1039             cp_back = NULL;
1040             continue;
1041         }
1042         p = 0;
1043         switch (*cp++) {
1044         case '-':  /* literal options */
1045             if (!*cp || *cp == SPACE) {        /* ignore the rest of arguments */
1046                 option_mode = 1;
1047                 return;
1048             }
1049             for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
1050                 p = (unsigned char *)long_option[i].name;
1051                 for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
1052                 if (*p == cp[j] || cp[j] == ' '){
1053                     p = &cp[j] + 1;
1054                     break;
1055                 }
1056                 p = 0;
1057             }
1058             if (p == 0) return;
1059             while(*cp && *cp != SPACE && cp++);
1060             if (long_option[i].alias[0]){
1061                 cp_back = cp;
1062                 cp = (unsigned char *)long_option[i].alias;
1063             }else{
1064 #ifdef OVERWRITE
1065                 if (strcmp(long_option[i].name, "overwrite") == 0){
1066                     file_out = TRUE;
1067                     overwrite = TRUE;
1068                     continue;
1069                 }
1070 #endif
1071 #ifdef INPUT_OPTION
1072                 if (strcmp(long_option[i].name, "cap-input") == 0){
1073                     cap_f = TRUE;
1074                     continue;
1075                 }
1076                 if (strcmp(long_option[i].name, "url-input") == 0){
1077                     url_f = TRUE;
1078                     continue;
1079                 }
1080 #endif
1081 #ifdef NUMCHAR_OPTION
1082                 if (strcmp(long_option[i].name, "numchar-input") == 0){
1083                     numchar_f = TRUE;
1084                     continue;
1085                 }
1086 #endif
1087 #ifdef CHECK_OPTION
1088                 if (strcmp(long_option[i].name, "no-output") == 0){
1089                     noout_f = TRUE;
1090                     continue;
1091                 }
1092                 if (strcmp(long_option[i].name, "debug") == 0){
1093                     debug_f = TRUE;
1094                     continue;
1095                 }
1096 #endif
1097                 if (strcmp(long_option[i].name, "cp932") == 0){
1098 #ifdef SHIFTJIS_CP932
1099                     cp51932_f = TRUE;
1100                     cp932inv_f = TRUE;
1101 #endif
1102 #ifdef UTF8_OUTPUT_ENABLE
1103                     ms_ucs_map_f = TRUE;
1104 #endif
1105                     continue;
1106                 }
1107                 if (strcmp(long_option[i].name, "no-cp932") == 0){
1108 #ifdef SHIFTJIS_CP932
1109                     cp51932_f = FALSE;
1110                     cp932inv_f = FALSE;
1111 #endif
1112 #ifdef UTF8_OUTPUT_ENABLE
1113                     ms_ucs_map_f = FALSE;
1114 #endif
1115                     continue;
1116                 }
1117 #ifdef SHIFTJIS_CP932
1118                 if (strcmp(long_option[i].name, "cp932inv") == 0){
1119                     cp932inv_f = TRUE;
1120                     continue;
1121                 }
1122 #endif
1123
1124 #ifdef X0212_ENABLE
1125                 if (strcmp(long_option[i].name, "x0212") == 0){
1126                     x0212_f = TRUE;
1127                     continue;
1128                 }
1129 #endif
1130
1131 #ifdef EXEC_IO
1132                   if (strcmp(long_option[i].name, "exec-in") == 0){
1133                       exec_f = 1;
1134                       return;
1135                   }
1136                   if (strcmp(long_option[i].name, "exec-out") == 0){
1137                       exec_f = -1;
1138                       return;
1139                   }
1140 #endif
1141 #if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
1142                 if (strcmp(long_option[i].name, "internal-unicode") == 0){
1143                     internal_unicode_f = TRUE;
1144                     continue;
1145                 }
1146                 if (strcmp(long_option[i].name, "fb-skip") == 0){
1147                     encode_fallback = NULL;
1148                     continue;
1149                 }
1150                 if (strcmp(long_option[i].name, "fb-html") == 0){
1151                     encode_fallback = encode_fallback_html;
1152                     continue;
1153                 }
1154                 if (strcmp(long_option[i].name, "fb-xml" ) == 0){
1155                     encode_fallback = encode_fallback_xml;
1156                     continue;
1157                 }
1158                 if (strcmp(long_option[i].name, "fb-java") == 0){
1159                     encode_fallback = encode_fallback_java;
1160                     continue;
1161                 }
1162                 if (strcmp(long_option[i].name, "fb-perl") == 0){
1163                     encode_fallback = encode_fallback_perl;
1164                     continue;
1165                 }
1166                 if (strcmp(long_option[i].name, "fb-subchar") == 0){
1167                     encode_fallback = encode_fallback_subchar;
1168                     continue;
1169                 }
1170                 if (strcmp(long_option[i].name, "fb-subchar=") == 0){
1171                     encode_fallback = encode_fallback_subchar;
1172                     unicode_subchar = 0;
1173                     if (p[0] != '0'){
1174                         /* decimal number */
1175                         for (i = 0; i < 7 && nkf_isdigit(p[i]); i++){
1176                             unicode_subchar *= 10;
1177                             unicode_subchar += hex2bin(p[i]);
1178                         }
1179                     }else if(p[1] == 'x' || p[1] == 'X'){
1180                         /* hexadecimal number */
1181                         for (i = 2; i < 8 && nkf_isxdigit(p[i]); i++){
1182                             unicode_subchar <<= 4;
1183                             unicode_subchar |= hex2bin(p[i]);
1184                         }
1185                     }else{
1186                         /* octal number */
1187                         for (i = 1; i < 8 && nkf_isoctal(p[i]); i++){
1188                             unicode_subchar *= 8;
1189                             unicode_subchar += hex2bin(p[i]);
1190                         }
1191                     }
1192                     w16e_conv(unicode_subchar, &i, &j);
1193                     unicode_subchar = i<<8 | j;
1194                     continue;
1195                 }
1196 #endif
1197 #ifdef UTF8_OUTPUT_ENABLE
1198                 if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
1199                     ms_ucs_map_f = TRUE;
1200                     continue;
1201                 }
1202 #endif
1203 #ifdef UNICODE_NORMALIZATION
1204                 if (strcmp(long_option[i].name, "utf8mac-input") == 0){
1205                     input_f = UTF8_INPUT;
1206                     nfc_f = TRUE;
1207                     continue;
1208                 }
1209 #endif
1210                 if (strcmp(long_option[i].name, "prefix=") == 0){
1211                     if (' ' < p[0] && p[0] < 128){
1212                         for (i = 1; ' ' < p[i] && p[i] < 128; i++){
1213                             prefix_table[p[i]] = p[0];
1214                         }
1215                     }
1216                     continue;
1217                 }
1218             }
1219             continue;
1220         case 'b':           /* buffered mode */
1221             unbuf_f = FALSE;
1222             continue;
1223         case 'u':           /* non bufferd mode */
1224             unbuf_f = TRUE;
1225             continue;
1226         case 't':           /* transparent mode */
1227             nop_f = TRUE;
1228             continue;
1229         case 'j':           /* JIS output */
1230         case 'n':
1231             output_conv = j_oconv;
1232             continue;
1233         case 'e':           /* AT&T EUC output */
1234             output_conv = e_oconv;
1235             continue;
1236         case 's':           /* SJIS output */
1237             output_conv = s_oconv;
1238             continue;
1239         case 'l':           /* ISO8859 Latin-1 support, no conversion */
1240             iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
1241             input_f = LATIN1_INPUT;
1242             continue;
1243         case 'i':           /* Kanji IN ESC-$-@/B */
1244             if (*cp=='@'||*cp=='B') 
1245                 kanji_intro = *cp++;
1246             continue;
1247         case 'o':           /* ASCII IN ESC-(-J/B */
1248             if (*cp=='J'||*cp=='B'||*cp=='H') 
1249                 ascii_intro = *cp++;
1250             continue;
1251         case 'h':
1252             /*  
1253                 bit:1   katakana->hiragana
1254                 bit:2   hiragana->katakana
1255             */
1256             if ('9'>= *cp && *cp>='0') 
1257                 hira_f |= (*cp++ -'0');
1258             else 
1259                 hira_f |= 1;
1260             continue;
1261         case 'r':
1262             rot_f = TRUE;
1263             continue;
1264 #if defined(MSDOS) || defined(__OS2__) 
1265         case 'T':
1266             binmode_f = FALSE;
1267             continue;
1268 #endif
1269 #ifndef PERL_XS
1270         case 'V':
1271             version();
1272             exit(1);
1273             break;
1274         case 'v':
1275             usage();
1276             exit(1);
1277             break;
1278 #endif
1279 #ifdef UTF8_OUTPUT_ENABLE
1280         case 'w':           /* UTF-8 output */
1281             if ('1'== cp[0] && '6'==cp[1]) {
1282                 output_conv = w_oconv16; cp+=2;
1283                 if (cp[0]=='L') {
1284                     unicode_bom_f=2; cp++;
1285                     w_oconv16_LE = 1;
1286                     if (cp[0] == '0'){
1287                         unicode_bom_f=1; cp++;
1288                     }
1289                 } else if (cp[0] == 'B') {
1290                     unicode_bom_f=2; cp++;
1291                     if (cp[0] == '0'){
1292                         unicode_bom_f=1; cp++;
1293                     }
1294                 } 
1295             } else if (cp[0] == '8') {
1296                 output_conv = w_oconv; cp++;
1297                 unicode_bom_f=2;
1298                 if (cp[0] == '0'){
1299                     unicode_bom_f=1; cp++;
1300                 }
1301             } else
1302                 output_conv = w_oconv;
1303             continue;
1304 #endif
1305 #ifdef UTF8_INPUT_ENABLE
1306         case 'W':           /* UTF-8 input */
1307             if ('1'== cp[0] && '6'==cp[1]) {
1308                 input_f = UTF16BE_INPUT;
1309                 utf16_mode = UTF16BE_INPUT;
1310                 cp += 2;
1311                 if (cp[0]=='L') {
1312                     cp++;
1313                     input_f = UTF16LE_INPUT;
1314                     utf16_mode = UTF16LE_INPUT;
1315                 } else if (cp[0] == 'B') {
1316                     cp++;
1317                     input_f = UTF16BE_INPUT;
1318                     utf16_mode = UTF16BE_INPUT;
1319                 }
1320             } else if (cp[0] == '8') {
1321                 cp++;
1322                 input_f = UTF8_INPUT;
1323             } else
1324                 input_f = UTF8_INPUT;
1325             continue;
1326 #endif
1327         /* Input code assumption */
1328         case 'J':   /* JIS input */
1329         case 'E':   /* AT&T EUC input */
1330             input_f = JIS_INPUT;
1331             continue;
1332         case 'S':   /* MS Kanji input */
1333             input_f = SJIS_INPUT;
1334             if (x0201_f==NO_X0201) x0201_f=TRUE;
1335             continue;
1336         case 'Z':   /* Convert X0208 alphabet to asii */
1337             /*  bit:0   Convert X0208
1338                 bit:1   Convert Kankaku to one space
1339                 bit:2   Convert Kankaku to two spaces
1340                 bit:3   Convert HTML Entity
1341             */
1342             if ('9'>= *cp && *cp>='0') 
1343                 alpha_f |= 1<<(*cp++ -'0');
1344             else 
1345                 alpha_f |= TRUE;
1346             continue;
1347         case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
1348             x0201_f = FALSE;    /* No X0201->X0208 conversion */
1349             /* accept  X0201
1350                     ESC-(-I     in JIS, EUC, MS Kanji
1351                     SI/SO       in JIS, EUC, MS Kanji
1352                     SSO         in EUC, JIS, not in MS Kanji
1353                     MS Kanji (0xa0-0xdf) 
1354                output  X0201
1355                     ESC-(-I     in JIS (0x20-0x5f)
1356                     SSO         in EUC (0xa0-0xdf)
1357                     0xa0-0xd    in MS Kanji (0xa0-0xdf) 
1358             */
1359             continue;
1360         case 'X':   /* Assume X0201 kana */
1361             /* Default value is NO_X0201 for EUC/MS-Kanji mix */
1362             x0201_f = TRUE;
1363             continue;
1364         case 'F':   /* prserve new lines */
1365             fold_preserve_f = TRUE;
1366         case 'f':   /* folding -f60 or -f */
1367             fold_f = TRUE;
1368             fold_len = 0;
1369             while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
1370                 fold_len *= 10;
1371                 fold_len += *cp++ - '0';
1372             }
1373             if (!(0<fold_len && fold_len<BUFSIZ)) 
1374                 fold_len = DEFAULT_FOLD;
1375             if (*cp=='-') {
1376                 fold_margin = 0;
1377                 cp++;
1378                 while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
1379                     fold_margin *= 10;
1380                     fold_margin += *cp++ - '0';
1381                 }
1382             }
1383             continue;
1384         case 'm':   /* MIME support */
1385             /* mime_decode_f = TRUE; */ /* this has too large side effects... */
1386             if (*cp=='B'||*cp=='Q') {
1387                 mime_decode_mode = *cp++;
1388                 mimebuf_f = FIXED_MIME;
1389             } else if (*cp=='N') {
1390                 mime_f = TRUE; cp++;
1391             } else if (*cp=='S') {
1392                 mime_f = STRICT_MIME; cp++;
1393             } else if (*cp=='0') {
1394                 mime_decode_f = FALSE;
1395                 mime_f = FALSE; cp++;
1396             }
1397             continue;
1398         case 'M':   /* MIME output */
1399             if (*cp=='B') {
1400                 mimeout_mode = 'B';
1401                 mimeout_f = FIXED_MIME; cp++;
1402             } else if (*cp=='Q') {
1403                 mimeout_mode = 'Q';
1404                 mimeout_f = FIXED_MIME; cp++;
1405             } else {
1406                 mimeout_f = TRUE;
1407             }
1408             continue;
1409         case 'B':   /* Broken JIS support */
1410             /*  bit:0   no ESC JIS
1411                 bit:1   allow any x on ESC-(-x or ESC-$-x
1412                 bit:2   reset to ascii on NL
1413             */
1414             if ('9'>= *cp && *cp>='0') 
1415                 broken_f |= 1<<(*cp++ -'0');
1416             else 
1417                 broken_f |= TRUE;
1418             continue;
1419 #ifndef PERL_XS
1420         case 'O':/* for Output file */
1421             file_out = TRUE;
1422             continue;
1423 #endif
1424         case 'c':/* add cr code */
1425             crmode_f = CRLF;
1426             continue;
1427         case 'd':/* delete cr code */
1428             crmode_f = NL;
1429             continue;
1430         case 'I':   /* ISO-2022-JP output */
1431             iso2022jp_f = TRUE;
1432             continue;
1433         case 'L':  /* line mode */
1434             if (*cp=='u') {         /* unix */
1435                 crmode_f = NL; cp++;
1436             } else if (*cp=='m') { /* mac */
1437                 crmode_f = CR; cp++;
1438             } else if (*cp=='w') { /* windows */
1439                 crmode_f = CRLF; cp++;
1440             } else if (*cp=='0') { /* no conversion  */
1441                 crmode_f = 0; cp++;
1442             }
1443             continue;
1444         case 'g':
1445 #ifndef PERL_XS
1446             guess_f = TRUE;
1447 #endif
1448             continue;
1449         case ' ':    
1450         /* module muliple options in a string are allowed for Perl moudle  */
1451             while(*cp && *cp++!='-');
1452             continue;
1453         default:
1454             /* bogus option but ignored */
1455             continue;
1456         }
1457     }
1458 }
1459
1460 #ifdef ANSI_C_PROTOTYPE
1461 struct input_code * find_inputcode_byfunc(int (*iconv_func)(int c2,int c1,int c0))
1462 #else
1463 struct input_code * find_inputcode_byfunc(iconv_func)
1464      int (*iconv_func)();
1465 #endif
1466 {
1467     if (iconv_func){
1468         struct input_code *p = input_code_list;
1469         while (p->name){
1470             if (iconv_func == p->iconv_func){
1471                 return p;
1472             }
1473             p++;
1474         }
1475     }
1476     return 0;
1477 }
1478
1479 #ifdef ANSI_C_PROTOTYPE
1480 void set_iconv(int f, int (*iconv_func)(int c2,int c1,int c0))
1481 #else
1482 void set_iconv(f, iconv_func)
1483      int f;
1484      int (*iconv_func)();
1485 #endif
1486 {
1487 #ifdef INPUT_CODE_FIX
1488     if (f || !input_f)
1489 #endif
1490         if (estab_f != f){
1491             estab_f = f;
1492         }
1493
1494     if (iconv_func
1495 #ifdef INPUT_CODE_FIX
1496         && (f == -TRUE || !input_f) /* -TRUE means "FORCE" */
1497 #endif
1498         ){
1499         iconv = iconv_func;
1500     }
1501 #ifdef CHECK_OPTION
1502     if (estab_f && iconv_for_check != iconv){
1503         struct input_code *p = find_inputcode_byfunc(iconv);
1504         if (p){
1505             set_input_codename(p->name);
1506             debug(input_codename);
1507         }
1508         iconv_for_check = iconv;
1509     }
1510 #endif
1511 }
1512
1513 #define SCORE_L2       (1)                   /* \e$BBh\e(B2\e$B?e=`4A;z\e(B */
1514 #define SCORE_KANA     (SCORE_L2 << 1)       /* \e$B$$$o$f$kH>3Q%+%J\e(B */
1515 #define SCORE_DEPEND   (SCORE_KANA << 1)     /* \e$B5!<o0MB8J8;z\e(B */
1516 #ifdef SHIFTJIS_CP932
1517 #define SCORE_CP932    (SCORE_DEPEND << 1)   /* CP932 \e$B$K$h$kFI$_49$(\e(B */
1518 #define SCORE_NO_EXIST (SCORE_CP932 << 1)    /* \e$BB8:_$7$J$$J8;z\e(B */
1519 #else
1520 #define SCORE_NO_EXIST (SCORE_DEPEND << 1)   /* \e$BB8:_$7$J$$J8;z\e(B */
1521 #endif
1522 #define SCORE_iMIME    (SCORE_NO_EXIST << 1) /* MIME \e$B$K$h$k;XDj\e(B */
1523 #define SCORE_ERROR    (SCORE_iMIME << 1) /* \e$B%(%i!<\e(B */
1524
1525 #define SCORE_INIT (SCORE_iMIME)
1526
1527 const int score_table_A0[] = {
1528     0, 0, 0, 0,
1529     0, 0, 0, 0,
1530     0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1531     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
1532 };
1533
1534 const int score_table_F0[] = {
1535     SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
1536     SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
1537     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1538     SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
1539 };
1540
1541 void set_code_score(ptr, score)
1542      struct input_code *ptr;
1543      int score;
1544 {
1545     if (ptr){
1546         ptr->score |= score;
1547     }
1548 }
1549
1550 void clr_code_score(ptr, score)
1551      struct input_code *ptr;
1552      int score;
1553 {
1554     if (ptr){
1555         ptr->score &= ~score;
1556     }
1557 }
1558
1559 void code_score(ptr)
1560      struct input_code *ptr;
1561 {
1562     int c2 = ptr->buf[0];
1563 #ifdef UTF8_OUTPUT_ENABLE
1564     int c1 = ptr->buf[1];
1565 #endif
1566     if (c2 < 0){
1567         set_code_score(ptr, SCORE_ERROR);
1568     }else if (c2 == SSO){
1569         set_code_score(ptr, SCORE_KANA);
1570 #ifdef UTF8_OUTPUT_ENABLE
1571     }else if (!e2w_conv(c2, c1)){
1572         set_code_score(ptr, SCORE_NO_EXIST);
1573 #endif
1574     }else if ((c2 & 0x70) == 0x20){
1575         set_code_score(ptr, score_table_A0[c2 & 0x0f]);
1576     }else if ((c2 & 0x70) == 0x70){
1577         set_code_score(ptr, score_table_F0[c2 & 0x0f]);
1578     }else if ((c2 & 0x70) >= 0x50){
1579         set_code_score(ptr, SCORE_L2);
1580     }
1581 }
1582
1583 void status_disable(ptr)
1584 struct input_code *ptr;
1585 {
1586     ptr->stat = -1;
1587     ptr->buf[0] = -1;
1588     code_score(ptr);
1589     if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
1590 }
1591
1592 void status_push_ch(ptr, c)
1593      struct input_code *ptr;
1594      int c;
1595 {
1596     ptr->buf[ptr->index++] = c;
1597 }
1598
1599 void status_clear(ptr)
1600      struct input_code *ptr;
1601 {
1602     ptr->stat = 0;
1603     ptr->index = 0;
1604 }
1605
1606 void status_reset(ptr)
1607      struct input_code *ptr;
1608 {
1609     status_clear(ptr);
1610     ptr->score = SCORE_INIT;
1611 }
1612
1613 void status_reinit(ptr)
1614      struct input_code *ptr;
1615 {
1616     status_reset(ptr);
1617     ptr->_file_stat = 0;
1618 }
1619
1620 void status_check(ptr, c)
1621      struct input_code *ptr;
1622      int c;
1623 {
1624     if (c <= DEL && estab_f){
1625         status_reset(ptr);
1626     }
1627 }
1628
1629 void s_status(ptr, c)
1630      struct input_code *ptr;
1631      int c;
1632 {
1633     switch(ptr->stat){
1634       case -1:
1635           status_check(ptr, c);
1636           break;
1637       case 0:
1638           if (c <= DEL){
1639               break;
1640 #ifdef NUMCHAR_OPTION
1641           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1642               break;
1643 #endif
1644           }else if (0xa1 <= c && c <= 0xdf){
1645               status_push_ch(ptr, SSO);
1646               status_push_ch(ptr, c);
1647               code_score(ptr);
1648               status_clear(ptr);
1649           }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xef)){
1650               ptr->stat = 1;
1651               status_push_ch(ptr, c);
1652 #ifdef SHIFTJIS_CP932
1653           }else if (cp51932_f
1654                     && CP932_TABLE_BEGIN <= c && c <= CP932_TABLE_END){
1655               ptr->stat = 2;
1656               status_push_ch(ptr, c);
1657 #endif /* SHIFTJIS_CP932 */
1658 #ifdef X0212_ENABLE
1659           }else if (x0212_f && 0xf0 <= c && c <= 0xfc){
1660               ptr->stat = 1;
1661               status_push_ch(ptr, c);
1662 #endif /* X0212_ENABLE */
1663           }else{
1664               status_disable(ptr);
1665           }
1666           break;
1667       case 1:
1668           if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1669               status_push_ch(ptr, c);
1670               s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
1671               code_score(ptr);
1672               status_clear(ptr);
1673           }else{
1674               status_disable(ptr);
1675           }
1676           break;
1677       case 2:
1678 #ifdef SHIFTJIS_CP932
1679           if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1680               status_push_ch(ptr, c);
1681               if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0){
1682                   set_code_score(ptr, SCORE_CP932);
1683                   status_clear(ptr);
1684                   break;
1685               }
1686           }
1687 #endif /* SHIFTJIS_CP932 */
1688 #ifndef X0212_ENABLE
1689           status_disable(ptr);
1690           break;
1691 #endif
1692     }
1693 }
1694
1695 void e_status(ptr, c)
1696      struct input_code *ptr;
1697      int c;
1698 {
1699     switch (ptr->stat){
1700       case -1:
1701           status_check(ptr, c);
1702           break;
1703       case 0:
1704           if (c <= DEL){
1705               break;
1706 #ifdef NUMCHAR_OPTION
1707           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1708               break;
1709 #endif
1710           }else if (SSO == c || (0xa1 <= c && c <= 0xfe)){
1711               ptr->stat = 1;
1712               status_push_ch(ptr, c);
1713 #ifdef X0212_ENABLE
1714           }else if (0x8f == c){
1715               ptr->stat = 2;
1716               status_push_ch(ptr, c);
1717 #endif /* X0212_ENABLE */
1718           }else{
1719               status_disable(ptr);
1720           }
1721           break;
1722       case 1:
1723           if (0xa1 <= c && c <= 0xfe){
1724               status_push_ch(ptr, c);
1725               code_score(ptr);
1726               status_clear(ptr);
1727           }else{
1728               status_disable(ptr);
1729           }
1730           break;
1731 #ifdef X0212_ENABLE
1732       case 2:
1733           if (0xa1 <= c && c <= 0xfe){
1734               ptr->stat = 1;
1735               status_push_ch(ptr, c);
1736           }else{
1737               status_disable(ptr);
1738           }
1739 #endif /* X0212_ENABLE */
1740     }
1741 }
1742
1743 #ifdef UTF8_INPUT_ENABLE
1744 void w16_status(ptr, c)
1745      struct input_code *ptr;
1746      int c;
1747 {
1748     switch (ptr->stat){
1749       case -1:
1750           break;
1751       case 0:
1752           if (ptr->_file_stat == 0){
1753               if (c == 0xfe || c == 0xff){
1754                   ptr->stat = c;
1755                   status_push_ch(ptr, c);
1756                   ptr->_file_stat = 1;
1757               }else{
1758                   status_disable(ptr);
1759                   ptr->_file_stat = -1;
1760               }
1761           }else if (ptr->_file_stat > 0){
1762               ptr->stat = 1;
1763               status_push_ch(ptr, c);
1764           }else if (ptr->_file_stat < 0){
1765               status_disable(ptr);
1766           }
1767           break;
1768
1769       case 1:
1770           if (c == EOF){
1771               status_disable(ptr);
1772               ptr->_file_stat = -1;
1773           }else{
1774               status_push_ch(ptr, c);
1775               status_clear(ptr);
1776           }
1777           break;
1778
1779       case 0xfe:
1780       case 0xff:
1781           if (ptr->stat != c && (c == 0xfe || c == 0xff)){
1782               status_push_ch(ptr, c);
1783               status_clear(ptr);
1784           }else{
1785               status_disable(ptr);
1786               ptr->_file_stat = -1;
1787           }
1788           break;
1789     }
1790 }
1791
1792 void w_status(ptr, c)
1793      struct input_code *ptr;
1794      int c;
1795 {
1796     switch (ptr->stat){
1797       case -1:
1798           status_check(ptr, c);
1799           break;
1800       case 0:
1801           if (c <= DEL){
1802               break;
1803 #ifdef NUMCHAR_OPTION
1804           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1805               break;
1806 #endif
1807           }else if (0xc0 <= c && c <= 0xdf){
1808               ptr->stat = 1;
1809               status_push_ch(ptr, c);
1810           }else if (0xe0 <= c && c <= 0xef){
1811               ptr->stat = 2;
1812               status_push_ch(ptr, c);
1813           }else{
1814               status_disable(ptr);
1815           }
1816           break;
1817       case 1:
1818       case 2:
1819           if (0x80 <= c && c <= 0xbf){
1820               status_push_ch(ptr, c);
1821               if (ptr->index > ptr->stat){
1822                   int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
1823                              && ptr->buf[2] == 0xbf);
1824                   w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
1825                            &ptr->buf[0], &ptr->buf[1]);
1826                   if (!bom){
1827                       code_score(ptr);
1828                   }
1829                   status_clear(ptr);
1830               }
1831           }else{
1832               status_disable(ptr);
1833           }
1834           break;
1835     }
1836 }
1837 #endif
1838
1839 void
1840 code_status(c)
1841      int c;
1842 {
1843     int action_flag = 1;
1844     struct input_code *result = 0;
1845     struct input_code *p = input_code_list;
1846     while (p->name){
1847         (p->status_func)(p, c);
1848         if (p->stat > 0){
1849             action_flag = 0;
1850         }else if(p->stat == 0){
1851             if (result){
1852                 action_flag = 0;
1853             }else{
1854                 result = p;
1855             }
1856         }
1857         ++p;
1858     }
1859
1860     if (action_flag){
1861         if (result && !estab_f){
1862             set_iconv(TRUE, result->iconv_func);
1863         }else if (c <= DEL){
1864             struct input_code *ptr = input_code_list;
1865             while (ptr->name){
1866                 status_reset(ptr);
1867                 ++ptr;
1868             }
1869         }
1870     }
1871 }
1872
1873 #ifndef WIN32DLL
1874 int 
1875 std_getc(f)
1876 FILE *f;
1877 {
1878     if (std_gc_ndx){
1879         return std_gc_buf[--std_gc_ndx];
1880     }
1881     return getc(f);
1882 }
1883 #endif /*WIN32DLL*/
1884
1885 int 
1886 std_ungetc(c,f)
1887 int c;
1888 FILE *f;
1889 {
1890     if (std_gc_ndx == STD_GC_BUFSIZE){
1891         return EOF;
1892     }
1893     std_gc_buf[std_gc_ndx++] = c;
1894     return c;
1895 }
1896
1897 #ifndef WIN32DLL
1898 void 
1899 std_putc(c)
1900 int c;
1901 {
1902     if(c!=EOF)
1903       putchar(c);
1904 }
1905 #endif /*WIN32DLL*/
1906
1907 #if !defined(PERL_XS) && !defined(WIN32DLL)
1908 int
1909 noconvert(f)
1910     FILE  *f;
1911 {
1912     int    c;
1913
1914     while ((c = (*i_getc)(f)) != EOF)
1915       (*o_putc)(c);
1916     return 1;
1917 }
1918 #endif
1919
1920 void
1921 module_connection()
1922 {
1923     oconv = output_conv; 
1924     o_putc = std_putc;
1925
1926     /* replace continucation module, from output side */
1927
1928     /* output redicrection */
1929 #ifdef CHECK_OPTION
1930     if (noout_f || guess_f){
1931         o_putc = no_putc;
1932     }
1933 #endif
1934     if (mimeout_f) {
1935         o_mputc = o_putc;
1936         o_putc = mime_putc;
1937         if (mimeout_f == TRUE) {
1938             o_base64conv = oconv; oconv = base64_conv;
1939         }
1940         /* base64_count = 0; */
1941     }
1942
1943     if (crmode_f) {
1944         o_crconv = oconv; oconv = cr_conv;
1945     }
1946     if (rot_f) {
1947         o_rot_conv = oconv; oconv = rot_conv;
1948     }
1949     if (iso2022jp_f) {
1950         o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
1951     }
1952     if (hira_f) {
1953         o_hira_conv = oconv; oconv = hira_conv;
1954     }
1955     if (fold_f) {
1956         o_fconv = oconv; oconv = fold_conv;
1957         f_line = 0;
1958     }
1959     if (alpha_f || x0201_f) {
1960         o_zconv = oconv; oconv = z_conv;
1961     }
1962
1963     i_getc = std_getc;
1964     i_ungetc = std_ungetc;
1965     /* input redicrection */
1966 #ifdef INPUT_OPTION
1967     if (cap_f){
1968         i_cgetc = i_getc; i_getc = cap_getc;
1969         i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
1970     }
1971     if (url_f){
1972         i_ugetc = i_getc; i_getc = url_getc;
1973         i_uungetc = i_ungetc; i_ungetc= url_ungetc;
1974     }
1975 #endif
1976 #ifdef NUMCHAR_OPTION
1977     if (numchar_f){
1978         i_ngetc = i_getc; i_getc = numchar_getc;
1979         i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
1980     }
1981 #endif
1982 #ifdef UNICODE_NORMALIZATION
1983     if (nfc_f && input_f == UTF8_INPUT){
1984         i_nfc_getc = i_getc; i_getc = nfc_getc;
1985         i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
1986     }
1987 #endif
1988     if (mime_f && mimebuf_f==FIXED_MIME) {
1989         i_mgetc = i_getc; i_getc = mime_getc;
1990         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
1991     }
1992     if (broken_f & 1) {
1993         i_bgetc = i_getc; i_getc = broken_getc;
1994         i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
1995     }
1996     if (input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
1997         set_iconv(-TRUE, e_iconv);
1998     } else if (input_f == SJIS_INPUT) {
1999         set_iconv(-TRUE, s_iconv);
2000 #ifdef UTF8_INPUT_ENABLE
2001     } else if (input_f == UTF8_INPUT) {
2002         set_iconv(-TRUE, w_iconv);
2003     } else if (input_f == UTF16BE_INPUT) {
2004         set_iconv(-TRUE, w_iconv16);
2005     } else if (input_f == UTF16LE_INPUT) {
2006         set_iconv(-TRUE, w_iconv16);
2007 #endif
2008     } else {
2009         set_iconv(FALSE, e_iconv);
2010     }
2011
2012     {
2013         struct input_code *p = input_code_list;
2014         while (p->name){
2015             status_reinit(p++);
2016         }
2017     }
2018 }
2019
2020 /*
2021    Conversion main loop. Code detection only. 
2022  */
2023
2024 int
2025 kanji_convert(f)
2026     FILE  *f;
2027 {
2028     int    c1,
2029                     c2, c3;
2030     int is_8bit = FALSE;
2031
2032     module_connection();
2033     c2 = 0;
2034
2035
2036     input_mode = ASCII;
2037     output_mode = ASCII;
2038     shift_mode = FALSE;
2039
2040 #define NEXT continue      /* no output, get next */
2041 #define SEND ;             /* output c1 and c2, get next */
2042 #define LAST break         /* end of loop, go closing  */
2043
2044     while ((c1 = (*i_getc)(f)) != EOF) {
2045         code_status(c1);
2046         if (c2) {
2047             /* second byte */
2048             if (c2 > DEL) {
2049                 /* in case of 8th bit is on */
2050                 if (!estab_f&&!mime_decode_mode) {
2051                     /* in case of not established yet */
2052                     /* It is still ambiguious */
2053                     if (h_conv(f, c2, c1)==EOF) 
2054                         LAST;
2055                     else 
2056                         c2 = 0;
2057                     NEXT;
2058                 } else
2059                     /* in case of already established */
2060                     if (c1 < AT) {
2061                         /* ignore bogus code */
2062                         c2 = 0;
2063                         NEXT;
2064                     } else
2065                         SEND;
2066             } else
2067                 /* second byte, 7 bit code */
2068                 /* it might be kanji shitfted */
2069                 if ((c1 == DEL) || (c1 <= SPACE)) {
2070                     /* ignore bogus first code */
2071                     c2 = 0;
2072                     NEXT;
2073                 } else
2074                     SEND;
2075         } else {
2076             /* first byte */
2077             if (
2078 #ifdef UTF8_INPUT_ENABLE
2079                 iconv == w_iconv16
2080 #else
2081                 0
2082 #endif
2083                 ) {
2084                 c2 = c1;
2085                 c1 = (*i_getc)(f);
2086                 SEND;
2087 #ifdef NUMCHAR_OPTION
2088             } else if ((c1 & CLASS_MASK) == CLASS_UTF16){
2089                 SEND;
2090 #endif
2091             } else if (c1 > DEL) {
2092                 /* 8 bit code */
2093                 if (!estab_f && !iso8859_f) {
2094                     /* not established yet */
2095                     if (!is_8bit) is_8bit = TRUE;
2096                     c2 = c1;
2097                     NEXT;
2098                 } else { /* estab_f==TRUE */
2099                     if (iso8859_f) {
2100                         c2 = ISO8859_1;
2101                         c1 &= 0x7f;
2102                         SEND;
2103                     } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
2104                         /* SJIS X0201 Case... */
2105                         if(iso2022jp_f && x0201_f==NO_X0201) {
2106                             (*oconv)(GETA1, GETA2);
2107                             NEXT;
2108                         } else {
2109                             c2 = X0201;
2110                             c1 &= 0x7f;
2111                             SEND;
2112                         }
2113                     } else if (c1==SSO && iconv != s_iconv) {
2114                         /* EUC X0201 Case */
2115                         c1 = (*i_getc)(f);  /* skip SSO */
2116                         code_status(c1);
2117                         if (SSP<=c1 && c1<0xe0) {
2118                             if(iso2022jp_f &&  x0201_f==NO_X0201) {
2119                                 (*oconv)(GETA1, GETA2);
2120                                 NEXT;
2121                             } else {
2122                                 c2 = X0201;
2123                                 c1 &= 0x7f;
2124                                 SEND;
2125                             }
2126                         } else  { /* bogus code, skip SSO and one byte */
2127                             NEXT;
2128                         }
2129                     } else {
2130                        /* already established */
2131                        c2 = c1;
2132                        NEXT;
2133                     }
2134                 }
2135             } else if ((c1 > SPACE) && (c1 != DEL)) {
2136                 /* in case of Roman characters */
2137                 if (shift_mode) { 
2138                     /* output 1 shifted byte */
2139                     if (iso8859_f) {
2140                         c2 = ISO8859_1;
2141                         SEND;
2142                     } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
2143                       /* output 1 shifted byte */
2144                         if(iso2022jp_f && x0201_f==NO_X0201) {
2145                             (*oconv)(GETA1, GETA2);
2146                             NEXT;
2147                         } else {
2148                             c2 = X0201;
2149                             SEND;
2150                         }
2151                     } else {
2152                         /* look like bogus code */
2153                         NEXT;
2154                     }
2155                 } else if (input_mode == X0208) {
2156                     /* in case of Kanji shifted */
2157                     c2 = c1;
2158                     NEXT;
2159                 } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
2160                     /* Check MIME code */
2161                     if ((c1 = (*i_getc)(f)) == EOF) {
2162                         (*oconv)(0, '=');
2163                         LAST;
2164                     } else if (c1 == '?') {
2165                         /* =? is mime conversion start sequence */
2166                         if(mime_f == STRICT_MIME) {
2167                             /* check in real detail */
2168                             if (mime_begin_strict(f) == EOF) 
2169                                 LAST;
2170                             else
2171                                 NEXT;
2172                         } else if (mime_begin(f) == EOF) 
2173                             LAST;
2174                         else
2175                             NEXT;
2176                     } else {
2177                         (*oconv)(0, '=');
2178                         (*i_ungetc)(c1,f);
2179                         NEXT;
2180                     }
2181                 } else {
2182                     /* normal ASCII code */ 
2183                     SEND;
2184                 }
2185             } else if (!is_8bit && c1 == SI) {
2186                 shift_mode = FALSE; 
2187                 NEXT;
2188             } else if (!is_8bit && c1 == SO) {
2189                 shift_mode = TRUE; 
2190                 NEXT;
2191             } else if (!is_8bit && c1 == ESC ) {
2192                 if ((c1 = (*i_getc)(f)) == EOF) {
2193                     /*  (*oconv)(0, ESC); don't send bogus code */
2194                     LAST;
2195                 } else if (c1 == '$') {
2196                     if ((c1 = (*i_getc)(f)) == EOF) {
2197                         /*
2198                         (*oconv)(0, ESC); don't send bogus code 
2199                         (*oconv)(0, '$'); */
2200                         LAST;
2201                     } else if (c1 == '@'|| c1 == 'B') {
2202                         /* This is kanji introduction */
2203                         input_mode = X0208;
2204                         shift_mode = FALSE;
2205                         set_input_codename("ISO-2022-JP");
2206 #ifdef CHECK_OPTION
2207                         debug(input_codename);
2208 #endif
2209                         NEXT;
2210                     } else if (c1 == '(') {
2211                         if ((c1 = (*i_getc)(f)) == EOF) {
2212                             /* don't send bogus code 
2213                             (*oconv)(0, ESC);
2214                             (*oconv)(0, '$');
2215                             (*oconv)(0, '(');
2216                                 */
2217                             LAST;
2218                         } else if (c1 == '@'|| c1 == 'B') {
2219                             /* This is kanji introduction */
2220                             input_mode = X0208;
2221                             shift_mode = FALSE;
2222                             NEXT;
2223 #ifdef X0212_ENABLE
2224                         } else if (c1 == 'D'){
2225                             input_mode = X0212;
2226                             shift_mode = FALSE;
2227                             NEXT;
2228 #endif /* X0212_ENABLE */
2229                         } else {
2230                             /* could be some special code */
2231                             (*oconv)(0, ESC);
2232                             (*oconv)(0, '$');
2233                             (*oconv)(0, '(');
2234                             (*oconv)(0, c1);
2235                             NEXT;
2236                         }
2237                     } else if (broken_f&0x2) {
2238                         /* accept any ESC-(-x as broken code ... */
2239                         input_mode = X0208;
2240                         shift_mode = FALSE;
2241                         NEXT;
2242                     } else {
2243                         (*oconv)(0, ESC);
2244                         (*oconv)(0, '$');
2245                         (*oconv)(0, c1);
2246                         NEXT;
2247                     }
2248                 } else if (c1 == '(') {
2249                     if ((c1 = (*i_getc)(f)) == EOF) {
2250                         /* don't send bogus code 
2251                         (*oconv)(0, ESC);
2252                         (*oconv)(0, '('); */
2253                         LAST;
2254                     } else {
2255                         if (c1 == 'I') {
2256                             /* This is X0201 kana introduction */
2257                             input_mode = X0201; shift_mode = X0201;
2258                             NEXT;
2259                         } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
2260                             /* This is X0208 kanji introduction */
2261                             input_mode = ASCII; shift_mode = FALSE;
2262                             NEXT;
2263                         } else if (broken_f&0x2) {
2264                             input_mode = ASCII; shift_mode = FALSE;
2265                             NEXT;
2266                         } else {
2267                             (*oconv)(0, ESC);
2268                             (*oconv)(0, '(');
2269                             /* maintain various input_mode here */
2270                             SEND;
2271                         }
2272                     }
2273                } else if ( c1 == 'N' || c1 == 'n' ){
2274                    /* SS2 */
2275                    c3 = (*i_getc)(f);  /* skip SS2 */
2276                    if ( (SPACE<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
2277                        c1 = c3;
2278                        c2 = X0201;
2279                        SEND;
2280                    }else{
2281                        (*i_ungetc)(c3, f);
2282                        /* lonely ESC  */
2283                        (*oconv)(0, ESC);
2284                        SEND;
2285                    }
2286                 } else {
2287                     /* lonely ESC  */
2288                     (*oconv)(0, ESC);
2289                     SEND;
2290                 }
2291             } else if ((c1 == NL || c1 == CR) && broken_f&4) {
2292                 input_mode = ASCII; set_iconv(FALSE, 0);
2293                 SEND;
2294             } else if (c1 == NL && mime_decode_f && !mime_decode_mode ) {
2295                 if ((c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
2296                     i_ungetc(SPACE,f);
2297                     continue;
2298                 } else {
2299                     i_ungetc(c1,f);
2300                 }
2301                 c1 = NL;
2302                 SEND;
2303             } else if (c1 == CR && mime_decode_f && !mime_decode_mode ) {
2304                 if ((c1=(*i_getc)(f))!=EOF) {
2305                     if (c1==SPACE) {
2306                         i_ungetc(SPACE,f);
2307                         continue;
2308                     } else if (c1 == NL && (c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
2309                         i_ungetc(SPACE,f);
2310                         continue;
2311                     } else {
2312                         i_ungetc(c1,f);
2313                     }
2314                     i_ungetc(NL,f);
2315                 } else {
2316                     i_ungetc(c1,f);
2317                 }
2318                 c1 = CR;
2319                 SEND;
2320             } else 
2321                 SEND;
2322         }
2323         /* send: */
2324         if (input_mode == X0208) 
2325             (*oconv)(c2, c1);  /* this is JIS, not SJIS/EUC case */
2326 #ifdef X0212_ENABLE
2327         else if (input_mode == X0212) 
2328             (*oconv)((0x8f << 8) | c2, c1);
2329 #endif /* X0212_ENABLE */
2330         else if (input_mode) 
2331             (*oconv)(input_mode, c1);  /* other special case */
2332         else if ((*iconv)(c2, c1, 0) < 0){  /* can be EUC/SJIS */
2333             int c0 = (*i_getc)(f);
2334             if (c0 != EOF){
2335                 code_status(c0);
2336                 (*iconv)(c2, c1, c0);
2337             }
2338         }
2339
2340         c2 = 0;
2341         continue;
2342         /* goto next_word */
2343     }
2344
2345     /* epilogue */
2346     (*iconv)(EOF, 0, 0);
2347     if (!is_inputcode_set)
2348     {
2349         if (is_8bit) {
2350             struct input_code *p = input_code_list;
2351             struct input_code *result = p;
2352             while (p->name){
2353                 if (p->score < result->score) result = p;
2354                 ++p;
2355             }
2356             set_input_codename(result->name);
2357         }
2358     }
2359     return 1;
2360 }
2361
2362 int
2363 h_conv(f, c2, c1)
2364     FILE  *f;
2365     int    c1,
2366                     c2;
2367 {
2368     int    wc,c3;
2369
2370
2371     /** it must NOT be in the kanji shifte sequence      */
2372     /** it must NOT be written in JIS7                   */
2373     /** and it must be after 2 byte 8bit code            */
2374
2375     hold_count = 0;
2376     push_hold_buf(c2);
2377     push_hold_buf(c1);
2378     c2 = 0;
2379
2380     while ((c1 = (*i_getc)(f)) != EOF) {
2381         if (c1 == ESC){
2382             (*i_ungetc)(c1,f);
2383             break;
2384         }
2385         code_status(c1);
2386         if (push_hold_buf(c1) == EOF || estab_f){
2387             break;
2388         }
2389     }
2390
2391     if (!estab_f){
2392         struct input_code *p = input_code_list;
2393         struct input_code *result = p;
2394         if (c1 == EOF){
2395             code_status(c1);
2396         }
2397         while (p->name){
2398             if (p->score < result->score){
2399                 result = p;
2400             }
2401             ++p;
2402         }
2403         set_iconv(FALSE, result->iconv_func);
2404     }
2405
2406
2407     /** now,
2408      ** 1) EOF is detected, or
2409      ** 2) Code is established, or
2410      ** 3) Buffer is FULL (but last word is pushed)
2411      **
2412      ** in 1) and 3) cases, we continue to use
2413      ** Kanji codes by oconv and leave estab_f unchanged.
2414      **/
2415
2416     c3=c1;
2417     wc = 0;
2418     while (wc < hold_count){
2419         c2 = hold_buf[wc++];
2420         if (c2 <= DEL
2421 #ifdef NUMCHAR_OPTION
2422             || (c2 & CLASS_MASK) == CLASS_UTF16
2423 #endif
2424             ){
2425             (*iconv)(0, c2, 0);
2426             continue;
2427         }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
2428             (*iconv)(X0201, c2, 0);
2429             continue;
2430         }
2431         if (wc < hold_count){
2432             c1 = hold_buf[wc++];
2433         }else{
2434             c1 = (*i_getc)(f);
2435             if (c1 == EOF){
2436                 c3 = EOF;
2437                 break;
2438             }
2439             code_status(c1);
2440         }
2441         if ((*iconv)(c2, c1, 0) < 0){
2442             int c0;
2443             if (wc < hold_count){
2444                 c0 = hold_buf[wc++];
2445             }else{
2446                 c0 = (*i_getc)(f);
2447                 if (c0 == EOF){
2448                     c3 = EOF;
2449                     break;
2450                 }
2451                 code_status(c0);
2452             }
2453             (*iconv)(c2, c1, c0);
2454             c1 = c0;
2455         }
2456     }
2457     return c3;
2458 }
2459
2460
2461
2462 int
2463 push_hold_buf(c2)
2464      int             c2;
2465 {
2466     if (hold_count >= HOLD_SIZE*2)
2467         return (EOF);
2468     hold_buf[hold_count++] = c2;
2469     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
2470 }
2471
2472 int s2e_conv(c2, c1, p2, p1)
2473      int c2, c1;
2474      int *p2, *p1;
2475 {
2476 #if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
2477     int val;
2478 #endif
2479 #ifdef SHIFTJIS_CP932
2480     if (cp51932_f && CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END){
2481         extern const unsigned short shiftjis_cp932[3][189];
2482         val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
2483         if (val){
2484             c2 = val >> 8;
2485             c1 = val & 0xff;
2486         }
2487     }
2488 #endif /* SHIFTJIS_CP932 */
2489 #ifdef X0212_ENABLE
2490     if (x0212_f && 0xfa <= c2 && c2 <= 0xfc){
2491         extern const unsigned short shiftjis_x0212[3][189];
2492         val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
2493         if (val){
2494             if (val & 0x8000){
2495                 c2 = (0x8f << 8) | (val >> 8);
2496                 c1 = val & 0xff;
2497             }else{
2498                 c2 = val >> 8;
2499                 c1 = val & 0xff;
2500             }
2501             if (p2) *p2 = c2;
2502             if (p1) *p1 = c1;
2503             return 0;
2504         }
2505     }
2506 #endif
2507     if(c2 >= 0x80){
2508         c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
2509         if (c1 < 0x9f)
2510             c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
2511         else {
2512             c1 = c1 - 0x7e;
2513             c2++;
2514         }
2515     }
2516
2517 #ifdef X0212_ENABLE
2518     if (x0212_f){
2519         c2 = x0212_unshift(c2);
2520     }
2521 #endif
2522     if (p2) *p2 = c2;
2523     if (p1) *p1 = c1;
2524     return 0;
2525 }
2526
2527 int
2528 s_iconv(c2, c1, c0)
2529     int    c2,
2530                     c1, c0;
2531 {
2532     if (c2 == X0201) {
2533         c1 &= 0x7f;
2534     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2535         /* NOP */
2536     } else {
2537         int ret = s2e_conv(c2, c1, &c2, &c1);
2538         if (ret) return ret;
2539     }
2540     (*oconv)(c2, c1);
2541     return 0;
2542 }
2543
2544 int
2545 e_iconv(c2, c1, c0)
2546     int    c2,
2547                     c1, c0;
2548 {
2549     if (c2 == X0201) {
2550         c1 &= 0x7f;
2551 #ifdef X0212_ENABLE
2552     }else if (c2 == 0x8f){
2553         if (c0 == 0){
2554             return -1;
2555         }
2556         c2 = (c2 << 8) | (c1 & 0x7f);
2557         c1 = c0 & 0x7f;
2558 #ifdef SHIFTJIS_CP932
2559         if (cp51932_f){
2560             int s2, s1;
2561             if (e2s_conv(c2, c1, &s2, &s1) == 0){
2562                 s2e_conv(s2, s1, &c2, &c1);
2563                 if ((c2 & 0xff00) == 0){
2564                     c1 &= 0x7f;
2565                     c2 &= 0x7f;
2566                 }
2567             }
2568         }
2569 #endif /* SHIFTJIS_CP932 */
2570 #endif /* X0212_ENABLE */
2571     } else if (c2 == SSO){
2572         c2 = X0201;
2573         c1 &= 0x7f;
2574     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2575         /* NOP */
2576     } else {
2577         c1 &= 0x7f;
2578         c2 &= 0x7f;
2579     }
2580     (*oconv)(c2, c1);
2581     return 0;
2582 }
2583
2584 #ifdef UTF8_INPUT_ENABLE
2585 int
2586 w2e_conv(c2, c1, c0, p2, p1)
2587     int    c2, c1, c0;
2588     int *p2, *p1;
2589 {
2590     extern const unsigned short *const utf8_to_euc_2bytes[];
2591     extern const unsigned short *const *const utf8_to_euc_3bytes[];
2592     int ret = 0;
2593
2594     if (0xc0 <= c2 && c2 <= 0xef) {
2595         const unsigned short *const *pp;
2596
2597         if (0xe0 <= c2) {
2598             if (c0 == 0) return -1;
2599             pp = utf8_to_euc_3bytes[c2 - 0x80];
2600             ret = w_iconv_common(c1, c0, pp, sizeof_utf8_to_euc_C2, p2, p1);
2601         } else {
2602             ret =  w_iconv_common(c2, c1, utf8_to_euc_2bytes, sizeof_utf8_to_euc_2bytes, p2, p1);
2603         }
2604 #ifdef NUMCHAR_OPTION
2605         if (ret){
2606             if (p2) *p2 = 0;
2607             if (p1) *p1 = CLASS_UTF16 | ww16_conv(c2, c1, c0);
2608             ret = 0;
2609         }
2610 #endif
2611         return ret;
2612     } else if (c2 == X0201) {
2613         c1 &= 0x7f;
2614     }
2615     if (p2) *p2 = c2;
2616     if (p1) *p1 = c1;
2617     return ret;
2618 }
2619
2620 int
2621 w_iconv(c2, c1, c0)
2622     int    c2,
2623                     c1, c0;
2624 {
2625     int ret = 0;
2626     
2627     if (c0 == 0){
2628         if (c2 == 0) /* 0x00-0x7f */
2629             ; /* 1byte */
2630         else if ((c2 & 0xe0) == 0xc0) /* 0xc0-0xdf */
2631             ; /* 2ytes */
2632         else if ((c2 & 0xf0) == 0xe0) /* 0xe0-0xef */
2633             return -1; /* 3bytes */
2634 #ifdef __COMMENT__
2635         else if (0xf0 <= c2)
2636             return 0; /* 4,5,6bytes */
2637         else if ((c2 & 0xc0) == 0x80) /* 0x80-0xbf */
2638             return 0; /* trail byte */
2639 #endif
2640         else return 0;
2641     }
2642     if (c2 == EOF);
2643     else if (c2 == 0xef && c1 == 0xbb && c0 == 0xbf) {
2644         return 0; /* throw BOM */
2645 #if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
2646     } else if (internal_unicode_f && (output_conv == w_oconv || output_conv == w_oconv16)){
2647         unsigned short val = 0;
2648         if(c2 == 0){
2649             c2 = c1;
2650             c1 = 0;
2651         }
2652         val = ww16_conv(c2, c1, c0);
2653         c2 = (val >> 8) & 0xff;
2654         c1 = val & 0xff;
2655 #endif
2656     } else {
2657         ret = w2e_conv(c2, c1, c0, &c2, &c1);
2658     }
2659     if (ret == 0){
2660         (*oconv)(c2, c1);
2661     }
2662     return ret;
2663 }
2664
2665 void
2666 w16w_conv(val, p2, p1, p0)
2667      unsigned short val;
2668      int *p2, *p1, *p0;
2669 {
2670     if (val < 0x80){
2671         *p2 = val;
2672         *p1 = 0;
2673         *p0 = 0;
2674     }else if (val < 0x800){
2675         *p2 = 0xc0 | (val >> 6);
2676         *p1 = 0x80 | (val & 0x3f);
2677         *p0 = 0;
2678     }else{
2679         *p2 = 0xe0 | (val >> 12);
2680         *p1 = 0x80 | ((val >> 6) & 0x3f);
2681         *p0 = 0x80 | (val        & 0x3f);
2682     }
2683 }
2684
2685 int
2686 ww16_conv(c2, c1, c0)
2687      int c2, c1, c0;
2688 {
2689     unsigned short val;
2690     if (c2 >= 0xe0){
2691         val = (c2 & 0x0f) << 12;
2692         val |= (c1 & 0x3f) << 6;
2693         val |= (c0 & 0x3f);
2694     }else if (c2 >= 0xc0){
2695         val = (c2 & 0x1f) << 6;
2696         val |= (c1 & 0x3f);
2697     }else{
2698         val = c2;
2699     }
2700     return val;
2701 }
2702
2703 int
2704 w16e_conv(val, p2, p1)
2705      unsigned short val;
2706      int *p2, *p1;
2707 {
2708     extern const unsigned short *const utf8_to_euc_2bytes[];
2709     extern const unsigned short *const *const utf8_to_euc_3bytes[];
2710     int c2, c1, c0;
2711     const unsigned short *const *pp;
2712     int psize;
2713     int ret = 0;
2714
2715     w16w_conv(val, &c2, &c1, &c0);
2716     if (c1){
2717         if (c0){
2718             pp = utf8_to_euc_3bytes[c2 - 0x80];
2719             psize = sizeof_utf8_to_euc_C2;
2720             ret =  w_iconv_common(c1, c0, pp, psize, p2, p1);
2721         }else{
2722             pp = utf8_to_euc_2bytes;
2723             psize = sizeof_utf8_to_euc_2bytes;
2724             ret =  w_iconv_common(c2, c1, pp, psize, p2, p1);
2725         }
2726 #ifdef NUMCHAR_OPTION
2727         if (ret){
2728             *p2 = 0;
2729             *p1 = CLASS_UTF16 | val;
2730             ret = 0;
2731         }
2732 #endif
2733     }else{
2734         *p2 = 0;
2735         *p1 = c2;
2736     }
2737     return ret;
2738 }
2739
2740 int
2741 w_iconv16(c2, c1, c0)
2742     int    c2, c1,c0;
2743 {
2744     int ret = 0;
2745
2746     if (c2==0376 && c1==0377){
2747         utf16_mode = UTF16BE_INPUT;
2748         return 0;    
2749     } else if (c2==0377 && c1==0376){
2750         utf16_mode = UTF16LE_INPUT;
2751         return 0;    
2752     }
2753     if (c2 != EOF && utf16_mode == UTF16LE_INPUT) {
2754         int tmp;
2755         tmp=c1; c1=c2; c2=tmp;
2756     }
2757     if ((c2==0 && c1 < 0x80) || c2==EOF) {
2758         (*oconv)(c2, c1);
2759         return 0;
2760     }
2761 #if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
2762     if (internal_unicode_f && (output_conv == w_oconv || output_conv == w_oconv16));
2763 #endif
2764     else ret = w16e_conv(((c2<<8)&0xff00) + c1, &c2, &c1);
2765     if (ret) return ret;
2766     (*oconv)(c2, c1);
2767     return 0;
2768 }
2769
2770 int
2771 w_iconv_common(c1, c0, pp, psize, p2, p1)
2772     int    c1,c0;
2773     const unsigned short *const *pp;
2774     int psize;
2775     int *p2, *p1;
2776 {
2777     int c2;
2778     const unsigned short *p;
2779     unsigned short val;
2780
2781     /* CP932/CP51932: U+00A6 (BROKEN BAR) -> not 0x8fa2c3, but 0x7c */
2782     if (cp51932_f && c1 == 0xC2 && c0 == 0xA6){
2783         if (p2) *p2 = 0;
2784         if (p1) *p1 = 0x7C;
2785         return 0;
2786     }
2787
2788     if (pp == 0) return 1;
2789
2790     c1 -= 0x80;
2791     if (c1 < 0 || psize <= c1) return 1;
2792     p = pp[c1];
2793     if (p == 0)  return 1;
2794
2795     c0 -= 0x80;
2796     if (c0 < 0 || sizeof_utf8_to_euc_E5B8 <= c0) return 1;
2797     val = p[c0];
2798     if (val == 0) return 1;
2799
2800     c2 = val >> 8;
2801     if (val & 0x8000){
2802         c2 &= 0x7f;
2803         c2 |= 0x8f00;
2804     }
2805     if (c2 == SO) c2 = X0201;
2806     c1 = val & 0x7f;
2807     if (p2) *p2 = c2;
2808     if (p1) *p1 = c1;
2809     return 0;
2810 }
2811
2812 #endif
2813
2814 #ifdef UTF8_OUTPUT_ENABLE
2815 void
2816 nkf_each_char_to_hex(f, c)
2817     void (*f)PROTO((int c2,int c1));
2818     int c;
2819 {
2820     const char *hex = "0123456789ABCDEF";
2821     c &= 0x00FFFFFF;
2822     int shift = 20;
2823     while(shift >= 0){
2824         if(c >= 1<<shift){
2825             while(shift >= 0){
2826                 (*f)(0, hex[(c>>shift)&0xF]);
2827                 shift -= 4;
2828             }
2829         }else{
2830             shift -= 4;
2831         }
2832     }
2833     return;
2834 }
2835
2836 void
2837 encode_fallback_html(c)
2838     int c;
2839 {
2840     (*oconv)(0, '&');
2841     (*oconv)(0, '#');
2842     c &= 0x00FFFFFF;
2843     if(c >= 1000000)
2844         (*oconv)(0, 0x30+(c/1000000)%10);
2845     if(c >= 100000)
2846         (*oconv)(0, 0x30+(c/100000 )%10);
2847     if(c >= 10000)
2848         (*oconv)(0, 0x30+(c/10000  )%10);
2849     if(c >= 1000)
2850         (*oconv)(0, 0x30+(c/1000   )%10);
2851     if(c >= 100)
2852         (*oconv)(0, 0x30+(c/100    )%10);
2853     if(c >= 10)
2854         (*oconv)(0, 0x30+(c/10     )%10);
2855     if(c >= 0)
2856         (*oconv)(0, 0x30+ c         %10);
2857     (*oconv)(0, ';');
2858     return;
2859 }
2860
2861 void
2862 encode_fallback_xml(c)
2863     int c;
2864 {
2865     (*oconv)(0, '&');
2866     (*oconv)(0, '#');
2867     (*oconv)(0, 'x');
2868     nkf_each_char_to_hex(oconv, c);
2869     (*oconv)(0, ';');
2870     return;
2871 }
2872
2873 void
2874 encode_fallback_java(c)
2875     int c;
2876 {
2877     const char *hex = "0123456789ABCDEF";
2878     (*oconv)(0, '\\');
2879     if((c&0x00FFFFFF) > 0xFFFF){
2880         (*oconv)(0, 'U');
2881         (*oconv)(0, '0');
2882         (*oconv)(0, '0');
2883         (*oconv)(0, hex[(c>>20)&0xF]);
2884         (*oconv)(0, hex[(c>>16)&0xF]);
2885     }else{
2886         (*oconv)(0, 'u');
2887     }
2888     (*oconv)(0, hex[(c>>12)&0xF]);
2889     (*oconv)(0, hex[(c>> 8)&0xF]);
2890     (*oconv)(0, hex[(c>> 4)&0xF]);
2891     (*oconv)(0, hex[ c     &0xF]);
2892     return;
2893 }
2894
2895 void
2896 encode_fallback_perl(c)
2897     int c;
2898 {
2899     (*oconv)(0, '\\');
2900     (*oconv)(0, 'x');
2901     (*oconv)(0, '{');
2902     nkf_each_char_to_hex(oconv, c);
2903     (*oconv)(0, '}');
2904     return;
2905 }
2906
2907 void
2908 encode_fallback_subchar(c)
2909     int c;
2910 {
2911     c = unicode_subchar;
2912     (*oconv)((c>>8)&0xFF, c&0xFF);
2913     return;
2914     int shift = 16;
2915     while(shift >= 0){
2916         if(c >= 1<<shift){
2917             while(shift >= 0){
2918                 (*oconv)(0, (c>>shift)&0xFF);
2919                 shift -= 8;
2920             }
2921         }else{
2922             shift -= 8;
2923         }
2924     }
2925     return;
2926 }
2927
2928 int
2929 e2w_conv(c2, c1)
2930     int    c2, c1;
2931 {
2932     extern const unsigned short euc_to_utf8_1byte[];
2933     extern const unsigned short *const euc_to_utf8_2bytes[];
2934     extern const unsigned short *const euc_to_utf8_2bytes_ms[];
2935     const unsigned short *p;
2936
2937     if (c2 == X0201) {
2938         p = euc_to_utf8_1byte;
2939 #ifdef X0212_ENABLE
2940     } else if (c2 >> 8 == 0x8f){
2941         extern const unsigned short *const x0212_to_utf8_2bytes[];
2942         c2 = (c2&0x7f) - 0x21;
2943         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
2944             p = x0212_to_utf8_2bytes[c2];
2945         else
2946             return 0;
2947 #endif
2948     } else {
2949         c2 &= 0x7f;
2950         c2 = (c2&0x7f) - 0x21;
2951         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
2952             p = ms_ucs_map_f ? euc_to_utf8_2bytes_ms[c2] : euc_to_utf8_2bytes[c2];
2953         else
2954             return 0;
2955     }
2956     if (!p) return 0;
2957     c1 = (c1 & 0x7f) - 0x21;
2958     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
2959         return p[c1];
2960     return 0;
2961 }
2962
2963 void
2964 w_oconv(c2, c1)
2965     int    c2,
2966                     c1;
2967 {
2968     int c0;
2969     unsigned short val;
2970     if (c2 == EOF) {
2971         (*o_putc)(EOF);
2972         return;
2973     }
2974
2975     if (unicode_bom_f==2) {
2976         (*o_putc)('\357');
2977         (*o_putc)('\273');
2978         (*o_putc)('\277');
2979         unicode_bom_f=1;
2980     }
2981
2982 #ifdef NUMCHAR_OPTION
2983     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2984         w16w_conv(c1, &c2, &c1, &c0);
2985         (*o_putc)(c2);
2986         if (c1){
2987             (*o_putc)(c1);
2988             if (c0) (*o_putc)(c0);
2989         }
2990         return;
2991     }
2992 #endif
2993
2994     if (c2 == 0) { 
2995         output_mode = ASCII;
2996         (*o_putc)(c1);
2997     } else if (c2 == ISO8859_1) {
2998         output_mode = ISO8859_1;
2999         (*o_putc)(c1 | 0x080);
3000     } else {
3001         output_mode = UTF8;
3002         if (internal_unicode_f && (iconv == w_iconv || iconv == w_iconv16))
3003             val = ((c2<<8)&0xff00) + c1;
3004         else val = e2w_conv(c2, c1);
3005         if (val){
3006             w16w_conv(val, &c2, &c1, &c0);
3007             (*o_putc)(c2);
3008             if (c1){
3009                 (*o_putc)(c1);
3010                 if (c0) (*o_putc)(c0);
3011             }
3012         }
3013     }
3014 }
3015
3016 void
3017 w_oconv16(c2, c1)
3018     int    c2,
3019                     c1;
3020 {
3021     if (c2 == EOF) {
3022         (*o_putc)(EOF);
3023         return;
3024     }    
3025
3026     if (unicode_bom_f==2) {
3027         if (w_oconv16_LE){
3028             (*o_putc)((unsigned char)'\377');
3029             (*o_putc)('\376');
3030         }else{
3031             (*o_putc)('\376');
3032             (*o_putc)((unsigned char)'\377');
3033         }
3034         unicode_bom_f=1;
3035     }
3036
3037     if (internal_unicode_f && (iconv == w_iconv || iconv == w_iconv16)){
3038     } else if (c2 == ISO8859_1) {
3039         c2 = 0;
3040         c1 |= 0x80;
3041 #ifdef NUMCHAR_OPTION
3042     } else if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16) {
3043         c2 = (c1 >> 8) & 0xff;
3044         c1 &= 0xff;
3045 #endif
3046     } else if (c2) {
3047         unsigned short val = e2w_conv(c2, c1);
3048         c2 = (val >> 8) & 0xff;
3049         c1 = val & 0xff;
3050     }
3051     if (w_oconv16_LE){
3052         (*o_putc)(c1);
3053         (*o_putc)(c2);
3054     }else{
3055         (*o_putc)(c2);
3056         (*o_putc)(c1);
3057     }
3058 }
3059
3060 #endif
3061
3062 void
3063 e_oconv(c2, c1)
3064     int    c2,
3065                     c1;
3066 {
3067 #ifdef NUMCHAR_OPTION
3068     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
3069         w16e_conv(c1, &c2, &c1);
3070         if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
3071             if(encode_fallback)(*encode_fallback)(c1);
3072             return;
3073         }
3074     }
3075 #endif
3076     if (c2 == EOF) {
3077         (*o_putc)(EOF);
3078         return;
3079     } else if (c2 == 0) { 
3080         output_mode = ASCII;
3081         (*o_putc)(c1);
3082     } else if (c2 == X0201) {
3083         output_mode = JAPANESE_EUC;
3084         (*o_putc)(SSO); (*o_putc)(c1|0x80);
3085     } else if (c2 == ISO8859_1) {
3086         output_mode = ISO8859_1;
3087         (*o_putc)(c1 | 0x080);
3088 #ifdef X0212_ENABLE
3089     } else if ((c2 & 0xff00) >> 8 == 0x8f){
3090         output_mode = JAPANESE_EUC;
3091 #ifdef SHIFTJIS_CP932
3092         if (cp51932_f){
3093             int s2, s1;
3094             if (e2s_conv(c2, c1, &s2, &s1) == 0){
3095                 s2e_conv(s2, s1, &c2, &c1);
3096             }
3097         }
3098 #endif
3099         if (c2 == 0) {
3100             output_mode = ASCII;
3101             (*o_putc)(c1);
3102         }else if ((c2 & 0xff00) >> 8 == 0x8f){
3103             if (x0212_f){
3104                 (*o_putc)(0x8f);
3105                 (*o_putc)((c2 & 0x7f) | 0x080);
3106                 (*o_putc)(c1 | 0x080);
3107             }
3108         }else{
3109             (*o_putc)((c2 & 0x7f) | 0x080);
3110             (*o_putc)(c1 | 0x080);
3111         }
3112 #endif
3113     } else {
3114         if ((c1<0x21 || 0x7e<c1) ||
3115            (c2<0x21 || 0x7e<c2)) {
3116             set_iconv(FALSE, 0);
3117             return; /* too late to rescue this char */
3118         }
3119         output_mode = JAPANESE_EUC;
3120         (*o_putc)(c2 | 0x080);
3121         (*o_putc)(c1 | 0x080);
3122     }
3123 }
3124
3125 #ifdef X0212_ENABLE
3126 int x0212_shift(c)
3127      int c;
3128 {
3129     int ret = c;
3130     c &= 0x7f;
3131     if ((ret & 0xff00) == 0x8f00){
3132         if (0x75 <= c && c <= 0x7f){
3133             ret = c + (0x109 - 0x75);
3134         }
3135     }else{
3136         if (0x75 <= c && c <= 0x7f){
3137             ret = c + (0x113 - 0x75);
3138         }
3139     }
3140     return ret;
3141 }
3142
3143
3144 int x0212_unshift(c)
3145      int c;
3146 {
3147     int ret = c;
3148     if (0x7f <= c && c <= 0x88){
3149         ret = c + (0x75 - 0x7f);
3150     }else if (0x89 <= c && c <= 0x92){
3151         ret = (0x8f << 8) | 0x80 | (c + (0x75 - 0x89));
3152     }
3153     return ret;
3154 }
3155 #endif /* X0212_ENABLE */
3156
3157 int
3158 e2s_conv(c2, c1, p2, p1)
3159      int c2, c1, *p2, *p1;
3160 {
3161 #ifdef X0212_ENABLE
3162     int val = 0;
3163     const unsigned short *ptr;
3164     int ndx;
3165     extern const unsigned short *const x0212_shiftjis[];
3166     if ((c2 & 0xff00) == 0x8f00){
3167         ndx = c2 & 0x7f;
3168         if (0x21 <= ndx && ndx <= 0x7e){
3169             ptr = x0212_shiftjis[ndx - 0x21];
3170             if (ptr){
3171                 val = ptr[(c1 & 0x7f) - 0x21];
3172             }
3173             if (val){
3174                 c2 = val >> 8;
3175                 c1 = val & 0xff;
3176                 if (p2) *p2 = c2;
3177                 if (p1) *p1 = c1;
3178                 return 0;
3179             }
3180         }
3181         c2 = x0212_shift(c2);
3182     }
3183 #endif /* X0212_ENABLE */
3184     if ((c2 & 0xff00) == 0x8f00){
3185         return 1;
3186     }
3187     if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
3188     if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
3189     return 0;
3190 }
3191
3192 void
3193 s_oconv(c2, c1)
3194     int    c2,
3195                     c1;
3196 {
3197 #ifdef NUMCHAR_OPTION
3198     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
3199         w16e_conv(c1, &c2, &c1);
3200         if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
3201             if(encode_fallback)(*encode_fallback)(c1);
3202             return;
3203         }
3204     }
3205 #endif
3206     if (c2 == EOF) {
3207         (*o_putc)(EOF);
3208         return;
3209     } else if (c2 == 0) {
3210         output_mode = ASCII;
3211         (*o_putc)(c1);
3212     } else if (c2 == X0201) {
3213         output_mode = SHIFT_JIS;
3214         (*o_putc)(c1|0x80);
3215     } else if (c2 == ISO8859_1) {
3216         output_mode = ISO8859_1;
3217         (*o_putc)(c1 | 0x080);
3218 #ifdef X0212_ENABLE
3219     } else if ((c2 & 0xff00) >> 8 == 0x8f){
3220         output_mode = SHIFT_JIS;
3221         if (e2s_conv(c2, c1, &c2, &c1) == 0){
3222             (*o_putc)(c2);
3223             (*o_putc)(c1);
3224         }
3225 #endif
3226     } else {
3227         if ((c1<0x20 || 0x7e<c1) ||
3228            (c2<0x20 || 0x7e<c2)) {
3229             set_iconv(FALSE, 0);
3230             return; /* too late to rescue this char */
3231         }
3232         output_mode = SHIFT_JIS;
3233         e2s_conv(c2, c1, &c2, &c1);
3234
3235 #ifdef SHIFTJIS_CP932
3236         if (cp932inv_f
3237             && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
3238             extern const unsigned short cp932inv[2][189];
3239             int c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
3240             if (c){
3241                 c2 = c >> 8;
3242                 c1 = c & 0xff;
3243             }
3244         }
3245 #endif /* SHIFTJIS_CP932 */
3246
3247         (*o_putc)(c2);
3248         if (prefix_table[(unsigned char)c1]){
3249             (*o_putc)(prefix_table[(unsigned char)c1]);
3250         }
3251         (*o_putc)(c1);
3252     }
3253 }
3254
3255 void
3256 j_oconv(c2, c1)
3257     int    c2,
3258                     c1;
3259 {
3260 #ifdef NUMCHAR_OPTION
3261     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
3262         w16e_conv(c1, &c2, &c1);
3263         if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
3264             if(encode_fallback)(*encode_fallback)(c1);
3265             return;
3266         }
3267     }
3268 #endif
3269     if (c2 == EOF) {
3270         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
3271             (*o_putc)(ESC);
3272             (*o_putc)('(');
3273             (*o_putc)(ascii_intro);
3274             output_mode = ASCII;
3275         }
3276         (*o_putc)(EOF);
3277 #ifdef X0212_ENABLE
3278     } else if ((c2 & 0xff00) >> 8 == 0x8f){
3279         if (output_mode!=X0212) {
3280             output_mode = X0212;
3281             (*o_putc)(ESC);
3282             (*o_putc)('$');
3283             (*o_putc)('(');
3284             (*o_putc)('D');
3285         }
3286         (*o_putc)(c2 & 0x7f);
3287         (*o_putc)(c1);
3288 #endif
3289     } else if (c2==X0201) {
3290         if (output_mode!=X0201) {
3291             output_mode = X0201;
3292             (*o_putc)(ESC);
3293             (*o_putc)('(');
3294             (*o_putc)('I');
3295         }
3296         (*o_putc)(c1);
3297     } else if (c2==ISO8859_1) {
3298             /* iso8859 introduction, or 8th bit on */
3299             /* Can we convert in 7bit form using ESC-'-'-A ? 
3300                Is this popular? */
3301         output_mode = ISO8859_1;
3302         (*o_putc)(c1|0x80);
3303     } else if (c2 == 0) {
3304         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
3305             (*o_putc)(ESC);
3306             (*o_putc)('(');
3307             (*o_putc)(ascii_intro);
3308             output_mode = ASCII;
3309         }
3310         (*o_putc)(c1);
3311     } else {
3312         if (output_mode != X0208) {
3313             output_mode = X0208;
3314             (*o_putc)(ESC);
3315             (*o_putc)('$');
3316             (*o_putc)(kanji_intro);
3317         }
3318         if (c1<0x20 || 0x7e<c1) 
3319             return;
3320         if (c2<0x20 || 0x7e<c2) 
3321             return;
3322         (*o_putc)(c2);
3323         (*o_putc)(c1);
3324     }
3325 }
3326
3327 void
3328 base64_conv(c2, c1)
3329     int    c2,
3330                     c1;
3331 {
3332     mime_prechar(c2, c1);
3333     (*o_base64conv)(c2,c1);
3334 }
3335
3336
3337 STATIC int broken_buf[3];
3338 STATIC int broken_counter = 0;
3339 STATIC int broken_last = 0;
3340 int
3341 broken_getc(f)
3342 FILE *f;
3343 {
3344     int c,c1;
3345
3346     if (broken_counter>0) {
3347         return broken_buf[--broken_counter];
3348     }
3349     c= (*i_bgetc)(f);
3350     if (c=='$' && broken_last != ESC 
3351             && (input_mode==ASCII || input_mode==X0201)) {
3352         c1= (*i_bgetc)(f);
3353         broken_last = 0;
3354         if (c1=='@'|| c1=='B') {
3355             broken_buf[0]=c1; broken_buf[1]=c; 
3356             broken_counter=2;
3357             return ESC;
3358         } else {
3359             (*i_bungetc)(c1,f);
3360             return c;
3361         }
3362     } else if (c=='(' && broken_last != ESC 
3363             && (input_mode==X0208 || input_mode==X0201)) { /* ) */
3364         c1= (*i_bgetc)(f);
3365         broken_last = 0;
3366         if (c1=='J'|| c1=='B') {
3367             broken_buf[0]=c1; broken_buf[1]=c;
3368             broken_counter=2;
3369             return ESC;
3370         } else {
3371             (*i_bungetc)(c1,f);
3372             return c;
3373         }
3374     } else {
3375         broken_last = c;
3376         return c;
3377     }
3378 }
3379
3380 int
3381 broken_ungetc(c,f)
3382 int c;
3383 FILE *f;
3384 {
3385     if (broken_counter<2)
3386         broken_buf[broken_counter++]=c;
3387     return c;
3388 }
3389
3390 STATIC int prev_cr = 0;
3391
3392 void
3393 cr_conv(c2,c1) 
3394 int c2,c1;
3395 {
3396     if (prev_cr) {
3397         prev_cr = 0;
3398         if (! (c2==0&&c1==NL) ) {
3399             cr_conv(0,'\n');
3400         }
3401     }
3402     if (c2) {
3403         (*o_crconv)(c2,c1);
3404     } else if (c1=='\r') {
3405         prev_cr = c1;
3406     } else if (c1=='\n') {
3407         if (crmode_f==CRLF) {
3408             (*o_crconv)(0,'\r');
3409         } else if (crmode_f==CR) {
3410             (*o_crconv)(0,'\r');
3411             return;
3412         } 
3413         (*o_crconv)(0,NL);
3414     } else if (c1!='\032' || crmode_f!=NL){
3415         (*o_crconv)(c2,c1);
3416     }
3417 }
3418
3419 /* 
3420   Return value of fold_conv()
3421
3422        \n  add newline  and output char
3423        \r  add newline  and output nothing
3424        ' ' space
3425        0   skip  
3426        1   (or else) normal output 
3427
3428   fold state in prev (previous character)
3429
3430       >0x80 Japanese (X0208/X0201)
3431       <0x80 ASCII
3432       \n    new line 
3433       ' '   space
3434
3435   This fold algorthm does not preserve heading space in a line.
3436   This is the main difference from fmt.
3437 */
3438
3439 #define char_size(c2,c1) (c2?2:1)
3440
3441 void
3442 fold_conv(c2,c1) 
3443 int c2,c1;
3444
3445     int prev0;
3446     int fold_state=0;
3447
3448     if (c1== '\r' && !fold_preserve_f) {
3449         fold_state=0;  /* ignore cr */
3450     }else if (c1== '\n'&&f_prev=='\r' && fold_preserve_f) {
3451         f_prev = '\n';
3452         fold_state=0;  /* ignore cr */
3453     } else if (c1== BS) {
3454         if (f_line>0) f_line--;
3455         fold_state =  1;
3456     } else if (c2==EOF && f_line != 0) {    /* close open last line */
3457             fold_state = '\n';
3458     } else if ((c1=='\n' && !fold_preserve_f)
3459                || ((c1=='\r'||(c1=='\n'&&f_prev!='\r'))
3460                    && fold_preserve_f)) {
3461         /* new line */
3462         if (fold_preserve_f) { 
3463             f_prev = c1;
3464             f_line = 0;
3465             fold_state =  '\r';
3466         } else if ((f_prev == c1 && !fold_preserve_f)
3467                    || (f_prev == '\n' && fold_preserve_f)
3468                    ) {        /* duplicate newline */
3469             if (f_line) {
3470                 f_line = 0;
3471                 fold_state =  '\n';    /* output two newline */
3472             } else {
3473                 f_line = 0;
3474                 fold_state =  1;
3475             }
3476         } else  {
3477             if (f_prev&0x80) {     /* Japanese? */
3478                 f_prev = c1;
3479                 fold_state =  0;       /* ignore given single newline */
3480             } else if (f_prev==' ') {
3481                 fold_state =  0;
3482             } else {
3483                 f_prev = c1;
3484                 if (++f_line<=fold_len) 
3485                     fold_state =  ' ';
3486                 else {
3487                     f_line = 0;
3488                     fold_state =  '\r';        /* fold and output nothing */
3489                 }
3490             }
3491         }
3492     } else if (c1=='\f') {
3493         f_prev = '\n';
3494         if (f_line==0)
3495             fold_state =  1;
3496         f_line = 0;
3497         fold_state =  '\n';            /* output newline and clear */
3498     } else if ( (c2==0  && c1==' ')||
3499                (c2==0  && c1=='\t')||
3500                (c2=='!'&& c1=='!')) {
3501         /* X0208 kankaku or ascii space */
3502             if (f_prev == ' ') {
3503                 fold_state = 0;         /* remove duplicate spaces */
3504             } else {
3505                 f_prev = ' ';    
3506                 if (++f_line<=fold_len) 
3507                     fold_state = ' ';         /* output ASCII space only */
3508                 else {
3509                     f_prev = ' '; f_line = 0;
3510                     fold_state = '\r';        /* fold and output nothing */
3511                 }
3512             }
3513     } else {
3514         prev0 = f_prev; /* we still need this one... , but almost done */
3515         f_prev = c1;
3516         if (c2 || c2==X0201) 
3517             f_prev |= 0x80;  /* this is Japanese */
3518         f_line += char_size(c2,c1);
3519         if (f_line<=fold_len) {   /* normal case */
3520             fold_state = 1;
3521         } else {
3522             if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
3523                 f_line = char_size(c2,c1);
3524                 fold_state =  '\n';       /* We can't wait, do fold now */
3525             } else if (c2==X0201) {
3526             /* simple kinsoku rules  return 1 means no folding  */
3527                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
3528                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
3529                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
3530                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
3531                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
3532                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
3533                 else if (SPACE<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
3534                     f_line = 1;
3535                     fold_state = '\n';/* add one new f_line before this character */
3536                 } else {
3537                     f_line = 1;
3538                     fold_state = '\n';/* add one new f_line before this character */
3539                 }
3540             } else if (c2==0) {
3541                 /* kinsoku point in ASCII */ 
3542                 if (  c1==')'||    /* { [ ( */
3543                      c1==']'||
3544                      c1=='}'||
3545                      c1=='.'||
3546                      c1==','||
3547                      c1=='!'||
3548                      c1=='?'||
3549                      c1=='/'||
3550                      c1==':'||
3551                      c1==';' ) {
3552                     fold_state = 1;
3553                 /* just after special */
3554                 } else if (!is_alnum(prev0)) {
3555                     f_line = char_size(c2,c1);
3556                     fold_state = '\n';
3557                 } else if ((prev0==' ') ||   /* ignored new f_line */
3558                       (prev0=='\n')||        /* ignored new f_line */
3559                       (prev0&0x80)) {        /* X0208 - ASCII */
3560                     f_line = char_size(c2,c1);
3561                     fold_state = '\n';/* add one new f_line before this character */
3562                 } else {
3563                     fold_state = 1;  /* default no fold in ASCII */
3564                 }
3565             } else {
3566                 if (c2=='!') {
3567                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
3568                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
3569                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
3570                     else if (c1=='K')  fold_state = 1; /* \e$B!K\e(B */
3571                     else if (c1=='$')  fold_state = 1; /* \e$B!$\e(B */
3572                     else if (c1=='%')  fold_state = 1; /* \e$B!%\e(B */
3573                     else if (c1=='\'') fold_state = 1; /* \e$B!\\e(B */
3574                     else if (c1=='(')  fold_state = 1; /* \e$B!(\e(B */
3575                     else if (c1==')')  fold_state = 1; /* \e$B!)\e(B */
3576                     else if (c1=='*')  fold_state = 1; /* \e$B!*\e(B */
3577                     else if (c1=='+')  fold_state = 1; /* \e$B!+\e(B */
3578                     else if (c1==',')  fold_state = 1; /* \e$B!,\e(B */
3579                          /* default no fold in kinsoku */
3580                     else { 
3581                         fold_state = '\n';
3582                         f_line = char_size(c2,c1);
3583                         /* add one new f_line before this character */
3584                     }
3585                 } else {
3586                     f_line = char_size(c2,c1);
3587                     fold_state = '\n'; 
3588                     /* add one new f_line before this character */
3589                 }
3590             }
3591         }
3592     }
3593     /* terminator process */
3594     switch(fold_state) {
3595         case '\n': 
3596             (*o_fconv)(0,'\n');
3597             (*o_fconv)(c2,c1);
3598             break;
3599         case 0:    
3600             return;
3601         case '\r': 
3602             (*o_fconv)(0,'\n');
3603             break;
3604         case '\t': 
3605         case ' ': 
3606             (*o_fconv)(0,' ');
3607             break;
3608         default:
3609             (*o_fconv)(c2,c1);
3610     }
3611 }
3612
3613 int z_prev2=0,z_prev1=0;
3614
3615 void
3616 z_conv(c2,c1)
3617 int c2,c1;
3618 {
3619
3620     /* if (c2) c1 &= 0x7f; assertion */
3621
3622     if (x0201_f && z_prev2==X0201) {  /* X0201 */
3623         if (c1==(0xde&0x7f)) { /* \e$BByE@\e(B */
3624             z_prev2=0;
3625             (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
3626             return;
3627         } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) {  /* \e$BH>ByE@\e(B */
3628             z_prev2=0;
3629             (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
3630             return;
3631         } else {
3632             z_prev2=0;
3633             (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
3634         }
3635     }
3636
3637     if (c2==EOF) {
3638         (*o_zconv)(c2,c1);
3639         return;
3640     }
3641
3642     if (x0201_f && c2==X0201) {
3643         if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
3644             /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
3645             z_prev1 = c1; z_prev2 = c2;
3646             return;
3647         } else {
3648             (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
3649             return;
3650         }
3651     }
3652
3653     /* JISX0208 Alphabet */
3654     if (alpha_f && c2 == 0x23 ) {
3655         c2 = 0;
3656     } else if (alpha_f && c2 == 0x21 ) { 
3657     /* JISX0208 Kigou */
3658        if (0x21==c1) {
3659            if (alpha_f&0x2) {
3660                c1 = ' ';
3661                c2 = 0;
3662            } else if (alpha_f&0x4) {
3663                 (*o_zconv)(0,' ');
3664                 (*o_zconv)(0,' ');
3665                 return;
3666            } 
3667        } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
3668            c1 = fv[c1-0x20];
3669            c2 =  0;
3670            if (alpha_f&0x8) {
3671                char *entity = 0;
3672                switch (c1){
3673                  case '>': entity = "&gt;"; break;
3674                  case '<': entity = "&lt;"; break;
3675                  case '\"': entity = "&quot;"; break;
3676                  case '&': entity = "&amp;"; break;
3677                }
3678                if (entity){
3679                    while (*entity) (*o_zconv)(0, *entity++);
3680                    return;
3681                }
3682            }
3683        } 
3684     }
3685     (*o_zconv)(c2,c1);
3686 }
3687
3688
3689 #define rot13(c)  ( \
3690       ( c < 'A' ) ? c: \
3691       (c <= 'M')  ? (c + 13): \
3692       (c <= 'Z')  ? (c - 13): \
3693       (c < 'a')   ? (c): \
3694       (c <= 'm')  ? (c + 13): \
3695       (c <= 'z')  ? (c - 13): \
3696       (c) \
3697 )
3698
3699 #define  rot47(c) ( \
3700       ( c < '!' ) ? c: \
3701       ( c <= 'O' ) ? (c + 47) : \
3702       ( c <= '~' ) ?  (c - 47) : \
3703       c \
3704 )
3705
3706 void
3707 rot_conv(c2,c1)
3708 int c2,c1;
3709 {
3710     if (c2==0 || c2==X0201 || c2==ISO8859_1) {
3711         c1 = rot13(c1);
3712     } else if (c2) {
3713         c1 = rot47(c1);
3714         c2 = rot47(c2);
3715     }
3716     (*o_rot_conv)(c2,c1);
3717 }
3718
3719 void
3720 hira_conv(c2,c1)
3721 int c2,c1;
3722 {
3723     if ((hira_f & 1) && c2==0x25 && 0x20<c1 && c1<0x74) {
3724         c2 = 0x24;
3725     } else if ((hira_f & 2) && c2==0x24 && 0x20<c1 && c1<0x74) {
3726         c2 = 0x25;
3727     } 
3728     (*o_hira_conv)(c2,c1);
3729 }
3730
3731
3732 void
3733 iso2022jp_check_conv(c2,c1)
3734 int    c2, c1;
3735 {
3736     STATIC const int range[RANGE_NUM_MAX][2] = {
3737         {0x222f, 0x2239,},
3738         {0x2242, 0x2249,},
3739         {0x2251, 0x225b,},
3740         {0x226b, 0x2271,},
3741         {0x227a, 0x227d,},
3742         {0x2321, 0x232f,},
3743         {0x233a, 0x2340,},
3744         {0x235b, 0x2360,},
3745         {0x237b, 0x237e,},