OSDN Git Service

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