OSDN Git Service

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