OSDN Git Service

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