diff options
author | (no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-07-19 05:44:27 +0000 |
---|---|---|
committer | (no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-07-19 05:44:27 +0000 |
commit | 512dc556b4557c0e3f4e39b651ec7e236a474f5a (patch) | |
tree | 825fb1083e09354f05fe60374f8f786cc2049a08 | |
parent | f943351e1fc5c09f4e7ec29f7c4f77ca48e6494e (diff) |
This commit was manufactured by cvs2svn to create branch 'ruby_1_6'.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_6@1630 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | COPYING.ja | 51 | ||||
-rw-r--r-- | README.EXT.ja | 1187 | ||||
-rw-r--r-- | README.ja | 153 | ||||
-rw-r--r-- | doc/forwardable.rd.ja | 81 | ||||
-rw-r--r-- | doc/irb/irb-tools.rd.ja | 185 | ||||
-rw-r--r-- | doc/irb/irb.rd.ja | 391 | ||||
-rw-r--r-- | doc/shell.rd.ja | 336 | ||||
-rw-r--r-- | ext/digest/MANIFEST | 11 | ||||
-rw-r--r-- | ext/digest/digest.txt.ja | 111 | ||||
-rw-r--r-- | ext/etc/etc.txt.ja | 72 | ||||
-rw-r--r-- | ext/pty/README.expect.ja | 21 | ||||
-rw-r--r-- | ext/pty/README.ja | 89 | ||||
-rw-r--r-- | ext/readline/README.ja | 63 |
13 files changed, 2751 insertions, 0 deletions
diff --git a/COPYING.ja b/COPYING.ja new file mode 100644 index 0000000000..933cc7cb9a --- /dev/null +++ b/COPYING.ja @@ -0,0 +1,51 @@ +$BK\%W%m%0%i%`$O%U%j!<%=%U%H%&%'%"$G$9!%(BGPL(the GNU General +Public License)$B$^$?$O0J2<$K<($9>r7o$GK\%W%m%0%i%`$r:FG[I[$G(B +$B$-$^$9!%(BGPL$B$K$D$$$F$O(BGPL$B%U%!%$%k$r;2>H$7$F2<$5$$!%(B + + 1. $BJ#@=$O@)8B$J$/<+M3$G$9!%(B + + 2. $B0J2<$N>r7o$N$$$:$l$+$rK~$?$9;~$KK\%W%m%0%i%`$N%=!<%9$r(B + $B<+M3$KJQ99$G$-$^$9!%(B + + (a) $B%M%C%H%K%e!<%:$K%]%9%H$7$?$j!$:n<T$KJQ99$rAwIU$9$k(B + $B$J$I$NJ}K!$G!$JQ99$r8x3+$9$k!%(B + + (b) $BJQ99$7$?K\%W%m%0%i%`$r<+J,$N=jB0$9$kAH?%FbIt$@$1$G(B + $B;H$&!%(B + + (c) $BJQ99E@$rL@<($7$?$&$(!$%=%U%H%&%'%"$NL>A0$rJQ99$9$k!%(B + $B$=$N%=%U%H%&%'%"$rG[I[$9$k;~$K$OJQ99A0$NK\%W%m%0%i(B + $B%`$bF1;~$KG[I[$9$k!%$^$?$OJQ99A0$NK\%W%m%0%i%`$N%=!<(B + $B%9$NF~<jK!$rL@<($9$k!%(B + + (d) $B$=$NB>$NJQ99>r7o$r:n<T$H9g0U$9$k!%(B + + 3. $B0J2<$N>r7o$N$$$:$l$+$rK~$?$9;~$KK\%W%m%0%i%`$r%3%s%Q%$(B + $B%k$7$?%*%V%8%'%/%H%3!<%I$d<B9T7A<0$G$bG[I[$G$-$^$9!%(B + + (a) $B%P%$%J%j$r<u$1<h$C$??M$,%=!<%9$rF~<j$G$-$k$h$&$K!$(B + $B%=!<%9$NF~<jK!$rL@<($9$k!%(B + + (b) $B5!3#2DFI$J%=!<%9%3!<%I$rE:IU$9$k!%(B + + (c) $BJQ99$r9T$C$?%P%$%J%j$OL>A0$rJQ99$7$?$&$(!$%*%j%8%J(B + $B%k$N%=!<%9%3!<%I$NF~<jK!$rL@<($9$k!%(B + + (d) $B$=$NB>$NG[I[>r7o$r:n<T$H9g0U$9$k!%(B + + 4. $BB>$N%W%m%0%i%`$X$N0zMQ$O$$$+$J$kL\E*$G$"$l<+M3$G$9!%$?(B + $B$@$7!$K\%W%m%0%i%`$K4^$^$l$kB>$N:n<T$K$h$k%3!<%I$O!$$=(B + $B$l$>$l$N:n<T$N0U8~$K$h$k@)8B$,2C$($i$l$k>l9g$,$"$j$^$9!%(B + + $B$=$l$i%U%!%$%k$N0lMw$H$=$l$>$l$NG[I[>r7o$J$I$KIU$$$F$O(B + LEGAL$B%U%!%$%k$r;2>H$7$F$/$@$5$$!%(B + + 5. $BK\%W%m%0%i%`$X$NF~NO$H$J$k%9%/%j%W%H$*$h$S!$K\%W%m%0%i(B + $B%`$+$i$N=PNO$N8"Mx$OK\%W%m%0%i%`$N:n<T$G$O$J$/!$$=$l$>(B + $B$l$NF~=PNO$r@8@.$7$??M$KB0$7$^$9!%$^$?!$K\%W%m%0%i%`$K(B + $BAH$_9~$^$l$k$?$a$N3HD%%i%$%V%i%j$K$D$$$F$bF1MM$G$9!%(B + + 6. $BK\%W%m%0%i%`$OL5J]>Z$G$9!%:n<T$OK\%W%m%0%i%`$r%5%]!<%H(B + $B$9$k0U;V$O$"$j$^$9$,!$%W%m%0%i%`<+?H$N%P%0$"$k$$$OK\%W(B + $B%m%0%i%`$N<B9T$J$I$+$iH/@8$9$k$$$+$J$kB;32$KBP$7$F$b@U(B + $BG$$r;}$A$^$;$s!%(B diff --git a/README.EXT.ja b/README.EXT.ja new file mode 100644 index 0000000000..068296eeb8 --- /dev/null +++ b/README.EXT.ja @@ -0,0 +1,1187 @@ +.\" README.EXT.ja - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995 + +Rubyの拡張ライブラリの作り方を説明します. + +1.基礎知識 + +Cの変数には型があり,データには型がありません.ですから,た +とえばポインタをintの変数に代入すると,その値は整数として取 +り扱われます.逆にRubyの変数には型がなく,データに型がありま +す.この違いのため,CとRubyは相互に変換しなければ,お互いの +データをアクセスできません. + +RubyのデータはVALUEというCの型で表現されます.VALUE型のデー +タはそのデータタイプを自分で知っています.このデータタイプと +いうのはデータ(オブジェクト)の実際の構造を意味していて,Ruby +のクラスとはまた違ったものです. + +VALUEからCにとって意味のあるデータを取り出すためには + + (1) VALUEのデータタイプを知る + (2) VALUEをCのデータに変換する + +の両方が必要です.(1)を忘れると間違ったデータの変換が行われ +て,最悪プログラムがcore dumpします. + +1.1 データタイプ + +Rubyにはユーザが使う可能性のある以下のタイプがあります. + + T_NIL nil + T_OBJECT 通常のオブジェクト + T_CLASS クラス + T_MODULE モジュール + T_FLOAT 浮動小数点数 + T_STRING 文字列 + T_REGEXP 正規表現 + T_ARRAY 配列 + T_FIXNUM Fixnum(31bit長整数) + T_HASH 連想配列 + T_STRUCT (Rubyの)構造体 + T_BIGNUM 多倍長整数 + T_FILE 入出力 + T_TRUE 真 + T_FALSE 偽 + T_DATA データ + T_SYMBOL シンボル + +その他に内部で利用されている以下のタイプがあります. + + T_ICLASS + T_MATCH + T_UNDEF + T_VARMAP + T_SCOPE + T_NODE + +ほとんどのタイプはCの構造体で実装されています. + +1.2 VALUEのデータタイプをチェックする + +ruby.hではTYPE()というマクロが定義されていて,VALUEのデータ +タイプを知ることが出来ます.TYPE()マクロは上で紹介したT_XXXX +の形式の定数を返します.VALUEのデータタイプに応じて処理する +場合には,TYPE()の値で分岐することになります. + + switch (TYPE(obj)) { + case T_FIXNUM: + /* FIXNUMの処理 */ + break; + case T_STRING: + /* 文字列の処理 */ + break; + case T_ARRAY: + /* 配列の処理 */ + break; + default: + /* 例外を発生させる */ + rb_raise(rb_eTypeError, "not valid value"); + break; + } + +それとデータタイプをチェックして,正しくなければ例外を発生す +る関数が用意されています. + + void Check_Type(VALUE value, int type) + +この関数はvalueがtypeで無ければ,例外を発生させます.引数と +して与えられたVALUEのデータタイプが正しいかどうかチェックす +るためには,この関数を使います. + +FIXNUMとNILに関してはより高速な判別マクロが用意されています. + + FIXNUM_P(obj) + NIL_P(obj) + +1.3 VALUEをCのデータに変換する + +データタイプがT_NIL, T_FALSE, T_TRUEである時,データはそれぞ +れnil, false, trueです.このデータタイプのオブジェクトはひと +つずつしか存在しません. + +データタイプがT_FIXNUMの時,これは31bitのサイズを持つ整数で +す.FIXNUMをCの整数に変換するためにはマクロ「FIX2INT()」を使 +います.それから,FIXNUMに限らずRubyのデータを整数に変換する +「NUM2INT()」というマクロがあります.このマクロはデータタイ +プのチェック無しで使えます(整数に変換できない場合には例外が +発生する). + +同様にチェック無しで使える変換マクロはdoubleを取り出す +「NUM2DBL()」とchar*を取り出す「STR2CSTR()」があります. + +それ以外のデータタイプは対応するCの構造体があります.対応す +る構造体のあるVALUEはそのままキャスト(型変換)すれば構造体の +ポインタに変換できます. + +構造体は「struct RXxxxx」という名前でruby.hで定義されていま +す.例えば文字列は「struct RString」です.実際に使う可能性が +あるのは文字列と配列くらいだと思います. + +ruby.hでは構造体へキャストするマクロも「RXXXXX()」(全部大文 +字にしたもの)という名前で提供されています(例: RSTRING()). + +例えば,文字列strの長さを得るためには「RSTRING(str)->len」と +し,文字列strをchar*として得るためには「RSTRING(str)->ptr」 +とします.配列の場合には,それぞれ「RARRAY(ary)->len」, +「RARRAY(ary)->ptr」となります. + +Rubyの構造体を直接アクセスする時に気をつけなければならないこ +とは,配列や文字列の構造体の中身は参照するだけで,直接変更し +ないことです.直接変更した場合,オブジェクトの内容の整合性が +とれなくなって,思わぬバグの原因になります. + +1.4 CのデータをVALUEに変換する + +VALUEの実際の構造は + + * FIXNUMの場合 + + 1bit左シフトして,LSBを立てる. + + * その他のポインタの場合 + + そのままVALUEにキャストする. + +となっています.よって,LSBをチェックすればVALUEがFIXNUMかど +うかわかるわけです(ポインタのLSBが立っていないことを仮定して +いる). + +ですから,FIXNUM以外のRubyのオブジェクトの構造体は単にVALUE +にキャストするだけでVALUEに変換出来ます.ただし,任意の構造 +体がVALUEにキャスト出来るわけではありません.キャストするの +はRubyの知っている構造体(ruby.hで定義されているstruct RXxxx +のもの)だけです. + +FIXNUMに関しては変換マクロを経由する必要があります.Cの整数 +からVALUEに変換するマクロは以下のものがあります.必要に応じ +て使い分けてください. + + INT2FIX() もとの整数が31bit以内に収まる自信がある時 + INT2NUM() 任意の整数からVALUEへ + +INT2NUM()は整数がFIXNUMの範囲に収まらない場合,Bignumに変換 +してくれます(が,少し遅い). + +1.5 Rubyのデータを操作する + +先程も述べた通り,Rubyの構造体をアクセスする時に内容の更新を +行うことは勧められません.で,Rubyのデータを操作する時には +Rubyが用意している関数を用いてください. + +ここではもっとも使われるであろう文字列と配列の生成/操作を行 +い関数をあげます(全部ではないです). + + 文字列に対する関数 + + rb_str_new(const char *ptr, long len) + + 新しいRubyの文字列を生成する. + + rb_str_new2(const char *ptr) + + Cの文字列からRubyの文字列を生成する.この関数の機能は + rb_str_new(ptr, strlen(ptr))と同等である. + + rb_tainted_str_new(const char *ptr, long len) + + 汚染マークが付加された新しいRubyの文字列を生成する.外部 + からのデータに基づく文字列には汚染マークが付加されるべき + である. + + rb_tainted_str_new2(const char *ptr) + + Cの文字列から汚染マークが付加されたRubyの文字列を生成する. + + rb_str_cat(VALUE str, const char *ptr, long len) + + Rubyの文字列strにlenバイトの文字列ptrを追加する. + + 配列に対する関数 + + rb_ary_new() + + 要素が0の配列を生成する. + + rb_ary_new2(long len) + + 要素が0の配列を生成する.len要素分の領域をあらかじめ割り + 当てておく. + + rb_ary_new3(long n, ...) + + 引数で指定したn要素を含む配列を生成する. + + rb_ary_new4(long n, VALUE *elts) + + 配列で与えたn要素の配列を生成する. + + rb_ary_push(VALUE ary, VALUE val) + rb_ary_pop(VALUE ary) + rb_ary_shift(VALUE ary) + rb_ary_unshift(VALUE ary, VALUE val) + + Arrayの同名のメソッドと同じ働きをする関数.第1引数は必ず + 配列でなければならない. + +2.Rubyの機能を使う + +原理的にRubyで書けることはCでも書けます.RubyそのものがCで記 +述されているんですから,当然といえば当然なんですけど.ここで +はRubyの拡張に使うことが多いだろうと予測される機能を中心に紹 +介します. + +2.1 Rubyに機能を追加する + +Rubyで提供されている関数を使えばRubyインタプリタに新しい機能 +を追加することができます.Rubyでは以下の機能を追加する関数が +提供されています. + + * クラス,モジュール + * メソッド,特異メソッドなど + * 定数 + +では順に紹介します. + +2.1.1 クラス/モジュール定義 + +クラスやモジュールを定義するためには,以下の関数を使います. + + VALUE rb_define_class(const char *name, VALUE super) + VALUE rb_define_module(const char *name) + +これらの関数は新しく定義されたクラスやモジュールを返します. +メソッドや定数の定義にこれらの値が必要なので,ほとんどの場合 +は戻り値を変数に格納しておく必要があるでしょう. + +クラスやモジュールを他のクラスの内部にネストして定義する時に +は以下の関数を使います. + + VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) + VALUE rb_define_module_under(VALUE outer, const char *name) + +2.1.2 メソッド/特異メソッド定義 + +メソッドや特異メソッドを定義するには以下の関数を使います. + + void rb_define_method(VALUE klass, const char *name, + VALUE (*func)(), int argc) + + void rb_define_singleton_method(VALUE object, const char *name, + VALUE (*func)(), int argc) + + +念のため説明すると「特異メソッド」とは,その特定のオブジェク +トに対してだけ有効なメソッドです.RubyではよくSmalltalkにお +けるクラスメソッドとして,クラスに対する特異メソッドが使われ +ます. + +これらの関数の argcという引数はCの関数へ渡される引数の数(と +形式)を決めます.argcが0以上の時は関数に引き渡す引数の数を意 +味します.16個以上の引数は使えません(が,要りませんよね,そ +んなに).実際の関数には先頭の引数としてselfが与えられますの +で,指定した数より1多い引数を持つことになります. + +argcが負の時は引数の数ではなく,形式を指定したことになります. +argcが-1の時は引数を配列に入れて渡されます.argcが-2の時は引 +数はRubyの配列として渡されます. + +メソッドを定義する関数はもう二つあります.ひとつはprivateメ +ソッドを定義する関数で,引数はrb_define_method()と同じです. + + void rb_define_private_method(VALUE klass, const char *name, + VALUE (*func)(), int argc) + +privateメソッドとは関数形式でしか呼び出すことの出来ないメソッ +ドです. + +もうひとつはモジュール関数を定義するものです.モジュール関数 +とはモジュールの特異メソッドであり,同時にprivateメソッドで +もあるものです.例をあげるとMathモジュールのsqrt()などがあげ +られます.このメソッドは + + Math.sqrt(4) + +という形式でも + + include Math + sqrt(4) + +という形式でも使えます.モジュール関数を定義する関数は以下の +通りです. + + void rb_define_module_function(VALUE module, const char *name, + VALUE (*func)(), int argc) + +関数的メソッド(Kernelモジュールのprivate method)を定義するた +めの関数は以下の通りです. + + void rb_define_global_function(const char *name, VALUE (*func)(), int argc) + + +メソッドの別名を定義するための関数は以下の通りです。 + + void rb_define_alias(VALUE module, const char* new, const char* old); + +2.1.3 定数定義 + +拡張ライブラリが必要な定数はあらかじめ定義しておいた方が良い +でしょう.定数を定義する関数は二つあります. + + void rb_define_const(VALUE klass, const char *name, VALUE val) + void rb_define_global_const(const char *name, VALUE val) + +前者は特定のクラス/モジュールに属する定数を定義するもの,後 +者はグローバルな定数を定義するものです. + +2.2 Rubyの機能をCから呼び出す + +既に『1.5 Rubyのデータを操作する』で一部紹介したような関数を +使えば,Rubyの機能を実現している関数を直接呼び出すことが出来 +ます. + +# このような関数の一覧表はいまのところありません.ソースを見 +# るしかないですね. + +それ以外にもRubyの機能を呼び出す方法はいくつかあります. + +2.2.1 Rubyのプログラムをevalする + +CからRubyの機能を呼び出すもっとも簡単な方法として,文字列で +与えられたRubyのプログラムを評価する以下の関数があります. + + VALUE rb_eval_string(const char *str) + +この評価は現在の環境で行われます.つまり,現在のローカル変数 +などを受け継ぎます. + +2.2.2 IDまたはシンボル + +Cから文字列を経由せずにRubyのメソッドを呼び出すこともできま +す.その前に,Rubyインタプリタ内でメソッドや変数名を指定する +時に使われているIDについて説明しておきましょう. + +IDとは変数名,メソッド名を表す整数です.Rubyの中では + + :識別子 + +でアクセスできます.Cからこの整数を得るためには関数 + + rb_intern(const char *name) + +を使います.Rubyから引数として与えられたシンボル(または文字 +列)をIDに変換するには以下の関数を使います. + + rb_to_id(VALUE symbol) + +2.2.3 CからRubyのメソッドを呼び出す + +Cから文字列を経由せずにRubyのメソッドを呼び出すためには以下 +の関数を使います. + + VALUE rb_funcall(VALUE recv, ID mid, int argc, ...) + +この関数はオブジェクトrecvのmidで指定されるメソッドを呼び出 +します.その他に引数の指定の仕方が違う以下の関数もあります. + + VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) + VALUE rb_apply(VALUE recv, ID mid, VALUE args) + +applyには引数としてRubyの配列を与えます. + +2.2.4 変数/定数を参照/更新する + +Cから関数を使って参照・更新できるのは,定数,インスタンス変 +数です.大域変数は一部のものはCの大域変数としてアクセスでき +ます.ローカル変数を参照する方法は公開していません. + +オブジェクトのインスタンス変数を参照・更新する関数は以下の通 +りです. + + VALUE rb_ivar_get(VALUE obj, ID id) + VALUE rb_ivar_set(VALUE obj, ID id, VALUE val) + +idはrb_intern()で得られるものを使ってください. + +定数を参照するには以下の関数を使ってください. + + VALUE rb_const_get(VALUE obj, ID id) + +定数を新しく定義するためには『2.1.3 定数定義』で紹介さ +れている関数を使ってください. + +3.RubyとCとの情報共有 + +C言語とRubyの間で情報を共有する方法について解説します. + +3.1 Cから参照できるRubyの定数 + +以下のRubyの定数はCのレベルから参照できます. + + Qtrue + Qfalse + + 真偽値.QfalseはC言語でも偽とみなされます(つまり0). + + Qnil + + C言語から見た「nil」. + +3.2 CとRubyで共有される大域変数 + +CとRubyで大域変数を使って情報を共有できます.共有できる大域 +変数にはいくつかの種類があります.そのなかでもっとも良く使わ +れると思われるのはrb_define_variable()です. + + void rb_define_variable(const char *name, VALUE *var) + +この関数はRubyとCとで共有する大域変数を定義します.変数名が +`$'で始まらない時には自動的に追加されます.この変数の値を変 +更すると自動的にRubyの対応する変数の値も変わります. + +またRuby側からは更新できない変数もあります.このread onlyの +変数は以下の関数で定義します. + + void rb_define_readonly_variable(const char *name, VALUE *var) + +これら変数の他にhookをつけた大域変数を定義できます.hook付き +の大域変数は以下の関数を用いて定義します.hook付き大域変数の +値の参照や設定はhookで行う必要があります. + + void rb_define_hooked_variable(const char *name, VALUE *var, + VALUE (*getter)(), void (*setter)()) + +この関数はCの関数によってhookのつけられた大域変数を定義しま +す.変数が参照された時には関数getterが,変数に値がセットされ +た時には関数setterが呼ばれる.hookを指定しない場合はgetterや +setterに0を指定します. + +# getterもsetterも0ならばrb_define_variable()と同じになる. + +それから,Cの関数によって実現されるRubyの大域変数を定義する +関数があります. + + void rb_define_virtual_variable(const char *name, + VALUE (*getter)(), void (*setter)()) + +この関数によって定義されたRubyの大域変数が参照された時には +getterが,変数に値がセットされた時にはsetterが呼ばれます. + +getterとsetterの仕様は以下の通りです. + + (*getter)(ID id, void *data, struct global_entry* entry); + (*setter)(VALUE val, ID id, void *data, struct global_entry* entry); + +3.3 CのデータをRubyオブジェクトにする + +Cの世界で定義されたデータ(構造体)をRubyのオブジェクトとして +取り扱いたい場合がありえます.このような場合には,Dataという +RubyオブジェクトにCの構造体(へのポインタ)をくるむことでRuby +オブジェクトとして取り扱えるようになります. + +Dataオブジェクトを生成して構造体をRubyオブジェクトにカプセル +化するためには,以下のマクロを使います. + + Data_Wrap_Struct(klass, mark, free, ptr) + +このマクロの戻り値は生成されたDataオブジェクトです. + +klassはこのDataオブジェクトのクラスです.ptrはカプセル化する +Cの構造体へのポインタです.markはこの構造体がRubyのオブジェ +クトへの参照がある時に使う関数です.そのような参照を含まない +時には0を指定します. + +# そのような参照は勧められません. + +freeはこの構造体がもう不要になった時に呼ばれる関数です.この +関数がガーベージコレクタから呼ばれます. + +Cの構造体の割当とDataオブジェクトの生成を同時に行うマクロと +して以下のものが提供されています. + + Data_Make_Struct(klass, type, mark, free, sval) + +このマクロの戻り値は生成されたDataオブジェクトです. + +klass, mark, freeはData_Wrap_Structと同じ働きをします.type +は割り当てるC構造体の型です.割り当てられた構造体は変数sval +に代入されます.この変数の型は (type*) である必要があります. + +Dataオブジェクトからポインタを取り出すのは以下のマクロを用い +ます. + + Data_Get_Struct(obj, type, sval) + +Cの構造体へのポインタは変数svalに代入されます. + +これらのDataの使い方はちょっと分かりにくいので,後で説明する +例題を参照してください. + +4.例題 - dbmパッケージを作る + +ここまでの説明でとりあえず拡張ライブラリは作れるはずです. +Rubyのextディレクトリにすでに含まれているdbmライブラリを例に +して段階的に説明します. + +(1) ディレクトリを作る + + % mkdir ext/dbm + +Ruby 1.1からは任意のディレクトリでダイナミックライブラリを作 +ることができるようになりました.Rubyに静的にリンクする場合に +はRubyを展開したディレクトリの下,extディレクトリの中に拡張 +ライブラリ用のディレクトリを作る必要があります.名前は適当に +選んで構いません. + +(2) MANIFESTファイルを作る + + % cd ext/dbm + % touch MANIFEST + +拡張ライブラリのディレクトリの下にはMANIFESTというファイルが +必要なので,とりあえず空のファイルを作っておきます.後でこの +ファイルには必要なファイル一覧が入ることになります. + +MANIFESTというファイルは,静的リンクのmakeの時にディレクトリ +が拡張ライブラリを含んでいるかどうか判定するために使われれて +います.ダイナミックライブラリを作る場合には必ずしも必要では +ありません. + +(3) 設計する + +まあ,当然なんですけど,どういう機能を実現するかどうかまず設 +計する必要があります.どんなクラスをつくるか,そのクラスには +どんなメソッドがあるか,クラスが提供する定数などについて設計 +します. + +(4) Cコードを書く + +拡張ライブラリ本体となるC言語のソースを書きます.C言語のソー +スがひとつの時には「ライブラリ名.c」を選ぶと良いでしょう.C +言語のソースが複数の場合には逆に「ライブラリ名.c」というファ +イル名は避ける必要があります.オブジェクトファイルとモジュー +ル生成時に中間的に生成される「ライブラリ名.o」というファイル +とが衝突するからです. + +Rubyは拡張ライブラリをロードする時に「Init_ライブラリ名」と +いう関数を自動的に実行します.dbmライブラリの場合「Init_dbm」 +です.この関数の中でクラス,モジュール,メソッド,定数などの +定義を行います.dbm.cから一部引用します. + +-- +Init_dbm() +{ + /* DBMクラスを定義する */ + cDBM = rb_define_class("DBM", rb_cObject); + /* DBMはEnumerateモジュールをインクルードする */ + rb_include_module(cDBM, rb_mEnumerable); + + /* DBMクラスのクラスメソッドopen(): 引数はCの配列で受ける */ + rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1); + + /* DBMクラスのメソッドclose(): 引数はなし */ + rb_define_method(cDBM, "close", fdbm_close, 0); + /* DBMクラスのメソッド[]: 引数は1個 */ + rb_define_method(cDBM, "[]", fdbm_fetch, 1); + : + + /* DBMデータを格納するインスタンス変数名のためのID */ + id_dbm = rb_intern("dbm"); +} +-- + +DBMライブラリはdbmのデータと対応するオブジェクトになるはずで +すから,Cの世界のdbmをRubyの世界に取り込む必要があります. + + +dbm.cではData_Make_Structを以下のように使っています. + +-- +struct dbmdata { + int di_size; + DBM *di_dbm; +}; + + +obj = Data_Make_Struct(klass, struct dbmdata, 0, free_dbm, dbmp); +-- + +ここではdbmstruct構造体へのポインタをDataにカプセル化してい +ます.DBM*を直接カプセル化しないのはclose()した時の処理を考 +えてのことです. + +Dataオブジェクトからdbmstruct構造体のポインタを取り出すため +に以下のマクロを使っています. + +-- +#define GetDBM(obj, dbmp) {\ + Data_Get_Struct(obj, struct dbmdata, dbmp);\ + if (dbmp->di_dbm == 0) closed_dbm();\ +} +-- + +ちょっと複雑なマクロですが,要するにdbmdata構造体のポインタ +の取り出しと,closeされているかどうかのチェックをまとめてい +るだけです. + +DBMクラスにはたくさんメソッドがありますが,分類すると3種類の +引数の受け方があります.ひとつは引数の数が固定のもので,例と +してはdeleteメソッドがあります.deleteメソッドを実装している +fdbm_delete()はこのようになっています. + +-- +static VALUE +fdbm_delete(obj, keystr) + VALUE obj, keystr; +{ + : +} +-- + +引数の数が固定のタイプは第1引数がself,第2引数以降がメソッド +の引数となります. + +引数の数が不定のものはCの配列で受けるものとRubyの配列で受け +るものとがあります.dbmライブラリの中で,Cの配列で受けるもの +はDBMのクラスメソッドであるopen()です.これを実装している関 +数fdbm_s_open()はこうなっています. + +-- +static VALUE +fdbm_s_open(argc, argv, klass) + int argc; + VALUE *argv; + VALUE klass; +{ + : + if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) { + mode = 0666; /* default value */ + } + : +} +-- + +このタイプの関数は第1引数が与えられた引数の数,第2引数が与え +られた引数の入っている配列になります.selfは第3引数として与 +えられます. + +この配列で与えられた引数を解析するための関数がopen()でも使わ +れているrb_scan_args()です.第3引数に指定したフォーマットに +従い,第4変数以降に指定した変数に値を代入してくれます.この +フォーマットは,第1文字目が省略できない引数の数,第2文字目が +省略できる引数の数,第3文字目が対応する相手が無いあまりの引 +数があるかどうかを示す"*"です.2文字目と3文字目は省略できま +す.dbm.cの例では,フォーマットは"11"ですから,引数は最低1つ +で,2つまで許されるという意味になります.省略されている時の +変数の値はnil(C言語のレベルではQnil)になります. + +Rubyの配列で引数を受け取るものはindexesがあります.実装はこ +うです. + +-- +static VALUE +fdbm_indexes(obj, args) + VALUE obj, args; +{ + : +} +-- + +第1引数はself,第2引数はRubyの配列です. + +** 注意事項 + +Rubyと共有はしないがRubyのオブジェクトを格納する可能性のある +Cの大域変数は以下の関数を使ってRubyインタプリタに変数の存在 +を教えてあげてください.でないとGCでトラブルを起こします. + + void rb_global_variable(VALUE *var) + +(5) extconf.rbを用意する + +Makefileを作る場合の雛型になるextconf.rbというファイルを作り +ます.extconf.rbはライブラリのコンパイルに必要な条件のチェッ +クなどを行うことが目的です.まず, + + require 'mkmf' + +をextconf.rbの先頭に置きます.extconf.rbの中では以下のRuby関 +数を使うことが出来ます. + + have_library(lib, func): ライブラリの存在チェック + have_func(func, header): 関数の存在チェック + have_header(header): ヘッダファイルの存在チェック + create_makefile(target): Makefileの生成 + +以下の変数を使うことができます. + + $CFLAGS: コンパイル時に追加的に指定するフラグ(-Iなど) + $LDFLAGS: リンク時に追加的に指定するフラグ(-Lなど) + +ライブラリをコンパイルする条件が揃わず,そのライブラリをコン +パイルしない時にはcreate_makefileを呼ばなければMakefileは生 +成されず,コンパイルも行われません. + +(6) dependを用意する + +もし,ディレクトリにdependというファイルが存在すれば, +Makefileが依存関係をチェックしてくれます. + + % gcc -MM *.c > depend + +などで作ることが出来ます.あって損は無いでしょう. + +(7) MANIFESTファイルにファイル名を入れる + + % find * -type f -print > MANIFEST + % vi MANIFEST + +*.o, *~など不必要なファイル以外はMANIFESTに追加しておきます. +make時にはMANIFESTの内容は参照しませんので,空のままでも問題 +は起きませんが,パッケージングの時に参照することがあるのと, +必要なファイルを区別できるので,用意しておいた方が良いでしょ +う. + +(8) Makefileを生成する + +Makefileを実際に生成するためには + + ruby extconf.rb + +とします.extconf.rbに require 'mkmf' の行がない場合にはエラー +になりますので,引数を追加して + + ruby -r mkmf extconf.rb + +としてください. + +ディレクトリをext以下に用意した場合にはRuby全体のmakeの時に +自動的にMakefileが生成されますので,このステップは不要です. + +(9) makeする + +動的リンクライブラリを生成する場合にはその場でmakeしてくださ +い.必要であれば make install でインストールされます. + +ext以下にディレクトリを用意した場合は,Rubyのディレクトリで +makeを実行するとMakefileを生成からmake,必要によってはそのモ +ジュールのRubyへのリンクまで自動的に実行してくれます. +extconf.rbを書き換えるなどしてMakefileの再生成が必要な時はま +たRubyディレクトリでmakeしてください. + +拡張ライブラリはmake installでRubyライブラリのディレクトリの +下にコピーされます.もし拡張ライブラリと協調して使うRubyで記 +述されたプログラムがあり,Rubyライブラリに置きたい場合には, +拡張ライブラリ用のディレクトリの下に lib というディレクトリ +を作り,そこに 拡張子 .rb のファイルを置いておけば同時にイン +ストールされます. + +(10) デバッグ + +まあ,デバッグしないと動かないでしょうね.ext/Setupにディレ +クトリ名を書くと静的にリンクするのでデバッガが使えるようにな +ります.その分コンパイルが遅くなりますけど. + +(11) できあがり + +後はこっそり使うなり,広く公開するなり,売るなり,ご自由にお +使いください.Rubyの作者は拡張ライブラリに関して一切の権利を +主張しません. + +Appendix A. Rubyのソースコードの分類 + +Rubyのソースはいくつかに分類することが出来ます.このうちクラ +スライブラリの部分は基本的に拡張ライブラリと同じ作り方になっ +ています.これらのソースは今までの説明でほとんど理解できると +思います. + +Ruby言語のコア + + class.c + error.c + eval.c + gc.c + object.c + parse.y + variable.c + +ユーティリティ関数 + + dln.c + regex.c + st.c + util.c + +Rubyコマンドの実装 + + dmyext.c + inits.c + main.c + ruby.c + version.c + +クラスライブラリ + + array.c + bignum.c + compar.c + dir.c + enum.c + file.c + hash.c + io.c + marshal.c + math.c + numeric.c + pack.c + prec.c + process.c + random.c + range.c + re.c + signal.c + sprintf.c + string.c + struct.c + time.c + +Appendix B. 拡張用関数リファレンス + +C言語からRubyの機能を利用するAPIは以下の通りである. + +** 型 + +VALUE + + Rubyオブジェクトを表現する型.必要に応じてキャストして用いる. + 組み込み型を表現するCの型はruby.hに記述してあるRで始まる構造 + 体である.VALUE型をこれらにキャストするためにRで始まる構造体 + 名を全て大文字にした名前のマクロが用意されている. + +** 変数・定数 + +Qnil + + 定数: nilオブジェクト + +Qtrue + + 定数: trueオブジェクト(真のデフォルト値) + +Qfalse + + 定数: falseオブジェクト + +** Cデータのカプセル化 + +Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *sval) + + Cの任意のポインタをカプセル化したRubyオブジェクトを返す.こ + のポインタがRubyからアクセスされなくなった時,freeで指定した + 関数が呼ばれる.また,このポインタの指すデータが他のRubyオブ + ジェクトを指している場合,markに指定する関数でマークする必要 + がある. + +Data_Make_Struct(klass, type, mark, free, sval) + + type型のメモリをmallocし,変数svalに代入した後,それをカプセ + ル化したデータを返すマクロ. + +Data_Get_Struct(data, type, sval) + + dataからtype型のポインタを取り出し変数svalに代入するマクロ. + +** 型チェック + +TYPE(value) +FIXNUM_P(value) +NIL_P(value) +void Check_Type(VALUE value, int type) +void Check_SafeStr(VALUE value) + +** 型変換 + +FIX2INT(value) +INT2FIX(i) +NUM2INT(value) +INT2NUM(i) +NUM2DBL(value) +rb_float_new(f) +STR2CSTR(value) +rb_str_new2(s) + +** クラス/モジュール定義 + +VALUE rb_define_class(const char *name, VALUE super) + + superのサブクラスとして新しいRubyクラスを定義する. + +VALUE rb_define_class_under(VALUE module, const char *name, VALUE super) + + superのサブクラスとして新しいRubyクラスを定義し,moduleの + 定数として定義する. + +VALUE rb_define_module(const char *name) + + 新しいRubyモジュールを定義する. + +VALUE rb_define_module_under(VALUE module, const char *name, VALUE super) + + 新しいRubyモジュールを定義し,moduleの定数として定義する. + +void rb_include_module(VALUE klass, VALUE module) + + モジュールをインクルードする.classがすでにmoduleをインク + ルードしている時には何もしない(多重インクルードの禁止). + +void rb_extend_object(VALUE object, VALUE module) + + オブジェクトをモジュール(で定義されているメソッド)で拡張する. + +** 大域変数定義 + +void rb_define_variable(const char *name, VALUE *var) + + RubyとCとで共有するグローバル変数を定義する.変数名が`$'で + 始まらない時には自動的に追加される.nameとしてRubyの識別子 + として許されない文字(例えば` ')を含む場合にはRubyプログラ + ムからは見えなくなる. + +void rb_define_readonly_variable(const char *name, VALUE *var) + + RubyとCとで共有するread onlyのグローバル変数を定義する. + read onlyであること以外はrb_define_variable()と同じ. + +void rb_define_virtual_variable(const char *name, + VALUE (*getter)(), void (*setter)()) + + 関数によって実現されるRuby変数を定義する.変数が参照された + 時にはgetterが,変数に値がセットされた時にはsetterが呼ばれ + る. + +void rb_define_hooked_variable(const char *name, VALUE *var, + VALUE (*getter)(), void (*setter)()) + + 関数によってhookのつけられたグローバル変数を定義する.変数 + が参照された時にはgetterが,関数に値がセットされた時には + setterが呼ばれる.getterやsetterに0を指定した時にはhookを + 指定しないのと同じ事になる. + +void rb_global_variable(VALUE *var) + + GCのため,Rubyプログラムからはアクセスされないが, Rubyオブ + ジェクトを含む大域変数をマークする. + +** 定数 + +void rb_define_const(VALUE klass, const char *name, VALUE val) + + 定数を定義する. + +void rb_define_global_const(const char *name, VALUE val) + + 大域定数を定義する. + + rb_define_const(rb_cObject, name, val) + + と同じ意味. + +** メソッド定義 + +rb_define_method(VALUE klass, const char *name, VALUE (*func)(), int argc) + + メソッドを定義する.argcはselfを除く引数の数.argcが-1の時, + 関数には引数の数(selfを含まない)を第1引数, 引数の配列を第2 + 引数とする形式で与えられる(第3引数はself).argcが-2の時, + 第1引数がself, 第2引数がargs(argsは引数を含むRubyの配列)と + いう形式で与えられる. + +rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(), int argc) + + privateメソッドを定義する.引数はrb_define_method()と同じ. + +rb_define_singleton_method(VALUE klass, const char *name, VALUE (*func)(), int argc) + + 特異メソッドを定義する.引数はrb_define_method()と同じ. + +rb_scan_args(int argc, VALUE *argv, const char *fmt, ...) + + argc, argv形式で与えられた引数を分解する.fmtは必須引数の数, + 付加引数の数, 残りの引数があるかを指定する文字列で, "数字 + 数字*"という形式である. 2 番目の数字と"*"はそれぞれ省略可 + 能である.必須引数が一つもない場合は0を指定する.第3引数以 + 降は変数へのポインタで, 該当する要素がその変数に格納される. + 付加引数に対応する引数が与えられていない場合は変数にQnilが + 代入される. + +** Rubyメソッド呼び出し + +VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) + + メソッド呼び出し.文字列からmidを得るためにはrb_intern()を + 使う. + +VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) + + メソッド呼び出し.引数をargc, argv形式で渡す. + +VALUE rb_eval_string(const char *str) + + 文字列をRubyスクリプトとしてコンパイル・実行する. + +ID rb_intern(const char *name) + + 文字列に対応するIDを返す. + +char *rb_id2name(ID id) + + IDに対応する文字列を返す(デバッグ用). + +char *rb_class2name(VALUE klass) + + クラスの名前を返す(デバッグ用).クラスが名前を持たない時には, + 祖先を遡って名前を持つクラスの名前を返す. + +int rb_respond_to(VALUE obj, ID id) + + objがidで示されるメソッドを持つかどうかを返す。 + +** インスタンス変数 + +VALUE rb_iv_get(VALUE obj, const char *name) + + objのインスタンス変数の値を得る.`@'で始まらないインスタン + ス変数は Rubyプログラムからアクセスできない「隠れた」イン + スタンス変数になる.定数は大文字の名前を持つクラス(または + モジュール)のインスタンス変数として実装されている. + +VALUE rb_iv_set(VALUE obj, const char *name, VALUE val) + + objのインスタンス変数をvalにセットする. + +** 制御構造 + +VALUE rb_iterate(VALUE (*func1)(), VALUE arg1, VALUE (*func2)(), VALUE arg2) + + func2をブロックとして設定し, func1をイテレータとして呼ぶ. + func1には arg1が引数として渡され, func2には第1引数にイテレー + タから与えられた値, 第2引数にarg2が渡される. + +VALUE rb_yield(VALUE val) + + valを値としてイテレータブロックを呼び出す. + +VALUE rb_rescue(VALUE (*func1)(), VALUE arg1, VALUE (*func2)(), VALUE arg2) + + 関数func1をarg1を引数に呼び出す.func1の実行中に例外が発生 + した時には func2をarg2を引数として呼ぶ.戻り値は例外が発生 + しなかった時はfunc1の戻り値, 例外が発生した時にはfunc2の戻 + り値である. + +VALUE rb_ensure(VALUE (*func1)(), VALUE arg1, void (*func2)(), VALUE arg2) + + 関数func1をarg1を引数として実行し, 実行終了後(たとえ例外が + 発生しても) func2をarg2を引数として実行する.戻り値はfunc1 + の戻り値である(例外が発生した時は戻らない). + +** 例外・エラー + +void rb_warning(const char *fmt, ...) + + rb_verbose時に標準エラー出力に警告情報を表示する.引数は + printf()と同じ. + +void rb_raise(rb_eRuntimeError, const char *fmt, ...) + + RuntimeError例外を発生させる.引数はprintf()と同じ. + +void rb_raise(VALUE exception, const char *fmt, ...) + + exceptionで指定した例外を発生させる.fmt以下の引数は + printf()と同じ. + +void rb_fatal(const char *fmt, ...) + + 致命的例外を発生させる.通常の例外処理は行なわれず, インター + プリタが終了する(ただしensureで指定されたコードは終了前に + 実行される). + +void rb_bug(const char *fmt, ...) + + インタープリタなどプログラムのバグでしか発生するはずのない + 状況の時呼ぶ.インタープリタはコアダンプし直ちに終了する. + 例外処理は一切行なわれない. + +** Rubyの初期化・実行 + +Rubyをアプリケーションに埋め込む場合には以下のインタフェース +を使う.通常の拡張ライブラリには必要ない. + +void ruby_init() + + Rubyインタプリタの初期化を行なう. + +void ruby_options(int argc, char **argv) + + Rubyインタプリタのコマンドライン引数の処理を行なう. + +void ruby_run() + + Rubyインタプリタを実行する. + +void ruby_script(char *name) + + Rubyのスクリプト名($0)を設定する. + + +Appendix B. extconf.rbで使える関数たち + +extconf.rbの中では利用可能なコンパイル条件チェックの関数は以 +下の通りである. + +have_library(lib, func) + + 関数funcを定義しているライブラリlibの存在をチェックする. + ライブラリが存在する時,trueを返す. + +find_library(lib, func, path...) + + 関数funcを定義しているライブラリlibの存在を -Lpath を追加 + しながらチェックする.ライブラリが見付かった時,trueを返す. + +have_func(func, header) + + ヘッダファイルheaderをインクルードして関数funcの存在をチェッ + クする.funcが標準ではリンクされないライブラリ内のものであ + る時には先にhave_libraryでそのライブラリをチェックしておく + 事.関数が存在する時trueを返す. + +have_header(header) + + ヘッダファイルの存在をチェックする.ヘッダファイルが存在す + る時trueを返す. + +create_makefile(target) + + 拡張ライブラリ用のMakefileを生成する.この関数を呼ばなけれ + ばそのライブラリはコンパイルされない.targetはモジュール名 + を表す. + +with_config(withval[, default=nil]) + + コマンドライン上の--with-<withval>で指定されたオプション値を得る. + +dir_config(target[, default_dir]) +dir_config(target[, default_include, default_lib]) + + コマンドライン上の--with-<target>-dir, --with-<target>-include, + --with-<target>-libのいずれかで指定されるディレクトリを + $CFLAGS や $LDFLAGS に追加する.--with-<target>-dir=/pathは + --with-<target>-include=/path/include --with-<target>-lib=/path/lib + と等価である.追加された include ディレクトリと lib ディレクトリの + 配列を返す. ([include_dir, lib_dir]) + +/* + * Local variables: + * fill-column: 60 + * end: + */ diff --git a/README.ja b/README.ja new file mode 100644 index 0000000000..be89ce1935 --- /dev/null +++ b/README.ja @@ -0,0 +1,153 @@ +* Rubyとは + +Rubyはシンプルかつ強力なオブジェクト指向スクリプト言語です. +Rubyは最初から純粋なオブジェクト指向言語として設計されていま +すから,オブジェクト指向プログラミングを手軽に行う事が出来ま +す.もちろん通常の手続き型のプログラミングも可能です. + +Rubyはテキスト処理関係の能力などに優れ,Perlと同じくらい強力 +です.さらにシンプルな文法と,例外処理やイテレータなどの機構 +によって,より分かりやすいプログラミングが出来ます. + + +* Rubyの特長 + + + シンプルな文法 + + 普通のオブジェクト指向機能(クラス,メソッドコールなど) + + 特殊なオブジェクト指向機能(Mixin, 特異メソッドなど) + + 演算子オーバーロード + + 例外処理機能 + + イテレータとクロージャ + + ガーベージコレクタ + + ダイナミックローディング (アーキテクチャによる) + + 移植性が高い.多くのUNIX上で動くだけでなく,DOSやWindows, + Mac,BeOSなどの上でも動く + + +* 入手法 + +** ftpで + +以下の場所においてあります. + + ftp://ftp.ruby-lang.org/pub/ruby/ + +** CVSで + + $ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login + (Logging in to anonymous@cvs.ruby-lang.org) + CVS password: anonymous + $ cvs -z4 -d :pserver:anonymous@cvs.ruby-lang.org:src checkout ruby + + +* ホームページ + +RubyのホームページのURLは + + http://www.ruby-lang.org/ + +です. + + +* メーリングリスト + +Rubyのメーリングリストがあります。参加希望の方は + + ruby-list-ctl@ruby-lang.org + +まで本文に + + subscribe YourFirstName YourFamilyName + +と書いて送って下さい。 + +Ruby開発者向けメーリングリストもあります。こちらではrubyのバ +グ、将来の仕様拡張など実装上の問題について議論されています。 +参加希望の方は + + ruby-dev-ctl@ruby-lang.org + +までruby-listと同様の方法でメールしてください。 + +Ruby拡張モジュールについて話し合うruby-extメーリングリストと +数学関係の話題について話し合うruby-mathメーリングリストと +英語で話し合うruby-talkメーリングリストもあります。参加方法 +はどれも同じです。 + + +* コンパイル・インストール + +以下の手順で行ってください. + + 1. もしconfigureファイルが見つからない、もしくは + configure.inより古いようなら、autoconfを実行して + 新しくconfigureを生成する + + 2. configureを実行してMakefileなどを生成する + + 3. (必要ならば)defines.hを編集する + + 多分,必要無いと思います. + + 4. (必要ならば)ext/Setupに静的にリンクする拡張モジュールを + 指定する + + ext/Setupに記述したモジュールは静的にリンクされます. + + ダイナミックローディングをサポートしていないアーキテク + チャではSetupの1行目の「option nodynamic」という行のコ + メントを外す必要があります.また,このアーキテクチャで + 拡張モジュールを利用するためには,あらかじめ静的にリン + クしておく必要があります. + + 5. makeを実行してコンパイルする + + 6. make testでテストを行う. + + 「test succeeded」と表示されれば成功です.ただしテスト + に成功しても完璧だと保証されている訳ではありません. + + 7. make install + + rootで作業する必要があるかもしれません. + +もし,コンパイル時にエラーが発生した場合にはエラーのログとマ +シン,OSの種類を含むできるだけ詳しいレポートを作者に送ってく +ださると他の方のためにもなります. + + +* 移植 + +UNIXであればconfigureがほとんどの差異を吸収してくれるはずで +すが,思わぬ見落としがあった場合(あるに違いない),作者にその +ことをレポートすれば,解決できるかも知れません. + +アーキテクチャにもっとも依存するのはGC部です.RubyのGCは対象 +のアーキテクチャがsetjmp()によって全てのレジスタを jmp_bufに +格納することと,jmp_bufとスタックが32bitアラインメントされて +いることを仮定しています.特に前者が成立しない場合の対応は非 +常に困難でしょう.後者の解決は比較的簡単で,gc.cでスタックを +マークしている部分にアラインメントのバイト数だけずらしてマー +クするコードを追加するだけで済みます.「defined(THINK_C)」で +括られている部分を参考にしてください + +# 実際にはRubyはThink Cではコンパイルできません. + +レジスタウィンドウを持つCPUでは,レジスタウィンドウをスタッ +クにフラッシュするアセンブラコードを追加する必要があるかも知 +れません. + + +* 配布条件 + +COPYING.jaファイルを参照してください。 + + +* 著者 + +コメント,バグレポートその他は matz@zetabits.com まで. +------------------------------------------------------- +created at: Thu Aug 3 11:57:36 JST 1995 +Local variables: +mode: indented-text +end: diff --git a/doc/forwardable.rd.ja b/doc/forwardable.rd.ja new file mode 100644 index 0000000000..d928fddc5e --- /dev/null +++ b/doc/forwardable.rd.ja @@ -0,0 +1,81 @@ + -- forwatable.rb + $Release Version: 1.1 $ + $Revision$ + $Date$ + +=begin += Forwardable + +クラスに対しメソッドの委譲機能を定義します. + +== 使い方 + +クラスに対してextendして使います. + + class Foo + extend Forwardable + + def_delegators("@out", "printf", "print") + def_delegators(:@in, :gets) + def_delegator(:@contents, :[], "content_at") + end + f = Foo.new + f.printf ... + f.gets + f.content_at(1) + +== メソッド + +--- Forwardable#def_instance_delegators(accessor, *methods) + + ((|methods|))で渡されたメソッドのリストを((|accessorに|))委譲する + ようにします. + +--- Forwardable#def_instance_delegator(accessor, method, ali = method) + + ((||method|))で渡されたメソッドを((|accessor|))に委譲するようにし + ます. ((|ali|))が引数として渡されたときは, メソッド((|ali|))が呼ば + れたときには, ((|accessor|))に対し((|method|))を呼び出します. + +--- Forwardable#def_delegators(accessor, *methods) + + ((|Forwardable#def_instance_delegators|))の別名です. + +--- Forwardable#def_delegator(accessor, method, ali = method) + + ((|Forwardable#def_instance_delegator|))の別名です. + += SingleForwardable + +オブジェクトに対し, メソッドの委譲機能を定義します. + +== 使い方 + +オブジェクトに対して((|extend|))して使います. + + g = Goo.new + g.extend SingleForwardable + g.def_delegator("@out", :puts) + g.puts ... + +== メソッド + +--- SingleForwardable#def_singleton_delegators(accessor, *methods) + + ((|methods|))で渡されたメソッドのリストを((|accessor|))に委譲する + ようにします. + +--- SingleForwardable#def_singleton_delegator(accessor, method, ali = method) + + ((|method|))で渡されたメソッドを((|accessor|))に委譲するようにしま + す. ((|ali|))が引数として渡されたときは, メソッド((|ali|))が呼ばれ + たときには, ((|accessor|))に対し((|method|))を呼び出します. + +--- SingleForwardable#def_delegators(accessor, *methods) + + ((|SingleForwardable#def_singleton_delegators|))の別名です. + +--- SingleForwardable#def_delegator(accessor, method, ali = method) + + ((|SingleForwardable#def_singleton_delegator|))の別名です. +=end diff --git a/doc/irb/irb-tools.rd.ja b/doc/irb/irb-tools.rd.ja new file mode 100644 index 0000000000..64d9ab29c8 --- /dev/null +++ b/doc/irb/irb-tools.rd.ja @@ -0,0 +1,185 @@ +irb関連おまけコマンドとライブラリ + $Release Version: 0.7.1 $ + $Revision$ + $Date$ + by Keiju ISHITSUKA(Nihon Rational Co.,Ltd.) + +=begin + +:コマンド: +* rtags -- ruby tags command + +:関数ライブラリ: +* xmp -- irb version of gotoken xmp-function + +:クラスライブラリ: +* frame.rb -- frame tracer +* completion.rb -- irb completor + += rtags + +rtagsはemacs及びvi用の, TAGファイルをつくるコマンドです. + +== 使い方 + + rtags [-vi] file.... + +カレントディレクトリにemacs用のTAGSファイルができます. -viオプションを +つけた時にはvi用のtagsファイルを作成します. + +emacsの場合, 通常のetags.elがそのまま使えます. 検索可能なのは, + +* クラス +* メソッド +* 特異メソッド +* alias +* attrで宣言されたアクセサ(パラメータがシンボルか文字列リテラルに限る) +* attr_XXXで宣言されたアクセサ(パラメータがシンボルか文字列リテラルに限る) + +です. + +Cなどで使っているのと違うのは, コンプリーションに関する部分で, + +関数名は, + + 関数名( + +クラスは, + + ::クラス名::....::クラス名 + +メソッドは, + + ::クラス名::....::クラス名#メソッド名 + +特異メソッド(クラスメソッド)は + + ::クラス名::....::クラス名.メソッド名 + +でコンプリーションを行なうところです. + += xmp.rb + +ごとけんxmpの上位互換バージョンです. ただ, 非常に重いのでごとけんxmpで +は対応できない時に, 使用すると良いでしょう. + +== 使い方 + +=== 関数として使う. + + require "irb/xmp" + xmp <<END + foo = 1 + foo + END + --- + foo = 1 + ==>1 + foo + ==>1 + +=== XMPインスタンスを用いる. + +この場合は, XMPがコンテキスト情報を持つので, 変数の値などを保持してい +ます. + + require "irb/xmp" + xmp = XMP.new + xmp.puts <<END + foo = 1 + foo + END + xmp.puts <<END + foo + END + === + foo = 1 + ==>1 + foo + ==>1 + foo + ==>1 + +== コンテキストに関して + +XMPメソッド群のコンテキストは, 呼び出す前のコンテキストで評価されます. +明示的にコンテキストを指定するとそのコンテキストで評価します. + +例: + + xmp "foo", an_binding + +:注: +マルチスレッドには対応していません. + += frame.rb +現在実行中のフレーム情報を取り扱うためのクラスです. + +* IRB::Frame.top(n = 0) + 上からn番目のコンテキストを取り出します. nは0が最上位になります. +* IRB::Frame.bottom(n = 0) + 下からn番目のコンテキストを取り出します. nは0が最下位になります. +* IRB::Frame.sender + センダになっているオブジェクトを取り出します. センダとは, そのメソッ + ドを呼び出した側のselfのことです. + +:注: +set_trace_funcを用いてRubyの実行をトレースしています. マルチスレッドに +は対応していません. + += completion.rb +irbのcompletion機能を提供するものです. + +== 使い方 + + % irb -r irb/completion + +とするか, ~/.irbrc 中に + + require "irb/completion" + +を入れてください. irb実行中に require "irb/completion" してもよいです. + +irb実行中に (TAB) を押すとコンプレーションします. + +トップレベルで(TAB)を押すとすべての構文要素, クラス, メソッドの候補がで +ます. 候補が唯一ならば完全に補完します. + + irb(main):001:0> in + in inspect instance_eval + include install_alias_method instance_of? + initialize install_aliases instance_variables + irb(main):001:0> inspect + "main" + irb(main):002:0> foo = Object.new + #<Object:0x4027146c> + + ((|変数名.|))の後に(TAB)を押すと, そのオブジェクトのメソッド一覧がでま + す. + + irb(main):003:0> foo. + foo.== foo.frozen? foo.protected_methods + foo.=== foo.hash foo.public_methods + foo.=~ foo.id foo.respond_to? + foo.__id__ foo.inspect foo.send + foo.__send__ foo.instance_eval foo.singleton_methods + foo.class foo.instance_of? foo.taint + foo.clone foo.instance_variables foo.tainted? + foo.display foo.is_a? foo.to_a + foo.dup foo.kind_of? foo.to_s + foo.eql? foo.method foo.type + foo.equal? foo.methods foo.untaint + foo.extend foo.nil? + foo.freeze foo.private_methods + +=end + +% Begin Emacs Environment +% Local Variables: +% mode: text +% comment-column: 0 +% comment-start: "%" +% comment-end: "\n" +% End: +% + diff --git a/doc/irb/irb.rd.ja b/doc/irb/irb.rd.ja new file mode 100644 index 0000000000..5068f4536f --- /dev/null +++ b/doc/irb/irb.rd.ja @@ -0,0 +1,391 @@ +irb -- interactive ruby + $Release Version: 0.6 $ + $Revision$ + $Date$ + by Keiju ISHITSUKA(keiju@ishitsuka.com) +=begin += irbとは? + +irbはinteractive rubyの略です. rubyの式を標準入力から簡単に入力/実行す +るためのツールです. + += 起動 + + % ruby -r irb -e0 + % irb + +のいずれかで行ないます. 前者の場合irbへのオプション指定は, 以下のように +なります. + + % ruby -r irb -e0 -- -v + += 使い方 + +irbの使い方は, Rubyさえ知っていればいたって簡単です. 基本的には irb と +いうコマンドを実行するだけです. irbを実行すると, 以下のようなプロンプ +トが表れてきます. 後は, rubyの式を入れて下さい. 式が完結した時点で実行 +されます. + + dim% irb + irb(main):001:0> 1+2 + 3 + irb(main):002:0> class Foo + irb(main):003:1> def foo + irb(main):004:2> print 1 + irb(main):005:2> end + irb(main):006:1> end + nil + irb(main):007:0> + +また, irbはReadlineモジュールにも対応しています. Readlineモジュールが +インストールされている時には, それを使うのが標準の動作になります. + += コマンドオプション + + irb.rb [options] file_name opts + options: + -f ~/.irbrc を読み込まない. + -m bcモード(分数, 行列の計算ができる) + -d $DEBUG をtrueにする(ruby -d と同じ) + -r load-module ruby -r と同じ. + --inspect 結果出力にinspectを用いる(bcモード以外はデフォルト). + --noinspect 結果出力にinspectを用いない. + --readline readlineライブラリを利用する. + --noreadline readlineライブラリを利用しない. デフォルトの動作は, + inf-reuby-mode以外でreadlineライブラリを利用しよう + とする. + --prompt prompt-mode + --prompt-mode prompt-mode + プロンプトモードを切替えます. 現在定義されているプ + ロンプトモードは, default, simple, xmp, inf-rubyが + 用意されています. デフォルトはdefaultプロンプトモー + ドになっています. + + --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特 + に指定がない限り, readlineライブラリは使わなくなる. + --simple-prompt + 非常にシンプルなプロンプトを用いるモードです. + --noprompt プロンプト表示を行なわない. + --tracer コマンド実行時にトレースを行なう. + --back-trace-limit n + バックトレース表示をバックトレースの頭から n, 後ろ + からnだけ行なう. デフォルトは16 + --irb_debug n irbのデバッグデバッグレベルをnに設定する(利用しな + い方が無難でしょう). + -v, --version irbのバージョンを表示する + += コンフィギュレーション + +irb起動時に``~/.irbrc''を読み込みます. もし存在しない場合は, +``.irbrc'', ``irb.rc'', ``_irbrc'', ``$irbrc''の順にloadを試みます. + +オプションを設定する代わりに, 以下のコマンドでもデフォルトの動作を設定 +できます. + + IRB.conf[:IRB_NAME]="irb" + IRB.conf[:MATH_MODE]=false + IRB.conf[:USE_TRACER]=false + IRB.conf[:USE_LOADER]=false + IRB.conf[:IGNORE_SIGINT]=true + IRB.conf[:IGNORE_EOF]=false + IRB.conf[:INSPECT_MODE]=nil + IRB.conf[:IRB_RC] = nil + IRB.conf[:BACK_TRACE_LIMIT]=16 + IRB.conf[:USE_LOADER] = false + IRB.conf[:USE_READLINE] = nil + IRB.conf[:USE_TRACER] = false + IRB.conf[:IGNORE_SIGINT] = true + IRB.conf[:IGNORE_EOF] = false + IRB.conf[:PROMPT_MODE] = :DEFALUT + IRB.conf[:PROMPT] = {...} + IRB.conf[:DEBUG_LEVEL]=0 + IRB.conf[:VERBOSE]=true + +== プロンプトの設定 + +プロンプトをカスタマイズしたい時には, + + IRB.conf[:PROMPT] + +を用います. 例えば, .irbrcの中で下のような式を記述します: + + IRB.conf[:PROMPT][:MY_PROMPT] = { # プロンプトモードの名前 + :PROMPT_I => nil, # 通常のプロンプト + :PROMPT_S => nil, # 文字列などの継続行のプロンプト + :PROMPT_C => nil, # 式が継続している時のプロンプト + :RETURN => " ==>%s\n" # リターン時のプロンプト + } + +プロンプトモードを指定したい時には, + + irb --prompt my-prompt + +でそのプロンプトモードで起動されます. または, .irbrcに下式を記述しても +OKです. + + IRB.conf[:PROMPT_MODE] = :MY_PROMPT + +PROMPT_I, PROMPT_S, PROMPT_Cは, フォーマットを指定します. + + %N 起動しているコマンド名が出力される. + %m mainオブジェクト(self)がto_sで出力される. + %M mainオブジェクト(self)がinspectされて出力される. + %l 文字列中のタイプを表す(", ', /, ], `]'は%wの中の時) + %NNi インデントのレベルを表す. NNは数字が入りprintfの%NNdと同じ. 省 + 略可能 + %NNn 行番号を表します. + %% % + +例えば, デフォルトのプロンプトモードは: + + IRB.conf[:PROMPT_MODE][:DEFAULT] = { + :PROMPT_I => "%N(%m):%03n:%i> ", + :PROMPT_S => "%N(%m):%03n:%i%l ", + :PROMPT_C => "%N(%m):%03n:%i* ", + :RETURN => "%s\n" + } + +となっています. + +RETURNは, 現在のところprintf形式です. 将来仕様が変わるかも知れません. + +== サブirbの設定 + +コマンドラインオプションおよびIRB.confは(サブ)irb起動時のデフォルトの +設定を決めるもので, `5. コマンド'にあるconfで個別の(サブ)irbの設定がで +きるようになっています. + +IRB.conf[:IRB_RC]にprocが設定されていると, サブirbを起動する時にその +procをirbのコンテキストを引数として呼び出します. これによって個別のサ +ブirbごとに設定を変えることができるようになります. + + += コマンド + +irb拡張コマンドは, 簡単な名前と頭に`irb_'をつけた名前と両方定義されて +います. これは, 簡単な名前がoverrideされた時のためです. + +--- exit, quit, irb_exit + 終了する. + サブirbの場合, そのサブirbを終了する. + cbしている場合, そのバインディングのモードを終了する. + +--- conf, irb_context + irbの現在の設定を表示する. 設定の変更は, confにメッセージを送るこ + とによって行なえる. + +--- conf.back_trace_limit + バックトレース表示をバックトレースの頭からn, 後ろからnだけ行なう. + デフォルトは16 + +--- conf.debug_level = N + irb用のデバッグレベルの設定 + +--- conf.ignore_eof = true/false + ^Dが入力された時の動作を設定する. trueの時は^Dを無視する, falseの + 時はirbを終了する. + +--- conf.ignore_sigint= true/false + ^Cが入力された時の動作を設定する. false時は, irbを終了する. trueの + 時の動作は以下のようになる: + 入力中: これまで入力したものをキャンセルしトップレベルに戻る. + 実行中: 実行を中止する. + +--- conf.inf_ruby_mode = true/false + inf-ruby-mode用のプロンプト表示を行なう. デフォルトはfalse. + +--- conf.inspect_mode = true/false/nil + インスペクトモードを設定する. + true: インスペクトして表示する. + false: 通常のprintで表示する. + nil: 通常モードであれば, inspect modeとなり, mathモードの時は, non + inspect modeとなる. + +--- conf.irb_level + 参照のみ. irbが何段cbしているか? + +--- conf.math_mode + 参照のみ. bcモード(分数, 行列の計算ができます)かどうか? + +--- conf.use_loader = true/false + load/require時にirbのfile読み込み機能を用いるモードのスイッチ(デフォ + ルトは用いない). このモードはIRB全体に反映される. + +--- conf.prompt_c + ifの直後など, 行が継続している時のプロンプト. + +--- conf.prompt_i + 通常のプロンプト. + +--- conf.prompt_s + 文字列中などを表すプロンプト. + +--- conf.rc + ~/.irbrcを読み込んだかどうか? + +--- conf.use_prompt = true/false + プロンプト表示するかどうか? デフォルトではプロンプトを表示する. + +--- conf.use_readline = true/false/nil + readlineを使うかどうか? + true: readlineを使う. + false: readlineを使わない. + nil: (デフォルト)inf-reuby-mode以外でreadlineライブラリを利用しよ + うとする. + +--- conf.verbose=T/F + irbからいろいろなメッセージを出力するか? + +--- cb, irb_change_binding [obj] + ローカル変数のスコープが違う新たなbindingに移る. objが指定された + 時は, そのobjをselfとする. + +--- irb [obj] + サブirbを立ちあげる. objが指定された時は, そのobjをselfとする. + +--- jobs, irb_jobs + サブirbのリスト + +--- fg n, irb_fg n + 指定したサブirbにスイッチする. nは, 次のものを指定する. + + irb番号 + スレッド + irbオブジェクト + self(irb objで起動した時のobj) + +--- kill n, irb_kill n + サブirbをkillする. nはfgと同じ. + + += システム変数 + + _ 前の計算の実行結果を覚えている(ローカル変数). + += 使用例 + +以下のような感じです. + + dim% ruby irb.rb + irb(main):001:0> irb # サブirbの立ちあげ + irb#1(main):001:0> jobs # サブirbのリスト + #0->irb on main (#<Thread:0x400fb7e4> : stop) + #1->irb#1 on main (#<Thread:0x40125d64> : running) + nil + irb#1(main):002:0> fg 0 # jobのスイッチ + nil + irb(main):002:0> class Foo;end + nil + irb(main):003:0> irb Foo # Fooをコンテキストしてirb + # 立ちあげ + irb#2(Foo):001:0> def foo # Foo#fooの定義 + irb#2(Foo):002:1> print 1 + irb#2(Foo):003:1> end + nil + irb#2(Foo):004:0> fg 0 # jobをスイッチ + nil + irb(main):004:0> jobs # jobのリスト + #0->irb on main (#<Thread:0x400fb7e4> : running) + #1->irb#1 on main (#<Thread:0x40125d64> : stop) + #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop) + nil + irb(main):005:0> Foo.instance_methods # Foo#fooがちゃんと定義さ + # れている + ["foo"] + irb(main):006:0> fg 2 # jobをスイッチ + nil + irb#2(Foo):005:0> def bar # Foo#barを定義 + irb#2(Foo):006:1> print "bar" + irb#2(Foo):007:1> end + nil + irb#2(Foo):010:0> Foo.instance_methods + ["bar", "foo"] + irb#2(Foo):011:0> fg 0 + nil + irb(main):007:0> f = Foo.new + #<Foo:0x4010af3c> + irb(main):008:0> irb f # Fooのインスタンスでirbを + # 立ちあげる. + irb#3(#<Foo:0x4010af3c>):001:0> jobs + #0->irb on main (#<Thread:0x400fb7e4> : stop) + #1->irb#1 on main (#<Thread:0x40125d64> : stop) + #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop) + #3->irb#3 on #<Foo:0x4010af3c> (#<Thread:0x4010a1e0> : running) + nil + irb#3(#<Foo:0x4010af3c>):002:0> foo # f.fooの実行 + nil + irb#3(#<Foo:0x4010af3c>):003:0> bar # f.barの実行 + barnil + irb#3(#<Foo:0x4010af3c>):004:0> kill 1, 2, 3# jobのkill + nil + irb(main):009:0> jobs + #0->irb on main (#<Thread:0x400fb7e4> : running) + nil + irb(main):010:0> exit # 終了 + dim% + += 使用上の制限 + +irbは, 評価できる時点(式が閉じた時点)での逐次実行を行ないます. したがっ +て, rubyを直接使った時と, 若干異なる動作を行なう場合があります. + +現在明らかになっている問題点を説明します. + +== ローカル変数の宣言 + +rubyでは, 以下のプログラムはエラーになります. + + eval "foo = 0" + foo + -- + -:2: undefined local variable or method `foo' for #<Object:0x40283118> (NameError) + --- + NameError + +ところが, irbを用いると + + >> eval "foo = 0" + => 0 + >> foo + => 0 + +となり, エラーを起こしません. これは, rubyが最初にスクリプト全体をコン +パイルしてローカル変数を決定するからです. それに対し, irbは実行可能に +なる(式が閉じる)と自動的に評価しているからです. 上記の例では, + + evel "foo = 0" + +を行なった時点で評価を行ない, その時点で変数が定義されるため, 次式で +変数fooは定義されているからです. + +このようなrubyとirbの動作の違いを解決したい場合は, begin...endで括って +バッチ的に実行して下さい: + + >> begin + ?> eval "foo = 0" + >> foo + >> end + NameError: undefined local variable or method `foo' for #<Object:0x4013d0f0> + (irb):3 + (irb_local_binding):1:in `eval' + +== ヒアドキュメント + +現在のところヒアドキュメントの実装は不完全です. + +== シンボル + +シンボルであるかどうかの判断を間違えることがあります. 具体的には式が完了 +しているのに継続行と見なすことがあります. + +=end + +% Begin Emacs Environment +% Local Variables: +% mode: text +% comment-column: 0 +% comment-start: "%" +% comment-end: "\n" +% End: +% + diff --git a/doc/shell.rd.ja b/doc/shell.rd.ja new file mode 100644 index 0000000000..073e71ea42 --- /dev/null +++ b/doc/shell.rd.ja @@ -0,0 +1,336 @@ + -- shell.rb + $Release Version: 0.6.0 $ + $Revision$ + $Date$ + by Keiju ISHITSUKA(keiju@ishitsuka.com) + +=begin + += 目的 + +ruby上でsh/cshのようにコマンドの実行及びフィルタリングを手軽に行う. +sh/cshの制御文はrubyの機能を用いて実現する. + += 主なクラス一覧 + +== Shell + +Shellオブジェクトはカレントディレクトリを持ち, コマンド実行はそこからの +相対パスになります. + +--- Shell#cwd +--- Shell#dir +--- Shell#getwd +--- Shell#pwd + + カレントディレクトリを返す。 + +--- Shell#system_path + + コマンドサーチパスの配列を返す。 + +--- Shell#umask + + umaskを返す。 + +== Filter + +コマンドの実行結果はすべてFilterとしてかえります. Enumerableをincludeし +ています. + += 主なメソッド一覧 + +== コマンド定義 + +OS上のコマンドを実行するにはまず, Shellのメソッドとして定義します. + +注) コマンドを定義しなくとも直接実行できるShell#systemコマンドもあります. + +--- Shell.def_system_command(command, path = command) + + Shellのメソッドとしてcommandを登録します. + + 例) + Shell.def_system_command "ls" + ls を定義 + + Shell.def_system_command "sys_sort", "sort" + sortコマンドをsys_sortとして定義 + +--- Shell.undef_system_command(command) + + commandを削除します. + +--- Shell.alias_command(ali, command, *opts) {...} + + commandのaliasをします. + + 例) + Shell.alias_command "lsC", "ls", "-CBF", "--show-control-chars" + Shell.alias_command("lsC", "ls"){|*opts| ["-CBF", "--show-control-chars", *opts]} + +--- Shell.unalias_command(ali) + + commandのaliasを削除します. + +--- Shell.install_system_commands(pre = "sys_") + + system_path上にある全ての実行可能ファイルをShellに定義する. メソッ + ド名は元のファイル名の頭にpreをつけたものとなる. + +== 生成 + +--- Shell.new + + プロセスのカレントディレクトリをカレントディレクトリとするShellオ + ブジェクトを生成します. + +--- Shell.cd(path) + + pathをカレントディレクトリとするShellオブジェクトを生成します. + +== プロセス管理 + +--- Shell#jobs + + スケジューリングされているjobの一覧を返す. + +--- Shell#kill sig, job + + jobにシグナルsigを送る + +== カレントディレクトリ操作 + +--- Shell#cd(path, &block) +--- Shell#chdir + + カレントディレクトリをpathにする. イテレータとして呼ばれたときには + ブロック実行中のみカレントディレクトリを変更する. + +--- Shell#pushd(path = nil, &block) +--- Shell#pushdir + + カレントディレクトリをディレクトリスタックにつみ, カレントディレク + トリをpathにする. pathが省略されたときには, カレントディレクトリと + ディレクトリスタックのトップを交換する. イテレータとして呼ばれたと + きには, ブロック実行中のみpushdする. + +--- Shell#popd +--- Shell#popdir + + ディレクトリスタックからポップし, それをカレントディレクトリにする. + +== ファイル/ディレクトリ操作 + +--- Shell#foreach(path = nil, &block) + + pathがファイルなら, File#foreach + pathがディレクトリなら, Dir#foreach + +--- Shell#open(path, mode) + + pathがファイルなら, File#open + pathがディレクトリなら, Dir#open + +--- Shell#unlink(path) + + pathがファイルなら, File#unlink + pathがディレクトリなら, Dir#unlink + +--- Shell#test(command, file1, file2) +--- Shell#[command, file1, file2] + + ファイルテスト関数testと同じ. + 例) + sh[?e, "foo"] + sh[:e, "foo"] + sh["e", "foo"] + sh[:exists?, "foo"] + sh["exists?", "foo"] + +--- Shell#mkdir(*path) + + Dir.mkdirと同じ(複数可) + +--- Shell#rmdir(*path) + + Dir.rmdirと同じ(複数可) + +== コマンド実行 + +--- System#system(command, *opts) + + commandを実行する. + 例) + print sh.system("ls", "-l") + sh.system("ls", "-l") | sh.head > STDOUT + +--- System#rehash + + リハッシュする + +--- Shell#transact &block + + ブロック中ではshellをselfとして実行する. + 例) + sh.transact{system("ls", "-l") | head > STDOUT} + +--- Shell#out(dev = STDOUT, &block) + + transactを呼び出しその結果をdevに出力する. + +== 内部コマンド + +--- Shell#echo(*strings) +--- Shell#cat(*files) +--- Shell#glob(patten) +--- Shell#tee(file) + + これらは実行すると, それらを内容とするFilterオブジェクトを返します. + +--- Filter#each &block + + フィルタの一行ずつをblockに渡す. + +--- Filter#<(src) + + srcをフィルタの入力とする. srcが, 文字列ならばファイルを, IOであれ + ばそれをそのまま入力とする. + +--- Filter#>(to) + + srcをフィルタの出力とする. toが, 文字列ならばファイルに, IOであれ + ばそれをそのまま出力とする. + +--- Filter#>>(to) + + srcをフィルタに追加する. toが, 文字列ならばファイルに, IOであれば + それをそのまま出力とする. + +--- Filter#|(filter) + + パイプ結合 + +--- Filter#+(filter) + + filter1 + filter2 は filter1の出力の後, filter2の出力を行う. + +--- Filter#to_a +--- Filter#to_s + +== 組込みコマンド + +--- Shell#atime(file) +--- Shell#basename(file, *opt) +--- Shell#chmod(mode, *files) +--- Shell#chown(owner, group, *file) +--- Shell#ctime(file) +--- Shell#delete(*file) +--- Shell#dirname(file) +--- Shell#ftype(file) +--- Shell#join(*file) +--- Shell#link(file_from, file_to) +--- Shell#lstat(file) +--- Shell#mtime(file) +--- Shell#readlink(file) +--- Shell#rename(file_from, file_to) +--- Shell#split(file) +--- Shell#stat(file) +--- Shell#symlink(file_from, file_to) +--- Shell#truncate(file, length) +--- Shell#utime(atime, mtime, *file) + + これらはFileクラスにある同名のクラスメソッドと同じです. + +--- Shell#blockdev?(file) +--- Shell#chardev?(file) +--- Shell#directory?(file) +--- Shell#executable?(file) +--- Shell#executable_real?(file) +--- Shell#exist?(file)/Shell#exists?(file) +--- Shell#file?(file) +--- Shell#grpowned?(file) +--- Shell#owned?(file) +--- Shell#pipe?(file) +--- Shell#readable?(file) +--- Shell#readable_real?(file) +--- Shell#setgid?(file) +--- Shell#setuid?(file) +--- Shell#size(file)/Shell#size?(file) +--- Shell#socket?(file) +--- Shell#sticky?(file) +--- Shell#symlink?(file) +--- Shell#writable?(file) +--- Shell#writable_real?(file) +--- Shell#zero?(file) + + これらはFileTestクラスにある同名のクラスメソッドと同じです. + +--- Shell#syscopy(filename_from, filename_to) +--- Shell#copy(filename_from, filename_to) +--- Shell#move(filename_from, filename_to) +--- Shell#compare(filename_from, filename_to) +--- Shell#safe_unlink(*filenames) +--- Shell#makedirs(*filenames) +--- Shell#install(filename_from, filename_to, mode) + + これらはFileToolsクラスにある同名のクラスメソッドと同じです. + + その他, 以下のものがエイリアスされています. + +--- Shell#cmp <- Shell#compare +--- Shell#mv <- Shell#move +--- Shell#cp <- Shell#copy +--- Shell#rm_f <- Shell#safe_unlink +--- Shell#mkpath <- Shell#makedirs + += サンプル + +== ex1 + + sh = Shell.cd("/tmp") + sh.mkdir "shell-test-1" unless sh.exists?("shell-test-1") + sh.cd("shell-test-1") + for dir in ["dir1", "dir3", "dir5"] + if !sh.exists?(dir) + sh.mkdir dir + sh.cd(dir) do + f = sh.open("tmpFile", "w") + f.print "TEST\n" + f.close + end + print sh.pwd + end + end + +== ex2 + + sh = Shell.cd("/tmp") + sh.transact do + mkdir "shell-test-1" unless exists?("shell-test-1") + cd("shell-test-1") + for dir in ["dir1", "dir3", "dir5"] + if !exists?(dir) + mkdir dir + cd(dir) do + f = open("tmpFile", "w") + f.print "TEST\n" + f.close + end + print pwd + end + end + end + +== ex3 + + sh.cat("/etc/printcap") | sh.tee("tee1") > "tee2" + (sh.cat < "/etc/printcap") | sh.tee("tee11") > "tee12" + sh.cat("/etc/printcap") | sh.tee("tee1") >> "tee2" + (sh.cat < "/etc/printcap") | sh.tee("tee11") >> "tee12" + +== ex4 + + print sh.cat("/etc/passwd").head.collect{|l| l =~ /keiju/} + +=end diff --git a/ext/digest/MANIFEST b/ext/digest/MANIFEST new file mode 100644 index 0000000000..bf7cfefce3 --- /dev/null +++ b/ext/digest/MANIFEST @@ -0,0 +1,11 @@ +MANIFEST +defs.h +digest.c +digest.h +digest.txt +digest.txt.ja +extconf.rb +lib/md5.rb +lib/sha1.rb +test.rb +test.sh diff --git a/ext/digest/digest.txt.ja b/ext/digest/digest.txt.ja new file mode 100644 index 0000000000..8997d25b9d --- /dev/null +++ b/ext/digest/digest.txt.ja @@ -0,0 +1,111 @@ +.\" digest.txt.ja - -*- Indented-Text -*- created at: Fri May 25 08:22:19 JST 2001 +$RoughId: digest.txt.jp,v 1.8 2001/07/13 15:38:27 knu Exp $ +$Id$ + +** MD5(クラス) + +RFC1321に記述されているRSA Data Security, Inc. の MD5 Message-Digest +Algorithmを実装するクラス。 + +Superclass: Digest::Base + +require 'digest/md5' + +** SHA1(クラス) + +FIPS PUB 180-1に記述されているNIST (the US' National Institute of +Standards and Technology) の SHA-1 Secure Hash Algorithmを実装するクラス。 + +Superclass: Digest::Base + +require 'digest/sha1' + +** SHA256(クラス) +** SHA384(クラス) +** SHA512(クラス) + +FIPS PUB 180-2に記述されているNIST (the US' National Institute of +Standards and Technology) の SHA-256/384/512 Secure Hash Algorithmを +実装するクラス。 + +Superclass: Digest::Base + +require 'digest/sha2' + +** RMD160(クラス) + +Hans Dobbertin, Antoon Bosselaers, Bart Preneel によって設計された +RIPEMD-160 ハッシュ関数を実装するクラス。 + +Superclass: Digest::Base + +require 'digest/rmd160' + + +これらのクラスは以下のような共通のインターフェースを提供する。 + + +Class Methods: + + new([str]) + + 新しいダイジェストオブジェクトを生成する.文字列引数が与えられる + とそれを追加する(see update)。 + + digest(str) + + 与えられた文字列に対するハッシュ値を文字列で返す。 + new(str).digest と等価。 + + hexdigest(str) + + 与えられた文字列に対するハッシュ値を、ASCIIコードを使って + 16進数の列を示す文字列にエンコードして返す。 + new(str).hexdigest と等価。 + +Methods: + + clone + + ダイジェストオブジェクトの複製を作る。 + + digest + + 今までに追加した文字列に対するハッシュ値を文字列で返す。MD5では + 16バイト長、SHA1およびRMD160では20バイト長、SHA256では32バイト長、 + SHA384では48バイト長、SHA512では64バイト長となる。 + + hexdigest + to_s + + 今までに追加した文字列に対するハッシュ値を、ASCIIコードを使って + 16進数の列を示す文字列にエンコードして返す。MD5では32バイト長、 + SHA1およびRMD160では40バイト長、SHA256では64バイト長、SHA384では + 96バイト長、SHA512では128バイト長となる。Rubyで書くと以下と同じ。 + + def hexdigest + digest.unpack("H*")[0] + end + + update(str) + << str + + 文字列を追加する。複数回updateを呼ぶことは文字列を連結して + updateを呼ぶことと等しい。すなわち m.update(a); m.update(b) は + m.update(a + b) と、 m << a << b は m << a + b とそれぞれ等価 + である。 + + == md + + 与えられたダイジェストオブジェクトと比較する。 + + == str + + 与えられた文字列を digest 値、もしくは hexdigest 値と比較する。 + いずれの値と見るかは与えられた文字列の長さによって自動判別 + される。 + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/etc/etc.txt.ja b/ext/etc/etc.txt.ja new file mode 100644 index 0000000000..2dddcfb036 --- /dev/null +++ b/ext/etc/etc.txt.ja @@ -0,0 +1,72 @@ +.\" etc.txt.ja - -*- Indented-Text -*- created at: Fri Jul 14 00:47:15 JST 1995 + +** Etc(モジュール) + +/etcディレクトリ以下の情報を得るためのモジュール.クラスにインクルード +して使うこともできる. + +Module Function: + + getlogin + + 自分のlogin名を返す.これが失敗した場合はgetpwuid()を用いると + 良い. + + getpwnam(name) + + /etc/passwdファイル(あるいはDBMファイルやNISデータベース)を検 + 索し,nameの名前を持つpasswdエントリを返す.戻り値はpasswd構造 + 体で以下のメンバを持つ. + + struct passwd + name # ユーザ名(文字列) + passwd # パスワード(文字列) + uid # ユーザID(整数) + gid # グループID(整数) + gecos # gecosフィールド(文字列) + dir # ホームディレクトリ(文字列) + shell # ログインシェル(文字列) + # 以降のメンバはシステムによっては提供されない. + change # パスワード変更時間(整数) + quota # クォータ(整数) + age # エージ(整数) + class # ユーザアクセスクラス(文字列) + comment # コメント(文字列) + expire # アカウント有効期限(整数) + end + + 詳細はgetpwnam(3)を参照のこと. + + getpwuid([uid]) + + uidをユーザIDとするpasswdエントリを返す.戻り値はgetpwnam()と + 同様である.引数を省略した場合にはgetuid()の値を用いる.詳細は + getpwuid(3)を参照のこと. + + getgrgid(gid) + + /etc/groupファイル(あるいは…getpwnam参照)を検索し,gidをグルー + プIDとするグループエントリを返す.戻り値はgroup構造体で以下の + メンバを持つ. + + struct group + name # グループ名(文字列) + passwd # グループのパスワード(文字列) + gid # グループID(整数) + mem # グループメンバ名の配列 + end + + 詳細はgetgrgid(3)を参照のこと. + + getgrnam(name) + + nameという名前のグループエントリを返す.戻り値はgetgrgid()と同 + 様である.詳細はgetgrnam(3)を参照. + + group + + 全てのグループエントリを順にアクセスするためのイテレータ. + + passwd + + 全てのpasswdエントリを順にアクセスするためのイテレータ. diff --git a/ext/pty/README.expect.ja b/ext/pty/README.expect.ja new file mode 100644 index 0000000000..db84695ee5 --- /dev/null +++ b/ext/pty/README.expect.ja @@ -0,0 +1,21 @@ + README for expect + by A. Ito, 28 October, 1998 + + Expectライブラリは,tcl の expect パッケージと似たような機能を +IOクラスに追加します. + + 追加されるメソッドの使い方は次の通りです. + + IO#expect(pattern,timeout=9999999) + +pattern は String か Regexp のインスタンス,timeout は Fixnum +のインスタンスです.timeout は省略できます. + このメソッドがブロックなしで呼ばれた場合,まずレシーバである +IOオブジェクトから pattern にマッチするパターンが読みこまれる +まで待ちます.パターンが得られたら,そのパターンに関する配列を +返します.配列の最初の要素は,pattern にマッチするまでに読みこ +まれた内容の文字列です.2番目以降の要素は,pattern の正規表現 +の中にアンカーがあった場合に,そのアンカーにマッチする部分です. +もしタイムアウトが起きた場合は,このメソッドはnilを返します. + このメソッドがブロック付きで呼ばれた場合には,マッチした要素の +配列がブロック引数として渡され,ブロックが評価されます. diff --git a/ext/pty/README.ja b/ext/pty/README.ja new file mode 100644 index 0000000000..5ae4fb06a0 --- /dev/null +++ b/ext/pty/README.ja @@ -0,0 +1,89 @@ +pty 拡張モジュール version 0.3 by A.ito + +1. はじめに + +この拡張モジュールは,仮想tty (pty) を通して適当なコマンドを +実行する機能を ruby に提供します. + +2. インストール + +次のようにしてインストールしてください. + +(1) ruby extconf.rb + + を実行すると Makefile が生成されます. + +(2) make; make install を実行してください. + +3. 何ができるか + +この拡張モジュールは,PTY というモジュールを定義します.その中 +には,次のようなモジュール関数が含まれています. + + getpty(command) + spawn(command) + + この関数は,仮想ttyを確保し,指定されたコマンドをその仮想tty + の向こうで実行し,配列を返します.戻り値は3つの要素からなる + 配列です.最初の要素は仮想ttyから読み出すためのIOオブジェクト, + 2番目は書きこむためのIOオブジェクト,3番目は子プロセスのプロ + セスIDです.この関数がイテレータとして呼ばれた場合,これらの + 要素はブロックパラメータとして渡され,関数自体はnilを返します. + + この関数によって作られたサブプロセスが動いている間,子プロセス + の状態を監視するために SIGCHLD シグナルを捕捉します.子プロセス + が終了したり停止した場合には,例外が発生します.この間,すべての + SIGCHLD が PTY モジュールのシグナルハンドラに捕捉されるので, + サブプロセスを生成する他の関数(system() とか IO.popen()など)を + 使うと,予期しない例外が発生することがあります.これを防ぐため + には,下記のprotect_signal()を参照してください. + + この関数がブロックパラメータ付きで呼ばれた場合には,そのブロック + の中でのみ SIGCHLD が捕捉されます.したがって,ブロックパラメータ + として渡されたIOオブジェクトを,ブロックの外に持ち出して使うの + は勧められません. + + + protect_signal + + この関数はイテレータです.ここで指定されたブロックの中では, + 子プロセスが終了しても例外を発生しません.この関数を使うことで, + PTYの子プロセスが動いている間でも,system()や IO.popen()などの + 関数を安全に使うことができます.例えば, + + PTY.spawn("command_foo") do |r,w| + ... + ... + PTY.protect_signal do + system "some other commands" + end + ... + end + + このような記述により,"some other commands" が終了したときに + 例外が発生するのを防げます. + + reset_signal + + PTY の子プロセスが動いていても,そのプロセスの終了時に例外が発生 + しないようにします. + +4. 利用について + +伊藤彰則が著作権を保有します. + +ソースプログラムまたはドキュメントに元の著作権表示が改変されずに +表示されている場合に限り,誰でも,このソフトウェアを無償かつ著作 +権者に無断で利用・配布・改変できます.利用目的は限定されていませ +ん. + +このプログラムの利用・配布その他このプログラムに関係する行為によ +って生じたいかなる損害に対しても,作者は一切責任を負いません. + +5. バグ報告等 + +バグレポートは歓迎します. + + aito@ei5sun.yz.yamagata-u.ac.jp + +まで電子メールでバグレポートをお送りください. diff --git a/ext/readline/README.ja b/ext/readline/README.ja new file mode 100644 index 0000000000..beb951fbf0 --- /dev/null +++ b/ext/readline/README.ja @@ -0,0 +1,63 @@ +GNU Readline Libraryを利用するための拡張モジュールです。 + +require "readline" +include Readline + +line = readline("Prompt> ", true) + +のように使用してください。 + +[Readline] + +<モジュール関数> + +readline(prompt, add_history=nil) + + 一行入力を読み込みます。 + add_historyがtrueの場合、ヒストリに読み込んだ文字列を追加します。 + +<クラスメソッド> + +completion_proc = proc + + 補完時の動作を決定するProcオブジェクトを指定します。 + procは引数に入力文字列を取り、候補文字列の配列を返すように + してください。 + +completion_proc + + 補完時の動作を決定するProcオブジェクトを返します。 + +completion_case_fold = case_fold + + 補完時に大文字小文字を区別しない場合、trueを指定します。 + +completion_case_fold + + 補完時に大文字小文字を区別しない場合、trueを返します。 + +completion_append_character = char + + 補完時に付加される文字を文字列で指定します。先頭の一文字が + 設定され、空文字列 ("") または nil を指定すると何も付加 + されなくなります。 + +completion_append_character + + 補完時に付加される文字を文字列で返します。デフォルトは + 空白 (" ") です。 + +vi_editing_mode + + VIモードになります。 + +emacs_editing_mode + + Emacsモードになります。 + +<クラス定数> + +HISTORY + +ヒストリに対する操作はこの定数を通して行ってください。 +配列と同じように扱えるようになっています。 |