An implementation of Scheme in the C language No right reserved or No warranty given by Kiyokazu SUTO +----+ |目次| +----+ $1. 序 $2. ファイル構成 $3. インストール $3.1. メイク $3.2. 動作確認 $3.3. 制限 $3.4. config.h $4. 動作 $4.1. 起動 $4.2. コマンドラインオプション $5. 謝辞 以下で {xxxx,yyy,...} のような書き方をしているところは, xxxx yyy ... の中 のどれか一つ, という意味です. $1. 序 ====== C 言語で記述した R4RS 準拠の Scheme の処理系のソースです. Scheme 記述のも のも含めれば, `char-ready?' 以外の R4RS の feature をすべて実装しています. さらに, 以下の拡張機能があります. 各種文字セットのサポートの為の機能 取り敢えず EUC と Shift JIS 用のコードが含まれています (`c/euc.c' と `c/sjis.c'). dynamic wind と例外処理 それぞれについて 2 種の版が含まれています. 一つは ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/prop にある proposal に準拠したもので, もう一つは処理系独自のものです. 前者は 後者を用いて実装されています. パッケージと多値 大体において Common Lisp のそれと同じ筈ですが, 多少違うところもあります. `プラグイン' メイク時のオプションにより入れたり入れなかったりできる機能, 程度に解釈し て下さい. 整数に対する Common Lisp 互換の論理演算, GNU の正規表現ライブ ラリ (regex) へのインターフェース, X Toolkit と Athena widget set へのイ ンターフェース, があります. gcc ならば多分コンパイル出来ると思います. suto が実際にメイク・動作確認を行ったのは Linux 2.0.29 上で gcc 2.7.2 と GNU make 3.74 (PC/AT clone) という組み合わせです. 旧版に関しては SunOS 4.1.3(JLE 1.1.3) 上で gcc 2.6.3 と GNU make 3.72.1 (SS1+) という組み合わせでもメイク・動作確認のレポートをいただいています. $2. ファイル構成 ================ readme.doc, changes.doc, builtin.doc US-ASCII のみによるドキュメント (どなたか英作文の添削をしてください^^;). readme.sj, changes.sj Shift JIS によるドキュメント. makefile.ux, makefile.dos, makefile.bc それぞれ UNIX, MS-DOS, BC++ 用メイクファイル. c/ C のソース等のディレクトリ. scm/ Scheme のソースのディレクトリ. scm/sys/ Scheme のソースのうち, 独自機能を使用しているもののディレクトリ. scm/sys/init.opt ダンプファイル (TeX のフォーマットファイルに相当) 作成用オプションファイ ル. $3. インストール ================ インストール上の注意を, suto の気がついた範囲で挙げます. なお以下では, ア ーカイブを展開したディレクトリを ${TOP} で表します. 実際に展開したディレクト リが (例えば) /home/suto/sick ならば, 以下の ${TOP} は /home/suto/sick に読 み替えて下さい. BC++ 版の場合はさらに, ${TOP}/makefile.dos を ${TOP}/makefile.bc に読み替えて下さい. $3.1. メイク ------------ ANSI 準拠の C コンパイラを想定しています. gcc ならばコンパイルは出来るので はないかと思います. 作者としては, gcc (Ver.2.5.8 以降) と gmake (Ver.3.7.1 以降) の組み合わせを強くお勧めします. C コンパイラが UNIX 上の gcc, djgpp, emx/gcc, または BC++ で, make が gmake ならば, 同梱のファイルを展開後, 以下のような手順でインストール出来る筈 です. バイナリ用のディレクトリを作る. ディレクトリ名は, 後述の `BIN' の値と一致するようにして下さい. djgpp, emx/gcc, または BC++ をお使いで {dj,em,bc} 以外の名前にする場合は, ${TOP}/c/makefile.{ux,dos} の中のターゲットの記述も書き換える必要があり ます. ${TOP}/makefile.{ux,dos} を ${TOP}/makefile にコピー後, 始めの方にあるマクロ を自分の環境に合わせて書き換える. 特に `BIN' バイナリを置くディレクトリ, `TOP' アーカイブを展開したディレクトリ, 及び `BINDIR' インストール先 の書き換えは必ず行ってください. jacal 用にメイクする場合は, slib と jacal をあらかじめインストールしておく必要があります. マクロ SLIB と JACAL は, それぞれをインストールしたディレクトリを指定する為のものです. また `EXDIRs' を ${TOP}/c/ のサブディレクトリの名前のリスト (区切りは半 角の空白文字または半角のコンマ) に定義すると, そのディレクトリ下にあるソ ースによって提供される機能が有効になります. 現時点で指定可能なものは以下 の通りです. logop 整数に対する CommonLisp 互換の論理演算. regex GNU の正規表現ライブラリ (regex 0.12) へのインターフェース. xt X Toolkit Intrinsics 及び Athena widget set へのインターフェース. `EXDIRs' の定義を変更した場合は, コマンドラインから `make config' として, ${TOP}/c/ の makefile.{ux,dos} と自動生成ヘッダファイル群を再構築して下 さい. その際 perl が必要になります. コマンドラインから `make {all, jacal}'. 普通の Scheme として用いる為のバイナリを生成する場合は all を, jacal 用 のバイナリを生成する場合は jacal を, ターゲットとして指定して下さい. コマンドラインから `make {install, jinstall}' インストール後は, ${TOP}/scm/, 以外のディレクトリ, ${TOP}/bin/sick 以外 のファイルは消してしまっても動作に支障は無い筈です. gcc 2.4.x に関する注意. i386 用で大域変数のレジスタへの割り当てを行うと, ${TOP}/c/ncvt.c, ${TOP}/c/num2.c, ${TOP}/c/nio.c などの浮動小数点演算を含むソースのコンパ イル中に, cc1 が abort してしまいます (djgpp 1.10 (gcc 2.4.1) と Linux 0.99pl{12,13} 上の gcc-2.4.5 で確認) . 該当版をお使いの場合は ${TOP}/bin/makefile 中のコマンド記述行に `-DNO_SPP_REG' を加えて下さい. なお gcc-2.4.x 以外ではこのような現象は起きていません. $3.2. 動作確認 -------------- 以下のような手順で動作の確認を行ってみて下さい. 何か普通でないように見える ことが起きたら, 是非 suto までご連絡を (_ _). コマンドラインから `sick checklst'. 数秒後に `> ' というプロンプトが出る筈です. プロンプトに対して `(check)'. `(tak 18 12 6)' から `(numbers-of-partitions 20)' までがすべて正常に実行 され (486DX/33MHz+エクステンダ版で 1 分半程度) 再びプロンプトが現れたら, 正しくメイク出来たものと考えてよいでしょう. プロンプトに対して `e'. shell のコマンドラインに戻ります. $3.3. 制限 ---------- 出来た実行ファイルが動く為には, 少なくとも以下の条件を満たさなければなりま せん. * ワード長は 2 の冪. * 負の整数の表現は 2 の補数. * ポインタ型相互, 及びポインタと long の間の cast は可逆な変換でなければなら ない. * 文字コードは long のビット長 - 2 または int のビット長の小さい方に納まらな ければならない. * malloc(), realloc() の返すアドレス及び int を含む構造体・共用体・配列の先 頭は, ${TOP}/c/config.h の中の WALIGN で指定するワード境界になければならな い. $3.4. config.h -------------- コンフィギュレーション用のマクロのうち, 主なものを挙げます. MYNAME C 言語の main() への第一引数が 0 の可能性が有る場合は, 実行ファイルの名 前を値として定義して下さい. SPP_REG, NO_SPP_REG gcc で, 大域変数 SPP にレジスタを割り当てることが出来る場合, ${TOP}/c/config.h ではなくて ${TOP}/c/makefile.{ux,dos} のコマンド行の記 述の中で, SPP_REG をそのレジスタ名に定義して下さい. 例えば `-DSPP_REG=ebx' (linux, djgpp, emx/gcc で有効な定義) などとします. SPP にレジスタを割り当てないことを明示する必要がある (例えば i386 用の gcc だと自動的に ebx が割り当てられるようになっていますが, それでは不都 合のある) 場合は, ${TOP}/c/makefile.{ux,dos} のコマンド記述行に `-DNO_SPP_REG' を加えてください. Tolower, Toupper #define Tolower tolower #define Toupper toupper という定義でうまくいかない場合は, #define Tolower(c) (isupper(c) ? tolower(c) : c) #define Toupper(c) (islower(c) ? toupper(c) : c) と定義してみて下さい. WALIGN 各オブジェクトの先頭を配置すべき境界を指定します. 2 の正冪でなければなり ません. 標準設定でうまく行かない場合は, 適当に大きな値に設定して見てくだ さい. DUMP_DEFAULT `-dump' オプションのデフォルト値を指定します ($4 参照). SBC, EUC, SJIS 文字集合として何を採用するかを, 単一バイト文字 ならば SBC EUC ならば EUC MS 漢字 ならば SJIS を非 0 に定義することにより指定します. 複数を同時に指定することも可能で す. デフォルトでは SBC, EUC, SJIS すべてが 1 に定義され, 文字集合の初期値は, MS-DOS または OS/2 の場合は SJIS に, UNIX の場合は EUC に, それ以外の場 合は SBC になります. なお suto が predefined macro を (一応) 把握している処理系以外の場合は sizeof(int) == sizeof(long) == sizeof( *) == 4, 8, または 16, CHAR_BIT == 8 であり, さらに厳格に ANSI 準拠の CC である, という設定になります (その筈です). この設定で不都合のある場合は, ${TOP}/c/config.h を適当に編集して下さい. 最 初の `#if 〜 #endif' ブロック, 特に `#elif defined(__unix__)' の部分と `#else' の部分が適当なテンプレートになるのではないかと思います. $4. 動作 ======== 以下では, 実行ファイルの動作を説明します. オプションファイルの中及び BC++ 版と go32 版のコマンドライン中では, B-sh のコマンドライン処理の機能のうち, 環境変数の単純置換, バッククォートによるコマンドの出力の取り込み, ワイルドカ ードの展開が実現されています (その筈です). $4.1. 起動 ---------- 起動後まず, argv[0] の内容からディレクトリ部分を取り除いた残りの文字列のう ち, C の isalnum() を偽にする文字の直前の文字までを名前とする環境変数の値を, 空白文字を区切りとしてトークン列に分解し argv[1] の前に埋め込みます. ただし 最初の文字に対しては isalnum() によるチェックは行われません. 例えば argv[0] の内容が "/home/sick/bin/sick.exe" であれば, 環境変数名は sick に, "/home/sick/bin/-sick" の場合は -sick になります 次に (新しい) argv[1] 以降の `-' で始まる引数をオプション指定とみなして解 析します. ただし `-' のみからなる引数は, オプションの終了を示すものとみなさ れます. この際, `@' で始まる引数は, 以下のように扱われます. もし `@' 以後にさらに 文字列が続けば, それをオプションファイル名とみなして, そのファイルの内容をそ こに埋め込みます. `@' のみであった場合は, 標準入力を読みます. オプションの解析が終わると, コマンドライン引数のうちオプションとして処理さ れなかったもののリストを引数として, 大域変数 `main' の値である手続きにジャン プします. 組み込みの `main' は, 引数である文字列の中で, 文字 `=' を含む文字列を変数 定義とみなして処理し (次節参照) , 残りの文字列に対して順に組み込み手続き `load' を適用します. その後, Scheme の変数 `batch-mode' の値が `#f' ならばトッ プレベルループに入ります. それ以外の値の場合は直ちに終了してしまいます. `batch-mode' の値は起動時に必ず, 以下の規則に従って初期化されます (次節参 照). (1) Scheme の変数 `explicit-batch-mode' が定義されていればその値. (2) (1) でなくかつ, 標準入力が端末でないか `-dump' オプションでダンプファイ ルへの出力が設定されていれば `#t'. (3) (1) でも (2) でもない場合 `#f'. トップレベルループからの終了は, 組み込み手続き `exit' を呼び出すことにより 行います. go32 に関する注意. お持ちの go32 が MS-DOS のファンクションコール 0x0a をサポートした版の場 合, ${TOP}/scm/sys/go32.scm をロードすると, DOSKEY や常駐 VZ を併用して トップレベルでの行編集やヒストリの機能が使えるようになります. ただし 1.11 より前の版の djgpp 付属の go32 と常駐 VZ の組合わせの場合に, 編集テ キストが無い状態で起動すると, トップレベルループのプロンプトに対して式を 入力後 Scheme に制御が戻った時点で, システムがリセットしたり Segmentation fault を起こすことがあります. 注意してお使い下さい. $4.2. コマンドラインオプション ------------------------------ 以下のコマンドラインオプションを受け付けます (最初の一行はコマンドラインか らの入力). bin/sick 3.05 @[