OSDN Git Service

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