これは jfilterj.info、jfilterj.texi より makeinfo バージョン 4.1
によって作成されました。

Japanese Character Code Conversion Filter procedures in Scheme
**************************************************************

カバー
******

  このコレクションにはISO 2022にしたがう日本語文字コード(JIS、EUC)と
Shift-JISの3種のコードを相互に変換する手続きと、ある種の全角文字コードを
一括して半角文字コードに変換する手続きが入っています。最初はHOBBITでコン
パイルして、本来どんなインタープリタにも苦手な1文字処理をスピードアップ
するために考えたものでした。このバージョンは、R5RSに準拠するすべての処理
系で動くように、R5RSにしたがってコーディングしています。本プログラムは、
GNU General Public Licenseにしたがって配布されるフリーソフトウェアです。

              May 2002 犬飼 大 (inukai.d@jeans.ocn.ne.jp)

この手続きコレクションについて
******************************

このコレクションは日本語文字コードを取り扱うものです。ソースコードに手を
入れればISO 2022にしたがうGB 2312とEUCあるいはKS C5601とEUC
間の変換もできるのではないかと思います。ユーザが自分の用途に合わせて書き
換えたり書き加えたりすることもできます。

日本語文字コードは表音文字カタカナと平仮名、および表意文字漢字で成り立っ
ています。日本語文字コードではアルファベットも使用されます。平仮名と漢字
は2バイトで表現され、カタカナには1バイトの半角カタカナと2バイトで表現さ
れる全角カタカナの2種類があります。

  ascii系の日本語文字コードには、JIS、EUC、Shift-JISの3種類があります。

JIS:

