OSDN Git Service

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