OSDN Git Service

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