OSDN Git Service

version strings
[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.67 2005/04/09 21:06:20 rei_furukawa Exp $ */
43 #define NKF_VERSION "2.0.5"
44 #define NKF_RELEASE_DATE "2005-04-10"
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         UTF16LE_INPUT  14
212 #define         UTF16BE_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 = UTF16LE_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     if (*cp++ != '-') 
974         return;
975     while (*cp) {
976         if (p && !*cp) {
977             cp = p;
978             p = 0;
979         }
980         switch (*cp++) {
981         case '-':  /* literal options */
982             if (!*cp) {        /* ignore the rest of arguments */
983                 option_mode = 1;
984                 return;
985             }
986             for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
987                 int j;
988                 p = (unsigned char *)long_option[i].name;
989                 for (j=0;*p && (*p != '=') && *p == cp[j];p++, j++);
990                 if (*p == cp[j]){
991                     p = &cp[j];
992                     break;
993                 }
994                 p = 0;
995             }
996             if (p == 0) return;
997             cp = (unsigned char *)long_option[i].alias;
998             if (!*cp){
999 #ifdef OVERWRITE
1000                 if (strcmp(long_option[i].name, "overwrite") == 0){
1001                     file_out = TRUE;
1002                     overwrite = TRUE;
1003                     continue;
1004                 }
1005 #endif
1006 #ifdef INPUT_OPTION
1007                 if (strcmp(long_option[i].name, "cap-input") == 0){
1008                     cap_f = TRUE;
1009                     continue;
1010                 }
1011                 if (strcmp(long_option[i].name, "url-input") == 0){
1012                     url_f = TRUE;
1013                     continue;
1014                 }
1015 #endif
1016 #ifdef NUMCHAR_OPTION
1017                 if (strcmp(long_option[i].name, "numchar-input") == 0){
1018                     numchar_f = TRUE;
1019                     continue;
1020                 }
1021 #endif
1022 #ifdef CHECK_OPTION
1023                 if (strcmp(long_option[i].name, "no-output") == 0){
1024                     noout_f = TRUE;
1025                     continue;
1026                 }
1027                 if (strcmp(long_option[i].name, "debug") == 0){
1028                     debug_f = TRUE;
1029                     continue;
1030                 }
1031 #endif
1032                 if (strcmp(long_option[i].name, "cp932") == 0){
1033 #ifdef SHIFTJIS_CP932
1034                     cp932_f = TRUE;
1035                     cp932inv_f = TRUE;
1036 #endif
1037 #ifdef UTF8_OUTPUT_ENABLE
1038                     ms_ucs_map_f = TRUE;
1039 #endif
1040                     continue;
1041                 }
1042                 if (strcmp(long_option[i].name, "no-cp932") == 0){
1043 #ifdef SHIFTJIS_CP932
1044                     cp932_f = FALSE;
1045                     cp932inv_f = FALSE;
1046 #endif
1047 #ifdef UTF8_OUTPUT_ENABLE
1048                     ms_ucs_map_f = FALSE;
1049 #endif
1050                     continue;
1051                 }
1052 #ifdef SHIFTJIS_CP932
1053                 if (strcmp(long_option[i].name, "cp932inv") == 0){
1054                     cp932inv_f = TRUE;
1055                     continue;
1056                 }
1057 #endif
1058
1059 #ifdef X0212_ENABLE
1060                 if (strcmp(long_option[i].name, "x0212") == 0){
1061                     x0212_f = TRUE;
1062                     continue;
1063                 }
1064 #endif
1065
1066 #ifdef EXEC_IO
1067                   if (strcmp(long_option[i].name, "exec-in") == 0){
1068                       exec_f = 1;
1069                       return;
1070                   }
1071                   if (strcmp(long_option[i].name, "exec-out") == 0){
1072                       exec_f = -1;
1073                       return;
1074                   }
1075 #endif
1076 #ifdef UTF8_OUTPUT_ENABLE
1077                 if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
1078                     ms_ucs_map_f = TRUE;
1079                     continue;
1080                 }
1081 #endif
1082                 if (strcmp(long_option[i].name, "prefix=") == 0){
1083                     if (*p == '=' && ' ' < p[1] && p[1] < 128){
1084                         for (i = 2; ' ' < p[i] && p[i] < 128; i++){
1085                             prefix_table[p[i]] = p[1];
1086                         }
1087                     }
1088                     continue;
1089                 }
1090             }
1091             continue;
1092         case 'b':           /* buffered mode */
1093             unbuf_f = FALSE;
1094             continue;
1095         case 'u':           /* non bufferd mode */
1096             unbuf_f = TRUE;
1097             continue;
1098         case 't':           /* transparent mode */
1099             nop_f = TRUE;
1100             continue;
1101         case 'j':           /* JIS output */
1102         case 'n':
1103             output_conv = j_oconv;
1104             continue;
1105         case 'e':           /* AT&T EUC output */
1106             output_conv = e_oconv;
1107             continue;
1108         case 's':           /* SJIS output */
1109             output_conv = s_oconv;
1110             continue;
1111         case 'l':           /* ISO8859 Latin-1 support, no conversion */
1112             iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
1113             input_f = LATIN1_INPUT;
1114             continue;
1115         case 'i':           /* Kanji IN ESC-$-@/B */
1116             if (*cp=='@'||*cp=='B') 
1117                 kanji_intro = *cp++;
1118             continue;
1119         case 'o':           /* ASCII IN ESC-(-J/B */
1120             if (*cp=='J'||*cp=='B'||*cp=='H') 
1121                 ascii_intro = *cp++;
1122             continue;
1123         case 'h':
1124             /*  
1125                 bit:1   hira -> kata
1126                 bit:2   kata -> hira
1127             */
1128             if ('9'>= *cp && *cp>='0') 
1129                 hira_f |= (*cp++ -'0');
1130             else 
1131                 hira_f |= 1;
1132             continue;
1133         case 'r':
1134             rot_f = TRUE;
1135             continue;
1136 #if defined(MSDOS) || defined(__OS2__) 
1137         case 'T':
1138             binmode_f = FALSE;
1139             continue;
1140 #endif
1141 #ifndef PERL_XS
1142         case 'V':
1143             version();
1144             exit(1);
1145             break;
1146         case 'v':
1147             usage();
1148             exit(1);
1149             break;
1150 #endif
1151 #ifdef UTF8_OUTPUT_ENABLE
1152         case 'w':           /* UTF-8 output */
1153             if ('1'== cp[0] && '6'==cp[1]) {
1154                 output_conv = w_oconv16; cp+=2;
1155                 if (cp[0]=='L') {
1156                     unicode_bom_f=2; cp++;
1157                     w_oconv16_LE = 1;
1158                     if (cp[0] == '0'){
1159                         unicode_bom_f=1; cp++;
1160                     }
1161                 } else if (cp[0] == 'B') {
1162                     unicode_bom_f=2; cp++;
1163                     if (cp[0] == '0'){
1164                         unicode_bom_f=1; cp++;
1165                     }
1166                 } 
1167             } else if (cp[0] == '8') {
1168                 output_conv = w_oconv; cp++;
1169                 unicode_bom_f=2;
1170                 if (cp[0] == '0'){
1171                     unicode_bom_f=1; cp++;
1172                 }
1173             } else
1174                 output_conv = w_oconv;
1175             continue;
1176 #endif
1177 #ifdef UTF8_INPUT_ENABLE
1178         case 'W':           /* UTF-8 input */
1179             if ('1'== cp[0] && '6'==cp[1]) {
1180                 input_f = UTF16LE_INPUT;
1181                 if (cp[0]=='L') {
1182                     cp++;
1183                 } else if (cp[0] == 'B') {
1184                     cp++;
1185                     input_f = UTF16BE_INPUT;
1186                 }
1187             } else if (cp[0] == '8') {
1188                 cp++;
1189                 input_f = UTF8_INPUT;
1190             } else
1191                 input_f = UTF8_INPUT;
1192             continue;
1193 #endif
1194         /* Input code assumption */
1195         case 'J':   /* JIS input */
1196         case 'E':   /* AT&T EUC input */
1197             input_f = JIS_INPUT;
1198             continue;
1199         case 'S':   /* MS Kanji input */
1200             input_f = SJIS_INPUT;
1201             if (x0201_f==NO_X0201) x0201_f=TRUE;
1202             continue;
1203         case 'Z':   /* Convert X0208 alphabet to asii */
1204             /*  bit:0   Convert X0208
1205                 bit:1   Convert Kankaku to one space
1206                 bit:2   Convert Kankaku to two spaces
1207                 bit:3   Convert HTML Entity
1208             */
1209             if ('9'>= *cp && *cp>='0') 
1210                 alpha_f |= 1<<(*cp++ -'0');
1211             else 
1212                 alpha_f |= TRUE;
1213             continue;
1214         case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
1215             x0201_f = FALSE;    /* No X0201->X0208 conversion */
1216             /* accept  X0201
1217                     ESC-(-I     in JIS, EUC, MS Kanji
1218                     SI/SO       in JIS, EUC, MS Kanji
1219                     SSO         in EUC, JIS, not in MS Kanji
1220                     MS Kanji (0xa0-0xdf) 
1221                output  X0201
1222                     ESC-(-I     in JIS (0x20-0x5f)
1223                     SSO         in EUC (0xa0-0xdf)
1224                     0xa0-0xd    in MS Kanji (0xa0-0xdf) 
1225             */
1226             continue;
1227         case 'X':   /* Assume X0201 kana */
1228             /* Default value is NO_X0201 for EUC/MS-Kanji mix */
1229             x0201_f = TRUE;
1230             continue;
1231         case 'F':   /* prserve new lines */
1232             fold_preserve_f = TRUE;
1233         case 'f':   /* folding -f60 or -f */
1234             fold_f = TRUE;
1235             fold_len = 0;
1236             while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
1237                 fold_len *= 10;
1238                 fold_len += *cp++ - '0';
1239             }
1240             if (!(0<fold_len && fold_len<BUFSIZ)) 
1241                 fold_len = DEFAULT_FOLD;
1242             if (*cp=='-') {
1243                 fold_margin = 0;
1244                 cp++;
1245                 while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
1246                     fold_margin *= 10;
1247                     fold_margin += *cp++ - '0';
1248                 }
1249             }
1250             continue;
1251         case 'm':   /* MIME support */
1252             /* mime_decode_f = TRUE; */ /* this has too large side effects... */
1253             if (*cp=='B'||*cp=='Q') {
1254                 mime_decode_mode = *cp++;
1255                 mimebuf_f = FIXED_MIME;
1256             } else if (*cp=='N') {
1257                 mime_f = TRUE; cp++;
1258             } else if (*cp=='S') {
1259                 mime_f = STRICT_MIME; cp++;
1260             } else if (*cp=='0') {
1261                 mime_decode_f = FALSE;
1262                 mime_f = FALSE; cp++;
1263             }
1264             continue;
1265         case 'M':   /* MIME output */
1266             if (*cp=='B') {
1267                 mimeout_mode = 'B';
1268                 mimeout_f = FIXED_MIME; cp++;
1269             } else if (*cp=='Q') {
1270                 mimeout_mode = 'Q';
1271                 mimeout_f = FIXED_MIME; cp++;
1272             } else {
1273                 mimeout_f = TRUE;
1274             }
1275             continue;
1276         case 'B':   /* Broken JIS support */
1277             /*  bit:0   no ESC JIS
1278                 bit:1   allow any x on ESC-(-x or ESC-$-x
1279                 bit:2   reset to ascii on NL
1280             */
1281             if ('9'>= *cp && *cp>='0') 
1282                 broken_f |= 1<<(*cp++ -'0');
1283             else 
1284                 broken_f |= TRUE;
1285             continue;
1286 #ifndef PERL_XS
1287         case 'O':/* for Output file */
1288             file_out = TRUE;
1289             continue;
1290 #endif
1291         case 'c':/* add cr code */
1292             crmode_f = CRLF;
1293             continue;
1294         case 'd':/* delete cr code */
1295             crmode_f = NL;
1296             continue;
1297         case 'I':   /* ISO-2022-JP output */
1298             iso2022jp_f = TRUE;
1299             continue;
1300         case 'L':  /* line mode */
1301             if (*cp=='u') {         /* unix */
1302                 crmode_f = NL; cp++;
1303             } else if (*cp=='m') { /* mac */
1304                 crmode_f = CR; cp++;
1305             } else if (*cp=='w') { /* windows */
1306                 crmode_f = CRLF; cp++;
1307             } else if (*cp=='0') { /* no conversion  */
1308                 crmode_f = 0; cp++;
1309             }
1310             continue;
1311         case 'g':
1312 #ifndef PERL_XS
1313             guess_f = TRUE;
1314 #endif
1315             continue;
1316         case ' ':    
1317         /* module muliple options in a string are allowed for Perl moudle  */
1318             while(*cp && *cp!='-') cp++;
1319             if(*cp=='-') cp++;
1320             continue;
1321         default:
1322             /* bogus option but ignored */
1323             continue;
1324         }
1325     }
1326 }
1327
1328 #ifdef ANSI_C_PROTOTYPE
1329 struct input_code * find_inputcode_byfunc(int (*iconv_func)(int c2,int c1,int c0))
1330 #else
1331 struct input_code * find_inputcode_byfunc(iconv_func)
1332      int (*iconv_func)();
1333 #endif
1334 {
1335     if (iconv_func){
1336         struct input_code *p = input_code_list;
1337         while (p->name){
1338             if (iconv_func == p->iconv_func){
1339                 return p;
1340             }
1341             p++;
1342         }
1343     }
1344     return 0;
1345 }
1346
1347 #ifdef CHECK_OPTION
1348 static int (*iconv_for_check)() = 0;
1349 #endif
1350
1351 #ifdef ANSI_C_PROTOTYPE
1352 void set_iconv(int f, int (*iconv_func)(int c2,int c1,int c0))
1353 #else
1354 void set_iconv(f, iconv_func)
1355      int f;
1356      int (*iconv_func)();
1357 #endif
1358 {
1359 #ifdef INPUT_CODE_FIX
1360     if (f || !input_f)
1361 #endif
1362         if (estab_f != f){
1363             estab_f = f;
1364         }
1365
1366     if (iconv_func
1367 #ifdef INPUT_CODE_FIX
1368         && (f == -TRUE || !input_f) /* -TRUE means "FORCE" */
1369 #endif
1370         ){
1371         iconv = iconv_func;
1372     }
1373 #ifdef CHECK_OPTION
1374     if (estab_f && iconv_for_check != iconv){
1375         struct input_code *p = find_inputcode_byfunc(iconv);
1376         if (p){
1377             set_input_codename(p->name);
1378             debug(input_codename);
1379         }
1380         iconv_for_check = iconv;
1381     }
1382 #endif
1383 }
1384
1385 #define SCORE_L2       (1)                   /* \e$BBh\e(B2\e$B?e=`4A;z\e(B */
1386 #define SCORE_KANA     (SCORE_L2 << 1)       /* \e$B$$$o$f$kH>3Q%+%J\e(B */
1387 #define SCORE_DEPEND   (SCORE_KANA << 1)     /* \e$B5!<o0MB8J8;z\e(B */
1388 #ifdef SHIFTJIS_CP932
1389 #define SCORE_CP932    (SCORE_DEPEND << 1)   /* CP932 \e$B$K$h$kFI$_49$(\e(B */
1390 #define SCORE_NO_EXIST (SCORE_CP932 << 1)    /* \e$BB8:_$7$J$$J8;z\e(B */
1391 #else
1392 #define SCORE_NO_EXIST (SCORE_DEPEND << 1)   /* \e$BB8:_$7$J$$J8;z\e(B */
1393 #endif
1394 #define SCORE_iMIME    (SCORE_NO_EXIST << 1) /* MIME \e$B$K$h$k;XDj\e(B */
1395 #define SCORE_ERROR    (SCORE_iMIME << 1) /* \e$B%(%i!<\e(B */
1396
1397 #define SCORE_INIT (SCORE_iMIME)
1398
1399 int score_table_A0[] = {
1400     0, 0, 0, 0,
1401     0, 0, 0, 0,
1402     0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1403     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
1404 };
1405
1406 int score_table_F0[] = {
1407     SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
1408     SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
1409     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
1410     SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
1411 };
1412
1413 void set_code_score(ptr, score)
1414      struct input_code *ptr;
1415      int score;
1416 {
1417     if (ptr){
1418         ptr->score |= score;
1419     }
1420 }
1421
1422 void clr_code_score(ptr, score)
1423      struct input_code *ptr;
1424      int score;
1425 {
1426     if (ptr){
1427         ptr->score &= ~score;
1428     }
1429 }
1430
1431 void code_score(ptr)
1432      struct input_code *ptr;
1433 {
1434     int c2 = ptr->buf[0];
1435     int c1 = ptr->buf[1];
1436     if (c2 < 0){
1437         set_code_score(ptr, SCORE_ERROR);
1438     }else if (c2 == SSO){
1439         set_code_score(ptr, SCORE_KANA);
1440 #ifdef UTF8_OUTPUT_ENABLE
1441     }else if (!e2w_conv(c2, c1)){
1442         set_code_score(ptr, SCORE_NO_EXIST);
1443 #endif
1444     }else if ((c2 & 0x70) == 0x20){
1445         set_code_score(ptr, score_table_A0[c2 & 0x0f]);
1446     }else if ((c2 & 0x70) == 0x70){
1447         set_code_score(ptr, score_table_F0[c2 & 0x0f]);
1448     }else if ((c2 & 0x70) >= 0x50){
1449         set_code_score(ptr, SCORE_L2);
1450     }
1451 }
1452
1453 void status_disable(ptr)
1454 struct input_code *ptr;
1455 {
1456     ptr->stat = -1;
1457     ptr->buf[0] = -1;
1458     code_score(ptr);
1459     if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
1460 }
1461
1462 void status_push_ch(ptr, c)
1463      struct input_code *ptr;
1464      int c;
1465 {
1466     ptr->buf[ptr->index++] = c;
1467 }
1468
1469 void status_clear(ptr)
1470      struct input_code *ptr;
1471 {
1472     ptr->stat = 0;
1473     ptr->index = 0;
1474 }
1475
1476 void status_reset(ptr)
1477      struct input_code *ptr;
1478 {
1479     status_clear(ptr);
1480     ptr->score = SCORE_INIT;
1481 }
1482
1483 void status_reinit(ptr)
1484      struct input_code *ptr;
1485 {
1486     status_reset(ptr);
1487     ptr->_file_stat = 0;
1488 }
1489
1490 void status_check(ptr, c)
1491      struct input_code *ptr;
1492      int c;
1493 {
1494     if (c <= DEL && estab_f){
1495         status_reset(ptr);
1496     }
1497 }
1498
1499 void s_status(ptr, c)
1500      struct input_code *ptr;
1501      int c;
1502 {
1503     switch(ptr->stat){
1504       case -1:
1505           status_check(ptr, c);
1506           break;
1507       case 0:
1508           if (c <= DEL){
1509               break;
1510 #ifdef NUMCHAR_OPTION
1511           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1512               break;
1513 #endif
1514           }else if (0xa1 <= c && c <= 0xdf){
1515               status_push_ch(ptr, SSO);
1516               status_push_ch(ptr, c);
1517               code_score(ptr);
1518               status_clear(ptr);
1519           }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xef)){
1520               ptr->stat = 1;
1521               status_push_ch(ptr, c);
1522 #ifdef SHIFTJIS_CP932
1523           }else if (cp932_f
1524                     && CP932_TABLE_BEGIN <= c && c <= CP932_TABLE_END){
1525               ptr->stat = 2;
1526               status_push_ch(ptr, c);
1527 #endif /* SHIFTJIS_CP932 */
1528 #ifdef X0212_ENABLE
1529           }else if (x0212_f && 0xf0 <= c && c <= 0xfc){
1530               ptr->stat = 1;
1531               status_push_ch(ptr, c);
1532 #endif /* X0212_ENABLE */
1533           }else{
1534               status_disable(ptr);
1535           }
1536           break;
1537       case 1:
1538           if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1539               status_push_ch(ptr, c);
1540               s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
1541               code_score(ptr);
1542               status_clear(ptr);
1543           }else{
1544               status_disable(ptr);
1545           }
1546           break;
1547       case 2:
1548 #ifdef SHIFTJIS_CP932
1549           if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
1550               status_push_ch(ptr, c);
1551               if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0){
1552                   set_code_score(ptr, SCORE_CP932);
1553                   status_clear(ptr);
1554                   break;
1555               }
1556           }
1557 #endif /* SHIFTJIS_CP932 */
1558 #ifndef X0212_ENABLE
1559           status_disable(ptr);
1560           break;
1561 #endif
1562     }
1563 }
1564
1565 void e_status(ptr, c)
1566      struct input_code *ptr;
1567      int c;
1568 {
1569     switch (ptr->stat){
1570       case -1:
1571           status_check(ptr, c);
1572           break;
1573       case 0:
1574           if (c <= DEL){
1575               break;
1576 #ifdef NUMCHAR_OPTION
1577           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1578               break;
1579 #endif
1580           }else if (SSO == c || (0xa1 <= c && c <= 0xfe)){
1581               ptr->stat = 1;
1582               status_push_ch(ptr, c);
1583 #ifdef X0212_ENABLE
1584           }else if (0x8f == c){
1585               ptr->stat = 2;
1586               status_push_ch(ptr, c);
1587 #endif /* X0212_ENABLE */
1588           }else{
1589               status_disable(ptr);
1590           }
1591           break;
1592       case 1:
1593           if (0xa1 <= c && c <= 0xfe){
1594               status_push_ch(ptr, c);
1595               code_score(ptr);
1596               status_clear(ptr);
1597           }else{
1598               status_disable(ptr);
1599           }
1600           break;
1601 #ifdef X0212_ENABLE
1602       case 2:
1603           if (0xa1 <= c && c <= 0xfe){
1604               ptr->stat = 1;
1605               status_push_ch(ptr, c);
1606           }else{
1607               status_disable(ptr);
1608           }
1609 #endif /* X0212_ENABLE */
1610     }
1611 }
1612
1613 #ifdef UTF8_INPUT_ENABLE
1614 void w16_status(ptr, c)
1615      struct input_code *ptr;
1616      int c;
1617 {
1618     switch (ptr->stat){
1619       case -1:
1620           break;
1621       case 0:
1622           if (ptr->_file_stat == 0){
1623               if (c == 0xfe || c == 0xff){
1624                   ptr->stat = c;
1625                   status_push_ch(ptr, c);
1626                   ptr->_file_stat = 1;
1627               }else{
1628                   status_disable(ptr);
1629                   ptr->_file_stat = -1;
1630               }
1631           }else if (ptr->_file_stat > 0){
1632               ptr->stat = 1;
1633               status_push_ch(ptr, c);
1634           }else if (ptr->_file_stat < 0){
1635               status_disable(ptr);
1636           }
1637           break;
1638
1639       case 1:
1640           if (c == EOF){
1641               status_disable(ptr);
1642               ptr->_file_stat = -1;
1643           }else{
1644               status_push_ch(ptr, c);
1645               status_clear(ptr);
1646           }
1647           break;
1648
1649       case 0xfe:
1650       case 0xff:
1651           if (ptr->stat != c && (c == 0xfe || c == 0xff)){
1652               status_push_ch(ptr, c);
1653               status_clear(ptr);
1654           }else{
1655               status_disable(ptr);
1656               ptr->_file_stat = -1;
1657           }
1658           break;
1659     }
1660 }
1661
1662 void w_status(ptr, c)
1663      struct input_code *ptr;
1664      int c;
1665 {
1666     switch (ptr->stat){
1667       case -1:
1668           status_check(ptr, c);
1669           break;
1670       case 0:
1671           if (c <= DEL){
1672               break;
1673 #ifdef NUMCHAR_OPTION
1674           }else if ((c & CLASS_MASK) == CLASS_UTF16){
1675               break;
1676 #endif
1677           }else if (0xc0 <= c && c <= 0xdf){
1678               ptr->stat = 1;
1679               status_push_ch(ptr, c);
1680           }else if (0xe0 <= c && c <= 0xef){
1681               ptr->stat = 2;
1682               status_push_ch(ptr, c);
1683           }else{
1684               status_disable(ptr);
1685           }
1686           break;
1687       case 1:
1688       case 2:
1689           if (0x80 <= c && c <= 0xbf){
1690               status_push_ch(ptr, c);
1691               if (ptr->index > ptr->stat){
1692                   int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
1693                              && ptr->buf[2] == 0xbf);
1694                   w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
1695                            &ptr->buf[0], &ptr->buf[1]);
1696                   if (!bom){
1697                       code_score(ptr);
1698                   }
1699                   status_clear(ptr);
1700               }
1701           }else{
1702               status_disable(ptr);
1703           }
1704           break;
1705     }
1706 }
1707 #endif
1708
1709 void
1710 code_status(c)
1711      int c;
1712 {
1713     int action_flag = 1;
1714     struct input_code *result = 0;
1715     struct input_code *p = input_code_list;
1716     while (p->name){
1717         (p->status_func)(p, c);
1718         if (p->stat > 0){
1719             action_flag = 0;
1720         }else if(p->stat == 0){
1721             if (result){
1722                 action_flag = 0;
1723             }else{
1724                 result = p;
1725             }
1726         }
1727         ++p;
1728     }
1729
1730     if (action_flag){
1731         if (result && !estab_f){
1732             set_iconv(TRUE, result->iconv_func);
1733         }else if (c <= DEL){
1734             struct input_code *ptr = input_code_list;
1735             while (ptr->name){
1736                 status_reset(ptr);
1737                 ++ptr;
1738             }
1739         }
1740     }
1741 }
1742
1743 #ifndef WIN32DLL
1744 int 
1745 std_getc(f)
1746 FILE *f;
1747 {
1748     if (std_gc_ndx){
1749         return std_gc_buf[--std_gc_ndx];
1750     }
1751     return getc(f);
1752 }
1753 #endif /*WIN32DLL*/
1754
1755 int 
1756 std_ungetc(c,f)
1757 int c;
1758 FILE *f;
1759 {
1760     if (std_gc_ndx == STD_GC_BUFSIZE){
1761         return EOF;
1762     }
1763     std_gc_buf[std_gc_ndx++] = c;
1764     return c;
1765 }
1766
1767 #ifndef WIN32DLL
1768 void 
1769 std_putc(c)
1770 int c;
1771 {
1772     if(c!=EOF)
1773       putchar(c);
1774 }
1775 #endif /*WIN32DLL*/
1776
1777 int
1778 noconvert(f)
1779     FILE  *f;
1780 {
1781     int    c;
1782
1783     while ((c = (*i_getc)(f)) != EOF)
1784       (*o_putc)(c);
1785     return 1;
1786 }
1787
1788
1789 void
1790 module_connection()
1791 {
1792     oconv = output_conv; 
1793     o_putc = std_putc;
1794
1795     /* replace continucation module, from output side */
1796
1797     /* output redicrection */
1798 #ifdef CHECK_OPTION
1799     if (noout_f || guess_f){
1800         o_putc = no_putc;
1801     }
1802 #endif
1803     if (mimeout_f) {
1804         o_mputc = o_putc;
1805         o_putc = mime_putc;
1806         if (mimeout_f == TRUE) {
1807             o_base64conv = oconv; oconv = base64_conv;
1808         }
1809         /* base64_count = 0; */
1810     }
1811
1812     if (crmode_f) {
1813         o_crconv = oconv; oconv = cr_conv;
1814     }
1815     if (rot_f) {
1816         o_rot_conv = oconv; oconv = rot_conv;
1817     }
1818     if (iso2022jp_f) {
1819         o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
1820     }
1821     if (hira_f) {
1822         o_hira_conv = oconv; oconv = hira_conv;
1823     }
1824     if (fold_f) {
1825         o_fconv = oconv; oconv = fold_conv;
1826         f_line = 0;
1827     }
1828     if (alpha_f || x0201_f) {
1829         o_zconv = oconv; oconv = z_conv;
1830     }
1831
1832     i_getc = std_getc;
1833     i_ungetc = std_ungetc;
1834     /* input redicrection */
1835 #ifdef INPUT_OPTION
1836     if (cap_f){
1837         i_cgetc = i_getc; i_getc = cap_getc;
1838         i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
1839     }
1840     if (url_f){
1841         i_ugetc = i_getc; i_getc = url_getc;
1842         i_uungetc = i_ungetc; i_ungetc= url_ungetc;
1843     }
1844 #endif
1845 #ifdef NUMCHAR_OPTION
1846     if (numchar_f){
1847         i_ngetc = i_getc; i_getc = numchar_getc;
1848         i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
1849     }
1850 #endif
1851     if (mime_f && mimebuf_f==FIXED_MIME) {
1852         i_mgetc = i_getc; i_getc = mime_getc;
1853         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
1854     }
1855     if (broken_f & 1) {
1856         i_bgetc = i_getc; i_getc = broken_getc;
1857         i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
1858     }
1859     if (input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
1860         set_iconv(-TRUE, e_iconv);
1861     } else if (input_f == SJIS_INPUT) {
1862         set_iconv(-TRUE, s_iconv);
1863 #ifdef UTF8_INPUT_ENABLE
1864     } else if (input_f == UTF8_INPUT) {
1865         set_iconv(-TRUE, w_iconv);
1866     } else if (input_f == UTF16LE_INPUT) {
1867         set_iconv(-TRUE, w_iconv16);
1868 #endif
1869     } else {
1870         set_iconv(FALSE, e_iconv);
1871     }
1872
1873     {
1874         struct input_code *p = input_code_list;
1875         while (p->name){
1876             status_reinit(p++);
1877         }
1878     }
1879 }
1880
1881 /*
1882    Conversion main loop. Code detection only. 
1883  */
1884
1885 int
1886 kanji_convert(f)
1887     FILE  *f;
1888 {
1889     int    c1,
1890                     c2, c3;
1891     int is_8bit = FALSE;
1892
1893     module_connection();
1894     c2 = 0;
1895
1896
1897     input_mode = ASCII;
1898     output_mode = ASCII;
1899     shift_mode = FALSE;
1900
1901 #define NEXT continue      /* no output, get next */
1902 #define SEND ;             /* output c1 and c2, get next */
1903 #define LAST break         /* end of loop, go closing  */
1904
1905     while ((c1 = (*i_getc)(f)) != EOF) {
1906         code_status(c1);
1907         if (c2) {
1908             /* second byte */
1909             if (c2 > DEL) {
1910                 /* in case of 8th bit is on */
1911                 if (!estab_f&&!mime_decode_mode) {
1912                     /* in case of not established yet */
1913                     /* It is still ambiguious */
1914                     if (h_conv(f, c2, c1)==EOF) 
1915                         LAST;
1916                     else 
1917                         c2 = 0;
1918                     NEXT;
1919                 } else
1920                     /* in case of already established */
1921                     if (c1 < AT) {
1922                         /* ignore bogus code */
1923                         c2 = 0;
1924                         NEXT;
1925                     } else
1926                         SEND;
1927             } else
1928                 /* second byte, 7 bit code */
1929                 /* it might be kanji shitfted */
1930                 if ((c1 == DEL) || (c1 <= SPACE)) {
1931                     /* ignore bogus first code */
1932                     c2 = 0;
1933                     NEXT;
1934                 } else
1935                     SEND;
1936         } else {
1937             /* first byte */
1938             if (
1939 #ifdef UTF8_INPUT_ENABLE
1940                 iconv == w_iconv16
1941 #else
1942                 0
1943 #endif
1944                 ) {
1945                 c2 = c1;
1946                 c1 = (*i_getc)(f);
1947                 SEND;
1948 #ifdef NUMCHAR_OPTION
1949             } else if ((c1 & CLASS_MASK) == CLASS_UTF16){
1950                 SEND;
1951 #endif
1952             } else if (c1 > DEL) {
1953                 /* 8 bit code */
1954                 if (!estab_f && !iso8859_f) {
1955                     /* not established yet */
1956                     if (!is_8bit) is_8bit = TRUE;
1957                     c2 = c1;
1958                     NEXT;
1959                 } else { /* estab_f==TRUE */
1960                     if (iso8859_f) {
1961                         c2 = ISO8859_1;
1962                         c1 &= 0x7f;
1963                         SEND;
1964                     } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
1965                         /* SJIS X0201 Case... */
1966                         if(iso2022jp_f && x0201_f==NO_X0201) {
1967                             (*oconv)(GETA1, GETA2);
1968                             NEXT;
1969                         } else {
1970                             c2 = X0201;
1971                             c1 &= 0x7f;
1972                             SEND;
1973                         }
1974                     } else if (c1==SSO && iconv != s_iconv) {
1975                         /* EUC X0201 Case */
1976                         c1 = (*i_getc)(f);  /* skip SSO */
1977                         code_status(c1);
1978                         if (SSP<=c1 && c1<0xe0) {
1979                             if(iso2022jp_f &&  x0201_f==NO_X0201) {
1980                                 (*oconv)(GETA1, GETA2);
1981                                 NEXT;
1982                             } else {
1983                                 c2 = X0201;
1984                                 c1 &= 0x7f;
1985                                 SEND;
1986                             }
1987                         } else  { /* bogus code, skip SSO and one byte */
1988                             NEXT;
1989                         }
1990                     } else {
1991                        /* already established */
1992                        c2 = c1;
1993                        NEXT;
1994                     }
1995                 }
1996             } else if ((c1 > SPACE) && (c1 != DEL)) {
1997                 /* in case of Roman characters */
1998                 if (shift_mode) { 
1999                     /* output 1 shifted byte */
2000                     if (iso8859_f) {
2001                         c2 = ISO8859_1;
2002                         SEND;
2003                     } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
2004                       /* output 1 shifted byte */
2005                         if(iso2022jp_f && x0201_f==NO_X0201) {
2006                             (*oconv)(GETA1, GETA2);
2007                             NEXT;
2008                         } else {
2009                             c2 = X0201;
2010                             SEND;
2011                         }
2012                     } else {
2013                         /* look like bogus code */
2014                         NEXT;
2015                     }
2016                 } else if (input_mode == X0208) {
2017                     /* in case of Kanji shifted */
2018                     c2 = c1;
2019                     NEXT;
2020                 } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
2021                     /* Check MIME code */
2022                     if ((c1 = (*i_getc)(f)) == EOF) {
2023                         (*oconv)(0, '=');
2024                         LAST;
2025                     } else if (c1 == '?') {
2026                         /* =? is mime conversion start sequence */
2027                         if(mime_f == STRICT_MIME) {
2028                             /* check in real detail */
2029                             if (mime_begin_strict(f) == EOF) 
2030                                 LAST;
2031                             else
2032                                 NEXT;
2033                         } else if (mime_begin(f) == EOF) 
2034                             LAST;
2035                         else
2036                             NEXT;
2037                     } else {
2038                         (*oconv)(0, '=');
2039                         (*i_ungetc)(c1,f);
2040                         NEXT;
2041                     }
2042                 } else {
2043                     /* normal ASCII code */ 
2044                     SEND;
2045                 }
2046             } else if (c1 == SI) {
2047                 shift_mode = FALSE; 
2048                 NEXT;
2049             } else if (c1 == SO) {
2050                 shift_mode = TRUE; 
2051                 NEXT;
2052             } else if (c1 == ESC ) {
2053                 if ((c1 = (*i_getc)(f)) == EOF) {
2054                     /*  (*oconv)(0, ESC); don't send bogus code */
2055                     LAST;
2056                 } else if (c1 == '$') {
2057                     if ((c1 = (*i_getc)(f)) == EOF) {
2058                         /*
2059                         (*oconv)(0, ESC); don't send bogus code 
2060                         (*oconv)(0, '$'); */
2061                         LAST;
2062                     } else if (c1 == '@'|| c1 == 'B') {
2063                         /* This is kanji introduction */
2064                         input_mode = X0208;
2065                         shift_mode = FALSE;
2066                         set_input_codename("ISO-2022-JP");
2067                         debug(input_codename);
2068                         NEXT;
2069                     } else if (c1 == '(') {
2070                         if ((c1 = (*i_getc)(f)) == EOF) {
2071                             /* don't send bogus code 
2072                             (*oconv)(0, ESC);
2073                             (*oconv)(0, '$');
2074                             (*oconv)(0, '(');
2075                                 */
2076                             LAST;
2077                         } else if (c1 == '@'|| c1 == 'B') {
2078                             /* This is kanji introduction */
2079                             input_mode = X0208;
2080                             shift_mode = FALSE;
2081                             NEXT;
2082 #ifdef X0212_ENABLE
2083                         } else if (c1 == 'D'){
2084                             input_mode = X0212;
2085                             shift_mode = FALSE;
2086                             NEXT;
2087 #endif /* X0212_ENABLE */
2088                         } else {
2089                             /* could be some special code */
2090                             (*oconv)(0, ESC);
2091                             (*oconv)(0, '$');
2092                             (*oconv)(0, '(');
2093                             (*oconv)(0, c1);
2094                             NEXT;
2095                         }
2096                     } else if (broken_f&0x2) {
2097                         /* accept any ESC-(-x as broken code ... */
2098                         input_mode = X0208;
2099                         shift_mode = FALSE;
2100                         NEXT;
2101                     } else {
2102                         (*oconv)(0, ESC);
2103                         (*oconv)(0, '$');
2104                         (*oconv)(0, c1);
2105                         NEXT;
2106                     }
2107                 } else if (c1 == '(') {
2108                     if ((c1 = (*i_getc)(f)) == EOF) {
2109                         /* don't send bogus code 
2110                         (*oconv)(0, ESC);
2111                         (*oconv)(0, '('); */
2112                         LAST;
2113                     } else {
2114                         if (c1 == 'I') {
2115                             /* This is X0201 kana introduction */
2116                             input_mode = X0201; shift_mode = X0201;
2117                             NEXT;
2118                         } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
2119                             /* This is X0208 kanji introduction */
2120                             input_mode = ASCII; shift_mode = FALSE;
2121                             NEXT;
2122                         } else if (broken_f&0x2) {
2123                             input_mode = ASCII; shift_mode = FALSE;
2124                             NEXT;
2125                         } else {
2126                             (*oconv)(0, ESC);
2127                             (*oconv)(0, '(');
2128                             /* maintain various input_mode here */
2129                             SEND;
2130                         }
2131                     }
2132                } else if ( c1 == 'N' || c1 == 'n' ){
2133                    /* SS2 */
2134                    c3 = (*i_getc)(f);  /* skip SS2 */
2135                    if ( (SPACE<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
2136                        c1 = c3;
2137                        c2 = X0201;
2138                        SEND;
2139                    }else{
2140                        (*i_ungetc)(c3, f);
2141                        /* lonely ESC  */
2142                        (*oconv)(0, ESC);
2143                        SEND;
2144                    }
2145                 } else {
2146                     /* lonely ESC  */
2147                     (*oconv)(0, ESC);
2148                     SEND;
2149                 }
2150             } else if ((c1 == NL || c1 == CR) && broken_f&4) {
2151                 input_mode = ASCII; set_iconv(FALSE, 0);
2152                 SEND;
2153             } else if (c1 == NL && mime_decode_f && !mime_decode_mode ) {
2154                 if ((c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
2155                     i_ungetc(SPACE,f);
2156                     continue;
2157                 } else {
2158                     i_ungetc(c1,f);
2159                 }
2160                 c1 = NL;
2161                 SEND;
2162             } else if (c1 == CR && mime_decode_f && !mime_decode_mode ) {
2163                 if ((c1=(*i_getc)(f))!=EOF) {
2164                     if (c1==SPACE) {
2165                         i_ungetc(SPACE,f);
2166                         continue;
2167                     } else if (c1 == NL && (c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
2168                         i_ungetc(SPACE,f);
2169                         continue;
2170                     } else {
2171                         i_ungetc(c1,f);
2172                     }
2173                     i_ungetc(NL,f);
2174                 } else {
2175                     i_ungetc(c1,f);
2176                 }
2177                 c1 = CR;
2178                 SEND;
2179             } else 
2180                 SEND;
2181         }
2182         /* send: */
2183         if (input_mode == X0208) 
2184             (*oconv)(c2, c1);  /* this is JIS, not SJIS/EUC case */
2185 #ifdef X0212_ENABLE
2186         else if (input_mode == X0212) 
2187             (*oconv)((0x8f << 8) | c2, c1);
2188 #endif /* X0212_ENABLE */
2189         else if (input_mode) 
2190             (*oconv)(input_mode, c1);  /* other special case */
2191         else if ((*iconv)(c2, c1, 0) < 0){  /* can be EUC/SJIS */
2192             int c0 = (*i_getc)(f);
2193             if (c0 != EOF){
2194                 code_status(c0);
2195                 (*iconv)(c2, c1, c0);
2196             }
2197         }
2198
2199         c2 = 0;
2200         continue;
2201         /* goto next_word */
2202     }
2203
2204     /* epilogue */
2205     (*iconv)(EOF, 0, 0);
2206     if (!is_inputcode_set)
2207     {
2208         if (is_8bit) {
2209             struct input_code *p = input_code_list;
2210             struct input_code *result = p;
2211             while (p->name){
2212                 if (p->score < result->score) result = p;
2213                 ++p;
2214             }
2215             set_input_codename(result->name);
2216         }
2217     }
2218     return 1;
2219 }
2220
2221 int
2222 h_conv(f, c2, c1)
2223     FILE  *f;
2224     int    c1,
2225                     c2;
2226 {
2227     int    wc,c3;
2228
2229
2230     /** it must NOT be in the kanji shifte sequence      */
2231     /** it must NOT be written in JIS7                   */
2232     /** and it must be after 2 byte 8bit code            */
2233
2234     hold_count = 0;
2235     push_hold_buf(c2);
2236     push_hold_buf(c1);
2237     c2 = 0;
2238
2239     while ((c1 = (*i_getc)(f)) != EOF) {
2240         if (c1 == ESC){
2241             (*i_ungetc)(c1,f);
2242             break;
2243         }
2244         code_status(c1);
2245         if (push_hold_buf(c1) == EOF || estab_f){
2246             break;
2247         }
2248     }
2249
2250     if (!estab_f){
2251         struct input_code *p = input_code_list;
2252         struct input_code *result = p;
2253         if (c1 == EOF){
2254             code_status(c1);
2255         }
2256         while (p->name){
2257             if (p->score < result->score){
2258                 result = p;
2259             }
2260             ++p;
2261         }
2262         set_iconv(FALSE, result->iconv_func);
2263     }
2264
2265
2266     /** now,
2267      ** 1) EOF is detected, or
2268      ** 2) Code is established, or
2269      ** 3) Buffer is FULL (but last word is pushed)
2270      **
2271      ** in 1) and 3) cases, we continue to use
2272      ** Kanji codes by oconv and leave estab_f unchanged.
2273      **/
2274
2275     c3=c1;
2276     wc = 0;
2277     while (wc < hold_count){
2278         c2 = hold_buf[wc++];
2279         if (c2 <= DEL
2280 #ifdef NUMCHAR_OPTION
2281             || (c2 & CLASS_MASK) == CLASS_UTF16
2282 #endif
2283             ){
2284             (*iconv)(0, c2, 0);
2285             continue;
2286         }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
2287             (*iconv)(X0201, c2, 0);
2288             continue;
2289         }
2290         if (wc < hold_count){
2291             c1 = hold_buf[wc++];
2292         }else{
2293             c1 = (*i_getc)(f);
2294             if (c1 == EOF){
2295                 c3 = EOF;
2296                 break;
2297             }
2298             code_status(c1);
2299         }
2300         if ((*iconv)(c2, c1, 0) < 0){
2301             int c0;
2302             if (wc < hold_count){
2303                 c0 = hold_buf[wc++];
2304             }else{
2305                 c0 = (*i_getc)(f);
2306                 if (c0 == EOF){
2307                     c3 = EOF;
2308                     break;
2309                 }
2310                 code_status(c0);
2311             }
2312             (*iconv)(c2, c1, c0);
2313             c1 = c0;
2314         }
2315     }
2316     return c3;
2317 }
2318
2319
2320
2321 int
2322 push_hold_buf(c2)
2323      int             c2;
2324 {
2325     if (hold_count >= HOLD_SIZE*2)
2326         return (EOF);
2327     hold_buf[hold_count++] = c2;
2328     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
2329 }
2330
2331 int s2e_conv(c2, c1, p2, p1)
2332      int c2, c1;
2333      int *p2, *p1;
2334 {
2335     int val;
2336 #ifdef SHIFTJIS_CP932
2337     if (cp932_f && CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END){
2338         extern unsigned short shiftjis_cp932[3][189];
2339         val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
2340         if (val){
2341             c2 = val >> 8;
2342             c1 = val & 0xff;
2343         }
2344     }
2345 #endif /* SHIFTJIS_CP932 */
2346 #ifdef X0212_ENABLE
2347     if (x0212_f && 0xfa <= c2 && c2 <= 0xfc){
2348         extern unsigned short shiftjis_x0212[3][189];
2349         val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
2350         if (val){
2351             if (val & 0x8000){
2352                 c2 = (0x8f << 8) | (val >> 8);
2353                 c1 = val & 0xff;
2354             }else{
2355                 c2 = val >> 8;
2356                 c1 = val & 0xff;
2357             }
2358             if (p2) *p2 = c2;
2359             if (p1) *p1 = c1;
2360             return 0;
2361         }
2362     }
2363 #endif
2364     c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
2365     if (c1 < 0x9f)
2366         c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
2367     else {
2368         c1 = c1 - 0x7e;
2369         c2++;
2370     }
2371
2372 #ifdef X0212_ENABLE
2373     if (x0212_f){
2374         c2 = x0212_unshift(c2);
2375     }
2376 #endif
2377     if (p2) *p2 = c2;
2378     if (p1) *p1 = c1;
2379     return 0;
2380 }
2381
2382 int
2383 s_iconv(c2, c1, c0)
2384     int    c2,
2385                     c1, c0;
2386 {
2387     if (c2 == X0201) {
2388         c1 &= 0x7f;
2389     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2390         /* NOP */
2391     } else {
2392         int ret = s2e_conv(c2, c1, &c2, &c1);
2393         if (ret) return ret;
2394     }
2395     (*oconv)(c2, c1);
2396     return 0;
2397 }
2398
2399 int
2400 e_iconv(c2, c1, c0)
2401     int    c2,
2402                     c1, c0;
2403 {
2404     if (c2 == X0201) {
2405         c1 &= 0x7f;
2406 #ifdef X0212_ENABLE
2407     }else if (c2 == 0x8f){
2408         if (c0 == 0){
2409             return -1;
2410         }
2411         c2 = (c2 << 8) | (c1 & 0x7f);
2412         c1 = c0 & 0x7f;
2413 #ifdef SHIFTJIS_CP932
2414         if (cp932_f){
2415             int s2, s1;
2416             if (e2s_conv(c2, c1, &s2, &s1) == 0){
2417                 s2e_conv(s2, s1, &c2, &c1);
2418                 if ((c2 & 0xff00) == 0){
2419                     c1 &= 0x7f;
2420                     c2 &= 0x7f;
2421                 }
2422             }
2423         }
2424 #endif /* SHIFTJIS_CP932 */
2425 #endif /* X0212_ENABLE */
2426     } else if (c2 == SSO){
2427         c2 = X0201;
2428         c1 &= 0x7f;
2429     } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
2430         /* NOP */
2431     } else {
2432         c1 &= 0x7f;
2433         c2 &= 0x7f;
2434     }
2435     (*oconv)(c2, c1);
2436     return 0;
2437 }
2438
2439 #ifdef UTF8_INPUT_ENABLE
2440 int
2441 w2e_conv(c2, c1, c0, p2, p1)
2442     int    c2, c1, c0;
2443     int *p2, *p1;
2444 {
2445     extern unsigned short * utf8_to_euc_2bytes[];
2446     extern unsigned short ** utf8_to_euc_3bytes[];
2447     int ret = 0;
2448
2449     if (0xc0 <= c2 && c2 <= 0xef) {
2450         unsigned short **pp;
2451
2452         if (0xe0 <= c2) {
2453             if (c0 == 0) return -1;
2454             pp = utf8_to_euc_3bytes[c2 - 0x80];
2455             ret = w_iconv_common(c1, c0, pp, sizeof_utf8_to_euc_C2, p2, p1);
2456         } else {
2457             ret =  w_iconv_common(c2, c1, utf8_to_euc_2bytes, sizeof_utf8_to_euc_2bytes, p2, p1);
2458         }
2459 #ifdef NUMCHAR_OPTION
2460         if (ret){
2461             if (p2) *p2 = 0;
2462             if (p1) *p1 = CLASS_UTF16 | ww16_conv(c2, c1, c0);
2463             ret = 0;
2464         }
2465 #endif
2466         return ret;
2467     } else if (c2 == X0201) {
2468         c1 &= 0x7f;
2469     }
2470     if (p2) *p2 = c2;
2471     if (p1) *p1 = c1;
2472     return ret;
2473 }
2474
2475 int
2476 w_iconv(c2, c1, c0)
2477     int    c2,
2478                     c1, c0;
2479 {
2480     int ret = w2e_conv(c2, c1, c0, &c2, &c1);
2481     if (ret == 0){
2482         (*oconv)(c2, c1);
2483     }
2484     return ret;
2485 }
2486
2487 void
2488 w16w_conv(val, p2, p1, p0)
2489      unsigned short val;
2490      int *p2, *p1, *p0;
2491 {
2492     if (val < 0x80){
2493         *p2 = val;
2494         *p1 = 0;
2495         *p0 = 0;
2496     }else if (val < 0x800){
2497         *p2 = 0xc0 | (val >> 6);
2498         *p1 = 0x80 | (val & 0x3f);
2499         *p0 = 0;
2500     }else{
2501         *p2 = 0xe0 | (val >> 12);
2502         *p1 = 0x80 | ((val >> 6) & 0x3f);
2503         *p0 = 0x80 | (val        & 0x3f);
2504     }
2505 }
2506
2507 int
2508 ww16_conv(c2, c1, c0)
2509      int c2, c1, c0;
2510 {
2511     unsigned short val;
2512     if (c2 >= 0xe0){
2513         val = (c2 & 0x0f) << 12;
2514         val |= (c1 & 0x3f) << 6;
2515         val |= (c0 & 0x3f);
2516     }else if (c2 >= 0xc0){
2517         val = (c2 & 0x1f) << 6;
2518         val |= (c1 & 0x3f);
2519     }else{
2520         val = c2;
2521     }
2522     return val;
2523 }
2524
2525 int
2526 w16e_conv(val, p2, p1)
2527      unsigned short val;
2528      int *p2, *p1;
2529 {
2530     extern unsigned short * utf8_to_euc_2bytes[];
2531     extern unsigned short ** utf8_to_euc_3bytes[];
2532     int c2, c1, c0;
2533     unsigned short **pp;
2534     int psize;
2535     int ret = 0;
2536
2537     w16w_conv(val, &c2, &c1, &c0);
2538     if (c1){
2539         if (c0){
2540             pp = utf8_to_euc_3bytes[c2 - 0x80];
2541             psize = sizeof_utf8_to_euc_C2;
2542             ret =  w_iconv_common(c1, c0, pp, psize, p2, p1);
2543         }else{
2544             pp = utf8_to_euc_2bytes;
2545             psize = sizeof_utf8_to_euc_2bytes;
2546             ret =  w_iconv_common(c2, c1, pp, psize, p2, p1);
2547         }
2548 #ifdef NUMCHAR_OPTION
2549         if (ret){
2550             *p2 = 0;
2551             *p1 = CLASS_UTF16 | val;
2552             ret = 0;
2553         }
2554 #endif
2555     }else{
2556         *p2 = 0;
2557         *p1 = c2;
2558     }
2559     return ret;
2560 }
2561
2562 int
2563 w_iconv16(c2, c1, c0)
2564     int    c2, c1,c0;
2565 {
2566     int ret;
2567
2568     if (c2==0376 && c1==0377){
2569         utf16_mode = UTF16LE_INPUT;
2570         return 0;    
2571     } else if (c2==0377 && c1==0376){
2572         utf16_mode = UTF16BE_INPUT;
2573         return 0;    
2574     }
2575     if (c2 != EOF && utf16_mode == UTF16BE_INPUT) {
2576         int tmp;
2577         tmp=c1; c1=c2; c2=tmp;
2578     }
2579     if ((c2==0 && c1 < 0x80) || c2==EOF) {
2580         (*oconv)(c2, c1);
2581         return 0;
2582     }
2583     ret = w16e_conv(((c2<<8)&0xff00) + c1, &c2, &c1);
2584     if (ret) return ret;
2585     (*oconv)(c2, c1);
2586     return 0;
2587 }
2588
2589 int
2590 w_iconv_common(c1, c0, pp, psize, p2, p1)
2591     int    c1,c0;
2592     unsigned short **pp;
2593     int psize;
2594     int *p2, *p1;
2595 {
2596     int c2;
2597     unsigned short *p ;
2598     unsigned short val;
2599
2600     if (pp == 0) return 1;
2601
2602     c1 -= 0x80;
2603     if (c1 < 0 || psize <= c1) return 1;
2604     p = pp[c1];
2605     if (p == 0)  return 1;
2606
2607     c0 -= 0x80;
2608     if (c0 < 0 || sizeof_utf8_to_euc_E5B8 <= c0) return 1;
2609     val = p[c0];
2610     if (val == 0) return 1;
2611
2612     c2 = val >> 8;
2613     if (val & 0x8000){
2614         c2 &= 0x7f;
2615         c2 |= 0x8f00;
2616     }
2617     if (c2 == SO) c2 = X0201;
2618     c1 = val & 0x7f;
2619     if (p2) *p2 = c2;
2620     if (p1) *p1 = c1;
2621     return 0;
2622 }
2623
2624 #endif
2625
2626 #ifdef UTF8_OUTPUT_ENABLE
2627 int
2628 e2w_conv(c2, c1)
2629     int    c2, c1;
2630 {
2631     extern unsigned short euc_to_utf8_1byte[];
2632     extern unsigned short * euc_to_utf8_2bytes[];
2633     extern unsigned short * euc_to_utf8_2bytes_ms[];
2634     unsigned short *p;
2635
2636     if (c2 == X0201) {
2637         p = euc_to_utf8_1byte;
2638 #ifdef X0212_ENABLE
2639     } else if (c2 >> 8 == 0x8f){
2640         extern unsigned short * x0212_to_utf8_2bytes[];
2641         c2 = (c2&0x7f) - 0x21;
2642         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
2643             p = x0212_to_utf8_2bytes[c2];
2644         else
2645             return 0;
2646 #endif
2647     } else {
2648         c2 &= 0x7f;
2649         c2 = (c2&0x7f) - 0x21;
2650         if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
2651             p = ms_ucs_map_f ? euc_to_utf8_2bytes_ms[c2] : euc_to_utf8_2bytes[c2];
2652         else
2653             return 0;
2654     }
2655     if (!p) return 0;
2656     c1 = (c1 & 0x7f) - 0x21;
2657     if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
2658         return p[c1];
2659     return 0;
2660 }
2661
2662 void
2663 w_oconv(c2, c1)
2664     int    c2,
2665                     c1;
2666 {
2667     int c0;
2668     if (c2 == EOF) {
2669         (*o_putc)(EOF);
2670         return;
2671     }
2672
2673     if (unicode_bom_f==2) {
2674         (*o_putc)('\357');
2675         (*o_putc)('\273');
2676         (*o_putc)('\277');
2677         unicode_bom_f=1;
2678     }
2679
2680 #ifdef NUMCHAR_OPTION
2681     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2682         w16w_conv(c1, &c2, &c1, &c0);
2683         (*o_putc)(c2);
2684         if (c1){
2685             (*o_putc)(c1);
2686             if (c0) (*o_putc)(c0);
2687         }
2688         return;
2689     }
2690 #endif
2691
2692     if (c2 == 0) { 
2693         output_mode = ASCII;
2694         (*o_putc)(c1);
2695     } else if (c2 == ISO8859_1) {
2696         output_mode = ISO8859_1;
2697         (*o_putc)(c1 | 0x080);
2698     } else {
2699         unsigned short val;
2700         output_mode = UTF8;
2701         val = e2w_conv(c2, c1);
2702         if (val){
2703             w16w_conv(val, &c2, &c1, &c0);
2704             (*o_putc)(c2);
2705             if (c1){
2706                 (*o_putc)(c1);
2707                 if (c0) (*o_putc)(c0);
2708             }
2709         }
2710     }
2711 }
2712
2713 void
2714 w_oconv16(c2, c1)
2715     int    c2,
2716                     c1;
2717 {
2718     if (c2 == EOF) {
2719         (*o_putc)(EOF);
2720         return;
2721     }    
2722
2723     if (unicode_bom_f==2) {
2724         if (w_oconv16_LE){
2725             (*o_putc)((unsigned char)'\377');
2726             (*o_putc)('\376');
2727         }else{
2728             (*o_putc)('\376');
2729             (*o_putc)((unsigned char)'\377');
2730         }
2731         unicode_bom_f=1;
2732     }
2733
2734     if (c2 == ISO8859_1) {
2735         c2 = 0;
2736         c1 |= 0x80;
2737 #ifdef NUMCHAR_OPTION
2738     } else if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16) {
2739         c2 = (c1 >> 8) & 0xff;
2740         c1 &= 0xff;
2741 #endif
2742     } else if (c2) {
2743         unsigned short val = e2w_conv(c2, c1);
2744         c2 = (val >> 8) & 0xff;
2745         c1 = val & 0xff;
2746     }
2747     if (w_oconv16_LE){
2748         (*o_putc)(c1);
2749         (*o_putc)(c2);
2750     }else{
2751         (*o_putc)(c2);
2752         (*o_putc)(c1);
2753     }
2754 }
2755
2756 #endif
2757
2758 void
2759 e_oconv(c2, c1)
2760     int    c2,
2761                     c1;
2762 {
2763 #ifdef NUMCHAR_OPTION
2764     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2765         w16e_conv(c1, &c2, &c1);
2766         if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2767             return;
2768         }
2769     }
2770 #endif
2771     if (c2 == EOF) {
2772         (*o_putc)(EOF);
2773         return;
2774     } else if (c2 == 0) { 
2775         output_mode = ASCII;
2776         (*o_putc)(c1);
2777     } else if (c2 == X0201) {
2778         output_mode = JAPANESE_EUC;
2779         (*o_putc)(SSO); (*o_putc)(c1|0x80);
2780     } else if (c2 == ISO8859_1) {
2781         output_mode = ISO8859_1;
2782         (*o_putc)(c1 | 0x080);
2783 #ifdef X0212_ENABLE
2784     } else if ((c2 & 0xff00) >> 8 == 0x8f){
2785         output_mode = JAPANESE_EUC;
2786 #ifdef SHIFTJIS_CP932
2787         if (cp932_f){
2788             int s2, s1;
2789             if (e2s_conv(c2, c1, &s2, &s1) == 0){
2790                 s2e_conv(s2, s1, &c2, &c1);
2791             }
2792         }
2793 #endif
2794         if ((c2 & 0xff00) >> 8 == 0x8f){
2795             if (x0212_f){
2796                 (*o_putc)(0x8f);
2797                 (*o_putc)((c2 & 0x7f) | 0x080);
2798                 (*o_putc)(c1 | 0x080);
2799             }
2800         }else{
2801             (*o_putc)((c2 & 0x7f) | 0x080);
2802             (*o_putc)(c1 | 0x080);
2803         }
2804 #endif
2805     } else {
2806         if ((c1<0x21 || 0x7e<c1) ||
2807            (c2<0x21 || 0x7e<c2)) {
2808             set_iconv(FALSE, 0);
2809             return; /* too late to rescue this char */
2810         }
2811         output_mode = JAPANESE_EUC;
2812         (*o_putc)(c2 | 0x080);
2813         (*o_putc)(c1 | 0x080);
2814     }
2815 }
2816
2817 #ifdef X0212_ENABLE
2818 int x0212_shift(c)
2819      int c;
2820 {
2821     int ret = c;
2822     c &= 0x7f;
2823     if ((ret & 0xff00) == 0x8f00){
2824         if (0x75 <= c && c <= 0x7f){
2825             ret = c + (0x109 - 0x75);
2826         }
2827     }else{
2828         if (0x75 <= c && c <= 0x7f){
2829             ret = c + (0x113 - 0x75);
2830         }
2831     }
2832     return ret;
2833 }
2834
2835
2836 int x0212_unshift(c)
2837      int c;
2838 {
2839     int ret = c;
2840     if (0x7f <= c && c <= 0x88){
2841         ret = c + (0x75 - 0x7f);
2842     }else if (0x89 <= c && c <= 0x92){
2843         ret = (0x8f << 8) | 0x80 | (c + (0x75 - 0x89));
2844     }
2845     return ret;
2846 }
2847 #endif /* X0212_ENABLE */
2848
2849 int
2850 e2s_conv(c2, c1, p2, p1)
2851      int c2, c1, *p2, *p1;
2852 {
2853     int val = 0;
2854     unsigned short *ptr;
2855     int ndx;
2856     extern unsigned short *x0212_shiftjis[];
2857 #ifdef X0212_ENABLE
2858     if ((c2 & 0xff00) == 0x8f00){
2859         ndx = c2 & 0x7f;
2860         if (0x21 <= ndx && ndx <= 0x7e){
2861             ptr = x0212_shiftjis[ndx - 0x21];
2862             if (ptr){
2863                 val = ptr[(c1 & 0x7f) - 0x21];
2864             }
2865             if (val){
2866                 c2 = val >> 8;
2867                 c1 = val & 0xff;
2868                 if (p2) *p2 = c2;
2869                 if (p1) *p1 = c1;
2870                 return 0;
2871             }
2872         }
2873         c2 = x0212_shift(c2);
2874     }
2875 #endif /* X0212_ENABLE */
2876     if ((c2 & 0xff00) == 0x8f00){
2877         return 1;
2878     }
2879     if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
2880     if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
2881     return 0;
2882 }
2883
2884 void
2885 s_oconv(c2, c1)
2886     int    c2,
2887                     c1;
2888 {
2889 #ifdef NUMCHAR_OPTION
2890     if (c2 == 0 && (c1 & CLASS_MASK) == CLASS_UTF16){
2891         w16e_conv(c1, &c2, &c1);
2892     }
2893 #endif
2894     if (c2 == EOF) {
2895         (*o_putc)(EOF);
2896         return;
2897     } else if (c2 == 0) {
2898         output_mode = ASCII;
2899         (*o_putc)(c1);
2900     } else if (c2 == X0201) {
2901         output_mode = SHIFT_JIS;
2902         (*o_putc)(c1|0x80);
2903     } else if (c2 == ISO8859_1) {
2904         output_mode = ISO8859_1;
2905         (*o_putc)(c1 | 0x080);
2906 #ifdef X0212_ENABLE
2907     } else if ((c2 & 0xff00) >> 8 == 0x8f){
2908         output_mode = SHIFT_JIS;
2909         if (e2s_conv(c2, c1, &c2, &c1) == 0){
2910             (*o_putc)(c2);
2911             (*o_putc)(c1);
2912         }
2913 #endif
2914     } else {
2915         if ((c1<0x20 || 0x7e<c1) ||
2916            (c2<0x20 || 0x7e<c2)) {
2917             set_iconv(FALSE, 0);
2918             return; /* too late to rescue this char */
2919         }
2920         output_mode = SHIFT_JIS;
2921         e2s_conv(c2, c1, &c2, &c1);
2922
2923 #ifdef SHIFTJIS_CP932
2924         if (cp932inv_f
2925             && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
2926             extern unsigned short cp932inv[2][189];
2927             int c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
2928             if (c){
2929                 c2 = c >> 8;
2930                 c1 = c & 0xff;
2931             }
2932         }
2933 #endif /* SHIFTJIS_CP932 */
2934
2935         (*o_putc)(c2);
2936         if (prefix_table[(unsigned char)c1]){
2937             (*o_putc)(prefix_table[(unsigned char)c1]);
2938         }
2939         (*o_putc)(c1);
2940     }
2941 }
2942
2943 void
2944 j_oconv(c2, c1)
2945     int    c2,
2946                     c1;
2947 {
2948 #ifdef NUMCHAR_OPTION
2949     if ((c1 & CLASS_MASK) == CLASS_UTF16){
2950         w16e_conv(c1, &c2, &c1);
2951     }
2952 #endif
2953     if (c2 == EOF) {
2954         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2955             (*o_putc)(ESC);
2956             (*o_putc)('(');
2957             (*o_putc)(ascii_intro);
2958             output_mode = ASCII;
2959         }
2960         (*o_putc)(EOF);
2961 #ifdef X0212_ENABLE
2962     } else if ((c2 & 0xff00) >> 8 == 0x8f){
2963         if (output_mode!=X0212) {
2964             output_mode = X0212;
2965             (*o_putc)(ESC);
2966             (*o_putc)('$');
2967             (*o_putc)('(');
2968             (*o_putc)('D');
2969         }
2970         (*o_putc)(c2 & 0x7f);
2971         (*o_putc)(c1);
2972 #endif
2973     } else if (c2==X0201) {
2974         if (output_mode!=X0201) {
2975             output_mode = X0201;
2976             (*o_putc)(ESC);
2977             (*o_putc)('(');
2978             (*o_putc)('I');
2979         }
2980         (*o_putc)(c1);
2981     } else if (c2==ISO8859_1) {
2982             /* iso8859 introduction, or 8th bit on */
2983             /* Can we convert in 7bit form using ESC-'-'-A ? 
2984                Is this popular? */
2985         output_mode = ISO8859_1;
2986         (*o_putc)(c1|0x80);
2987     } else if (c2 == 0) {
2988         if (output_mode !=ASCII && output_mode!=ISO8859_1) {
2989             (*o_putc)(ESC);
2990             (*o_putc)('(');
2991             (*o_putc)(ascii_intro);
2992             output_mode = ASCII;
2993         }
2994         (*o_putc)(c1);
2995     } else {
2996         if (output_mode != X0208) {
2997             output_mode = X0208;
2998             (*o_putc)(ESC);
2999             (*o_putc)('$');
3000             (*o_putc)(kanji_intro);
3001         }
3002         if (c1<0x20 || 0x7e<c1) 
3003             return;
3004         if (c2<0x20 || 0x7e<c2) 
3005             return;
3006         (*o_putc)(c2);
3007         (*o_putc)(c1);
3008     }
3009 }
3010
3011 void
3012 base64_conv(c2, c1)
3013     int    c2,
3014                     c1;
3015 {
3016     mime_prechar(c2, c1);
3017     (*o_base64conv)(c2,c1);
3018 }
3019
3020
3021 static int broken_buf[3];
3022 static int broken_counter = 0;
3023 static int broken_last = 0;
3024 int
3025 broken_getc(f)
3026 FILE *f;
3027 {
3028     int c,c1;
3029
3030     if (broken_counter>0) {
3031         return broken_buf[--broken_counter];
3032     }
3033     c= (*i_bgetc)(f);
3034     if (c=='$' && broken_last != ESC 
3035             && (input_mode==ASCII || input_mode==X0201)) {
3036         c1= (*i_bgetc)(f);
3037         broken_last = 0;
3038         if (c1=='@'|| c1=='B') {
3039             broken_buf[0]=c1; broken_buf[1]=c; 
3040             broken_counter=2;
3041             return ESC;
3042         } else {
3043             (*i_bungetc)(c1,f);
3044             return c;
3045         }
3046     } else if (c=='(' && broken_last != ESC 
3047             && (input_mode==X0208 || input_mode==X0201)) { /* ) */
3048         c1= (*i_bgetc)(f);
3049         broken_last = 0;
3050         if (c1=='J'|| c1=='B') {
3051             broken_buf[0]=c1; broken_buf[1]=c;
3052             broken_counter=2;
3053             return ESC;
3054         } else {
3055             (*i_bungetc)(c1,f);
3056             return c;
3057         }
3058     } else {
3059         broken_last = c;
3060         return c;
3061     }
3062 }
3063
3064 int
3065 broken_ungetc(c,f)
3066 int c;
3067 FILE *f;
3068 {
3069     if (broken_counter<2)
3070         broken_buf[broken_counter++]=c;
3071     return c;
3072 }
3073
3074 static int prev_cr = 0;
3075
3076 void
3077 cr_conv(c2,c1) 
3078 int c2,c1;
3079 {
3080     if (prev_cr) {
3081         prev_cr = 0;
3082         if (! (c2==0&&c1==NL) ) {
3083             cr_conv(0,'\n');
3084         }
3085     }
3086     if (c2) {
3087         (*o_crconv)(c2,c1);
3088     } else if (c1=='\r') {
3089         prev_cr = c1;
3090     } else if (c1=='\n') {
3091         if (crmode_f==CRLF) {
3092             (*o_crconv)(0,'\r');
3093         } else if (crmode_f==CR) {
3094             (*o_crconv)(0,'\r');
3095             return;
3096         } 
3097         (*o_crconv)(0,NL);
3098     } else if (c1!='\032' || crmode_f!=NL){
3099         (*o_crconv)(c2,c1);
3100     }
3101 }
3102
3103 /* 
3104   Return value of fold_conv()
3105
3106        \n  add newline  and output char
3107        \r  add newline  and output nothing
3108        ' ' space
3109        0   skip  
3110        1   (or else) normal output 
3111
3112   fold state in prev (previous character)
3113
3114       >0x80 Japanese (X0208/X0201)
3115       <0x80 ASCII
3116       \n    new line 
3117       ' '   space
3118
3119   This fold algorthm does not preserve heading space in a line.
3120   This is the main difference from fmt.
3121 */
3122
3123 #define char_size(c2,c1) (c2?2:1)
3124
3125 void
3126 fold_conv(c2,c1) 
3127 int c2,c1;
3128
3129     int prev0;
3130     int fold_state=0;
3131
3132     if (c1== '\r' && !fold_preserve_f) {
3133         fold_state=0;  /* ignore cr */
3134     }else if (c1== '\n'&&f_prev=='\r' && fold_preserve_f) {
3135         f_prev = '\n';
3136         fold_state=0;  /* ignore cr */
3137     } else if (c1== BS) {
3138         if (f_line>0) f_line--;
3139         fold_state =  1;
3140     } else if (c2==EOF && f_line != 0) {    /* close open last line */
3141             fold_state = '\n';
3142     } else if ((c1=='\n' && !fold_preserve_f)
3143                || ((c1=='\r'||(c1=='\n'&&f_prev!='\r'))
3144                    && fold_preserve_f)) {
3145         /* new line */
3146         if (fold_preserve_f) { 
3147             f_prev = c1;
3148             f_line = 0;
3149             fold_state =  '\r';
3150         } else if ((f_prev == c1 && !fold_preserve_f)
3151                    || (f_prev == '\n' && fold_preserve_f)
3152                    ) {        /* duplicate newline */
3153             if (f_line) {
3154                 f_line = 0;
3155                 fold_state =  '\n';    /* output two newline */
3156             } else {
3157                 f_line = 0;
3158                 fold_state =  1;
3159             }
3160         } else  {
3161             if (f_prev&0x80) {     /* Japanese? */
3162                 f_prev = c1;
3163                 fold_state =  0;       /* ignore given single newline */
3164             } else if (f_prev==' ') {
3165                 fold_state =  0;
3166             } else {
3167                 f_prev = c1;
3168                 if (++f_line<=fold_len) 
3169                     fold_state =  ' ';
3170                 else {
3171                     f_line = 0;
3172                     fold_state =  '\r';        /* fold and output nothing */
3173                 }
3174             }
3175         }
3176     } else if (c1=='\f') {
3177         f_prev = '\n';
3178         if (f_line==0)
3179             fold_state =  1;
3180         f_line = 0;
3181         fold_state =  '\n';            /* output newline and clear */
3182     } else if ( (c2==0  && c1==' ')||
3183                (c2==0  && c1=='\t')||
3184                (c2=='!'&& c1=='!')) {
3185         /* X0208 kankaku or ascii space */
3186             if (f_prev == ' ') {
3187                 fold_state = 0;         /* remove duplicate spaces */
3188             } else {
3189                 f_prev = ' ';    
3190                 if (++f_line<=fold_len) 
3191                     fold_state = ' ';         /* output ASCII space only */
3192                 else {
3193                     f_prev = ' '; f_line = 0;
3194                     fold_state = '\r';        /* fold and output nothing */
3195                 }
3196             }
3197     } else {
3198         prev0 = f_prev; /* we still need this one... , but almost done */
3199         f_prev = c1;
3200         if (c2 || c2==X0201) 
3201             f_prev |= 0x80;  /* this is Japanese */
3202         f_line += char_size(c2,c1);
3203         if (f_line<=fold_len) {   /* normal case */
3204             fold_state = 1;
3205         } else {
3206             if (f_line>=fold_len+fold_margin) { /* too many kinsou suspension */
3207                 f_line = char_size(c2,c1);
3208                 fold_state =  '\n';       /* We can't wait, do fold now */
3209             } else if (c2==X0201) {
3210             /* simple kinsoku rules  return 1 means no folding  */
3211                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
3212                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
3213                 else if (c1==(0xa4&0x7f)) fold_state = 1; /* \e$B!#\e(B*/
3214                 else if (c1==(0xa3&0x7f)) fold_state = 1; /* \e$B!$\e(B*/
3215                 else if (c1==(0xa1&0x7f)) fold_state = 1; /* \e$B!W\e(B*/
3216                 else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
3217                 else if (SPACE<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
3218                     f_line = 1;
3219                     fold_state = '\n';/* add one new f_line before this character */
3220                 } else {
3221                     f_line = 1;
3222                     fold_state = '\n';/* add one new f_line before this character */
3223                 }
3224             } else if (c2==0) {
3225                 /* kinsoku point in ASCII */ 
3226                 if (  c1==')'||    /* { [ ( */
3227                      c1==']'||
3228                      c1=='}'||
3229                      c1=='.'||
3230                      c1==','||
3231                      c1=='!'||
3232                      c1=='?'||
3233                      c1=='/'||
3234                      c1==':'||
3235                      c1==';' ) {
3236                     fold_state = 1;
3237                 /* just after special */
3238                 } else if (!is_alnum(prev0)) {
3239                     f_line = char_size(c2,c1);
3240                     fold_state = '\n';
3241                 } else if ((prev0==' ') ||   /* ignored new f_line */
3242                       (prev0=='\n')||        /* ignored new f_line */
3243                       (prev0&0x80)) {        /* X0208 - ASCII */
3244                     f_line = char_size(c2,c1);
3245                     fold_state = '\n';/* add one new f_line before this character */
3246                 } else {
3247                     fold_state = 1;  /* default no fold in ASCII */
3248                 }
3249             } else {
3250                 if (c2=='!') {
3251                     if (c1=='"')  fold_state = 1; /* \e$B!"\e(B */
3252                     else if (c1=='#')  fold_state = 1; /* \e$B!#\e(B */
3253                     else if (c1=='W')  fold_state = 1; /* \e$B!W\e(B */
3254                     else if (c1=='K')  fold_state = 1; /* \e$B!K\e(B */
3255                     else if (c1=='$')  fold_state = 1; /* \e$B!$\e(B */
3256                     else if (c1=='%')  fold_state = 1; /* \e$B!%\e(B */
3257                     else if (c1=='\'') fold_state = 1; /* \e$B!\\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                          /* default no fold in kinsoku */
3264                     else { 
3265                         fold_state = '\n';
3266                         f_line = char_size(c2,c1);
3267                         /* add one new f_line before this character */
3268                     }
3269                 } else {
3270                     f_line = char_size(c2,c1);
3271                     fold_state = '\n'; 
3272                     /* add one new f_line before this character */
3273                 }
3274             }
3275         }
3276     }
3277     /* terminator process */
3278     switch(fold_state) {
3279         case '\n': 
3280             (*o_fconv)(0,'\n');
3281             (*o_fconv)(c2,c1);
3282             break;
3283         case 0:    
3284             return;
3285         case '\r': 
3286             (*o_fconv)(0,'\n');
3287             break;
3288         case '\t': 
3289         case ' ': 
3290             (*o_fconv)(0,' ');
3291             break;
3292         default:
3293             (*o_fconv)(c2,c1);
3294     }
3295 }
3296
3297 int z_prev2=0,z_prev1=0;
3298
3299 void
3300 z_conv(c2,c1)
3301 int c2,c1;
3302 {
3303
3304     /* if (c2) c1 &= 0x7f; assertion */
3305
3306     if (x0201_f && z_prev2==X0201) {  /* X0201 */
3307         if (c1==(0xde&0x7f)) { /* \e$BByE@\e(B */
3308             z_prev2=0;
3309             (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
3310             return;
3311         } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) {  /* \e$BH>ByE@\e(B */
3312             z_prev2=0;
3313             (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
3314             return;
3315         } else {
3316             z_prev2=0;
3317             (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
3318         }
3319     }
3320
3321     if (c2==EOF) {
3322         (*o_zconv)(c2,c1);
3323         return;
3324     }
3325
3326     if (x0201_f && c2==X0201) {
3327         if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
3328             /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
3329             z_prev1 = c1; z_prev2 = c2;
3330             return;
3331         } else {
3332             (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
3333             return;
3334         }
3335     }
3336
3337     /* JISX0208 Alphabet */
3338     if (alpha_f && c2 == 0x23 ) {
3339         c2 = 0;
3340     } else if (alpha_f && c2 == 0x21 ) { 
3341     /* JISX0208 Kigou */
3342        if (0x21==c1) {
3343            if (alpha_f&0x2) {
3344                c1 = ' ';
3345                c2 = 0;
3346            } else if (alpha_f&0x4) {
3347                 (*o_zconv)(0,' ');
3348                 (*o_zconv)(0,' ');
3349                 return;
3350            } 
3351        } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
3352            c1 = fv[c1-0x20];
3353            c2 =  0;
3354            if (alpha_f&0x8) {
3355                char *entity = 0;
3356                switch (c1){
3357                  case '>': entity = "&gt;"; break;
3358                  case '<': entity = "&lt;"; break;
3359                  case '\"': entity = "&quot;"; break;
3360                  case '&': entity = "&amp;"; break;
3361                }
3362                if (entity){
3363                    while (*entity) (*o_zconv)(0, *entity++);
3364                    return;
3365                }
3366            }
3367        } 
3368     }
3369     (*o_zconv)(c2,c1);
3370 }
3371
3372
3373 #define rot13(c)  ( \
3374       ( c < 'A' ) ? c: \
3375       (c <= 'M')  ? (c + 13): \
3376       (c <= 'Z')  ? (c - 13): \
3377       (c < 'a')   ? (c): \
3378       (c <= 'm')  ? (c + 13): \
3379       (c <= 'z')  ? (c - 13): \
3380       (c) \
3381 )
3382
3383 #define  rot47(c) ( \
3384       ( c < '!' ) ? c: \
3385       ( c <= 'O' ) ? (c + 47) : \
3386       ( c <= '~' ) ?  (c - 47) : \
3387       c \
3388 )
3389
3390 void
3391 rot_conv(c2,c1)
3392 int c2,c1;
3393 {
3394     if (c2==0 || c2==X0201 || c2==ISO8859_1) {
3395         c1 = rot13(c1);
3396     } else if (c2) {
3397         c1 = rot47(c1);
3398         c2 = rot47(c2);
3399     }
3400     (*o_rot_conv)(c2,c1);
3401 }
3402
3403 void
3404 hira_conv(c2,c1)
3405 int c2,c1;
3406 {
3407     if ((hira_f & 1) && c2==0x25 && 0x20<c1 && c1<0x74) {
3408         c2 = 0x24;
3409     } else if ((hira_f & 2) && c2==0x24 && 0x20<c1 && c1<0x74) {
3410         c2 = 0x25;
3411     } 
3412     (*o_hira_conv)(c2,c1);
3413 }
3414
3415
3416 void
3417 iso2022jp_check_conv(c2,c1)
3418 int    c2, c1;
3419 {
3420     static int range[RANGE_NUM_MAX][2] = {
3421         {0x222f, 0x2239,},
3422         {0x2242, 0x2249,},
3423         {0x2251, 0x225b,},
3424         {0x226b, 0x2271,},
3425         {0x227a, 0x227d,},
3426         {0x2321, 0x232f,},
3427         {0x233a, 0x2340,},
3428         {0x235b, 0x2360,},
3429         {0x237b, 0x237e,},
3430         {0x2474, 0x247e,},
3431         {0x2577, 0x257e,},
3432         {0x2639, 0x2640,},
3433         {0x2659, 0x267e,},
3434         {0x2742, 0x2750,},
3435         {0x2772, 0x277e,},
3436         {0x2841, 0x287e,},
3437         {0x4f54, 0x4f7e,},
3438         {0x7425, 0x747e},
3439     };
3440     int i;
3441     int start, end, c;
3442
3443     if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
3444         c2 = GETA1;
3445         c1 = GETA2;
3446     }
3447     if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
3448         c2 = GETA1;
3449         c1 = GETA2;
3450     }
3451
3452     for (i = 0; i < RANGE_NUM_MAX; i++) {
3453         start = range[i][0];
3454         end   = range[i][1];
3455         c     = (c2 << 8) + c1;
3456         if (c >= start && c <= end) {
3457             c2 = GETA1;
3458             c1 = GETA2;
3459         }
3460     }
3461     (*o_iso2022jp_check_conv)(c2,c1);
3462 }
3463
3464
3465 /* This converts  =?ISO-2022-JP?B?HOGE HOGE?= */
3466
3467 unsigned char *mime_pattern[] = {
3468    (unsigned char *)"\075?EUC-JP?B?",
3469    (unsigned char *)"\075?SHIFT_JIS?B?",
3470    (unsigned char *)"\075?ISO-8859-1?Q?",
3471    (unsigned char *)"\075?ISO-8859-1?B?",
3472    (unsigned char *)"\075?ISO-2022-JP?B?",
3473    (unsigned char *)"\075?ISO-2022-JP?Q?",
3474 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3475    (unsigned char *)"\075?UTF-8?B?",
3476    (unsigned char *)"\075?UTF-8?Q?",
3477 #endif
3478    (unsigned char *)"\075?US-ASCII?Q?",
3479    NULL
3480 };
3481
3482
3483 /* \e$B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u\e(B */
3484 int (*mime_priority_func[])PROTO((int c2, int c1, int c0)) = {
3485     e_iconv, s_iconv, 0, 0, 0, 0,
3486 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3487     w_iconv, w_iconv,
3488 #endif
3489     0,
3490 };
3491
3492 int      mime_encode[] = {
3493     JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
3494 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3495     UTF8, UTF8,
3496 #endif
3497     ASCII,
3498     0
3499 };
3500
3501 int      mime_encode_method[] = {
3502     'B', 'B','Q', 'B', 'B', 'Q',
3503 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
3504     'B', 'Q',
3505 #endif
3506     'Q',
3507     0
3508 };
3509
3510
3511 #define MAXRECOVER 20
3512
3513 /* I don't trust portablity of toupper */
3514 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
3515 #define nkf_isdigit(c)  ('0'<=c && c<='9')
3516 #define nkf_isxdigit(c)  (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
3517 #define nkf_isblank(c) (c == SPACE || c == TAB)
3518 #define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == NL)
3519 #define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
3520 #define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c))
3521
3522 void
3523 switch_mime_getc()
3524 {
3525     if (i_getc!=mime_getc) {
3526         i_mgetc = i_getc; i_getc = mime_getc;
3527         i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
3528         if(mime_f==STRICT_MIME) {
3529             i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
3530             i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
3531         }
3532     }
3533 }
3534
3535 void
3536 unswitch_mime_getc()
3537 {
3538     if(mime_f==STRICT_MIME) {
3539         i_mgetc = i_mgetc_buf;
3540         i_mungetc = i_mungetc_buf;
3541     }
3542     i_getc = i_mgetc;
3543     i_ungetc = i_mungetc;
3544 }
3545
3546 int
3547 mime_begin_strict(f)
3548 FILE *f;
3549 {
3550     int c1 = 0;
3551     int i,j,k;
3552     unsigned char *p,*q;
3553     int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */
3554
3555     mime_decode_mode = FALSE;
3556     /* =? has been checked */
3557     j = 0;
3558     p = mime_pattern[j];
3559     r[0]='='; r[1]='?';
3560
3561     for(i=2;p[i]>' ';i++) {                   /* start at =? */
3562         if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
3563             /* pattern fails, try next one */
3564             q = p;
3565             while ((p = mime_pattern[++j])) {
3566                 for(k=2;k<i;k++)              /* assume length(p) > i */
3567                     if (p[k]!=q[k]) break;
3568                 if (k==i && nkf_toupper(c1)==p[k]) break;
3569             }
3570             if (p) continue;  /* found next one, continue */
3571             /* all fails, output from recovery buffer */
3572             (*i_ungetc)(c1,f);
3573             for(j=0;j<i;j++) {
3574                 (*oconv)(0,r[j]);
3575             }
3576             return c1;
3577         }
3578     }
3579     mime_decode_mode = p[i-2];
3580
3581     set_iconv(FALSE, mime_priority_func[j]);
3582     clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
3583
3584     if (mime_decode_mode=='B') {
3585         mimebuf_f = unbuf_f;
3586         if (!unbuf_f) {
3587             /* do MIME integrity check */
3588             return mime_integrity(f,mime_pattern[j]);
3589         } 
3590     }
3591     switch_mime_getc();
3592     mimebuf_f = TRUE;
3593     return c1;
3594 }
3595
3596 int
3597 mime_getc_buf(f) 
3598 FILE *f;
3599 {
3600     /* we don't keep eof of Fifo, becase it contains ?= as
3601        a terminator. It was checked in mime_integrity. */
3602     return ((mimebuf_f)?
3603         (*i_mgetc_buf)(f):Fifo(mime_input++));
3604 }
3605
3606 int
3607 mime_ungetc_buf(c,f) 
3608 FILE *f;
3609 int c;
3610 {
3611     if (mimebuf_f)
3612         (*i_mungetc_buf)(c,f);
3613     else 
3614         Fifo(--mime_input)=c;
3615     return c;
3616 }
3617
3618 int
3619 mime_begin(f)
3620 FILE *f;
3621 {
3622     int c1;
3623     int i,k;
3624
3625     /* In NONSTRICT mode, only =? is checked. In case of failure, we  */
3626     /* re-read and convert again from mime_buffer.  */
3627
3628     /* =? has been checked */
3629     k = mime_last;
3630     Fifo(mime_last++)='='; Fifo(mime_last++)='?';
3631     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
3632         /* We accept any character type even if it is breaked by new lines */
3633         c1 = (*i_getc)(f); Fifo(mime_last++)= c1 ;
3634         if (c1=='\n'||c1==' '||c1=='\r'||
3635                 c1=='-'||c1=='_'||is_alnum(c1) ) continue;
3636         if (c1=='=') {
3637             /* Failed. But this could be another MIME preemble */
3638             (*i_ungetc)(c1,f);
3639             mime_last--;
3640             break;
3641         }
3642         if (c1!='?') break;
3643         else {
3644             /* c1=='?' */
3645             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3646             if (!(++i<MAXRECOVER) || c1==EOF) break;
3647             if (c1=='b'||c1=='B') {
3648                 mime_decode_mode = 'B';
3649             } else if (c1=='q'||c1=='Q') {
3650                 mime_decode_mode = 'Q';
3651             } else {
3652                 break;
3653             }
3654             c1 = (*i_getc)(f); Fifo(mime_last++) = c1;
3655             if (!(++i<MAXRECOVER) || c1==EOF) break;
3656             if (c1!='?') {
3657                 mime_decode_mode = FALSE;
3658             }
3659             break;
3660         }
3661     }
3662     switch_mime_getc();
3663     if (!mime_decode_mode) {
3664         /* false MIME premble, restart from mime_buffer */
3665         mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
3666         /* Since we are in MIME mode until buffer becomes empty,    */
3667         /* we never go into mime_begin again for a while.           */
3668         return c1;
3669     }
3670     /* discard mime preemble, and goto MIME mode */
3671     mime_last = k;
3672     /* do no MIME integrity check */
3673     return c1;   /* used only for checking EOF */
3674 }
3675
3676 #ifdef CHECK_OPTION
3677 void
3678 no_putc(c)
3679      int c;
3680 {
3681     ;
3682 }
3683
3684 void debug(str)
3685      char *str;
3686 {
3687     if (debug_f){
3688         fprintf(stderr, "%s\n", str);
3689     }
3690 }
3691 #endif
3692
3693 void
3694 set_input_codename (codename)
3695     char *codename;
3696 {
3697     if (guess_f && 
3698         is_inputcode_set &&
3699         strcmp(codename, "") != 0 && 
3700         strcmp(codename, input_codename) != 0)
3701     {
3702         is_inputcode_mixed = TRUE;
3703     }
3704     input_codename = codename;
3705     is_inputcode_set = TRUE;
3706 }
3707
3708 #ifndef WIN32DLL
3709 void
3710 print_guessed_code (filename)
3711     char *filename;
3712 {
3713     char *codename = "BINARY";
3714     if (!is_inputcode_mixed) {
3715         if (strcmp(input_codename, "") == 0) {
3716             codename = "ASCII";
3717         } else {
3718             codename = input_codename;
3719         }
3720     }
3721     if (filename != NULL) printf("%s:", filename);
3722     printf("%s\n", codename);
3723 }
3724 #endif /*WIN32DLL*/
3725
3726 int
3727 hex2bin(x)
3728      int x;
3729 {
3730     if (nkf_isdigit(x)) return x - '0';
3731     return nkf_toupper(x) - 'A' + 10;
3732 }
3733
3734 #ifdef INPUT_OPTION 
3735
3736 #ifdef ANSI_C_PROTOTYPE
3737 int hex_getc(int ch, FILE *f, int (*g)(FILE *f), int (*u)(int c, FILE *f))
3738 #else
3739 int
3740 hex_getc(ch, f, g, u)
3741      int ch;
3742      FILE *f;
3743      int (*g)();
3744      int (*u)();
3745 #endif
3746 {
3747     int c1, c2, c3;
3748     c1 = (*g)(f);
3749     if (c1 != ch){
3750         return c1;
3751     }
3752     c2 = (*g)(f);
3753     if (!nkf_isxdigit(c2)){
3754         (*u)(c2, f);
3755         return c1;
3756     }
3757     c3 = (*g)(f);
3758     if (!nkf_isxdigit(c3)){
3759         (*u)(c2, f);
3760         (*u)(c3, f);
3761         return c1;
3762     }
3763     return (hex2bin(c2) << 4) | hex2bin(c3);
3764 }
3765
3766 int
3767 cap_getc(f)
3768      FILE *f;
3769 {
3770     return hex_getc(':', f, i_cgetc, i_cungetc);
3771 }
3772
3773 int
3774 cap_ungetc(c, f)
3775      int c;
3776      FILE *f;
3777 {
3778     return (*i_cungetc)(c, f);
3779 }
3780
3781 int
3782 url_getc(f)