OSDN Git Service

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