OSDN Git Service

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