OSDN Git Service

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