この日本語文字コード系は、ISO 2022もしくはJIS(日本工業規格)がもとになっています。

  - JISX0201文字セットでは、制御文字とascii文字(#x01から#x7e)、および
半角文字(#xa1から#xdf)が定義されています。- JISX0208文字セット(1978
年版と1983年版があります)では、1バイトが#x21から#x7eまでの7ビットで表現
される、2バイト文字が定義されています。

JIS文字セットでは、エスケープ文字16進#x1bで始まるエスケープシーケンスで
それに続く文字コードを指定します。この方法は中国語文字セットGB 2312
と韓国語文字セットKS C5601にも使用されているようです。3つの文字セッ
トすべてについて、制御文字とascii文字は共通しています。文字コードの違い
は多バイト文字にあります。

EUC:

すべての文字が8ビットで表現されます。JISコードの最高位ビット(MSB)を1にすればEUCコードになります。
半角文字コードはJISと同じですが、EUCではその前に#x8eがつきます。

Shift JIS:

すべての文字が8ビットで表現されます。ascii文字と半角文字はJISと同じ文字コードです。多くの場合テキストは、Carriage Return文字とNewline文字の2文字を使って構造化されます。

シフトJISの2バイト文字は、次のようにしてJIS文字コードから変換されます。

   * 2バイトのJISコードを第1バイトか奇数コードのものと偶数コードの
     ものに分けます。

   * 第1バイトが偶数のものについては、第2バイトに#x7eを加えれば、
     それがシフトJISの第2バイトになります。

   * 第1バイトが奇数のコードについては、

        * 第2バイトが#x60未満ならば、第2バイトに#x1fを加えればそれが
          シフトJISの第2バイトになります。

        * 第2バイトが#x60以上のコードの場合、第2バイトに#x20を加えれば、
          それがシフトJISコードの第2バイトになります。

        * さらにasciiと半角カタカナが使用していない領域に第1バイトが
          来るように、第1バイトを次のようにシフトします。

             * 第1バイトが#x5f未満の場合は、#x81と#x9fの間に来るように
               第1バイトをシフトします。

             * 第1バイトが#x5f以上の場合は、#xe0と#xfcの間に第1バイトが
               来るようにシフトします。

日本語文字コード変換プログラムにはこれまでにもnkfやqkcがあります。新たに
似たようなプログラムを著した理由はScgeneで書いたこと以外にはありませんが、
Schemeで書いたことによってコードの変更や追加ができることに加えて、Scheme
で書いた別のプログラムとの連結が容易になります。

定数
****

次の文字コードは本プログラムでは頻繁に使用するものですが、R5RSで明確には定義されていないものです。

     CHAR:ESCAPE: 16進数#X1Bに対応するエスケープ文字
     CHAR:RETURN: 16進数#X0Dに対応するキャリッジリターン文字

MS-DOS系のOSでテキストを行で構造化する場合には、キャリッジリターン文字と
改行文字の組合せ、あるいはキャリッジリターン文字が単独で使用されることが
あります。

  文字セットの指定には次のシンボルを使用しています。

     'jis   : JIS 1978か1983文字セットを示します。
     'eucj  : 日本語EUC文字セットを示します。
     'sjis  : シフトJIS文字セットを示します。
     'ascii : ascii文字セットを示します。
     'binary: これは文字セットではなく、文字がバイナリコードであることを示します。

  次のエスケープ文字列定数のリストはいろいろな用途に使用されています。

     JCCCF:ASCII:          続く文字はascii。
     JCCCF:ROMAN:          続く文字はローマ字。
     JCCCF:X0201:          次は半角文字。
     JCCCF:LATIN1:         続く文字はlatin-1文字セット。
     JCCCF:X0208-1978:     続く文字は1978版JISX0208。
     JCCCF:X0208-1983:     続く文字は1983版JISX0208。
     JCCCF:X0208-1978-2:   もう1つのJISX0208-1978指定。
     JCCCF:X0208-1983-2:   もう1つのJISX0208-1983指定。

ISO 2022では、中国語や韓国語用の別のエスケープシーケンスが定義されていますが、本プログラムでは使用していません。

コード変換のための述語手続き
****************************

 - procedure: euc1? c
     char Cが2バイトeuc文字の第1バイトであれば#tを、そうでなければ
     #fを返します。

 - procedure: euc2? c
     char Cが2バイトeuc文字の第2バイトであれば#tを、そうでなければ
     #fを返します。

 - procedure: sjis1? c
     char Cが2バイトシフトJIS文字の第1バイトであれば#tを、そうでな
     ければ#fを返します。

 - procedure: sjis2? c
     char Cが2バイトシフトJIS文字の第2バイトであれば#tを、そうでな
     ければ#fを返します。

 - procedure: hankana? c
     char Cが半角文字の場合に#tを返します。

Jfilterの下位手続き
*******************

この項では、次項に説明するjfilterのメインの手続きが使用する、下位手続き
とサービス手続きを説明しています。

 - procedure: upper-byte w
     2バイト整数Wを引数にとって上位の1バイト整数を返します。

 - procedure: lower-byte w
     2バイト整数Wを引数にとって下位の1バイト整数を返します。

 - procedure: byte->word uc lc
     上位文字コードがUC、下位文字コードがLCの2バイト整数を 返します。

 - procedure: han->zen c to-code
     7ビットを1バイトとするjis文字(カタカナ)か2バイト文字（濁点か半濁点
     がついたカタカナ)の整数コードのリストCを引数にとって、
     TO-CODEに応じた全角カタカナ文字のリストを返します。
     TO-CODEにはシンボル('jis、'sjis、'eucj)のいずれか1つを指
     定します。この手続きは引数Cを書き変えます。

 - procedure: jis->sjis s
     1バイトか2バイトの7ビットJIS文字の文字のリストSを引数にとっ
     て、ascii文字はそのまま1バイトの文字のリストとして、半角カタカナコー
     ドと2バイトのJIS文字のリストは2バイトのシフトJIS文字のリストとして
     返します。この手続きは引数Sを書き変えます。

 - procedure: sjis->jis s
     1バイトか2バイトのシフトjis文字のリストSを引数にとって、
     ascii文字は1バイトの文字列のリストして、半角カタカナコードと2バイ
     ト文字は2バイトのJIS文字のリストとしてそれを返します。この手続きは
     引数Sを書き変えます。

 - procedure: jis->euc s
     jisコードの文字のリストSを引数にとって、ascii文字はそのまま1
     バイトの文字のリストとして、半角カタカナと2バイトコードのjis文字の
     リストは2バイトのeuc文字のリストとしてそれを返します。この手続きは
     引数Sを書き変えます。

 - procedure: euc->jis s
     eucコードの文字のリストSを引数にとって、ascii文字はそのまま1
     バイトの文字のリストとして、半角カタカナと2バイトコードのeuc文字の
     リストは2バイトのjis文字のリストとしてそれを返します。この手続きは
     引数Sを書き変えます。

 - procedure: sjis->euc s
     シフトjis文字のリストSをeuc文字のリストに変換して返します。
     この手続きは引数Sを書き変えます。

 - procedure: euc->sjis s
     シフトjis文字のリストSをeuc文字のリストに変換して返します。こ
     の手続きは引数Sを書き変えます。

 - procedure: jcccf:convert s from-code to-code prev-sequence
          cur-sequence add-cr zen2han?
     FROM-CODEの文字のリストSをTO-CODEの文字のリスト
     に変換して返します。_SCHEMEは常にファイルを順次的に読み込みま
     すので、_ PREV-SEQUENCEとCUR-SEQUENCEには、現在読取り
     中の文字種が以前の文字種から変化したかどうかを確認できるような変数
     を指定して下さい。使い方のサンプルは手続きJFILTER:CVのコードに入っ
     ています。ADD-CRには、シフトJISへの変換の場合に#\newlineの前
     にキャリッジリターンを追加するかどうかの論理値を指定します。この手
     続きは引数Sを書き変えます。

     ZEN2HAN?には、EUCJP、SHIFT_JIS、JIS(ISO-2022-JP)の一部の全角文字(2
     バイト文字)を、1バイトの半角文字に変換するかどうかを制御する論理値を指定
     します。

     jcccf:convertの局所手続き'zen->han'は、渡された全角文字リスト引数
     CHAR-LISTを全角文字ベクタから捜し出して、半角文字ベクタの中からイ
     ンデックスが等しい半角文字を返します。

     半角に変換する全角文字には、恣意的に次のものを選んでいます。

     SP,.:;?!"^~_-/|`'()[]{}<>+-=$%#&*  および

     [0-9A-Za-z]*.

 - procedure: jcccf:set-sequence! cur-sequence prev-sequence sequence
     新しく遭遇した文字属性をSEQUENCEに指定すると、現在の文字属性
     CUR-SEQUNCEがSEQUENCEで置き換えられ、
     CUR-SEQUENCEのそれまでの属性がprev-sequenceに移されます。こ
     の手続きは、手続きを使って大域変数を書き換えるために用意しました。

 - procedure: jcccf:write-list s port
     文字リストSをPORTに書き出します。

Jfilterの主手続き
*****************

 - procedure: cv-file input output from-code to-code remove-cr add-cr
          check-length zen2han?
     INPUTのコードを変換してOUTPUTに書き出します。INPUTと
     OUTPUTにはSchemeのポートかファイル名か#fを指定します。
     TO-CODEとFROM-CODEは'jis、'eucj、'sjis、#fのいずれかでなけれ
     ばなりません。最後の4つの引数REMOVE-CR、ADD-CR、
     CHECK-LENGTH、ZEN2HAN?はオプションの引数で、省略できます。
     REMOVE-CRとADD-CRには、シフトJISの変換の場合にキャリッジリター
     ンを削除するか追加するかの論理値を指定します。CHECK-LENGTHには、
     INPUTのコード判定のために読み込む文字数を指定します。
     ZEN2HAN?二は、全角から半角への変換を行なう場合は#tを、そうでなけれ
     ば#fを指定します。ZEN2HAN?を指定する場合は、REMOVE-CR、
     ADD-CR、CHECK-LENGTHをすべて指定する必要があります。
     CHECK-LENGTHを指定する場合は、REMOVE-CRとADD-CRをすべ
     て指定する必要があります。同様にADD-CRを指定する場合は
     REMOVE-CRを指定しなければなりません。デフォルトは#fで指定され、引
     数すべてに#fを指定した場合(cv-file#f #f #f #f)、デフォルトで、
     INPUTに(current-input-port)が、OUTPUTに(current-output-port)
     が、FROM-CODEにJUDGE-FILEによる<自動判定>が、TO-CODEに'eucj
     が、REMOVE-CRに#tが、ADD-CRに#fが、CHECK-LENGTHに5000
     が、ZEN2HAN?には#fが指定されます。

 - procedure: cv-string str from-code to-code
     STRに指定したScheme文字列のコードをFROM-CODEから
     TO-CODEに変換し、変換後の文字列を新しく作成して返します。
     FROM-CODEとTO-CODEには'jis、'eucj、'sjisのいずれかのシ
     ンボルを指定します。ascii文字は変更されずに新しいコードに渡されま
     す。

          ;例
          (require 'line-i/o)

          (define (convert-string file from-code to-code)
            (call-with-input-file file
              (lambda (inport)
                (do ((s (read-line inport)(read-line inport)))
                    ((eof-object? s))
                  (write-line (cv-string s from-code to-code))))))

     上の手続きは、テキストファイルのすべての行をfrom-codeからto-code
     に変換して標準出力に表示します。ファイル全体の文字コードの変換に
     は前記の手続きcv-fileの方が効率的です。cv-stringは新しい文字列を
     作成しますので、文字数の制限はありませんが短い文字列の変換に適し
     ています。

 - procedure: judge-file input c-length
     C-LENGTHはオプションです。INPUTをC-LENGTH文字ま
     で読んだ上でINPUTのコードを判定します。C-LENGTHが省略
     された場合は5000文字まで読み込みます。この手続きは、INPUTに
     指定したファイルにしたがって'jis、'sjis、'eucj、'ascii、'binaryの
     いずれかのシンボルを返します。INPUTには、ファイル名かポート
     が指定できます。この手続きのコード判定は完全ではなく、3種の文字コー
     ドセットすべてに共通する文字コード、特に半角カタカナが大量に含まれ
     るファイルについては、判定に失敗します。