OSDN Git Service

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