No. 141/622 Index Prev Next
Path: titcca!ccut!ascgw!flab!ichikawa
From: ichikawa@flab.fujitsu.JUNET (Itaru Ichikawa)
Newsgroups: fj.sources,fj.kanji
Subject: Network Kanji Filter
Keywords: Kanji Filter
Message-ID: < 011740@flab.fujitsu.JUNET> 
Date: 18 Aug 87 11:14:21 GMT
Sender: ichikawa@flab.fujitsu.junet
Reply-To: ichikawa@flab.fujitsu.junet
Followup-To: fj.sources.d,fj.kanji
Distribution: fj
Organization: Fujitsu Laboratories Ltd., Kawasaki, Japan
Lines: 802
Xref: titcca fj.sources:431 fj.kanji:199
Posted: Tue Aug 18 20:14:21 1987

PDSとして、Network Kanji Filter (NKF)のソースを投稿します。

ニュース記事の規約を守って書かれている、JIS 7bit, EUC, Shift JISのいずれ
かで書かれた入力も、そのコードが何であるかを意識せずに、自分の指定した
コード系に変換してくれるフィルタです。
(詳細(というほどでもありませんが)は、nkf.docにあります)

cut here以下を切りとり、shでアンシャーしてください。すると、

	nkf.doc, nkf.c nkf.1

の3つのファイルができるはずです。で、nkf.cをコンパイルすれば、
たいていの機械で動くはずです。(確認はありませんが)

いちおう、著作権については、太腹なことを書いております。皆さまの
道義心を信用しています。
(富士通に明らかに損害を与えるようなことをされると、苦労して出した
私の立場がないのですから...、そうゆうことは、やめてほしいなぁ)

まあ、たいしたプログラムではありませんが、EUC, JIS, Shit JISの
いずれで書かれたメッセージや記事も、指定したコードで出力できるので、
それなりに便利だと思います。(ちょっと、のろいという感じはある)

御使用していただければ、光栄です。

−−−	富士通研究所 ソフト3研 市川 至	ichikawa@flab.fujitsu

------------8< ------------------cut here----------------8< --------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it into a file and typing " sh file" . 
# To overwrite existing files, type " sh file -c" .  You can also feed
# this as standard input via unshar, or by typing "sh < file", e.g.. 
# If this archive is complete, you will see the following message at
# the end:
#		" End of archive for nkf." 
# Contents:  nkf.doc nkf.c nkf.1
# Wrapped by ichikawa@flab on Wed Aug 18 09:00:00 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f nkf.doc -a " ${1}"  != " -c"  ; then 
  echo shar: Will not over-write existing file \" nkf.doc\" 
