OSDN Git Service

最初のコミット
[winaudioj/stedx.git] / nkflib.cpp
1 #include "stdafx.h"\r
2 \r
3 #ifdef HAVE_CONFIG_H\r
4 #include "config.h"\r
5 #endif /* HAVE_CONFIG_H */\r
6 \r
7 /** Network Kanji Filter. (PDS Version)\r
8 ************************************************************************\r
9 ** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)\r
10 ** 連絡先: (株)富士通研究所 ソフト3研 市川 至 \r
11 ** (E-Mail Address: ichikawa@flab.fujitsu.co.jp)\r
12 ** Copyright (C) 1996,1998\r
13 ** 連絡先: 琉球大学情報工学科 河野 真治  mine/X0208 support\r
14 ** (E-Mail Address: kono@ie.u-ryukyu.ac.jp)\r
15 ** 連絡先: COW for DOS & Win16 & Win32 & OS/2\r
16 ** (E-Mail Address: GHG00637@niftyserve.or.p)\r
17 **    このソースのいかなる複写,改変,修正も許諾します。ただし、\r
18 **    その際には、誰が貢献したを示すこの部分を残すこと。\r
19 **    再配布や雑誌の付録などの問い合わせも必要ありません。\r
20 **    このプログラムについては特に何の保証もしない、悪しからず。\r
21 **    Everyone is permitted to do anything on this program \r
22 **    including copying, modifying, improving.\r
23 **    as long as you don't try to pretend that you wrote it.\r
24 **    i.e., the above copyright notice has to appear in all copies.\r
25 **    You don't have to ask before copying or publishing.\r
26 **    THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.\r
27 ***********************************************************************/\r
28 \r
29 /* 以下のソースは、nkf を文字列操作できるよう改造したライブラリである。\r
30 \r
31    nkf_conv(元文字列,出力文字列、out モード)\r
32      出力文字列を NULL としたときは、元文字列を操作する。\r
33      バグ : 変換され出力される文字列のための領域はある程度とっておくこと。\r
34             さもないと、バグを生じる。\r
35    nkf_convert(元文字列、出力文字列、出力文字列の最大の大きさ、\r
36                in モード、out モード)\r
37      kanji_conv に準じる。出力文字列の最大の大きさが指定できる。\r
38      その大きさ以上になったときはそれ以上の文字の出力は打ち切られる。\r
39    モード\r
40      nkf の convert に与えるオプションを与える文字列。空白で区切って指定する。\r
41      各オプション:\r
42 \r
43    このプログラムに関しての著作権がらみのことは nkf に準じるものとする。\r
44    無保証であるので、使用の場合は自らの責任をもってすること。\r
45    改変者 青木大輔       1997.02\r
46 */\r
47 \r
48 /* 無駄なところを削除した.\r
49    他で用いられないインターフェースは static にした.\r
50    コンパイラの Warning メッセージを抑制するように ANSI C の形式にした.\r
51    文字を unsigned char * で SFILE に蓄えるようにした.\r
52    SFILE を簡単化.\r
53    input_f == FALSE で convert すると,半角カタカナ SJIS が EUC\r
54          と判断されてしまうバグ(仕様だった?)を直した.\r
55          しかしながら,SJIS の半角カタカナ 2 文字と EUC は区別できない\r
56          場合がある.このときは SJIS として変換することにした.\r
57    EUC_STRICT_CHECK を定義すると EUC-Japan の定義コードを完全にチェックする\r
58    ようにした.\r
59    読み込み文字を指定できるようにした.\r
60    改変者 出雲正尚 1997\r
61 */\r
62 \r
63 /*\r
64   1.7ベースに変更。\r
65   改変者 青木大輔 2000.10\r
66 */\r
67 \r
68 /*\r
69   STed2 で必要ない部分を削除。\r
70   改変者 八田真行 2000.10\r
71 */\r
72 \r
73 /* もし,EUC-Japan の完全なチェックをする場合は EUC_STRICT_CHECK を定義\r
74  * してください.ただし,1 バイトでも EUC-Japan の未定義文字が含まれていると\r
75  * EUC とみなされなくなってしまいます.他のプログラムで漢字コードを EUC に変換\r
76  * した場合,EUC の未定義域へマップされる可能性があります.\r
77  */\r
78 /* #define EUC_STRICT_CHECK */\r
79 \r
80 #if 0\r
81 static char *CopyRight =\r
82       "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1998 S. Kono, COW";\r
83 static char *Version =\r
84       "1.7";\r
85 static char *Patchlevel =\r
86       "0/9711/Shinji Kono";\r
87 #endif\r
88 \r
89 /*\r
90 **\r
91 **\r
92 **\r
93 ** USAGE:       nkf [flags] [file] \r
94 **\r
95 ** Flags:\r
96 ** b    Output is bufferred             (DEFAULT)\r
97 ** u    Output is unbufferred\r
98 **\r
99 ** t    no operation\r
100 **\r
101 ** j    Outout code is JIS 7 bit        (DEFAULT SELECT) \r
102 ** s    Output code is MS Kanji         (DEFAULT SELECT) \r
103 ** e    Output code is AT&T JIS         (DEFAULT SELECT) \r
104 ** l    Output code is JIS 7bit and ISO8859-1 Latin-1\r
105 **\r
106 ** m    MIME conversion for ISO-2022-JP\r
107 ** i_ Output sequence to designate JIS-kanji (DEFAULT_J)\r
108 ** o_ Output sequence to designate single-byte roman characters (DEFAULT_R)\r
109 **\r
110 ** r  {de/en}crypt ROT13/47\r
111 **\r
112 ** v  display Version\r
113 **\r
114 ** T  Text mode output        (for MS-DOS)\r
115 **\r
116 ** x    Do not convert X0201 kana into X0208\r
117 ** Z    Convert X0208 alphabet to ASCII\r
118 **\r
119 ** f60  fold option\r
120 **\r
121 ** m    MIME decode\r
122 ** B    try to fix broken JIS, missing Escape\r
123 ** B[1-9]  broken level\r
124 **\r
125 ** O   Output to 'nkf.out' file \r
126 ** d   Delete \r in line feed \r
127 ** c   Add \r in line feed \r
128 **/\r
129 /******************************/\r
130 /* デフォルトの出力コード選択 */\r
131 /* Select DEFAULT_CODE */\r
132 #define DEFAULT_CODE_JIS\r
133 /* #define DEFAULT_CODE_SJIS */\r
134 /* #define DEFAULT_CODE_EUC */\r
135 /******************************/\r
136 \r
137 #if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS)\r
138 #define MSDOS\r
139 #endif\r
140 \r
141 #include <stdio.h>\r
142 #include <stdlib.h>\r
143 #ifndef NO_STRING_H\r
144 #include <string.h>\r
145 #else\r
146 #include <strings.h>\r
147 #endif\r
148 \r
149 #ifdef MSDOS\r
150 #ifdef LSI_C\r
151 #define setbinmode(fp) fsetbin(fp)\r
152 #else /* Microsoft C, Turbo C */\r
153 #define setbinmode(fp) setmode(fileno(fp), O_BINARY)\r
154 #endif\r
155 #else /* UNIX,OS/2 */\r
156 #define setbinmode(fp)\r
157 #endif\r
158 \r
159 #ifdef _IOFBF /* SysV and MSDOS */\r
160 #define       setvbuffer(fp, buf, size)       setvbuf(fp, buf, _IOFBF, size)\r
161 #else /* BSD */\r
162 #define       setvbuffer(fp, buf, size)       setbuffer(fp, buf, size)\r
163 #endif\r
164 \r
165 #include "nkflib.h"\r
166 \r
167 #define VOIDVOID 0\r
168 \r
169 #ifndef FALSE\r
170 #define FALSE   0\r
171 #endif /* FALSE */\r
172 \r
173 #ifndef TRUE\r
174 #define TRUE    1\r
175 #endif /* TRUE */\r
176 \r
177 /* state of output_mode and input_mode  */\r
178 \r
179 #define         ASCII           0\r
180 #define         X0208           1\r
181 #define         X0201           2\r
182 #define         NO_X0201        3\r
183 #define         JIS_INPUT       4\r
184 #define         SJIS_INPUT      5\r
185 #define         LATIN1_INPUT    6\r
186 #define         FIXED_MIME      7\r
187 #define         DOUBLE_SPACE    -2\r
188 #define         EUC_INPUT       8\r
189 \r
190 #define         NL      0x0a\r
191 #define         ESC     0x1b\r
192 #define         SPACE      0x20\r
193 #define         AT      0x40\r
194 #define         SSP     0xa0\r
195 #define         DEL     0x7f\r
196 #define         SI      0x0f\r
197 #define         SO      0x0e\r
198 #define         SSO     0x8e\r
199 \r
200 #define         HOLD_SIZE       32\r
201 #define         IOBUF_SIZE      16384\r
202 \r
203 #define         DEFAULT_J       'B'\r
204 #define         DEFAULT_R       'B'\r
205 \r
206 #define         SJ0162  0x00e1          /* 01 - 62 ku offset */\r
207 #define         SJ6394  0x0161          /* 63 - 94 ku offset */\r
208 \r
209 \r
210 /* SFILE begin */\r
211 /* 文字列 を FILE みたいに扱う小細工 */\r
212 \r
213 /*\r
214    これは nkf の漢字コード変換がファイルに対してのみ対応しているのでそれを\r
215    文字列操作で使えるようにするためのインターフェースである。ただし、\r
216    対応している機能は少ないし、必要なものしか作っていない。したがって、\r
217    これらは nkf の中でしか意味のないものであろう。\r
218 \r
219    SFILE は FILE みたいなもので文字列をファイルみたいに扱えるようにする。\r
220    SFILE を使うためには必ずオープンすること。sopen で mode=="new" または\r
221    "auto" 指定していなければクローズする必要はない。SFILE の中を直接操作\r
222    した場合はいろいろ問題が出てくるであろう。\r
223 \r
224    SEOF は EOF みたいなもの。\r
225 \r
226    sopen は open みたいな関数で、\r
227       sf : SFILE 型の変数\r
228       st : 文字列\r
229       maxsize : 文字列が許容できる最大の大きさ。sputc 時に制限を入れるもの。\r
230                 maxsize に -1 を指定するとこの処理を無視するようになる。\r
231                 そのときは、必要以上の文字を sputc しないように気をつけなけれ\r
232                 ばならない。\r
233       mode : newstr、stdout、stdin の文字列を指定できる。\r
234              例えば mode="new stdout"\r
235              newstr は自動的に文字列のメモリを maxsize だけ獲得する。\r
236              ただし、maxsize < 1 のときはディフォルトの値を獲得する。\r
237              stdout は SFILE の標準出力 stdout となる文字列を指定する。\r
238              stdin は SFILE の標準入力 stdin となる文字列を指定する。\r
239 \r
240    sclose は close みたいな関数で、newstr でオープンされていたときは、\r
241    文字列も free で消去する。\r
242 \r
243    sgetc、sungetc、sputc、sputchar はそれぞれ getc、ungetc、putc、putchar\r
244    に相当する。引数の sf が NULL の時は SEOF を返す。\r
245 */\r
246 \r
247 typedef struct __SFILE {\r
248   unsigned char *pointer;      /* 文字列現在のポインタ */\r
249   unsigned char *head;         /* 文字列の最初の位置 */\r
250   unsigned char *tail;         /* 文字列の許容の最後の位置 */\r
251   char mode[20];               /* 文字列オープンモード newstr,stdout,stdin */\r
252                                 /* "newstr stdin" の組合わせはない */\r
253 } SFILE;\r
254 #define SEOF -1\r
255 \r
256 static SFILE *sstdout=NULL;\r
257 static SFILE *sstdin=NULL; /* Never used ? */\r
258 #ifndef BUFSIZ\r
259 #define BUFSIZ 1024\r
260 #endif /* BUFSIZ */\r
261 static char sfile_buffer[BUFSIZ];\r
262 #ifndef SAFE_CONVERT_LENGTH\r
263 #define SAFE_CONVERT_LENGTH(len) (2 * (len) + 7)\r
264 #endif /* SAFE_CONVERT_LENGTH */\r
265 \r
266 /* Functions */\r
267 static SFILE *sopen(SFILE *, char *string,signed int maxsize,char *md);\r
268 static void sclose(SFILE *sf);\r
269 static int sgetc(SFILE *sf);\r
270 static int sungetc(int c,SFILE *sf);\r
271 static int sputc(int c,SFILE *sf);\r
272 #define sputchar(c) sputc(c,sstdout)\r
273 \r
274 /* nkf 漢字コンバート */\r
275 char *nkf_convert(char *si,char *so,int maxsize,char *in_mode,char *out_mode);\r
276 char *nkf_conv(char *si,char *so,char *out_mode);\r
277 \r
278 static int check_kanji_code(unsigned char *p);\r
279 \r
280 /* MIME preprocessor */\r
281 \r
282 #undef STRICT_MIME       /* do stupid strict mime integrity check */\r
283 #define GETC(p) ((!mime_mode)?sgetc(p):mime_getc(p))\r
284 #define UNGETC(c,p)     ((!mime_mode)?sungetc(c,p):mime_ungetc(c))\r
285 \r
286 \r
287 #ifdef EASYWIN /*Easy Win */\r
288  POINT _BufferSize;\r
289 #endif\r
290 \r
291 /*      function prototype  */\r
292 \r
293 static  int     noconvert(SFILE *f);\r
294 static  int     kanji_convert(SFILE *f);\r
295 static  int     h_conv(SFILE *f,int c2,int c1);\r
296 static  int     push_hold_buf(int c2,int c1);\r
297 static  int     s_iconv(int c2,int c1);\r
298 static  int     e_oconv(int c2,int c1);\r
299 static  int     s_oconv(int c2,int c1);\r
300 static  int     j_oconv(int c2,int c1);\r
301 static  int     line_fold(int c2,int c1);\r
302 static  int     pre_convert(int c1,int c2);\r
303 static  int     mime_begin(SFILE *f);\r
304 static  int     mime_getc(SFILE *f);\r
305 static  int     mime_ungetc(unsigned int c);\r
306 static  int     mime_integrity(SFILE *f,unsigned char *p);\r
307 static  int     base64decode(int c);\r
308 static  int     usage(void);\r
309 static  void    arguments(char *c);\r
310 static  void    reinit();\r
311 \r
312 /* buffers */\r
313 \r
314 static char            stdibuf[IOBUF_SIZE];\r
315 static char            stdobuf[IOBUF_SIZE];\r
316 static unsigned char   hold_buf[HOLD_SIZE*2];\r
317 static int             hold_count;\r
318 \r
319 /* MIME preprocessor fifo */\r
320 \r
321 #define MIME_BUF_SIZE   (1024)    /* 2^n ring buffer */\r
322 #define MIME_BUF_MASK   (MIME_BUF_SIZE-1)   \r
323 #define Fifo(n)         mime_buf[(n)&MIME_BUF_MASK]\r
324 static unsigned char           mime_buf[MIME_BUF_SIZE];\r
325 static unsigned int            mime_top = 0;\r
326 static unsigned int            mime_last = 0;  /* decoded */\r
327 static unsigned int            mime_input = 0; /* undecoded */\r
328 \r
329 /* flags */\r
330 static int             unbuf_f = FALSE;\r
331 static int             estab_f = FALSE;\r
332 static int             nop_f = FALSE;\r
333 static int             binmode_f = TRUE;       /* binary mode */\r
334 static int             rot_f = FALSE;          /* rot14/43 mode */\r
335 static int             input_f = FALSE;        /* non fixed input code  */\r
336 static int             alpha_f = FALSE;        /* convert JIx0208 alphbet to ASCII */\r
337 static int             mime_f = TRUE;         /* convert MIME B base64 or Q */\r
338 static int             mimebuf_f = FALSE;      /* MIME buffered input */\r
339 static int             broken_f = FALSE;       /* convert ESC-less broken JIS */\r
340 static int             iso8859_f = FALSE;      /* ISO8859 through */\r
341 #if defined(MSDOS) || defined(__OS2__) \r
342 static int             x0201_f = TRUE;         /* Assume JISX0201 kana */\r
343 #else\r
344 static int             x0201_f = NO_X0201;     /* Assume NO JISX0201 */\r
345 #endif\r
346 \r
347 /* X0208 -> ASCII converter */\r
348 \r
349 static int             c1_return;\r
350 \r
351 /* fold parameter */\r
352 static int line = 0;    /* chars in line */\r
353 static int prev = 0;\r
354 static int             fold_f  = FALSE;\r
355 static int             fold_len  = 0;\r
356 \r
357 /* options */\r
358 static char            kanji_intro = DEFAULT_J,\r
359                 ascii_intro = DEFAULT_R;\r
360 \r
361 /* Folding */\r
362 \r
363 int line_fold();\r
364 #define FOLD_MARGIN  10\r
365 #define DEFAULT_FOLD 60\r
366 \r
367 /* converters */\r
368 \r
369 #ifdef DEFAULT_CODE_JIS\r
370 #   define  DEFAULT_CONV j_oconv\r
371 #endif\r
372 #ifdef DEFAULT_CODE_SJIS\r
373 #   define  DEFAULT_CONV s_oconv\r
374 #endif\r
375 #ifdef DEFAULT_CODE_EUC\r
376 #   define  DEFAULT_CONV e_oconv\r
377 #endif\r
378 \r
379 static int             (*iconv)(int c2,int c1);   \r
380                                         /* s_iconv or oconv */\r
381 static int             (*oconv)(int c2,int c1) = DEFAULT_CONV; \r
382                                           /* [ejs]_oconv */\r
383 \r
384 /* Global states */\r
385 static int             output_mode = ASCII,    /* output kanji mode */\r
386                 input_mode =  ASCII,    /* input kanji mode */\r
387                 shift_mode =  FALSE;    /* TRUE shift out, or X0201  */\r
388 static int             mime_mode =   FALSE;    /* MIME mode B base64, Q hex */\r
389 \r
390 /* X0201 / X0208 conversion tables */\r
391 \r
392 /* X0201 kana conversion table */\r
393 /* 90-9F A0-DF */\r
394 unsigned char cv[]= {\r
395 0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,\r
396 0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,\r
397 0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,\r
398 0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,\r
399 0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,\r
400 0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,\r
401 0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,\r
402 0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,\r
403 0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,\r
404 0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,\r
405 0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,\r
406 0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,\r
407 0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,\r
408 0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,\r
409 0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,\r
410 0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,\r
411 0x00,0x00};\r
412 \r
413 \r
414 /* X0201 kana conversion table for daguten */\r
415 /* 90-9F A0-DF */\r
416 unsigned char dv[]= { \r
417 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
418 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
419 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
420 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
421 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
422 0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,\r
423 0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,\r
424 0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,\r
425 0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,\r
426 0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,\r
427 0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,\r
428 0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,\r
429 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
430 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
431 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
432 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
433 0x00,0x00};\r
434 \r
435 /* X0201 kana conversion table for han-daguten */\r
436 /* 90-9F A0-DF */\r
437 unsigned char ev[]= { \r
438 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
439 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
440 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
441 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
442 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
443 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
444 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
445 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
446 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
447 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
448 0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,\r
449 0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,\r
450 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
451 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
452 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
453 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
454 0x00,0x00};\r
455 \r
456 \r
457 /* X0208 kigou conversion table */\r
458 /* 0x8140 - 0x819e */\r
459 unsigned char fv[] = {\r
460 \r
461 0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,\r
462 0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,\r
463 0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,\r
464 0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,\r
465 0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,\r
466 0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,\r
467 0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,\r
468 0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,\r
469 0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,\r
470 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
471 0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,\r
472 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
473 } ;\r
474 \r
475 \r
476 /* SFILE 関連関数 */\r
477 \r
478 static SFILE *\r
479 sopen(SFILE *sf, char *string, signed int maxsize, char *md)\r
480 {\r
481   char *st;\r
482   strcpy(sf->mode,md);\r
483   if (strstr(sf->mode,"newstr"))\r
484   {\r
485       if(maxsize <= sizeof(sfile_buffer))\r
486           st = sfile_buffer;\r
487       else\r
488           st = (char *)malloc(maxsize);\r
489   }\r
490   else\r
491     st=string;\r
492   sf->pointer=sf->head=(unsigned char *)st;\r
493   if (strstr(sf->mode,"stdout"))\r
494     sstdout=sf;\r
495   else if (strstr(sf->mode,"stdin"))\r
496   {\r
497     sstdin=sf;\r
498     maxsize=strlen((char *)st);\r
499   }\r
500   sf->tail=sf->head+maxsize;\r
501   return sf;\r
502 }\r
503 \r
504 static void\r
505 sclose(SFILE *sf)\r
506 {\r
507   if (sf==NULL)\r
508     return;\r
509   if (strstr(sf->mode,"stdout"))\r
510       sstdout=NULL;\r
511   if (strstr(sf->mode,"stdin"))\r
512       sstdin=NULL;\r
513   if (strstr(sf->mode,"newstr") && sf->head != (unsigned char *)sfile_buffer)\r
514       free(sf->head);\r
515 }\r
516 \r
517 static int\r
518 sgetc(SFILE *sf)\r
519 {\r
520   if (sf==NULL)\r
521     return SEOF;\r
522   if(sf->pointer<sf->tail)\r
523       return (int)*sf->pointer++;\r
524   return SEOF;\r
525 }\r
526 \r
527 static int\r
528 sungetc(int c, SFILE *sf)\r
529 {\r
530   if (sf==NULL)\r
531     return SEOF;\r
532   if (sf->head<sf->pointer) {\r
533     *--sf->pointer=(unsigned char)c;\r
534     return c;\r
535   } else\r
536     return SEOF;\r
537 }\r
538 \r
539 static int\r
540 sputc(int c, SFILE *sf)\r
541 {\r
542   if (sf==NULL)\r
543     return SEOF;\r
544   if (sf->pointer<sf->tail)\r
545       return (int)(*sf->pointer++=(unsigned char)c);\r
546   return SEOF;\r
547 }\r
548 \r
549 /* public 関数 start */\r
550 \r
551 /* nkf 漢字コンバート関数 */\r
552 /* si must be terminated with '\0' */\r
553 char *\r
554 nkf_convert(char *si, char *so, int maxsize, char *in_mode, char *out_mode)\r
555 {\r
556 /* 前処理 */\r
557   SFILE *fi,*fo;\r
558   SFILE xfi,xfo;\r
559   int a;\r
560 \r
561   reinit(); /* 使用? */\r
562 \r
563   if(maxsize == -1)\r
564     maxsize = SAFE_CONVERT_LENGTH(strlen(si));\r
565   else if(maxsize == 0)\r
566     return si;\r
567 \r
568   fi = &xfi;\r
569   fo = &xfo;\r
570   if (so!=NULL) {\r
571     sopen(fi,si,0,"stdin");\r
572     sopen(fo,so,maxsize,"stdout");\r
573   } else {\r
574     sopen(fi,si,0,"stdin");\r
575     sopen(fo,so,maxsize,"newstr stdout");\r
576   }\r
577 \r
578 /* 変数をデフォルト設定 */\r
579   unbuf_f = FALSE;\r
580   estab_f = FALSE;\r
581   rot_f = FALSE;        /* rot14/43 mode */\r
582   input_f = FALSE;      /* non fixed input code  */\r
583   alpha_f = FALSE;      /* convert JIx0208 alphbet to ASCII */\r
584   mime_f = FALSE;       /* convert MIME base64 */\r
585   broken_f = FALSE;     /* convert ESC-less broken JIS */\r
586   iso8859_f = FALSE;    /* ISO8859 through */\r
587 #ifdef MSDOS\r
588   x0201_f = TRUE;       /* Assume JISX0201 kana */\r
589 #else\r
590   x0201_f = NO_X0201;   /* Assume NO JISX0201 */\r
591 #endif\r
592   line = 0;     /* chars in line */\r
593   prev = 0;\r
594   fold_f  = FALSE;\r
595   fold_len  = 0;\r
596   kanji_intro = DEFAULT_J;\r
597   ascii_intro = DEFAULT_R;\r
598   output_mode = ASCII;  /* output kanji mode */\r
599   input_mode = ASCII;   /* input kanji mode */\r
600   shift_mode = FALSE;   /* TRUE shift out, or X0201  */\r
601   mime_mode = FALSE;    /* MIME mode B base64, Q hex */\r
602   \r
603 #if     0\r
604 /* No X0201->X0208 conversion 半角カナを有効に*/\r
605   x0201_f = FALSE;\r
606 #else\r
607 /* 半角カナを全角にする */\r
608   x0201_f = TRUE;\r
609 #endif\r
610 \r
611 /* オプション mode 解析 */\r
612   oconv=e_oconv;\r
613   if (strstr(out_mode,"EUCK")||strstr(out_mode,"euck")||strstr(out_mode,"ujisk")){\r
614     /*Hankaku Enable (For WRD File )*/\r
615     oconv=e_oconv; \r
616     /* No X0201->X0208 conversion 半角カナを有効に*/\r
617     x0201_f = FALSE;\r
618   }\r
619   else if (strstr(out_mode,"SJISK")||strstr(out_mode,"sjisk")){\r
620     /*Hankaku Enable (For WRD File )*/\r
621     oconv=s_oconv; \r
622     /* No X0201->X0208 conversion 半角カナを有効に*/\r
623     x0201_f = FALSE;\r
624   }\r
625   else if (strstr(out_mode,"JISK")||strstr(out_mode,"jisk")){\r
626     /*Hankaku Enable (For WRD File )*/\r
627     oconv=j_oconv; \r
628     /* No X0201->X0208 conversion 半角カナを有効に*/\r
629     x0201_f = FALSE;\r
630   }\r
631   else if (strstr(out_mode,"EUC")||strstr(out_mode,"euc")||strstr(out_mode,"ujis"))\r
632     oconv=e_oconv;\r
633   else if (strstr(out_mode,"SJIS")||strstr(out_mode,"sjis"))\r
634     oconv=s_oconv;\r
635   else if (strstr(out_mode,"JIS")||strstr(out_mode,"jis"))\r
636     oconv=j_oconv;\r
637   /* 読み込みコードのチェック */\r
638   input_f = -1;\r
639   if(in_mode != NULL)\r
640   {\r
641       if(strstr(in_mode,"EUC")||strstr(in_mode,"euc")||strstr(in_mode,"ujis"))\r
642           input_f = JIS_INPUT;\r
643       else if (strstr(in_mode,"SJIS")||strstr(in_mode,"sjis"))\r
644           input_f = SJIS_INPUT;\r
645       else if (strstr(in_mode,"JIS")||strstr(in_mode,"jis"))\r
646           input_f = JIS_INPUT;\r
647   }\r
648   if(input_f == -1)\r
649   {\r
650       /* Auto detect */\r
651       input_f = check_kanji_code((unsigned char *)si);\r
652       if(input_f == -1)\r
653           input_f = SJIS_INPUT;\r
654       else if(input_f == EUC_INPUT)\r
655           input_f = JIS_INPUT;\r
656       if(input_f == SJIS_INPUT && x0201_f == NO_X0201)\r
657           x0201_f = TRUE;\r
658   }\r
659 \r
660   /* コンバート */\r
661   kanji_convert(fi);\r
662 \r
663 /* 後処理 */\r
664   sputchar('\0');\r
665   if (so==NULL) {\r
666     /* Copy `fo' buffer to `si' */\r
667 \r
668     a = fo->pointer - fo->head; /* Stored length */\r
669     if(a > maxsize)\r
670         a = maxsize;\r
671     memcpy(si, fo->head, a); /* Do copy */\r
672     so = si;\r
673   }\r
674   sclose(fi);\r
675   sclose(fo);\r
676   return so;\r
677 }\r
678 \r
679 char *\r
680 nkf_conv(char *si, char *so, char *mode)\r
681 {\r
682   return nkf_convert(si,so,-1,NULL,mode);\r
683 }\r
684 \r
685 /* public 関数 end */\r
686 \r
687 #define IS_SJIS_HANKAKU(c)      (0xa0 <= (c) && (c) <= 0xdf)\r
688 #define IS_SJIS_BYTE1(c)        ((0x81 <= (c) && (c) <= 0x9f) ||\\r
689                                  (0xe0 <= (c) && (c) <= 0xfc))\r
690 #define IS_SJIS_BYTE2(c)        ((0x40 <= (c) && (c) <= 0x7e) ||\\r
691                                  (0x80 <= (c) && (c) <= 0xfc))\r
692 \r
693 #define IS_EUC_BYTE1(c)         (0xa1 <= (c) && (c) <= 0xf4)\r
694 #ifdef EUC_STRICT_CHECK\r
695 #define IS_EUC_BYTE2(c)         (0xa1 <= (c) && (c) <= 0xfe)\r
696 #else\r
697 #define IS_EUC_BYTE2(c)         (0xa0 <= (c) && (c) <= 0xff)\r
698 #endif /* EUC_STRICT_CHECK */\r
699 \r
700 \r
701 #ifdef EUC_STRICT_CHECK\r
702 #define EUC_GAP_LIST_SIZE (16*2)\r
703 static unsigned int euc_gap_list[EUC_GAP_LIST_SIZE] =\r
704 {\r
705     0xa2af, 0xa2b9,\r
706     0xa2c2, 0xa2c9,\r
707     0xa2d1, 0xa2db,\r
708     0xa2eb, 0xa2f1,\r
709     0xa2fa, 0xa2fd,\r
710     0xa3a1, 0xa3af,\r
711     0xa3ba, 0xa3c0,\r
712     0xa3db, 0xa3e0,\r
713     0xa3fb, 0xa3fe,\r
714     0xa4f4, 0xa4fe,\r
715     0xa5f7, 0xa5fe,\r
716     0xa6b9, 0xa6c0,\r
717     0xa6d9, 0xa6fe,\r
718     0xa7c2, 0xa7d0,\r
719     0xa7f2, 0xa7fe,\r
720     0xa8c1, 0xaffe\r
721 };\r
722 #endif /* EUC_STRICT_CHECK */\r
723 \r
724 static int check_kanji_code(unsigned char *p)\r
725 {\r
726     int c1, c2, mode;\r
727     int noteuc;\r
728 \r
729     /* check JIS or ASCII code */\r
730     mode = ASCII;\r
731     while(*p)\r
732     {\r
733         if(*p < SPACE || *p >= DEL)\r
734         {\r
735             if(*p == ESC)\r
736                 return JIS_INPUT;\r
737             mode = -1; /* None ASCII */\r
738             break;\r
739         }\r
740         p++;\r
741     }\r
742     if(mode == ASCII)\r
743         return ASCII;\r
744 \r
745     /* EUC or SJIS */\r
746     noteuc = 0;\r
747     while(*p)\r
748     {\r
749         /* skip ASCII */\r
750         while(*p && *p <= DEL)\r
751             p++;\r
752 \r
753         if(!*p)\r
754             return -1;\r
755         c1 = p[0];\r
756         c2 = p[1];\r
757         if(c2 == 0)\r
758         {\r
759             if(IS_SJIS_HANKAKU(c1))\r
760                 return SJIS_INPUT;\r
761             return -1;\r
762         }\r
763 \r
764         if(IS_SJIS_HANKAKU(c1))\r
765         {\r
766 #ifdef EUC_STRICT_CHECK\r
767             unsigned int c;\r
768 #endif /* EUC_STRICT_CHECK */\r
769 /*\r
770             0xa0   0xa1              0xdf   0xf4   0xfe\r
771              |<-----+---- SH -------->|      |      |     SH: SJIS-HANKAKU\r
772                     |<------- E1 ----------->|      |     E1: EUC (MSB)\r
773                     |<--------E2------------------->|     E2: EUC (LSB)\r
774 */\r
775             if(!IS_EUC_BYTE1(c1) || !IS_EUC_BYTE2(c2))\r
776                 return SJIS_INPUT;\r
777             if(!IS_SJIS_HANKAKU(c2)) /* (0xdf..0xfe] */\r
778                 return EUC_INPUT;\r
779 #ifdef EUC_STRICT_CHECK\r
780             if(!noteuc)\r
781             {\r
782                 int i;\r
783                 /* Checking more strictly */\r
784                 c = (((unsigned int)c1)<<8 | (unsigned int)c2);\r
785                 for(i = 0; i < EUC_GAP_LIST_SIZE; i += 2)\r
786                     if(euc_gap_list[i] <= c && c <= euc_gap_list[i + 1])\r
787                     {\r
788                         noteuc = 1;\r
789                         break;\r
790                     }\r
791             }\r
792 #endif /* EUC_STRICT_CHECK */\r
793             p += 2;\r
794         }\r
795         else if(IS_SJIS_BYTE1(c1) && IS_SJIS_BYTE2(c2))\r
796         {\r
797             if(!(IS_EUC_BYTE1(c1) && IS_EUC_BYTE2(c2)))\r
798                 return SJIS_INPUT;\r
799             p += 2;\r
800         }\r
801         else if(IS_EUC_BYTE1(c1) && IS_EUC_BYTE2(c2))\r
802         {\r
803             return EUC_INPUT;\r
804         }\r
805         else\r
806             p++; /* What?  Is this japanese?  Try check again. */\r
807     }\r
808     if(noteuc)\r
809         return SJIS_INPUT;\r
810     return -1;\r
811 }\r
812 \r
813 #ifdef EUC_STRICT_CHECK\r
814 static void fix_euc_code(unsigned char *s, int len)\r
815 {\r
816     int i, j, c;\r
817 \r
818     for(i = 0; i < len - 1; i++)\r
819     {\r
820         if(s[i] & 0x80)\r
821         {\r
822             c = (((unsigned int)s[i])<<8 | (unsigned int)s[i + 1]);\r
823             for(j = 0; j < EUC_GAP_LIST_SIZE; j += 2)\r
824                 if(euc_gap_list[j] <= c && c <= euc_gap_list[j + 1])\r
825                 {\r
826                     s[i] = 0xa1;\r
827                     s[i + 1] = 0xa1;\r
828                     break;\r
829                 }\r
830             i++;\r
831         }\r
832     }\r
833 }\r
834 #endif /* EUC_STRICT_CHECK */\r
835 \r
836 \r
837 static int             file_out = FALSE;\r
838 static int             add_cr = FALSE;\r
839 static int             del_cr = FALSE;\r
840 static int             end_check;\r
841 \r
842 #if 0\r
843 #ifndef PERL_XS\r
844 int\r
845 main(argc, argv)\r
846     int             argc;\r
847     char          **argv;\r
848 {\r
849     FILE  *fin;\r
850     char  *cp;\r
851 \r
852 #ifdef EASYWIN /*Easy Win */\r
853     _BufferSize.y = 400;/*Set Scroll Buffer Size*/\r
854 #endif\r
855 \r
856     for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {\r
857         cp = *argv;\r
858         arguments(cp);\r
859     }\r
860 \r
861     if(iso8859_f && (oconv != j_oconv || !x0201_f )) {\r
862         fprintf(stderr,"Mixed ISO8859/JISX0201/SJIS/EUC output is not allowed.\n");\r
863         exit(1);\r
864     }\r
865 \r
866     if(binmode_f == TRUE)\r
867 #ifdef __OS2__\r
868     if(freopen("","wb",stdout) == NULL) \r
869         return (-1);\r
870 #else\r
871     setbinmode(stdout);\r
872 #endif\r
873 \r
874     if(unbuf_f)\r
875       setbuf(stdout, (char *) NULL);\r
876     else\r
877       setvbuffer(stdout, stdobuf, IOBUF_SIZE);\r
878 \r
879     if(argc == 0) {\r
880       if(binmode_f == TRUE)\r
881 #ifdef __OS2__\r
882       if(freopen("","rb",stdin) == NULL) return (-1);\r
883 #else\r
884       setbinmode(stdin);\r
885 #endif\r
886       setvbuffer(stdin, stdibuf, IOBUF_SIZE);\r
887       if(nop_f)\r
888           noconvert(stdin);\r
889       else\r
890           kanji_convert(stdin);\r
891     } else {\r
892       while (argc--) {\r
893           if((fin = fopen(*argv++, "r")) == NULL) {\r
894               perror(*--argv);\r
895               return(-1);\r
896           } else {\r
897 /* reopen file for stdout */\r
898               if(file_out == TRUE){ \r
899                   if(argc == 1 ) {\r
900                       if(freopen(*argv++, "w", stdout) == NULL) {\r
901                           perror(*--argv);\r
902                           return (-1);\r
903                       }\r
904                       argc--;\r
905                   } else {\r
906                       if(freopen("nkf.out", "w", stdout) == NULL) {\r
907                          perror(*--argv);\r
908                          return (-1);\r
909                       }\r
910                   }\r
911                   if(binmode_f == TRUE) {\r
912 #ifdef __OS2__\r
913                       if(freopen("","wb",stdout) == NULL) \r
914                            return (-1);\r
915 #else\r
916                       setbinmode(stdout);\r
917 #endif\r
918                   }\r
919               }\r
920               if(binmode_f == TRUE)\r
921 #ifdef __OS2__\r
922                  if(freopen("","rb",fin) == NULL) \r
923                     return (-1);\r
924 #else\r
925                  setbinmode(fin);\r
926 #endif \r
927               setvbuffer(fin, stdibuf, IOBUF_SIZE);\r
928               if(nop_f)\r
929                   noconvert(fin);\r
930               else\r
931                   kanji_convert(fin);\r
932               fclose(fin);\r
933           }\r
934       }\r
935     }\r
936 #ifdef EASYWIN /*Easy Win */\r
937     if(file_out == FALSE) \r
938         scanf("%d",&end_check);\r
939     else \r
940         fclose(stdout);\r
941 #else /* for Other OS */\r
942     if(file_out == TRUE) \r
943         fclose(stdout);\r
944 #endif \r
945     return (0);\r
946 }\r
947 #endif\r
948 \r
949 void\r
950 arguments(char *cp) \r
951 {\r
952     while (*cp) {\r
953         switch (*cp++) {\r
954         case 'b':           /* buffered mode */\r
955             unbuf_f = FALSE;\r
956             continue;\r
957         case 'u':           /* non bufferd mode */\r
958             unbuf_f = TRUE;\r
959             continue;\r
960         case 't':           /* transparent mode */\r
961             nop_f = TRUE;\r
962             continue;\r
963         case 'j':           /* JIS output */\r
964         case 'n':\r
965             oconv = j_oconv;\r
966             continue;\r
967         case 'e':           /* AT&T EUC output */\r
968             oconv = e_oconv;\r
969             continue;\r
970         case 's':           /* SJIS output */\r
971             oconv = s_oconv;\r
972             continue;\r
973         case 'l':           /* ISO8859 Latin-1 support, no conversion */\r
974             iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */\r
975             input_f = LATIN1_INPUT;\r
976             continue;\r
977         case 'i':           /* Kanji IN ESC-$-@/B */\r
978             if(*cp=='@'||*cp=='B') \r
979                 kanji_intro = *cp++;\r
980             continue;\r
981         case 'o':           /* ASCII IN ESC-(-J/B */\r
982             if(*cp=='J'||*cp=='B'||*cp=='H') \r
983                 ascii_intro = *cp++;\r
984             continue;\r
985         case 'r':\r
986             rot_f = TRUE;\r
987             continue;\r
988 #if defined(MSDOS) || defined(__OS2__) \r
989         case 'T':\r
990             binmode_f = FALSE;\r
991             continue;\r
992 #endif\r
993 #ifndef PERL_XS\r
994         case 'v':\r
995             usage();\r
996             exit(1);\r
997             break;\r
998 #endif\r
999         /* Input code assumption */\r
1000         case 'J':   /* JIS input */\r
1001         case 'E':   /* AT&T EUC input */\r
1002             input_f = JIS_INPUT;\r
1003             continue;\r
1004         case 'S':   /* MS Kanji input */\r
1005             input_f = SJIS_INPUT;\r
1006             if(x0201_f==NO_X0201) x0201_f=TRUE;\r
1007             continue;\r
1008         case 'Z':   /* Convert X0208 alphabet to asii */\r
1009             /*  bit:0   Convert X0208\r
1010                 bit:1   Convert Kankaku to one space\r
1011                 bit:2   Convert Kankaku to two spaces\r
1012             */\r
1013             if('9'>= *cp && *cp>='0') \r
1014                 alpha_f |= 1<<(*cp++ -'0');\r
1015             else \r
1016                 alpha_f |= TRUE;\r
1017             continue;\r
1018         case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */\r
1019             x0201_f = FALSE;    /* No X0201->X0208 conversion */\r
1020             /* accept  X0201\r
1021                     ESC-(-I     in JIS, EUC, MS Kanji\r
1022                     SI/SO       in JIS, EUC, MS Kanji\r
1023                     SSO         in EUC, JIS, not in MS Kanji\r
1024                     MS Kanji (0xa0-0xdf) \r
1025                output  X0201\r
1026                     ESC-(-I     in JIS (0x20-0x5f)\r
1027                     SSO         in EUC (0xa0-0xdf)\r
1028                     0xa0-0xd    in MS Kanji (0xa0-0xdf) \r
1029             */\r
1030             continue;\r
1031         case 'X':   /* Assume X0201 kana */\r
1032             /* Default value is NO_X0201 for EUC/MS-Kanji mix */\r
1033             x0201_f = TRUE;\r
1034             continue;\r
1035         case 'f':   /* folding -f60 or -f */\r
1036             fold_f = TRUE;\r
1037             fold_len = atoi(cp);\r
1038             if(!(0<fold_len && fold_len<BUFSIZ)) \r
1039                 fold_len = DEFAULT_FOLD;\r
1040             while('0'<= *cp && *cp <='9') cp++;\r
1041             continue;\r
1042         case 'm':   /* MIME support */\r
1043             mime_f = TRUE;\r
1044             if(*cp=='B'||*cp=='Q') {\r
1045                 mime_mode = *cp++;\r
1046                 mimebuf_f = FIXED_MIME;\r
1047             } else if (*cp=='0') {\r
1048                 mime_f = FALSE;\r
1049             }\r
1050             continue;\r
1051         case 'M':   /* MIME output */\r
1052             oconv = j_oconv;    /* sorry... not yet done.. */\r
1053             continue;\r
1054         case 'B':   /* Broken JIS support */\r
1055             /*  bit:0   no ESC JIS\r
1056                 bit:1   allow any x on ESC-(-x or ESC-$-x\r
1057                 bit:2   reset to ascii on NL\r
1058             */\r
1059             if('9'>= *cp && *cp>='0') \r
1060                 broken_f |= 1<<(*cp++ -'0');\r
1061             else \r
1062                 broken_f |= TRUE;\r
1063             continue;\r
1064 #ifndef PERL_XS\r
1065         case 'O':/* for Output file */\r
1066             file_out = TRUE;\r
1067             continue;\r
1068 #endif\r
1069         case 'c':/* add cr code */\r
1070             add_cr = TRUE;\r
1071             continue;\r
1072         case 'd':/* delete cr code */\r
1073             del_cr = TRUE;\r
1074             continue;\r
1075         default:\r
1076             /* bogus option but ignored */\r
1077             continue;\r
1078         }\r
1079     }\r
1080 }\r
1081 #endif\r
1082 \r
1083 int\r
1084 noconvert(SFILE  *f)\r
1085 {\r
1086     int    c;\r
1087 \r
1088     while ((c = sgetc(f)) != EOF)\r
1089       sputchar(c);\r
1090     return 1;\r
1091 }\r
1092 \r
1093 \r
1094 \r
1095 \r
1096 int\r
1097 kanji_convert(SFILE  *f)\r
1098 {\r
1099     int    c1, c2;\r
1100 \r
1101     c2 = 0;\r
1102 \r
1103     if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) {\r
1104         estab_f = TRUE; iconv = oconv;\r
1105     } else if(input_f == SJIS_INPUT) {\r
1106         estab_f = TRUE;  iconv = s_iconv;\r
1107     } else {\r
1108         estab_f = FALSE; iconv = oconv;\r
1109     }\r
1110     input_mode = ASCII;\r
1111     output_mode = ASCII;\r
1112     shift_mode = FALSE;\r
1113 \r
1114 #define NEXT continue      /* no output, get next */\r
1115 #define SEND ;             /* output c1 and c2, get next */\r
1116 #define LAST break         /* end of loop, go closing  */\r
1117 \r
1118     while ((c1 = GETC(f)) != EOF) {\r
1119         if(c2) {\r
1120             /* second byte */\r
1121             if(c2 > DEL) {\r
1122                 /* in case of 8th bit is on */\r
1123                 if(!estab_f) {\r
1124                     /* in case of not established yet */\r
1125                     if(c1 > SSP) {\r
1126                         /* It is still ambiguious */\r
1127                         h_conv(f, c2, c1);\r
1128                         c2 = 0;\r
1129                         NEXT;\r
1130                     } else if(c1 < AT) {\r
1131                         /* ignore bogus code */\r
1132                         c2 = 0;\r
1133                         NEXT;\r
1134                     } else {\r
1135                         /* established */\r
1136                         /* it seems to be MS Kanji */\r
1137                         estab_f = TRUE;\r
1138                         iconv = s_iconv;\r
1139                         SEND;\r
1140                     }\r
1141                 } else\r
1142                     /* in case of already established */\r
1143                     if(c1 < AT) {\r
1144                         /* ignore bogus code */\r
1145                         c2 = 0;\r
1146                         NEXT;\r
1147                     } else\r
1148                         SEND;\r
1149             } else\r
1150                 /* 7 bit code */\r
1151                 /* it might be kanji shitfted */\r
1152                 if((c1 == DEL) || (c1 <= SPACE)) {\r
1153                     /* ignore bogus first code */\r
1154                     c2 = 0;\r
1155                     NEXT;\r
1156                 } else\r
1157                     SEND;\r
1158         } else {\r
1159             /* first byte */\r
1160             if(c1 > DEL) {\r
1161                 /* 8 bit code */\r
1162                 if(!estab_f && !iso8859_f) {\r
1163                     /* not established yet */\r
1164                     if(c1 < SSP) {\r
1165                         /* it seems to be MS Kanji */\r
1166                         estab_f = TRUE;\r
1167                         iconv = s_iconv;\r
1168                     } else if(c1 < 0xe0) {\r
1169                         /* it seems to be EUC */\r
1170                         estab_f = TRUE;\r
1171                         iconv = oconv;\r
1172                     } else {\r
1173                         /* still ambiguious */\r
1174                     }\r
1175                     c2 = c1;\r
1176                     NEXT;\r
1177                 } else { /* estab_f==TRUE */\r
1178                     if(iso8859_f) {\r
1179                         SEND;\r
1180                     } else if(SSP<=c1 && c1<0xe0 && iconv == s_iconv) {\r
1181                         /* SJIS X0201 Case... */\r
1182                         /* This is too arrogant, but ... */\r
1183                         if(x0201_f==NO_X0201) {\r
1184                             iconv = oconv;\r
1185                             c2 = c1;\r
1186                             NEXT;\r
1187                         } else \r
1188                         if(x0201_f) {\r
1189                             if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {\r
1190                             /* look ahead for X0201/X0208conversion */\r
1191                                 if((c2 = GETC(f)) == EOF) {\r
1192                                     (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1193                                     LAST;\r
1194                                 } else if(c2==(0xde)) { /* 濁点 */\r
1195                                     (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);\r
1196                                     c2=0; \r
1197                                     NEXT;\r
1198                                 } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { \r
1199                                     /* 半濁点 */\r
1200                                     (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);\r
1201                                     c2=0; \r
1202                                     NEXT;\r
1203                                 } \r
1204                                 UNGETC(c2,f); c2 = 0;\r
1205                             }\r
1206                             (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1207                             NEXT;\r
1208                         } else\r
1209                             SEND;\r
1210                     } else if(c1==SSO && iconv != s_iconv) {\r
1211                         /* EUC X0201 Case */\r
1212                         /* This is too arrogant\r
1213                         if(x0201_f == NO_X0201) {\r
1214                             estab_f = FALSE; \r
1215                             c2 = 0;  \r
1216                             NEXT;\r
1217                         } */\r
1218                         c1 = GETC(f);  /* skip SSO */\r
1219                         euc_1byte_check:\r
1220                         if(x0201_f && SSP<=c1 && c1<0xe0) {\r
1221                             if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {\r
1222                                 if((c2 = GETC(f)) == EOF) {\r
1223                                     (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1224                                     LAST;\r
1225                                 }\r
1226                                 /* forward lookup 濁点/半濁点 */\r
1227                                 if(c2 != SSO) {\r
1228                                     UNGETC(c2,f); c2 = 0; \r
1229                                     (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1230                                     NEXT;\r
1231                                 } else if((c2 = GETC(f)) == EOF) {\r
1232                                     (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1233                                     (*oconv)(0,SSO); \r
1234                                     LAST;\r
1235                                 } else if(c2==(0xde)) { /* 濁点 */\r
1236                                     (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);\r
1237                                     c2=0; \r
1238                                     NEXT;\r
1239                                 } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { \r
1240                                     /* 半濁点 */\r
1241                                     (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);\r
1242                                     c2=0; \r
1243                                     NEXT;\r
1244                                 } else {\r
1245                                     (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1246                                     /* we have to check this c2 */\r
1247                                     /* and no way to push back SSO */\r
1248                                     c1 = c2; c2 = 0;\r
1249                                     goto euc_1byte_check;\r
1250                                 }\r
1251                             }\r
1252                             (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1253                             NEXT;\r
1254                         } else \r
1255                             SEND;\r
1256                     } else if(c1 < SSP && iconv != s_iconv) {\r
1257                         /* strange code in EUC */\r
1258                         iconv = s_iconv;  /* try SJIS */\r
1259                         c2 = c1;\r
1260                         NEXT;\r
1261                     } else {\r
1262                        /* already established */\r
1263                        c2 = c1;\r
1264                        NEXT;\r
1265                     }\r
1266                 }\r
1267             } else if((c1 > SPACE) && (c1 != DEL)) {\r
1268                 /* in case of Roman characters */\r
1269                 if(shift_mode) { \r
1270                     c1 |= 0x80;\r
1271                     /* output 1 shifted byte */\r
1272                     if(x0201_f && (!iso8859_f||input_mode==X0201) && \r
1273                             SSP<=c1 && c1<0xe0 ) {\r
1274                         if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {\r
1275                             if((c2 = GETC(f)) == EOF) {\r
1276                                 (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1277                                 LAST;\r
1278                             } else if(c2==(0xde&0x7f)) { /* 濁点 */\r
1279                                 (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);\r
1280                                 c2=0; \r
1281                                 NEXT;\r
1282                             } else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) {  \r
1283                                 /* 半濁点 */\r
1284                                 (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);\r
1285                                 c2=0; \r
1286                                 NEXT;\r
1287                             }\r
1288                             UNGETC(c2,f); c2 = 0;\r
1289                         }\r
1290                         (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);\r
1291                         NEXT;\r
1292                     } else\r
1293                         SEND;\r
1294                 } else if(c1 == '(' && broken_f && input_mode == X0208\r
1295                         && !mime_mode ) {\r
1296                     /* Try to recover missing escape */\r
1297                     if((c1 = GETC(f)) == EOF) {\r
1298                         (*oconv)(0, '(');\r
1299                         LAST;\r
1300                     } else {\r
1301                         if(c1 == 'B' || c1 == 'J' || c1 == 'H') {\r
1302                             input_mode = ASCII; shift_mode = FALSE;\r
1303                             NEXT;\r
1304                         } else {\r
1305                             (*oconv)(0, '(');\r
1306                             /* do not modify various input_mode */\r
1307                             /* It can be vt100 sequence */\r
1308                             SEND;\r
1309                         }\r
1310                     }\r
1311                 } else if(input_mode == X0208) {\r
1312                     /* in case of Kanji shifted */\r
1313                     c2 = c1;\r
1314                     NEXT;\r
1315                     /* goto next_byte */\r
1316                 } else if(c1 == '=' && mime_f && !mime_mode ) {\r
1317                     if((c1 = sgetc(f)) == EOF) {\r
1318                         (*oconv)(0, '=');\r
1319                         LAST;\r
1320                     } else if(c1 == '?') {\r
1321                         /* =? is mime conversion start sequence */\r
1322                         if(mime_begin(f) == EOF) /* check in detail */\r
1323                             LAST;\r
1324                         else\r
1325                             NEXT;\r
1326                     } else {\r
1327                         (*oconv)(0, '=');\r
1328                         sungetc(c1,f);\r
1329                         NEXT;\r
1330                     }\r
1331                 } else if(c1 == '$' && broken_f && !mime_mode) {\r
1332                     /* try to recover missing escape */\r
1333                     if((c1 = GETC(f)) == EOF) {\r
1334                         (*oconv)(0, '$');\r
1335                         LAST;\r
1336                     } else if(c1 == '@'|| c1 == 'B') {\r
1337                         /* in case of Kanji in ESC sequence */\r
1338                         input_mode = X0208;\r
1339                         shift_mode = FALSE;\r
1340                         NEXT;\r
1341                     } else {\r
1342                         /* sorry */\r
1343                         (*oconv)(0, '$');\r
1344                         (*oconv)(0, c1);\r
1345                         NEXT;\r
1346                     }\r
1347                 } else\r
1348                     SEND;\r
1349             } else if(c1 == SI) {\r
1350                 shift_mode = FALSE; \r
1351                 NEXT;\r
1352             } else if(c1 == SO) {\r
1353                 shift_mode = TRUE; \r
1354                 NEXT;\r
1355             } else if(c1 == ESC ) {\r
1356                 if((c1 = GETC(f)) == EOF) {\r
1357                     (*oconv)(0, ESC);\r
1358                     LAST;\r
1359                 } else if(c1 == '$') {\r
1360                     if((c1 = GETC(f)) == EOF) {\r
1361                         (*oconv)(0, ESC);\r
1362                         (*oconv)(0, '$');\r
1363                         LAST;\r
1364                     } else if(c1 == '@'|| c1 == 'B') {\r
1365                         /* This is kanji introduction */\r
1366                         input_mode = X0208;\r
1367                         shift_mode = FALSE;\r
1368                         NEXT;\r
1369                     } else if(c1 == '(') {\r
1370                         if((c1 = GETC(f)) == EOF) {\r
1371                             (*oconv)(0, ESC);\r
1372                             (*oconv)(0, '$');\r
1373                             (*oconv)(0, '(');\r
1374                             LAST;\r
1375                         } else if(c1 == '@'|| c1 == 'B') {\r
1376                             /* This is kanji introduction */\r
1377                             input_mode = X0208;\r
1378                             shift_mode = FALSE;\r
1379                             NEXT;\r
1380                         } else {\r
1381                             (*oconv)(0, ESC);\r
1382                             (*oconv)(0, '$');\r
1383                             (*oconv)(0, '(');\r
1384                             (*oconv)(0, c1);\r
1385                             NEXT;\r
1386                         }\r
1387                     } else if(broken_f&0x2) {\r
1388                         input_mode = X0208;\r
1389                         shift_mode = FALSE;\r
1390                         NEXT;\r
1391                     } else {\r
1392                         (*oconv)(0, ESC);\r
1393                         (*oconv)(0, '$');\r
1394                         (*oconv)(0, c1);\r
1395                         NEXT;\r
1396                     }\r
1397                 } else if(c1 == '(') {\r
1398                     if((c1 = GETC(f)) == EOF) {\r
1399                         (*oconv)(0, ESC);\r
1400                         (*oconv)(0, '(');\r
1401                         LAST;\r
1402                     } else {\r
1403                         if(c1 == 'I') {\r
1404                             /* This is X0201 kana introduction */\r
1405                             input_mode = X0201; shift_mode = X0201;\r
1406                             NEXT;\r
1407                         } else if(c1 == 'B' || c1 == 'J' || c1 == 'H') {\r
1408                             /* This is X0208 kanji introduction */\r
1409                             input_mode = ASCII; shift_mode = FALSE;\r
1410                             NEXT;\r
1411                         } else if(broken_f&0x2) {\r
1412                             input_mode = ASCII; shift_mode = FALSE;\r
1413                             NEXT;\r
1414                         } else {\r
1415                             (*oconv)(0, ESC);\r
1416                             (*oconv)(0, '(');\r
1417                             /* maintain various input_mode here */\r
1418                             SEND;\r
1419                         }\r
1420                     }\r
1421                 } else {\r
1422                     /* lonely ESC  */\r
1423                     (*oconv)(0, ESC);\r
1424                     SEND;\r
1425                 }\r
1426             } else if(c1 == NL && broken_f&4) {\r
1427                 input_mode = ASCII; \r
1428                 SEND;\r
1429             } else\r
1430                 SEND;\r
1431         }\r
1432         /* send: */\r
1433         if(input_mode == X0208) \r
1434             (*oconv)(c2, c1);  /* this is JIS, not SJIS/EUC case */\r
1435         else\r
1436             (*iconv)(c2, c1);  /* can be EUC/SJIS */\r
1437         c2 = 0;\r
1438         continue;\r
1439         /* goto next_word */\r
1440     }\r
1441 \r
1442     /* epilogue */\r
1443     (*iconv)(EOF, 0);\r
1444     return 1;\r
1445 }\r
1446 \r
1447 \r
1448 \r
1449 \r
1450 int\r
1451 h_conv(SFILE  *f, int c2, int c1)\r
1452 {\r
1453     int    wc;\r
1454 \r
1455 \r
1456     /** it must NOT be in the kanji shifte sequence      */\r
1457     /** it must NOT be written in JIS7                   */\r
1458     /** and it must be after 2 byte 8bit code            */\r
1459 \r
1460     hold_count = 0;\r
1461     push_hold_buf(c2, c1);\r
1462     c2 = 0;\r
1463 \r
1464     while ((c1 = GETC(f)) != EOF) {\r
1465         if(c2) {\r
1466             /* second byte */\r
1467             if(!estab_f) {\r
1468                 /* not established */\r
1469                 if(c1 > SSP) {\r
1470                     /* it is still ambiguious yet */\r
1471                     SEND;\r
1472                 } else if(c1 < AT) {\r
1473                     /* ignore bogus first byte */\r
1474                     c2 = 0;\r
1475                     SEND;\r
1476                 } else {\r
1477                     /* now established */\r
1478                     /* it seems to be MS Kanji */\r
1479                     estab_f = TRUE;\r
1480                     iconv = s_iconv;\r
1481                     SEND;\r
1482                 }\r
1483             } else\r
1484                 SEND;\r
1485         } else {\r
1486             /* First byte */\r
1487             if(c1 > DEL) {\r
1488                 /* 8th bit is on */\r
1489                 if(c1 < SSP) {\r
1490                     /* it seems to be MS Kanji */\r
1491                     estab_f = TRUE;\r
1492                     iconv = s_iconv;\r
1493                 } else if(c1 < 0xe0) {\r
1494                     /* it seems to be EUC */\r
1495                     estab_f = TRUE;\r
1496                     iconv = oconv;\r
1497                 } else {\r
1498                     /* still ambiguious */\r
1499                 }\r
1500                 c2 = c1;\r
1501                 NEXT;\r
1502             } else\r
1503             /* 7 bit code , then send without any process */\r
1504                 SEND;\r
1505         }\r
1506         /* send: */\r
1507         if((push_hold_buf(c2, c1) == EOF) || estab_f)\r
1508             break;\r
1509         c2 = 0;\r
1510         continue;\r
1511     }\r
1512 \r
1513     /** now,\r
1514      ** 1) EOF is detected, or\r
1515      ** 2) Code is established, or\r
1516      ** 3) Buffer is FULL (but last word is pushed)\r
1517      **\r
1518      ** in 1) and 3) cases, we continue to use\r
1519      ** Kanji codes by oconv and leave estab_f unchanged.\r
1520      **/\r
1521 \r
1522     for (wc = 0; wc < hold_count; wc += 2) {\r
1523         c2 = hold_buf[wc];\r
1524         c1 = hold_buf[wc+1];\r
1525         (*iconv)(c2, c1);\r
1526     }\r
1527     return VOIDVOID;\r
1528 }\r
1529 \r
1530 \r
1531 \r
1532 int\r
1533 push_hold_buf(int c2, int c1)\r
1534 {\r
1535     if(hold_count >= HOLD_SIZE*2)\r
1536         return (EOF);\r
1537     hold_buf[hold_count++] = c2;\r
1538     hold_buf[hold_count++] = c1;\r
1539     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);\r
1540 }\r
1541 \r
1542 \r
1543 int\r
1544 s_iconv(int c2, int c1)\r
1545 {\r
1546     if((c2 == EOF) || (c2 == 0)) {\r
1547         /* NOP */\r
1548     } else {\r
1549         c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);\r
1550         if(c1 < 0x9f)\r
1551             c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);\r
1552         else {\r
1553             c1 = c1 - 0x7e;\r
1554             c2++;\r
1555         }\r
1556     }\r
1557     (*oconv)(c2, c1);\r
1558     return 1;\r
1559 }\r
1560 \r
1561 \r
1562 int e_oconv(int c2, int c1)\r
1563 {\r
1564     c2 = pre_convert(c1,c2); c1 = c1_return;\r
1565     if(fold_f) {\r
1566         switch(line_fold(c2,c1)) {\r
1567             case '\n': \r
1568                 if(add_cr == TRUE) {\r
1569                     sputchar('\r');\r
1570                     c1 = '\n';\r
1571                 }\r
1572                 sputchar('\n');\r
1573                 break;\r
1574             case 0:    return VOIDVOID;\r
1575             case '\r': \r
1576                 c1 = '\n'; c2 = 0;\r
1577                 break;\r
1578             case '\t': \r
1579             case ' ': \r
1580                 c1 = ' '; c2 = 0;\r
1581                 break;\r
1582         }\r
1583     }\r
1584     if(c2==DOUBLE_SPACE) {\r
1585         sputchar(' '); sputchar(' ');\r
1586         return VOIDVOID;\r
1587     }\r
1588     if(c2 == EOF)\r
1589         return VOIDVOID;\r
1590     else if(c2 == 0 && (c1&0x80)) {\r
1591         sputchar(SSO); sputchar(c1);\r
1592     } else if(c2 == 0) {\r
1593         if(c1 == '\n' && add_cr == TRUE) \r
1594             sputchar('\r');\r
1595         if(c1 != '\r') \r
1596             sputchar(c1);\r
1597         else if(del_cr == FALSE) \r
1598             sputchar(c1);\r
1599     } else {\r
1600         if((c1<0x20 || 0x7e<c1) ||\r
1601            (c2<0x20 || 0x7e<c2)) {\r
1602             estab_f = FALSE;\r
1603             return VOIDVOID; /* too late to rescue this char */\r
1604         }\r
1605         sputchar(c2 | 0x080);\r
1606         sputchar(c1 | 0x080);\r
1607     }\r
1608     return VOIDVOID;\r
1609 }\r
1610 \r
1611 \r
1612 \r
1613 int\r
1614 s_oconv(int c2, int c1)\r
1615 {\r
1616     c2 = pre_convert(c1,c2); c1 = c1_return;\r
1617     if(fold_f) {\r
1618         switch(line_fold(c2,c1)) {\r
1619             case '\n': \r
1620                 if(add_cr == TRUE) {\r
1621                    sputchar('\r');\r
1622                    c1 = '\n';\r
1623                 }\r
1624                 sputchar('\n');\r
1625                 break;\r
1626             case '\r': \r
1627                 c1 = '\n'; c2 = 0;\r
1628                 break;\r
1629             case 0:    return VOIDVOID;\r
1630             case '\t': \r
1631             case ' ': \r
1632                 c1 = ' '; c2 = 0;\r
1633                 break;\r
1634         }\r
1635     }\r
1636     if(c2==DOUBLE_SPACE) {\r
1637         sputchar(' '); sputchar(' ');\r
1638         return VOIDVOID;\r
1639     }\r
1640     if(c2 == EOF)\r
1641         return VOIDVOID;\r
1642     else if(c2 == 0) {\r
1643         if(c1 == '\n' && add_cr == TRUE) \r
1644             sputchar('\r');\r
1645         if(c1 != '\r') \r
1646             sputchar(c1);\r
1647         else if(del_cr == FALSE) \r
1648             sputchar(c1);\r
1649     } else {\r
1650         if((c1<0x20 || 0x7e<c1) ||\r
1651            (c2<0x20 || 0x7e<c2)) {\r
1652             estab_f = FALSE;\r
1653             return VOIDVOID; /* too late to rescue this char */\r
1654         }\r
1655         sputchar((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));\r
1656         sputchar((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));\r
1657     }\r
1658     return VOIDVOID;\r
1659 }\r
1660 \r
1661 int\r
1662 j_oconv(int c2, int c1)\r
1663 {\r
1664     c2 = pre_convert(c1,c2); c1 = c1_return;\r
1665     if(fold_f) {\r
1666         switch(line_fold(c2,c1)) {\r
1667             case '\n': \r
1668                 if(output_mode) {\r
1669                     sputchar(ESC);\r
1670                     sputchar('(');\r
1671                     sputchar(ascii_intro);\r
1672                 }\r
1673                 if(add_cr == TRUE) {\r
1674                     sputchar('\r');\r
1675                     c1 = '\n';\r
1676                 }\r
1677                 sputchar('\n');\r
1678                 output_mode = ASCII;\r
1679                 break;\r
1680             case '\r': \r
1681                 c1 = '\n'; c2 = 0;\r
1682                 break;\r
1683             case '\t': \r
1684             case ' ': \r
1685                 c1 = ' '; c2 = 0;\r
1686                 break;\r
1687             case 0:    return VOIDVOID;\r
1688         }\r
1689      }\r
1690     if(c2 == EOF) {\r
1691         if(output_mode) {\r
1692             sputchar(ESC);\r
1693             sputchar('(');\r
1694             sputchar(ascii_intro);\r
1695         }\r
1696     } else if(c2 == 0 && (c1 & 0x80)) {\r
1697         if(input_mode==X0201 || !iso8859_f) {\r
1698             if(output_mode!=X0201) {\r
1699                 sputchar(ESC);\r
1700                 sputchar('(');\r
1701                 sputchar('I');\r
1702                 output_mode = X0201;\r
1703             }\r
1704             c1 &= 0x7f;\r
1705         } else {\r
1706             /* iso8859 introduction, or 8th bit on */\r
1707             /* Can we convert in 7bit form using ESC-'-'-A ? \r
1708                Is this popular? */\r
1709         }\r
1710         sputchar(c1);\r
1711     } else if(c2 == 0) {\r
1712         if(output_mode) {\r
1713             sputchar(ESC);\r
1714             sputchar('(');\r
1715             sputchar(ascii_intro);\r
1716             output_mode = ASCII;\r
1717         }\r
1718         if(c1 == '\n' && add_cr == TRUE) \r
1719             sputchar('\r');\r
1720         if(c1 != '\r') \r
1721             sputchar(c1);\r
1722         else if(del_cr == FALSE) \r
1723             sputchar(c1);\r
1724     } else if(c2 == DOUBLE_SPACE) {\r
1725         if(output_mode) {\r
1726             sputchar(ESC);\r
1727             sputchar('(');\r
1728             sputchar(ascii_intro);\r
1729             output_mode = ASCII;\r
1730         }\r
1731         sputchar(' ');\r
1732         if(c1 == '\n' && add_cr == TRUE) \r
1733             sputchar('\r');\r
1734         if(c1 != '\r') \r
1735             sputchar(c1);\r
1736         else if(del_cr == FALSE) \r
1737             sputchar(c1);\r
1738     } else {\r
1739         if(output_mode != X0208) {\r
1740             sputchar(ESC);\r
1741             sputchar('$');\r
1742             sputchar(kanji_intro);\r
1743             output_mode = X0208;\r
1744         }\r
1745         if(c1<0x20 || 0x7e<c1) \r
1746             return VOIDVOID;\r
1747         if(c2<0x20 || 0x7e<c2) \r
1748             return VOIDVOID;\r
1749         sputchar(c2);\r
1750         if(c1 == '\n' && add_cr == TRUE) \r
1751             sputchar('\r');\r
1752         if(c1 != '\r') \r
1753             sputchar(c1);\r
1754         else if(del_cr == FALSE) \r
1755             sputchar(c1);\r
1756     }\r
1757     return VOIDVOID;\r
1758 }\r
1759 \r
1760 \r
1761 \r
1762 #define rot13(c)  ( \\r
1763       ( c < 'A' ) ? c: \\r
1764       (c <= 'M')  ? (c + 13): \\r
1765       (c <= 'Z')  ? (c - 13): \\r
1766       (c < 'a')   ? (c): \\r
1767       (c <= 'm')  ? (c + 13): \\r
1768       (c <= 'z')  ? (c - 13): \\r
1769       (c) \\r
1770 )\r
1771 \r
1772 #define  rot47(c) ( \\r
1773       ( c < '!' ) ? c: \\r
1774       ( c <= 'O' ) ? (c + 47) : \\r
1775       ( c <= '~' ) ?  (c - 47) : \\r
1776       c \\r
1777 )\r
1778 \r
1779 \r
1780 /* \r
1781   Return value of line_fold()\r
1782 \r
1783        \n  add newline  and output char\r
1784        \r  add newline  and output nothing\r
1785        ' ' space\r
1786        0   skip  \r
1787        1   (or else) normal output \r
1788 \r
1789   fold state in prev (previous character)\r
1790 \r
1791       >0x80 Japanese (X0208/X0201)\r
1792       <0x80 ASCII\r
1793       \n    new line \r
1794       ' '   space\r
1795 \r
1796   This fold algorthm does not preserve heading space in a line.\r
1797   This is the main difference from fmt.\r
1798 */\r
1799 \r
1800 int\r
1801 line_fold(int c2, int c1) \r
1802\r
1803     int prev0;\r
1804     if(c1=='\r') \r
1805         return 0;               /* ignore cr */\r
1806     if(c1== 8) {\r
1807         if(line>0) line--;\r
1808         return 1;\r
1809     }\r
1810     if(c2==EOF && line != 0)    /* close open last line */\r
1811         return '\n';\r
1812     /* new line */\r
1813     if(c1=='\n') {\r
1814         if(prev == c1) {        /* duplicate newline */\r
1815             if(line) {\r
1816                 line = 0;\r
1817                 return '\n';    /* output two newline */\r
1818             } else {\r
1819                 line = 0;\r
1820                 return 1;\r
1821             }\r
1822         } else  {\r
1823             if(prev&0x80) {     /* Japanese? */\r
1824                 prev = c1;\r
1825                 return 0;       /* ignore given single newline */\r
1826             } else if(prev==' ') {\r
1827                 return 0;\r
1828             } else {\r
1829                 prev = c1;\r
1830                 if(++line<=fold_len) \r
1831                     return ' ';\r
1832                 else {\r
1833                     line = 0;\r
1834                     return '\r';        /* fold and output nothing */\r
1835                 }\r
1836             }\r
1837         }\r
1838     }\r
1839     if(c1=='\f') {\r
1840         prev = '\n';\r
1841         if(line==0)\r
1842             return 1;\r
1843         line = 0;\r
1844         return '\n';            /* output newline and clear */\r
1845     }\r
1846     /* X0208 kankaku or ascii space */\r
1847     if( (c2==0&&c1==' ')||\r
1848         (c2==0&&c1=='\t')||\r
1849         (c2==DOUBLE_SPACE)||\r
1850         (c2=='!'&& c1=='!')) {\r
1851         if(prev == ' ') {\r
1852             return 0;           /* remove duplicate spaces */\r
1853         } \r
1854         prev = ' ';    \r
1855         if(++line<=fold_len) \r
1856             return ' ';         /* output ASCII space only */\r
1857         else {\r
1858             prev = ' '; line = 0;\r
1859             return '\r';        /* fold and output nothing */\r
1860         }\r
1861     } \r
1862     prev0 = prev; /* we still need this one... , but almost done */\r
1863     prev = c1;\r
1864     if(c2 || (SSP<=c1 && c1<=0xdf)) \r
1865         prev |= 0x80;  /* this is Japanese */\r
1866     line += (c2==0)?1:2;\r
1867     if(line<=fold_len) {   /* normal case */\r
1868         return 1;\r
1869     }\r
1870     if(line>=fold_len+FOLD_MARGIN) { /* too many kinsou suspension */\r
1871         line = (c2==0)?1:2;\r
1872         return '\n';       /* We can't wait, do fold now */\r
1873     }\r
1874     /* simple kinsoku rules  return 1 means no folding  */\r
1875     if(c2==0) {\r
1876         if(c1==0xde) return 1; /* ゛*/\r
1877         if(c1==0xdf) return 1; /* ゜*/\r
1878         if(c1==0xa4) return 1; /* 。*/\r
1879         if(c1==0xa3) return 1; /* ,*/\r
1880         if(c1==0xa1) return 1; /* 」*/\r
1881         if(c1==0xb0) return 1; /* - */\r
1882         if(SSP<=c1 && c1<=0xdf) {               /* X0201 */\r
1883             line = 1;\r
1884             return '\n';/* add one new line before this character */\r
1885         }\r
1886         /* fold point in ASCII { [ ( */\r
1887         if(( c1!=')'&&\r
1888              c1!=']'&&\r
1889              c1!='}'&&\r
1890              c1!='.'&&\r
1891              c1!=','&&\r
1892              c1!='!'&&\r
1893              c1!='?'&&\r
1894              c1!='/'&&\r
1895              c1!=':'&&\r
1896              c1!=';')&&\r
1897             ((prev0=='\n')|| (prev0==' ')||     /* ignored new line */\r
1898             (prev0&0x80))                       /* X0208 - ASCII */\r
1899             ) {\r
1900             line = 1;\r
1901             return '\n';/* add one new line before this character */\r
1902         }\r
1903         return 1;  /* default no fold in ASCII */\r
1904     } else {\r
1905         if(c2=='!') {\r
1906             if(c1=='"')  return 1; /* 、 */\r
1907             if(c1=='#')  return 1; /* 。 */\r
1908             if(c1=='$')  return 1; /* , */\r
1909             if(c1=='%')  return 1; /* . */\r
1910             if(c1=='\'') return 1; /* + */\r
1911             if(c1=='(')  return 1; /* ; */\r
1912             if(c1==')')  return 1; /* ? */\r
1913             if(c1=='*')  return 1; /* ! */\r
1914             if(c1=='+')  return 1; /* ゛ */\r
1915             if(c1==',')  return 1; /* ゜ */\r
1916         }\r
1917         line = 2;\r
1918         return '\n'; /* add one new line before this character */\r
1919     }\r
1920 }\r
1921 \r
1922 int\r
1923 pre_convert(int c1, int c2)\r
1924 {\r
1925         if(c2) c1 &= 0x7f;\r
1926         c1_return = c1;\r
1927         if(c2==EOF) return c2;\r
1928         c2 &= 0x7f;\r
1929         if(rot_f) {\r
1930             if(c2) {\r
1931                 c1 = rot47(c1);\r
1932                 c2 = rot47(c2);\r
1933             } else {\r
1934                 if(!(c1 & 0x80)) \r
1935                     c1 = rot13(c1);\r
1936             }\r
1937             c1_return = c1;\r
1938         }\r
1939         /* JISX0208 Alphabet */\r
1940         if(alpha_f && c2 == 0x23 ) return 0; \r
1941         /* JISX0208 Kigou */\r
1942         if(alpha_f && c2 == 0x21 ) { \r
1943            if(0x21==c1) {\r
1944                if(alpha_f&0x2) {\r
1945                    c1_return = ' ';\r
1946                    return 0;\r
1947                } else if(alpha_f&0x4) {\r
1948                    c1_return = ' ';\r
1949                    return DOUBLE_SPACE;\r
1950                } else {\r
1951                    return c2;\r
1952                }\r
1953            } else if(0x20<c1 && c1<0x7f && fv[c1-0x20]) {\r
1954                c1_return = fv[c1-0x20];\r
1955                return 0;\r
1956            } \r
1957         }\r
1958         return c2;\r
1959 }\r
1960 \r
1961 \r
1962 #ifdef STRICT_MIME\r
1963 /* This converts  =?ISO-2022-JP?B?HOGE HOGE?= */\r
1964 \r
1965 unsigned char *mime_pattern[] = {\r
1966    (unsigned char *)"\075?ISO-8859-1?Q?",\r
1967    (unsigned char *)"\075?ISO-2022-JP?B?",\r
1968    (unsigned char *)"\075?ISO-2022-JP?Q?",\r
1969    (unsigned char *)"\075?JAPANESE_EUC?B?",\r
1970    (unsigned char *)"\075?SHIFT_JIS?B?",\r
1971    NULL\r
1972 };\r
1973 \r
1974 int      mime_encode[] = {\r
1975     'Q', 'B', 'Q',\r
1976     0\r
1977 };\r
1978 #endif\r
1979 \r
1980 #define MAXRECOVER 20\r
1981 int iso8859_f_save;\r
1982 \r
1983 #ifdef STRICT_MIME\r
1984 \r
1985 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)\r
1986 /* I don't trust portablity of toupper */\r
1987 \r
1988 int\r
1989 mime_begin(SFILE *f)\r
1990 {\r
1991     int c1;\r
1992     int i,j,k;\r
1993     unsigned char *p,*q;\r
1994     int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */\r
1995 \r
1996     mime_mode = FALSE;\r
1997     /* =? has been checked */\r
1998     j = 0;\r
1999     p = mime_pattern[j];\r
2000     r[0]='='; r[1]='?';\r
2001 \r
2002     for(i=2;p[i]>' ';i++) {                   /* start at =? */\r
2003         if( ((r[i] = c1 = sgetc(f))==EOF) || nkf_toupper(c1) != p[i] ) {\r
2004             /* pattern fails, try next one */\r
2005             q = p;\r
2006             while (p = mime_pattern[++j]) {\r
2007                 for(k=2;k<i;k++)              /* assume length(p) > i */\r
2008                     if(p[k]!=q[k]) break;\r
2009                 if(k==i && nkf_toupper(c1)==p[k]) break;\r
2010             }\r
2011             if(p) continue;  /* found next one, continue */\r
2012             /* all fails, output from recovery buffer */\r
2013             sungetc(c1,f);\r
2014             for(j=0;j<i;j++) {\r
2015                 (*oconv)(0,r[j]);\r
2016             }\r
2017             return c1;\r
2018         }\r
2019     }\r
2020     mime_mode = mime_encode[j];\r
2021     iso8859_f_save = iso8859_f;\r
2022     if(j==0) {\r
2023         iso8859_f = TRUE;\r
2024     }\r
2025     if(mime_mode=='B') {\r
2026         mimebuf_f = unbuf_f;\r
2027         if(!unbuf_f) {\r
2028             /* do MIME integrity check */\r
2029             return mime_integrity(f,mime_pattern[j]);\r
2030         } \r
2031     }\r
2032     mimebuf_f = TRUE;\r
2033     return c1;\r
2034 }\r
2035 \r
2036 #define mime_getc0(f)   (mimebuf_f?sgetc(f):Fifo(mime_input++))\r
2037 #define mime_ungetc0(c,f) (mimebuf_f?sungetc(c,f):mime_input--)\r
2038 \r
2039 #else\r
2040 int\r
2041 mime_begin(SFILE *f)\r
2042 {\r
2043     int c1;\r
2044     int i,j;\r
2045     int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */\r
2046 \r
2047     mime_mode = FALSE;\r
2048     /* =? has been checked */\r
2049     j = 0;\r
2050     r[0]='='; r[1]='?';\r
2051     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */\r
2052         /* We accept any charcter type even if it is breaked by new lines */\r
2053         if( (r[i] = c1 = sgetc(f))==EOF) break;\r
2054         if(c1=='=') break;\r
2055         if(c1<' '&& c1!='\r' && c1!='\n') break;\r
2056         if(c1=='?') {\r
2057             i++;\r
2058             if(!(i<MAXRECOVER) || (r[i] = c1 = sgetc(f))==EOF) break;\r
2059             if(c1=='b'||c1=='B') {\r
2060                 mime_mode = 'B';\r
2061             } else if(c1=='q'||c1=='Q') {\r
2062                 mime_mode = 'Q';\r
2063             } else {\r
2064                 break;\r
2065             }\r
2066             i++;\r
2067             if(!(i<MAXRECOVER) || (r[i] = c1 = sgetc(f))==EOF) break;\r
2068             if(c1=='?') {\r
2069                 break;\r
2070             } else {\r
2071                 mime_mode = FALSE;\r
2072             }\r
2073             break;\r
2074         }\r
2075     }\r
2076     if(!mime_mode || c1==EOF || i==MAXRECOVER) {\r
2077         sungetc(c1,f);\r
2078         for(j=0;j<i;j++) {\r
2079             (*oconv)(0,r[j]);\r
2080         }\r
2081         return c1;\r
2082     }\r
2083     iso8859_f_save = iso8859_f;\r
2084     /* do no MIME integrity check */\r
2085     return c1;   /* used only for checking EOF */\r
2086 }\r
2087 \r
2088 #define mime_getc0(f)   sgetc(f)\r
2089 #define mime_ungetc0(c,f) sungetc(c,f)\r
2090 \r
2091 #endif\r
2092 \r
2093 int \r
2094 mime_getc(SFILE *f)\r
2095 {\r
2096     int c1, c2, c3, c4, cc;\r
2097     int t1, t2, t3, t4, mode, exit_mode;\r
2098 \r
2099     if(mime_top != mime_last) {  /* Something is in FIFO */\r
2100         return  Fifo(mime_top++);\r
2101     }\r
2102 \r
2103     if(mimebuf_f == FIXED_MIME)\r
2104         exit_mode = mime_mode;\r
2105     else\r
2106         exit_mode = FALSE;\r
2107     if(mime_mode == 'Q') {\r
2108         if((c1 = mime_getc0(f)) == EOF) return (EOF);\r
2109         if(c1=='_') return ' ';\r
2110         if(c1!='=' && c1!='?') \r
2111             return c1;\r
2112         mime_mode = exit_mode; /* prepare for quit */\r
2113         if(c1<=' ') return c1;\r
2114         if((c2 = mime_getc0(f)) == EOF) return (EOF);\r
2115         if(c2<=' ') return c2;\r
2116         if(c1=='?'&&c2=='=') {\r
2117             /* end Q encoding */\r
2118             input_mode = exit_mode;\r
2119             iso8859_f = iso8859_f_save;\r
2120             return sgetc(f);\r
2121         }\r
2122         if(c1=='?') {\r
2123             mime_mode = 'Q'; /* still in MIME */\r
2124             mime_ungetc0(c2,f);\r
2125             return c1;\r
2126         }\r
2127         if((c3 = mime_getc0(f)) == EOF) return (EOF);\r
2128         if(c2<=' ') return c2;\r
2129         mime_mode = 'Q'; /* still in MIME */\r
2130 #define hex(c)   (('0'<=c&&c<='9')?(c-'0'):\\r
2131      ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)\r
2132         return ((hex(c2)<<4) + hex(c3));\r
2133     }\r
2134 \r
2135     if(mime_mode != 'B') {\r
2136         mime_mode = FALSE;\r
2137         return sgetc(f);\r
2138     }\r
2139 \r
2140 \r
2141     /* Base64 encoding */\r
2142     /* \r
2143         MIME allows line break in the middle of \r
2144         Base64, but we are very pessimistic in decoding\r
2145         in unbuf mode because MIME encoded code may broken by \r
2146         less or editor's control sequence (such as ESC-[-K in unbuffered\r
2147         mode. ignore incomplete MIME.\r
2148     */\r
2149     mode = mime_mode;\r
2150     mime_mode = exit_mode;  /* prepare for quit */\r
2151 \r
2152     while ((c1 = mime_getc0(f))<=' ') {\r
2153         if(c1==EOF)\r
2154             return (EOF);\r
2155     }\r
2156     if((c2 = mime_getc0(f))<=' ') {\r
2157         if(c2==EOF)\r
2158             return (EOF);\r
2159         if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;  \r
2160         return c2;\r
2161     }\r
2162     if((c1 == '?') && (c2 == '=')) {\r
2163         input_mode = ASCII;\r
2164         while((c1 =  sgetc(f))==' ' /* || c1=='\n' || c1=='\r' */);\r
2165         return c1;\r
2166     }\r
2167     if((c3 = mime_getc0(f))<=' ') {\r
2168         if(c3==EOF)\r
2169             return (EOF);\r
2170         if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;  \r
2171         return c3;\r
2172     }\r
2173     if((c4 = mime_getc0(f))<=' ') {\r
2174         if(c4==EOF)\r
2175             return (EOF);\r
2176         if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;  \r
2177         return c4;\r
2178     }\r
2179 \r
2180     mime_mode = mode; /* still in MIME sigh... */\r
2181 \r
2182     /* BASE 64 decoding */\r
2183 \r
2184     t1 = 0x3f & base64decode(c1);\r
2185     t2 = 0x3f & base64decode(c2);\r
2186     t3 = 0x3f & base64decode(c3);\r
2187     t4 = 0x3f & base64decode(c4);\r
2188     cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);\r
2189     if(c2 != '=') {\r
2190         Fifo(mime_last++) = cc;\r
2191         cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);\r
2192         if(c3 != '=') {\r
2193             Fifo(mime_last++) = cc;\r
2194             cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);\r
2195             if(c4 != '=') \r
2196                 Fifo(mime_last++) = cc;\r
2197         }\r
2198     } else {\r
2199         return c1;\r
2200     }\r
2201     return  Fifo(mime_top++);\r
2202 }\r
2203 \r
2204 int\r
2205 mime_ungetc(unsigned int   c) \r
2206 {\r
2207     Fifo(mime_last++) = c;\r
2208     return c;\r
2209 }\r
2210 \r
2211 #ifdef STRICT_MIME\r
2212 int\r
2213 mime_integrity(SFILE *f, unsigned char *p)\r
2214 {\r
2215     int c,d;\r
2216     unsigned int q;\r
2217     /* In buffered mode, read until =? or NL or buffer full\r
2218      */\r
2219     mime_input = mime_top;\r
2220     mime_last = mime_top;\r
2221     while(*p) Fifo(mime_input++) = *p++;\r
2222     d = 0;\r
2223     q = mime_input;\r
2224     while((c=sgetc(f))!=EOF) {\r
2225         if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break;\r
2226         if(c=='=' && d=='?') {\r
2227             /* checked. skip header, start decode */\r
2228             Fifo(mime_input++) = c;\r
2229             mime_input = q; \r
2230             return 1;\r
2231         }\r
2232         if(!( (c=='+'||c=='/'|| c=='=' || c=='?' ||\r
2233             ('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))))\r
2234             break;\r
2235         /* Should we check length mod 4? */\r
2236         Fifo(mime_input++) = c;\r
2237         d=c;\r
2238     }\r
2239     /* In case of Incomplete MIME, no MIME decode  */\r
2240     Fifo(mime_input++) = c;\r
2241     mime_last = mime_input;     /* point undecoded buffer */\r
2242     mime_mode = 1;              /* no decode on Fifo last in mime_getc */\r
2243     return 1;\r
2244 }\r
2245 #endif\r
2246 \r
2247 int\r
2248 base64decode(int c)\r
2249 {\r
2250     int             i;\r
2251     if(c > '@')\r
2252         if(c < '[')\r
2253             i = c - 'A';                        /* A..Z 0-25 */\r
2254         else\r
2255             i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */\r
2256     else if(c > '/')\r
2257         i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */\r
2258     else if(c == '+')\r
2259         i = '>'             /* 62 */ ;          /* +  62 */\r
2260     else\r
2261         i = '?'             /* 63 */ ;          /* / 63 */\r
2262     return (i);\r
2263 }\r
2264 \r
2265 void \r
2266 reinit()\r
2267 {\r
2268     unbuf_f = FALSE;\r
2269     estab_f = FALSE;\r
2270     nop_f = FALSE;\r
2271     binmode_f = TRUE;       \r
2272     rot_f = FALSE;         \r
2273     input_f = FALSE;      \r
2274     alpha_f = FALSE;     \r
2275     mime_f = TRUE;      \r
2276     mimebuf_f = FALSE; \r
2277     broken_f = FALSE;  \r
2278     iso8859_f = FALSE; \r
2279     x0201_f = TRUE;    \r
2280     x0201_f = NO_X0201; \r
2281     fold_f  = FALSE;\r
2282     kanji_intro = DEFAULT_J;\r
2283     ascii_intro = DEFAULT_R;\r
2284     oconv = DEFAULT_CONV; \r
2285     output_mode = ASCII;\r
2286     input_mode =  ASCII;\r
2287     shift_mode =  FALSE;\r
2288     mime_mode =   FALSE;\r
2289     file_out = FALSE;\r
2290     add_cr = FALSE;\r
2291     del_cr = FALSE;\r
2292 }\r
2293 \r
2294 #if 0\r
2295 #ifndef PERL_XS\r
2296 int \r
2297 usage()   \r
2298 {\r
2299     fprintf(stderr,"USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");\r
2300     fprintf(stderr,"Flags:\n");\r
2301     fprintf(stderr,"b,u      Output is bufferred (DEFAULT),Output is unbufferred\n");\r
2302 #ifdef DEFAULT_CODE_SJIS\r
2303     fprintf(stderr,"j,s,e    Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC)\n");\r
2304 #endif\r
2305 #ifdef DEFAULT_CODE_JIS\r
2306     fprintf(stderr,"j,s,e    Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC)\n");\r
2307 #endif\r
2308 #ifdef DEFAULT_CODE_EUC\r
2309     fprintf(stderr,"j,s,e    Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT)\n");\r
2310 #endif\r
2311     fprintf(stderr,"J,S,E    Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC)\n");\r
2312     fprintf(stderr,"t        no conversion\n");\r
2313     fprintf(stderr,"i_       Output sequence to designate JIS-kanji (DEFAULT B)\n");\r
2314     fprintf(stderr,"o_       Output sequence to designate ASCII (DEFAULT B)\n");\r
2315     fprintf(stderr,"r        {de/en}crypt ROT13/47\n");\r
2316     fprintf(stderr,"v        Show this usage\n");\r
2317     fprintf(stderr,"m[BQ0]   MIME decode [B:base64,Q:quoted,0:no decode]\n");\r
2318     fprintf(stderr,"l        ISO8859-1 (Latin-1) support\n");\r
2319     fprintf(stderr,"f        Folding: -f60 or -f\n");\r
2320     fprintf(stderr,"Z[0-2]   Convert X0208 alphabet to ASCII  1: Kankaku to space,2: 2 spaces\n");\r
2321     fprintf(stderr,"X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n");\r
2322     fprintf(stderr,"B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");\r
2323 #ifdef MSDOS\r
2324     fprintf(stderr,"T        Text mode output\n");\r
2325 #endif\r
2326     fprintf(stderr,"O        Output to File (DEFAULT 'nkf.out')\n");\r
2327     fprintf(stderr,"d,c      Delete \\r in line feed, Add \\r in line feed\n");\r
2328     fprintf(stderr,"Network Kanji Filter Version %s (%s) "\r
2329 #if defined(MSDOS) && !defined(_Windows)\r
2330                   "for DOS"\r
2331 #endif\r
2332 #if !defined(__WIN32__) && defined(_Windows)\r
2333                   "for Win16"\r
2334 #endif\r
2335 #if defined(__WIN32__) && defined(_Windows)\r
2336                   "for Win32"\r
2337 #endif\r
2338 #ifdef __OS2__\r
2339                   "for OS/2"\r
2340 #endif\r
2341                   ,Version,Patchlevel);\r
2342     fprintf(stderr,"\n%s\n",CopyRight);\r
2343     return 0;\r
2344 }\r
2345 #endif\r
2346 #endif\r
2347 \r
2348 /**\r
2349  ** パッチ制作者\r
2350  **  void@merope.pleiades.or.jp (Kusakabe Youichi)\r
2351  **  NIDE Naoyuki <nide@ics.nara-wu.ac.jp>\r
2352  **  ohta@src.ricoh.co.jp (Junn Ohta)\r
2353  **  inouet@strl.nhk.or.jp (Tomoyuki Inoue)\r
2354  **  kiri@pulser.win.or.jp (Tetsuaki Kiriyama)\r
2355  **  Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>\r
2356  **  a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)\r
2357  **  kono@ie.u-ryukyu.ac.jp (Shinji Kono)\r
2358  **  GHG00637@nifty-serve.or.jp (COW)\r
2359  **\r
2360  ** 最終更新日\r
2361  **  1998.11.7\r
2362  **/\r
2363 \r
2364 /* end */\r
2365 \r