OSDN Git Service

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