else
echo shar: Extracting \" nkf.doc\"  \(3461 characters\)
sed "s/^X//" >nkf.doc < < 'END_OF_nkf.doc'
X
XNAME
X	nkf - ネットワーク用漢字コード変換フィルタ
X
XSYNOPSIS
X	nkf [options] [file]
X
XDESCRIPTION
X
X nkfは,ネットワークでメールやニュースの読み書きをするために作られた,
X漢字コードの変換フィルタである.
X
X このnkfの特徴としては,入力漢字コード系の統計的な自動認識機能がある.
Xこのため,利用者は,入力漢字コード系が何であるかを,知らなくても,出力漢
X字コード系のみ指定すれば良いことになる.ただ,この判定機構は,理論的には
X完全ではないが,通常のニュースやメールのメッセージについては確実に動作す
Xる安全なものにはなっている。
X
X 現在,nkfが認識できる入力の漢字コード系は,7ビットJIS,シフトJIS,EUC
Xのいずれかである.出力する漢字コード系も,この3種類である.
X
X 入力は,ファイルを指定しなければ,標準入力となる.出力は標準出力である.
X
X 指定できるオプションは,以下の通り.
X
X	-b	バッファリング出力を行う.(デフォルト)
X	-u	出力時に,バッファリングしない.
X
X	-t	なにもしない.
X
X	-j
X	-n	7ビットJISコードを出力する.(デフォルト)
X
X	-s
X	-x	シフトJISコードを出力する.
X
X	-e
X	-a	EUC(AT& Tコード)を出力する.
X
X	-i?	(7ビットJISの)出力の漢字インとして,ESC-'$'-?を使用する.
X		(デフォルトは,ESC-'$'-'B')
X
X	-o?	(7ビットJISの)出力の漢字アウトとして,ESC-'('-?を使用する.
X		(デフォルトは,ESC-'('-'J')
X
X	-@J
X	-J	-i@ -oJと同じ.
X
X	-@H
X	-H	-i@ -oHと同じ.
X
X	-BJ	-iB -oJと同じ.
X
X	-BB	-iB -oBと同じ.
X
XAUTHOR
X 市川 至	ichikawa@flab.fujitsu.junet
X
XACKNOWLEDGE
X	morb@fujitsu, kiss@ayumi.stars.flab.fujitsu, cen122@flab.fujitsu,
X	yuki@flab.fujitsu  他,fujitsu &  flab.fujitsuの皆さんの協力に感謝.
X	shinoda@cs.titech, kato@cs.titech, uematsu@cs.titech TNX
X
XBUGS
X 実は,入力のコード系の判定は,EUCとシフトJISとの自動判定であり,最初に
X特定できる文字が来た時点で確定してしまう.そして,特定不能の間は保留バッ
Xファにためておかれ,確定後に処理される.このため;
X
X	1)nkfは,入力中に,複数の漢字コード系のコードが混在した場合,
X	その入力を正しく変換できない.
X
X	2)いわゆる半角カナが入力にあった場合については,その動作を保証
X	できない.(^O,^Nは保存しますが...)
X
X	3)判定不能な文字(第二水準)と英数文字だけからなる入力は判定
X	できない.(保留バッファが満杯になるか,入力が終了すると,
X	どっちかにテケトーに判断して変換してしまう)
X
X	4)ちょっと,のろい.
X
X また,入力および出力の漢字イン/アウトには,大胆な仮定をしている.例え
Xば,入力にESC-'$'と来たら,次が何であろうが,(文字セットや他国語を無視
Xして)漢字を指定しているシーケンスとしてしまっている.(ESC-'('の場合も
X同様)そして,出力の.シーケンスについては,オプションで指定したもので行
Xう.このため,文字セットの切り換え(例えば,ASCIIとJIS)については保存さ
Xれない.
X
X このフィルタの変換は,コード系に対応した一括写像を施すだけなので,外字
Xや特殊記号や罫線素片など,JIS第一,第二水準表において定義されていないコ
Xードに各社により割り当てられた文字がどうなるかまでは関知しない.そして,
X第二水準がないとかあるとかによる問題は,このフィルタの範囲外と思える.そ
Xれらは,書き手の責任でなんとかしてもらいたい.
X
X いずれにせよ,通常のニュースの記事については問題はなく変換できるはずで
Xある.(と思うのだが,今ひとつ自信はない)
END_OF_nkf.doc
if test 3461 -ne `wc -c < nkf.doc`; then
    echo shar: \" nkf.doc\"  unpacked with wrong size!
fi
# end of overwriting check
fi
#
if test -f nkf.c -a " ${1}"  != " -c"  ; then 
  echo shar: Will not over-write existing file \" nkf.c\" 
else
echo shar: Extracting \" nkf.c\"  \(9758 characters\)
sed "s/^X//" >nkf.c < < 'END_OF_nkf.c'
X/** Network Kanji Filter. (PDS Version)
X************************************************************************
X************************************************************************
X** Copyright (C) Fujitsu LTD. (Itaru ICHIKAWA), 1987
X** 連絡先: (株)富士通研究所 ソフト3研 市川 至
X** (E-Mail Address: ichikawa@flab.fujitsu.junet)
X** このプログラムのいかなる複写,移植,改変,修正も許諾します.
X** Everyone is permitted to do anything on this program
X** including copying, transplanting, debugging, and modifying.
X************************************************************************
X************************************************************************
X** 	
X**					 Written by I.Ichikawa
X**					 Fujitsu Labs.,  JH2FKN/1
X**
X** USAGE:	nkf [flags] [file] 
X**
X** Flags:
X** b    Output is bufferred 		(DEFAULT)
X** u	Output is unbufferred
X**
X** t	no operation
X**
X** j,n	Outout code is JIS 7 bit 	(DEFAULT) 
X** s,x	Output code is Shift JIS
X** e,a	Output code is AT& T JIS
X**
X** i_	Output Kanji-in is ESC+'$'+ _	(DEFAULT_KI)
X** o_   Output Kanji-out is ESC+'('+ _	(DEFAULT_KO)
X**
X** @J,J	= i@oJ				
X** @H,H	= i@oH			
X** BJ	= iBoJ			
X** BB	= iBoB 	
X**
X**/
X
X#include 
X#include 
X
X#define		FALSE	0
X#define		TRUE	1
X
X#define		ESC	0x1b
X#define		SP	0x20
X#define		AT	0x40
X#define		SSP	0xa0
X#define		DEL	0x7f
X
X#define		HOLD_SIZE	32
X
X#define		DEFAULT_KI	'@'
X#define		DEFAULT_KO	'J'
X#define		DEFAULT_I	oconv		/* EUC, JIS7 */
X/* #define	DEFAULT_I	s_oconv		/* Shift JIS */
X
X#define		SJ0162	0x00e1		/* 01 - 62 ku offset */
X#define		SJ6394	0x0161		/* 63 - 94 ku offset */
X
X
X
X
X
X/* buffers */
Xchar            stdbuf[BUFSIZ];
Xshort           hold_buf[HOLD_SIZE];
Xint             hold_count;
X
X/* flags */
Xint             unbuf_f = TRUE,
X                estab_f = FALSE,
X                nop_f = FALSE;
X
X/* options */
Xchar            k_in = DEFAULT_KI,
X                k_out = DEFAULT_KO;
X
X/* converters */
Xint             s_iconv ();
X
Xint             e_oconv ();
Xint             j_oconv ();
Xint             s_oconv ();
Xint             (*iconv) ();
Xint             (*oconv) ();
X
X/* Global states */
Xint             in_kanji = FALSE,
X                k_shift = FALSE;
X
X
X
X
Xmain (argc, argv)
X    int             argc;
X    char          **argv;
X{
X    register FILE  *fin;
X    register int    c;
X    register char  *cp;
X
X    oconv = j_oconv;
X    for (argv++; (argc > 1) & &  **argv == '-'; argc--, argv++) {
X	cp = *argv;
X	while (*cp)
X	    switch (*cp++) {
X	    case 'b':
X		unbuf_f = FALSE;
X		continue;
X	    case 'u':
X		unbuf_f = TRUE;
X		continue;
X	    case 't':
X		nop_f = TRUE;
X		continue;
X	    case 'j':
X	    case 'n':
X		oconv = j_oconv;
X		continue;
X	    case 'e':
X	    case 'a':
X		oconv = e_oconv;
X		continue;
X	    case 's':
X	    case 'x':
X		oconv = s_oconv;
X		continue;
X	    case 'i':
X		k_in = *cp++;
X		continue;
X	    case 'o':
X		k_out = *cp++;
X		continue;
X	    case '@':
X		k_in = '@';
X		k_out = *cp++;
X		continue;
X	    case 'B':
X		k_in = 'B';
X		k_out = *cp++;
X		continue;
X	    case 'J':
X		k_in = '@';
X		k_out = 'J';
X		continue;
X	    case 'H':
X		k_in = '@';
X		k_out = 'H';
X		continue;
X	    default:
X		/* bogus option but ignored */
X		continue;
X	    }
X    }
X
X    if (unbuf_f)
X	setbuf (stdout, (char *) NULL);
X    else
X	setbuf (stdout, stdbuf);
X
X    if (argc <  2)
X	fin = stdin;
X    else if ((fin = fopen (*argv, " r" )) == NULL) {
X	perror (*argv);
X	return (-1);
X    }
X    if (nop_f) {
X	while ((c = getc (fin)) != EOF)
X	    putchar (c);
X    } else
X	convert (fin);
X
X    if (fin != stdin)
X	fclose (fin);
X
X    return (0);
X}
X
X
X
X
X
X
Xconvert (f)
X    register FILE  *f;
X{
X    register int    c1,
X                    c2;
X
X    c2 = 0;
X    iconv = oconv;
X
X    while ((c1 = getc (f)) != EOF) {
X	if (c2) {
X	    /* second byte */
X	    if (c2 >  DEL) {
X		/* in case of 8th bit is on */
X		if (!estab_f) {
X		    /* in case of not established yet */
X		    if (c1 >  SSP) {
X			/* It is still ambiguious */
X			h_conv (f, c2, c1);
X			c2 = 0;
X			continue;
X			/* goto next_word */
X		    } else if (c1 <  AT) {
X			/* ignore bogus code */
X			c2 = 0;
X			continue;
X			/* goto next_word */
X		    } else {
X			/* established */
X			/* it seems to be Shift JIS */
X			estab_f = TRUE;
X			iconv = s_iconv;
X			/* goto send */
X		    }
X		} else
X		    /* in case of already established */
X		if (c1 <  AT) {
X		    /* ignore bogus code */
X		    c2 = 0;
X		    continue;
X		    /* goto next_word */
X		} else;
X		/* goto send */
X	    } else
X		/* 7 bit code */
X		/* it might be kanji shitfted */
X	    if ((c1 == DEL) || (c1 < = SP)) {
X		/* ignore bogus code */
X		c2 = 0;
X		continue;
X		/* goto next_word */
X	    } else;
X	    /* goto send */
X	} else {
X	    /* first byte */
X	    if (c1 >  DEL) {
X		/* 8 bit code */
X		if (!estab_f) {
X		    /* not established yet */
X		    if (c1 <  SSP) {
X			/* it seems to be Shift JIS */
X			estab_f = TRUE;
X			iconv = s_iconv;
X		    } else if (c1 <  0xe0) {
X			/* it seems to be EUC */
X			estab_f = TRUE;
X		    } else {
X			/* still ambiguious */
X		    }
X		} else {
X		    /* already established */
X		}
X		c2 = c1;
X		continue;
X		/* goto next_byte */
X	    } else if ((c1 > SP) & &  (c1 != DEL)) {
X		/* in case of Roman characters */
X		if (k_shift) {
X		    /* in case of Kanji shifted */
X		    c2 = c1;
X		    continue;
X		    /* goto next_byte */
X		} else;
X		/* goto send */
X	    } else if (c1 == ESC) {
X		/* in case of ESC */
X		if ((c1 = getc (f)) == EOF) {
X		    (*iconv) (0, ESC);
X		    break;
X		} else if (c1 == '$') {
X		    if ((c1 = getc (f)) == EOF) {
X			(*iconv) (0, ESC);
X			(*iconv) (0, '$');
X			break;
X		    } else {
X			/* in case of Kanji in ESC sequence */
X			k_shift = TRUE;
X			continue;
X		    }
X		} else if (c1 == '(') {
X		    if ((c1 = getc (f)) == EOF) {
X			(*iconv) (0, ESC);
X			(*iconv) (0, '(');
X			break;
X		    } else {
X			/* in case of Kanji out ESC sequence */
X			k_shift = FALSE;
X			continue;
X		    }
X		} else {
X		    /* not kanji control */
X		    (*iconv) (0, ESC);
X		    /* goto send */
X		}
X	    } else;
X	    /* goto send */
X	}
X	/* send: */
X	(*iconv) (c2, c1);
X	c2 = 0;
X	continue;
X	/* goto next_word */
X    }
X
X    /* epilogue */
X    (*iconv) (EOF, 0);
X    return;
X}
X
X
X
X
X
Xh_conv (f, c2, c1)
X    register FILE  *f;
X    register int    c1,
X                    c2;
X{
X    register int    wc;
X
X
X    /** it must NOT be in the kanji shifte sequence	 */
X    /** it must NOT be written in JIS7 			 */
X    /** and it must be after 2 byte 8bit code		 */
X
X    hold_count = 0;
X    push_hold_buf (c2, c1);
X    c2 = 0;
X
X    while ((c1 = getc (f)) != EOF) {
X	if (c2) {
X	    /* second byte */
X	    if (c1 >  DEL) {
X		/* then 8th bit is on */
X		if (!estab_f) {
X		    /* not established */
X		    if (c1 >  SSP) {
X			/* it is still ambiguious yet */
X			/* goto send */
X		    } else if (c1 <  AT) {
X			/* ignore bogus code */
X			c2 = 0;
X			continue;
X			/* goto next byte */
X		    } else {
X			/* now established */
X			/* it seems to be Shift JIS */
X			estab_f = TRUE;
X			iconv = s_iconv;
X			/* goto send */
X		    }
X		} else;
X		/* just established */
X		/* goto send without checking */
X	    } else {
X		/* 7 bit code */
X		/* it might be bogus code  then ignore */
X		c2 = 0;
X		continue;
X		/* goto next byte */
X	    }
X	} else {
X	    /* First byte */
X	    if (c1 >  DEL) {
X		/* 8th bit is on */
X		if (c1 <  SSP) {
X		    /* it seems to be Shift JIS */
X		    estab_f = TRUE;
X		    iconv = s_iconv;
X		} else if (c1 <  0xe0) {
X		    /* it seems to be EUC */
X		    estab_f = TRUE;
X		} else {
X		    /* still ambiguious */
X		}
X		c2 = c1;
X		continue;
X		/* goto next_byte */
X	    } else;
X	    /* 7 bit code , then send without any process */
X	    /* goto send */
X	}
X	/* send: */
X	if ((push_hold_buf (c2, c1) == EOF) || estab_f)
X	    break;
X	c2 = 0;
X	continue;
X    }
X
X    /** now,
X     ** 1) EOF is detected, or
X     ** 2) Code is established, or
X     ** 3) Buffer is FULL (but last word is pushed)
X     **
X     ** in 1) and 3) cases, we must use default
X     ** Kanji codes, that is DEFAULT_I
X     **/
X
X    if (estab_f == FALSE) {
X	iconv = DEFAULT_I;
X	estab_f = TRUE;
X    }
X    for (wc = 0; wc <  hold_count; wc++) {
X	c1 = hold_buf[wc];
X	c2 = 0x0ff &  (c1 >> 8);
X	c1 = c1 &  0x0ff;
X	(*iconv) (c2, c1);
X    }
X    return;
X}
X
X
X
X
Xpush_hold_buf (c2, c1)
X    int             c2,
X                    c1;
X{
X    if (hold_count > = HOLD_SIZE)
X	return (EOF);
X    hold_buf[hold_count++] = ((c2 &  0x0ff) << 8) | (c1 &  0x0ff);
X    return ((hold_count > = HOLD_SIZE) ? EOF : hold_count);
X}
X
X
X
Xs_iconv (c2, c1)
X    register int    c2,
X                    c1;
X{
X    if ((c2 == EOF) || (c2 == 0)) {
X	/* NOP */
X    } else {
X	c2 & = 0x0ff;
X	c1 & = 0x0ff;
X
X	c2 = c2 + c2 - ((c2 < = 0x9f) ? SJ0162 : SJ6394);
X	if (c1 <  0x9f)
X	    c1 = c1 - ((c1 >  DEL) ? SP : 0x1f);
X	else {
X	    c1 = c1 - 0x7e;
X	    c2++;
X	}
X    }
X    (*oconv) (c2, c1);
X}
X
X
Xe_oconv (c2, c1)
X    register int    c2,
X                    c1;
X{
X    if (c2 == EOF)
X	return;
X    else if (c2 == 0)
X	putchar ((c1 &  0x7f));
X    else {
X	putchar (((c2 &  0x7f) | 0x080));
X	putchar (((c1 &  0x7f) | 0x080));
X    }
X}
X
X
X
X
X
Xs_oconv (c2, c1)
X    register int    c2,
X                    c1;
X{
X    if (c2 == EOF)
X	return;
X    else if (c2 == 0)
X	putchar ((c1 &  0x7f));
X    else {
X	c2 & = 0x07f;
X	c1 & = 0x07f;
X	putchar ((((c2 - 1) >> 1) + ((c2 < = 0x51) ? 0x71 : 0xb1)));
X	putchar ((c1 + ((c2 &  1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
X    }
X}
X
Xj_oconv (c2, c1)
X    register int    c2,
X                    c1;
X{
X    if (c2 == EOF) {
X	if (in_kanji) {
X	    putchar (ESC);
X	    putchar ('(');
X	    putchar (k_out);
X	}
X    } else if (c2 == 0) {
X	if (in_kanji) {
X	    putchar (ESC);
X	    putchar ('(');
X	    putchar (k_out);
X	    in_kanji = FALSE;
X	}
X	putchar ((c1 &  0x7f));
X    } else {
X	if (in_kanji == FALSE) {
X	    putchar (ESC);
X	    putchar ('$');
X	    putchar (k_in);
X	    in_kanji = TRUE;
X	}
X	putchar ((c2 &  0x7f));
X	putchar ((c1 &  0x7f));
X    }
X}
X
END_OF_nkf.c
if test 9758 -ne `wc -c < nkf.c`; then
    echo shar: \" nkf.c\"  unpacked with wrong size!
fi
# end of overwriting check
fi
#
if test -f nkf.1 -a " ${1}"  != " -c"  ; then 
  echo shar: Will not over-write existing file \" nkf.1\" 
else
echo shar: Extracting \" nkf.1\"  \(1380 characters\)
sed "s/^X//" >nkf.1 < < 'END_OF_nkf.1'
X
X.TH NKF 1L 18/Aug/87
X.SH NAME
Xnkf \- Network Kanji code conversion Filter
X.SH SYNOPSIS
X.B nkf
X[
X.B options
X] [
X.B file
X]
X.SH DESCRIPTION
X.PP
X.B Nkf
Xis a yet another kanji code converter among networks, hosts and terminals.
XIt converts input kanji code to designated kanji code
Xsuch as 7-bit JIS, shifted-JIS or EUC.
X.PP
XOne of the most unique facicility of 
X.B nkf
Xis the guess of the input kanji code.
XIt currently recognizes 7-bit JIS, shifted-JIS and EUC.
XSo users needn't the input kanji code specification.
X.PP
XOptions are bellow:
X.TP
X.B \-b
Xbufferd output.
XThis is a default.
X.TP
X.B \-u
Xunbufferd output.
X.TP
X.B \-t
Xno operations.
X.TP
X.B \-j
X.br
X.ns
X.TP
X.B \-n
Xoutput 7-bit JIS code.
XThis is a default.
X.TP
X.B \-s
X.br
X.ns
X.TP
X.B \-x
Xoutput shifted-JIS code.
X.TP
X.B \-e
X.br
X.ns
X.TP
X.B \-a
Xoutput EUC (AT& T) code.
X.TP
X.BI \-i c
Xoutput 
X.BI ESC\-$\- c
Xas kanji-in.
X(Default is
X.BR B .)
X.TP
X.BI \-i c
Xoutput 
X.BI ESC\-(\- c
Xas kanji-out.
X(Default is
X.BR J .)
X.TP
X.B \-@J
X.br
X.ns
X.TP
X.B \-J
Xsame as
X.BR \-i @
X.BR \-o J.
X.TP
X.B \-@H
X.br
X.ns
X.TP
X.B \-H
Xsame as
X.BR \-i @
X.BR \-o H.
X.TP
X.B \-BJ
Xsame as
X.BR \-i B
X.BR \-o J.
X.TP
X.B \-BB
Xsame as
X.BR \-i B
X.BR \-o B.
X.SH " FILES" 
Xnkf - binary
X.SH AUTHOR
XItaru Ichikawa		ichikawa@fujitsu.JUNET
X.SH BUGS
X.B Nkf
Xcannot handle some input that contains mixed kanji codes.
X.SH NOTES
XKanji-out used in
X.B JUNET
Xshould
X.I NOT
X.BR ESC\-(-H .
X
END_OF_nkf.1
if test 1380 -ne `wc -c < nkf.1`; then
    echo shar: \" nkf.1\"  unpacked with wrong size!
fi
# end of overwriting check
fi
#
echo shar: End of archive of nkf
##  End of shell archive.
exit 0
Next
Continue < 635@tansei.cc.u-tokyo.JUNET>
< 1464@flab.flab.fujitsu.JUNET>
< 547@cskvax.csk.JUNET>