diff options
author | Yukihiro Matsumoto <matz@ruby-lang.org> | 1995-12-21 00:56:57 +0900 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2019-08-17 22:09:32 +0900 |
commit | fca49a8a69a0f6bb4feae74c6cd0e93d7fac8b36 (patch) | |
tree | 590a6d2ffcfa31212c1595e34a01d9cda56ba308 | |
parent | 8bf1c909dc31fd4bcdc1488cda9fe89a62bc2830 (diff) |
version 0.95v0_95
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.95.tar.gz
Thu Dec 21 00:56:57 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.95 - fj.sourcesに
* eval.c (rb_eval): rescueのロジックをrb_rescue()に一元化.
Wed Dec 20 19:30:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* Makefile.in: 不要なコンパイルの回避(より完全に).
* class.c (singleton_class_new): `single'->`singleton'
Tue Dec 19 07:14:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* io.c (closed?): IOがcloseされているかどうかを知る述語.
* parse.y (primary): 特異メソッドの引数のlex_stateが不適切.
* lib/tk.rb: tcl->rubyの変換関数の用意.
* ext/extmk.rb.in (install): installの2重コンパイルの回避.
* array.c (range_beg_len): range指定の不適切なエラーを訂正.
* string.c (str_aref): range指定のバグを削除.
* lib/tk.rb (tk_split_list): Tclのリストに対応.
Mon Dec 18 09:58:12 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.94
* dln.c (dln_load): HP対応(未確認)
* eval.c (Init_Proc): BlockをProcに改名.
Sat Dec 16 13:46:14 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c (rb_eval): retryでイテレータの再実行ができるように.
Fri Dec 15 17:14:30 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c: proc:lambdaの親しみやすい別名
Thu Dec 14 17:21:55 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c (dyna_var_asgn): イテレータブロック内で最初に初期化された
ローカル変数の有効範囲をそのブロック内に限定.これでlambdaと呼べ
ないことはない.
Wed Dec 13 02:30:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* gc.c: autoloadのマークミス.
* lib/tk.rb: wishからの複数行の戻り値に対応
* lib/tkcomposite.rb: 複合widget
* variable.c (rb_class2path): ICLASSに対応してなかった.
* eval.c (ruby_run): exit(0)のバグ
Sat Dec 9 01:21:24 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* ext/marshal/marshal.c (dumps|load): 文字列に対する入出力を可能に
した(ただし実はファイル経由なのだ).
Fri Dec 8 18:29:11 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* ext/marshal/marshal.c: シンボルを一度だけ初期化する.
Thu Dec 7 07:58:50 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* parse.y (yylex): 第1引数の正規表現の認識にエラーがあった.同時に
状態数を減らした.
* string.c (str_sub): 置換でスキップ幅が大きすぎた.
Wed Dec 6 15:14:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* string.c (str_sub_method): sub/gsub(!なし)は置換が行なわれなかっ
た時,置換前の文字列を返す.
Tue Dec 5 00:55:15 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* parse.y (yylex): 括弧を省略した時の引数展開の`*'に対応.
* eval.c (ruby_run): EXITハンドラ内での例外に対応.
* bignum.c (big_cmp): BignumとFixnumの比較で落ちる.
Mon Dec 4 14:21:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* parse.y (call_op): コンパイル時の定数式の展開をやめた.労多くし
て益少ないと判断したので.
Thu Nov 30 01:35:15 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* lib/tk.rb: {Radio,Check}Buttonのvariableの実装.
* eval.c (rb_yield_0): Block.callがネストした時のバグ.
* io.c (f_select): 常に配列3つをふくむ配列を返すように
* lib/tk.rb: fileeventをruby側で実装.
Wed Nov 29 17:53:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* variable.c (rb_ivar_get): selfを常に指定するように.
Tue Nov 14 00:07:29 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* lib/tk.rb: Tk4.0対応
Mon Nov 13 16:23:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.93
Thu Nov 9 23:26:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* gc.c (gc_mark): モジュールのMixinのマーク忘れ.
* parse.y (f_arglist): メソッド定義の引数を括弧で括らなくても良い
ようにした.
Wed Nov 8 00:17:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c (rb_yield_0): 未初期化のローカル変数があった.
* eval.c (rb_eval): pendig signalのチェックをeval実行後に行うよう
にした.でないとシグナルの発生と検出が遠く離れてしまう事がある.
* parse.y: class文のsuperclass部を定数から式に拡張した.
* lib/tk.rb: Tkのほぼ全ウィンドウクラスに対応.キャンバスとテキス
ト上のオブジェクトが残っている.
Tue Nov 7 08:18:37 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* signal.c (trap): ブロックを指定できるように.
Mon Nov 6 16:44:00 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c (f_caller): 呼出元の情報を得る.
* ext/tkutil/tkutil.c: wishのstderr出力を監視することで,エラー処
理を行う.
* ext/tkutil/tkutil.c: wishとの通信部をCで記述.
Sat Nov 4 01:12:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* sample/ruby-mode.el (ruby-calculate-indent): インデントの計算を
もう少しスマートにした(正規表現のチェック,継続行のチェック).
* eval.c (rb_call): 無限再帰を避けるため,関数のネストレベルの制限
を行なう.
* lib/tk.rb: Tkインターフェース.まだ不完全だが.
* eval.c (rb_yield_0): 空のBlockのバグ.
* sample/ruby-mode.el (ruby-calculate-indent): 行末の演算子による
行継続に対応.
Fri Nov 3 12:56:21 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c (rb_call): 本体が空の関数の実行にバグ.
* parse.y (var_extend): 文字列の末尾の変数展開のバグ.
* variable.c (rb_gvar_set): traceの評価時にに変数値を与えるように.
* eval.c (f_require): ruby scriptのrequireにbug.
* variable.c (rb_const_get): モジュールのinclude対策.
Thu Oct 19 13:56:06 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* dln.c (dln_load): HP対応でのtypo.
Wed Oct 18 17:39:39 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.92
* object.c (krn_type): オブジェクトの動的な型を返すメソッド.
Tue Oct 17 00:48:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* ruby.c (proc_options): -X オプション.chdirだけを行う.
* re.c (reg_search): 漢字コードを途中で変更できるように.コンパイ
ル時のコードが変更された時にはマッチの直前に正規表現の再コンパイ
ルを行う.定数KCODEから変数$KCODEへ.
* parse.y: ()のなかにcompexprを許す.
* re.c (reg_search): メモリリークを直した.
Fri Oct 13 13:19:19 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* string.c (str_sub): 文字列置換にバグ.
* string.c (str_strip_bang): 文字列の後ろの長さの調整が行われてい
なかった.
* re.c (reg_search): $&, $1...のはローカルに束縛するようになった.
呼び出したメソッドでのマッチは現スコープの$&などの値に影響しない.
マッチの情報をスコープ外で得たいときには$~を使って束縛情報を持ち
出す必要がある.
Thu Oct 12 00:33:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* re.c (reg_search): String:split, String:indexでは$&, $1...が変化
しないようにした.
* io.c (rb_str_setter): setterの仕様が変更になっていた.
* variable.c (f_trace_var): 第2引数を省略してイテレータとして呼べ
るように.
Wed Oct 11 11:50:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.91
* variable.c (var_setter): 引数が間違っていた.致命的バグ.
* io.c (pipe_open): $stderrの値が変更されている時にはそちらを
子プロセスのstderrに設定する.
Mon Oct 9 13:06:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* object.c (mod_to_s): モジュール内のモジュールは`::'を使った表現
で表示されるように.
* variable.c (rb_gvar_set): 代入によるループが発生しないように,
trace内での代入ではtraceを評価しない.
* struct.c (struct_equal): structのequal判定にクラスの一致を含めた.
Sat Oct 7 00:18:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c (rb_eval): defined?の機能を拡張(yieldのチェック,superの
存在など).
Fri Oct 6 12:06:47 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.90
* st.c (st_foreach): 要素を削除した時に要素数が変化していなかった.
* hash.c (hash_values): バグ修正.keysを返していた….
* parse.y (call_op): defined? の引数では定数の畳み込みを行わない
(チェックする前にコンパイルエラーになっては困る).
* スコープ生成の一部見直し.
Thu Oct 5 00:29:43 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* 関数とクラスの命名規則を変更した.関数名,変数名の全面書き換え.
* gc.c (looks_pointerp): ヒープチェックの高速化.
* struct.c (Fstruct_aset): 構造体に対する`[]='.
(struct_set): 構造体メンバに対する代入.
Wed Oct 4 09:54:07 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.89
* eval.c (Frequire): ダイナミックロードのエラーチェックを厳しく.
* struct.c: structの構造を完全に書き換えた.以前は順序付きの
id->valueの連想配列であったが,今度は構造体毎に新しいクラスを生
成するようにした.
* parse.y: `::'の意味をAssocの生成からクラス(モジュール)内の定数ア
クセスへ変更.
* assoc.c: なくす.
Tue Oct 3 13:31:08 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* variable.c (Ftrace_var): trace_var, 大域変数への書き込みhookを設
定する.
* variable.c: global_entryの構成を書き換えた.これでtrace_varを実
装できる.
* file.c (Ffile_stat): "&"で直前のfstatの結果も参照できるように.
Fri Sep 29 14:15:13 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.88
* dln.c (dln_load): AIXとHPに対応したコードを入れた(動作は未確認).
* ext/extmk.rb.in: 必要に応じて,定数EXTLIBを定義するように.
* dln.c (dln_load): dln独立に書き換える.将来の拡張用.
(load_1): dln_a_outにおいてソースコードでライブラリを明示的にロー
ドする必要がないように変更した.
Thu Sep 28 13:31:37 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* sample/ruby-mode.el: もっとましなhilit19対応(正規表現).
Wed Sep 27 04:12:44 1995 Takahasi Mamoru <taka@soum.co.jp>
* sample/test.rb: echoで-nを使わないように(SysV対策).
* ext/extmk.rb.in: sub -> sub!
Tue Sep 26 19:12:42 1995 Yasuo OHBA <jammy@csg.mes.co.jp>
* dln.c (dln_find_1): `.', `..'から始まるパスに対応した.
Mon Sep 25 12:33:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.87
Sat Sep 23 10:00:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c (Fmod_modfunc): メソッドをprivateにし,同時に特異メソッド
も定義するメソッド.パッケージ的使い方のモジュール用.
Fri Sep 22 11:02:44 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* lib/find.rb: findを提供するライブラリ
* variable.c (rb_define_variable): hookの設定を分離.
(add_hook): 1変数に対して複数のhookを設定できるように.
Thu Sep 21 00:22:11 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* string.c (Fstr_frozen): 文字列が更新不可かどうかをチェックする述
語メソッド.
* hash.c (Fhash_aset): keyが文字列の時,キーの内容が変化しないよう
に,dupしてfreezeする.
Wed Sep 20 16:12:44 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.86
* ext/extmk.rb.in (have_header): キャッシュにバグ.
* ext/extmk.rb.in (have_library): 引数の順序が変わった.
Thu Sep 14 18:00:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* object.c (obj_is_instance_of): is_member_ofから名称変更.
Wed Sep 13 15:44:35 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* string.c (Fstr_tr_bang): 範囲外の文字に対する変換バグ.
Tue Sep 12 14:27:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* file.c (Sfile_expand_path): expand_file_name -> expand_pathに名
称変更.
* enum.c (Fenum_member): includes? -> member? に名称変更.
* string.c (Fstr_each_byte): StringはByteArrayであるという基本に戻っ
て,eachの定義をeach_byteに変更した.今までのeachはeach_lineでア
クセスできる.
Mon Sep 11 18:31:17 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* file.c (cache_stat): ファイル名として"&"を指定すると直前の
stat(2)の結果を再利用するように.
Fri Sep 8 14:18:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* ruby.texi: `!', `?'に対応してアップデート.
* parse.y: defined -> defined?
* file.c: FileOpの一文字メソッドをなくす.一文字テストはtestメソッ
ドにまかせる.
* parse.y (yylex): 変数名の後ろに`?'も許す.述語メソッドの後ろに
`?'を追加する.
Thu Sep 7 20:01:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* string.c: 文字列の中身を更新するメソッドの名前の終りに`!'を付加.
`!'の無いバージョンも用意した.
* parse.y: 変数名の後ろに`!'を許す.
Wed Sep 6 14:12:19 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.85
* string.c (Fstr_dup): 文字列の複製を作る
(Fstr_freeze): 文字列の更新不可属性を設定できるように.
(Fsub/Fgsub): $_の内容をdupしてから置換を行うように.
* ruby.h (CLONESETUP): flagsの状態もコピー
Tue Sep 5 01:27:50 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* sample/test.rb: 失敗の検出を厳しく.
Fri Aug 25 14:31:02 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* process.c (Ffork): イテレータとしても動作するように.
* version 0.84
* signal.c (sig_beg): ハンドラが設定されている時には再設定しない.
* ext/extmk.rb.in (create_makefile): shared objectのリンクの際に
`-l'オプションを指定するように.
* signal.c (trap): `EXIT'で終了処理を行う設定が出来る.
Wed Aug 16 00:13:22 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* signal.c (sig_beg): デフォルトではbegin節の中でだけSIGINTを捕捉
するように変更.
* io.c (io_ctl): fcntlを持たないシステムにも対応.
* 各ディレクトリに分散していたMANIFESTをまとめた.拡張モジュール毎
には必要.
* string.c (Sstr_new,str_sub,Fstr_crypt): 引数を自動的に文字列に変
換するように.
Sat Aug 12 00:44:02 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* string.c (Fstr_crypt): PD cryptを用意した.
Fri Aug 11 14:37:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* assoc.c (Fassoc_clone): assocもcloneできるように.
* io.c: マクロREAD_DATA_PENDINGの定義を変更(Linux対応)
* io.c (io_fptr_finalize): ftprの開放時の処理を指定できるように.
Wed Aug 9 16:52:41 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* eval.c (rb_provided): 複数のfeatureをロードすると無限ループに落
ちるという単純な(しかし凶悪な)ミス.
* ext/extmk.rb.in (install): dlopen対応を行った.今までdlnにしか十
分に対応していなかった.
Tue Aug 8 14:17:06 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.83
Mon Aug 7 12:47:41 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* parse.y: resque -> rescue.恥ずかしいがtypoを残しておくわけには
いかないよなあ.なんで今まで気がつかなかったのか….
Thu Aug 3 18:18:05 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* missing/nt.c: NT移植用の関数群をまとめた.
* variable.c (rb_const_get): また例外を発生するようにした.defined
がある以上例外を発生させない理由がないので(例外が発生した方がタ
イプミスの検出などの点で有利).
* variable.c (Fautoload): autoloadを実装.今度は使えるか.
Mon Jul 31 15:44:21 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* parse.y (arg_ambiguous): 第1引数のあいまいさを警告(-vオプション
で有効).
* eval.c (rb_eval): `-v'オプションをつけて`def'が呼ばれると不必要
なエラーメッセージが出た.
* parse.y (yylex): メソッドの第1引数の判定をもうちょっと賢くした.
Fri Jul 28 19:04:43 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* parse.y (yylex): `+/-/['の直前に空白が来るかどうかで動作を変更し
た(混乱のもとか?)
Wed Jul 26 09:21:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.82a
* sprintf.c (Fsprintf): `%s'で'\0'を含む文字列に対応.
* pack.c (Fpck_pack): packの要素確保のバグ.
* eval.c (Floop): 無限ループのイテレータ.
* io.c (next_argv): 存在しないファイル名が指定された時のエラー処理
が行われていなかった.
Mon Jul 24 17:37:34 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.82
* ext/extmk.rb.in (install): 拡張モジュールをstatic linkする場合は
そのモジュールが既にrequireされたのと同じようにfeatureを設定する.
これで拡張モジュールの機能が必要な時には(static linkされているか
どうかにかかわらず)requireすればよくなる.
* eval.c (Frequire): `$"'に格納する文字列をフルパスでなくフィーチャ
名とする.rubyスクリプトをロードした時には`.rb',オブジェクトを
ロードした時には`.o'をフィーチャ名に付加する.lispのrequireと
provideの働きに(少し)近い.
Thu Jul 20 12:50:05 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* Makefile.in (test): make testができるように.
* struct.c (struct_new): typo.
* eval.c (rb_eval): `defined'を追加.メソッド/変数/定数の定義状態
を知る事が出来る.
Wed Jul 19 18:04:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.81
Mon Jul 17 14:53:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* variable.c (rb_const_get): 未初期化のCONSTANTの値をnilにした.し
かし,今後また例外に戻す可能性はある.要はoptionalなクラス/モジュー
ルが存在するかチェックしたいだけなんだな.
* st.c (int): grow_factorを固定にした(大嶋さんのマシンに対応).
Fri Jul 14 00:48:40 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* ext/extmk.rb.in: キャッシュのバグを修正.
* parse.y (var_extend): #{$数字}に対応した.
* dln.c (dln_load_1): `Init_FILENAME'だけを有効に.`init_*'は今後
実行しない.
* ext/etc/etc.c : Etcモジュールを拡張モジュールとして分離.実はNT
対応への布石だったりするかもしれない.
Tue Jul 11 17:12:48 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* gcc -Wallで出たwarningを元にソースを変更.
* signal.c (trap): typo.
Fri Jul 7 10:08:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.80
* ruby.texi: texinfo documentを提供.specとruby.1は無くなった.
* signal.c (Ftrap): 割込み禁止中の例外発生に対応.
* eval.c (Flambda): Blockオブジェクトを返す.Block.newと同義.
Thu Jul 6 00:35:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* signal.c (Ftrap): SIG_DFLの処理を変更.SIGINTへのデフォルトハン
ドラを用意(例外を発生する).
* file.c (Sfile_expand_fname): パス名を絶対パスに展開するメソッド.
(Sfile_basename): basenameを得るメソッド.拡張子も外せる.
(Sfile_dirname): basenameの反対.
* eval.c (rb_call): argument評価中の例外発生に対応.
* file.c (Ftest): `M', `A', `C'を追加.
Tue Jul 4 12:36:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* file.c (Ftest): ファイルテスト用メソッド.
* ruby.c (proc_options): `-r'オプションを追加.
* parse.y (f_args): デフォルト引数を追加.
* eval.c (rb_call): 該当する引数が無い時,rest引数の値をnilに.
* numeric.c (num_equal): 数値以外との比較で例外が発生していた.
FALSEを返すように.
* eval.c (masign): 多重代入のrest部の動作がおかしかった.
Sat Jun 17 01:03:16 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* parse.y (gettable): 未初期化のローカル変数の参照(独立した識別子)
は正式にメソッド呼び出しとした.
* parse.y (read_escape): tokenbufを使わないように修正.それにとも
ない,`\C-x',`\M-x'などのエスケープ表現を復活.これでドキュメン
トと実際の処理系が一致した.
Thu Jun 15 15:42:00 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* re.c (re_regcomp): cacheのチェックを改善.
Mon Jun 12 18:50:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* version 0.79
Sat Jun 10 00:25:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* re.c (re_regcomp): cache判定に`$='の値も反映させた.
* sample/test.rb: test suite作成.
Fri Jun 9 15:58:34 1995 Yukihiro Matsumoto <matz@ix-02>
* re.c (re_regcomp): cacheの判定が間違っていた.
Fri Jun 9 00:01:35 1995 Yukihiro Matsumoto (matz@dyna)
* eval.c (rb_yield): block構造体に初期化していないメンバ(iter)があっ
たのでイテレータのネストが正しく動作しなかった.
Thu Jun 8 00:59:03 1995 Yukihiro Matsumoto (matz@dyna)
* re.c (=~): String以外との比較がFALSEを返すように(例外を発生して
いた).
* extmk.rb.in: 判定した値をファイルにキャッシュするようにした.
* assoc.c (to_a): to_aメソッドが再定義されていなかった.
* eval.c (rb_eval): 初期化されていないローカル変数へのアクセスを引
数の無いメソッド呼び出しと解釈する.ただし,(現状では)メソッドが
定義されていない場合,エラーにせず変数未初期化のwaringを出して
nilを返している.「ruby -pe print」などが実行できるという意味で
はありがたいこの仕様は,しかし今後の検討が必要である.-- メソッ
ド呼び出しとするのを止めるか(以前の仕様),いつもメソッド呼び出し
とする(未定義ならばエラー)か,今の仕様で行くか.
* eval.c (rb_eval): 初期化されていないローカル変数へのアクセスで
(evalなどで)初期化された事が分かった時には以後初期化されたローカ
ル変数とみなす.
Wed Jun 7 11:58:12 1995 Yukihiro Matsumoto <matz@ix-02>
* eval.c (rb_fail): 例外処理後も`$!'をクリアしないように.
(rb_fail): `$!'変数に最後に改行を追加しない.
* io.c (Fprint): privateメソッドに変更.引数を取らない時の動作を変
更(`$_'を出力する).
(Fio_print): 出力先指定のprintメソッド.
(Fio_printf): 出力先指定のprintfメソッド.
* parse.y: not演算子の追加.優先順位の低い`!'演算子.
Mon Jun 5 19:00:55 1995 Yukihiro Matsumoto <matz@ix-02>
* version 0.78
Fri Jun 2 17:52:03 1995 Yukihiro Matsumoto <matz@ix-02>
* ruby.c (proc_options): -Iオプションで`$:'への追加される順番を修
正した.
Fri Jun 2 00:36:34 1995 Yukihiro Matsumoto (matz@dyna)
* parse.y: while修飾子の動作を通常のwhileと同じにした.ただし,
begin式へのwhile修飾子だけはdo..while型のループとなる.
Wed May 31 18:36:30 1995 Yukihiro Matsumoto <matz@ix-02>
* version 0.77
Mon May 29 18:39:37 1995 Yukihiro Matsumoto <matz@ix-02>
* ext/extmk.rb.in (install): 拡張モジュールもインストールできるよ
うに.
Fri May 26 14:43:01 1995 Yukihiro Matsumoto <matz@ix-02>
* process.c (Fsystem): 戻り値をサブプロセスの失敗/成功を表す真偽値
にした.終了ステータスは`$?'で得る.
Tue May 23 10:58:11 1995 Yukihiro Matsumoto <matz@ix-02>
* string.c (Fstr_upto): 無限ループに陥らないように.
* parse.y (cond): `||'などの右辺に制御式が書けるように,条件式がか
ならずしも値を持たなくても良いようにした.
* ext/marshal/marshal.c: オブジェクトの読み書きをメソッドの再定義
でコントロールできるように.インスタンスが`_dump_to'というメソッ
ドを定義している時はそちらを使うように.
* ext/extmk.rb.in: static linkも設定できるような仕様にした.
ext/Setupというファイルにディレクトリ名を記述するとそのディレク
トリに存在するモジュールはstatic linkされる(はず).
* eval.c (rb_eval): `..'を文法に組み込み,`..'と`...'の動作をperl
に合わせた.
Sat May 20 01:22:48 1995 Yukihiro Matsumoto (matz@dyna)
* io.c (select): timeout時と割込み時の動作の明確化.
Co-authored-by: Takahasi Mamoru <taka@soum.co.jp>
Co-authored-by: Yasuo OHBA <jammy@csg.mes.co.jp>
-rw-r--r-- | C-IF | 204 | ||||
-rw-r--r-- | ChangeLog | 713 | ||||
-rw-r--r-- | FAQ | 65 | ||||
-rw-r--r-- | MANIFEST | 84 | ||||
-rw-r--r-- | Makefile.in | 100 | ||||
-rw-r--r-- | README | 182 | ||||
-rw-r--r-- | README.EXT | 308 | ||||
-rw-r--r-- | ToDo | 5 | ||||
-rw-r--r-- | array.c | 374 | ||||
-rw-r--r-- | assoc.c | 150 | ||||
-rw-r--r-- | bignum.c | 147 | ||||
-rw-r--r-- | class.c | 76 | ||||
-rw-r--r-- | compar.c | 29 | ||||
-rw-r--r-- | configure.in | 176 | ||||
-rw-r--r-- | defines.h | 16 | ||||
-rw-r--r-- | dir.c | 85 | ||||
-rw-r--r-- | dln.c | 539 | ||||
-rw-r--r-- | dln.h | 12 | ||||
-rw-r--r-- | dmyext.c | 4 | ||||
-rw-r--r-- | enum.c | 118 | ||||
-rw-r--r-- | env.h | 22 | ||||
-rw-r--r-- | error.c | 41 | ||||
-rw-r--r-- | eval.c | 1537 | ||||
-rw-r--r-- | ext/MANIFEST | 3 | ||||
-rw-r--r-- | ext/Setup | 7 | ||||
-rw-r--r-- | ext/dbm/MANIFEST | 5 | ||||
-rw-r--r-- | ext/dbm/dbm.c | 435 | ||||
-rw-r--r-- | ext/dbm/dbm.doc | 107 | ||||
-rw-r--r-- | ext/dbm/depend | 1 | ||||
-rw-r--r-- | ext/dbm/extconf.rb | 4 | ||||
-rw-r--r-- | ext/etc/MANIFEST | 5 | ||||
-rw-r--r-- | ext/etc/depend | 1 | ||||
-rw-r--r-- | ext/etc/etc.c (renamed from etc.c) | 143 | ||||
-rw-r--r-- | ext/etc/etc.doc | 73 | ||||
-rw-r--r-- | ext/etc/extconf.rb | 7 | ||||
-rw-r--r-- | ext/extmk.rb.in | 398 | ||||
-rw-r--r-- | ext/marshal/MANIFEST | 4 | ||||
-rw-r--r-- | ext/marshal/depend | 2 | ||||
-rw-r--r-- | ext/marshal/marshal.c | 565 | ||||
-rw-r--r-- | ext/marshal/marshal.doc | 45 | ||||
-rw-r--r-- | ext/socket/MANIFEST | 5 | ||||
-rw-r--r-- | ext/socket/depend | 1 | ||||
-rw-r--r-- | ext/socket/extconf.rb | 6 | ||||
-rw-r--r-- | ext/socket/socket.c | 785 | ||||
-rw-r--r-- | ext/socket/socket.doc | 227 | ||||
-rw-r--r-- | ext/tkutil/MANIFEST | 3 | ||||
-rw-r--r-- | ext/tkutil/extconf.rb | 11 | ||||
-rw-r--r-- | ext/tkutil/tkutil.c | 54 | ||||
-rw-r--r-- | file.c | 782 | ||||
-rw-r--r-- | gc.c | 161 | ||||
-rw-r--r-- | glob.c | 9 | ||||
-rw-r--r-- | hash.c | 283 | ||||
-rw-r--r-- | ident.h | 26 | ||||
-rw-r--r-- | inits.c | 9 | ||||
-rw-r--r-- | io.c | 544 | ||||
-rw-r--r-- | io.h | 11 | ||||
-rw-r--r-- | lib/base64.rb | 55 | ||||
-rw-r--r-- | lib/find.rb | 38 | ||||
-rw-r--r-- | lib/getopts.rb (renamed from sample/getopts.rb) | 0 | ||||
-rw-r--r-- | lib/mailread.rb | 45 | ||||
-rw-r--r-- | lib/parsearg.rb (renamed from sample/parsearg.rb) | 0 | ||||
-rw-r--r-- | lib/parsedate.rb | 42 | ||||
-rw-r--r-- | lib/tk.rb | 1215 | ||||
-rw-r--r-- | lib/tkcanvas.rb | 318 | ||||
-rw-r--r-- | lib/tkclass.rb | 36 | ||||
-rw-r--r-- | lib/tkentry.rb | 74 | ||||
-rw-r--r-- | lib/tktext.rb | 160 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | math.c | 46 | ||||
-rw-r--r-- | missing/MANIFEST | 10 | ||||
-rw-r--r-- | missing/crypt.c | 276 | ||||
-rw-r--r-- | missing/dup2.c | 36 | ||||
-rw-r--r-- | missing/nt.c | 1732 | ||||
-rw-r--r-- | missing/nt.h | 246 | ||||
-rw-r--r-- | missing/setenv.c | 73 | ||||
-rw-r--r-- | node.h | 28 | ||||
-rw-r--r-- | numeric.c | 367 | ||||
-rw-r--r-- | object.c | 314 | ||||
-rw-r--r-- | pack.c | 20 | ||||
-rw-r--r-- | parse.y | 963 | ||||
-rw-r--r-- | process.c | 184 | ||||
-rw-r--r-- | random.c | 11 | ||||
-rw-r--r-- | range.c | 80 | ||||
-rw-r--r-- | re.c | 387 | ||||
-rw-r--r-- | re.h | 10 | ||||
-rw-r--r-- | regex.c | 18 | ||||
-rw-r--r-- | regex.h | 1 | ||||
-rw-r--r-- | ruby.1 | 248 | ||||
-rw-r--r-- | ruby.c | 107 | ||||
-rw-r--r-- | ruby.h | 140 | ||||
-rw-r--r-- | ruby.texi | 5044 | ||||
-rw-r--r-- | sample/MANIFEST | 63 | ||||
-rw-r--r-- | sample/aset.rb | 7 | ||||
-rw-r--r-- | sample/attr.rb | 14 | ||||
-rw-r--r-- | sample/blk.rb | 9 | ||||
-rw-r--r-- | sample/case.rb | 14 | ||||
-rw-r--r-- | sample/cat.rb | 5 | ||||
-rw-r--r-- | sample/cat2.rb | 5 | ||||
-rw-r--r-- | sample/clnt.rb | 3 | ||||
-rw-r--r-- | sample/clone.rb | 18 | ||||
-rw-r--r-- | sample/const.rb | 24 | ||||
-rw-r--r-- | sample/dbm.rb | 2 | ||||
-rw-r--r-- | sample/exyacc.rb | 20 | ||||
-rwxr-xr-x | sample/from.rb | 102 | ||||
-rw-r--r-- | sample/gctest.rb | 67 | ||||
-rw-r--r-- | sample/gctest2.rb | 71 | ||||
-rw-r--r-- | sample/hash.rb | 11 | ||||
-rw-r--r-- | sample/list3.rb | 6 | ||||
-rw-r--r-- | sample/marshal.rb | 13 | ||||
-rw-r--r-- | sample/math.rb | 4 | ||||
-rw-r--r-- | sample/mkproto.rb | 27 | ||||
-rw-r--r-- | sample/occur2.rb | 2 | ||||
-rw-r--r-- | sample/opt_s.rb | 12 | ||||
-rw-r--r-- | sample/opt_x.test | 10 | ||||
-rw-r--r-- | sample/rcs.rb | 2 | ||||
-rw-r--r-- | sample/ruby-mode.el | 305 | ||||
-rw-r--r-- | sample/samp.rb | 15 | ||||
-rw-r--r-- | sample/sieve.rb | 2 | ||||
-rw-r--r-- | sample/split.rb | 13 | ||||
-rw-r--r-- | sample/struct.rb | 8 | ||||
-rw-r--r-- | sample/svr.rb | 2 | ||||
-rw-r--r-- | sample/system.rb | 2 | ||||
-rw-r--r-- | sample/t1.rb | 20 | ||||
-rw-r--r-- | sample/t2.rb | 23 | ||||
-rw-r--r-- | sample/test.rb | 1043 | ||||
-rw-r--r-- | sample/tkbiff.rb | 121 | ||||
-rw-r--r-- | sample/tkbrowse.rb | 69 | ||||
-rw-r--r-- | sample/tkdialog.rb | 62 | ||||
-rw-r--r-- | sample/tkfrom.rb | 115 | ||||
-rw-r--r-- | sample/tkhello.rb | 13 | ||||
-rw-r--r-- | sample/tkline.rb | 29 | ||||
-rw-r--r-- | sample/tktimer.rb | 49 | ||||
-rw-r--r-- | sample/trap.pl | 6 | ||||
-rw-r--r-- | sample/trap.rb | 3 | ||||
-rw-r--r-- | sample/tt.rb | 100 | ||||
-rw-r--r-- | sig.h | 28 | ||||
-rw-r--r-- | signal.c | 200 | ||||
-rw-r--r-- | spec | 3538 | ||||
-rw-r--r-- | sprintf.c | 49 | ||||
-rw-r--r-- | st.c | 91 | ||||
-rw-r--r-- | st.h | 2 | ||||
-rw-r--r-- | string.c | 708 | ||||
-rw-r--r-- | struct.c | 399 | ||||
-rw-r--r-- | time.c | 239 | ||||
-rw-r--r-- | util.c | 1 | ||||
-rw-r--r-- | variable.c | 553 | ||||
-rw-r--r-- | version.c | 7 | ||||
-rw-r--r-- | version.h | 4 |
148 files changed, 21293 insertions, 9071 deletions
@@ -1,204 +0,0 @@ -.\" C-IF - -*- Text -*- created at: Tue Oct 12 14:15:00 JST 1993 - -Ruby-C ե - - - - VALUE - - Ruby֥Ȥɽ뷿. ɬפ˱ƥ㥹ȤѤ. Ȥ - ߷ɽCηruby.h˵ҤƤRǻϤޤ빽¤ΤǤ. - VALUE˥㥹Ȥ뤿RǻϤޤ빽¤̾ʸ - ̾ΥޥѰդƤ. - -ѿ - - Qnil - - : nil֥ - - Qself - - ѿ: ߤself֥Ȥ. ̤˥åɤˤselfؤ - ͿΤ, ѿ˥ɬפϤʤ. ѿͤ - ѹϰʸselfͤΤΤѤäƤޤΤ, ̤ʻ - ʤ¤ƤϤʤʤ. - - TRUE - - : t֥(Υǥե) - - FALSE - - : nil֥ - -饹⥸塼 - - VALUE rb_define_class(char *name, VALUE super) - - superΥ֥饹ȤƿRuby饹. - - VALUE rb_define_module(char *name) - - Ruby⥸塼. - - void rb_include_module(VALUE class, VALUE module) - - ⥸塼롼ɤ. classǤmodule롼ɤ - ˤϲ⤷ʤ(¿ť롼ɤζػ). - -ѿ - - void rb_define_variable(char *name, VALUE *var, - VALUE (*get_hook), VALUE (*set_hook)(), void *data) - - RubyCȤǶͭ륰Хѿ. get_hookQnilǤʤ, - ѿȤκݤget_hook˥åȤ줿ؿƤФ. set_hookQnil - Ǥʤˤλset_hookƤФ. hookؿˤѿ̾ - ID(set hookξ翷ͤ)ȤȤdataͿǡȤ - Ϥ. - - ѿ̾`$'ǻϤޤʤˤϼưŪɲä. ѿ̾Ȥruby - ̻ҤȤƵʤʸ(㤨` ')ޤˤrubyץफ - 饢Ǥʤʤ. - - void rb_global_variable(VALUE *var) - - GCΤᡤRubyץफϥʤ, Ruby֥ - ޤѿޡ. - - void rb_read_only_hook() - - ɤ߽ФѤѿΤset_hookؿ. ͤꤷ褦Ȥ㳰 - ȯ. - -饹 - - void rb_define_const(VALUE class, char *name, VALUE val) - - 饹. - -å - - rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc) - - åɤ. argcselfο. argc-1λ, ؿ - ϰο(selfޤޤʤ)1, 2Ȥ - Ϳ(3self). argc-2λ, self, args(args - ޤruby)ȤͿ. - - rb_define_single_method(VALUE class, char *name, VALUE (*func)(), int argc) - - ðۥåɤ. rb_define_method()Ʊ. - - rb_scan_args(int atgc, VALUE *argv, 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(char *str) - - ʸrubyȥץȤƥѥ롦¹Ԥ롥 - - ID rb_intern(char *name) - - ʸбID֤. - - char *rb_id2name(ID id) - - IDбʸ֤(ǥХå). - - char *rb_class2name(VALUE class) - - class֤̾(ǥХå). class̾ʤˤ, ֶ - ̾ĥ饹֤̾. - -ѿ - - VALUE rb_iv_get(VALUE obj, char *name) - - objΥѿͤ. `@'ǻϤޤʤѿ - Rubyץफ饢Ǥʤ. - - VALUE rb_iv_set(VALUE obj, char *name, VALUE val) - - objΥѿval˥åȤ. - -湽¤ - - VALUE rb_iterate(VALUE (*func1)(), char *arg1, VALUE (*func2)(), char *arg2) - - func2֥åȤꤷ, func1ƥ졼ȤƸƤ. func1 - arg1ȤϤ, func2ˤ1˥ƥ졼Ϳ - , 2arg2Ϥ. - - VALUE rb_yield(VALUE val) - - valͤȤƥƥ졼֥åƤӽФ. - - VALUE rb_resque(VALUE (*func1)(), char *arg1, VALUE (*func2)(), char *arg2) - - ؿfunc1arg1˸ƤӽФ. func1μ¹㳰ȯ - func2arg2ȤƸƤ. ͤ㳰ȯʤä - func1, 㳰ȯˤfunc2ͤǤ. - - VALUE rb_ensure(VALUE (*func1)(), char *arg1, VALUE (*func2)(), char *arg2) - - ؿfunc1arg1ȤƼ¹Ԥ, ¹Խλ(Ȥ㳰ȯ - ) func2arg2ȤƼ¹Ԥ. ͤfunc1ͤǤ( - ȯʤ). - -㳰顼 - - void Warning(char *fmt, ...) - - ɸ२顼Ϥ˷ٹɽ. printf()Ʊ. - - void Fail(char *fmt, ...) - - 㳰ȯ. printf()Ʊ. - - void Fatal(char *fmt, ...) - - ̿Ū㳰ȯ. ̾㳰ϹԤʤ줺, ץ - λ(ensureǻꤵ줿ɤϽλ˼¹Ԥ). - - void Bug(char *fmt, ...) - - ץʤɥץΥХǤȯϤΤʤλ - Ƥ. ץϥפľ˽λ. 㳰ϰڹ - ʤʤ. - -rubyν¹ - - void ruby_init(int argc, char **argv, char **envp) - - rubyץνԤʤ. - - void ruby_run() - - rubyץ¹Ԥ. - - void ruby_script(char *name) - - rubyΥץ̾($0)ꤹ. - -/* - * Local variables: - * fill-column: 70 - * end: - */ @@ -1,3 +1,709 @@ +Thu Dec 21 00:56:57 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.95 - fj.sources + + * eval.c (rb_eval): rescueΥårb_rescue()˰층 + +Wed Dec 20 19:30:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * Makefile.in: פʥѥβ(괰) + + * class.c (singleton_class_new): `single'->`singleton' + +Tue Dec 19 07:14:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * io.c (closed?): IOcloseƤ뤫ɤΤҸ졥 + + * parse.y (primary): ðۥåɤΰlex_stateŬڡ + + * lib/tk.rb: tcl->rubyѴؿѰա + + * ext/extmk.rb.in (install): install2ťѥβ + + * array.c (range_beg_len): rangeŬڤʥ顼 + + * string.c (str_aref): rangeΥХ + + * lib/tk.rb (tk_split_list): TclΥꥹȤб + +Mon Dec 18 09:58:12 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.94 + + * dln.c (dln_load): HPб(̤ǧ) + + * eval.c (Init_Proc): BlockProc˲̾ + +Sat Dec 16 13:46:14 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_eval): retryǥƥ졼κƼ¹ԤǤ褦ˡ + +Fri Dec 15 17:14:30 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c: proc:lambdaοƤߤ䤹̾ + +Thu Dec 14 17:21:55 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (dyna_var_asgn): ƥ졼֥åǺǽ˽줿 + ѿͭϰϤΥ֥å˸ꡥlambdaȸƤ + ʤȤϤʤ + +Wed Dec 13 02:30:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * gc.c: autoloadΥޡߥ + + * lib/tk.rb: wishʣԤͤб + + * lib/tkcomposite.rb: ʣwidget + + * variable.c (rb_class2path): ICLASSбƤʤä + + * eval.c (ruby_run): exit(0)ΥХ + +Sat Dec 9 01:21:24 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/marshal/marshal.c (dumps|load): ʸФϤǽ + (¤ϥեͳʤΤ) + +Fri Dec 8 18:29:11 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/marshal/marshal.c: ܥ٤롥 + +Thu Dec 7 07:58:50 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (yylex): 1ɽǧ˥顼äƱ + ֿ餷 + + * string.c (str_sub): ִǥå礭 + +Wed Dec 6 15:14:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_sub_method): sub/gsub(!ʤ)ִԤʤʤ + ִʸ֤ + +Tue Dec 5 00:55:15 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (yylex): ̤άΰŸ`*'б + + * eval.c (ruby_run): EXITϥɥǤ㳰б + + * bignum.c (big_cmp): BignumFixnumӤ롥 + +Mon Dec 4 14:21:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (call_op): ѥŸϫ¿ + ƱʤȽǤΤǡ + +Thu Nov 30 01:35:15 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * lib/tk.rb: {Radio,Check}Buttonvariableμ + + * eval.c (rb_yield_0): Block.callͥȤΥХ + + * io.c (f_select): 3Ĥդ֤褦 + + * lib/tk.rb: fileeventruby¦Ǽ + +Wed Nov 29 17:53:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * variable.c (rb_ivar_get): self˻ꤹ褦ˡ + +Tue Nov 14 00:07:29 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * lib/tk.rb: Tk4.0б + +Mon Nov 13 16:23:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.93 + +Thu Nov 9 23:26:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * gc.c (gc_mark): ⥸塼MixinΥޡ˺졥 + + * parse.y (f_arglist): åΰ̤dzʤƤɤ + 褦ˤ + +Wed Nov 8 00:17:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_yield_0): ̤Υѿä + + * eval.c (rb_eval): pendig signalΥåeval¹Ը˹Ԥ褦 + ˤǤʤȥʥȯȸФΥƤޤ롥 + + * parse.y: classʸsuperclass鼰˳ĥ + + * lib/tk.rb: TkΤۤɥ饹бХȥƥ + ȾΥ֥ȤĤäƤ롥 + +Tue Nov 7 08:18:37 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * signal.c (trap): ֥åǤ褦ˡ + +Mon Nov 6 16:44:00 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (f_caller): ƽиξ롥 + + * ext/tkutil/tkutil.c: wishstderrϤƻ뤹뤳Ȥǡ顼 + Ԥ + + * ext/tkutil/tkutil.c: wishȤ̿Cǵҡ + +Sat Nov 4 01:12:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-calculate-indent): ǥȤη + ⤦ޡȤˤ(ɽΥå³ԤΥå) + + * eval.c (rb_call): ̵ºƵ뤿ᡤؿΥͥȥ٥ + Ԥʤ + + * lib/tk.rb: TkեޤԴ + + * eval.c (rb_yield_0): BlockΥХ + + * sample/ruby-mode.el (ruby-calculate-indent): α黻Ҥˤ + Է³б + +Fri Nov 3 12:56:21 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_call): Τδؿμ¹Ԥ˥Х + + * parse.y (var_extend): ʸѿŸΥХ + + * variable.c (rb_gvar_set): traceɾˤѿͤͿ褦ˡ + + * eval.c (f_require): ruby scriptrequirebug + + * variable.c (rb_const_get): ⥸塼includeк + +Thu Oct 19 13:56:06 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * dln.c (dln_load): HPбǤtypo. + +Wed Oct 18 17:39:39 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.92 + + * object.c (krn_type): ֥ȤưŪʷ֤åɡ + +Tue Oct 17 00:48:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ruby.c (proc_options): -X ץchdirԤ + + * re.c (reg_search): ɤѹǤ褦ˡѥ + Υɤѹ줿ˤϥޥåľɽκƥѥ + ԤKCODEѿ$KCODEء + + * parse.y: ()Τʤcompexpr + + * re.c (reg_search): ľ + +Fri Oct 13 13:19:19 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_sub): ʸִ˥Х + + * string.c (str_strip_bang): ʸθĹĴԤƤ + ʤä + + * re.c (reg_search): $&, $1...Τϥ«褦ˤʤä + ƤӽФåɤǤΥޥåϸפ$&ʤɤͤ˱ƶʤ + ޥåξ׳Ȥˤ$~Ȥä« + Фɬפ롥 + +Thu Oct 12 00:33:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * re.c (reg_search): String:split, String:indexǤ$&, $1...Ѳ + ʤ褦ˤ + + * io.c (rb_str_setter): setterλͤѹˤʤäƤ + + * variable.c (f_trace_var): 2άƥƥ졼ȤƸƤ + 褦ˡ + +Wed Oct 11 11:50:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.91 + + * variable.c (var_setter): ְäƤ̿ŪХ + + * io.c (pipe_open): $stderrͤѹƤˤϤ + ҥץstderrꤹ롥 + +Mon Oct 9 13:06:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * object.c (mod_to_s): ⥸塼Υ⥸塼`::'Ȥäɽ + ɽ褦ˡ + + * variable.c (rb_gvar_set): ˤ롼פȯʤ褦ˡ + traceǤǤtraceɾʤ + + * struct.c (struct_equal): structequalȽ˥饹ΰפޤ + +Sat Oct 7 00:18:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_eval): defined?εǽĥ(yieldΥåsuper + ¸ߤʤ) + +Fri Oct 6 12:06:47 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.90 + + * st.c (st_foreach): ǤǿѲƤʤä + + * hash.c (hash_values): Хkeys֤Ƥġ + + * parse.y (call_op): defined? ΰǤξ߹ߤԤʤ + (å˥ѥ륨顼ˤʤäƤϺ) + + * ΰľ + +Thu Oct 5 00:29:43 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ؿȥ饹̿̾§ѹؿ̾ѿ̾̽ + + * gc.c (looks_pointerp): ҡץåι® + + * struct.c (Fstruct_aset): ¤ΤФ`[]=' + (struct_set): ¤ΥФФ + +Wed Oct 4 09:54:07 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.89 + + * eval.c (Frequire): ʥߥåɤΥ顼å + + * struct.c: structι¤˽Ͻդ + id->valueϢǤä٤Ϲ¤˿饹 + 褦ˤ + + * parse.y: `::'ΰ̣Assoc饯饹(⥸塼) + ѹ + + * assoc.c: ʤ + +Tue Oct 3 13:31:08 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * variable.c (Ftrace_var): trace_var, ѿؤνhook + ꤹ롥 + + * variable.c: global_entryιtrace_var + Ǥ롥 + + * file.c (Ffile_stat): "&"ľfstatη̤⻲ȤǤ褦ˡ + +Fri Sep 29 14:15:13 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.88 + + * dln.c (dln_load): AIXHPбɤ줿(ư̤ǧ) + + * ext/extmk.rb.in: ɬפ˱ơEXTLIB褦ˡ + + * dln.c (dln_load): dlnΩ˽롥γĥѡ + (load_1): dln_a_outˤƥɤǥ饤֥Ū˥ + ɤɬפʤ褦ѹ + +Thu Sep 28 13:31:37 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el: äȤޤhilit19б(ɽ) + +Wed Sep 27 04:12:44 1995 Takahasi Mamoru <taka@soum.co.jp> + + * sample/test.rb: echo-nȤʤ褦(SysVк) + + * ext/extmk.rb.in: sub -> sub! + +Tue Sep 26 19:12:42 1995 Yasuo OHBA <jammy@csg.mes.co.jp> + + * dln.c (dln_find_1): `.', `..'Ϥޤѥб. + +Mon Sep 25 12:33:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.87 + +Sat Sep 23 10:00:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (Fmod_modfunc): åɤprivateˤƱðۥå + åɡѥåŪȤΥ⥸塼ѡ + +Fri Sep 22 11:02:44 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * lib/find.rb: find饤֥ + + * variable.c (rb_define_variable): hookʬΥ + (add_hook): 1ѿФʣhookǤ褦ˡ + +Thu Sep 21 00:22:11 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (Fstr_frozen): ʸԲĤɤå + åɡ + + * hash.c (Fhash_aset): keyʸλƤѲʤ褦 + ˡdupfreeze롥 + +Wed Sep 20 16:12:44 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.86 + + * ext/extmk.rb.in (have_header): å˥Х + + * ext/extmk.rb.in (have_library): νѤä + +Thu Sep 14 18:00:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * object.c (obj_is_instance_of): is_member_of̾ѹ + +Wed Sep 13 15:44:35 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (Fstr_tr_bang): ϰϳʸФѴХ + +Tue Sep 12 14:27:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * file.c (Sfile_expand_path): expand_file_name -> expand_path̾ + ѹ + + * enum.c (Fenum_member): includes? -> member? ̾ѹ + + * string.c (Fstr_each_byte): StringByteArrayǤȤܤ + ơeacheach_byteѹޤǤeacheach_lineǥ + Ǥ롥 + +Mon Sep 11 18:31:17 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * file.c (cache_stat): ե̾Ȥ"&"ꤹľ + stat(2)η̤Ѥ褦ˡ + +Fri Sep 8 14:18:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ruby.texi: `!', `?'бƥåץǡȡ + + * parse.y: defined -> defined? + + * file.c: FileOpΰʸåɤʤʸƥȤtest + ɤˤޤ롥 + + * parse.y (yylex): ѿ̾θ`?'Ҹåɤθ + `?'ɲä롥 + +Thu Sep 7 20:01:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c: ʸȤåɤ̾ν`!'ղá + `!'̵СѰդ + + * parse.y: ѿ̾θ`!' + +Wed Sep 6 14:12:19 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.85 + + * string.c (Fstr_dup): ʸʣ + (Fstr_freeze): ʸιԲ°Ǥ褦ˡ + (Fsub/Fgsub): $_ƤdupƤִԤ褦ˡ + + * ruby.h (CLONESETUP): flagsξ֤⥳ԡ + +Tue Sep 5 01:27:50 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/test.rb: ԤθФ + +Fri Aug 25 14:31:02 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * process.c (Ffork): ƥ졼ȤƤư褦ˡ + + * version 0.84 + + * signal.c (sig_beg): ϥɥ餬ꤵƤˤϺꤷʤ + + * ext/extmk.rb.in (create_makefile): shared objectΥκݤ + `-l'ץꤹ褦ˡ + + * signal.c (trap): `EXIT'ǽλԤ꤬롥 + +Wed Aug 16 00:13:22 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * signal.c (sig_beg): ǥեȤǤbeginǤSIGINTª + 褦ѹ + + * io.c (io_ctl): fcntlʤƥˤб + + * ƥǥ쥯ȥʬƤMANIFESTޤȤĥ⥸塼 + ˤɬס + + * string.c (Sstr_new,str_sub,Fstr_crypt): ưŪʸ + 褦ˡ + +Sat Aug 12 00:44:02 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (Fstr_crypt): PD cryptѰդ + +Fri Aug 11 14:37:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * assoc.c (Fassoc_clone): assoccloneǤ褦ˡ + + * io.c: ޥREAD_DATA_PENDINGѹ(Linuxб) + + * io.c (io_fptr_finalize): ftprγνǤ褦ˡ + +Wed Aug 9 16:52:41 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_provided): ʣfeatureɤ̵¥롼פ + Ȥñ()ߥ + + * ext/extmk.rb.in (install): dlopenбԤäޤdlnˤ + ʬбƤʤä + +Tue Aug 8 14:17:06 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.83 + +Mon Aug 7 12:47:41 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y: resque -> rescueѤtypoĤƤ櫓ˤ + ʤʤʤǺޤǵĤʤäΤġ + +Thu Aug 3 18:18:05 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * missing/nt.c: NTܿѤδؿޤȤ + + * variable.c (rb_const_get): ޤ㳰ȯ褦ˤdefined + ʾ㳰ȯʤͳʤΤ(㳰ȯ + ץߥθФʤɤͭ) + + * variable.c (Fautoload): autoload٤ϻȤ뤫 + +Mon Jul 31 15:44:21 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (arg_ambiguous): 1Τޤٹ(-vץ + ͭ) + + * eval.c (rb_eval): `-v'ץĤ`def'ƤФɬ + ʥ顼åФ + + * parse.y (yylex): åɤ1Ƚ⤦äȸ + +Fri Jul 28 19:04:43 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (yylex): `+/-/['ľ˶뤫ɤưѹ + (ΤȤ?) + +Wed Jul 26 09:21:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.82a + + * sprintf.c (Fsprintf): `%s''\0'ޤʸб + + * pack.c (Fpck_pack): packdzݤΥХ + + * eval.c (Floop): ̵¥롼פΥƥ졼 + + * io.c (next_argv): ¸ߤʤե̾ꤵ줿Υ顼 + ԤƤʤä + +Mon Jul 24 17:37:34 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.82 + + * ext/extmk.rb.in (install): ĥ⥸塼static link + Υ⥸塼뤬require줿ΤƱ褦featureꤹ롥 + dzĥ⥸塼εǽɬפʻˤ(static linkƤ뤫 + ɤˤ餺)requireФ褯ʤ롥 + + * eval.c (Frequire): `$"'˳ǼʸեѥǤʤե + ̾Ȥ롥rubyץȤɤˤ`.rb'֥Ȥ + ɤˤ`.o'ե̾ղä롥lisprequire + provideƯ()ᤤ + +Thu Jul 20 12:50:05 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * Makefile.in (test): make testǤ褦ˡ + + * struct.c (struct_new): typo. + + * eval.c (rb_eval): `defined'ɲáå/ѿ/ + Τ롥 + +Wed Jul 19 18:04:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.81 + +Mon Jul 17 14:53:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * variable.c (rb_const_get): ̤CONSTANTͤnilˤ + ޤ㳰᤹ǽϤ롥פoptionalʥ饹/⥸塼 + 뤬¸ߤ뤫åʤʡ + + * st.c (int): grow_factorˤ(褵Υޥб) + +Fri Jul 14 00:48:40 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/extmk.rb.in: åΥХ + + * parse.y (var_extend): #{$}б + + * dln.c (dln_load_1): `Init_FILENAME'ͭˡ`init_*'Ϻ + ¹Ԥʤ + + * ext/etc/etc.c : Etc⥸塼ĥ⥸塼ȤʬΥ¤NT + бؤФäꤹ뤫⤷ʤ + +Tue Jul 11 17:12:48 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * gcc -WallǽФwarning˥ѹ + + * signal.c (trap): typo. + +Fri Jul 7 10:08:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.80 + + * ruby.texi: texinfo documentspecruby.1̵ʤä + + * signal.c (Ftrap): ߶ػ㳰ȯб + + * eval.c (Flambda): Block֥Ȥ֤Block.newƱ + +Thu Jul 6 00:35:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * signal.c (Ftrap): SIG_DFLνѹSIGINTؤΥǥեȥϥ + ɥѰ(㳰ȯ) + + * file.c (Sfile_expand_fname): ѥ̾ХѥŸåɡ + (Sfile_basename): basenameåɡĥҤ⳰롥 + (Sfile_dirname): basenameȿС + + * eval.c (rb_call): argumentɾ㳰ȯб + + * file.c (Ftest): `M', `A', `C'ɲ. + +Tue Jul 4 12:36:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * file.c (Ftest): եƥѥåɡ + + * ruby.c (proc_options): `-r'ץɲá + + * parse.y (f_args): ǥեȰɲá + + * eval.c (rb_call): ̵restͤnilˡ + + * numeric.c (num_equal): ͰʳȤӤ㳰ȯƤ + FALSE֤褦ˡ + + * eval.c (masign): ¿restưä + +Sat Jun 17 01:03:16 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (gettable): ̤Υѿλ(Ω̻) + ˥åɸƤӽФȤ + + * parse.y (read_escape): tokenbufȤʤ褦˽ˤȤ + ʤ`\C-x',`\M-x'ʤɤΥɽ补ǥɥ + ȤȼºݤνϤפ + +Thu Jun 15 15:42:00 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * re.c (re_regcomp): cacheΥå + +Mon Jun 12 18:50:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.79 + +Sat Jun 10 00:25:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * re.c (re_regcomp): cacheȽ`$='ͤȿǤ + + * sample/test.rb: test suite + +Fri Jun 9 15:58:34 1995 Yukihiro Matsumoto <matz@ix-02> + + * re.c (re_regcomp): cacheȽְ꤬äƤ + +Fri Jun 9 00:01:35 1995 Yukihiro Matsumoto (matz@dyna) + + * eval.c (rb_yield): block¤Τ˽Ƥʤ(iter) + Τǥƥ졼ΥͥȤưʤä + +Thu Jun 8 00:59:03 1995 Yukihiro Matsumoto (matz@dyna) + + * re.c (=~): StringʳȤӤFALSE֤褦(㳰ȯ + ) + + * extmk.rb.in: Ƚꤷͤե˥å夹褦ˤ + + * assoc.c (to_a): to_aåɤƤʤä + + * eval.c (rb_eval): ƤʤѿؤΥ + ̵åɸƤӽФȲ᤹롥(Ǥ)åɤ + Ƥʤ硤顼ˤѿ̤waringФ + nil֤Ƥ롥ruby -pe printפʤɤ¹ԤǤȤ̣ + Ϥ꤬λͤϡθƤɬפǤ롥-- + ɸƤӽФȤΤߤ뤫(λ)ĤåɸƤӽФ + Ȥ(̤ʤХ顼)λͤǹԤ + + * eval.c (rb_eval): ƤʤѿؤΥ + (evalʤɤ)줿ʬäˤϰʸ줿 + ѿȤߤʤ + +Wed Jun 7 11:58:12 1995 Yukihiro Matsumoto <matz@ix-02> + + * eval.c (rb_fail): 㳰`$!'ꥢʤ褦ˡ + (rb_fail): `$!'ѿ˺Ǹ˲Ԥɲäʤ + + * io.c (Fprint): privateåɤѹʤư + (`$_'Ϥ) + (Fio_print): printåɡ + (Fio_printf): printfåɡ + + * parse.y: not黻Ҥɲá̤ͥ㤤`!'黻ҡ + +Mon Jun 5 19:00:55 1995 Yukihiro Matsumoto <matz@ix-02> + + * version 0.78 + +Fri Jun 2 17:52:03 1995 Yukihiro Matsumoto <matz@ix-02> + + * ruby.c (proc_options): -Iץ`$:'ؤɲä֤ + + +Fri Jun 2 00:36:34 1995 Yukihiro Matsumoto (matz@dyna) + + * parse.y: whileҤư̾whileƱˤ + beginؤwhileҤdo..whileΥ롼פȤʤ롥 + +Wed May 31 18:36:30 1995 Yukihiro Matsumoto <matz@ix-02> + + * version 0.77 + +Mon May 29 18:39:37 1995 Yukihiro Matsumoto <matz@ix-02> + + * ext/extmk.rb.in (install): ĥ⥸塼⥤ȡǤ + ˡ + +Fri May 26 14:43:01 1995 Yukihiro Matsumoto <matz@ix-02> + + * process.c (Fsystem): ֥ͤץμ/ɽ + ˤλơ`$?'롥 + +Tue May 23 10:58:11 1995 Yukihiro Matsumoto <matz@ix-02> + + * string.c (Fstr_upto): ̵¥롼פ˴٤ʤ褦ˡ + + * parse.y (cond): `||'ʤɤαդ漰褦ˡP + ʤ餺ͤʤƤɤ褦ˤ + + * ext/marshal/marshal.c: ֥Ȥɤ߽åɤκ + ǥȥǤ褦ˡ`_dump_to'Ȥ + ɤƤϤȤ褦ˡ + + * ext/extmk.rb.in: static linkǤ褦ʻͤˤ + ext/SetupȤե˥ǥ쥯ȥ̾ҤȤΥǥ쥯 + ȥ¸ߤ⥸塼static link(Ϥ) + + * eval.c (rb_eval): `..'ʸˡȤ߹ߡ`..'`...'ưperl + ˹碌 + +Sat May 20 01:22:48 1995 Yukihiro Matsumoto (matz@dyna) + + * io.c (select): timeoutȳưβ + Fri May 19 15:33:23 1995 Yukihiro Matsumoto <matz@ix-02> * version 0.76 @@ -241,8 +947,7 @@ Wed Feb 22 00:51:38 1995 Yukihiro Matsumoto (matz@dyna) Tue Feb 21 18:56:56 1995 Yukihiro Matsumoto (matz@ix-02) - * io.c(STDIN, STDOUT, STDERR): ȤޤǤ$stdinʤ - Ͼʤʤ뤫Τʤ + * io.c(STDIN, STDOUT, STDERR): Ȥ * io.c(select): bug fix. @@ -351,8 +1056,8 @@ Tue Jan 17 11:11:27 1995 Yukihiro Matsumoto (matz@ix-02) Ѿ롥ǽλϺޤǤƱǥե(ȥåץ ǴؿŪ饹̾å) - * object.c(Class::new): ֥Ȥ˴ؿŪ - åinit_objectɬƤФ褦ѹ + * object.c(Class::new): ֥Ȥ˴ؿŪå + init_objectɬƤФ褦ѹ * eval.c: ̤ΥåɤФunknownåɤƤФ褦 ʤä顼ɽޤǤƱˤʤ褦envĴᤷƤ롥 @@ -1,65 +0,0 @@ -.\" FAQ - -*- Indented-Text -*- created at: Tue Jan 4 12:48:12 JST 1994 -Ruby˴ؤFAQ(Frequently Asked Question)ޤȤΤǤ. -EmacsǤΥեƤˤM-2 C-x $Ǽʬɤळ -ȤǤޤ. C-x $Ƥɤ֤᤻ޤ. ------------------------------- -1) Ruby̾Τͳ - - RubyϲάΤǤϤʤ, ֤Ф̾Ȥä̾դޤ. - perl(pearl6)μܻؤ(Ruby7)Ȥ̣ - ޤ. ͤΤǤäߤȤꤤޤޤ - Ƥޤ. ------------------------------- -2) Rubyƶ? - - RubyθͤC, Perl, EiffelγƸˤν˱ƶƤ - . ¾˱ƶȤƤtcl, AWK, bourne shell, CLU, - Icon, Sather, Smalltalk, Emacs Lispʤɤޤ. ------------------------------- -3) Rubyħ? - - ʲ˲վˤޤ. - - + ץǤ, ڤ˥ץǤ. - + ѿפʤ. - + ե䥹ȥʤɤؤUNIXŪñˤǤ. - + Хʥեⰷ. - + Ȥ֥ȻظǤ. - + ðۥåɤεǽƤ. - + ⥸塼ˤ뵡ǽζͭǤ. - + 㳰ǽ. - + GCΤǥˤʤƺѤ. - + Τ. - + ʣʥǡ¤ⰷ. - + ʥߥåɤݡȤ(ƥˤ). - - դ˷ - - - ȯŸӾǵǽʤ. - - ǥХå(ޤ)ʤ. - - ٤. - - ȤǤ礦. ------------------------------- -4) RubyѿʤȤΥåȤ? - - ѿɤΥפ°뤫ܤʬΤ, ץɤ - פ, פȤΥåȤǤ. ޤȡΥ - ̤Τǽפ, ڤˤޤ. ------------------------------- -5) RubyPerlΰ㤤? - - RubyPerlϥƥͥ줿ץȸǤȤ, - СϰϤ, 츫ȥ饤Х˸ޤ. ΤRuby߷ - ˤơPerlˤǤ뤳ȤϤǤ褦ˡפȤȤ, Ĥν - ɸǤ. , RubyοŪϤޤǤּڤʥ֥ - ȻظפǤ, ޤ, Ruby߷פ3ɸǤ, ǽ - ĥη̤Ȥ, RubyPerlȤϰۤʤˤʤޤ. - - RubyPerlۤɡֲǤ⤢פǤϤޤ, ۤȤɤξPerl - ®٤٤Ǥ. , RubyΥ֥ȻظǽPerlǤ - Ǥʤͤ˥ԡ뤹Ȼפޤ. ------------------------------- -Local variables: -fill-column: 70 -end: @@ -1,12 +1,10 @@ -C-IF ChangeLog -FAQ MANIFEST Makefile.in README +README.EXT ToDo array.c -assoc.c bignum.c class.c compar.c @@ -18,10 +16,10 @@ defines.h dir.c dln.c dln.h +dmyext.c enum.c env.h error.c -etc.c eval.c file.c fnmatch.c @@ -29,7 +27,6 @@ fnmatch.h gc.c glob.c hash.c -ident.h inits.c install-sh io.c @@ -48,11 +45,11 @@ re.c re.h regex.c regex.h -ruby.1 ruby.c ruby.h +ruby.texi +sig.h signal.c -spec sprintf.c st.c st.h @@ -64,3 +61,76 @@ util.c variable.c version.c version.h +ext/Setup +ext/extmk.rb.in +lib/base64.rb +lib/find.rb +lib/getopts.rb +lib/mailread.rb +lib/parsearg.rb +lib/parsedate.rb +lib/tk.rb +lib/tkcanvas.rb +lib/tkentry.rb +lib/tktext.rb +lib/tkclass.rb +missing/alloca.c +missing/crypt.c +missing/dup2.c +missing/memmove.c +missing/mkdir.c +missing/nt.c +missing/nt.h +missing/setenv.c +missing/strdup.c +missing/strerror.c +missing/strftime.c +missing/strstr.c +missing/strtol.c +missing/strtoul.c +sample/biorhythm.rb +sample/cbreak.rb +sample/clnt.rb +sample/dbm.rb +sample/dir.rb +sample/evaldef.rb +sample/export.rb +sample/exyacc.rb +sample/fib.awk +sample/fib.pl +sample/fib.rb +sample/fib.scm +sample/freq.rb +sample/from.rb +sample/fullpath.pl +sample/fullpath.rb +sample/getopts.test +sample/io.rb +sample/less.rb +sample/list.rb +sample/list2.rb +sample/list3.rb +sample/marshal.rb +sample/mkproto.rb +sample/mpart.rb +sample/occur.pl +sample/occur.rb +sample/occur2.rb +sample/rcs.awk +sample/rcs.dat +sample/rcs.rb +sample/ruby-mode.el +sample/sieve.rb +sample/svr.rb +sample/test.rb +sample/time.rb +sample/tkbiff.rb +sample/tkbrowse.rb +sample/tkdialog.rb +sample/tkfrom.rb +sample/tkhello.rb +sample/tkline.rb +sample/tktimer.rb +sample/trojan.pl +sample/trojan.rb +sample/uumerge.rb diff --git a/Makefile.in b/Makefile.in index 9f804f1706..81e3feca79 100644 --- a/Makefile.in +++ b/Makefile.in @@ -13,21 +13,23 @@ INSTALL_DATA = @INSTALL_DATA@ PURIFY= @SET_MAKE@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ -I. STATIC = @STATIC@ LDFLAGS = $(CFLAGS) @LDFLAGS@ -LIBS = @LIBS@ +LIBS = -lm @LIBS@ $(EXTLIBS) MISSING = @LIBOBJS@ @ALLOCA@ prefix = @prefix@ binprefix = exec_prefix = @exec_prefix@ bindir = $(exec_prefix)/bin +libdir = @prefix@/lib/ruby #### End of system configuration section. #### +EXTOBJS = dmyext.o + OBJS = array.o \ - assoc.o \ bignum.o \ class.o \ compar.o \ @@ -35,7 +37,6 @@ OBJS = array.o \ dln.o \ enum.o \ error.o \ - etc.o \ eval.o \ file.o \ fnmatch.o \ @@ -65,41 +66,49 @@ OBJS = array.o \ util.o \ variable.o \ version.o \ - $(MISSING) + $(MISSING) \ + $(EXTOBJS) + +PROGRAM = miniruby -PROGRAM = ruby +all: extruby -all: $(PROGRAM) @EXTMAKE@ +extruby: miniruby ext/Setup + @if test -z "$$UNDER_EXTMAKE_RB"; \ + then echo "Compiling ext modules"; \ + UNDER_EXTMAKE_RB=yes; export UNDER_EXTMAKE_RB; \ + cd ext; ../miniruby ./extmk.rb; fi $(PROGRAM): $(OBJS) @rm -f $(PROGRAM) $(PURIFY) $(CC) $(STATIC) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM) -extmake:; @echo "Compiling ext modules"; \ - for extdir in ext/*; do \ - test -d $$extdir || continue; \ - test -f $$extdir/MANIFEST || continue; \ - echo `basename $$extdir`; \ - ( cd $$extdir; ../../ruby ../extmk.rb; );\ - done +$(bindir)/ruby: extruby + $(INSTALL_PROGRAM) ruby $(bindir)/ruby + strip $(bindir)/ruby -$(bindir)/$(PROGRAM): $(PROGRAM) - $(INSTALL_PROGRAM) $(PROGRAM) $(bindir)/$(PROGRAM) - -install: $(bindir)/$(PROGRAM) +install: $(bindir)/ruby + cd ext; ../miniruby ./extmk.rb install + $(INSTALL_DATA) lib/*.rb $(libdir) clean:; @rm -f $(OBJS) - @for extdir in ext/*; do \ - test -d $$extdir || continue; \ - test -f $$extdir/MANIFEST || continue; \ - if test -f $$extdir/Makefile; then \ - ( cd $$extdir; make clean ); \ - fi; \ - done + @rm -f ext/extinit.c ext/extinit.o + cd ext; ../ruby ./extmk.rb install realclean: clean - @rm -f ext/extmk.rb - @rm -f core ruby *~ config.* Makefile + @rm -f Makefile ext/extmk.rb + @rm -f config.cache config.h config.log config.status + @rm -f core ruby miniruby *~ + +test:; @-./ruby sample/test.rb > ./ruby_test 2>&1;\ + if grep '^end of test' ./ruby_test > /dev/null; then \ + echo "test succeeded"; \ + else \ + grep '^sample/test.rb' ./ruby_test; \ + grep '^not' ./ruby_test; \ + echo "test failed";\ + fi;\ + rm -f ./ruby_test .c.o: $(CC) $(CFLAGS) $(CPPFLAGS) -c $< @@ -107,12 +116,21 @@ realclean: clean alloca.o: missing/alloca.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/alloca.c +crypt.o: missing/crypt.c + $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/crypt.c + +dup2.o: missing/dup2.c + $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/dup2.c + memmove.o: missing/memmove.c $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/memmove.c mkdir.o: missing/mkdir.c $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/mkdir.c +setenv.o: missing/setenv.c + $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/setenv.c + strerror.o: missing/strerror.c $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strerror.c @@ -131,47 +149,49 @@ strtol.o: missing/strtol.c strtoul.o: missing/strtoul.c $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strtoul.c +nt.o: missing/nt.c + $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/nt.c + # Prevent GNU make v3 from overflowing arg limit on SysV. .NOEXPORT: ### -parse.o : parse.y ruby.h defines.h config.h env.h node.h st.h ident.h regex.h +parse.o : parse.y ruby.h defines.h config.h env.h node.h st.h regex.h ### array.o: array.c ruby.h config.h defines.h bignum.o: bignum.c ruby.h config.h defines.h -class.o: class.c ruby.h config.h defines.h env.h node.h st.h +class.o: class.c ruby.h config.h defines.h node.h st.h compar.o: compar.c ruby.h config.h defines.h -cons.o: cons.c ruby.h config.h defines.h dir.o: dir.c ruby.h config.h defines.h dln.o: dln.c config.h defines.h dln.h +dmyext.o: dmyext.c +dummy.o: dummy.c config.h dln.c defines.h dln.h enum.o: enum.c ruby.h config.h defines.h error.o: error.c ruby.h config.h defines.h env.h -etc.o: etc.c ruby.h config.h defines.h -eval.o: eval.c ruby.h config.h defines.h ident.h env.h node.h st.h dln.h -file.o: file.c ruby.h config.h defines.h io.h +eval.o: eval.c ruby.h config.h defines.h env.h node.h sig.h st.h dln.h +file.o: file.c ruby.h config.h defines.h io.h sig.h fnmatch.o: fnmatch.c config.h fnmatch.h -gc.o: gc.c ruby.h config.h defines.h env.h st.h node.h +gc.o: gc.c ruby.h config.h defines.h env.h st.h node.h re.h regex.h glob.o: glob.c config.h fnmatch.h hash.o: hash.c ruby.h config.h defines.h st.h inits.o: inits.c ruby.h config.h defines.h -io.o: io.c ruby.h config.h defines.h io.h +io.o: io.c ruby.h config.h defines.h io.h sig.h main.o: main.c math.o: math.c ruby.h config.h defines.h numeric.o: numeric.c ruby.h config.h defines.h env.h -object.o: object.c ruby.h config.h defines.h env.h st.h +object.o: object.c ruby.h config.h defines.h st.h pack.o: pack.c ruby.h config.h defines.h -process.o: process.c ruby.h config.h defines.h st.h +process.o: process.c ruby.h config.h defines.h sig.h st.h random.o: random.c ruby.h config.h defines.h range.o: range.c ruby.h config.h defines.h re.o: re.c ruby.h config.h defines.h re.h regex.h regex.o: regex.c config.h defines.h regex.h util.h ruby.o: ruby.c ruby.h config.h defines.h re.h regex.h dln.h -signal.o: signal.c ruby.h config.h defines.h +signal.o: signal.c ruby.h config.h defines.h sig.h sprintf.o: sprintf.c ruby.h config.h defines.h st.o: st.c config.h st.h string.o: string.c ruby.h config.h defines.h re.h regex.h struct.o: struct.c ruby.h config.h defines.h env.h -tclglob.o: tclglob.c time.o: time.c ruby.h config.h defines.h util.o: util.c defines.h config.h util.h -variable.o: variable.c ruby.h config.h defines.h env.h ident.h st.h +variable.o: variable.c ruby.h config.h defines.h env.h st.h version.o: version.c ruby.h config.h defines.h version.h @@ -1,73 +1,153 @@ -.\" README - -*- Text -*- created at: Wed Aug 3 11:57:36 JST 1994 +* RubyȤ -ѥ롦ȡ +Rubyϥץ뤫ĶϤʥ֥ȻظץȸǤ +RubyϺǽ餫ʥ֥ȻظȤ߷פƤ +顤֥Ȼظץߥڤ˹Ԥ +̾μ³ΥץߥǽǤ - 1. configure¹ԤMakefile. - 2. (ɬפʤ)defines.hԽ. - 3. make¹Ԥƥѥ뤹 - 4. make install +RubyϥƥȽطǽϤʤɤͥ졤perlƱ餤 +Ǥ˥ץʸˡȡ㳰䥤ƥ졼ʤɤε +ˤäơʬ䤹ץߥޤ - ⤷, ѥ˥顼ȯˤϥ顼Υȥ - , OSμޤǤܤݡȤԤäƤ - . +* RubyĹ -ǽɲ + + ץʸˡ + + ̤Υ֥Ȼظǽ(饹åɥʤ) + + üʥ֥Ȼظǽ(Mixin, ðۥåɤʤ) + + 黻ҥС + + 㳰ǽ + + ƥ졼ȥ + + ١쥯 + + ʥߥåǥ (ƥˤ) + + ܿ⤤¿UNIXư - CɤȤˤä, ñruby˵ǽɲäǤ. - Τޤʼϰʲ̤Ǥ. +* ˡ - * ؿŪåɤɲä +** ftp - (1) CǴؿ - (2) rb_define_method()ǥͥ륯饹ΥåɤȤƴ - rubyϿؿ - (3) init.cԽ, ϿؿƤӽФ +ʲξˤƤޤ - * 饹ɲä + ftp://ftp.kk.info.kanagawa-u.ac.jp/pub/languages/ruby/ - (1) 饹߷פ - (2) åɤCǵҤ - (3) rb_define_class()ǥ饹륳ɤ - (4) rb_define_method()ǥåɤϿ륳ɤ - (5) init.cԽ, ؿƤӽФ +** ᥤ - ܤC-IF. +ʲΥɥ쥹`send'ȤSubjectΥᥤäƲ -ܿ + ruby-archive@caelum.co.jp - UNIXǤconfigureۤȤɤκۤۼƤϤ - , פ̸Ȥä(˰㤤ʤ), Ԥ˥ - ݡȤ, Ǥ뤫Τʤ. +ʸˤϲƤޤޤ֤ǿǤruby +ޤ - ƥˤäȤ¸ΤGCǤ. rubyGC - оݤΥƥ㤬setjmp()ˤä, ƤΥ쥸 - jmp_buf˳Ǽ뤳Ȥ, jmp_bufȥå32bit饤 - ȤƤ뤳ȤꤷƤ. Ԥ¤Ǥʤ - ܿϺˤ. Ԥϳȴñ˲Ǥ. gc.c - Υåޡʬ˥饤ȤΥХȿ - 餷ƥޡ륳ɤɲäǺѤ. +* ᥤꥹ - sparcʳΥ쥸ɥCPUǤ, 쥸 - ɥեå夹륳ɤɲäɬפ뤫Τʤ. + Ruby˴ؤΤΥᥤꥹȤ⤷ޤ + ɥ쥹 -۾ + ruby-list@caelum.co.jp - RubyϺǽŪˤGNU Public Licenseˤäۤ - ͽ, Ǥϰʲξۤ. + ǤΥɥ쥹˥ᥤСưŪϿޤ - * +* ѥ롦ȡ - ʤŪǤ켫ͳǤ. , ХϺԤؤ - եɥХåԤ(ǤϤʤ) +ʲμǹԤäƤ - * ¾Υץؤΰ + 1. configure¹ԤMakefileʤɤ - ʤŪǤ켫ͳǤ. , ۤɤ˴ - ޤ¾κԤˤ륳ɤ, 줾κԤΰոˤ - ¤ä. + 2. (ɬפʤ)defines.hԽ - * + ¿ʬɬ̵Ȼפޤ - ػߤ. ꤷͤϺԤľϢȤ뤳. - Rubyθͤʾ֤ΤޤήۤΤ¤ - 뤿Ǥ, ͤꤷǺۼͳȤ. + 3. (ɬפʤ)ext/SetupŪ˥ĥ⥸塼 + ꤹ + + ext/Setup˵Ҥ⥸塼Ū˥ޤ + + ʥߥåǥݡȤƤʤƥ + ǤSetup1ܤΡoption nodynamicפȤԤΥ + ȤɬפޤޤΥƥ + ĥ⥸塼Ѥ뤿ˤϡ餫Ū˥ + Ƥɬפޤ + + 4. make¹Ԥƥѥ뤹 + + 5. make testǥƥȤԤ + + test succeededפɽǤ + + 6. make install + +⤷ѥ˥顼ȯˤϥ顼Υȥ +OSμޤǤܤݡȤԤäƤ +¾Τˤʤޤ + +* ܿ + +UNIXǤconfigureۤȤɤκۤۼƤϤ +פ̸Ȥä(˰㤤ʤ)Ԥˤ +ȤݡȤСǤ뤫Τޤ + +ƥˤäȤ¸ΤGCǤrubyGCо +Υƥ㤬setjmp()ˤäơƤΥ쥸 jmp_buf +˳Ǽ뤳Ȥȡjmp_bufȥå32bit饤Ȥ +Ƥ뤳ȤꤷƤޤԤΩʤбϺ +ˤǤ礦ԤβŪñǡgc.cǥå +ޡƤʬ˥饤ȤΥХȿ餷ƥޡ +륳ɤɲäǺѤߤޤdefined(THINK_C)פ +ƤʬͤˤƤ + +# ºݤˤrubyThink CǥѥǤޤ + +sparcʳΥ쥸ɥCPUǤϡ쥸 +եå夹륳ɤɲäɬפ뤫Τޤ + +* ۾ + +Rubyۤ˴ؤݻԤǤ<matz@caelum.co.jp> +ϰʲξĤޤ + + + + + ʤŪǤ켫ͳǤǽĥХ + ԤؤΥեɥХåԤޤ(ǤϤ + ޤ) + + + ¾Υץؤΰ + + ʤŪǤ켫ͳǤruby˴ޤޤ¾κ + Ԥˤ륳ɤϡ줾κԤΰոˤ¤ä + ޤŪˤgc.c()regex.[ch]fnmatch.[ch] + glob.c, st.[ch]missingǥ쥯ȥ겼Υե뷲 + ޤ + + + + + ֤ۤݻ¤꼫ͳǤѹԤäΤ + ۤ뤳Ȥ˾ˤϺԤϢƤ + ʥrubyΤ˶̤Ǥ褦ǤСۤǧ + ˤǤ + + ѹԤʤʤrubyѥ뤷Хʥۤ϶ػ + ޤѥ˵ȥ֥餹 + ˡѥξǤܤ˾ + ޤ + + + RubyץȤθ + + ƤrubyץȤθϤ줾Ԥ°ޤ + ԤϤ˴ؤưڤθĥޤޤruby + Ȥ߹िγĥ⥸塼˴ؤƤƱͤǤ + + + ̵ݾ + + Ruby̵ݾڤǤԤrubyݡȤջ֤Ϥޤ + rubyȤΥХ뤤rubyץȤΥХʤɤȯ + 뤤ʤ»ФƤǤޤ + +* + +ȡХݡȤ¾ matz@caelum.co.jp ޤǡ +------------------------------------------------------- +created at: Thu Aug 3 11:57:36 JST 1995 +Local variables: +mode: indented-text +end: diff --git a/README.EXT b/README.EXT new file mode 100644 index 0000000000..efa627a24a --- /dev/null +++ b/README.EXT @@ -0,0 +1,308 @@ +.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995 + +Rubyĥ뤿ˡ⤹롥 + +RubyCɤȤˤäơñ˵ǽɲäǤ롥ޤʼ +ϰʲ̤Ǥ롥 + + 1. եѰդ + + extǥ쥯ȥβ˳ĥ⥸塼ѤΥǥ쥯ȥѰդơ + ۲˰ʲΥեѰդɬפ롥 + + + MANIFESTɬפʥեΰ + + ɬɬסŪʥեʳƤΥե̾11ե + ηǵҤ뤳ȡ + + + CΥե롥 + + ⥸塼뤬1եʤϥ⥸塼̾Ʊ̾Υե + ̾(⥸塼.c)Ĥ롥դ˥⥸塼뤬ʣʤ + ⥸塼̾ΤĤե뤳ȡ + + + extconf.rb(optional)ѥե롥 + + ؿ饤֥ꡤإå¸ߥåꡤ⥸塼̾ + ɤꤹ롥Υե뤬̵ƥǥեȤǥѥ + 롥 + + + depend(optional)Makefile˥롼ɤ뤿Υե + ΰ¸طҤե롥 + + `gcc -MM *.c > depend'ȤмưŪǤ롥 + + 2. CΥեѰդ + + ɬInit_⥸塼̾פȤؿѰդǡѿ䥯 + 䡤饹ؤΥåɤϿʤɤνԤȡ + ؿθƤӽФϥץν(Ūξ)⥸塼 + Υɻ(ưŪξ)˼ưŪ˹Ԥ롥 + +* Ruby API + +C줫RubyεǽѤAPIϰʲ̤Ǥ롥 + +** + + VALUE + + Ruby֥Ȥɽ뷿ɬפ˱ƥ㥹ȤѤ롥Ȥ + ߷ɽCηruby.h˵ҤƤRǻϤޤ빽¤ΤǤ롥 + VALUE˥㥹Ȥ뤿RǻϤޤ빽¤̾ʸ + ̾ΥޥѰդƤ롥 + +** ѿ + + Qnil + + : nil֥ + + Qself + + ѿ: ߤself֥Ȥ̤͡˥åɤˤselfؤ + ͿΤ, ѿ˥ɬפϤʤѿͤ + ѹϰʸselfͤΤΤѤäƤޤΤ, ̤ʻ + ʤ¤ƤϤʤʤ + + TRUE + + : t֥(Υǥե) + + FALSE + + : nil֥ + +** CǡΥץ벽 + + VALUE data_new(void *sval, void (*mark)(), void (*free)()) + + CǤդΥݥץ벽ruby֥Ȥ֤Υݥ + ruby饢ʤʤäfreeǻꤷؿƤФ롥 + ޤΥݥλؤǡ¾ruby֥ȤؤƤ + 硤mark˻ꤹؿǥޡɬפ롥 + + Make_Data_Struct(obj, iv, type, mark, free, sval) + + typeΥmallocѿsval塤ץ벽 + ǡobjΥѿivޥ + + Get_Data_Struct(obj, iv, type, sval) + + objΥѿivؤǡtypeΥݥФ + ѿsvalޥ + +** 饹/⥸塼 + + VALUE rb_define_class(char *name, VALUE super) + + superΥ֥饹ȤƿRuby饹롥 + + VALUE rb_define_module(char *name) + + Ruby⥸塼롥 + + void rb_include_module(VALUE class, VALUE module) + + ⥸塼롼ɤ롥classǤmodule롼ɤ + ˤϲ⤷ʤ(¿ť롼ɤζػ) + + void rb_extend_object(VALUE object, VALUE module) + + ֥Ȥ⥸塼(Ƥå)dzĥ롥 + +** ѿ + + void rb_define_variable(char *name, VALUE *var) + + RubyCȤǶͭ륰Хѿ롥ѿ̾`$'ǻϤޤ + ˤϼưŪɲä롥nameȤrubyμ̻ҤȤƵʤ + ʸ(㤨` ')ޤˤrubyץफϸʤʤ롥 + + void rb_define_readonly_variable(char *name, VALUE *var) + + RubyCȤǶͭread onlyΥХѿ롥read only + 뤳Ȱʳrb_define_variable()Ʊ + + void rb_define_virtual_variable(char *name, + VALUE (*getter)(), VALUE (*setter)()) + + ؿˤäƼ¸Rubyѿ롥ѿȤ줿ˤ + getterؿͤåȤ줿ˤsetterƤФ롥 + + void rb_define_hooked_variable(char *name, VALUE *var, + VALUE (*getter)(), VALUE (*setter)()) + + ؿˤähookΤĤ줿Хѿ롥ѿȤ + 줿ˤgetterؿͤåȤ줿ˤsetterƤФ롥 + gettersetter0ꤷˤhookꤷʤΤƱˤʤ롥 + + void rb_global_variable(VALUE *var) + + GCΤᡤRubyץफϥʤ, Ruby֥ + ޤѿޡ롥 + +** 饹 + + void rb_define_const(VALUE class, char *name, VALUE val) + + 饹롥 + +** å + + rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc) + + åɤ롥argcselfοargc-1λ, ؿ + ϰο(selfޤޤʤ)1, 2Ȥ + Ϳ(3self)argc-2λ, self, args(args + ޤruby)ȤͿ롥 + + rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc) + + privateåɤ롥rb_define_method()Ʊ + + rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc) + + ðۥåɤ롥rb_define_method()Ʊ + + rb_scan_args(int atgc, VALUE *argv, 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(char *str) + + ʸrubyȥץȤƥѥ롦¹Ԥ롥 + + ID rb_intern(char *name) + + ʸбID֤ + + char *rb_id2name(ID id) + + IDбʸ֤(ǥХå) + + char *rb_class2name(VALUE class) + + class֤̾(ǥХå)class̾ʤˤ, ֶ + ̾ĥ饹֤̾ + +** ѿ + + VALUE rb_iv_get(VALUE obj, char *name) + + objΥѿͤ롥`@'ǻϤޤʤѿ + Rubyץफ饢Ǥʤֱ줿ץѿˤʤ롥 + + VALUE rb_iv_set(VALUE obj, char *name, VALUE val) + + objΥѿval˥åȤ롥 + +** 湽¤ + + VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2) + + func2֥åȤꤷ, func1ƥ졼ȤƸƤ֡ func1 + arg1ȤϤ, func2ˤ1˥ƥ졼Ϳ + , 2arg2Ϥ롥 + + VALUE rb_yield(VALUE val) + + valͤȤƥƥ졼֥åƤӽФ + + VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2) + + ؿfunc1arg1˸ƤӽФfunc1μ¹㳰ȯ + func2arg2ȤƸƤ֡ͤ㳰ȯʤä + func1, 㳰ȯˤfunc2ͤǤ롥 + + VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2) + + ؿfunc1arg1ȤƼ¹Ԥ, ¹Խλ(Ȥ㳰ȯ + ) func2arg2ȤƼ¹Ԥ롥ͤfunc1ͤǤ( + ȯʤ) + +** 㳰顼 + + void Warning(char *fmt, ...) + + verboseɸ२顼Ϥ˷ٹɽ롥printf()Ʊ + + void Fail(char *fmt, ...) + + 㳰ȯ롥printf()Ʊ + + void Fatal(char *fmt, ...) + + ̿Ū㳰ȯ롥̾㳰ϹԤʤ줺, ץ + λ(ensureǻꤵ줿ɤϽλ˼¹Ԥ) + + void Bug(char *fmt, ...) + + ץʤɥץΥХǤȯϤΤʤλ + Ƥ֡ץϥפľ˽λ롥㳰ϰڹ + ʤʤ + +** rubyν¹ + +RubyץꥱˤϰʲΥեȤ +γĥ⥸塼ˤɬפʤ + + void ruby_init(int argc, char **argv, char **envp) + + rubyץνԤʤ + + void ruby_run() + + rubyץ¹Ԥ롥 + + void ruby_script(char *name) + + rubyΥץ̾($0)ꤹ롥 + +* extconf.rbε + +ĥ⥸塼Υǥ쥯ȥ`extconf.rb'Ȥե뤬¸ߤ +ϡ줬¹Ԥ졤⥸塼ΥѥɬפʾΥåʤɤ +Ԥ롥extconf.rbǤϰʲδؿȤǤ롥 + + have_library(lib, func) + + ؿfuncƤ饤֥lib¸ߤå롥饤֥ + ¸ߤTRUE֤ + + have_func(func) + + ؿfunc¸ߤå롥funcɸǤϥʤ饤֥ + ΤΤǤˤhave_libraryǤΥ饤֥å + Ƥؿ¸ߤTRUE֤ + + have_header(header) + + إåե¸ߤå롥إåե뤬¸ߤTRUE + ֤ + + create_makefile(target) + + ĥ⥸塼ѤMakefile롥δؿƤФʤФΥ + 塼ϥѥ뤵ʤ + +/* + * Local variables: + * fill-column: 70 + * end: + */ @@ -1,10 +1,9 @@ -* Process Class +* threadб +* Hand written parser(recursive decent) * 饹饤֥θľ(UNIX¸餹) * formatǽ * here document * perlΤ褦setuid check -* Ŭڤsignal handling -* rubyѿhookμ¸ * write debugger for ruby * re-write regex code for speed * byte code interpretor @@ -12,7 +12,7 @@ #include "ruby.h" -VALUE C_Array; +VALUE cArray; VALUE rb_to_a(); @@ -20,14 +20,15 @@ VALUE rb_to_a(); VALUE ary_new2(len) + int len; { NEWOBJ(ary, struct RArray); - OBJSETUP(ary, C_Array, T_ARRAY); + OBJSETUP(ary, cArray, T_ARRAY); ary->len = 0; ary->capa = len; if (len == 0) - ary->ptr = Qnil; + ary->ptr = 0; else ary->ptr = ALLOC_N(VALUE, len); @@ -49,7 +50,7 @@ ary_new3(n, va_alist) { va_list ar; struct RArray* ary; - int len, i; + int i; if (n < 0) { Fail("Negative number of items(%d)", n); @@ -80,8 +81,22 @@ ary_new4(n, elts) return (VALUE)ary; } +VALUE +assoc_new(car, cdr) + VALUE car, cdr; +{ + struct RArray* ary; + + ary = (struct RArray*)ary_new2(2); + ary->ptr[0] = car; + ary->ptr[1] = cdr; + ary->len = 2; + + return (VALUE)ary; +} + static VALUE -Sary_new(class) +ary_s_new(class) VALUE class; { NEWOBJ(ary, struct RArray); @@ -95,7 +110,7 @@ Sary_new(class) } static VALUE -Sary_create(argc, argv, class) +ary_s_create(argc, argv, class) int argc; VALUE *argv; VALUE class; @@ -106,7 +121,7 @@ Sary_create(argc, argv, class) ary->len = argc; ary->capa = argc; if (argc == 0) { - ary->ptr = Qnil; + ary->ptr = 0; } else { ary->ptr = ALLOC_N(VALUE, argc); @@ -150,7 +165,7 @@ ary_push(ary, item) } static VALUE -Fary_append(ary, item) +ary_append(ary, item) struct RArray *ary; VALUE item; { @@ -178,7 +193,7 @@ ary_shift(ary) ary->len--; /* sliding items */ - memmove(ary->ptr, ary->ptr+1, sizeof(VALUE)*(ary->len)); + MEMMOVE(ary->ptr, ary->ptr+1, VALUE, ary->len); return top; } @@ -186,16 +201,15 @@ ary_shift(ary) VALUE ary_unshift(ary, item) struct RArray *ary; + int item; { - VALUE top; - if (ary->len >= ary->capa) { ary->capa+=ARY_DEFAULT_SIZE; REALLOC_N(ary->ptr, VALUE, ary->capa); } /* sliding items */ - memmove(ary->ptr+1, ary->ptr, sizeof(VALUE)*(ary->len)); + MEMMOVE(ary->ptr+1, ary->ptr, VALUE, ary->len); ary->len++; return ary->ptr[0] = item; @@ -224,7 +238,6 @@ ary_subseq(ary, beg, len) int beg, len; { struct RArray *ary2; - VALUE *ptr; if (beg < 0) { beg = ary->len + beg; @@ -247,37 +260,42 @@ ary_subseq(ary, beg, len) return (VALUE)ary2; } -extern VALUE C_Range; - -static void -range_beg_end(range, begp, lenp, len) +static VALUE +beg_len(range, begp, lenp, len) VALUE range; int *begp, *lenp; int len; { int beg, end; - beg = rb_iv_get(range, "start"); beg = NUM2INT(beg); - end = rb_iv_get(range, "end"); end = NUM2INT(end); + if (!range_beg_end(range, &beg, &end)) return FALSE; + if (beg < 0) { beg = len + beg; if (beg < 0) beg = 0; } - if (end < 0) { - end = len + end; - if (end < 0) end = 0; + *begp = beg; + if (beg > len) { + *lenp = 0; } - if (beg > end) { - int tmp; - - Warning("start %d is bigger than end %d", beg, end); - tmp = beg; beg = end; end = tmp; + else { + if (end < 0) { + end = len + end; + if (end < 0) end = 0; + } + if (len < end) end = len; + if (beg < end) { + *lenp = 0; + } + else { + *lenp = end - beg +1; + } } - *begp = beg; *lenp = end - beg + 1; + return TRUE; } static VALUE -Fary_aref(argc, argv, ary) +ary_aref(argc, argv, ary) int argc; VALUE *argv; struct RArray *ary; @@ -301,18 +319,18 @@ Fary_aref(argc, argv, ary) } /* check if idx is Range */ - if (obj_is_kind_of(arg1, C_Range)) { + { int beg, len; - range_beg_end(arg1, &beg, &len, ary->len); - return ary_subseq(ary, beg, len); + if (beg_len(arg1, &beg, &len, ary->len)) { + return ary_subseq(ary, beg, len); + } } - return ary_entry(ary, NUM2INT(arg1)); } static VALUE -Fary_index(ary, val) +ary_index(ary, val) struct RArray *ary; VALUE val; { @@ -322,11 +340,11 @@ Fary_index(ary, val) if (rb_equal(ary->ptr[i], val)) return INT2FIX(i); } - return Qnil; + return Qnil; /* should be FALSE? */ } static VALUE -Fary_indexes(ary, args) +ary_indexes(ary, args) struct RArray *ary, *args; { VALUE *p, *pend; @@ -348,7 +366,7 @@ Fary_indexes(ary, args) } static VALUE -Fary_aset(argc, argv, ary) +ary_aset(argc, argv, ary) int argc; VALUE *argv; struct RArray *ary; @@ -397,46 +415,46 @@ Fary_aset(argc, argv, ary) REALLOC_N(ary->ptr, VALUE, ary->capa); } - memmove(ary->ptr+beg+arg3->len, ary->ptr+beg+len, - sizeof(VALUE)*(ary->len-(beg+len))); - memcpy(ary->ptr+beg, arg3->ptr, sizeof(VALUE)*arg3->len); + MEMMOVE(ary->ptr+beg+arg3->len, ary->ptr+beg+len, + VALUE, ary->len-(beg+len)); + MEMCPY(ary->ptr+beg, arg3->ptr, VALUE, arg3->len); ary->len = alen; } return (VALUE)arg3; } /* check if idx is Range */ - if (obj_is_kind_of(arg1, C_Range)) { + { int beg, len; - Check_Type(arg2, T_ARRAY); - range_beg_end(arg1, &beg, &len, ary->len); - if (ary->len < beg) { - len = beg + RARRAY(arg2)->len; - if (len >= ary->capa) { - ary->capa=len; - REALLOC_N(ary->ptr, VALUE, ary->capa); + if (beg_len(arg1, &beg, &len, ary->len)) { + Check_Type(arg2, T_ARRAY); + if (ary->len < beg) { + len = beg + RARRAY(arg2)->len; + if (len >= ary->capa) { + ary->capa=len; + REALLOC_N(ary->ptr, VALUE, ary->capa); + } + MEMZERO(ary->ptr+ary->len, VALUE, beg-ary->len); + MEMCPY(ary->ptr+beg, RARRAY(arg2)->ptr, VALUE, RARRAY(arg2)->len); + ary->len = len; } - MEMZERO(ary->ptr+ary->len, VALUE, beg-ary->len); - MEMCPY(ary->ptr+beg, RARRAY(arg2)->ptr, VALUE, RARRAY(arg2)->len); - ary->len = len; - } - else { - int alen; - - alen = ary->len + RARRAY(arg2)->len - len; - if (alen >= ary->capa) { - ary->capa=alen; - REALLOC_N(ary->ptr, VALUE, ary->capa); + else { + int alen; + + alen = ary->len + RARRAY(arg2)->len - len; + if (alen >= ary->capa) { + ary->capa=alen; + REALLOC_N(ary->ptr, VALUE, ary->capa); + } + + MEMMOVE(ary->ptr+beg+RARRAY(arg2)->len, ary->ptr+beg+len, + VALUE, ary->len-(beg+len)); + MEMCPY(ary->ptr+beg, RARRAY(arg2)->ptr, VALUE, RARRAY(arg2)->len); + ary->len = alen; } - - memmove(ary->ptr+beg+RARRAY(arg2)->len, ary->ptr+beg+len, - sizeof(VALUE)*(ary->len-(beg+len))); - memcpy(ary->ptr+beg, RARRAY(arg2)->ptr, - sizeof(VALUE)*RARRAY(arg2)->len); - ary->len = alen; + return arg2; } - return arg2; } offset = NUM2INT(arg1); @@ -448,7 +466,7 @@ Fary_aset(argc, argv, ary) } static VALUE -Fary_each(ary) +ary_each(ary) struct RArray *ary; { int i; @@ -457,6 +475,7 @@ Fary_each(ary) for (i=0; i<ary->len; i++) { rb_yield(ary->ptr[i]); } + return Qnil; } else { return (VALUE)ary; @@ -464,7 +483,7 @@ Fary_each(ary) } static VALUE -Fary_each_index(ary) +ary_each_index(ary) struct RArray *ary; { int i; @@ -472,10 +491,11 @@ Fary_each_index(ary) for (i=0; i<ary->len; i++) { rb_yield(INT2FIX(i)); } + return Qnil; } static VALUE -Fary_length(ary) +ary_length(ary) struct RArray *ary; { return INT2FIX(ary->len); @@ -505,7 +525,7 @@ ary_join(ary, sep) if (ary->len == 0) return str_new(0, 0); if (TYPE(ary->ptr[0]) == T_STRING) - result = str_clone(ary->ptr[0]); + result = str_dup(ary->ptr[0]); else result = obj_as_string(ary->ptr[0]); @@ -528,7 +548,7 @@ ary_join(ary, sep) } static VALUE -Fary_join(argc, argv, ary) +ary_join_method(argc, argv, ary) int argc; VALUE *argv; struct RArray *ary; @@ -545,7 +565,7 @@ Fary_join(argc, argv, ary) } VALUE -Fary_to_s(ary) +ary_to_s(ary) VALUE ary; { VALUE str = ary_join(ary, OFS); @@ -554,7 +574,7 @@ Fary_to_s(ary) } VALUE -Fary_print_on(ary, port) +ary_print_on(ary, port) struct RArray *ary; VALUE port; { @@ -569,46 +589,31 @@ Fary_print_on(ary, port) return port; } -#define INSPECT_MAX 10 - static VALUE -Fary_inspect(ary) +ary_inspect(ary) struct RArray *ary; { int i, len; - VALUE str; + VALUE s, str; char *p; - ary = (struct RArray*)ary_clone(ary); + if (ary->len == 0) return str_new2("[]"); + str = str_new2("["); + len = 1; - len = ary->len; - for (i=0; i<len; i++) { - if (i > INSPECT_MAX) break; - ary->ptr[i] = rb_funcall(ary->ptr[i], rb_intern("_inspect"), 0, Qnil); + for (i=0; i<ary->len; i++) { + s = rb_funcall(ary->ptr[i], rb_intern("inspect"), 0, 0); + if (i > 0) str_cat(str, ", ", 2); + str_cat(str, RSTRING(s)->ptr, RSTRING(s)->len); + len += RSTRING(s)->len + 2; } - - str = str_new2(", "); - str = ary_join(ary, str); - if (str == Qnil) return str_new2("[]"); - len = RSTRING(str)->len; - if (ary->len > INSPECT_MAX) - str_grow(str, len+5); - else - str_grow(str, len+2); - - p = RSTRING(str)->ptr; - memmove(p+1, p, len); - p[0] = '['; - if (ary->len > INSPECT_MAX) - strcpy(p+len, "...]"); - else - p[len+1] = ']'; + str_cat(str, "]", 1); return str; } static VALUE -Fary_to_a(ary) +ary_to_a(ary) VALUE ary; { return ary; @@ -626,8 +631,8 @@ rb_to_a(obj) return obj; } -static VALUE -Fary_reverse(ary) +VALUE +ary_reverse(ary) struct RArray *ary; { VALUE ary2 = ary_new2(ary->len); @@ -663,7 +668,7 @@ sort_2(a, b) } VALUE -Fary_sort(ary) +ary_sort(ary) struct RArray *ary; { qsort(ary->ptr, ary->len, sizeof(VALUE), iterator_p()?sort_1:sort_2); @@ -671,7 +676,7 @@ Fary_sort(ary) } static VALUE -Fary_delete(ary, item) +ary_delete(ary, item) struct RArray *ary; VALUE item; { @@ -690,7 +695,7 @@ Fary_delete(ary, item) } static VALUE -Fary_delete_if(ary) +ary_delete_if(ary) struct RArray *ary; { int i1, i2; @@ -708,7 +713,7 @@ Fary_delete_if(ary) } static VALUE -Fary_clear(ary) +ary_clear(ary) struct RArray *ary; { ary->len = 0; @@ -716,7 +721,7 @@ Fary_clear(ary) } static VALUE -Fary_fill(argc, argv, ary) +ary_fill(argc, argv, ary) int argc; VALUE *argv; struct RArray *ary; @@ -726,8 +731,8 @@ Fary_fill(argc, argv, ary) VALUE *p, *pend; rb_scan_args(argc, argv, "12", &item, &arg1, &arg2); - if (arg2 == Qnil && obj_is_kind_of(arg1, C_Range)) { - range_beg_end(arg1, &beg, &len, ary->len); + if (arg2 == Qnil && beg_len(arg1, &beg, &len, ary->len)) { + /* beg and len set already */ } else { beg = NUM2INT(arg1); @@ -762,7 +767,7 @@ Fary_fill(argc, argv, ary) } static VALUE -Fary_plus(x, y) +ary_plus(x, y) struct RArray *x, *y; { struct RArray *z; @@ -784,7 +789,7 @@ Fary_plus(x, y) } static VALUE -Fary_times(ary, times) +ary_times(ary, times) struct RArray *ary; VALUE times; { @@ -803,7 +808,7 @@ Fary_times(ary, times) } VALUE -Fary_assoc(ary, key) +ary_assoc(ary, key) struct RArray *ary; VALUE key; { @@ -811,15 +816,16 @@ Fary_assoc(ary, key) p = ary->ptr; pend = p + ary->len; while (p < pend) { - if (TYPE(*p) == T_ASSOC - && rb_equal(RASSOC(*p)->car, key)) + if (TYPE(*p) == T_ARRAY + && RARRAY(*p)->len > 1 + && rb_equal(RARRAY(*p)->ptr[0], key)) return *p; } - return Qnil; + return Qnil; /* should be FALSE? */ } VALUE -Fary_rassoc(ary, value) +ary_rassoc(ary, value) struct RArray *ary; VALUE value; { @@ -827,15 +833,16 @@ Fary_rassoc(ary, value) p = ary->ptr; pend = p + ary->len; while (p < pend) { - if (TYPE(*p) == T_ASSOC - && rb_equal(RASSOC(*p)->cdr, value)) + if (TYPE(*p) == T_ARRAY + && RARRAY(*p)->len > 2 + && rb_equal(RARRAY(*p)->ptr[1], value)) return *p; } - return Qnil; + return Qnil; /* should be FALSE? */ } static VALUE -Fary_equal(ary1, ary2) +ary_equal(ary1, ary2) struct RArray *ary1, *ary2; { int i; @@ -850,7 +857,7 @@ Fary_equal(ary1, ary2) } static VALUE -Fary_hash(ary) +ary_hash(ary) struct RArray *ary; { int i, h; @@ -858,14 +865,14 @@ Fary_hash(ary) h = 0; for (i=0; i<ary->len; i++) { - h += rb_funcall(ary->ptr[i], hash, 0); + h ^= rb_funcall(ary->ptr[i], hash, 0); } h += ary->len; return INT2FIX(h); } static VALUE -Fary_includes(ary, item) +ary_includes(ary, item) struct RArray *ary; VALUE item; { @@ -879,34 +886,34 @@ Fary_includes(ary, item) } static VALUE -Fary_diff(ary1, ary2) +ary_diff(ary1, ary2) struct RArray *ary1, *ary2; { VALUE ary3; - int i, j; + int i; Check_Type(ary2, T_ARRAY); ary3 = ary_new(); for (i=0; i<ary1->len; i++) { - if (Fary_includes(ary2, ary1->ptr[i])) continue; - if (Fary_includes(ary3, ary1->ptr[i])) continue; + if (ary_includes(ary2, ary1->ptr[i])) continue; + if (ary_includes(ary3, ary1->ptr[i])) continue; ary_push(ary3, ary1->ptr[i]); } return ary3; } static VALUE -Fary_and(ary1, ary2) +ary_and(ary1, ary2) struct RArray *ary1, *ary2; { VALUE ary3; - int i, j; + int i; Check_Type(ary2, T_ARRAY); ary3 = ary_new(); for (i=0; i<ary1->len; i++) { - if (Fary_includes(ary2, ary1->ptr[i]) - && !Fary_includes(ary3, ary1->ptr[i])) { + if (ary_includes(ary2, ary1->ptr[i]) + && !ary_includes(ary3, ary1->ptr[i])) { ary_push(ary3, ary1->ptr[i]); } } @@ -914,77 +921,78 @@ Fary_and(ary1, ary2) } static VALUE -Fary_or(ary1, ary2) +ary_or(ary1, ary2) struct RArray *ary1, *ary2; { VALUE ary3; int i; if (TYPE(ary2) != T_ARRAY) { - if (Fary_includes(ary1, ary2)) return (VALUE)ary1; - else return Fary_plus(ary1, ary2); + if (ary_includes(ary1, ary2)) return (VALUE)ary1; + else return ary_plus(ary1, ary2); } ary3 = ary_new(); for (i=0; i<ary1->len; i++) { - if (!Fary_includes(ary3, ary1->ptr[i])) + if (!ary_includes(ary3, ary1->ptr[i])) ary_push(ary3, ary1->ptr[i]); } for (i=0; i<ary2->len; i++) { - if (!Fary_includes(ary3, ary2->ptr[i])) + if (!ary_includes(ary3, ary2->ptr[i])) ary_push(ary3, ary2->ptr[i]); } return ary3; } -extern VALUE C_Kernel; -extern VALUE M_Enumerable; +extern VALUE cKernel; +extern VALUE mEnumerable; +void Init_Array() { - C_Array = rb_define_class("Array", C_Object); - rb_include_module(C_Array, M_Enumerable); - - rb_define_single_method(C_Array, "new", Sary_new, 0); - rb_define_single_method(C_Array, "[]", Sary_create, -1); - rb_define_method(C_Array, "to_s", Fary_to_s, 0); - rb_define_method(C_Array, "_inspect", Fary_inspect, 0); - rb_define_method(C_Array, "to_a", Fary_to_a, 0); - - rb_define_method(C_Array, "print_on", Fary_print_on, 1); - - rb_define_method(C_Array, "==", Fary_equal, 1); - rb_define_method(C_Array, "hash", Fary_hash, 0); - rb_define_method(C_Array, "[]", Fary_aref, -1); - rb_define_method(C_Array, "[]=", Fary_aset, -1); - rb_define_method(C_Array, "<<", Fary_append, 1); - rb_define_method(C_Array, "push", ary_push, 1); - rb_define_method(C_Array, "pop", ary_pop, 0); - rb_define_method(C_Array, "shift", ary_shift, 0); - rb_define_method(C_Array, "unshift", ary_unshift, 1); - rb_define_method(C_Array, "each", Fary_each, 0); - rb_define_method(C_Array, "each_index", Fary_each_index, 0); - rb_define_method(C_Array, "length", Fary_length, 0); - rb_define_alias(C_Array, "size", "length"); - rb_define_method(C_Array, "index", Fary_index, 1); - rb_define_method(C_Array, "indexes", Fary_indexes, -2); - rb_define_method(C_Array, "clone", ary_clone, 0); - rb_define_method(C_Array, "join", Fary_join, -1); - rb_define_method(C_Array, "reverse", Fary_reverse, 0); - rb_define_method(C_Array, "sort", Fary_sort, 0); - rb_define_method(C_Array, "delete", Fary_delete, 1); - rb_define_method(C_Array, "delete_if", Fary_delete_if, 0); - rb_define_method(C_Array, "clear", Fary_clear, 0); - rb_define_method(C_Array, "fill", Fary_fill, -1); - rb_define_method(C_Array, "includes", Fary_includes, 1); - - rb_define_method(C_Array, "assoc", Fary_assoc, 1); - rb_define_method(C_Array, "rassoc", Fary_rassoc, 1); - - rb_define_method(C_Array, "+", Fary_plus, 1); - rb_define_method(C_Array, "*", Fary_times, 1); - - rb_define_method(C_Array, "-", Fary_diff, 1); - rb_define_method(C_Array, "&", Fary_and, 1); - rb_define_method(C_Array, "|", Fary_or, 1); + cArray = rb_define_class("Array", cObject); + rb_include_module(cArray, mEnumerable); + + rb_define_singleton_method(cArray, "new", ary_s_new, 0); + rb_define_singleton_method(cArray, "[]", ary_s_create, -1); + rb_define_method(cArray, "to_s", ary_to_s, 0); + rb_define_method(cArray, "inspect", ary_inspect, 0); + rb_define_method(cArray, "to_a", ary_to_a, 0); + + rb_define_method(cArray, "print_on", ary_print_on, 1); + + rb_define_method(cArray, "==", ary_equal, 1); + rb_define_method(cArray, "hash", ary_hash, 0); + rb_define_method(cArray, "[]", ary_aref, -1); + rb_define_method(cArray, "[]=", ary_aset, -1); + rb_define_method(cArray, "<<", ary_append, 1); + rb_define_method(cArray, "push", ary_push, 1); + rb_define_method(cArray, "pop", ary_pop, 0); + rb_define_method(cArray, "shift", ary_shift, 0); + rb_define_method(cArray, "unshift", ary_unshift, 1); + rb_define_method(cArray, "each", ary_each, 0); + rb_define_method(cArray, "each_index", ary_each_index, 0); + rb_define_method(cArray, "length", ary_length, 0); + rb_define_alias(cArray, "size", "length"); + rb_define_method(cArray, "index", ary_index, 1); + rb_define_method(cArray, "indexes", ary_indexes, -2); + rb_define_method(cArray, "clone", ary_clone, 0); + rb_define_method(cArray, "join", ary_join_method, -1); + rb_define_method(cArray, "reverse", ary_reverse, 0); + rb_define_method(cArray, "sort", ary_sort, 0); + rb_define_method(cArray, "delete", ary_delete, 1); + rb_define_method(cArray, "delete_if", ary_delete_if, 0); + rb_define_method(cArray, "clear", ary_clear, 0); + rb_define_method(cArray, "fill", ary_fill, -1); + rb_define_method(cArray, "includes", ary_includes, 1); + + rb_define_method(cArray, "assoc", ary_assoc, 1); + rb_define_method(cArray, "rassoc", ary_rassoc, 1); + + rb_define_method(cArray, "+", ary_plus, 1); + rb_define_method(cArray, "*", ary_times, 1); + + rb_define_method(cArray, "-", ary_diff, 1); + rb_define_method(cArray, "&", ary_and, 1); + rb_define_method(cArray, "|", ary_or, 1); } diff --git a/assoc.c b/assoc.c deleted file mode 100644 index f3172b3ca0..0000000000 --- a/assoc.c +++ /dev/null @@ -1,150 +0,0 @@ -/************************************************ - - assoc.c - - - $Author: matz $ - $Date: 1995/01/10 10:30:37 $ - created at: Fri Jan 6 10:10:36 JST 1995 - - Copyright (C) 1993-1995 Yukihiro Matsumoto - -************************************************/ - -#include "ruby.h" - -static VALUE C_Assoc; - -static ID eq; - -VALUE rb_to_a(); - -VALUE -assoc_new(car, cdr) - VALUE car, cdr; -{ - NEWOBJ(assoc, struct RAssoc); - OBJSETUP(assoc, C_Assoc, T_ASSOC); - - assoc->car = car; - assoc->cdr = cdr; - - return (VALUE)assoc; -} - -static VALUE -Fassoc_car(assoc) - struct RAssoc *assoc; -{ - return assoc->car; -} - -static VALUE -Fassoc_cdr(assoc) - struct RAssoc *assoc; -{ - return assoc->cdr; -} - -static VALUE -Fassoc_set_car(assoc, val) - struct RAssoc *assoc; - VALUE val; -{ - return assoc->car = val; -} - -static VALUE -Fassoc_set_cdr(assoc, val) - struct RAssoc *assoc; - VALUE val; -{ - return assoc->cdr = val; -} - -static VALUE -Fassoc_equal(assoc1, assoc2) - struct RAssoc *assoc1, *assoc2; -{ - if (TYPE(assoc2) != T_ASSOC) return FALSE; - if (!rb_equal(assoc1->car, assoc2->car)) return FALSE; - return rb_equal(assoc1->cdr, assoc2->cdr); -} - -static VALUE -Fassoc_hash(assoc) - struct RAssoc *assoc; -{ - static ID hash; - int key; - - if (!hash) hash = rb_intern("hash"); - key = rb_funcall(assoc->car, hash, 0, 0); - key ^= rb_funcall(assoc->cdr, hash, 0, 0); - return INT2FIX(key); -} - -static VALUE -Fassoc_to_s(assoc) - struct RAssoc *assoc; -{ - VALUE str1, str2; - static ID to_s; - - if (!to_s) to_s = rb_intern("to_s"); - - str1 = rb_funcall(assoc->car, to_s, 0); - assoc = RASSOC(assoc->cdr); - while (assoc) { - if (TYPE(assoc) != T_ASSOC) { - str2 = rb_funcall(assoc, to_s, 0); - str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); - break; - } - str2 = rb_funcall(assoc->car, to_s, 0); - str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); - assoc = RASSOC(assoc->cdr); - } - - return str1; -} - -static VALUE -Fassoc_inspect(assoc) - struct RAssoc *assoc; -{ - VALUE str1, str2; - static ID inspect; - - if (!inspect) inspect = rb_intern("_inspect"); - - str1 = rb_funcall(assoc->car, inspect, 0, 0); - str2 = rb_funcall(assoc->cdr, inspect, 0, 0); - str_cat(str1, "::", 2); - str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); - - return str1; -} - -extern VALUE C_Kernel; - -Init_Assoc() -{ - C_Assoc = rb_define_class("Assoc", C_Object); - - rb_undef_method(CLASS_OF(C_Assoc), "new"); - rb_undef_method(C_Assoc, "clone"); - - rb_define_method(C_Assoc, "car", Fassoc_car, 0); - rb_define_method(C_Assoc, "cdr", Fassoc_cdr, 0); - - rb_define_method(C_Assoc, "car=", Fassoc_set_car, 1); - rb_define_method(C_Assoc, "cdr=", Fassoc_set_cdr, 1); - - rb_define_method(C_Assoc, "==", Fassoc_equal, 1); - rb_define_method(C_Assoc, "hash", Fassoc_hash, 0); - - rb_define_method(C_Assoc, "to_s", Fassoc_to_s, 0); - rb_define_method(C_Assoc, "_inspect", Fassoc_inspect, 0); - - rb_define_method(C_Kernel, "::", assoc_new, 1); -} @@ -12,8 +12,8 @@ #include <ctype.h> #include <math.h> -extern VALUE C_Integer; -VALUE C_Bignum; +extern VALUE cInteger; +VALUE cBignum; #define BDIGITS(x) RBIGNUM(x)->digits #define BITSPERDIG (sizeof(USHORT)*CHAR_BIT) @@ -23,9 +23,6 @@ VALUE C_Bignum; #define BIGDN(x) ((x) >> BITSPERDIG) #define BIGLO(x) ((x) & (BIGRAD-1)) -#define MAX(a,b) ((a)>(b)?(a):(b)) -#define MIN(a,b) ((a)<(b)?(a):(b)) - static VALUE bignew_1(class, len, sign) VALUE class; @@ -33,7 +30,7 @@ bignew_1(class, len, sign) char sign; { NEWOBJ(big, struct RBignum); - OBJSETUP(big, C_Bignum, T_BIGNUM); + OBJSETUP(big, cBignum, T_BIGNUM); big->sign = sign; big->len = len; BDIGITS(big) = ALLOC_N(USHORT, len); @@ -41,10 +38,10 @@ bignew_1(class, len, sign) return (VALUE)big; } -#define bignew(len,sign) bignew_1(C_Bignum,len,sign) +#define bignew(len,sign) bignew_1(cBignum,len,sign) static VALUE -Sbig_new(class, y) +big_s_new(class, y) VALUE class; struct RBignum *y; { @@ -201,7 +198,7 @@ str2inum(str, base) } if (len <= (sizeof(VALUE)*CHAR_BIT)) { - int result = strtoul(str, Qnil, base); + int result = strtoul(str, 0, base); if (!sign) result = -result; if (FIXABLE(result)) return INT2FIX(result); @@ -283,6 +280,8 @@ big2str(x, base) hbase = 020; } else { + j = 0; + hbase = 0; Fail("bignum cannot treat base %d", base); } @@ -318,7 +317,7 @@ big2str(x, base) } static VALUE -Fbig_to_s(x) +big_to_s(x) struct RBignum *x; { return big2str(x, 10); @@ -345,7 +344,7 @@ big2int(x) } VALUE -Fbig_to_i(x) +big_to_i(x) VALUE x; { int v = big2int(x); @@ -396,14 +395,14 @@ big2dbl(x) } VALUE -Fbig_to_f(x) +big_to_f(x) VALUE x; { return float_new(big2dbl(x)); } static VALUE -Fbig_uminus(x) +big_uminus(x) struct RBignum *x; { VALUE z = big_clone(x); @@ -423,7 +422,12 @@ bigadd(x, y, sign) long num; UINT i, len; - len = MAX(x->len, y->len) + 1; + if (x->len > y->len) { + len = x->len + 1; + } + else { + len = y->len + 1; + } z = (struct RBignum*)bignew(len, sign==y->sign); zds = BDIGITS(z); @@ -486,7 +490,7 @@ bigadd(x, y, sign) } VALUE -Fbig_plus(x, y) +big_plus(x, y) VALUE x, y; { VALUE z; @@ -501,7 +505,7 @@ Fbig_plus(x, y) } VALUE -Fbig_minus(x, y) +big_minus(x, y) VALUE x, y; { if (FIXNUM_P(y)) y = int2big(FIX2INT(y)); @@ -514,7 +518,7 @@ Fbig_minus(x, y) } VALUE -Fbig_mul(x, y) +big_mul(x, y) struct RBignum *x, *y; { UINT i = 0, j; @@ -674,7 +678,7 @@ bigdivmod(x, y, div, mod) } static VALUE -Fbig_div(x, y) +big_div(x, y) VALUE x, y; { VALUE z; @@ -683,13 +687,13 @@ Fbig_div(x, y) else { Check_Type(y, T_BIGNUM); } - bigdivmod(x, y, &z, Qnil); + bigdivmod(x, y, &z, 0); return z; } static VALUE -Fbig_mod(x, y) +big_mod(x, y) VALUE x, y; { VALUE z; @@ -698,13 +702,13 @@ Fbig_mod(x, y) else { Check_Type(y, T_BIGNUM); } - bigdivmod(x, y, Qnil, &z); + bigdivmod(x, y, 0, &z); return z; } static VALUE -Fbig_divmod(x, y) +big_divmod(x, y) VALUE x, y; { VALUE div, mod; @@ -719,10 +723,9 @@ Fbig_divmod(x, y) } VALUE -Fbig_pow(x, y) +big_pow(x, y) VALUE x, y; { - double d1, d2; VALUE z; int n; @@ -739,15 +742,15 @@ Fbig_pow(x, y) while (--n) { while (!(n % 2)) { n = n /2; - x = Fbig_mul(x, x); + x = big_mul(x, x); } - z = Fbig_mul(z, x); + z = big_mul(z, x); } return z; } VALUE -Fbig_and(x, y) +big_and(x, y) struct RBignum *x, *y; { VALUE z; @@ -798,7 +801,7 @@ Fbig_and(x, y) } VALUE -Fbig_or(x, y) +big_or(x, y) struct RBignum *x, *y; { VALUE z; @@ -850,7 +853,7 @@ Fbig_or(x, y) } VALUE -Fbig_xor(x, y) +big_xor(x, y) struct RBignum *x, *y; { VALUE z; @@ -904,7 +907,7 @@ Fbig_xor(x, y) } static VALUE -Fbig_neg(x) +big_neg(x) struct RBignum *x; { VALUE z = big_clone(x); @@ -919,22 +922,22 @@ Fbig_neg(x) return bignorm(z); } -static VALUE Fbig_rshift(); +static VALUE big_rshift(); VALUE -Fbig_lshift(x, y) +big_lshift(x, y) struct RBignum *x; VALUE y; { USHORT *xds, *zds; - UINT shift = NUM2INT(y); + int shift = NUM2INT(y); UINT s1 = shift/(sizeof(USHORT)*CHAR_BIT); UINT s2 = shift%(sizeof(USHORT)*CHAR_BIT); VALUE z; unsigned long num = 0; UINT len, i; - if (shift < 0) return Fbig_rshift(x, INT2FIX(-shift)); + if (shift < 0) return big_rshift(x, INT2FIX(-shift)); xds = BDIGITS(x); len = x->len; z = bignew(len+s1+1, x->sign); @@ -952,19 +955,19 @@ Fbig_lshift(x, y) } static VALUE -Fbig_rshift(x, y) +big_rshift(x, y) struct RBignum *x; VALUE y; { USHORT *xds, *zds; - UINT shift = NUM2INT(y); + int shift = NUM2INT(y); UINT s1 = shift/(sizeof(USHORT)*CHAR_BIT); UINT s2 = shift%(sizeof(USHORT)*CHAR_BIT); VALUE z; unsigned long num = 0; UINT i = x->len, j; - if (shift < 0) return Fbig_lshift(x, INT2FIX(-shift)); + if (shift < 0) return big_lshift(x, INT2FIX(-shift)); if (s1 > x->len) { if (x->sign) return INT2FIX(0); @@ -984,7 +987,7 @@ Fbig_rshift(x, y) } static VALUE -Fbig_aref(x, y) +big_aref(x, y) struct RBignum *x; VALUE y; { @@ -1011,12 +1014,17 @@ Fbig_aref(x, y) } static VALUE -Fbig_cmp(x, y) +big_cmp(x, y) struct RBignum *x, *y; { int xlen = x->len; - Check_Type(x, T_BIGNUM); + if (FIXNUM_P(y)) { + y = (struct RBignum*)int2big(FIX2INT(y)); + } + else { + Check_Type(y, T_BIGNUM); + } if (x->sign > y->sign) return INT2FIX(1); if (x->sign < y->sign) return INT2FIX(-1); if (xlen < y->len) @@ -1032,7 +1040,7 @@ Fbig_cmp(x, y) } static VALUE -Fbig_hash(x) +big_hash(x) struct RBignum *x; { int i, len, key; @@ -1046,7 +1054,7 @@ Fbig_hash(x) } static VALUE -Fbig_coerce(x, y) +big_coerce(x, y) struct RBignum *x; VALUE y; { @@ -1061,7 +1069,7 @@ Fbig_coerce(x, y) } static VALUE -Fbig_abs(x) +big_abs(x) struct RBignum *x; { if (!x->sign) { @@ -1071,32 +1079,33 @@ Fbig_abs(x) return (VALUE)x; } +void Init_Bignum() { - C_Bignum = rb_define_class("Bignum", C_Integer); - rb_define_single_method(C_Bignum, "new", Sbig_new, 1); - - rb_define_method(C_Bignum, "to_s", Fbig_to_s, 0); - rb_define_method(C_Bignum, "coerce", Fbig_coerce, 1); - rb_define_method(C_Bignum, "-@", Fbig_uminus, 0); - rb_define_method(C_Bignum, "+", Fbig_plus, 1); - rb_define_method(C_Bignum, "-", Fbig_minus, 1); - rb_define_method(C_Bignum, "*", Fbig_mul, 1); - rb_define_method(C_Bignum, "/", Fbig_div, 1); - rb_define_method(C_Bignum, "%", Fbig_mod, 1); - rb_define_method(C_Bignum, "divmod", Fbig_divmod, 1); - rb_define_method(C_Bignum, "**", Fbig_pow, 1); - rb_define_method(C_Bignum, "&", Fbig_and, 1); - rb_define_method(C_Bignum, "|", Fbig_or, 1); - rb_define_method(C_Bignum, "^", Fbig_xor, 1); - rb_define_method(C_Bignum, "~", Fbig_neg, 0); - rb_define_method(C_Bignum, "<<", Fbig_lshift, 1); - rb_define_method(C_Bignum, ">>", Fbig_rshift, 1); - rb_define_method(C_Bignum, "[]", Fbig_aref, 1); - - rb_define_method(C_Bignum, "<=>", Fbig_cmp, 1); - rb_define_method(C_Bignum, "hash", Fbig_hash, 0); - rb_define_method(C_Bignum, "to_i", Fbig_to_i, 0); - rb_define_method(C_Bignum, "to_f", Fbig_to_f, 0); - rb_define_method(C_Bignum, "abs_f", Fbig_abs, 0); + cBignum = rb_define_class("Bignum", cInteger); + rb_define_singleton_method(cBignum, "new", big_s_new, 1); + + rb_define_method(cBignum, "to_s", big_to_s, 0); + rb_define_method(cBignum, "coerce", big_coerce, 1); + rb_define_method(cBignum, "-@", big_uminus, 0); + rb_define_method(cBignum, "+", big_plus, 1); + rb_define_method(cBignum, "-", big_minus, 1); + rb_define_method(cBignum, "*", big_mul, 1); + rb_define_method(cBignum, "/", big_div, 1); + rb_define_method(cBignum, "%", big_mod, 1); + rb_define_method(cBignum, "divmod", big_divmod, 1); + rb_define_method(cBignum, "**", big_pow, 1); + rb_define_method(cBignum, "&", big_and, 1); + rb_define_method(cBignum, "|", big_or, 1); + rb_define_method(cBignum, "^", big_xor, 1); + rb_define_method(cBignum, "~", big_neg, 0); + rb_define_method(cBignum, "<<", big_lshift, 1); + rb_define_method(cBignum, ">>", big_rshift, 1); + rb_define_method(cBignum, "[]", big_aref, 1); + + rb_define_method(cBignum, "<=>", big_cmp, 1); + rb_define_method(cBignum, "hash", big_hash, 0); + rb_define_method(cBignum, "to_i", big_to_i, 0); + rb_define_method(cBignum, "to_f", big_to_f, 0); + rb_define_method(cBignum, "abs_f", big_abs, 0); } @@ -11,22 +11,21 @@ ************************************************/ #include "ruby.h" -#include "env.h" #include "node.h" #include "st.h" struct st_table *new_idhash(); extern st_table *rb_class_tbl; -extern VALUE C_Class; -extern VALUE C_Module; +extern VALUE cClass; +extern VALUE cModule; VALUE class_new(super) struct RClass *super; { NEWOBJ(cls, struct RClass); - OBJSETUP(cls, C_Class, T_CLASS); + OBJSETUP(cls, cClass, T_CLASS); cls->super = super; cls->m_tbl = new_idhash(); @@ -35,7 +34,7 @@ class_new(super) } VALUE -single_class_new(super) +singleton_class_new(super) struct RClass *super; { struct RClass *cls = (struct RClass*)class_new(super); @@ -56,13 +55,13 @@ clone_method(mid, body, tbl) } VALUE -single_class_clone(class) +singleton_class_clone(class) struct RClass *class; { if (!FL_TEST(class, FL_SINGLE)) return (VALUE)class; else { - /* copy single(unnamed) class */ + /* copy singleton(unnamed) class */ NEWOBJ(clone, struct RClass); CLONESETUP(clone, class); @@ -81,9 +80,11 @@ rb_define_class_id(id, super) { struct RClass *cls = (struct RClass*)class_new(super); + if (!super) super = (struct RBasic*)cClass; + cls = (struct RClass*)class_new(super); rb_name_class(cls, id); /* make metaclass */ - RBASIC(cls)->class = single_class_new(super?super->class:C_Class); + RBASIC(cls)->class = singleton_class_new(super->class); return (VALUE)cls; } @@ -104,6 +105,7 @@ rb_define_class(name, super) return class; } +VALUE rb_define_class_under(under, name, super) VALUE under; char *name; @@ -124,7 +126,7 @@ VALUE module_new() { NEWOBJ(mdl, struct RClass); - OBJSETUP(mdl, C_Module, T_MODULE); + OBJSETUP(mdl, cModule, T_MODULE); mdl->super = Qnil; mdl->m_tbl = new_idhash(); @@ -158,6 +160,7 @@ rb_define_module(name) return module; } +VALUE rb_define_module_under(under, name) VALUE under; char *name; @@ -176,10 +179,8 @@ static struct RClass * include_class_new(module, super) struct RClass *module, *super; { - struct RClass *p; - NEWOBJ(cls, struct RClass); - OBJSETUP(cls, C_Class, T_ICLASS); + OBJSETUP(cls, cClass, T_ICLASS); cls->m_tbl = module->m_tbl; cls->iv_tbl = module->iv_tbl; @@ -202,8 +203,15 @@ rb_include_module(class, module) if (!module) return; - Check_Type(module, T_MODULE); + switch (TYPE(module)) { + case T_MODULE: + case T_CLASS: + break; + default: + Check_Type(module, T_MODULE); + } + if (class == module) return; if (BUILTIN_TYPE(class) == T_CLASS) { rb_clear_cache(class); } @@ -226,6 +234,16 @@ rb_include_module(class, module) } void +rb_define_method_id(class, name, func, argc) + struct RClass *class; + ID name; + VALUE (*func)(); + int argc; +{ + rb_add_method(class, name, NEW_CFUNC(func, argc), NOEX_PUBLIC); +} + +void rb_define_method(class, name, func, argc) struct RClass *class; char *name; @@ -254,7 +272,7 @@ rb_define_private_method(class, name, func, argc) } VALUE -rb_single_class(obj) +rb_singleton_class(obj) struct RBasic *obj; { switch (TYPE(obj)) { @@ -264,24 +282,24 @@ rb_single_class(obj) case T_STRUCT: break; default: - Fail("can't define single method for built-in class"); + Fail("can't define singleton method for built-in class"); break; } if (FL_TEST(obj->class, FL_SINGLE)) { return (VALUE)obj->class; } - return obj->class = single_class_new(obj->class); + return obj->class = singleton_class_new(obj->class); } void -rb_define_single_method(obj, name, func, argc) +rb_define_singleton_method(obj, name, func, argc) VALUE obj; char *name; VALUE (*func)(); int argc; { - rb_define_method(rb_single_class(obj), name, func, argc); + rb_define_method(rb_singleton_class(obj), name, func, argc); } void @@ -292,7 +310,7 @@ rb_define_module_function(module, name, func, argc) int argc; { rb_define_private_method(module, name, func, argc); - rb_define_single_method(module, name, func, argc); + rb_define_singleton_method(module, name, func, argc); } void @@ -304,37 +322,30 @@ rb_define_alias(class, name1, name2) } void -rb_define_attr(class, name, pub) +rb_define_attr(class, id, pub) struct RClass *class; - char *name; + ID id; int pub; { + char *name; char *buf; ID attr, attreq, attriv; + name = rb_id2name(id); attr = rb_intern(name); buf = ALLOCA_N(char,strlen(name)+2); sprintf(buf, "%s=", name); attreq = rb_intern(buf); sprintf(buf, "@%s", name); attriv = rb_intern(buf); - if (rb_method_boundp(class, attr) == Qnil) { + if (rb_method_boundp(class, attr) == FALSE) { rb_add_method(class, attr, NEW_IVAR(attriv), 0); } - if (pub && rb_method_boundp(class, attreq) == Qnil) { + if (pub && rb_method_boundp(class, attreq) == FALSE) { rb_add_method(class, attreq, NEW_ATTRSET(attriv), 0); } } -void -rb_define_single_attr(obj, name, pub) - VALUE obj; - char *name; - int pub; -{ - rb_define_attr(rb_single_class(obj), name, pub); -} - #include <varargs.h> #include <ctype.h> @@ -409,4 +420,5 @@ rb_scan_args(argc, argv, fmt, va_alist) error: Fail("bad scan arg format: %s", fmt); + return 0; } @@ -12,12 +12,12 @@ #include "ruby.h" -VALUE M_Comparable; +VALUE mComparable; static ID cmp; static VALUE -Fcmp_eq(x, y) +cmp_eq(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); @@ -28,7 +28,7 @@ Fcmp_eq(x, y) } static VALUE -Fcmp_gt(x, y) +cmp_gt(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); @@ -39,7 +39,7 @@ Fcmp_gt(x, y) } static VALUE -Fcmp_ge(x, y) +cmp_ge(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); @@ -50,7 +50,7 @@ Fcmp_ge(x, y) } static VALUE -Fcmp_lt(x, y) +cmp_lt(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); @@ -61,7 +61,7 @@ Fcmp_lt(x, y) } static VALUE -Fcmp_le(x, y) +cmp_le(x, y) VALUE x, y; { VALUE c = rb_funcall(x, cmp, 1, y); @@ -72,7 +72,7 @@ Fcmp_le(x, y) } static VALUE -Fcmp_between(x, min, max) +cmp_between(x, min, max) VALUE x, min, max; { VALUE c = rb_funcall(x, cmp, 1, min); @@ -85,15 +85,16 @@ Fcmp_between(x, min, max) return TRUE; } +void Init_Comparable() { - M_Comparable = rb_define_module("Comparable"); - rb_define_method(M_Comparable, "==", Fcmp_eq, 1); - rb_define_method(M_Comparable, ">", Fcmp_gt, 1); - rb_define_method(M_Comparable, ">=", Fcmp_ge, 1); - rb_define_method(M_Comparable, "<", Fcmp_lt, 1); - rb_define_method(M_Comparable, "<=", Fcmp_le, 1); - rb_define_method(M_Comparable, "between", Fcmp_between, 2); + mComparable = rb_define_module("Comparable"); + rb_define_method(mComparable, "==", cmp_eq, 1); + rb_define_method(mComparable, ">", cmp_gt, 1); + rb_define_method(mComparable, ">=", cmp_ge, 1); + rb_define_method(mComparable, "<", cmp_lt, 1); + rb_define_method(mComparable, "<=", cmp_le, 1); + rb_define_method(mComparable, "between?", cmp_between, 2); cmp = rb_intern("<=>"); } diff --git a/configure.in b/configure.in index 77153b6ed0..fc87754cb8 100644 --- a/configure.in +++ b/configure.in @@ -4,6 +4,23 @@ AC_INIT(ruby.h) PROGS="ruby" AC_SUBST(PROGS)dnl +dnl checks for alternative programs +AC_ARG_WITH(gcc, [--without-gcc never use gcc], [ + case $withval in + no) CC=cc + without_gcc=yes;; + yes) CC=gcc + without_gcc=no;; + *) CC=$withval + without_gcc=$withval;; + esac], [without_gcc=no]) +dnl If the user switches compilers, we can't believe the cache +if test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC" +then + AC_ERROR(cached CC is different -- throw away $cache_file +(it is also a good idea to do 'make clean' before compiling)) +fi + dnl Checks for programs. AC_PROG_CC AC_PROG_GCC_TRADITIONAL @@ -11,16 +28,21 @@ AC_PROG_YACC AC_PROG_INSTALL AC_PROG_MAKE_SET +# checks for UNIX variants that set C preprocessor variables +AC_AIX +AC_MINIX + dnl Checks for libraries. -AC_CHECK_LIB(m, pow) AC_CHECK_LIB(crypt, crypt) -AC_CHECK_LIB(dl, dlopen, [:]) +AC_CHECK_LIB(dl, dlopen, [:]) # Dynamic linking for SunOS/Solaris and SYSV +AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX dnl Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h limits.h sys/file.h sys/ioctl.h sys/time.h unistd.h\ - stdlib.h syscall.h a.out.h string.h utime.h) +AC_CHECK_HEADERS(limits.h sys/file.h sys/ioctl.h pwd.h\ + sys/time.h sys/times.h sys/param.h unistd.h\ + syscall.h a.out.h string.h utime.h memory.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_TYPE_UID_T @@ -34,12 +56,12 @@ AC_TYPE_GETGROUPS AC_TYPE_SIGNAL AC_FUNC_ALLOCA AC_FUNC_VFORK -AC_REPLACE_FUNCS(memmove mkdir strerror strftime\ - strstr strtoul strdup) +AC_REPLACE_FUNCS(dup2 setenv memmove mkdir strerror strftime\ + strstr strtoul strdup crypt) AC_CHECK_FUNCS(fmod killpg random wait4 waitpid syscall getcwd\ + truncate chsize times utimes fcntl\ setruid seteuid setreuid setrgid setegid setregid\ - getpriority sigprocmask dlopen utimes) -AC_CHECK_FUNC(setenv, [], AC_CHECK_FUNCS(putenv)) + getgroups getpriority sigprocmask dlopen) if test "$ac_cv_func strftime" = no; then AC_STRUCT_TIMEZONE AC_TRY_LINK([], @@ -47,89 +69,125 @@ if test "$ac_cv_func strftime" = no; then fi AC_C_BIGENDIAN -AC_MSG_CHECKING(std stdio) -AC_CACHE_VAL(rb_cv_stdstdio, -[AC_TRY_COMPILE([#include <stdio.h>], - [stdin->_cnt > 0;], - rb_cv_stdstdio=yes, - rb_cv_stdstdio=no)]) -AC_MSG_RESULT($rb_cv_stdstdio) -if test "$rb_cv_stdstdio" = yes; then - AC_DEFINE(STDSTDIO) + +AC_MSG_CHECKING([count field in FILE structures]) +AC_CACHE_VAL(rb_cv_fcnt, +[AC_TRY_COMPILE([#include <stdio.h>], + [FILE *f = stdin; f->_cnt = 0;], rb_cv_fcnt="_cnt", ) +if test "$rb_cv_fcnt=" = ""; then + AC_TRY_COMPILE([#include <stdio.h>], + [FILE *f = stdin; f->__cnt = 0;], rb_cv_fcnt="__cnt", ) +fi +if test "$rb_cv_fcnt=" = ""; then + AC_TRY_COMPILE([#include <stdio.h>], + [FILE *f = stdin; f->_r = 0;], rb_cv_fcnt="_r", ) +fi +if test "$rb_cv_fcnt=" = ""; then + AC_TRY_COMPILE([#include <stdio.h>], + [FILE *f = stdin; f->readCount = 0;], rb_cv_fcnt="readCount", ) +fi]) +if test "$rb_cv_fcnt"; then + AC_MSG_RESULT($rb_cv_fcnt) + AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt) +else + AC_MSG_RESULT([not found(OK if using GNU libc)]) fi -AC_MSG_CHECKING(struct passwd) -AC_EGREP_HEADER(pw_change, pwd.h, AC_DEFINE(PW_CHANGE)) -AC_EGREP_HEADER(pw_quota, pwd.h, AC_DEFINE(PW_QUOTA)) -AC_EGREP_HEADER(pw_age, pwd.h, AC_DEFINE(PW_AGE)) -AC_EGREP_HEADER(pw_class, pwd.h, AC_DEFINE(PW_CLASS)) -AC_EGREP_HEADER(pw_comment, pwd.h, AC_DEFINE(PW_COMMENT)) -AC_EGREP_HEADER(pw_expire, pwd.h, AC_DEFINE(PW_EXPIRE)) -AC_MSG_RESULT(done) - -if test "$ac_cv_header_a_out_h" = yes; then + +if test "$ac_cv_func_getpwent" = yes; then + AC_MSG_CHECKING(struct passwd) + AC_EGREP_HEADER(pw_change, pwd.h, AC_DEFINE(PW_CHANGE)) + AC_EGREP_HEADER(pw_quota, pwd.h, AC_DEFINE(PW_QUOTA)) + AC_EGREP_HEADER(pw_age, pwd.h, AC_DEFINE(PW_AGE)) + AC_EGREP_HEADER(pw_class, pwd.h, AC_DEFINE(PW_CLASS)) + AC_EGREP_HEADER(pw_comment, pwd.h, AC_DEFINE(PW_COMMENT)) + AC_EGREP_HEADER(pw_expire, pwd.h, AC_DEFINE(PW_EXPIRE)) + AC_MSG_RESULT(done) +fi + +dnl wheather use dln_a_out ot not +AC_ARG_WITH(dln-a-out, [--with-dln-a-out use dln_a_out if possible], [ + case $withval in + yes) with_dln_a_out=yes;; + *) with_dln_a_out=no;; + esac], [with_dln_a_out=no]) + +if test "$with_dln_a_out" = yes && test "$ac_cv_header_a_out_h" = yes; then + AC_MSG_CHECKING(whether matz's dln works) - cp confdefs.h config.h - AC_CACHE_VAL(rb_cv_mydln, + cat confdefs.h > config.h + AC_CACHE_VAL(rb_cv_dln_a_out, [AC_TRY_COMPILE([ -#define USE_MY_DLN +#define USE_DLN_A_OUT #include "dln.c" ], [], - rb_cv_mydln=yes, - rb_cv_mydln=no)]) - AC_MSG_RESULT($rb_cv_mydln) - if test "$rb_cv_mydln" = yes; then - AC_DEFINE(USE_MY_DLN) + rb_cv_dln_a_out=yes, + rb_cv_dln_a_out=no)]) + AC_MSG_RESULT($rb_cv_dln_a_out) + if test "$rb_cv_dln_a_out" = yes; then + AC_DEFINE(USE_DLN_A_OUT) fi +else + rb_cv_dln_a_out=no fi AC_SUBST(STATIC)dnl AC_SUBST(CCDLFLAGS)dnl -AC_SUBST(LDDLFLAGS)dnl +AC_SUBST(LDSHARED)dnl AC_SUBST(DLEXT)dnl -AC_SUBST(EXTMAKE)dnl -EXTMAKE= STATIC= -if test "$rb_cv_mydln" = yes; then - EXTMAKE=extmake - if test "$HOSTTYPE" = sparc; then - if test "$ac_cv_prog_CC" = gcc; then - STATIC=-static - else - STATIC=-Bstatic - fi +if test "$rb_cv_dln_a_out" = yes; then + if test "$GCC" = yes; then + STATIC=-static + else + STATIC=-Bstatic fi DLEXT=o AC_DEFINE(DLEXT, ".o") CCDLFLAGS= LDCMD= -elif test "$ac_cv_lib_dl" = yes || test "$ac_cv_func_dlopen" = yes; then + +else + AC_CANONICAL_HOST - echo "please mail this value to matz -- $host_os" - EXTMAKE=extmake - DLEXT=so - AC_DEFINE(DLEXT, ".so") - if test "$ac_cv_prog_CC" = gcc; then + case "$host_os" in + hpux*) DLEXT=sl + AC_DEFINE(DLEXT, ".sl");; + *) DLEXT=so + AC_DEFINE(DLEXT, ".so");; + esac + + if test "$GCC" = yes; then CCDLFLAGS=-fpic else case "$host_os" in - hpux*) CCDLFLAGS='+z' ;; + hpux*) CCDLFLAGS='+z';; solaris*|irix*) CCDLFLAGS='-K pic' ;; sunos*) CCDLFLAGS='-pic' ;; svr4*|esix*) CCDLFLAGS='-Kpic' ;; *) CCDLFLAGS='' ;; esac fi + case "$host_os" in - hpux*) LDDLFLAGS='-b' ;; - solaris*) LDDLFLAGS='-G' ;; - sunos*) LDDLFLAGS='-assert nodefinitions' ;; - svr4*|esix*) LDDLFLAGS="-G $LDFLAGS" ;; - *) LDDLFLAGS="" ;; + hpux*) LDSHARED='ld -b' ;; + solaris*) LDSHARED='ld -G' ;; + sunos*) LDSHARED='ld -assert nodefinitions' ;; + svr4*|esix*) LDSHARED="ld -G" ;; + linux*) LDSHARED="gcc-elf -shared" ;; + *) LDSHARED='ld' ;; esac fi -cp confdefs.h config.h +if test "$prefix" = NONE; then + AC_DEFINE_UNQUOTED(RUBY_LIB, ".:${ac_default_prefix}/lib/ruby") +else + AC_DEFINE_UNQUOTED(RUBY_LIB, ".:${prefix}/lib/ruby") +fi + +echo "creating config.h" +cat confdefs.h > config.h + AC_OUTPUT(Makefile ext/extmk.rb) @@ -16,20 +16,10 @@ #define EUC #undef SJIS +#define SAFE_SIGHANDLE -/* define USE_DL to load object file(.o). */ -#define USE_DL - -/* a.out.h or dlopen() needed to load object */ -#if !defined(HAVE_DLOPEN) && !defined(HAVE_A_OUT_H) -# undef USE_DL -#endif - -#ifdef USE_MY_DLN -# define LIBC_NAME "libc.a" -# define DLN_DEFAULT_PATH "/lib:/usr/lib:." +#ifdef NT +#include "missing/nt.h" #endif -#define SAFE_SIGHANDLE - #endif @@ -10,7 +10,6 @@ ************************************************/ -#include <sys/param.h> #include "ruby.h" #include <sys/types.h> @@ -18,10 +17,10 @@ #include <unistd.h> #endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> #else -char *getenv(); +# define MAXPATHLEN 1024 #endif #if HAVE_DIRENT_H @@ -39,9 +38,14 @@ char *getenv(); # if HAVE_NDIR_H # include <ndir.h> # endif +# ifdef NT +# include "missing/dirent.h" +# endif #endif -static VALUE C_Dir; +char *getenv(); + +static VALUE cDir; static ID id_dir; static void @@ -52,7 +56,7 @@ free_dir(dir) } static VALUE -Sdir_open(dir_class, dirname) +dir_s_open(dir_class, dirname) VALUE dir_class; struct RString *dirname; { @@ -66,7 +70,7 @@ Sdir_open(dir_class, dirname) obj = obj_alloc(dir_class); if (!id_dir) id_dir = rb_intern("dir"); - Make_Data_Struct(obj, id_dir, DIR*, Qnil, free_dir, d); + Make_Data_Struct(obj, id_dir, DIR*, 0, free_dir, d); *d = dirp; return obj; @@ -87,7 +91,7 @@ closeddir() } static VALUE -Fdir_each(dir) +dir_each(dir) VALUE dir; { extern VALUE rb_lastline; @@ -103,7 +107,7 @@ Fdir_each(dir) } static VALUE -Fdir_tell(dir) +dir_tell(dir) VALUE dir; { DIR *dirp; @@ -115,7 +119,7 @@ Fdir_tell(dir) } static VALUE -Fdir_seek(dir, pos) +dir_seek(dir, pos) VALUE dir, pos; { DIR *dirp; @@ -126,7 +130,7 @@ Fdir_seek(dir, pos) } static VALUE -Fdir_rewind(dir) +dir_rewind(dir) VALUE dir; { DIR *dirp; @@ -137,7 +141,7 @@ Fdir_rewind(dir) } static VALUE -Fdir_close(dir) +dir_close(dir) VALUE dir; { DIR **dirpp; @@ -151,7 +155,7 @@ Fdir_close(dir) } static VALUE -Sdir_chdir(argc, argv, obj) +dir_s_chdir(argc, argv, obj) int argc; VALUE *argv; VALUE obj; @@ -178,7 +182,7 @@ Sdir_chdir(argc, argv, obj) } static VALUE -Sdir_getwd(dir) +dir_s_getwd(dir) VALUE dir; { extern char *getwd(); @@ -194,7 +198,7 @@ Sdir_getwd(dir) } static VALUE -Sdir_chroot(dir, path) +dir_s_chroot(dir, path) VALUE dir, path; { Check_Type(path, T_STRING); @@ -206,7 +210,7 @@ Sdir_chroot(dir, path) } static VALUE -Sdir_mkdir(argc, argv, obj) +dir_s_mkdir(argc, argv, obj) int argc; VALUE *argv; VALUE obj; @@ -229,7 +233,7 @@ Sdir_mkdir(argc, argv, obj) } static VALUE -Sdir_rmdir(obj, dir) +dir_s_rmdir(obj, dir) VALUE obj; struct RString *dir; { @@ -262,7 +266,7 @@ push_globs(ary, s) free(fnames); } -static int +static void push_braces(ary, s) VALUE ary; char *s; @@ -272,11 +276,11 @@ push_braces(ary, s) char *lbrace, *rbrace; p = s; - lbrace = rbrace = Qnil; + lbrace = rbrace = 0; while (*p) { if (*p == '{' && !lbrace) lbrace = p; if (*p == '}' && lbrace) rbrace = p; - *p++; + p++; } if (lbrace) { @@ -300,7 +304,7 @@ push_braces(ary, s) } static VALUE -Sdir_glob(dir, str) +dir_s_glob(dir, str) VALUE dir; struct RString *str; { @@ -342,31 +346,32 @@ Sdir_glob(dir, str) return ary; } +void Init_Dir() { - extern VALUE M_Enumerable; + extern VALUE mEnumerable; - C_Dir = rb_define_class("Dir", C_Object); + cDir = rb_define_class("Dir", cObject); - rb_include_module(C_Dir, M_Enumerable); + rb_include_module(cDir, mEnumerable); - rb_define_single_method(C_Dir, "open", Sdir_open, 1); + rb_define_singleton_method(cDir, "open", dir_s_open, 1); - rb_define_method(C_Dir,"each", Fdir_each, 0); - rb_define_method(C_Dir,"rewind", Fdir_rewind, 0); - rb_define_method(C_Dir,"tell", Fdir_tell, 0); - rb_define_method(C_Dir,"seek", Fdir_seek, 1); - rb_define_method(C_Dir,"close", Fdir_close, 0); + rb_define_method(cDir,"each", dir_each, 0); + rb_define_method(cDir,"rewind", dir_rewind, 0); + rb_define_method(cDir,"tell", dir_tell, 0); + rb_define_method(cDir,"seek", dir_seek, 1); + rb_define_method(cDir,"close", dir_close, 0); - rb_define_single_method(C_Dir,"chdir", Sdir_chdir, -1); - rb_define_single_method(C_Dir,"getwd", Sdir_getwd, 0); - rb_define_single_method(C_Dir,"pwd", Sdir_getwd, 0); - rb_define_single_method(C_Dir,"chroot", Sdir_chroot, 1); - rb_define_single_method(C_Dir,"mkdir", Sdir_mkdir, -1); - rb_define_single_method(C_Dir,"rmdir", Sdir_rmdir, 1); - rb_define_single_method(C_Dir,"delete", Sdir_rmdir, 1); - rb_define_single_method(C_Dir,"unlink", Sdir_rmdir, 1); + rb_define_singleton_method(cDir,"chdir", dir_s_chdir, -1); + rb_define_singleton_method(cDir,"getwd", dir_s_getwd, 0); + rb_define_singleton_method(cDir,"pwd", dir_s_getwd, 0); + rb_define_singleton_method(cDir,"chroot", dir_s_chroot, 1); + rb_define_singleton_method(cDir,"mkdir", dir_s_mkdir, -1); + rb_define_singleton_method(cDir,"rmdir", dir_s_rmdir, 1); + rb_define_singleton_method(cDir,"delete", dir_s_rmdir, 1); + rb_define_singleton_method(cDir,"unlink", dir_s_rmdir, 1); - rb_define_single_method(C_Dir,"glob", Sdir_glob, 1); - rb_define_single_method(C_Dir,"[]", Sdir_glob, 1); + rb_define_singleton_method(cDir,"glob", dir_s_glob, 1); + rb_define_singleton_method(cDir,"[]", dir_s_glob, 1); } @@ -14,19 +14,25 @@ #include "defines.h" #include "dln.h" +char *dln_argv0; + #if defined(HAVE_ALLOCA_H) && !defined(__GNUC__) #include <alloca.h> #endif +void *xmalloc(); +void *xcalloc(); +void *xrealloc(); + #include <stdio.h> -#include <sys/param.h> #include <sys/file.h> +#include <sys/types.h> #include <sys/stat.h> -#ifdef HAVE_STDLIB_H -# include <stdlib.h> +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> #else -char *getenv(); +# define MAXPATHLEN 1024 #endif #ifdef HAVE_UNISTD_H @@ -35,15 +41,29 @@ char *getenv(); #if defined (HAVE_STRING_H) # include <string.h> -#else /* !HAVE_STRING_H */ +#else # include <strings.h> -#endif /* !HAVE_STRING_H */ +#endif + +char *strdup(); + +char *getenv(); -#ifdef RUBY int eaccess(); + +#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) +/* dynamic load with dlopen() */ +# define USE_DLN_DLOPEN +#endif + +#ifndef FUNCNAME_PATTERN +# if defined(hpux) || defined(__NetBSD__) || defined(__BORLANDC__) +# define FUNCNAME_PATTERN "_Init_%.200s" +# else +# define FUNCNAME_PATTERN "Init_%.200s" +# endif #endif -#ifdef USE_DL static void init_funcname(buf, file) char *buf, *file; @@ -54,7 +74,7 @@ init_funcname(buf, file) for (p = file, slash = p-1; *p; p++) /* Find position of last '/' */ if (*p == '/') slash = p; - sprintf(buf, "init_%s", slash + 1); + sprintf(buf, FUNCNAME_PATTERN, slash + 1); for (p = buf; *p; p++) { /* Delete suffix it it exists */ if (*p == '.') { *p = '\0'; break; @@ -62,83 +82,27 @@ init_funcname(buf, file) } } -# if defined(HAVE_DLOPEN) && !defined(USE_MY_DLN) - -/* dynamic load with dlopen() */ -#include <dlfcn.h> +#ifdef USE_DLN_A_OUT -int -dln_init(file) - char *file; -{ - return 0; -} - -int -dln_load(file) - char *file; -{ - void *handle; - char buf[MAXPATHLEN]; - void (*init_fct)(); - int len = strlen(file); -#ifndef RTLD_LAZY -# define RTLD_LAZY 1 +#ifndef LIBC_NAME +# define LIBC_NAME "libc.a" #endif - strcpy(buf, file); - if (len > 3 - && (buf[len-1] == 'o' || buf[len-1] == 'a') - && buf[len-2] == '.') { - buf[len-1] = 's'; buf[len] = 'o'; buf[len+1] = '\0'; - } - - /* Load file */ - if ((handle = dlopen(buf, RTLD_LAZY)) == NULL) { - return -1; - } - - /* Load the file as an object one */ - init_funcname(buf, file); - - if ((init_fct = (void(*)())dlsym(handle, buf)) == NULL) { - buf[0] = 'I'; /* try Init_.. */ - if ((init_fct = (void(*)())dlsym(handle, buf)) == NULL) { - return -1; - } - } - /* Call the init code */ - (*init_fct)(); - - return 0; -} - -char * -dln_strerror() -{ - return dlerror(); -} - -int -dln_load_lib(lib) - char *lib; -{ - return 0; -} - -# else +#ifndef DLN_DEFAULT_PATH +# define DLN_DEFAULT_PATH "/lib:/usr/lib:." +#endif #include <errno.h> static int dln_errno; #define DLN_ENOEXEC ENOEXEC /* Exec format error */ -#define DLN_ECONFL 101 /* Symbol name conflict */ -#define DLN_ENOINIT 102 /* No inititalizer given */ -#define DLN_EUNDEF 103 /* Undefine symbol remains */ -#define DLN_ENOTLIB 104 /* Not a library file */ -#define DLN_EBADLIB 105 /* Malformed library file */ -#define DLN_EINIT 106 /* Not initialized */ +#define DLN_ECONFL 201 /* Symbol name conflict */ +#define DLN_ENOINIT 202 /* No inititalizer given */ +#define DLN_EUNDEF 203 /* Undefine symbol remains */ +#define DLN_ENOTLIB 204 /* Not a library file */ +#define DLN_EBADLIB 205 /* Malformed library file */ +#define DLN_EINIT 206 /* Not initialized */ static int dln_init_p = 0; @@ -157,8 +121,10 @@ static int dln_init_p = 0; static st_table *sym_tbl; static st_table *undef_tbl; +static int load_lib(); + static int -dln_load_header(fd, hdrp, disp) +load_header(fd, hdrp, disp) int fd; struct exec *hdrp; long disp; @@ -178,13 +144,30 @@ dln_load_header(fd, hdrp, disp) return 0; } +#if defined(sequent) +#define RELOC_SYMBOL(r) ((r)->r_symbolnum) +#define RELOC_MEMORY_SUB_P(r) ((r)->r_bsr) +#define RELOC_PCREL_P(r) ((r)->r_pcrel || (r)->r_bsr) +#define RELOC_TARGET_SIZE(r) ((r)->r_length) +#endif + +/* Default macros */ +#ifndef RELOC_ADDRESS +#define RELOC_ADDRESS(r) ((r)->r_address) +#define RELOC_EXTERN_P(r) ((r)->r_extern) +#define RELOC_SYMBOL(r) ((r)->r_symbolnum) +#define RELOC_MEMORY_SUB_P(r) 0 +#define RELOC_PCREL_P(r) ((r)->r_pcrel) +#define RELOC_TARGET_SIZE(r) ((r)->r_length) +#endif + #if defined(sun) && defined(sparc) /* Sparc (Sun 4) macros */ # undef relocation_info # define relocation_info reloc_info_sparc -# define R_RIGHTSHIFT(r) (reloc_r_rightshift[(r)->r_type]) -# define R_BITSIZE(r) (reloc_r_bitsize[(r)->r_type]) -# define R_LENGTH(r) (reloc_r_length[(r)->r_type]) +# define R_RIGHTSHIFT(r) (reloc_r_rightshift[(r)->r_type]) +# define R_BITSIZE(r) (reloc_r_bitsize[(r)->r_type]) +# define R_LENGTH(r) (reloc_r_length[(r)->r_type]) static int reloc_r_rightshift[] = { 0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 0, 0, 0, }; @@ -197,14 +180,24 @@ static int reloc_r_length[] = { # define R_PCREL(r) \ ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22) # define R_SYMBOL(r) ((r)->r_index) -#else -# define R_LENGTH(r) ((r)->r_length) -# define R_PCREL(r) ((r)->r_pcrel) -# define R_SYMBOL(r) ((r)->r_symbolnum) +#endif + +#if defined(sequent) +#define R_SYMBOL(r) ((r)->r_symbolnum) +#define R_MEMORY_SUB(r) ((r)->r_bsr) +#define R_PCREL(r) ((r)->r_pcrel || (r)->r_bsr) +#define R_LENGTH(r) ((r)->r_length) +#endif + +#ifndef R_SYMBOL +# define R_SYMBOL(r) ((r)->r_symbolnum) +# define R_MEMORY_SUB(r) 0 +# define R_PCREL(r) ((r)->r_pcrel) +# define R_LENGTH(r) ((r)->r_length) #endif static struct relocation_info * -dln_load_reloc(fd, hdrp, disp) +load_reloc(fd, hdrp, disp) int fd; struct exec *hdrp; long disp; @@ -231,7 +224,7 @@ dln_load_reloc(fd, hdrp, disp) } static struct nlist * -dln_load_sym(fd, hdrp, disp) +load_sym(fd, hdrp, disp) int fd; struct exec *hdrp; long disp; @@ -241,7 +234,6 @@ dln_load_sym(fd, hdrp, disp) struct nlist * end; long displ; int size; - st_table *tbl; lseek(fd, N_SYMOFF(*hdrp) + hdrp->a_syms + disp, 0); if (read(fd, &size, sizeof(int)) != sizeof(int)) { @@ -276,7 +268,7 @@ dln_load_sym(fd, hdrp, disp) } static st_table * -dln_sym_hash(hdrp, syms) +sym_hash(hdrp, syms) struct exec *hdrp; struct nlist *syms; { @@ -297,31 +289,29 @@ dln_sym_hash(hdrp, syms) return tbl; } -int +static int dln_init(prog) - char *prog; { char *file; - int fd, size; + int fd; struct exec hdr; struct nlist *syms; - if (dln_init_p == 1) return; + if (dln_init_p == 1) return 0; file = dln_find_exe(prog, NULL); - if (file == NULL) return -1; - if ((fd = open(file, O_RDONLY)) < 0) { + if (file == NULL || (fd = open(file, O_RDONLY)) < 0) { dln_errno = errno; return -1; } - if (dln_load_header(fd, &hdr, 0) == -1) return -1; - syms = dln_load_sym(fd, &hdr, 0); + if (load_header(fd, &hdr, 0) == -1) return -1; + syms = load_sym(fd, &hdr, 0); if (syms == NULL) { close(fd); return -1; } - sym_tbl = dln_sym_hash(&hdr, syms); + sym_tbl = sym_hash(&hdr, syms); if (sym_tbl == NULL) { /* file may be start with #! */ char c = '\0'; char buf[MAXPATHLEN]; @@ -370,8 +360,8 @@ dln_init(prog) return -1; } -long -dln_load_text_data(fd, hdrp, bss, disp) +static long +load_text_data(fd, hdrp, bss, disp) int fd; struct exec *hdrp; int bss; @@ -423,16 +413,14 @@ dln_print_undef() st_foreach(undef_tbl, undef_print, NULL); } -static +static void dln_undefined() { - fprintf(stderr, "dln: Calling undefined function\n"); - dln_print_undef(); -#ifdef RUBY - rb_exit(1); -#else - exit(1); -#endif + if (undef_tbl->num_entries > 0) { + fprintf(stderr, "dln: Calling undefined function\n"); + dln_print_undef(); + rb_exit(1); + } } struct undef { @@ -504,7 +492,7 @@ reloc_undef(no, undef, arg) #if defined(sun) && defined(sparc) datum += undef->reloc.r_addend; datum >>= R_RIGHTSHIFT(&(undef->reloc)); - mask = 1 << R_BITSIZE(&(undef->reloc)) - 1; + mask = (1 << R_BITSIZE(&(undef->reloc))) - 1; mask |= mask -1; datum &= mask; switch (R_LENGTH(&(undef->reloc))) { @@ -527,13 +515,19 @@ reloc_undef(no, undef, arg) #else switch (R_LENGTH(&(undef->reloc))) { case 0: /* byte */ - *address = undef->u.c + datum; + if (R_MEMORY_SUB(&(undef->reloc))) + *address = datum - *address; + else *address = undef->u.c + datum; break; case 1: /* word */ - *(short *)address = undef->u.s + datum; + if (R_MEMORY_SUB(&(undef->reloc))) + *(short*)address = datum - *(short*)address; + else *(short*)address = undef->u.s + datum; break; case 2: /* long */ - *(long *)address = undef->u.l + datum; + if (R_MEMORY_SUB(&(undef->reloc))) + *(long*)address = datum - *(long*)address; + else *(long*)address = undef->u.l + datum; break; } #endif @@ -542,7 +536,7 @@ reloc_undef(no, undef, arg) return ST_DELETE; } -static int +static void unlink_undef(name, value) char *name; long value; @@ -555,7 +549,7 @@ unlink_undef(name, value) } static int -dln_load_1(fd, disp, need_init) +load_1(fd, disp, need_init) int fd; long disp; char *need_init; @@ -571,14 +565,14 @@ dln_load_1(fd, disp, need_init) int init_p = 0; char buf[256]; - if (dln_load_header(fd, &hdr, disp) == -1) return -1; + if (load_header(fd, &hdr, disp) == -1) return -1; if (INVALID_OBJECT(hdr)) { dln_errno = DLN_ENOEXEC; return -1; } - reloc = dln_load_reloc(fd, &hdr, disp); + reloc = load_reloc(fd, &hdr, disp); if (reloc == NULL) return -1; - syms = dln_load_sym(fd, &hdr, disp); + syms = load_sym(fd, &hdr, disp); if (syms == NULL) return -1; sym = syms; @@ -624,7 +618,7 @@ dln_load_1(fd, disp, need_init) sym++; } - block = dln_load_text_data(fd, &hdr, hdr.a_bss + new_common, disp); + block = load_text_data(fd, &hdr, hdr.a_bss + new_common, disp); if (block == 0) goto err_exit; sym = syms; @@ -637,6 +631,7 @@ dln_load_1(fd, disp, need_init) sym->n_value += hdr.a_text + hdr.a_data; case N_TEXT|N_EXT: case N_DATA|N_EXT: + sym->n_value += block; if (st_lookup(sym_tbl, sym->n_un.n_name, &new_sym) != 0 @@ -655,6 +650,12 @@ dln_load_1(fd, disp, need_init) *new_sym = *sym; new_sym->n_un.n_name = strdup(sym->n_un.n_name); st_insert(sym_tbl, new_sym->n_un.n_name, new_sym); + break; + + case N_TEXT: + case N_DATA: + sym->n_value += block; + break; } sym++; } @@ -693,7 +694,7 @@ dln_load_1(fd, disp, need_init) } } /* end.. look it up */ else { /* is static */ - switch (R_SYMBOL(rel) & N_TYPE) { + switch (R_SYMBOL(rel)) { case N_TEXT: case N_DATA: datum = block; @@ -710,7 +711,7 @@ dln_load_1(fd, disp, need_init) #if defined(sun) && defined(sparc) datum += rel->r_addend; datum >>= R_RIGHTSHIFT(rel); - mask = 1 << R_BITSIZE(rel) - 1; + mask = (1 << R_BITSIZE(rel)) - 1; mask |= mask -1; datum &= mask; @@ -748,37 +749,33 @@ dln_load_1(fd, disp, need_init) if (need_init) { int len; + char **libs_to_be_linked = 0; if (undef_tbl->num_entries > 0) { - if (dln_load_lib(libc) == -1) goto err_exit; + if (load_lib(libc) == -1) goto err_exit; } init_funcname(buf, need_init); len = strlen(buf); -#if 1 - sym = syms; - while (sym < end) { + for (sym = syms; sym<end; sym++) { char *name = sym->n_un.n_name; - if (name[0] == '_' && sym->n_value >= block - && ((bcmp (name, "_Init_", 6) == 0 - || bcmp (name, "_init_", 6) == 0) && name[6] != '_')) { - init_p = 1; - ((int (*)())sym->n_value)(); + if (name[0] == '_' && sym->n_value >= block) { + if (strcmp(name+1, "libs_to_be_linked") == 0) { + libs_to_be_linked = (char**)sym->n_value; + } + if (strcmp(name+1, buf) == 0) { + init_p = 1; + ((int (*)())sym->n_value)(); + } } - sym++; } -#else - for (sym = syms; sym<end; sym++) { - char *name = sym->n_un.n_name; - if (name[0] == '_' && sym->n_value >= block - && (name[1] == 'i' || name[1] == 'I') - && bcmp(name+2, buf+1, len-1) == 0) { - init_p = 1; - ((int (*)())sym->n_value)(); + if (libs_to_be_linked && undef_tbl->num_entries > 0) { + while (*libs_to_be_linked) { + load_lib(*libs_to_be_linked); + libs_to_be_linked++; } } -#endif } free(reloc); free(syms); @@ -788,7 +785,7 @@ dln_load_1(fd, disp, need_init) return -1; } if (undef_tbl->num_entries > 0) { - if (dln_load_lib(libc) == -1) goto err_exit; + if (load_lib(libc) == -1) goto err_exit; if (undef_tbl->num_entries > 0) { dln_errno = DLN_EUNDEF; return -1; @@ -804,38 +801,6 @@ dln_load_1(fd, disp, need_init) return -1; } -int -dln_load(file) - char *file; -{ - int fd; - int result; - - if (dln_init_p == 0) { - dln_errno = DLN_ENOINIT; - return -1; - } - result = strlen(file); - if (file[result-1] == 'a') { - return dln_load_lib(file); - } - - fd = open(file, O_RDONLY); - if (fd == -1) { - dln_errno = errno; - return -1; - } - result = dln_load_1(fd, 0, file); - close(fd); - - return result; -} - -struct symdef { - int str_index; - int lib_offset; -}; - static int target_offset; static int search_undef(key, value, lib_tbl) @@ -854,10 +819,15 @@ search_undef(key, value, lib_tbl) return ST_STOP; } +struct symdef { + int str_index; + int lib_offset; +}; + char *dln_library_path = DLN_DEFAULT_PATH; -int -dln_load_lib(lib) +static int +load_lib(lib) char *lib; { char *path, *file; @@ -927,7 +897,7 @@ dln_load_lib(lib) target_offset = -1; st_foreach(undef_tbl, search_undef, lib_tbl); if (target_offset == -1) break; - if (dln_load_1(fd, target_offset, 0) == -1) { + if (load_1(fd, target_offset, 0) == -1) { st_free_table(lib_tbl); free(data); goto badlib; @@ -957,9 +927,9 @@ dln_load_lib(lib) goto badlib; } offset += sizeof(ahdr); - if (dln_load_header(fd, &hdr, offset) == -1) + if (load_header(fd, &hdr, offset) == -1) goto badlib; - syms = dln_load_sym(fd, &hdr, offset); + syms = load_sym(fd, &hdr, offset); if (syms == NULL) goto badlib; sym = syms; end = syms + (hdr.a_syms / sizeof(struct nlist)); @@ -973,7 +943,7 @@ dln_load_lib(lib) if (sym < end) { found++; free(syms); - if (dln_load_1(fd, offset, 0) == -1) { + if (load_1(fd, offset, 0) == -1) { goto badlib; } } @@ -993,6 +963,32 @@ dln_load_lib(lib) return -1; } +static int +load(file) + char *file; +{ + int fd; + int result; + + if (dln_init_p == 0) { + if (dln_init(dln_argv0) == -1) return -1; + } + result = strlen(file); + if (file[result-1] == 'a') { + return load_lib(file); + } + + fd = open(file, O_RDONLY); + if (fd == -1) { + dln_errno = errno; + return -1; + } + result = load_1(fd, 0, file); + close(fd); + + return result; +} + void* dln_sym(name) char *name; @@ -1004,9 +1000,32 @@ dln_sym(name) return NULL; } -char * +#endif /* USE_DLN_A_OUT */ + +#ifdef USE_DLN_DLOPEN +# ifdef __NetBSD__ +# include <nlist.h> +# include <link.h> +# else +# include <dlfcn.h> +# endif +#endif + +#ifdef hpux +#include <errno.h> +#include "dl.h" +#endif + +#ifdef _AIX +#include <ctype.h> /* for isdigit() */ +#include <errno.h> /* for global errno */ +#include <string.h> /* for strerror() */ +#endif + +static char * dln_strerror() { +#ifdef USE_DLN_A_OUT char *strerror(); switch (dln_errno) { @@ -1025,18 +1044,151 @@ dln_strerror() default: return strerror(dln_errno); } +#endif + +#ifdef USE_DLN_DLOPEN + return dlerror(); +#endif } -# endif -void -dln_perror(str) - char *str; +#ifdef _AIX +static void +aix_loaderror(char *pathname) { - fprintf(stderr, "%s: %s\n", str, dln_strerror()); + char *message[8], errbuf[1024]; + int i,j; + + struct errtab { + int errno; + char *errstr; + } load_errtab[] = { + {L_ERROR_TOOMANY, "too many errors, rest skipped."}, + {L_ERROR_NOLIB, "can't load library:"}, + {L_ERROR_UNDEF, "can't find symbol in library:"}, + {L_ERROR_RLDBAD, + "RLD index out of range or bad relocation type:"}, + {L_ERROR_FORMAT, "not a valid, executable xcoff file:"}, + {L_ERROR_MEMBER, + "file not an archive or does not contain requested member:"}, + {L_ERROR_TYPE, "symbol table mismatch:"}, + {L_ERROR_ALIGN, "text allignment in file is wrong."}, + {L_ERROR_SYSTEM, "System error:"}, + {L_ERROR_ERRNO, NULL} + }; + +#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0])) +#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1) + + sprintf(errbuf, "load failed - %.200s ", pathname); + + if (!loadquery(1, &message[0], sizeof(message))) + ERRBUF_APPEND(strerror(errno)); + for(i = 0; message[i] && *message[i]; i++) { + int nerr = atoi(message[i]); + for (j=0; j<LOAD_ERRTAB_LEN ; j++) { + if (nerr == load_errtab[i].errno && load_errtab[i].errstr) + ERRBUF_APPEND(load_errtab[i].errstr); + } + while (isdigit(*message[i])) message[i]++ ; + ERRBUF_APPEND(message[i]); + ERRBUF_APPEND("\n"); + } + errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */ + Fail(errbuf); +return; } +#endif + +void +dln_load(file) + char *file; +{ +#ifdef USE_DLN_A_OUT + if (load(file) == -1) { + goto failed; + } + return; +#else -#endif /* USE_DL */ + char buf[MAXPATHLEN]; + /* Load the file as an object one */ + init_funcname(buf, file); + +#ifdef USE_DLN_DLOPEN +#define DLN_DEFINED + { + void *handle; + void (*init_fct)(); + int len = strlen(file); + +# ifndef RTLD_LAZY +# define RTLD_LAZY 1 +# endif + + /* Load file */ + if ((handle = dlopen(file, RTLD_LAZY)) == NULL) { + goto failed; + } + + if ((init_fct = (void(*)())dlsym(handle, buf)) == NULL) { + goto failed; + } + /* Call the init code */ + (*init_fct)(); + return; + } +#endif /* USE_DLN_DLOPEN */ + +#ifdef hpux +#define DLN_DEFINED + { + shl_t lib = NULL; + int flags; + void (*init_fct)(); + + flags = BIND_DEFERRED; + lib = shl_load(file, flags, 0); + if (lib == NULL) { + char buf[256]; + Fail("Failed to load %.200s", file); + } + shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct); + if (init_fct == NULL) { + shl_findsym(&lib, buf, TYPE_DATA, (void*)&init_fct); + if (init_fct == NULL) { + rb_sys_fail(file); + } + } + (*init_fct)(); + return; + } +#endif /* hpux */ + +#ifdef _AIX +#define DLN_DEFINED + { + void (*init_fct)(); + + init_fct = (void(*)())load(file, 1, 0); + if (init_fct == NULL) { + aix_loaderror(file); + } + (*init_fct)(); + return; + } +#endif /* _AIX */ + +#ifndef DLN_DEFINED + Fail("dynamic link not supported"); +#endif + +#endif /* USE_DLN_A_OUT */ +#ifndef _AIX + failed: + Fail("%s - %s", dln_strerror(), file); +#endif +} static char *dln_find_1(); @@ -1073,6 +1225,8 @@ dln_find_1(fname, path, exe_flag) struct stat st; if (fname[0] == '/') return fname; + if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0) + return fname; for (dp = path;; dp = ++ep) { @@ -1144,22 +1298,7 @@ dln_find_1(fname, path, exe_flag) if (stat(fbuf, &st) == 0) { if (exe_flag == 0) return fbuf; /* looking for executable */ -#ifdef RUBY if (eaccess(fbuf, X_OK) == 0) return fbuf; -#else - { - uid_t uid = getuid(); - gid_t gid = getgid(); - - if (uid == st.st_uid && - (st.st_mode & S_IEXEC) || - gid == st.st_gid && - (st.st_mode & (S_IEXEC>>3)) || - st.st_mode & (S_IEXEC>>6)) { - return fbuf; - } - } -#endif } /* if not, and no other alternatives, life is bleak */ if (*ep == '\0') { @@ -11,16 +11,12 @@ #ifndef DLN_H #define DLN_H -#include <sys/errno.h> - char *dln_find_exe(); char *dln_find_file(); -int dln_init(); -int dln_load(); -int dln_load_lib(); - -char *dln_strerror(); -void dln_perror(); +#ifdef USE_DLN_A_OUT +extern char *dln_argv0; +#endif +void dln_load(); #endif diff --git a/dmyext.c b/dmyext.c new file mode 100644 index 0000000000..4120d493c3 --- /dev/null +++ b/dmyext.c @@ -0,0 +1,4 @@ +void +Init_ext() +{ +} @@ -12,7 +12,7 @@ #include "ruby.h" -VALUE M_Enumerable; +VALUE mEnumerable; static ID id_each, id_match, id_cmp; void @@ -20,11 +20,11 @@ rb_each(obj) VALUE obj; { if (!id_each) id_each = rb_intern("each"); - rb_funcall(obj, id_each, 0, Qnil); + rb_funcall(obj, id_each, 0, 0); } static void -enum_grep(i, arg) +grep_i(i, arg) VALUE i, *arg; { if (!id_match) id_match = rb_intern("=~"); @@ -34,7 +34,7 @@ enum_grep(i, arg) } static void -enum_grep_iter(i, pat) +grep_iter_i(i, pat) VALUE i, pat; { if (!id_match) id_match = rb_intern("=~"); @@ -44,25 +44,25 @@ enum_grep_iter(i, pat) } static VALUE -Fenum_grep(obj, pat) - VALUE obj; +enum_grep(obj, pat) + VALUE obj, pat; { if (iterator_p()) { - rb_iterate(rb_each, obj, enum_grep_iter, pat); + rb_iterate(rb_each, obj, grep_iter_i, pat); return obj; } else { VALUE tmp, arg[2]; arg[0] = pat; arg[1] = tmp = ary_new(); - rb_iterate(rb_each, obj, enum_grep, arg); + rb_iterate(rb_each, obj, grep_i, arg); return tmp; } } static void -enum_find(i, foundp) +find_i(i, foundp) VALUE i; int *foundp; { @@ -73,19 +73,19 @@ enum_find(i, foundp) } static VALUE -Fenum_find(obj) +enum_find(obj) VALUE obj; { int enum_found; enum_found = FALSE; - rb_iterate(rb_each, obj, enum_find, &enum_found); + rb_iterate(rb_each, obj, find_i, &enum_found); return enum_found; } static void -enum_find_all(i, tmp) - VALUE i; +find_all_i(i, tmp) + VALUE i, tmp; { if (rb_yield(i)) { ary_push(tmp, i); @@ -93,20 +93,20 @@ enum_find_all(i, tmp) } static VALUE -Fenum_find_all(obj) +enum_find_all(obj) VALUE obj; { VALUE tmp; tmp = ary_new(); - rb_iterate(rb_each, obj, enum_find_all, Qnil); + rb_iterate(rb_each, obj, find_all_i, 0); return tmp; } static void -enum_collect(i, tmp) - VALUE i; +collect_i(i, tmp) + VALUE i, tmp; { VALUE retval; @@ -117,32 +117,32 @@ enum_collect(i, tmp) } static VALUE -Fenum_collect(obj) +enum_collect(obj) VALUE obj; { VALUE tmp; tmp = ary_new(); - rb_iterate(rb_each, obj, enum_collect, tmp); + rb_iterate(rb_each, obj, collect_i, tmp); return tmp; } static void -enum_reverse(i, tmp) +reverse_i(i, tmp) VALUE i, tmp; { ary_unshift(tmp, i); } static VALUE -Fenum_reverse(obj) +enum_reverse(obj) VALUE obj; { VALUE tmp; tmp = ary_new(); - rb_iterate(rb_each, obj, enum_reverse, tmp); + rb_iterate(rb_each, obj, reverse_i, tmp); return tmp; } @@ -155,7 +155,7 @@ enum_all(i, ary) } static VALUE -Fenum_to_a(obj) +enum_to_a(obj) VALUE obj; { VALUE ary; @@ -167,18 +167,14 @@ Fenum_to_a(obj) } static VALUE -Fenum_sort(obj) +enum_sort(obj) VALUE obj; { - VALUE ary; - - ary = Fenum_to_a(obj); - Fary_sort(ary); - return ary; + return ary_sort(enum_to_a(obj)); } static void -enum_min(i, min) +min_i(i, min) VALUE i, *min; { VALUE cmp; @@ -194,17 +190,17 @@ enum_min(i, min) } static VALUE -Fenum_min(obj) +enum_min(obj) VALUE obj; { VALUE min = Qnil; - rb_iterate(rb_each, obj, enum_min, &min); + rb_iterate(rb_each, obj, min_i, &min); return min; } static void -enum_max(i, max) +max_i(i, max) VALUE i, *max; { VALUE cmp; @@ -220,12 +216,12 @@ enum_max(i, max) } static VALUE -Fenum_max(obj) +enum_max(obj) VALUE obj; { VALUE max = Qnil; - rb_iterate(rb_each, obj, enum_max, &max); + rb_iterate(rb_each, obj, max_i, &max); return max; } @@ -236,7 +232,7 @@ struct i_v_pair { }; static void -enum_index(item, iv) +index_i(item, iv) VALUE item; struct i_v_pair *iv; { @@ -250,21 +246,21 @@ enum_index(item, iv) } static VALUE -Fenum_index(obj, val) - VALUE obj; +enum_index(obj, val) + VALUE obj, val; { struct i_v_pair iv; iv.i = 0; iv.v = val; iv.found = 0; - rb_iterate(rb_each, obj, enum_index, &iv); + rb_iterate(rb_each, obj, index_i, &iv); if (iv.found) return INT2FIX(iv.i); return Qnil; /* not found */ } static void -enum_includes(item, iv) +member_i(item, iv) VALUE item; struct i_v_pair *iv; { @@ -275,20 +271,20 @@ enum_includes(item, iv) } static VALUE -Fenum_includes(obj, val) - VALUE obj; +enum_member(obj, val) + VALUE obj, val; { struct i_v_pair iv; iv.i = 0; iv.v = val; - rb_iterate(rb_each, obj, enum_includes, &iv); + rb_iterate(rb_each, obj, member_i, &iv); if (iv.i) return TRUE; return FALSE; } static void -enum_length(i, length) +length_i(i, length) VALUE i; int *length; { @@ -296,29 +292,31 @@ enum_length(i, length) } static VALUE -Fenum_length(obj) +enum_length(obj) VALUE obj; { int length = 0; - rb_iterate(rb_each, obj, enum_length, &length); + rb_iterate(rb_each, obj, length_i, &length); return INT2FIX(length); } +void Init_Enumerable() { - M_Enumerable = rb_define_module("Enumerable"); - - rb_define_method(M_Enumerable,"to_a", Fenum_to_a, 0); - - rb_define_method(M_Enumerable,"grep", Fenum_grep, 1); - rb_define_method(M_Enumerable,"find", Fenum_find, 0); - rb_define_method(M_Enumerable,"find_all", Fenum_find_all, 0); - rb_define_method(M_Enumerable,"collect", Fenum_collect, 0); - rb_define_method(M_Enumerable,"reverse", Fenum_reverse, 0); - rb_define_method(M_Enumerable,"min", Fenum_min, 0); - rb_define_method(M_Enumerable,"max", Fenum_max, 0); - rb_define_method(M_Enumerable,"index", Fenum_index, 1); - rb_define_method(M_Enumerable,"includes", Fenum_includes, 1); - rb_define_method(M_Enumerable,"length", Fenum_length, 0); + mEnumerable = rb_define_module("Enumerable"); + + rb_define_method(mEnumerable,"to_a", enum_to_a, 0); + + rb_define_method(mEnumerable,"sort", enum_sort, 0); + rb_define_method(mEnumerable,"grep", enum_grep, 1); + rb_define_method(mEnumerable,"find", enum_find, 0); + rb_define_method(mEnumerable,"find_all", enum_find_all, 0); + rb_define_method(mEnumerable,"collect", enum_collect, 0); + rb_define_method(mEnumerable,"reverse", enum_reverse, 0); + rb_define_method(mEnumerable,"min", enum_min, 0); + rb_define_method(mEnumerable,"max", enum_max, 0); + rb_define_method(mEnumerable,"index", enum_index, 1); + rb_define_method(mEnumerable,"member?", enum_member, 1); + rb_define_method(mEnumerable,"length", enum_length, 0); } @@ -11,28 +11,36 @@ #ifndef ENV_H #define ENV_H -extern struct ENVIRON { +extern struct FRAME { int argc; VALUE *argv; ID last_func; struct RClass *last_class; - struct ENVIRON *prev; -} *the_env; + struct FRAME *prev; + char *file; + int line; +} *the_frame; extern struct SCOPE { struct RBasic super; ID *local_tbl; VALUE *local_vars; - int flags; + int flag; } *the_scope; -#define SCOPE_MALLOCED (1<<0) +#define SCOPE_ALLOCA 0 +#define SCOPE_MALLOC 1 extern int rb_in_eval; extern struct RClass *the_class; -#define NOEX_PUBLIC 0 -#define NOEX_PRIVATE 1 +struct RVarmap { + struct RBasic super; + ID id; + VALUE val; + struct RVarmap *next; +}; +extern struct RVarmap *the_dyna_vars; #endif /* ENV_H */ @@ -59,18 +59,6 @@ err_print(fmt, args) } void -yyerror(msg) - char *msg; -{ - static char *f; - static int line; - - if (line == sourceline && strcmp(f, sourcefile) == 0) - return; - f = sourcefile; line = sourceline; - Error("%s", msg); -} - Error(fmt, va_alist) char *fmt; va_dcl @@ -83,6 +71,21 @@ Error(fmt, va_alist) nerrs++; } +int +yyerror(msg) + char *msg; +{ + static char *f; + static int line; + + if (line == sourceline && strcmp(f, sourcefile) == 0) + return; + f = sourcefile; line = sourceline; + Error("%s", msg); + return 0; +} + +void Warning(fmt, va_alist) char *fmt; va_dcl @@ -99,6 +102,7 @@ Warning(fmt, va_alist) va_end(args); } +void Fatal(fmt, va_alist) char *fmt; va_dcl @@ -111,6 +115,7 @@ Fatal(fmt, va_alist) rb_exit(1); } +void Bug(fmt, va_alist) char *fmt; va_dcl @@ -126,6 +131,7 @@ Bug(fmt, va_alist) abort(); } +void Fail(fmt, va_alist) char *fmt; va_dcl @@ -140,16 +146,18 @@ Fail(fmt, va_alist) rb_fail(str_new2(buf)); } +void rb_sys_fail(mesg) char *mesg; { + char *strerror(); char buf[BUFSIZ]; extern int errno; if (mesg == Qnil) - sprintf(buf, "%s\n", strerror(errno)); + sprintf(buf, "%s", strerror(errno)); else - sprintf(buf, "%s - %s\n", strerror(errno), mesg); + sprintf(buf, "%s - %s", strerror(errno), mesg); errno = 0; rb_fail(str_new2(buf)); @@ -167,14 +175,13 @@ static char *builtin_types[] = { "Array", "Fixnum", "Hash", - "Data", - "Method", "Struct", "Bignum", - "Assoc", "Data", + "Match", }; +void WrongType(x, t) VALUE x; int t; @@ -11,9 +11,9 @@ ************************************************/ #include "ruby.h" -#include "ident.h" #include "env.h" #include "node.h" +#include "sig.h" #include <stdio.h> #include <setjmp.h> @@ -24,13 +24,11 @@ # include <string.h> #else char *strchr(); +char *strrchr(); #endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#else -char *getenv(); -#endif +VALUE cProc; +static VALUE proc_call(); static void rb_clear_cache_body(); static void rb_clear_cache_entry(); @@ -48,6 +46,7 @@ struct cache_entry { /* method hash table. */ ID mid; /* method's id */ struct RClass *class; /* receiver's class */ struct RClass *origin; /* where method defined */ + int nargs; /* # of args */ NODE *method; int noex; }; @@ -63,7 +62,7 @@ rb_add_method(class, mid, node, noex) { NODE *body; - if (class == Qnil) class = (struct RClass*)C_Object; + if (class == Qnil) class = (struct RClass*)cObject; if (st_lookup(class->m_tbl, mid, &body)) { Warning("redefine %s", rb_id2name(mid)); rb_clear_cache_body(body); @@ -97,14 +96,13 @@ rb_get_method_body(classp, idp, noexp) ID *idp; int *noexp; { - int pos, i; ID id = *idp; struct RClass *class = *classp; NODE *body; struct RClass *origin; struct cache_entry *ent; - if ((body = search_method(class, id, &origin)) == Qnil) { + if ((body = search_method(class, id, &origin)) == FALSE) { return Qnil; } if (body->nd_body == Qnil) return Qnil; @@ -186,16 +184,30 @@ rb_export_method(class, name, noex) } } -VALUE -rb_method_boundp(class, id) +static VALUE +method_boundp(class, id, ex) struct RClass *class; ID id; + int ex; { - if (rb_get_method_body(&class, &id, 0)) + int noex; + + if (rb_get_method_body(&class, &id, &noex)) { + if (ex && noex == NOEX_PRIVATE) + return FALSE; return TRUE; + } return FALSE; } +VALUE +rb_method_boundp(class, id) + struct RClass *class; + ID id; +{ + return method_boundp(class, id, 0); +} + static void rb_clear_cache_body(body) NODE *body; @@ -251,44 +263,51 @@ extern int nerrs; extern VALUE TopSelf; VALUE Qself; -#define PUSH_SELF(s) { \ - VALUE __saved_self__ = Qself; \ - Qself = s; \ +#define PUSH_SELF(s) { \ + VALUE __saved_self__ = Qself; \ + Qself = s; \ #define POP_SELF() Qself = __saved_self__; } -struct ENVIRON *the_env, *top_env; -struct SCOPE *the_scope, *top_scope; +struct FRAME *the_frame; +struct SCOPE *the_scope; +static struct FRAME *top_frame; +static struct SCOPE *top_scope; -#define PUSH_ENV() { \ - struct ENVIRON _env; \ - _env.prev = the_env; \ - the_env = &_env; \ +#define PUSH_FRAME() { \ + struct FRAME _frame; \ + _frame.prev = the_frame; \ + _frame.file = sourcefile; \ + _frame.line = sourceline; \ + the_frame = &_frame; \ -#define POP_ENV() the_env = _env.prev; } +#define POP_FRAME() the_frame = _frame.prev; } struct BLOCK { NODE *var; NODE *body; VALUE self; - struct ENVIRON env; + struct FRAME frame; struct SCOPE *scope; int level; - VALUE block; int iter; + struct RVarmap *d_vars; struct BLOCK *prev; } *the_block; #define PUSH_BLOCK(v,b) { \ struct BLOCK _block; \ _block.level = tag_level; \ - _block.var=v; \ + _block.var = v; \ _block.body = b; \ _block.self = Qself; \ - _block.env = *the_env; \ + _block.frame = *the_frame; \ + _block.frame.file = sourcefile; \ + _block.frame.line = sourceline; \ _block.scope = the_scope; \ - _block.block = Qnil; \ + _block.d_vars = the_dyna_vars; \ _block.prev = the_block; \ + _block.iter = iter->iter; \ the_block = &_block; \ #define PUSH_BLOCK2(b) { \ @@ -297,6 +316,51 @@ struct BLOCK { #define POP_BLOCK() the_block = the_block->prev; } +struct RVarmap *the_dyna_vars; +#define PUSH_VARS() { \ + struct RVarmap *_old; \ + _old = the_dyna_vars; + +#define POP_VARS() the_dyna_vars = _old; } + +VALUE +dyna_var_ref(id) + ID id; +{ + struct RVarmap *vars = the_dyna_vars; + + while (vars) { + if (vars->id == id) return vars->val; + vars = vars->next; + } + return Qnil; +} + +VALUE +dyna_var_asgn(id, value) + ID id; + VALUE value; +{ + struct RVarmap *vars = the_dyna_vars; + + while (vars) { + if (vars->id == id) { + vars->val = value; + return; + } + vars = vars->next; + } + { + NEWOBJ(_vars, struct RVarmap); + OBJSETUP(_vars, Qnil, T_VARMAP); + _vars->id = id; + _vars->val = value; + _vars->next = the_dyna_vars; + the_dyna_vars = _vars; + } + return value; +} + static struct iter { int iter; struct iter *prev; @@ -322,7 +386,7 @@ static struct tag { jmp_buf buf; struct gc_list *gclist; VALUE self; - struct ENVIRON *env; + struct FRAME *frame; struct iter *iter; struct tag *prev; } *prot_tag; @@ -331,15 +395,16 @@ static struct tag { struct tag _tag; \ _tag.level= ++tag_level; \ _tag.self = Qself; \ - _tag.env = the_env; \ + _tag.frame = the_frame; \ _tag.iter = iter; \ _tag.prev = prot_tag; \ prot_tag = &_tag; \ #define EXEC_TAG() (setjmp(prot_tag->buf)) + #define JUMP_TAG(val) { \ Qself = prot_tag->self; \ - the_env = prot_tag->env; \ + the_frame = prot_tag->frame; \ iter = prot_tag->iter; \ longjmp(prot_tag->buf,(val)); \ } @@ -372,8 +437,8 @@ struct class_link { class_link = &_link \ #define POP_CLASS() \ - the_class = class_link->class; \ - class_link = _link.prev; } + the_class = class_link->class; \ + class_link = _link.prev; } #define PUSH_SCOPE() { \ struct SCOPE *_old; \ @@ -382,16 +447,24 @@ struct class_link { _old = the_scope; \ the_scope = _scope; \ -#define POP_SCOPE() the_scope = _old; } +#define POP_SCOPE() \ + if (the_scope->flag == SCOPE_ALLOCA) {\ + the_scope->local_vars = 0;\ + the_scope->local_tbl = 0;\ + }\ + the_scope = _old;\ +} static VALUE rb_eval(); -static VALUE Feval(); +static VALUE f_eval(); static VALUE rb_call(); VALUE rb_apply(); VALUE rb_xstring(); void rb_fail(); +VALUE rb_rescue(); + static void module_setup(); static VALUE masign(); @@ -404,20 +477,15 @@ extern VALUE rb_stderr; extern int sourceline; extern char *sourcefile; -VALUE -rb_self() -{ - return Qself; -} - static ID last_func; static void -error_print() +error_print(last_func) + ID last_func; { if (errat) { fwrite(RSTRING(errat)->ptr, 1, RSTRING(errat)->len, stderr); if (last_func) { - fprintf(stderr, ":in method `%s': ", rb_id2name(last_func)); + fprintf(stderr, ":in `%s': ", rb_id2name(last_func)); } else { fprintf(stderr, ": "); @@ -426,34 +494,43 @@ error_print() if (errstr) { fwrite(RSTRING(errstr)->ptr, 1, RSTRING(errstr)->len, stderr); + if (RSTRING(errstr)->ptr[RSTRING(errstr)->len - 1] != '\n') { + putc('\n', stderr); + } } else { fprintf(stderr, "unhandled failure.\n"); } - rb_trap_exit(); - exit(1); } +extern char **environ; +char **origenviron; + void ruby_init(argc, argv, envp) int argc; char **argv, **envp; { int state; - static struct ENVIRON env; - the_env = top_env = &env; + static struct FRAME frame; + the_frame = top_frame = &frame; + + origenviron = environ; +#ifdef NT + NtInitialize(&argc, &argv); +#endif init_heap(); PUSH_SCOPE(); - the_scope->local_vars = Qnil; - the_scope->local_tbl = Qnil; + the_scope->local_vars = 0; + the_scope->local_tbl = 0; top_scope = the_scope; PUSH_TAG(); PUSH_ITER(ITER_NOT); if ((state = EXEC_TAG()) == 0) { rb_call_inits(); - the_class = (struct RClass*)C_Object; + the_class = (struct RClass*)cObject; ruby_options(argc, argv, envp); } POP_ITER(); @@ -466,37 +543,27 @@ ruby_init(argc, argv, envp) exit(FIX2UINT(last_val)); } if (state) { - PUSH_TAG(); - error_print(); - POP_TAG(); + error_print(last_func); } } -VALUE rb_readonly_hook(); - static VALUE Eval() { - VALUE result; + VALUE result = Qnil; NODE *tree; int state; if (!eval_tree) return Qnil; tree = eval_tree; - eval_tree = Qnil; - sourcefile = tree->file; - - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - result = rb_eval(tree); - } - POP_TAG(); - if (state) JUMP_TAG(state); + eval_tree = 0; + result = rb_eval(tree); return result; } +void ruby_run() { int state; @@ -504,13 +571,14 @@ ruby_run() if (nerrs > 0) exit(nerrs); init_stack(); - rb_define_variable("$!", &errstr, Qnil, Qnil, 0); + rb_define_variable("$!", &errstr); errat = Qnil; /* clear for execution */ PUSH_TAG(); PUSH_ITER(ITER_NOT); if ((state = EXEC_TAG()) == 0) { Eval(); + rb_trap_exit(); } POP_ITER(); POP_TAG(); @@ -534,12 +602,10 @@ ruby_run() Fatal("retry outside of protect clause"); break; case TAG_FAIL: - PUSH_TAG(); - error_print(); - POP_TAG(); + error_print(last_func); + exit(1); break; case TAG_EXIT: - rb_trap_exit(); exit(FIX2UINT(last_val)); break; default: @@ -566,11 +632,12 @@ rb_eval_string(str) char *str; { char *oldsrc = sourcefile; - VALUE result; lex_setsrc("(eval)", str, strlen(str)); - eval_tree = Qnil; + eval_tree = 0; + PUSH_VARS(); yyparse(); + POP_VARS(); sourcefile = oldsrc; if (nerrs == 0) { return Eval(); @@ -582,22 +649,30 @@ rb_eval_string(str) } void -rb_trap_eval(cmd) - VALUE cmd; +rb_eval_cmd(cmd, arg) + VALUE cmd, arg; { int state; struct SCOPE *saved_scope; + if (TYPE(cmd) != T_STRING) { + if (TYPE(cmd) == T_OBJECT + && obj_is_kind_of(cmd, cProc)) { + proc_call(cmd, arg); + return; + } + } + PUSH_SELF(TopSelf); PUSH_CLASS(); PUSH_TAG(); saved_scope = the_scope; the_scope = top_scope; - the_class = (struct RClass*)C_Object; + the_class = (struct RClass*)cObject; if ((state = EXEC_TAG()) == 0) { - Feval(Qself, cmd); + f_eval(Qself, cmd); } the_scope = saved_scope; @@ -624,21 +699,40 @@ rb_trap_eval(cmd) Fatal("retry outside of protect clause"); break; default: + JUMP_TAG(state); + break; + } +} + +void +rb_trap_eval(cmd, sig) + VALUE cmd; + int sig; +{ #ifdef SAFE_SIGHANDLE + int state; + + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig))); + } + POP_TAG(); + if (state) { trap_immediate = 0; -#endif JUMP_TAG(state); - break; } +#else + rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig))); +#endif } -#define SETUP_ARGS do {\ +#define SETUP_ARGS {\ NODE *n = node->nd_args;\ if (!n) {\ argc = 0;\ - argv = Qnil;\ + argv = 0;\ }\ - else if (/*nd_type(n) == NODE_LIST ||*/ nd_type(n) == NODE_ARRAY) {\ + else if (nd_type(n) == NODE_ARRAY) {\ argc=n->nd_alen;\ if (argc > 0) {\ int i;\ @@ -649,6 +743,10 @@ rb_trap_eval(cmd) n=n->nd_next;\ }\ }\ + else {\ + argc = 0;\ + argv = 0;\ + }\ }\ else {\ VALUE args = rb_eval(n);\ @@ -658,45 +756,36 @@ rb_trap_eval(cmd) argv = ALLOCA_N(VALUE, argc);\ MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\ }\ -} while (0) +} + +#define RETURN(v) do { result = (v); goto finish; } while (0) static VALUE rb_eval(node) register NODE *node; { int state; - int go_out; - VALUE result; + VALUE result = Qnil; again: - if (node == Qnil) return Qnil; + if (node == Qnil) RETURN(Qnil); sourceline = node->line; - -#ifdef SAFE_SIGHANDLE - { - extern int trap_pending; - - if (trap_pending) { - rb_trap_exec(); - } - } -#endif + sourcefile = node->file; switch (nd_type(node)) { case NODE_BLOCK: - while (node->nd_next) { - rb_eval(node->nd_head); + while (node) { + result = rb_eval(node->nd_head); node = node->nd_next; } - node = node->nd_head; - goto again; + break; case NODE_SELF: - return Qself; + RETURN(Qself); case NODE_NIL: - return Qnil; + RETURN(Qnil); case NODE_IF: if (rb_eval(node->nd_cond)) { @@ -706,7 +795,7 @@ rb_eval(node) node = node->nd_else; } if (node) goto again; - return Qnil; + RETURN(Qnil); case NODE_CASE: { @@ -720,18 +809,18 @@ rb_eval(node) while (tag) { if (rb_funcall(rb_eval(tag->nd_head), match, 1, val)){ - return rb_eval(node->nd_body); + RETURN(rb_eval(node->nd_body)); } tag = tag->nd_next; } } else { - return rb_eval(node); + RETURN(rb_eval(node)); } node = node->nd_next; } } - return Qnil; + RETURN(Qnil); case NODE_WHILE: PUSH_TAG(); @@ -742,23 +831,26 @@ rb_eval(node) while_redo: rb_eval(node->nd_body); } - go_out = 0; break; case TAG_REDO: + state = 0; goto while_redo; case TAG_CONTINUE: + state = 0; goto while_cont; default: - go_out = 1; break; + } + POP_TAG(); + switch (state) { + case 0: case TAG_BREAK: - go_out = 0; + break; + default: + JUMP_TAG(state); break; } - while_out: - POP_TAG(); - if (go_out) JUMP_TAG(state); - return Qnil; + RETURN(Qnil); case NODE_WHILE2: PUSH_TAG(); @@ -769,25 +861,31 @@ rb_eval(node) while2_redo: rb_eval(node->nd_body); } while (rb_eval(node->nd_cond)); - go_out = 0; break; case TAG_REDO: + state = 0; goto while2_redo; case TAG_CONTINUE: + state = 0; goto while2_cont; default: - go_out = 1; case TAG_BREAK: break; } - while2_out: POP_TAG(); - if (go_out) JUMP_TAG(state); - return Qnil; + switch (state) { + case 0: + case TAG_BREAK: + break; + default: + JUMP_TAG(state); + } + RETURN(Qnil); case NODE_ITER: case NODE_FOR: { + iter_retry: PUSH_BLOCK(node->nd_var, node->nd_body); PUSH_TAG(); @@ -803,7 +901,7 @@ rb_eval(node) recv = rb_eval(node->nd_iter); PUSH_ITER(ITER_PRE); - result = rb_call(CLASS_OF(recv),recv,each,0,Qnil,0); + result = rb_call(CLASS_OF(recv),recv,each,0,0,0); POP_ITER(); } } @@ -812,13 +910,16 @@ rb_eval(node) switch (state) { case 0: break; + + case TAG_RETRY: + goto iter_retry; + case IN_BLOCK|TAG_BREAK: if (target_level != tag_level) { JUMP_TAG(state); } result = Qnil; break; - case IN_BLOCK|TAG_RETRY: case IN_BLOCK|TAG_RETURN: if (target_level == tag_level) { state &= ~IN_BLOCK; @@ -828,91 +929,100 @@ rb_eval(node) JUMP_TAG(state); } } - return result; + break; case NODE_FAIL: { VALUE mesg = rb_eval(node->nd_stts); if (mesg) Check_Type(mesg, T_STRING); rb_fail(mesg); - return Qnil; /* not reached */ } + break; case NODE_YIELD: - { - VALUE val; - - val = rb_eval(node->nd_stts); - result = rb_yield(val); - } - return result; + result = rb_yield(rb_eval(node->nd_stts)); + break; case NODE_BEGIN: - PUSH_TAG(); - switch (state = EXEC_TAG()) { - case 0: - retry_entry: - result = rb_eval(node->nd_head); - break; + if (node->nd_resq == Qnil && node->nd_ensr == Qnil) { + node = node->nd_head; + goto again; + } + else { + VALUE (*r_proc)(); - case TAG_FAIL: - if (node->nd_resq) { - if (node->nd_resq == (NODE*)1) { - state = 0; - } - else { - PUSH_TAG(); - state = EXEC_TAG(); - if (state == 0) result = rb_eval(node->nd_resq); - POP_TAG(); - if (state == TAG_RETRY) { - goto retry_entry; - } + if (node->nd_resq == (NODE*)1) { + r_proc = 0; + } + else { + r_proc = rb_eval; + } + if (node->nd_ensr) { + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + result = rb_rescue(rb_eval, node->nd_head, r_proc, node->nd_resq); } - if (state == 0) { - errstr = errat = Qnil; - last_func = 0; + POP_TAG(); + /* ensure clause */ + rb_eval(node->nd_ensr); + if (state) { + JUMP_TAG(state); } } - break; - } - POP_TAG(); - - /* ensure clause */ - rb_eval(node->nd_ensr); - - if (state != 0) { - JUMP_TAG(state); + else { + result = rb_rescue(rb_eval, node->nd_head, r_proc, node->nd_resq); + } } - return result; + break; case NODE_AND: - if ((result = rb_eval(node->nd_1st)) == Qnil) return result; + if ((result = rb_eval(node->nd_1st)) == FALSE) RETURN(result); node = node->nd_2nd; goto again; case NODE_OR: - if ((result = rb_eval(node->nd_1st)) != Qnil) return result; + if ((result = rb_eval(node->nd_1st)) != FALSE) RETURN(result); node = node->nd_2nd; goto again; case NODE_NOT: - if (rb_eval(node->nd_body)) return FALSE; - return TRUE; + if (rb_eval(node->nd_body)) result = FALSE; + else result = TRUE; + break; + case NODE_DOT2: case NODE_DOT3: + RETURN(range_new(rb_eval(node->nd_beg), rb_eval(node->nd_end))); + + case NODE_FLIP2: /* like AWK */ + if (node->nd_state == 0) { + if (rb_eval(node->nd_beg)) { + node->nd_state = rb_eval(node->nd_end)?0:1; + result = TRUE; + } + result = FALSE; + } + else { + if (rb_eval(node->nd_end)) { + node->nd_state = 0; + } + result = TRUE; + } + break; + + case NODE_FLIP3: /* like SED */ if (node->nd_state == 0) { if (rb_eval(node->nd_beg)) { node->nd_state = 1; - return TRUE; + result = TRUE; } - return FALSE; + result = FALSE; } else { if (rb_eval(node->nd_end)) { node->nd_state = 0; } - return TRUE; + result = TRUE; } break; @@ -946,7 +1056,7 @@ rb_eval(node) recv = rb_eval(node->nd_recv); SETUP_ARGS; POP_ITER(); - return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0); + result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0); } break; @@ -957,19 +1067,18 @@ rb_eval(node) PUSH_ITER(ITER_NOT); SETUP_ARGS; POP_ITER(); - return rb_call(CLASS_OF(Qself),Qself,node->nd_mid,argc,argv,1); + result = rb_call(CLASS_OF(Qself),Qself,node->nd_mid,argc,argv,1); } break; case NODE_SUPER: case NODE_ZSUPER: { - int i; int argc; VALUE *argv; /* used in SETUP_ARGS */ if (nd_type(node) == NODE_ZSUPER) { - argc = the_env->argc; - argv = the_env->argv; + argc = the_frame->argc; + argv = the_frame->argv; } else { PUSH_ITER(ITER_NOT); @@ -978,16 +1087,14 @@ rb_eval(node) } PUSH_ITER(iter->iter?ITER_PRE:ITER_NOT); - result = rb_call(the_env->last_class->super, Qself, - the_env->last_func, argc, argv, 1); + result = rb_call(the_frame->last_class->super, Qself, + the_frame->last_func, argc, argv, 1); POP_ITER(); } - return result; + break; case NODE_SCOPE: { - VALUE result; - PUSH_SCOPE(); PUSH_TAG(); if (node->nd_cnt > 0) { @@ -996,22 +1103,17 @@ rb_eval(node) the_scope->local_tbl = node->nd_tbl; } else { - the_scope->local_vars = Qnil; - the_scope->local_tbl = Qnil; + the_scope->local_vars = 0; + the_scope->local_tbl = 0; } if ((state = EXEC_TAG()) == 0) { result = rb_eval(node->nd_body); } POP_TAG(); - if (!(the_scope->flags & SCOPE_MALLOCED)) { - the_scope->local_vars = Qnil; - the_scope->local_tbl = Qnil; - } POP_SCOPE(); if (state != 0) JUMP_TAG(state); - - return result; } + break; case NODE_OP_ASGN1: { @@ -1026,8 +1128,9 @@ rb_eval(node) val = rb_funcall(val, node->nd_mid, 1, rb_eval(rval)); ary_push(args, val); rb_apply(recv, aset, args); - return val; + result = val; } + break; case NODE_OP_ASGN2: { @@ -1036,24 +1139,27 @@ rb_eval(node) recv = rb_funcall(rb_eval(node->nd_recv), id, 0); - id &= ~ID_SCOPE_MASK; - id |= ID_ATTRSET; + id = id_attrset(id); val = rb_eval(node->nd_value); rb_funcall(recv, id, 1, val); - return val; + result = val; } + break; case NODE_MASGN: - { - VALUE val = rb_eval(node->nd_value); - return masign(node, val); - } + result = masign(node, rb_eval(node->nd_value)); + break; case NODE_LASGN: - if (the_scope->local_vars == Qnil) + if (the_scope->local_vars == 0) Bug("unexpected local variable asignment"); - return the_scope->local_vars[node->nd_cnt] = rb_eval(node->nd_value); + result = the_scope->local_vars[node->nd_cnt] = rb_eval(node->nd_value); + break; + + case NODE_DASGN: + result = dyna_var_asgn(node->nd_vid, rb_eval(node->nd_value)); + break; case NODE_GASGN: { @@ -1061,51 +1167,47 @@ rb_eval(node) val = rb_eval(node->nd_value); rb_gvar_set(node->nd_entry, val); - return val; + result = val; } + break; + case NODE_IASGN: { VALUE val; val = rb_eval(node->nd_value); - rb_ivar_set(node->nd_vid, val); - return val; + rb_ivar_set(Qself, node->nd_vid, val); + result = val; } + break; + case NODE_CASGN: { VALUE val; val = rb_eval(node->nd_value); rb_const_set(the_class, node->nd_vid, val); - return val; + result = val; } break; case NODE_LVAR: - if (the_scope->local_vars == Qnil) + if (the_scope->local_vars == 0) Bug("unexpected local variable"); - return the_scope->local_vars[node->nd_cnt]; - - case NODE_LVAR2: - if (the_scope->flags & SCOPE_MALLOCED) { - ID id = node->nd_vid, *tbl = the_scope->local_tbl; - int i, len = tbl[0]; + result = the_scope->local_vars[node->nd_cnt]; + break; - tbl++; - for (i=0; i<len; i++) { - if (id == tbl[i]) break; - } - if (i<len) { - return the_scope->local_vars[i]; - } - } - Warning("local var %s not initialized", rb_id2name(node->nd_vid)); - return Qnil; + case NODE_DVAR: + result = dyna_var_ref(node->nd_vid); + break; case NODE_GVAR: - return rb_gvar_get(node->nd_entry); + result = rb_gvar_get(node->nd_entry); + break; + case NODE_IVAR: - return rb_ivar_get(node->nd_vid); + result = rb_ivar_get(Qself, node->nd_vid); + break; case NODE_CVAR: { @@ -1114,14 +1216,54 @@ rb_eval(node) val = rb_const_get(node->nd_rval->nd_clss, node->nd_vid); nd_set_type(node, NODE_CONST); node->nd_cval = val; - return val; + result = val; } + break; case NODE_CONST: - return node->nd_cval; + result = node->nd_cval; + break; + + case NODE_COLON2: + { + VALUE cls; + + cls = rb_eval(node->nd_head); + switch (TYPE(cls)) { + case T_CLASS: + case T_MODULE: + break; + default: + Check_Type(cls, T_CLASS); + break; + } + result = rb_const_get(cls, node->nd_mid); + } + break; +#define MATCH_DATA the_scope->local_vars[node->nd_cnt] case NODE_NTH_REF: - return re_nth_match(node->nd_nth); + result = reg_nth_match(node->nd_nth, MATCH_DATA); + break; + + case NODE_BACK_REF: + switch (node->nd_nth) { + case '&': + result = reg_last_match(MATCH_DATA); + break; + case '`': + result = reg_match_pre(MATCH_DATA); + break; + case '\'': + result = reg_match_post(MATCH_DATA); + break; + case '+': + result = reg_match_last(MATCH_DATA); + break; + default: + Bug("unexpected back-ref"); + } + break; case NODE_HASH: { @@ -1133,24 +1275,24 @@ rb_eval(node) while (list) { key = rb_eval(list->nd_head); list = list->nd_next; - if (list == Qnil) + if (list == 0) Bug("odd number list for Hash"); val = rb_eval(list->nd_head); list = list->nd_next; - Fhash_aset(hash, key, val); + hash_aset(hash, key, val); } - return hash; + result = hash; } break; case NODE_ZARRAY: /* zero length list */ - return ary_new(); + result = ary_new(); + break; case NODE_ARRAY: { VALUE ary; int i; - NODE *list; i = node->nd_alen; ary = ary_new2(i); @@ -1159,12 +1301,13 @@ rb_eval(node) RARRAY(ary)->len = i; } - return ary; + result = ary; } break; case NODE_STR: - return str_new3(node->nd_lit); + result = str_new3(node->nd_lit); + break; case NODE_STR2: case NODE_XSTR2: @@ -1188,26 +1331,32 @@ rb_eval(node) list = list->nd_next; } if (nd_type(node) == NODE_DREGX) { - VALUE re = regexp_new(RSTRING(str)->ptr, RSTRING(str)->len, - node->nd_cflag); - return re; + VALUE re = reg_new(RSTRING(str)->ptr, RSTRING(str)->len, + node->nd_cflag); + result = re; + } + else if (nd_type(node) == NODE_XSTR2) { + result = rb_xstring(str); } - if (nd_type(node) == NODE_XSTR2) { - return rb_xstring(str); + else { + result = str; } - return str; } + break; case NODE_XSTR: - return rb_xstring(node->nd_lit); + result = rb_xstring(node->nd_lit); + break; case NODE_LIT: - return node->nd_lit; + result = node->nd_lit; + break; case NODE_ATTRSET: - if (the_env->argc != 1) - Fail("Wrong # of arguments(%d for 1)", the_env->argc); - return rb_ivar_set(node->nd_vid, the_env->argv[0]); + if (the_frame->argc != 1) + Fail("Wrong # of arguments(%d for 1)", the_frame->argc); + result = rb_ivar_set(Qself, node->nd_vid, the_frame->argv[0]); + break; case NODE_DEFN: if (node->nd_defn) { @@ -1216,7 +1365,7 @@ rb_eval(node) int noex; body = search_method(the_class, node->nd_mid, &origin); - if (verbose && origin != (VALUE)the_class + if (body && verbose && origin != (VALUE)the_class && body->nd_noex != node->nd_noex) { Warning("change method %s's scope", rb_id2name(node->nd_mid)); } @@ -1225,8 +1374,9 @@ rb_eval(node) else noex = node->nd_noex; /* default(1 for toplevel) */ rb_add_method(the_class, node->nd_mid, node->nd_defn, noex); + result = Qnil; } - return Qnil; + break; case NODE_DEFS: if (node->nd_defn) { @@ -1236,20 +1386,23 @@ rb_eval(node) Fail("Can't define method \"%s\" for nil", rb_id2name(node->nd_mid)); } - rb_funcall(recv, rb_intern("single_method_added"), + rb_funcall(recv, rb_intern("singleton_method_added"), 1, INT2FIX(node->nd_mid)); - rb_add_method(rb_single_class(recv),node->nd_mid,node->nd_defn, + rb_add_method(rb_singleton_class(recv),node->nd_mid,node->nd_defn, NOEX_PUBLIC); + result = Qnil; } - return Qnil; + break; case NODE_UNDEF: rb_add_method(the_class, node->nd_mid, Qnil, NOEX_PUBLIC); - return Qnil; + result = Qnil; + break; case NODE_ALIAS: rb_alias(the_class, node->nd_new, node->nd_old); - return Qnil; + result = Qnil; + break; case NODE_CLASS: { @@ -1257,17 +1410,16 @@ rb_eval(node) struct RClass *tmp; if (node->nd_super) { - super = rb_const_get(the_class, node->nd_super); - if (super == Qnil) { - Fail("undefined superclass %s", - rb_id2name(node->nd_super)); + super = rb_eval(node->nd_super); + if (super == Qnil || TYPE(super) != T_CLASS) { + Fail("superclass undefined"); } } else { super = Qnil; } - if (rb_const_bound(the_class, node->nd_cname)) { + if (rb_const_defined(the_class, node->nd_cname)) { class = rb_const_get(the_class, node->nd_cname); if (super) { if (TYPE(class) != T_CLASS) @@ -1280,27 +1432,28 @@ rb_eval(node) tmp = RCLASS(tmp)->super; } if (tmp != RCLASS(super)) - Fail("%s's superclass differs", + Fail("superclass mismatch for %s", rb_id2name(node->nd_cname)); } Warning("extending class %s", rb_id2name(node->nd_cname)); } else { - if (super == Qnil) super = C_Object; + if (super == Qnil) super = cObject; class = rb_define_class_id(node->nd_cname, super); rb_const_set(the_class, node->nd_cname, class); rb_set_class_path(class,the_class,rb_id2name(node->nd_cname)); } module_setup(class, node->nd_body); - return class; + result = class; } + break; case NODE_MODULE: { VALUE module; - if (rb_const_bound(the_class, node->nd_cname)) { + if (rb_const_defined(the_class, node->nd_cname)) { module = rb_const_get(the_class, node->nd_cname); if (TYPE(module) != T_MODULE) Fail("%s is not a module", rb_id2name(node->nd_cname)); @@ -1313,13 +1466,141 @@ rb_eval(node) } module_setup(module, node->nd_body); - return module; + result = module; } + break; + + case NODE_DEFINED: + { + VALUE obj; + + node = node->nd_head; + switch (nd_type(node)) { + case NODE_SUPER: + case NODE_ZSUPER: + if (the_frame->last_func == 0) result = FALSE; + else { + result = method_boundp(the_frame->last_class->super, + the_frame->last_func, 1); + } + break; + + case NODE_FCALL: + obj = CLASS_OF(Qself); + goto check_bound; + + case NODE_CALL: + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + obj = rb_eval(node->nd_recv); + } + POP_TAG(); + if (state == TAG_FAIL) { + result = FALSE; + break; + } + else { + if (state) JUMP_TAG(state); + obj = CLASS_OF(obj); + check_bound: + if (method_boundp(obj, node->nd_mid, + nd_type(node)== NODE_CALL)) { + result = TRUE; + } + else result = FALSE; + } + break; + + case NODE_YIELD: + result = iterator_p(); + break; + + case NODE_BREAK: + case NODE_CONTINUE: + case NODE_REDO: + case NODE_RETRY: + + case NODE_SELF: + case NODE_NIL: + case NODE_FAIL: + case NODE_ATTRSET: + case NODE_DEFINED: + + case NODE_OP_ASGN1: + case NODE_OP_ASGN2: + case NODE_MASGN: + case NODE_LASGN: + case NODE_DASGN: + case NODE_GASGN: + case NODE_IASGN: + case NODE_CASGN: + case NODE_LVAR: + case NODE_DVAR: + result = TRUE; + break; + + case NODE_GVAR: + result = rb_gvar_defined(node->nd_entry); + break; + + case NODE_IVAR: + result = rb_ivar_defined(node->nd_vid); + break; + + case NODE_CVAR: + result = rb_const_defined(node->nd_rval->nd_clss, node->nd_vid); + break; + + case NODE_CONST: + result = TRUE; + break; + + case NODE_COLON2: + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + obj = rb_eval(node->nd_head); + } + POP_TAG(); + if (state == TAG_FAIL) result = FALSE; + else { + if (state) JUMP_TAG(state); + result = rb_const_defined(obj, node->nd_mid); + } + break; + + case NODE_NTH_REF: + result = reg_nth_defined(node->nd_nth, MATCH_DATA); + break; + + case NODE_BACK_REF: + result = reg_nth_defined(0, MATCH_DATA); + break; + + default: + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + rb_eval(node); + } + POP_TAG(); + if (state == TAG_FAIL) result = FALSE; + else { + if (state) JUMP_TAG(state); + result = TRUE; + } + } + } + break; default: Bug("unknown node type %d", nd_type(node)); } - return Qnil; /* not reached */ + finish: +#ifdef SAFE_SIGHANDLE + if (trap_pending) { + rb_trap_exec(); + } +#endif + return result; /* not reached */ } static void @@ -1337,7 +1618,6 @@ module_setup(module, node) the_class = (struct RClass*)module; PUSH_SELF((VALUE)the_class); PUSH_SCOPE(); - PUSH_TAG(); if (node->nd_cnt > 0) { the_scope->local_vars = ALLOCA_N(VALUE, node->nd_cnt); @@ -1345,20 +1625,15 @@ module_setup(module, node) the_scope->local_tbl = node->nd_tbl; } else { - the_scope->local_vars = Qnil; - the_scope->local_tbl = Qnil; + the_scope->local_vars = 0; + the_scope->local_tbl = 0; } + PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { rb_eval(node->nd_body); } - POP_TAG(); - if (!(the_scope->flags & SCOPE_MALLOCED)) { - the_scope->local_vars = Qnil; - the_scope->local_tbl = Qnil; - } - if (state != 0) JUMP_TAG(state); POP_SCOPE(); POP_SELF(); POP_CLASS(); @@ -1366,20 +1641,10 @@ module_setup(module, node) } VALUE -obj_responds_to(obj, msg) +rb_responds_to(obj, id) VALUE obj; - struct RString *msg; -{ ID id; - - if (FIXNUM_P(msg)) { - id = FIX2INT(msg); - } - else { - Check_Type(msg, T_STRING); - id = rb_intern(msg->ptr); - } - +{ if (rb_method_boundp(CLASS_OF(obj), id)) { return TRUE; } @@ -1393,11 +1658,12 @@ rb_exit(status) last_val = INT2FIX(status); if (prot_tag) JUMP_TAG(TAG_EXIT); + rb_trap_exit(); exit(FIX2UINT(last_val)); } static VALUE -Fexit(argc, argv, obj) +f_exit(argc, argv, obj) int argc; VALUE *argv; VALUE obj; @@ -1440,25 +1706,22 @@ rb_fail(mesg) { char buf[BUFSIZ]; - if (errat == Qnil || sourcefile) { - if (the_env->last_func) { - last_func = the_env->last_func; + if (errat == Qnil && mesg == Qnil) { + errstr = Qnil; + } + + if (errat == Qnil && sourcefile) { + if (the_frame->last_func) { + last_func = the_frame->last_func; } sprintf(buf, "%s:%d", sourcefile, sourceline); errat = str_new2(buf); } if (mesg) { - if (RSTRING(mesg)->ptr[RSTRING(mesg)->len - 1] == '\n') { - errstr = mesg; - } - else { - errstr = str_clone(mesg); - str_cat(errstr, "\n", 1); - } + errstr = mesg; } - - if (prot_tag->level == 0) error_print(); + if (prot_tag->level == 0) error_print(last_func); JUMP_TAG(TAG_FAIL); } @@ -1470,48 +1733,54 @@ iterator_p() } static VALUE -Fiterator_p() +f_iterator_p() { if (iter->prev && iter->prev->iter) return TRUE; return FALSE; } VALUE -rb_yield(val) - VALUE val; +rb_yield_0(val, self) + VALUE val, self; { struct BLOCK *block; NODE *node; int state; - VALUE result; - struct ENVIRON *old_env; - struct SCOPE *old_scope; + VALUE result = Qnil; + struct SCOPE *old_scope; + struct FRAME frame; if (!iterator_p()) { Fail("yield called out of iterator"); } + PUSH_VARS(); block = the_block; - old_env = the_env; - the_env = &(block->env); + frame = block->frame; + frame.prev = the_frame; + the_frame = &(frame); old_scope = the_scope; the_scope = block->scope; the_block = block->prev; + the_dyna_vars = block->d_vars; if (block->var) { if (nd_type(block->var) == NODE_MASGN) masign(block->var, val); else asign(block->var, val); } + node = block->body; PUSH_ITER(block->iter); - PUSH_SELF(block->self); + PUSH_SELF(self?self:block->self); PUSH_TAG(); - node = block->body; switch (state = EXEC_TAG()) { redo: case 0: - if (nd_type(node) == NODE_CFUNC) { + if (!node) { + result = Qnil; + } + else if (nd_type(node) == NODE_CFUNC) { result = (*node->nd_cfnc)(val,node->nd_argc); } else { @@ -1523,24 +1792,40 @@ rb_yield(val) case TAG_CONTINUE: state = 0; break; - case TAG_RETRY: case TAG_BREAK: case TAG_RETURN: target_level = block->level; state = IN_BLOCK|state; break; + default: + break; } POP_TAG(); POP_SELF(); POP_ITER(); + POP_VARS(); the_block = block; - the_env = old_env; + the_frame = the_frame->prev; the_scope = old_scope; if (state) JUMP_TAG(state); return result; } +VALUE +rb_yield(val) + VALUE val; +{ + return rb_yield_0(val, 0); +} + +static VALUE +f_loop() +{ + for (;;) { rb_yield(Qnil); } + return Qnil; +} + static VALUE masign(node, val) NODE *node; @@ -1590,15 +1875,19 @@ asign(lhs, val) break; case NODE_IASGN: - rb_ivar_set(lhs->nd_vid, val); + rb_ivar_set(Qself, lhs->nd_vid, val); break; case NODE_LASGN: - if (the_scope->local_vars == Qnil) + if (the_scope->local_vars == 0) Bug("unexpected iterator variable asignment"); the_scope->local_vars[lhs->nd_cnt] = val; break; + case NODE_DASGN: + dyna_var_asgn(lhs->nd_vid, val); + break; + case NODE_CASGN: rb_const_set(the_class, lhs->nd_vid, val); break; @@ -1631,13 +1920,13 @@ asign(lhs, val) VALUE rb_iterate(it_proc, data1, bl_proc, data2) VALUE (*it_proc)(), (*bl_proc)(); - char *data1, *data2; + void *data1, *data2; { int state; - VALUE retval; + VALUE retval = Qnil; NODE *node = NEW_CFUNC(bl_proc, data2); - struct BLOCK block; + iter_retry: PUSH_ITER(ITER_PRE); PUSH_BLOCK(Qnil, node); PUSH_TAG(); @@ -1654,13 +1943,17 @@ rb_iterate(it_proc, data1, bl_proc, data2) switch (state) { case 0: break; + + case TAG_RETRY: + goto iter_retry; + case IN_BLOCK|TAG_BREAK: if (target_level != tag_level) { JUMP_TAG(state); } retval = Qnil; break; - case IN_BLOCK|TAG_RETRY: + case IN_BLOCK|TAG_RETURN: if (target_level == tag_level) { state &= ~IN_BLOCK; @@ -1674,23 +1967,24 @@ rb_iterate(it_proc, data1, bl_proc, data2) } VALUE -rb_resque(b_proc, data1, r_proc, data2) +rb_rescue(b_proc, data1, r_proc, data2) VALUE (*b_proc)(), (*r_proc)(); - char *data1, *data2; + void *data1, *data2; { int state; - int go_out; - VALUE result; + VALUE result = Qnil; + volatile SIGHANDLE handle; PUSH_TAG(); switch (state = EXEC_TAG()) { case 0: + handle = sig_beg(); retry_entry: result = (*b_proc)(data1); - go_out = 0; break; case TAG_FAIL: + sig_end(handle); if (r_proc) { PUSH_TAG(); state = EXEC_TAG(); @@ -1698,28 +1992,25 @@ rb_resque(b_proc, data1, r_proc, data2) result = (*r_proc)(data2); } POP_TAG(); - switch (state) { - case TAG_RETRY: + if (state == TAG_RETRY) { goto retry_entry; - case 0: - go_out = 0; - break; - default: - go_out = 1; - break; } } + else { + state = 0; + } if (state == 0) { - errstr = errat = Qnil; + errat = Qnil; + last_func = 0; } break; default: - go_out = 1; + sig_end(handle); break; } POP_TAG(); - if (go_out) JUMP_TAG(state); + if (state) JUMP_TAG(state); return result; } @@ -1727,10 +2018,10 @@ rb_resque(b_proc, data1, r_proc, data2) VALUE rb_ensure(b_proc, data1, e_proc, data2) VALUE (*b_proc)(), (*e_proc)(); - char *data1, *data2; + void *data1, *data2; { int state; - VALUE result; + VALUE result = Qnil; PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { @@ -1748,7 +2039,7 @@ rb_ensure(b_proc, data1, e_proc, data2) static int last_noex; static VALUE -Fmissing(argc, argv, obj) +f_missing(argc, argv, obj) int argc; VALUE *argv; VALUE obj; @@ -1756,31 +2047,33 @@ Fmissing(argc, argv, obj) VALUE desc; ID id; char *format; - struct ENVIRON *env; + struct FRAME *frame; id = FIX2INT(argv[0]); argc--; argv++; - desc = obj_as_string(obj); - if (RSTRING(desc)->len > 160) { - desc = Fkrn_to_s(obj); + if (TYPE(obj) == T_STRING) { + desc = krn_inspect(obj); + } + else { + desc = obj_as_string(obj); } if (last_noex) - format = "method `%s' not available for \"%s\"(%s)"; + format = "method `%s' not available for %s(%s)"; else - format = "undefined method `%s' for \"%s\"(%s)"; + format = "undefined method `%s' for %s(%s)"; - /* fake environment */ - PUSH_ENV(); - env = the_env->prev; - MEMCPY(the_env, env->prev, struct ENVIRON, 1); - the_env->prev = env; + /* fake frame */ + PUSH_FRAME(); + frame = the_frame->prev; + *the_frame = *frame->prev; + the_frame->prev = frame; Fail(format, rb_id2name(id), RSTRING(desc)->ptr, rb_class2name(CLASS_OF(obj))); - POP_ENV(); + POP_FRAME(); } static VALUE @@ -1793,7 +2086,6 @@ rb_undefined(obj, id, argc, argv, noex) { VALUE *nargv; - argc; nargv = ALLOCA_N(VALUE, argc+1); nargv[0] = INT2FIX(id); MEMCPY(nargv+1, argv, VALUE, argc); @@ -1803,6 +2095,9 @@ rb_undefined(obj, id, argc, argv, noex) return rb_funcall2(obj, rb_intern("method_missing"), argc+1, nargv); } +#define STACK_LEVEL_MAX 10000 +static int stack_level; + static VALUE rb_call(class, recv, mid, argc, argv, scope) struct RClass *class; @@ -1814,7 +2109,7 @@ rb_call(class, recv, mid, argc, argv, scope) { NODE *body; int noex; - VALUE result; + VALUE result = Qnil; struct cache_entry *ent; int itr; enum node_type type; @@ -1830,7 +2125,7 @@ rb_call(class, recv, mid, argc, argv, scope) else { ID id = mid; - if ((body = rb_get_method_body(&class, &id, &noex)) == Qnil) { + if ((body = rb_get_method_body(&class, &id, &noex)) == FALSE) { return rb_undefined(recv, mid, argc, argv, 0); } mid = id; @@ -1861,13 +2156,16 @@ rb_call(class, recv, mid, argc, argv, scope) return rb_call(class->super, recv, mid, argc, argv, scope?scope:1); } + if (stack_level++ > STACK_LEVEL_MAX) + Fail("stack level too deep"); + PUSH_ITER(itr); PUSH_SELF(recv); - PUSH_ENV(); - the_env->last_func = mid; - the_env->last_class = class; - the_env->argc = argc; - the_env->argv = argv; + PUSH_FRAME(); + the_frame->last_func = mid; + the_frame->last_class = class; + the_frame->argc = argc; + the_frame->argv = argv; switch (type) { case NODE_CFUNC: @@ -1985,14 +2283,14 @@ rb_call(class, recv, mid, argc, argv, scope) /* for attr get/set */ case NODE_ATTRSET: case NODE_IVAR: - return rb_eval(body); + result = rb_eval(body); + break; default: { int state; VALUE *local_vars; - sourcefile = body->file; PUSH_SCOPE(); if (body->nd_cnt > 0) { @@ -2002,47 +2300,59 @@ rb_call(class, recv, mid, argc, argv, scope) the_scope->local_vars = local_vars; } else { - local_vars = the_scope->local_vars = Qnil; - the_scope->local_tbl = Qnil; + local_vars = the_scope->local_vars = 0; + the_scope->local_tbl = 0; } body = body->nd_body; - if (nd_type(body) == NODE_BLOCK) { - NODE *node = body->nd_head; - NODE *local; - int i; - - if (nd_type(node) != NODE_ARGS) { - Bug("no argument-node"); - } + PUSH_TAG(); + state = EXEC_TAG(); + if (state == 0) { + if (nd_type(body) == NODE_BLOCK) { + NODE *node = body->nd_head; + int i; - body = body->nd_next; - i = node->nd_cnt; - if (i > argc || (node->nd_rest == -1 && i < argc)) - Fail("Wrong # of arguments(%d for %d)", argc, i); + if (nd_type(node) != NODE_ARGS) { + Bug("no argument-node"); + } - if (local_vars) { - if (i > 0) { - MEMCPY(local_vars, argv, VALUE, i); + body = body->nd_next; + i = node->nd_cnt; + if (i > argc + || (node->nd_rest == -1 + && i+(node->nd_opt?node->nd_opt->nd_alen:0)<argc)){ + Fail("Wrong # of arguments(%d for %d)", argc, i); } - if (node->nd_rest >= 0) { - if (argc == 0) - local_vars[node->nd_rest] = ary_new(); - else - local_vars[node->nd_rest] = ary_new4(argc-i, argv+i); + + if (local_vars) { + if (i > 0) { + MEMCPY(local_vars, argv, VALUE, i); + } + argv += i; argc -= i; + if (node->nd_opt) { + NODE *opt = node->nd_opt; + + while (opt && argc) { + asign(opt->nd_head, *argv); + argv++; argc--; + opt = opt->nd_next; + } + rb_eval(opt); + } + if (node->nd_rest >= 0) { + if (argc > 0) + local_vars[node->nd_rest]=ary_new4(argc,argv); + else + local_vars[node->nd_rest] = ary_new2(0); + } } } - } - PUSH_TAG(); - state = EXEC_TAG(); - if (state == 0) { + else if (nd_type(body) == NODE_ARGS) { + body = 0; + } result = rb_eval(body); } POP_TAG(); - if (!(the_scope->flags & SCOPE_MALLOCED)) { - the_scope->local_vars = Qnil; - the_scope->local_tbl = Qnil; - } POP_SCOPE(); switch (state) { case 0: @@ -2056,20 +2366,23 @@ rb_call(class, recv, mid, argc, argv, scope) case TAG_REDO: Fatal("unexpected redo"); break; - case TAG_RETRY: - Fatal("retry outside of resque clause"); - break; case TAG_RETURN: result = last_val; break; + case TAG_RETRY: + if (!iterator_p()) { + Fatal("retry outside of rescue clause"); + } default: + stack_level--; JUMP_TAG(state); } } } - POP_ENV(); + POP_FRAME(); POP_SELF(); POP_ITER(); + stack_level--; return result; } @@ -2089,7 +2402,7 @@ rb_apply(recv, mid, args) } static VALUE -Fapply(argc, argv, recv) +f_send(argc, argv, recv) int argc; VALUE *argv; VALUE recv; @@ -2133,7 +2446,7 @@ rb_funcall(recv, mid, n, va_alist) va_end(ar); } else { - argv = Qnil; + argv = 0; } return rb_call(CLASS_OF(recv), recv, mid, n, argv, 1); @@ -2149,17 +2462,69 @@ rb_funcall2(recv, mid, argc, argv) return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1); } +static VALUE +f_caller(argc, argv) + int argc; + VALUE *argv; +{ + VALUE level; + struct FRAME *frame = the_frame; + int lev, n; + char buf[BUFSIZ]; + + rb_scan_args(argc, argv, "01", &level); + if (level == Qnil) lev = 1; + else lev = NUM2INT(level); + n = lev; + if (n < 0) Fail("negative level(%d)", n); + else { + while (n-- > 0) { + frame = frame->prev; + if (!frame) return Qnil; + } + if (!frame->file) return Qnil; + if (frame->prev && frame->prev->last_func) { + sprintf(buf, "%s:%d:in `%s'", + frame->file, frame->line, + rb_id2name(frame->prev->last_func)); + } + else { + sprintf(buf, "%s:%d", frame->file, frame->line); + } + } + return str_new2(buf); +} + +void +rb_backtrace() +{ + VALUE c, lev; + int n = 0; + + lev = INT2FIX(n); + while (c = f_caller(1, &lev)) { + printf("%s\n", RSTRING(c)->ptr); + n++; + lev = INT2FIX(n); + } +} + +ID +rb_frame_last_func() +{ + return the_frame->last_func; +} + int rb_in_eval = 0; static VALUE -Feval(obj, src) +f_eval(obj, src) VALUE obj; struct RString *src; { - VALUE result; + VALUE result = Qnil; int state; NODE *node; - char *oldsrc = sourcefile; Check_Type(src, T_STRING); PUSH_TAG(); @@ -2173,11 +2538,12 @@ Feval(obj, src) if ((state = EXEC_TAG()) == 0) { lex_setsrc("(eval)", src->ptr, src->len); - eval_tree = Qnil; + eval_tree = 0; + PUSH_VARS(); yyparse(); - sourcefile = oldsrc; + POP_VARS(); if (nerrs == 0) { - result = Eval(0); + result = Eval(); } } eval_tree = node; @@ -2221,22 +2587,22 @@ find_file(file) } VALUE -Fload(obj, fname) +f_load(obj, fname) VALUE obj; struct RString *fname; { int state, in_eval = rb_in_eval; - NODE *node; - char *file; + char *file, *src; Check_Type(fname, T_STRING); file = find_file(fname->ptr); - if (!file) Fail("No such file to load -- %s", file); + if (!file) Fail("No such file to load -- %s", fname->ptr); PUSH_SELF(TopSelf); PUSH_TAG(); PUSH_CLASS(); - the_class = (struct RClass*)C_Object; + the_class = (struct RClass*)cObject; + PUSH_SCOPE(); the_scope->local_vars = top_scope->local_vars; the_scope->local_tbl = top_scope->local_tbl; rb_in_eval = 1; @@ -2244,9 +2610,11 @@ Fload(obj, fname) if (state == 0) { rb_load_file(file); if (nerrs == 0) { - Eval(0); + Eval(); } } + top_scope->flag = the_scope->flag; + POP_SCOPE(); POP_CLASS(); POP_TAG(); POP_SELF(); @@ -2259,98 +2627,175 @@ Fload(obj, fname) return TRUE; } -static VALUE rb_loadfiles; +static VALUE rb_features; -Frequire(obj, fname) - VALUE obj; - struct RString *fname; +static VALUE +rb_provided(feature) + char *feature; { - char *file; VALUE *p, *pend; + char *f; + int len; - Check_Type(fname, T_STRING); - file = find_file(fname->ptr); - if (!file) { - char *buf = ALLOCA_N(char, strlen(fname->ptr) + 4); - sprintf(buf, "%s.rb", fname->ptr); - file = find_file(buf); -#ifdef USE_DL - if (!file) { - sprintf(buf, "%s%s", fname->ptr, DLEXT); - file = find_file(buf); - } -#endif - if (!file) Fail("No such file to load -- %s", file); - } - - p = RARRAY(rb_loadfiles)->ptr; - pend = p + RARRAY(rb_loadfiles)->len; + p = RARRAY(rb_features)->ptr; + pend = p + RARRAY(rb_features)->len; while (p < pend) { Check_Type(*p, T_STRING); - if (strcmp(RSTRING(*p)->ptr, file) == 0) return FALSE; + f = RSTRING(*p)->ptr; + if (strcmp(f, feature) == 0) return TRUE; + len = strlen(feature); + if (strncmp(f, feature, len) == 0 + && (strcmp(f+len, ".rb") == 0 ||strcmp(f+len, ".o") == 0)) { + return TRUE; + } + p++; } - fname = (struct RString*)str_new2(file); - ary_push(rb_loadfiles, fname); - file = fname->ptr; + return FALSE; +} -#ifdef USE_DL - { - int len = strlen(file), extsiz = sizeof(DLEXT); +void +rb_provide(feature) + char *feature; +{ + if (!rb_provided(feature)) + ary_push(rb_features, str_new2(feature)); +} - if (len > extsiz) { - int i; - for (i=1;i<extsiz;i++) { - if (file[len-i] != DLEXT[extsiz-i-1]) break; +VALUE +f_require(obj, fname) + VALUE obj; + struct RString *fname; +{ + char *ext, *file, *feature, *buf; + VALUE load; + + Check_Type(fname, T_STRING); + if (rb_provided(fname->ptr)) return FALSE; + + ext = strrchr(fname->ptr, '.'); + if (ext) { + if (strcmp(".rb", ext) == 0) { + feature = file = fname->ptr; + file = find_file(file); + if (file) goto rb_load; + } + else if (strcmp(".o", ext) == 0) { + feature = fname->ptr; + if (strcmp(".o", DLEXT) != 0) { + buf = ALLOCA_N(char, strlen(fname->ptr) + 3); + strcpy(buf, feature); + ext = strrchr(buf, '.'); + strcpy(ext, DLEXT); + file = find_file(buf); } - if (i==extsiz) { - static int rb_dln_init = 0; - extern char *rb_dln_argv0; + if (file) goto dyna_load; + } + else if (strcmp(DLEXT, ext) == 0) { + feature = fname->ptr; + file = find_file(feature); + if (file) goto dyna_load; + } + } + buf = ALLOCA_N(char, strlen(fname->ptr) + 4); + sprintf(buf, "%s.rb", fname->ptr); + file = find_file(buf); + if (file) { + fname = (struct RString*)str_new2(file); + feature = buf; + goto rb_load; + } + sprintf(buf, "%s%s", fname->ptr, DLEXT); + file = find_file(buf); + if (file) { + feature = buf; + goto dyna_load; + } + Fail("No such file to load -- %s", fname->ptr); + + dyna_load: + load = str_new2(file); + file = RSTRING(load)->ptr; + dln_load(file); + rb_provide(feature); + return TRUE; - if (rb_dln_init == 0 && dln_init(rb_dln_argv0) == -1) { - Fail("%s: %s", rb_dln_argv0, dln_strerror()); - } + rb_load: + f_load(obj, fname); + rb_provide(feature); + return TRUE; +} - if (dln_load(file) == -1) - Fail(dln_strerror()); +static void +set_method_visibility(argc, argv, ex) + int argc; + VALUE *argv; + int ex; +{ + VALUE self = Qself; + int i; + ID id; - return TRUE; - } + for (i=0; i<argc; i++) { + if (FIXNUM_P(argv[i])) { + id = FIX2INT(argv[i]); } + else { + Check_Type(argv[i], T_STRING); + id = rb_intern(RSTRING(argv[i])->ptr); + } + rb_export_method(self, id, ex); } -#endif - return Fload(obj, fname); } -#ifndef RUBY_LIB -#define RUBY_LIB "/usr/local/lib/ruby:." -#endif - -#define RUBY_LIB_SEP ':' +static VALUE +mod_public(argc, argv) + int argc; + VALUE *argv; +{ + set_method_visibility(argc, argv, NOEX_PUBLIC); + return Qnil; +} -static void -addpath(path) - char *path; +static VALUE +mod_private(argc, argv) + int argc; + VALUE *argv; { - char *p, *s; + set_method_visibility(argc, argv, NOEX_PRIVATE); + return Qnil; +} - if (path == Qnil) return; +static VALUE +mod_modfunc(argc, argv, module) + int argc; + VALUE *argv; + VALUE module; +{ + int i; + ID id; + NODE *body, *old; - p = s = path; - while (*p) { - while (*p == RUBY_LIB_SEP) p++; - if (s = strchr(p, RUBY_LIB_SEP)) { - ary_push(rb_load_path, str_new(p, (int)(s-p))); - p = s + 1; + set_method_visibility(argc, argv, NOEX_PRIVATE); + for (i=0; i<argc; i++) { + if (FIXNUM_P(argv[i])) { + id = FIX2INT(argv[i]); } else { - ary_push(rb_load_path, str_new2(p)); - break; + Check_Type(argv[i], T_STRING); + id = rb_intern(RSTRING(argv[i])->ptr); } + body = search_method(module, id, 0); + if (body == 0 || body->nd_body == 0) { + Fail("undefined method `%s' for module `%s'", + rb_id2name(id), rb_class2name(module)); + } + rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC); } + return Qnil; } static VALUE -Fmod_include(argc, argv, module) +mod_include(argc, argv, module) int argc; VALUE *argv; struct RClass *module; @@ -2358,33 +2803,43 @@ Fmod_include(argc, argv, module) int i; for (i=0; i<argc; i++) { + Check_Type(argv[i], T_MODULE); rb_include_module(module, argv[i]); } return (VALUE)module; } static VALUE -Ftop_include(argc, argv) +top_include(argc, argv) + int argc; + VALUE *argv; { - return Fmod_include(argc, argv, C_Object); + return mod_include(argc, argv, cObject); } static VALUE -Fobj_extend(argc, argv, obj) +obj_extend(argc, argv, obj) + int argc; + VALUE *argv; + VALUE obj; { - return Fmod_include(argc, argv, rb_single_class(obj)); + return mod_include(argc, argv, rb_singleton_class(obj)); } void rb_extend_object(obj, module) VALUE obj, module; { - rb_include_module(rb_single_class(obj), module); + rb_include_module(rb_singleton_class(obj), module); } -extern VALUE C_Kernel; -extern VALUE C_Module; +extern VALUE cKernel; +extern VALUE cModule; +VALUE f_trace_var(); +VALUE f_untrace_var(); + +void Init_eval() { match = rb_intern("=~"); @@ -2395,126 +2850,137 @@ Init_eval() rb_global_variable(&top_scope); rb_global_variable(&eval_tree); - rb_define_private_method(C_Kernel, "exit", Fexit, -1); - rb_define_private_method(C_Kernel, "eval", Feval, 1); - rb_define_private_method(C_Kernel, "iterator_p", Fiterator_p, 0); - rb_define_method(C_Kernel, "apply", Fapply, -1); - rb_define_method(C_Kernel, "method_missing", Fmissing, -1); - - rb_define_method(C_Module, "include", Fmod_include, -1); - rb_define_method(CLASS_OF(TopSelf), "include", Ftop_include, -1); - rb_define_method(C_Object, "extend", Fobj_extend, -1); + rb_global_variable(&the_dyna_vars); + rb_define_private_method(cKernel, "exit", f_exit, -1); + rb_define_private_method(cKernel, "eval", f_eval, 1); + rb_define_private_method(cKernel, "iterator?", f_iterator_p, 0); + rb_define_private_method(cKernel, "method_missing", f_missing, -1); + rb_define_private_method(cKernel, "loop", f_loop, 0); + rb_define_private_method(cKernel, "caller", f_caller, -1); + + rb_define_method(cKernel, "send", f_send, -1); + + rb_define_method(cModule, "include", mod_include, -1); + rb_define_method(cModule, "public", mod_public, -1); + rb_define_method(cModule, "private", mod_private, -1); + rb_define_method(cModule, "module_function", mod_modfunc, -1); + + rb_define_method(CLASS_OF(TopSelf), "include", top_include, -1); + rb_define_method(cObject, "extend", obj_extend, -1); + + rb_define_private_method(cKernel, "trace_var", f_trace_var, -1); + rb_define_private_method(cKernel, "untrace_var", f_untrace_var, 1); } +VALUE f_autoload(); + +void Init_load() { - char *path; - rb_load_path = ary_new(); - rb_define_variable("$:", &rb_load_path, Qnil, rb_readonly_hook, 0); - rb_define_variable("$LOAD_PATH", &rb_load_path, Qnil, rb_readonly_hook, 0); + rb_define_readonly_variable("$:", &rb_load_path); + rb_define_readonly_variable("$LOAD_PATH", &rb_load_path); - rb_loadfiles = ary_new(); - rb_define_variable("$\"", &rb_load_path, Qnil, rb_readonly_hook, 0); - rb_define_variable("$LOAD_FILES", &rb_load_path, Qnil, rb_readonly_hook,0); - addpath(getenv("RUBYLIB")); - addpath(RUBY_LIB); + rb_features = ary_new(); + rb_define_readonly_variable("$\"", &rb_features); - rb_define_private_method(C_Kernel, "load", Fload, 1); - rb_define_private_method(C_Kernel, "require", Frequire, 1); + rb_define_private_method(cKernel, "load", f_load, 1); + rb_define_private_method(cKernel, "require", f_require, 1); + rb_define_private_method(cKernel, "autoload", f_autoload, 2); } -void +static void scope_dup(scope) struct SCOPE *scope; { ID *tbl; VALUE *vars; - if (scope->flags & SCOPE_MALLOCED) return; - if (!scope->local_tbl) return; + if (scope->flag == SCOPE_MALLOC) return; - tbl = scope->local_tbl; - scope->local_tbl = ALLOC_N(ID, tbl[0]+1); - MEMCPY(scope->local_tbl, tbl, ID, tbl[0]+1); - vars = scope->local_vars; - scope->local_vars = ALLOC_N(VALUE, tbl[0]); - MEMCPY(scope->local_vars, vars, VALUE, tbl[0]); - scope->flags |= SCOPE_MALLOCED; + if (scope->local_tbl) { + tbl = scope->local_tbl; + scope->local_tbl = ALLOC_N(ID, tbl[0]+1); + MEMCPY(scope->local_tbl, tbl, ID, tbl[0]+1); + vars = scope->local_vars; + scope->local_vars = ALLOC_N(VALUE, tbl[0]); + MEMCPY(scope->local_vars, vars, VALUE, tbl[0]); + scope->flag = SCOPE_MALLOC; + } } -VALUE C_Block; static ID blkdata; static void blk_mark(data) struct BLOCK *data; { - gc_mark_env(&data->env); + gc_mark_frame(&data->frame); gc_mark(data->scope); gc_mark(data->var); gc_mark(data->body); gc_mark(data->self); + gc_mark(data->d_vars); } static void blk_free(data) struct BLOCK *data; { - free(data->env.argv); + free(data->frame.argv); } static VALUE -Sblk_new(class) +proc_s_new(class) + VALUE class; { - VALUE blk; + VALUE proc; struct BLOCK *data; - struct SCOPE *scope; - if (!iterator_p() && !Fiterator_p()) { - Fail("tryed to create Block out of iterator"); + if (!iterator_p() && !f_iterator_p()) { + Fail("tryed to create Procedure-Object out of iterator"); } - if (the_block->block) return the_block->block; - blk = obj_alloc(class); + proc = obj_alloc(class); if (!blkdata) blkdata = rb_intern("blk"); - Make_Data_Struct(blk, blkdata, struct BLOCK, Qnil, blk_free, data); + Make_Data_Struct(proc, blkdata, struct BLOCK, blk_mark, blk_free, data); MEMCPY(data, the_block, struct BLOCK, 1); - data->env.argv = ALLOC_N(VALUE, data->env.argc); - MEMCPY(data->env.argv, the_block->env.argv, VALUE, data->env.argc); + data->frame.argv = ALLOC_N(VALUE, data->frame.argc); + MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc); scope_dup(data->scope); - the_block->block = blk; - return blk; + return proc; } VALUE -block_new() +f_lambda() { - return Sblk_new(C_Block); + return proc_s_new(cProc); } static VALUE -Fblk_call(blk, args) - VALUE blk, args; +proc_call(proc, args) + VALUE proc, args; { struct BLOCK *data; - VALUE result; + VALUE result = Qnil; int state; - switch (RARRAY(args)->len) { - case 0: - args = Qnil; - break; - case 1: - args = RARRAY(args)->ptr[0]; - break; + if (TYPE(args) == T_ARRAY) { + switch (RARRAY(args)->len) { + case 0: + args = 0; + break; + case 1: + args = RARRAY(args)->ptr[0]; + break; + } } - Get_Data_Struct(blk, blkdata, struct BLOCK, data); + Get_Data_Struct(proc, blkdata, struct BLOCK, data); /* PUSH BLOCK from data */ PUSH_BLOCK2(data); @@ -2525,18 +2991,14 @@ Fblk_call(blk, args) if (state == 0) { result = rb_yield(args); } - POP_TAG(); + POP_ITER(); POP_BLOCK(); switch (state) { case 0: break; - case TAG_RETRY: - case IN_BLOCK|TAG_RETRY: - Fail("retry from block-closure"); - break; case TAG_BREAK: case IN_BLOCK|TAG_BREAK: Fail("break from block-closure"); @@ -2552,11 +3014,14 @@ Fblk_call(blk, args) return result; } -Init_Block() +void +Init_Proc() { - C_Block = rb_define_class("Block", C_Object); + cProc = rb_define_class("Proc", cObject); - rb_define_single_method(C_Block, "new", Sblk_new, 0); + rb_define_singleton_method(cProc, "new", proc_s_new, 0); - rb_define_method(C_Block, "call", Fblk_call, -2); + rb_define_method(cProc, "call", proc_call, -2); + rb_define_private_method(cKernel, "lambda", f_lambda, 0); + rb_define_private_method(cKernel, "proc", f_lambda, 0); } diff --git a/ext/MANIFEST b/ext/MANIFEST deleted file mode 100644 index 9580b61544..0000000000 --- a/ext/MANIFEST +++ /dev/null @@ -1,3 +0,0 @@ -MANIFEST -extmk.rb.in - diff --git a/ext/Setup b/ext/Setup new file mode 100644 index 0000000000..93586ea0e6 --- /dev/null +++ b/ext/Setup @@ -0,0 +1,7 @@ +#option nodynamic + +#dbm +#etc +#marshal +#socket +tkutil diff --git a/ext/dbm/MANIFEST b/ext/dbm/MANIFEST new file mode 100644 index 0000000000..141b8dd601 --- /dev/null +++ b/ext/dbm/MANIFEST @@ -0,0 +1,5 @@ +MANIFEST +dbm.c +dbm.doc +depend +extconf.rb diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c new file mode 100644 index 0000000000..dbdd99c0ca --- /dev/null +++ b/ext/dbm/dbm.c @@ -0,0 +1,435 @@ +/************************************************ + + dbm.c - + + $Author: matz $ + $Date: 1995/01/10 10:42:24 $ + created at: Mon Jan 24 15:59:52 JST 1994 + + Copyright (C) 1995 Yukihiro Matsumoto + +************************************************/ + +#include "ruby.h" + +#include <ndbm.h> +#include <fcntl.h> +#include <errno.h> + +VALUE cDBM; +static ID id_dbm; + +extern VALUE mEnumerable; + +static void +closeddbm() +{ + Fail("closed DBM file"); +} + +#define GetDBM(obj, dbmp) {\ + DBM **_dbm;\ + Get_Data_Struct(obj, id_dbm, DBM*, _dbm);\ + dbmp = *_dbm;\ + if (dbmp == Qnil) closeddbm();\ +} + +static void +free_dbm(dbmp) + DBM **dbmp; +{ + if (*dbmp) dbm_close(*dbmp); +} + +#define MakeDBM(obj, dp) {\ + DBM **_dbm;\ + if (!id_dbm) id_dbm = rb_intern("dbm");\ + Make_Data_Struct(obj,id_dbm,DBM*,Qnil,free_dbm,_dbm);\ + *_dbm=dp;\ +} + +static VALUE +fdbm_s_open(argc, argv, class) + int argc; + VALUE *argv; + VALUE class; +{ + VALUE file, vmode; + DBM *dbm, **dbm2; + int mode; + VALUE obj; + + if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) { + mode = 0666; /* default value */ + } + else if (NIL_P(vmode)) { + mode = -1; /* return nil if DB not exist */ + } + else { + mode = NUM2INT(vmode); + } + Check_Type(file, T_STRING); + + dbm = Qnil; + if (mode >= 0) + dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode); + if (!dbm) + dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, mode); + if (!dbm) + dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, mode); + + if (!dbm) { + if (mode == -1) return Qnil; + rb_sys_fail(RSTRING(file)->ptr); + } + + obj = obj_alloc(class); + MakeDBM(obj, dbm); + + return obj; +} + +static VALUE +fdbm_close(obj) + VALUE obj; +{ + DBM **dbmp; + + Get_Data_Struct(obj, id_dbm, DBM*, dbmp); + if (*dbmp == Qnil) Fail("already closed DBM file"); + dbm_close(*dbmp); + *dbmp = Qnil; + + return Qnil; +} + +static VALUE +fdbm_fetch(obj, keystr) + VALUE obj, keystr; +{ + datum key, value; + DBM *dbm; + + Check_Type(keystr, T_STRING); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + + GetDBM(obj, dbm); + value = dbm_fetch(dbm, key); + if (value.dptr == Qnil) { + return Qnil; + } + return str_new(value.dptr, value.dsize); +} + +static VALUE +fdbm_indexes(obj, args) + VALUE obj; + struct RArray *args; +{ + VALUE *p, *pend; + struct RArray *new; + int i = 0; + + if (!args || args->len == 1 && TYPE(args->ptr) != T_ARRAY) { + args = (struct RArray*)rb_to_a(args->ptr[0]); + } + + new = (struct RArray*)ary_new2(args->len); + + p = args->ptr; pend = p + args->len; + while (p < pend) { + new->ptr[i++] = fdbm_fetch(obj, *p++); + new->len = i; + } + return (VALUE)new; +} + +static VALUE +fdbm_delete(obj, keystr) + VALUE obj, keystr; +{ + datum key; + DBM *dbm; + + Check_Type(keystr, T_STRING); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + + GetDBM(obj, dbm); + if (dbm_delete(dbm, key)) { + Fail("dbm_delete failed"); + } + return obj; +} + +static VALUE +fdbm_shift(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE keystr, valstr; + + GetDBM(obj, dbm); + + key = dbm_firstkey(dbm); + if (!key.dptr) return Qnil; + val = dbm_fetch(dbm, key); + dbm_delete(dbm, key); + + keystr = str_new(key.dptr, key.dsize); + valstr = str_new(val.dptr, val.dsize); + return assoc_new(keystr, valstr); +} + +static VALUE +fdbm_delete_if(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE keystr, valstr; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + keystr = str_new(key.dptr, key.dsize); + valstr = str_new(val.dptr, val.dsize); + if (rb_yield(assoc_new(keystr, valstr)) + && dbm_delete(dbm, key)) { + Fail("dbm_delete failed"); + } + } + return obj; +} + +static VALUE +fdbm_clear(obj) + VALUE obj; +{ + datum key; + DBM *dbm; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + if (dbm_delete(dbm, key)) { + Fail("dbm_delete failed"); + } + } + return obj; +} + +static VALUE +fdbm_store(obj, keystr, valstr) + VALUE obj, keystr, valstr; +{ + datum key, val; + DBM *dbm; + + if (valstr == Qnil) { + fdbm_delete(obj, keystr); + return Qnil; + } + + Check_Type(keystr, T_STRING); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + Check_Type(valstr, T_STRING); + val.dptr = RSTRING(valstr)->ptr; + val.dsize = RSTRING(valstr)->len; + + GetDBM(obj, dbm); + if (dbm_store(dbm, key, val, DBM_REPLACE)) { + dbm_clearerr(dbm); + if (errno == EPERM) rb_sys_fail(Qnil); + Fail("dbm_store failed"); + } + return valstr; +} + +static VALUE +fdbm_length(obj) + VALUE obj; +{ + datum key; + DBM *dbm; + int i = 0; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + i++; + } + return INT2FIX(i); +} + +static VALUE +fdbm_each_value(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + rb_yield(str_new(val.dptr, val.dsize)); + } + return obj; +} + +static VALUE +fdbm_each_key(obj) + VALUE obj; +{ + datum key; + DBM *dbm; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + rb_yield(str_new(key.dptr, key.dsize)); + } + return obj; +} + +static VALUE +fdbm_each_pair(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE keystr, valstr; + + GetDBM(obj, dbm); + + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + keystr = str_new(key.dptr, key.dsize); + valstr = str_new(val.dptr, val.dsize); + rb_yield(assoc_new(keystr, valstr)); + } + + return obj; +} + +static VALUE +fdbm_keys(obj) + VALUE obj; +{ + datum key; + DBM *dbm; + VALUE ary; + + ary = ary_new(); + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + ary_push(ary, str_new(key.dptr, key.dsize)); + } + + return ary; +} + +static VALUE +fdbm_values(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE ary; + + ary = ary_new(); + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + ary_push(ary, str_new(val.dptr, val.dsize)); + } + + return ary; +} + +static VALUE +fdbm_has_key(obj, keystr) + VALUE obj, keystr; +{ + datum key, val; + DBM *dbm; + + Check_Type(keystr, T_STRING); + key.dptr = RSTRING(keystr)->ptr; + key.dsize = RSTRING(keystr)->len; + + GetDBM(obj, dbm); + val = dbm_fetch(dbm, key); + if (val.dptr) return TRUE; + return FALSE; +} + +static VALUE +fdbm_has_value(obj, valstr) + VALUE obj, valstr; +{ + datum key, val; + DBM *dbm; + + Check_Type(valstr, T_STRING); + val.dptr = RSTRING(valstr)->ptr; + val.dsize = RSTRING(valstr)->len; + + GetDBM(obj, dbm); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + if (val.dsize == RSTRING(valstr)->len && + memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0) + return TRUE; + } + return FALSE; +} + +static VALUE +fdbm_to_a(obj) + VALUE obj; +{ + datum key, val; + DBM *dbm; + VALUE ary; + + GetDBM(obj, dbm); + + ary = ary_new(); + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + ary_push(ary, assoc_new(str_new(key.dptr, key.dsize), + str_new(val.dptr, val.dsize))); + } + + return ary; +} + +Init_dbm() +{ + cDBM = rb_define_class("DBM", cObject); + rb_include_module(cDBM, mEnumerable); + + rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1); + rb_define_method(cDBM, "close", fdbm_close, 0); + rb_define_method(cDBM, "[]", fdbm_fetch, 1); + rb_define_method(cDBM, "[]=", fdbm_store, 2); + rb_define_method(cDBM, "indexes", fdbm_indexes, -2); + rb_define_method(cDBM, "length", fdbm_length, 0); + rb_define_alias(cDBM, "size", "length"); + rb_define_method(cDBM, "each", fdbm_each_pair, 0); + rb_define_method(cDBM, "each_value", fdbm_each_value, 0); + rb_define_method(cDBM, "each_key", fdbm_each_key, 0); + rb_define_method(cDBM, "each_pair", fdbm_each_pair, 0); + rb_define_method(cDBM, "keys", fdbm_keys, 0); + rb_define_method(cDBM, "values", fdbm_values, 0); + rb_define_method(cDBM, "shift", fdbm_shift, 1); + rb_define_method(cDBM, "delete", fdbm_delete, 1); + rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0); + rb_define_method(cDBM, "clear", fdbm_clear, 0); + rb_define_method(cDBM, "includes", fdbm_has_key, 1); + rb_define_method(cDBM, "has_key", fdbm_has_key, 1); + rb_define_method(cDBM, "has_value", fdbm_has_value, 1); + + rb_define_method(cDBM, "to_a", fdbm_to_a, 0); +} diff --git a/ext/dbm/dbm.doc b/ext/dbm/dbm.doc new file mode 100644 index 0000000000..45f174b7aa --- /dev/null +++ b/ext/dbm/dbm.doc @@ -0,0 +1,107 @@ +.\" dbm.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:28:31 JST 1995 + +** DBM(饹) + +NDBMե륯饹ǡȤʸǤʤФ +ʤȤ¤ȡǡե¸ȤƤ +Dict饹Ʊͤ˰ȤǤ롥NDBMƤʤƥǤ +Υ饹ʤ + +SuperClass: Object + +Included Modules: Enumerable + +Methods: + + self [key] + + keyȤ֤ͤ + + self [key]= value + + keyȤơvalueǼ롥valueȤnilꤹȡ + keyФܤκȤʤ롥 + + clear + + DBMեȤˤ롥 + + close + + DBMե롥ʸ㳰ȯ롥 + + delete(key) + + keyȤȤ롥 + + delete_if + + Ǥ륤ƥ졼key::valueȤڥͿơ֥ + ɾͤλܤ롥 + + each + each_pair + + key::valueʤڥͿ륤ƥ졼 + + each_key + + ƤkeyФƷ֤ƥ졼 + + each_value + + ƤvalueФƷ֤ƥ졼 + + has_key(key) + includes(key) + + keyǡ١¸ߤ֤ + + has_value(value) + + valueͤȤȤǡ١¸ߤ + ֤ + + indexes(ary) + indexes(key-1, ..., key-n) + + 1ܤηǤʸȤƼơǤ + ȤǤޤ֤2ܤηǤϳưͤ + Ǥޤ֤. + + keys + + ǡ١¸ߤ륭Ƥޤ֤ + + length + size + + ǡ١Ǥο֤(:ߤμ¸Ǥǿ + 뤿˥ǡ١Τǡ빽Ȥ⤤ + ĤƻȤ.) + + shift + + ǡ١ǤļФ(ǡ١) + key::valueȤڥ֤ + + to_a + + ǡ١key-valueڥǤȤ֤ + + values + + ǡ١¸ߤƤޤ֤ + +Single Methods: + + open(dbname[, mode]) + + dbnameǻꤷǡ١⡼ɤmodeꤷƥץ + 롥modeξάͤ0666Ǥ롥modeȤnilꤹȥǡ + ١¸ߤʤˤϿ˥ץnil֤ + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/dbm/depend b/ext/dbm/depend new file mode 100644 index 0000000000..40139962a7 --- /dev/null +++ b/ext/dbm/depend @@ -0,0 +1 @@ +dbm.o: dbm.c ../../ruby.h ../../config.h ../../defines.h diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb new file mode 100644 index 0000000000..5105cd662f --- /dev/null +++ b/ext/dbm/extconf.rb @@ -0,0 +1,4 @@ +have_library("dbm", "dbm_open") +if have_func("dbm_open") + create_makefile("dbm") +end diff --git a/ext/etc/MANIFEST b/ext/etc/MANIFEST new file mode 100644 index 0000000000..a0f521b386 --- /dev/null +++ b/ext/etc/MANIFEST @@ -0,0 +1,5 @@ +MANIFEST +etc.c +etc.doc +depend +extconf.rb diff --git a/ext/etc/depend b/ext/etc/depend new file mode 100644 index 0000000000..5c95ef117a --- /dev/null +++ b/ext/etc/depend @@ -0,0 +1 @@ +etc.o : etc.c ../../ruby.h ../../config.h ../../defines.h @@ -9,62 +9,77 @@ ************************************************/ #include "ruby.h" + +#ifdef HAVE_GETPWENT #include <pwd.h> +#endif + +#ifdef HAVE_GETGRENT #include <grp.h> +#endif -char *getlogin(); +static VALUE sPasswd, sGroup; static VALUE -Fetc_getlogin(obj) +etc_getlogin(obj) VALUE obj; { +#ifdef HAVE_GETLOGIN + char *getlogin(); char *login = getlogin(); +#else + char *getenv(); + char *login = getenv("USER"); +#endif if (login) return str_new2(login); return Qnil; } +#ifdef HAVE_GETPWENT static VALUE setup_passwd(pwd) struct passwd *pwd; { if (pwd == Qnil) rb_sys_fail("/etc/passwd"); - return struct_new("passwd", - "name", str_new2(pwd->pw_name), - "passwd", str_new2(pwd->pw_passwd), - "uid", INT2FIX(pwd->pw_uid), - "gid", INT2FIX(pwd->pw_gid), - "gecos", str_new2(pwd->pw_gecos), - "dir", str_new2(pwd->pw_dir), - "shell", str_new2(pwd->pw_shell), + return struct_new(sPasswd, + str_new2(pwd->pw_name), + str_new2(pwd->pw_passwd), + INT2FIX(pwd->pw_uid), + INT2FIX(pwd->pw_gid), + str_new2(pwd->pw_gecos), + str_new2(pwd->pw_dir), + str_new2(pwd->pw_shell), #ifdef PW_CHANGE - "change", INT2FIX(pwd->pw_change), + INT2FIX(pwd->pw_change), #endif #ifdef PW_QUOTA - "quota", INT2FIX(pwd->pw_quota), + INT2FIX(pwd->pw_quota), #endif #ifdef PW_AGE - "age", INT2FIX(pwd->pw_age), + INT2FIX(pwd->pw_age), #endif #ifdef PW_CLASS - "class", str_new2(pwd->pw_class), + str_new2(pwd->pw_class), #endif #ifdef PW_COMMENT - "comment", str_new2(pwd->pw_comment), + str_new2(pwd->pw_comment), #endif #ifdef PW_EXPIRE - "expire", INT2FIX(pwd->pw_expire), + INT2FIX(pwd->pw_expire), #endif Qnil); } +#endif static VALUE -Fetc_getpwuid(argc, argv, obj) +etc_getpwuid(argc, argv, obj) int argc; VALUE *argv; VALUE obj; { +#ifdef HAVE_GETPWENT VALUE id; int uid; struct passwd *pwd; @@ -78,24 +93,32 @@ Fetc_getpwuid(argc, argv, obj) pwd = getpwuid(uid); if (pwd == Qnil) Fail("can't find user for %d", uid); return setup_passwd(pwd); +#else + return Qnil; +#endif } static VALUE -Fetc_getpwnam(obj, nam) +etc_getpwnam(obj, nam) VALUE obj, nam; { +#ifdef HAVE_GETPWENT struct passwd *pwd; Check_Type(nam, T_STRING); pwd = getpwnam(RSTRING(nam)->ptr); if (pwd == Qnil) Fail("can't find user for %s", RSTRING(nam)->ptr); return setup_passwd(pwd); +#else + return Qnil; +#endif } static VALUE -Fetc_passwd(obj) +etc_passwd(obj) VALUE obj; { +#ifdef HAVE_GETPWENT struct passwd *pw; if (iterator_p()) { @@ -109,8 +132,12 @@ Fetc_passwd(obj) pw = getpwent(); if (pw == Qnil) Fail("can't fetch next -- /etc/passwd"); return setup_passwd(pw); +#else + return Qnil; +#endif } +#ifdef HAVE_GETGRENT static VALUE setup_group(grp) struct group *grp; @@ -124,18 +151,20 @@ setup_group(grp) ary_push(mem, str_new2(*tbl)); tbl++; } - return struct_new("group", - "name", str_new2(grp->gr_name), - "passwd", str_new2(grp->gr_passwd), - "gid", INT2FIX(grp->gr_gid), - "mem", mem, + return struct_new(sGroup, + str_new2(grp->gr_name), + str_new2(grp->gr_passwd), + INT2FIX(grp->gr_gid), + mem, Qnil); } +#endif static VALUE -Fetc_getgrgid(obj, id) +etc_getgrgid(obj, id) VALUE obj, id; { +#ifdef HAVE_GETGRENT int gid; struct group *grp; @@ -143,24 +172,32 @@ Fetc_getgrgid(obj, id) grp = getgrgid(gid); if (grp == Qnil) Fail("can't find group for %d", gid); return setup_group(grp); +#else + return Qnil; +#endif } static VALUE -Fetc_getgrnam(obj, nam) +etc_getgrnam(obj, nam) VALUE obj, nam; { +#ifdef HAVE_GETGRENT struct group *grp; Check_Type(nam, T_STRING); grp = getgrnam(RSTRING(nam)->ptr); if (grp == Qnil) Fail("can't find group for %s", RSTRING(nam)->ptr); return setup_group(grp); +#else + return Qnil; +#endif } static VALUE -Fetc_group(obj) +etc_group(obj) VALUE obj; { +#ifdef HAVE_GETGRENT struct group *grp; if (iterator_p()) { @@ -172,22 +209,52 @@ Fetc_group(obj) return obj; } return setup_group(getgrent()); +#else + return Qnil; +#endif } -VALUE M_Etc; +VALUE mEtc; -Init_Etc() +void +Init_etc() { - M_Etc = rb_define_module("Etc"); - rb_extend_object(M_Etc, M_Etc); + mEtc = rb_define_module("Etc"); + + rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0); - rb_define_method(M_Etc, "getlogin", Fetc_getlogin, 0); + rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1); + rb_define_module_function(mEtc, "getpwnam", etc_getpwnam, 1); + rb_define_module_function(mEtc, "passwd", etc_passwd, 0); - rb_define_method(M_Etc, "getpwuid", Fetc_getpwuid, -1); - rb_define_method(M_Etc, "getpwnam", Fetc_getpwnam, 1); - rb_define_method(M_Etc, "passwd", Fetc_passwd, 0); + rb_define_module_function(mEtc, "getgrgid", etc_getgrgid, 1); + rb_define_module_function(mEtc, "getgrnam", etc_getgrnam, 1); + rb_define_module_function(mEtc, "group", etc_group, 0); - rb_define_method(M_Etc, "getgrgid", Fetc_getgrgid, 1); - rb_define_method(M_Etc, "getgrnam", Fetc_getgrnam, 1); - rb_define_method(M_Etc, "group", Fetc_group, 0); + sPasswd = struct_define("Passwd", + "name", "passwd", "uid", "gid", + "gecos", "dir", "shell", +#ifdef PW_CHANGE + "change", +#endif +#ifdef PW_QUOTA + "quota", +#endif +#ifdef PW_AGE + "age", +#endif +#ifdef PW_CLASS + "class", +#endif +#ifdef PW_COMMENT + "comment", +#endif +#ifdef PW_EXPIRE + "expire", +#endif + Qnil); + +#ifdef HAVE_GETGRENT + sGroup = struct_define("Group", "name", "passwd", "gid", "mem", Qnil); +#endif } diff --git a/ext/etc/etc.doc b/ext/etc/etc.doc new file mode 100644 index 0000000000..2af895c9de --- /dev/null +++ b/ext/etc/etc.doc @@ -0,0 +1,73 @@ +.\" etc.doc - -*- Indented-Text -*- created at: Fri Jul 14 00:47:15 JST 1995 + +** Etc(⥸塼) + +/etcǥ쥯ȥʲξ뤿Υ⥸塼롥饹˥롼 +ƻȤȤǤ롥 + +Methods: +Single Methods: + + 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/etc/extconf.rb b/ext/etc/extconf.rb new file mode 100644 index 0000000000..884de93ec8 --- /dev/null +++ b/ext/etc/extconf.rb @@ -0,0 +1,7 @@ +have_library("sun", "getpwnam") # NIS (== YP) interface for IRIX 4 +a = have_func("getlogin") +b = have_func("getpwent") +c = have_func("getgrent") +if a or b or c + create_makefile("etc") +end diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index 25bf6b9027..b61ccd222f 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -1,10 +1,40 @@ #! /usr/local/bin/ruby +if $ARGV[0] == 'install' + $install = TRUE + $ARGV.shift +end + +if $ARGV[0] == 'clean' + $clean = TRUE + $ARGV.shift +end + +$cache_mod = FALSE; +$lib_cache = {} +$func_cache = {} +$hdr_cache = {} + +if File.exists?("config.cache") then + f = open("config.cache", "r") + while f.gets + case $_ + when /^lib: ([\w_]+) (yes|no)/ + $lib_cache[$1] = $2 + when /^func: ([\w_]+) (yes|no)/ + $func_cache[$1] = $2 + when /^hdr: (.+) (yes|no)/ + $hdr_cache[$1] = $2 + end + end + f.close +end + def older(file1, file2) - if !File.exists(file1) then + if !File.exists?(file1) then return TRUE end - if !File.exists(file2) then + if !File.exists?(file2) then return FALSE end if File.mtime(file1) < File.mtime(file2) @@ -13,77 +43,144 @@ def older(file1, file2) return FALSE end -if !File.exists("./Makefile") || - older("./Makefile", "../extmk.rb") || - older("./Makefile", "./extconf.rb") then +LINK = "@CC@ -o conftest %s %s conftest.c %s > /dev/null 2>&1" +CPP = "@CPP@ @CPPFLAGS@ %s conftest.c > /dev/null 2>&1" - LINK = "@CC@ -o conftest @CFLAGS@ @LDFLAGS@ conftest.c %s > /dev/null 2>&1" - $defs = [] +def have_library(lib, func) + if $lib_cache[lib] + if $lib_cache[lib] == "yes" + if $libs + $libs = $libs + " -l" + lib + else + $libs = "-l" + lib + end + return TRUE + else + return FALSE + end + end - def have_library(func, lib) - cfile = open("conftest.c", "w") - printf cfile, "\ + cfile = open("conftest.c", "w") + printf cfile, "\ int main() { return 0; } int t() { %s(); return 0; } ", func - cfile.close - - begin - if system(format(LINK, "-l" + lib)) != 0 - return FALSE - end - ensure - system "/bin/rm -f conftest*" - end + cfile.close + begin if $libs - $libs = $libs + " -l" + lib + libs = "-l" + lib + " " + $libs else - $libs = "-l" + lib + libs = "-l" + lib end - $defs.push(format("-DHAVE_LIB%s", lib.toupper)) - return TRUE + if !system(format(LINK, $CFLAGS, $LDFLAGS, libs)) + $lib_cache[lib] = 'no' + $cache_mod = TRUE + return FALSE + end + ensure + system "/bin/rm -f conftest*" end - def have_func(func) + $libs = libs + $lib_cache[lib] = 'yes' + $cache_mod = TRUE + return TRUE +end - cfile = open("conftest.c", "w") - printf cfile, "\ +def have_func(func) + if $func_cache[func] + if $func_cache[func] == "yes" + $defs.push(format("-DHAVE_%s", func.upcase)) + return TRUE + else + return FALSE + end + end + + cfile = open("conftest.c", "w") + printf cfile, "\ char %s(); int main() { return 0; } int t() { %s(); return 0; } ", func, func - cfile.close + cfile.close - libs = $libs - libs = "" if libs == nil + libs = $libs + libs = "" if libs == nil - begin - if system(format(LINK, libs)) != 0 - return FALSE - end - ensure - system "/bin/rm -f conftest*" + begin + if !system(format(LINK, $CFLAGS, $LDFLAGS, libs)) + $func_cache[func] = 'no' + $cache_mod = TRUE + return FALSE end - $defs.push(format("-DHAVE_%s", func.toupper)) - return TRUE + ensure + system "/bin/rm -f conftest*" + end + $defs.push(format("-DHAVE_%s", func.upcase)) + $func_cache[func] = 'yes' + $cache_mod = TRUE + return TRUE +end +def have_header(header) + if $hdr_cache[header] + if $hdr_cache[header] == "yes" + header.tr!("a-z./\055", "A-Z___") + $defs.push(format("-DHAVE_%s", header)) + return TRUE + else + return FALSE + end end - def create_header() - if $defs.length > 0 - hfile = open("extconf.h", "w") - for line in $defs - line =~ /^-D(.*)/ - printf hfile, "#define %s 1\n", $1 - end - hfile.close + cfile = open("conftest.c", "w") + printf cfile, "\ +#include <%s> +", header + cfile.close + + begin + if !system(format(CPP, $CFLAGS)) + $hdr_cache[header] = 'no' + $cache_mod = TRUE + return FALSE end + ensure + system "/bin/rm -f conftest*" end + $hdr_cache[header] = 'yes' + header.tr!("a-z./\055", "A-Z___") + $defs.push(format("-DHAVE_%s", header)) + $cache_mod = TRUE + return TRUE +end - def create_makefile(target) - mfile = open("Makefile", "w") - printf mfile, "\ +def create_header() + if $defs.length > 0 + hfile = open("extconf.h", "w") + for line in $defs + line =~ /^-D(.*)/ + printf hfile, "#define %s 1\n", $1 + end + hfile.close + end +end + +def create_makefile(target) + + if $libs and "@DLEXT@" == "o" + libs = $libs.split + for lib in libs + lib.sub!(/-l(.*)/, '"lib\1.a"') + end + $defs.push(format("-DEXTLIB='%s'", libs.join(","))) + end + $libs = "" if not $libs + + mfile = open("Makefile", "w") + printf mfile, "\ SHELL = /bin/sh #### Start of system configuration section. #### @@ -93,84 +190,205 @@ VPATH = @srcdir@ CC = @CC@ -CFLAGS = -I../.. @CCDLFLAGS@ @CFLAGS@ %s -LDDLFLAGS = @LDDLFLAGS@ -", $defs.join(" ") +CFLAGS = %s #$CFLAGS %s +LDSHARED = @LDSHARED@ +", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ") - printf mfile, "\ + printf mfile, "\ prefix = @prefix@ binprefix = exec_prefix = @exec_prefix@ bindir = $(exec_prefix)/bin +libdir = @prefix@/lib/ruby @SET_MAKE@ #### End of system configuration section. #### " - printf mfile, "OBJS = " - if !$objs then - $objs = Dir["*.c"] - for f in $objs - f.sub(/\.c$/, ".o") - end + printf mfile, "LIBS = %s\n", $libs + printf mfile, "OBJS = " + if !$objs then + $objs = Dir["*.c"] + for f in $objs + f.sub!(/\.c$/, ".o") end - printf mfile, $objs.join(" ") - printf mfile, "\n" + end + printf mfile, $objs.join(" ") + printf mfile, "\n" - printf mfile, "\ -TARGET = %s.@DLEXT@ + printf mfile, "\ +TARGET = %s.%s + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ all: $(TARGET) -clean:; @rm -f *.o *.so +clean:; @rm -f *.o *.so *.sl @rm -f Makefile extconf.h conftest.* @rm -f core ruby *~ realclean: clean -", target +", target, if $static then "o" else "@DLEXT@" end + + if !$static + printf mfile, "\ + +install: $(libdir)/$(TARGET) + +$(libdir)/$(TARGET): $(TARGET) + @test -d $(libdir) || mkdir $(libdir) + $(INSTALL_DATA) $(TARGET) $(libdir)/$(TARGET) +" + else + printf mfile, "\ - if "@DLEXT@" == "so" - printf mfile, "\ -.SUFFIXES: .so $(SUFFIXES) +install:; +" + end -$(TARGET).so: $(OBJS) - ld $(LDDLFLAGS) -o $*.so $(OBJS) + if !$static && "@DLEXT@" != "o" + printf mfile, "\ +$(TARGET): $(OBJS) + $(LDSHARED) -o $(TARGET) $(OBJS) $(LIBS) " - elsif !File.exists(target + ".c") - printf mfile, "\ -$(TARGET).o: $(OBJS) - ld $(LDDLFLAGS) -r $*.o $(OBJS) + elsif !File.exists?(target + ".c") + printf mfile, "\ +$(TARGET): $(OBJS) + ld $(LDDLFLAGS) -r $(TARGET) $(OBJS) " + end + + if File.exists?("depend") + dfile = open("depend", "r") + printf mfile, "###\n" + while line = dfile.gets() + printf mfile, "%s", line end + dfile.close + end + mfile.close + if $static + $extinit += format("\ +\tInit_%s();\n\ +\trb_provide(\"%s.o\");\n\ +", target, target) + $extobjs += format("ext/%s/%s.o ", $static, target) + end +end - if File.exists("depend") - dfile = open("depend", "r") - printf mfile, "###\n" - while line = dfile.gets() - printf mfile, "%s", line +def extmake(target) + if $static_ext[target] + $static = target + else + $static = FALSE + end + + return if $nodynamic and not $static + + $libs = nil + $objs = nil + $CFLAGS = "-I../.. @CFLAGS@" + $LDFLAGS = "@STATIC@ @LDFLAGS@" + + begin + Dir.chdir target + if $static_ext.size > 0 || + !File.exists?("./Makefile") || + older("./Makefile", "../Setup") || + older("./Makefile", "../extmk.rb") || + older("./Makefile", "./extconf.rb") + then + $defs = [] + if File.exists?("extconf.rb") + load "extconf.rb" + else + create_makefile(target); + end + end + if File.exists?("./Makefile") + if $install + system "make install" + elsif $clean + system "make clean" + else + system "make all" end - dfile.close end - mfile.close + $extlibs += " " + $libs if $static && $libs + ensure + Dir.chdir ".." end +end - if File.exists("configure") && - (!File.exists("config.status") || - File.mtime("config.status") < File.mtime("configure")) then +# get static-link modules +$static_ext = {} +if File.file? "./Setup" + f = open("./Setup") + while f.gets() + $_.chop! + sub!(/#.*$/, '') + continue if /^\s*$/ + if /^option +nodynamic/ + $nodynamic = TRUE + continue + end + $static_ext[$_.split[0]] = TRUE + end + f.close +end - system "./configure" +for d in Dir["*"] + File.directory?(d) || continue + File.file?(d + "/MANIFEST") || continue + + d = $1 if d =~ /\/([\/]*)$/ + print "compiling ", d, "\n" + extmake(d) +end + +if $cache_mod + f = open("config.cache", "w") + for k,v in $lib_cache + printf f, "lib: %s %s\n", k, v + end + for k,v in $func_cache + printf f, "func: %s %s\n", k, v end + for k,v in $hdr_cache + printf f, "hdr: %s %s\n", k, v + end + f.close +end - if File.exists("extconf.rb") - load "extconf.rb" - else - Dir.pwd =~ /[^\/]+$/ - create_makefile($&); +exit if $install +if $extobjs + if older("extinit.c", "Setup") + f = open("extinit.c", "w") + printf f, "void Init_ext() {\n" + printf f, $extinit + printf f, "}\n" + f.close + end + if older("extinit.o", "extinit.c") + cmd = "@CC@ @CFLAGS@ -c extinit.c" + print cmd, "\n" + system cmd or exit 1 end + Dir.chdir ".." + $extobjs = "ext/extinit.o " + $extobjs + + if older("ruby", "ext/Setup") or older("ruby", "miniruby") + `rm -f ruby` + end + system format('make ruby PROGRAM=ruby EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs) +else + Dir.chdir ".." + `rm -f ruby` + `cp miniruby ruby` end -system "make all" if File.exists("./Makefile") #Local variables: # mode: ruby diff --git a/ext/marshal/MANIFEST b/ext/marshal/MANIFEST new file mode 100644 index 0000000000..53b0849484 --- /dev/null +++ b/ext/marshal/MANIFEST @@ -0,0 +1,4 @@ +MANIFEST +depend +marshal.c +marshal.doc diff --git a/ext/marshal/depend b/ext/marshal/depend new file mode 100644 index 0000000000..c955eb2d59 --- /dev/null +++ b/ext/marshal/depend @@ -0,0 +1,2 @@ +marshal.o: marshal.c ../../ruby.h ../../config.h ../../defines.h ../../io.h \ + ../../st.h diff --git a/ext/marshal/marshal.c b/ext/marshal/marshal.c new file mode 100644 index 0000000000..0b29ad5ab8 --- /dev/null +++ b/ext/marshal/marshal.c @@ -0,0 +1,565 @@ +/************************************************ + + marshal.c - + + $Author$ + $Revision$ + $Date$ + created at: Thu Apr 27 16:30:01 JST 1995 + +************************************************/ + +#include "ruby.h" +#include "io.h" +#include "st.h" + +#define TYPE_NIL '0' +#define TYPE_FIXNUM 'i' + +#define TYPE_OBJECT 'o' +#define TYPE_LINK '@' +#define TYPE_FLOAT 'f' +#define TYPE_BIGNUM 'l' +#define TYPE_STRING '"' +#define TYPE_REGEXP '/' +#define TYPE_ARRAY '[' +#define TYPE_HASH '{' +#define TYPE_STRUCT 'S' + +char *rb_class2path(); +VALUE rb_path2class(); + +static ID s_dump, s_load; + +#define w_byte(c, fp) putc((c), fp) +#define w_bytes(s, n, fp) (w_long((n), fp),fwrite(s, 1, n, fp)) + +static void +w_short(x, fp) + int x; + FILE *fp; +{ + w_byte( x & 0xff, fp); + w_byte((x>> 8) & 0xff, fp); +} + +static void +w_long(x, fp) + long x; + FILE *fp; +{ + w_byte((int)( x & 0xff), fp); + w_byte((int)((x>> 8) & 0xff), fp); + w_byte((int)((x>>16) & 0xff), fp); + w_byte((int)((x>>24) & 0xff), fp); +} + +static void +w_float(d, fp) + double d; + FILE *fp; +{ + char buf[100]; + + sprintf(buf, "%.12g", d); + w_bytes(buf, strlen(buf), fp); +} + +static void +w_symbol(id, fp) + ID id; + FILE *fp; +{ + char *sym = rb_id2name(id); + + w_bytes(sym, strlen(sym), fp); +} + +static void w_object(); +extern VALUE cBignum, cStruct; + +static int +hash_each(key, value, fp) + VALUE key, value; + FILE *fp; +{ + w_object(key, fp); + w_object(value, fp); + return ST_CONTINUE; +} + +static int +obj_each(id, value, fp) + ID id; + VALUE value; + FILE *fp; +{ + w_symbol(id, fp); + w_object(value, fp); + return ST_CONTINUE; +} + +struct st_table *new_idhash(); + +static void +w_object(obj, fp, port, table) + VALUE obj, port; + FILE *fp; + st_table *table; +{ + if (obj == Qnil) { + w_byte(TYPE_NIL, fp); + } + else if (FIXNUM_P(obj)) { + w_byte(TYPE_FIXNUM, fp); + w_long(FIX2INT(obj), fp); + } + else if (st_lookup(table, obj, 0)) { + w_byte(TYPE_LINK, fp); + w_long(obj, fp); + } + else { + st_insert(table, obj, 0); + switch (BUILTIN_TYPE(obj)) { + case T_FLOAT: + w_byte(TYPE_FLOAT, fp); + w_long(obj, fp); + w_float(RFLOAT(obj)->value, fp); + break; + + case T_BIGNUM: + w_byte(TYPE_BIGNUM, fp); + w_long(obj, fp); + { + char sign = RBIGNUM(obj)->sign?'+':'-'; + int len = RBIGNUM(obj)->len; + USHORT *d = RBIGNUM(obj)->digits; + + w_byte(sign, fp); + w_long(len, fp); + while (len--) { + w_short(d, fp); + d++; + } + } + break; + + case T_STRING: + w_byte(TYPE_STRING, fp); + w_long(obj, fp); + w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); + break; + + case T_REGEXP: + w_byte(TYPE_REGEXP, fp); + w_long(obj, fp); + w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, fp); + w_byte(FL_TEST(obj, FL_USER1), fp); + break; + + case T_ARRAY: + w_byte(TYPE_ARRAY, fp); + w_long(obj, fp); + { + int len = RARRAY(obj)->len; + VALUE *ptr = RARRAY(obj)->ptr; + + w_long(len, fp); + while (len--) { + w_object(*ptr, fp, port, table); + ptr++; + } + } + break; + + case T_HASH: + w_byte(TYPE_HASH, fp); + w_long(obj, fp); + w_long(RHASH(obj)->tbl->num_entries, fp); + st_foreach(RHASH(obj)->tbl, hash_each, fp); + break; + + case T_STRUCT: + w_byte(TYPE_STRUCT, fp); + w_long(obj, fp); + { + int len = RSTRUCT(obj)->len; + char *path = rb_class2path(CLASS_OF(obj)); + VALUE mem; + int i; + + w_bytes(path, strlen(path), fp); + w_long(len, fp); + mem = rb_ivar_get(CLASS_OF(obj), rb_intern("__member__")); + if (mem == Qnil) { + Fail("non-initialized struct"); + } + for (i=0; i<len; i++) { + w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), fp); + w_object(RSTRUCT(obj)->ptr[i], fp, port, table); + } + } + break; + + case T_OBJECT: + w_byte(TYPE_OBJECT, fp); + w_long(obj, fp); + { + VALUE class = CLASS_OF(obj); + char *path = rb_class2path(class); + + w_bytes(path, strlen(path), fp); + if (rb_responds_to(obj, s_dump)) { + w_long(-1, fp); + rb_funcall(obj, s_dump, 1, port); + } + else if (ROBJECT(obj)->iv_tbl) { + w_long(ROBJECT(obj)->iv_tbl->num_entries, fp); + st_foreach(ROBJECT(obj)->iv_tbl, obj_each, fp); + } + else { + w_long(0, fp); + } + } + break; + + default: + Fail("can't dump %s", rb_class2name(CLASS_OF(obj))); + break; + } + } +} + +static VALUE +marshal_dump(self, obj, port) + VALUE self, obj, port; +{ + extern VALUE cIO; + FILE *fp; + OpenFile *fptr; + st_table *table; + + if (obj_is_kind_of(port, cIO)) { + GetOpenFile(port, fptr); + if (!(fptr->mode & FMODE_WRITABLE)) { + Fail("not opened for writing"); + } + fp = (fptr->f2) ? fptr->f2 : fptr->f; + } + else { + Fail("instance of IO needed"); + } + + table = new_idhash(); + + w_object(obj, fp, port, table); + + st_free_table(table); + return Qnil; +} + +static VALUE +marshal_dumps(self, obj) + VALUE self, obj; +{ + VALUE str = str_new(0, 0); + VALUE port; + FILE *fp = Qnil; + char buf[BUFSIZ]; + int n; + + sprintf(buf, "/tmp/rb-mrsr-%x", getpid()^(int)buf); + port = file_open(buf, "w"); + if (!port) rb_sys_fail("tmp file"); + fp = fopen(buf, "r"); + if (!fp) rb_sys_fail("tmp file(read)"); + unlink(buf); + + marshal_dump(self, obj, port); + io_close(port); + + while (n = fread(buf, 1, BUFSIZ, fp)) { + str_cat(str, buf, n); + } + + return str; +} + +#define r_byte(fp) getc(fp) + +static int +r_short(fp) + FILE *fp; +{ + register short x; + x = r_byte(fp); + x |= r_byte(fp) << 8; + /* XXX If your short is > 16 bits, add sign-extension here!!! */ + return x; +} + +static long +r_long(fp) + FILE *fp; +{ + register long x; + x = r_byte(fp); + x |= (long)r_byte(fp) << 8; + x |= (long)r_byte(fp) << 16; + x |= (long)r_byte(fp) << 24; + /* XXX If your long is > 32 bits, add sign-extension here!!! */ + return x; +} +#define r_bytes(s, fp) r_bytes0(&s, fp) +static int +r_bytes0(s, fp) + char **s; + FILE *fp; +{ + int len = r_long(fp); + *s = ALLOC_N(char, len+1); + + fread(*s, 1, len, fp); + (*s)[len] = '\0'; + return len; +} + +static ID +r_symbol(fp) + FILE *fp; +{ + char *buf; + ID id; + + r_bytes(buf, fp); + id = rb_intern(buf); + free(buf); + return id; +} + +static VALUE +r_object(fp, port, table) + FILE *fp; + VALUE port; + st_table *table; +{ + VALUE v; + int type = r_byte(fp); + int id; + + switch (type) { + case EOF: + Fail("EOF read where object expected"); + return Qnil; + + case TYPE_NIL: + return Qnil; + + case TYPE_LINK: + if (st_lookup(table, r_long(fp), &v)) { + return v; + } + Fail("corrupted marshal file"); + break; + + case TYPE_FIXNUM: + { + int i = r_long(fp); + return INT2FIX(i); + } + } + + id = r_long(fp); + switch (type) { + case TYPE_FLOAT: + { + double atof(); + char *buf; + + r_bytes(buf, fp); + v = float_new(atof(buf)); + free(buf); + } + break; + + case TYPE_BIGNUM: + { + int len; + USHORT *digits; + + NEWOBJ(big, struct RBignum); + OBJSETUP(big, cBignum, T_BIGNUM); + big->sign = (r_byte(fp) == '+'); + big->len = len = r_long(fp); + big->digits = digits = ALLOC_N(USHORT, len); + while (len--) { + *digits++ = r_short(fp); + } + v = (VALUE)big; + } + break; + + case TYPE_STRING: + { + char *buf; + int len = r_bytes(buf, fp); + v = str_new(buf, len); + free(buf); + } + break; + + case TYPE_REGEXP: + { + char *buf; + int len = r_bytes(buf, fp); + int ci = r_byte(fp); + v = reg_new(buf, len, ci); + free(buf); + } + break; + + case TYPE_ARRAY: + { + int len = r_long(fp); + v = ary_new2(len); + while (len--) { + ary_push(v, r_object(fp, port, table)); + } + } + break; + + case TYPE_HASH: + { + int len = r_long(fp); + + v = hash_new(); + while (len--) { + VALUE key = r_object(fp, port, table); + VALUE value = r_object(fp, port, table); + hash_aset(v, key, value); + } + } + break; + + case TYPE_STRUCT: + { + VALUE class, mem, values; + char *path; + int i, len; + + r_bytes(path, fp); + class = rb_path2class(path); + free(path); + mem = rb_ivar_get(class, rb_intern("__member__")); + if (mem == Qnil) { + Fail("non-initialized struct"); + } + len = r_long(fp); + + values = ary_new(); + i = 0; + while (len--) { + ID slot = r_symbol(fp); + if (RARRAY(mem)->ptr[i++] != INT2FIX(slot)) + Fail("struct not compatible"); + ary_push(values, r_object(fp, port, table)); + } + v = struct_alloc(class, values); + } + break; + + case TYPE_OBJECT: + { + VALUE class; + int len; + char *path; + + r_bytes(path, fp); + class = rb_path2class(path); + free(path); + len = r_long(fp); + if (len == -1) { + if (rb_responds_to(class, s_load)) { + v = rb_funcall(class, s_load, 1, port); + } + else { + Fail("class %s needs to have method `_load_from'", + rb_class2name(class)); + } + } + else { + v = obj_alloc(class); + if (len > 0) { + while (len--) { + ID id = r_symbol(fp); + VALUE val = r_object(fp, port, table); + rb_ivar_set(v, id, val); + } + } + } + } + break; + + default: + Fail("dump format error(0x%x)", type); + break; + } + st_insert(table, id, v); + return v; +} + +static VALUE +marshal_load(self, port) + VALUE self, port; +{ + extern VALUE cIO; + void *fp; + VALUE v; + OpenFile *fptr; + st_table *table; + + if (TYPE(port) == T_STRING) { + char buf[32]; + + sprintf(buf, "/tmp/rb-mrsw-%x", getpid()^(int)buf); + fp = fopen(buf, "w"); + if (!fp) rb_sys_fail("tmp file"); + v = file_open(buf, "r"); + if (!v) rb_sys_fail("tmp file(read)"); + unlink(buf); + + fwrite(RSTRING(port)->ptr, RSTRING(port)->len, 1, fp); + fclose(fp); + port = v; + } + if (obj_is_kind_of(port, cIO)) { + GetOpenFile(port, fptr); + if (!(fptr->mode & FMODE_READABLE)) { + Fail("not opened for reading"); + } + fp = fptr->f; + } + else { + Fail("instance of IO needed"); + } + + table = new_idhash(); + + v = r_object(fp, port, table); + + st_free_table(table); + + return v; +} + +Init_marshal() +{ + VALUE mMarshal = rb_define_module("Marshal"); + + s_dump = rb_intern("_dump_to"); + s_load = rb_intern("_load_from"); + rb_define_module_function(mMarshal, "dump", marshal_dump, 2); + rb_define_module_function(mMarshal, "dumps", marshal_dumps, 1); + rb_define_module_function(mMarshal, "load", marshal_load, 1); + rb_define_module_function(mMarshal, "restore", marshal_load, 1); +} diff --git a/ext/marshal/marshal.doc b/ext/marshal/marshal.doc new file mode 100644 index 0000000000..8c3b63072e --- /dev/null +++ b/ext/marshal/marshal.doc @@ -0,0 +1,45 @@ +.\" marshal.doc - -*- Indented-Text -*- created at: Tue May 16 12:18:08 JST 1995 + +** Marshal(⥸塼) + +ruby֥Ȥե˽Фꡤɤߤ٤ꤹ뵡ǽ +⥸塼롥ʬΥ饹ΥФǤ뤬ե +ؤԲǽʥ饹¸ߤ(:IO)Τ褦ʥ饹Ф +㳰ȯ롥 + +Methods: +Single Methods: + + dump(obj, port) + + objƵŪ˥ե˽Фե˽Фʤ饹Υ + ե˽ФȤ㳰ȯ롥ե + ˽Фʤ饹ϰʲ̤ꡥ + + Class, Module, Data + + ޤΥ饹Ū˻ؤ饹(㤨IOΥ֥饹)ʤ + ФʤportIO(ޤϤΥ֥饹)Υ + 롥 + + Ϥ륪֥Ȥå`_dump_to'Ƥˤϡե + ϤϤΥåɤȤäƹԤ롥å`_dump_to'ϰ + ƽΥե륪֥Ȥ롥å + `_dump_to'ĥ饹ɬƱեޥåȤɤ᤹ðۥå + `_load_from'ɬפ롥 + + + dumps(obj) + + dump()ե˽ФΤƱƤޤʸ֤ + + load(port) + + port饪֥Ȥɤ߹ơΥ֥ȤƱ֤ + ĥ֥Ȥ롥portʸIO(ޤϤΥ֥饹) + ΥǤ롥 + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/socket/MANIFEST b/ext/socket/MANIFEST new file mode 100644 index 0000000000..836caada41 --- /dev/null +++ b/ext/socket/MANIFEST @@ -0,0 +1,5 @@ +MANIFEST +depend +extconf.rb +socket.c +socket.doc diff --git a/ext/socket/depend b/ext/socket/depend new file mode 100644 index 0000000000..e6ede5a411 --- /dev/null +++ b/ext/socket/depend @@ -0,0 +1 @@ +socket.o : socket.c ../../ruby.h ../../config.h ../../defines.h ../../io.h ../../sig.h diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb new file mode 100644 index 0000000000..60d6deeb84 --- /dev/null +++ b/ext/socket/extconf.rb @@ -0,0 +1,6 @@ +have_library("inet", "gethostbyname") +have_library("socket", "socket") +have_header("sys/un.h") +if have_func("socket") + create_makefile("socket") +end diff --git a/ext/socket/socket.c b/ext/socket/socket.c new file mode 100644 index 0000000000..5671b2762c --- /dev/null +++ b/ext/socket/socket.c @@ -0,0 +1,785 @@ +/************************************************ + + socket.c - + + $Author: matz $ + $Date: 1995/01/10 10:42:55 $ + created at: Thu Mar 31 12:21:29 JST 1994 + +************************************************/ + +#include "ruby.h" +#include "io.h" +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <errno.h> +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#else +#undef AF_UNIX +#endif + +extern VALUE cIO; +VALUE cBasicSocket; +VALUE cTCPsocket; +VALUE cTCPserver; +#ifdef AF_UNIX +VALUE cUNIXsocket; +VALUE cUNIXserver; +#endif +VALUE cSocket; + +FILE *rb_fdopen(); +char *strdup(); + +#ifdef NT +static void +sock_finalize(fptr) + OpenFile *fptr; +{ + SOCKET s = fileno(fptr->f); + free(fptr->f); + free(fptr->f2); + closesocket(s); +} +#endif + +static VALUE +sock_new(class, fd) + VALUE class; + int fd; +{ + VALUE sock = obj_alloc(class); + OpenFile *fp; + + MakeOpenFile(sock, fp); +#ifdef NT + fp->finalize = sock_finalize; +#endif + fp->f = rb_fdopen(fd, "r"); + setbuf(fp->f, NULL); + fp->f2 = rb_fdopen(fd, "w"); + fp->mode = FMODE_READWRITE|FMODE_SYNC; + + return sock; +} + +static VALUE +bsock_shutdown(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + VALUE howto; + int how; + OpenFile *fptr; + + rb_scan_args(argc, argv, "01", &howto); + if (howto == Qnil) + how = 2; + else { + how = NUM2INT(howto); + if (how < 0 && how > 2) how = 2; + } + GetOpenFile(sock, fptr); + if (shutdown(fileno(fptr->f), how) == -1) + rb_sys_fail(Qnil); + + return INT2FIX(0); +} + +static VALUE +bsock_setopt(sock, lev, optname, val) + VALUE sock, lev, optname; + struct RString *val; +{ + int level, option; + OpenFile *fptr; + + level = NUM2INT(lev); + option = NUM2INT(optname); + Check_Type(val, T_STRING); + + GetOpenFile(sock, fptr); + if (setsockopt(fileno(fptr->f), level, option, val->ptr, val->len) < 0) + rb_sys_fail(fptr->path); + + return INT2FIX(0); +} + +static VALUE +bsock_getopt(sock, lev, optname) + VALUE sock, lev, optname; +{ + int level, option, len; + struct RString *val; + OpenFile *fptr; + + level = NUM2INT(lev); + option = NUM2INT(optname); + len = 256; + val = (struct RString*)str_new(0, len); + Check_Type(val, T_STRING); + + GetOpenFile(sock, fptr); + if (getsockopt(fileno(fptr->f), level, option, val->ptr, &len) < 0) + rb_sys_fail(fptr->path); + val->len = len; + return (VALUE)val; +} + +static VALUE +bsock_getsockname(sock) + VALUE sock; +{ + char buf[1024]; + int len = sizeof buf; + OpenFile *fptr; + + GetOpenFile(sock, fptr); + if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0) + rb_sys_fail("getsockname(2)"); + return str_new(buf, len); +} + +static VALUE +bsock_getpeername(sock) + VALUE sock; +{ + char buf[1024]; + int len = sizeof buf; + OpenFile *fptr; + + GetOpenFile(sock, fptr); + if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0) + rb_sys_fail("getpeername(2)"); + return str_new(buf, len); +} + +static VALUE +open_inet(class, h, serv, server) + VALUE class, h, serv; + int server; +{ + char *host; + struct hostent *hostent, _hostent; + struct servent *servent, _servent; + struct protoent *protoent; + struct sockaddr_in sockaddr; + int fd, status; + int hostaddr, hostaddrPtr[2]; + int servport; + char *syscall; + VALUE sock; + + if (h) { + Check_Type(h, T_STRING); + host = RSTRING(h)->ptr; + hostent = gethostbyname(host); + if (hostent == NULL) { + hostaddr = inet_addr(host); + if (hostaddr == -1) { + if (server && !strlen(host)) + hostaddr = INADDR_ANY; + else + rb_sys_fail(host); + } + _hostent.h_addr_list = (char **)hostaddrPtr; + _hostent.h_addr_list[0] = (char *)&hostaddr; + _hostent.h_addr_list[1] = NULL; + _hostent.h_length = sizeof(hostaddr); + _hostent.h_addrtype = AF_INET; + hostent = &_hostent; + } + } + servent = NULL; + if (FIXNUM_P(serv)) { + servport = FIX2UINT(serv); + goto setup_servent; + } + Check_Type(serv, T_STRING); + servent = getservbyname(RSTRING(serv)->ptr, "tcp"); + if (servent == NULL) { + servport = strtoul(RSTRING(serv)->ptr, Qnil, 0); + if (servport == -1) Fail("no such servce %s", RSTRING(serv)->ptr); + setup_servent: + _servent.s_port = servport; + _servent.s_proto = "tcp"; + servent = &_servent; + } + protoent = getprotobyname(servent->s_proto); + if (protoent == NULL) Fail("no such proto %s", servent->s_proto); + + fd = socket(PF_INET, SOCK_STREAM, protoent->p_proto); + + sockaddr.sin_family = AF_INET; + if (h == Qnil) { + sockaddr.sin_addr.s_addr = INADDR_ANY; + } + else { + memcpy((char *)&(sockaddr.sin_addr.s_addr), + (char *) hostent->h_addr_list[0], + (size_t) hostent->h_length); + } + sockaddr.sin_port = servent->s_port; + + if (server) { + status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + syscall = "bind(2)"; + } + else { + status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + syscall = "connect(2)"; + } + + if (status < 0) { + close (fd); + rb_sys_fail(syscall); + } + if (server) listen(fd, 5); + + /* create new instance */ + sock = sock_new(class, fd); + + return sock; +} + +static VALUE +tcp_s_sock_open(class, host, serv) + VALUE class, host, serv; +{ + Check_Type(host, T_STRING); + return open_inet(class, host, serv, 0); +} + +static VALUE +tcp_svr_s_open(argc, argv, class) + int argc; + VALUE *argv; + VALUE class; +{ + VALUE arg1, arg2; + + if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) + return open_inet(class, arg1, arg2, 1); + else + return open_inet(class, Qnil, arg1, 1); +} + +static VALUE +s_accept(class, fd, sockaddr, len) + VALUE class; + int fd; + struct sockaddr *sockaddr; + int *len; +{ + int fd2; + + retry: + fd2 = accept(fd, sockaddr, len); + if (fd2 < 0) { + if (errno == EINTR) goto retry; + rb_sys_fail(Qnil); + } + return sock_new(class, fd2); +} + +static VALUE +tcp_accept(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_in from; + int fromlen; + + GetOpenFile(sock, fptr); + fromlen = sizeof(struct sockaddr_in); + return s_accept(cTCPsocket, fileno(fptr->f), + (struct sockaddr*)&from, &fromlen); +} + +#ifdef AF_UNIX +static VALUE +open_unix(class, path, server) + VALUE class; + struct RString *path; + int server; +{ + struct sockaddr_un sockaddr; + int fd, status; + char *syscall; + VALUE sock; + OpenFile *fptr; + + Check_Type(path, T_STRING); + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) rb_sys_fail("socket(2)"); + + sockaddr.sun_family = AF_UNIX; + strncpy(sockaddr.sun_path, path->ptr, sizeof(sockaddr.sun_path)-1); + sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = '\0'; + + if (server) { + status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + syscall = "bind(2)"; + } + else { + status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + syscall = "connect(2)"; + } + + if (status < 0) { + close (fd); + rb_sys_fail(syscall); + } + + if (server) listen(fd, 5); + + sock = sock_new(class, fd); + GetOpenFile(sock, fptr); + fptr->path = strdup(path->ptr); + + return sock; +} +#endif + +static VALUE +tcpaddr(sockaddr) + struct sockaddr_in *sockaddr; +{ + VALUE family, port, addr; + VALUE ary; + struct hostent *hostent; + + family = str_new2("AF_INET"); + hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr, + sizeof(sockaddr->sin_addr), + AF_INET); + if (hostent) { + addr = str_new2(hostent->h_name); + } + else { + char buf[16]; + char *a = (char*)&sockaddr->sin_addr; + sprintf(buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); + addr = str_new2(buf); + } + port = INT2FIX(sockaddr->sin_port); + ary = ary_new3(3, family, port, addr); + + return ary; +} + +static VALUE +tcp_addr(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_in addr; + int len = sizeof addr; + + GetOpenFile(sock, fptr); + + if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail("getsockname(2)"); + return tcpaddr(&addr); +} + +static VALUE +tcp_peeraddr(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_in addr; + int len = sizeof addr; + + GetOpenFile(sock, fptr); + + if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail("getsockname(2)"); + return tcpaddr(&addr); +} + +#ifdef AF_UNIX +static VALUE +unix_s_sock_open(sock, path) + VALUE sock, path; +{ + return open_unix(sock, path, 0); +} + +static VALUE +unix_path(sock) + VALUE sock; +{ + OpenFile *fptr; + + GetOpenFile(sock, fptr); + if (fptr->path == Qnil) { + struct sockaddr_un addr; + int len = sizeof(addr); + if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail(Qnil); + fptr->path = strdup(addr.sun_path); + } + return str_new2(fptr->path); +} + +static VALUE +unix_svr_s_open(class, path) + VALUE class, path; +{ + return open_unix(class, path, 1); +} + +static VALUE +unix_accept(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_un from; + int fromlen; + + GetOpenFile(sock, fptr); + fromlen = sizeof(struct sockaddr_un); + return s_accept(cUNIXsocket, fileno(fptr->f), + (struct sockaddr*)&from, &fromlen); +} + +static VALUE +unixaddr(sockaddr) + struct sockaddr_un *sockaddr; +{ + return assoc_new(str_new2("AF_UNIX"),str_new2(sockaddr->sun_path)); +} + +static VALUE +unix_addr(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_un addr; + int len = sizeof addr; + + GetOpenFile(sock, fptr); + + if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail("getsockname(2)"); + return unixaddr(&addr); +} + +static VALUE +unix_peeraddr(sock) + VALUE sock; +{ + OpenFile *fptr; + struct sockaddr_un addr; + int len = sizeof addr; + + GetOpenFile(sock, fptr); + + if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + rb_sys_fail("getsockname(2)"); + return unixaddr(&addr); +} +#endif + +static void +setup_domain_and_type(domain, dv, type, tv) + VALUE domain, type; + int *dv, *tv; +{ + char *ptr; + + if (TYPE(domain) == T_STRING) { + ptr = RSTRING(domain)->ptr; + if (strcmp(ptr, "PF_INET") == 0) + *dv = PF_INET; +#ifdef PF_UNIX + else if (strcmp(ptr, "PF_UNIX") == 0) + *dv = PF_UNIX; +#endif +#ifdef PF_IMPLINK + else if (strcmp(ptr, "PF_IMPLINK") == 0) + *dv = PF_IMPLINK; +#endif +#ifdef PF_AX25 + else if (strcmp(ptr, "PF_AX25") == 0) + *dv = PF_AX25; +#endif +#ifdef PF_IPX + else if (strcmp(ptr, "PF_IPX") == 0) + *dv = PF_IPX; +#endif + else + Fail("Unknown socket domain %s", ptr); + } + else { + *dv = NUM2INT(domain); + } + if (TYPE(type) == T_STRING) { + ptr = RSTRING(type)->ptr; + if (strcmp(ptr, "SOCK_STREAM") == 0) + *tv = SOCK_STREAM; + else if (strcmp(ptr, "SOCK_DGRAM") == 0) + *tv = SOCK_DGRAM; +#ifdef SOCK_RAW + else if (strcmp(ptr, "SOCK_RAW") == 0) + *tv = SOCK_RAW; +#endif +#ifdef SOCK_SEQPACKET + else if (strcmp(ptr, "SOCK_SEQPACKET") == 0) + *tv = SOCK_SEQPACKET; +#endif +#ifdef SOCK_RDM + else if (strcmp(ptr, "SOCK_RDM") == 0) + *tv = SOCK_RDM; +#endif +#ifdef SOCK_PACKET + else if (strcmp(ptr, "SOCK_PACKET") == 0) + *tv = SOCK_PACKET; +#endif + else + Fail("Unknown socket type %s", ptr); + } + else { + *tv = NUM2INT(type); + } +} + +static VALUE +sock_s_open(class, domain, type, protocol) + VALUE class, domain, type, protocol; +{ + int fd; + int d, t; + + setup_domain_and_type(domain, &d, type, &t); + fd = socket(d, t, NUM2INT(protocol)); + if (fd < 0) rb_sys_fail("socke(2)"); + return sock_new(class, fd); +} + +static VALUE +sock_s_for_fd(class, fd) + VALUE class, fd; +{ + return sock_new(class, NUM2INT(fd)); +} + +static VALUE +sock_s_socketpair(class, domain, type, protocol) + VALUE class, domain, type, protocol; +{ + int fd; + int d, t, sp[2]; + + setup_domain_and_type(domain, &d, type, &t); + if (socketpair(d, t, NUM2INT(protocol), sp) < 0) + rb_sys_fail("socketpair(2)"); + + return assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1])); +} + +static VALUE +sock_connect(sock, addr) + VALUE sock; + struct RString *addr; +{ + OpenFile *fptr; + + Check_Type(addr, T_STRING); + str_modify(addr); + + GetOpenFile(sock, fptr); + if (connect(fileno(fptr->f), (struct sockaddr*)addr->ptr, addr->len) < 0) + rb_sys_fail("connect(2)"); + + return INT2FIX(0); +} + +static VALUE +sock_bind(sock, addr) + VALUE sock; + struct RString *addr; +{ + OpenFile *fptr; + + Check_Type(addr, T_STRING); + str_modify(addr); + + GetOpenFile(sock, fptr); + if (bind(fileno(fptr->f), (struct sockaddr*)addr->ptr, addr->len) < 0) + rb_sys_fail("bind(2)"); + + return INT2FIX(0); +} + +static VALUE +sock_listen(sock, log) + VALUE sock, log; +{ + OpenFile *fptr; + + GetOpenFile(sock, fptr); + if (listen(fileno(fptr->f), NUM2INT(log)) < 0) + rb_sys_fail("listen(2)"); + + return INT2FIX(0); +} + +static VALUE +sock_accept(sock) + VALUE sock; +{ + OpenFile *fptr; + VALUE addr, sock2; + char buf[1024]; + int len = sizeof buf; + + GetOpenFile(sock, fptr); + sock2 = s_accept(cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len); + + return assoc_new(sock2, str_new(buf, len)); +} + +static VALUE +sock_send(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + struct RString *msg, *to; + VALUE flags; + OpenFile *fptr; + FILE *f; + int fd, n; + + rb_scan_args(argc, argv, "21", &msg, &flags, &to); + + Check_Type(msg, T_STRING); + + GetOpenFile(sock, fptr); + f = fptr->f2?fptr->f2:fptr->f; + fd = fileno(f); + if (to) { + Check_Type(to, T_STRING); + n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags), + (struct sockaddr*)to->ptr, to->len); + } + else { + n = send(fd, msg->ptr, msg->len, NUM2INT(flags)); + } + if (n < 0) { + rb_sys_fail("send(2)"); + } + return INT2FIX(n); +} + +static VALUE +s_recv(sock, argc, argv, from) + VALUE sock; + int argc; + VALUE *argv; + int from; +{ + OpenFile *fptr; + FILE f; + struct RString *str; + char buf[1024]; + int fd, alen = sizeof buf; + VALUE len, flg; + int flags; + + rb_scan_args(argc, argv, "11", &len, &flg); + + if (flg == Qnil) flags = 0; + else flags = NUM2INT(flg); + + str = (struct RString*)str_new(0, NUM2INT(len)); + + GetOpenFile(sock, fptr); + fd = fileno(fptr->f); + if ((str->len = recvfrom(fd, str->ptr, str->len, flags, + (struct sockaddr*)buf, &alen)) < 0) { + rb_sys_fail("recvfrom(2)"); + } + + if (from) + return assoc_new(str, str_new(buf, alen)); + else + return (VALUE)str; +} + +static VALUE +sock_recv(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + return s_recv(sock, argc, argv, 0); +} + +static VALUE +sock_recvfrom(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + return s_recv(sock, argc, argv, 1); +} + +Init_socket () +{ + cBasicSocket = rb_define_class("BasicSocket", cIO); + rb_undef_method(cBasicSocket, "new"); + rb_define_method(cBasicSocket, "shutdown", bsock_shutdown, -1); + rb_define_method(cBasicSocket, "setopt", bsock_setopt, 3); + rb_define_method(cBasicSocket, "getopt", bsock_getopt, 2); + rb_define_method(cBasicSocket, "getsockname", bsock_getsockname, 0); + rb_define_method(cBasicSocket, "getpeername", bsock_getpeername, 0); + + cTCPsocket = rb_define_class("TCPsocket", cBasicSocket); + rb_define_singleton_method(cTCPsocket, "open", tcp_s_sock_open, 2); + rb_define_singleton_method(cTCPsocket, "new", tcp_s_sock_open, 2); + rb_define_method(cTCPsocket, "addr", tcp_addr, 0); + rb_define_method(cTCPsocket, "peeraddr", tcp_peeraddr, 0); + + cTCPserver = rb_define_class("TCPserver", cTCPsocket); + rb_define_singleton_method(cTCPserver, "open", tcp_svr_s_open, -1); + rb_define_singleton_method(cTCPserver, "new", tcp_svr_s_open, -1); + rb_define_method(cTCPserver, "accept", tcp_accept, 0); + +#ifdef AF_UNIX + cUNIXsocket = rb_define_class("UNIXsocket", cBasicSocket); + rb_define_singleton_method(cUNIXsocket, "open", unix_s_sock_open, 1); + rb_define_singleton_method(cUNIXsocket, "new", unix_s_sock_open, 1); + rb_define_method(cUNIXsocket, "path", unix_path, 0); + rb_define_method(cUNIXsocket, "addr", unix_addr, 0); + rb_define_method(cUNIXsocket, "peeraddr", unix_peeraddr, 0); + + cUNIXserver = rb_define_class("UNIXserver", cUNIXsocket); + rb_define_singleton_method(cUNIXserver, "open", unix_svr_s_open, 1); + rb_define_singleton_method(cUNIXserver, "new", unix_svr_s_open, 1); + rb_define_method(cUNIXserver, "accept", unix_accept, 0); +#endif + + cSocket = rb_define_class("Socket", cBasicSocket); + rb_define_singleton_method(cSocket, "open", sock_s_open, 3); + rb_define_singleton_method(cSocket, "new", sock_s_open, 3); + rb_define_singleton_method(cSocket, "for_fd", sock_s_for_fd, 1); + + rb_define_method(cSocket, "connect", sock_connect, 1); + rb_define_method(cSocket, "bind", sock_bind, 1); + rb_define_method(cSocket, "listen", sock_listen, 1); + rb_define_method(cSocket, "accept", sock_accept, 0); + + rb_define_method(cSocket, "send", sock_send, -1); + rb_define_method(cSocket, "recv", sock_recv, -1); + rb_define_method(cSocket, "recvfrom", sock_recv, -1); + + rb_define_singleton_method(cSocket, "socketpair", sock_s_socketpair, 3); +} diff --git a/ext/socket/socket.doc b/ext/socket/socket.doc new file mode 100644 index 0000000000..aa5bfedbff --- /dev/null +++ b/ext/socket/socket.doc @@ -0,0 +1,227 @@ +.\" socket.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:29:02 JST 1995 + +** Socket(饹) + +SuperClass: BasicSocket + +åȤΤΤФ륷ƥॳ٥Υ륯饹 +PerlΥåȤФ륢Ʊ٥εǽƤ롥Υ +Ǥϥåȥɥ쥹pack줿ʸǡꤹ롥UDPåȤϤ +Υ饹ȤäѤ롥 + +Methods: + + accept + + ³դơ³Ф륽åȤȥɥ쥹 + ڥ֤accept(2)ȡ + + bind(addr) + + bind(2)ƱƯ롥addrpack줿åȥɥ쥹¤ + ΤǤ롥 + + connect(addr) + + connect(2)ƱƯ롥addrpack줿åȥɥ쥹 + ¤ΤǤ롥 + + listen(backlog) + + listen(2)ƱƯ롥 + + recv(len[, flags]) + + åȤǡꡤʸȤ֤lenϼ + Ĺꤹ롥flagsˤĤƤrecv(2)ȡflagsΥ + եͤ0Ǥ롥 + + recvfrom(len[, flags]) + + recvƱͤ˥åȤǡ뤬ͤʸ + åȤΥɥ쥹ΥڥǤ롥ˤĤƤrecvƱ͡ + + send(mesg, flags[, to]) + + åȤ𤷤ƥǡ롥flags˴ؤƤsend(2)Ȥλ + connectƤʤåȤФƤǤtoꤹɬ + פ롥ºݤäǡĹ֤ + +Single Methods: + + open(domain, type, protocol) + new(domain, type, protocol) + + åȤ롥domaintypeprotocolϥ롼 + եƤͤǻꤹ롥domaintype˴ؤ + ϡʸǻǤ뤬٤ƤСƤݾڤϤʤ + + socketpair(domain, type, protocol) + + åȤΥڥ֤λ openƱǤ롥 + +** BasicSocket(饹) + +åȤɽݥ饹Ūʥåϥ֥饹롥 +㤨ХͥåȥɥᥤξTCPsocketѤ롥 + +SuperClass: IO + +Methods: + + getopt(level, optname) + + åȤΥץ롥getsockopt(2)ȤΤȡ + ץƤޤʸ֤ + + getpeername + + ³ΥåȤξ롥ѥå줿sockaddr¤ + ٥˥פʸ֤롥getpeername(2)ȤΤȡ + + getsockname + + åȤξ롥ѥå줿sockaddr¤Τ٥˥ + ʸ֤롥getsockname(2)ȤΤȡ + + setopt(level, optname, optval) + + åȤΥץꤹ롥setsockopt(2)ȤΤȡ + + shutdown(how) + + åȤΰʹߤ³λ롥how0Ǥʹߤμ + how1Ǥϡʹߤݤ롥how2λˤϡ + ʹߤȤ˵ݤ롥shutdown(2)ȡ + +** TCPserver(饹) + +TCP/IPȥ³Υ¦ΥåȤΥ饹Υ饹ˤä +ñ˥åȤѤФΥץߥǤ롥㤨echo +ФϰʲΤ褦ˤʤ롥 + + gs = TCPserver.open(4444) + socks = [gs] + + while TRUE + nsock = select(socks); + if nsock == nil; continue end + for s in nsock[0] + if s == gs + socks.push(s.accept) + else + if s.eof + s.close + socks.delete(s) + else + str = s.gets + s.write(str) + end + end + end + end + +SuperClass: TCPsocket + +Methods: + + accept + + 饤Ȥ³դ³TCPsocketΥ + ֤ + +Single Methods: + + new([host, ]service) + open([host, ]service) + + service/etc/services(ޤNIS)ϿƤ륵ӥ̾ + ݡֹǻꤹ롥hostꤷϻꤷۥȤ + ³դ롥άƤΥۥȤ³ + 롥 + +** TCPsocket + +ͥåȥɥᥤΥȥåȤΥ饹̾IO饹 +֥饹ƱͤϤǤ롥Υ饹ˤäƥåȤѤ +饤Ȥñ˵ҤǤ롥桼ϤΤޤޥФž +ϰʲΤ褦ˤʤ롥 + + s = TCPsocket("localhost", 4444) + while gets() + s.write($_) + print(s.read) + end + +SuperClass: BasicSocket + +Methods: + + addr + + åȤ³ɽ֤γǤ1 + ʸ "AF_INET"2Ǥportֹ桤3ǤۥȤɽʸ + Ǥ롥 + + peeraddr + + ³襽åȤξɽ֤γǤ + addråɤ֤ƱǤ롥 + +Single Methods: + + open(host, service) + new(host, service) + + hostǻꤷۥȤserviceǻꤷݡȤ³ + Ȥ֤hostϥۥ̾ޤϥͥåȥɥ쥹ʸ + service/etc/services(ޤNIS)ϿƤ륵 + ̾ݡֹǤ롥 + +** UNIXserver + +UNIXȥ³Υ¦ΥåȤΥ饹 + +SuperClass: UNIXsocket + +Methods: + + accept + + 饤Ȥ³դ³UNIXsocketΥ + ֤ + +** UNIXsocket + +UNIXɥᥤΥȥåȤΥ饹̾IO饹Υ֥饹 +ƱͤϤǤ롥 + +SuperClass: BasicSocket + +Methods: + + addr + + åȤ³ɽ֤γǤ1 + ʸ "AF_UNIX"2ǤpathǤ롥 + + path + + UNIXåȤΥѥ֤ + + peeraddr + + ³襽åȤξɽ֤γǤ + addråɤ֤ƱǤ롥 + +Single Methods: + + open(path) + new(path) + + pathǻꤷѥ̾Ѥ³åȤ֤ + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/tkutil/MANIFEST b/ext/tkutil/MANIFEST new file mode 100644 index 0000000000..98df4663b3 --- /dev/null +++ b/ext/tkutil/MANIFEST @@ -0,0 +1,3 @@ +MANIFEST +extconf.rb +tkutil.c diff --git a/ext/tkutil/extconf.rb b/ext/tkutil/extconf.rb new file mode 100644 index 0000000000..b61a7ac01c --- /dev/null +++ b/ext/tkutil/extconf.rb @@ -0,0 +1,11 @@ +for dir in ENV['PATH'].split(':') + if File.exists? "#{dir}/wish" + $CFLAGS = $CFLAGS + " -DWISHPATH=" + "'\"#{dir}/wish\"'" + have_wish = TRUE + break + end +end + +if have_wish and have_func('pipe') + create_makefile("tkutil") +end diff --git a/ext/tkutil/tkutil.c b/ext/tkutil/tkutil.c new file mode 100644 index 0000000000..2b74b254c2 --- /dev/null +++ b/ext/tkutil/tkutil.c @@ -0,0 +1,54 @@ +/************************************************ + + tk.c - + + $Author: matz $ + $Date: 1995/11/03 00:47:55 $ + created at: Fri Nov 3 00:47:54 JST 1995 + +************************************************/ + +#include "ruby.h" + +static VALUE +tk_eval_cmd(argc, argv) + int argc; + VALUE argv[]; +{ + VALUE cmd, rest; + + rb_scan_args(argc, argv, "1*", &cmd, &rest); + rb_eval_cmd(cmd, rest); + return Qnil; +} + +static VALUE +tk_yield(obj) + VALUE obj; +{ + rb_yield_0(obj, obj); +} + +static VALUE +tk_s_new(argc, argv, class) + int argc; + VALUE *argv; + VALUE class; +{ + VALUE obj = obj_alloc(class); + + rb_funcall2(obj, rb_intern("initialize"), argc, argv); + if (iterator_p()) tk_yield(obj); + return obj; +} + +Init_tkutil() +{ + VALUE mTK = rb_define_module("TkUtil"); + VALUE cTK = rb_define_class("TkKernel", cObject); + + rb_define_const(mTK, "WISH_PATH", str_new2(WISHPATH)); + rb_define_singleton_method(mTK, "eval_cmd", tk_eval_cmd, -1); + + rb_define_singleton_method(cTK, "new", tk_s_new, -1); +} @@ -10,24 +10,49 @@ ************************************************/ -#include <sys/param.h> -#include <sys/time.h> #include "ruby.h" #include "io.h" + #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#else +# define MAXPATHLEN 1024 +#endif + +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#else +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif + #ifdef HAVE_UTIME_H #include <utime.h> #endif +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + +#ifdef HAVE_STRING_H +# include <string.h> +#else +char *strrchr(); +#endif char *strdup(); +char *getenv(); -extern VALUE C_IO; -VALUE C_File; -VALUE M_FileTest; +extern VALUE cIO; +VALUE cFile; +VALUE mFileTest; +static VALUE sStat; VALUE time_new(); @@ -38,7 +63,7 @@ file_open(fname, mode) VALUE port; OpenFile *fptr; - port = obj_alloc(C_File); + port = obj_alloc(cFile); MakeOpenFile(port, fptr); fptr->mode = io_mode_flags(mode); @@ -79,7 +104,7 @@ apply2files(func, args, arg) } static VALUE -Ffile_tell(obj) +file_tell(obj) VALUE obj; { OpenFile *fptr; @@ -94,7 +119,7 @@ Ffile_tell(obj) } static VALUE -Ffile_seek(obj, offset, ptrname) +file_seek(obj, offset, ptrname) VALUE obj, offset, ptrname; { OpenFile *fptr; @@ -110,7 +135,7 @@ Ffile_seek(obj, offset, ptrname) } static VALUE -Ffile_set_pos(obj, offset) +file_set_pos(obj, offset) VALUE obj, offset; { OpenFile *fptr; @@ -125,7 +150,7 @@ Ffile_set_pos(obj, offset) } static VALUE -Ffile_rewind(obj) +file_rewind(obj) VALUE obj; { OpenFile *fptr; @@ -138,7 +163,7 @@ Ffile_rewind(obj) } static VALUE -Ffile_eof(obj) +file_eof(obj) VALUE obj; { OpenFile *fptr; @@ -149,7 +174,7 @@ Ffile_eof(obj) } static VALUE -Ffile_path(obj) +file_path(obj) VALUE obj; { OpenFile *fptr; @@ -159,7 +184,7 @@ Ffile_path(obj) } static VALUE -Ffile_isatty(obj) +file_isatty(obj) VALUE obj; { return FALSE; @@ -174,56 +199,55 @@ stat_new(st) struct stat *st; { if (st == Qnil) Bug("stat_new() called with nil"); - return struct_new("stat", - "dev", INT2FIX((int)st->st_dev), - "ino", INT2FIX((int)st->st_ino), - "mode", INT2FIX((int)st->st_mode), - "nlink", INT2FIX((int)st->st_nlink), - "uid", INT2FIX((int)st->st_uid), - "gid", INT2FIX((int)st->st_gid), + return struct_new(sStat, + INT2FIX((int)st->st_dev), + INT2FIX((int)st->st_ino), + INT2FIX((int)st->st_mode), + INT2FIX((int)st->st_nlink), + INT2FIX((int)st->st_uid), + INT2FIX((int)st->st_gid), #ifdef HAVE_ST_RDEV - "rdev", INT2FIX((int)st->st_rdev), + INT2FIX((int)st->st_rdev), #else - "rdev", INT2FIX(0), + INT2FIX(0), #endif - "size", INT2FIX((int)st->st_size), + INT2FIX((int)st->st_size), #ifdef HAVE_ST_BLKSIZE - "blksize", INT2FIX((int)st->st_blksize), + INT2FIX((int)st->st_blksize), #else - "blksize", INT2FIX(0), + INT2FIX(0), #endif #ifdef HAVE_ST_BLOCKS - "blocks", INT2FIX((int)st->st_blocks), + INT2FIX((int)st->st_blocks), #else - "blocks", INT2FIX(0), + INT2FIX(0), #endif - "atime", time_new(st->st_atime, 0), - "mtime", time_new(st->st_mtime, 0), - "ctime", time_new(st->st_ctime, 0), + time_new(st->st_atime, 0), + time_new(st->st_mtime, 0), + time_new(st->st_ctime, 0), Qnil); } -static char lastpath[MAXPATHLEN]; static struct stat laststat; +int cache_stat(path, st) char *path; struct stat *st; { - if (strcmp(lastpath, path) == 0) { + if (strcmp("&", path) == 0) { *st = laststat; return 0; } if (stat(path, st) == -1) return -1; - strcpy(lastpath, path); - laststat = *st; + laststat = *st; return 0; } static VALUE -Sfile_stat(obj, fname) +file_s_stat(obj, fname) VALUE obj; struct RString *fname; { @@ -237,21 +261,20 @@ Sfile_stat(obj, fname) } static VALUE -Ffile_stat(obj) +file_stat(obj) VALUE obj; { OpenFile *fptr; - struct stat st; GetOpenFile(obj, fptr); - if (fstat(fileno(fptr->f), &st) == -1) { + if (fstat(fileno(fptr->f), &laststat) == -1) { rb_sys_fail(fptr->path); } - return stat_new(&st); + return stat_new(&laststat); } static VALUE -Sfile_lstat(obj, fname) +file_s_lstat(obj, fname) VALUE obj; struct RString *fname; { @@ -265,7 +288,7 @@ Sfile_lstat(obj, fname) } static VALUE -Ffile_lstat(obj) +file_lstat(obj) VALUE obj; { OpenFile *fptr; @@ -278,21 +301,18 @@ Ffile_lstat(obj) return stat_new(&st); } -#define HAS_GETGROUPS - static int group_member(gid) GETGROUPS_T gid; { - GETGROUPS_T egid; - +#ifndef NT if (getgid() == gid || getegid() == gid) return TRUE; -#ifdef HAS_GETGROUPS -#ifndef NGROUPS -#define NGROUPS 32 -#endif +# ifdef HAVE_GETGROUPS +# ifndef NGROUPS +# define NGROUPS 32 +# endif { GETGROUPS_T gary[NGROUPS]; int anum; @@ -302,6 +322,7 @@ group_member(gid) if (gary[anum] == gid) return TRUE; } +# endif #endif return FALSE; } @@ -315,7 +336,6 @@ eaccess(path, mode) char *path; int mode; { - extern int group_member (); struct stat st; static int euid = -1; @@ -347,7 +367,7 @@ eaccess(path, mode) } static VALUE -Ftest_d(obj, fname) +test_d(obj, fname) VALUE obj; struct RString *fname; { @@ -364,7 +384,7 @@ Ftest_d(obj, fname) } static VALUE -Ftest_p(obj, fname) +test_p(obj, fname) VALUE obj; struct RString *fname; { @@ -384,7 +404,7 @@ Ftest_p(obj, fname) } static VALUE -Ftest_l(obj, fname) +test_l(obj, fname) VALUE obj; struct RString *fname; { @@ -413,7 +433,8 @@ Ftest_l(obj, fname) return FALSE; } -Ftest_S(obj, fname) +VALUE +test_S(obj, fname) VALUE obj; struct RString *fname; { @@ -443,7 +464,7 @@ Ftest_S(obj, fname) } static VALUE -Ftest_b(obj, fname) +test_b(obj, fname) VALUE obj; struct RString *fname; { @@ -465,7 +486,7 @@ Ftest_b(obj, fname) } static VALUE -Ftest_c(obj, fname) +test_c(obj, fname) VALUE obj; struct RString *fname; { @@ -483,7 +504,7 @@ Ftest_c(obj, fname) } static VALUE -Ftest_e(obj, fname) +test_e(obj, fname) VALUE obj; struct RString *fname; { @@ -495,7 +516,7 @@ Ftest_e(obj, fname) } static VALUE -Ftest_r(obj, fname) +test_r(obj, fname) VALUE obj; struct RString *fname; { @@ -505,7 +526,7 @@ Ftest_r(obj, fname) } static VALUE -Ftest_R(obj, fname) +test_R(obj, fname) VALUE obj; struct RString *fname; { @@ -515,7 +536,7 @@ Ftest_R(obj, fname) } static VALUE -Ftest_w(obj, fname) +test_w(obj, fname) VALUE obj; struct RString *fname; { @@ -525,7 +546,7 @@ Ftest_w(obj, fname) } static VALUE -Ftest_W(obj, fname) +test_W(obj, fname) VALUE obj; struct RString *fname; { @@ -535,7 +556,7 @@ Ftest_W(obj, fname) } static VALUE -Ftest_x(obj, fname) +test_x(obj, fname) VALUE obj; struct RString *fname; { @@ -545,7 +566,7 @@ Ftest_x(obj, fname) } static VALUE -Ftest_X(obj, fname) +test_X(obj, fname) VALUE obj; struct RString *fname; { @@ -555,7 +576,7 @@ Ftest_X(obj, fname) } static VALUE -Ftest_f(obj, fname) +test_f(obj, fname) VALUE obj; struct RString *fname; { @@ -568,7 +589,7 @@ Ftest_f(obj, fname) } static VALUE -Ftest_z(obj, fname) +test_z(obj, fname) VALUE obj; struct RString *fname; { @@ -581,7 +602,7 @@ Ftest_z(obj, fname) } static VALUE -Ftest_s(obj, fname) +test_s(obj, fname) VALUE obj; struct RString *fname; { @@ -594,7 +615,7 @@ Ftest_s(obj, fname) } static VALUE -Ftest_owned(obj, fname) +test_owned(obj, fname) VALUE obj; struct RString *fname; { @@ -607,7 +628,7 @@ Ftest_owned(obj, fname) } static VALUE -Ftest_grpowned(obj, fname) +test_rowned(obj, fname) VALUE obj; struct RString *fname; { @@ -615,7 +636,24 @@ Ftest_grpowned(obj, fname) Check_Type(fname, T_STRING); if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (st.st_uid == getuid()) return TRUE; + return FALSE; +} + +static VALUE +test_grpowned(obj, fname) + VALUE obj; + struct RString *fname; +{ +#ifndef NT + struct stat st; + + Check_Type(fname, T_STRING); + if (cache_stat(fname->ptr, &st) < 0) return FALSE; if (st.st_gid == getegid()) return TRUE; +#else + Check_Type(fname, T_STRING); +#endif return FALSE; } @@ -634,7 +672,7 @@ check3rdbyte(file, mode) #endif static VALUE -Ftest_suid(obj, fname) +test_suid(obj, fname) VALUE obj; struct RString *fname; { @@ -647,12 +685,12 @@ Ftest_suid(obj, fname) } static VALUE -Ftest_sgid(obj, fname) +test_sgid(obj, fname) VALUE obj; struct RString *fname; { Check_Type(fname, T_STRING); -#ifdef S_ISGID +#ifndef NT return check3rdbyte(fname->ptr, S_ISGID); #else return FALSE; @@ -660,7 +698,7 @@ Ftest_sgid(obj, fname) } static VALUE -Ftest_sticky(obj, fname) +test_sticky(obj, fname) VALUE obj; struct RString *fname; { @@ -673,7 +711,7 @@ Ftest_sticky(obj, fname) } static VALUE -Sfile_type(obj, fname) +file_s_type(obj, fname) VALUE obj; struct RString *fname; { @@ -718,7 +756,7 @@ Sfile_type(obj, fname) } static VALUE -Sfile_atime(obj, fname) +file_s_atime(obj, fname) VALUE obj; struct RString *fname; { @@ -730,7 +768,7 @@ Sfile_atime(obj, fname) } static VALUE -Ffile_atime(obj) +file_atime(obj) VALUE obj; { OpenFile *fptr; @@ -744,7 +782,7 @@ Ffile_atime(obj) } static VALUE -Sfile_mtime(obj, fname) +file_s_mtime(obj, fname) VALUE obj; struct RString *fname; { @@ -756,7 +794,7 @@ Sfile_mtime(obj, fname) } static VALUE -Ffile_mtime(obj) +file_mtime(obj) VALUE obj; { OpenFile *fptr; @@ -770,7 +808,7 @@ Ffile_mtime(obj) } static VALUE -Sfile_ctime(obj, fname) +file_s_ctime(obj, fname) VALUE obj; struct RString *fname; { @@ -782,7 +820,7 @@ Sfile_ctime(obj, fname) } static VALUE -Ffile_ctime(obj) +file_ctime(obj) VALUE obj; { OpenFile *fptr; @@ -805,15 +843,13 @@ chmod_internal(path, mode) } static VALUE -Sfile_chmod(argc, argv, obj) +file_s_chmod(argc, argv) int argc; VALUE *argv; - VALUE obj; { VALUE vmode; VALUE rest; int mode, n; - VALUE path; rb_scan_args(argc, argv, "1*", &vmode, &rest); mode = NUM2INT(vmode); @@ -823,7 +859,7 @@ Sfile_chmod(argc, argv, obj) } static VALUE -Ffile_chmod(obj, vmode) +file_chmod(obj, vmode) VALUE obj, vmode; { OpenFile *fptr; @@ -852,10 +888,9 @@ chown_internal(path, args) } static VALUE -Sfile_chown(argc, argv, obj) +file_s_chown(argc, argv) int argc; VALUE *argv; - VALUE obj; { VALUE o, g, rest; struct chown_args arg; @@ -879,11 +914,11 @@ Sfile_chown(argc, argv, obj) return INT2FIX(n); } -Ffile_chown(obj, owner, group) +VALUE +file_chown(obj, owner, group) VALUE obj, owner, group; { OpenFile *fptr; - int mode; GetOpenFile(obj, fptr); if (fchown(fileno(fptr->f), NUM2INT(owner), NUM2INT(group)) == -1) @@ -894,7 +929,7 @@ Ffile_chown(obj, owner, group) struct timeval *time_timeval(); -#ifdef HAVE_UTIME +#ifdef HAVE_UTIMES static void utime_internal(path, tvp) @@ -906,10 +941,9 @@ utime_internal(path, tvp) } static VALUE -Sfile_utime(argc, argv, obj) +file_s_utime(argc, argv) int argc; VALUE *argv; - VALUE obj; { VALUE atime, mtime, rest; struct timeval tvp[2]; @@ -926,39 +960,35 @@ Sfile_utime(argc, argv, obj) #else +#ifndef HAVE_UTIME_H +# ifdef NT +# include <sys/utime.h> +# else +struct utimbuf { + long actime; + long modtime; +}; +# endif +#endif + static void utime_internal(path, utp) char *path; -#ifdef HAVE_UTIME_H struct utimbuf *utp; -#else - struct { - long actime; - long modtime; - } *utp; -#endif { if (utime(path, utp) < 0) rb_sys_fail(path); } static VALUE -Sfile_utime(argc, argv, obj) +file_s_utime(argc, argv) int argc; VALUE *argv; - VALUE obj; { VALUE atime, mtime, rest; int n; struct timeval *tv; -#ifdef HAVE_UTIME_H struct utimbuf utbuf; -#else - struct { - long actime; - long modtime; - } utbuf; -#endif rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest); @@ -974,7 +1004,7 @@ Sfile_utime(argc, argv, obj) #endif static VALUE -Sfile_link(obj, from, to) +file_s_link(obj, from, to) VALUE obj; struct RString *from, *to; { @@ -987,7 +1017,7 @@ Sfile_link(obj, from, to) } static VALUE -Sfile_symlink(obj, from, to) +file_s_symlink(obj, from, to) VALUE obj; struct RString *from, *to; { @@ -1000,7 +1030,7 @@ Sfile_symlink(obj, from, to) } static VALUE -Sfile_readlink(obj, path) +file_s_readlink(obj, path) VALUE obj; struct RString *path; { @@ -1024,7 +1054,7 @@ unlink_internal(path) } static VALUE -Sfile_unlink(obj, args) +file_s_unlink(obj, args) VALUE obj; struct RArray *args; { @@ -1035,7 +1065,7 @@ Sfile_unlink(obj, args) } static VALUE -Sfile_rename(obj, from, to) +file_s_rename(obj, from, to) VALUE obj; struct RString *from, *to; { @@ -1049,12 +1079,11 @@ Sfile_rename(obj, from, to) } static VALUE -Sfile_umask(argc, argv) +file_s_umask(argc, argv) int argc; VALUE *argv; { - VALUE mask; - int omask; + int omask = 0; if (argc == 0) { int omask = umask(0); @@ -1069,20 +1098,44 @@ Sfile_umask(argc, argv) return INT2FIX(omask); } +#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE) static VALUE -Sfile_truncate(obj, path, len) +file_s_truncate(obj, path, len) VALUE obj, len; struct RString *path; { Check_Type(path, T_STRING); +#ifdef HAVE_TRUNCATE if (truncate(path->ptr, NUM2INT(len)) < 0) rb_sys_fail(path->ptr); +#else +# ifdef HAVE_CHSIZE + { + int tmpfd; + +#if defined(NT) + if ((tmpfd = open(path->ptr, O_RDWR)) < 0) { + rb_sys_fail(path->ptr); + } +#else + if ((tmpfd = open(path->ptr, 0)) < 0) { + rb_sys_fail(path->ptr); + } +#endif + if (chsize(tmpfd, NUM2INT(len)) < 0) { + close(tmpfd); + rb_sys_fail(path->ptr); + } + close(tmpfd); + } +# endif +#endif return TRUE; } static VALUE -Ffile_truncate(obj, len) +file_truncate(obj, len) VALUE obj, len; { OpenFile *fptr; @@ -1092,111 +1145,424 @@ Ffile_truncate(obj, len) if (!(fptr->mode & FMODE_WRITABLE)) { Fail("not opened for writing"); } +#ifdef HAVE_TRUNCATE if (ftruncate(fileno(fptr->f), NUM2INT(len)) < 0) rb_sys_fail(fptr->path); +#else +# ifdef HAVE_CHSIZE + if (chsize(fileno(fptr->f), NUM2INT(len)) < 0) + rb_sys_fail(fptr->path); +# endif +#endif return TRUE; } +#endif +#ifdef HAVE_FCNTL static VALUE -Ffile_fcntl(obj, req, arg) +file_fcntl(obj, req, arg) VALUE obj, req; struct RString *arg; { io_ctl(obj, req, arg, 0); return obj; } +#endif + +static VALUE +file_s_expand_path(obj, fname) + VALUE obj; + struct RString *fname; +{ + char *s, *p; + char buf[MAXPATHLEN]; + + Check_Type(fname, T_STRING); + s = fname->ptr; + + p = buf; + if (s[0] == '~') { + if (s[1] == '/' || s[1] == '\0') { + char *dir = getenv("HOME"); + + if (!dir) { + Fail("couldn't find HOME environment -- expanding `%s'", s); + } + strcpy(buf, dir); + p = &buf[strlen(buf)]; + s++; + } + else { +#ifdef HAVE_PWD_H + struct passwd *pwPtr; + s++; +#endif + + while (*s && *s != '/') { + *p++ = *s++; + } + *p = '\0'; +#ifdef HAVE_PWD_H + pwPtr = getpwnam(buf); + if (!pwPtr) { + endpwent(); + Fail("user %s doesn't exist", buf); + } + strcpy(buf, pwPtr->pw_dir); + p = &buf[strlen(buf)]; + endpwent(); +#endif + } + } + else if (s[0] != '/') { +#ifdef HAVE_GETCWD + getcwd(buf, MAXPATHLEN); +#else + getwd(buf)l +#endif + p = &buf[strlen(buf)]; + } + *p = '/'; + + for ( ; *s; s++) { + switch (*s) { + case '.': + if (*(s+1)) { + switch (*++s) { + case '.': + if (*(s+1) == '\0' || *(s+1) == '/') { + /* We must go back to the parent */ + if (*p == '/' && p > buf) p--; + while (p > buf && *p != '/') p--; + } + else { + *++p = '.'; + *++p = '.'; + } + break; + case '/': + if (*p != '/') *++p = '/'; + break; + default: + *++p = '.'; *++p = *s; break; + } + } + break; + case '/': + if (*p != '/') *++p = '/'; break; + default: + *++p = *s; + } + } + + /* Place a \0 at end. If path ends with a "/", delete it */ + if (p == buf || *p != '/') p++; + *p = '\0'; + + return str_new2(buf); +} + +static int +rmext(p, e) + char *p, *e; +{ + int l1, l2; + + l1 = strlen(p); + if (!e) return 0; + + l2 = strlen(e); + if (l1 < l2) return l1; + + if (strcmp(p+l1-l2, e) == 0) { + return l1-l2; + } + return 0; +} + +static VALUE +file_s_basename(argc, argv) + int argc; + VALUE *argv; +{ + struct RString *fname; + struct RString *ext; + char *p; + int f; + + rb_scan_args(argc, argv, "11", &fname, &ext); + Check_Type(fname, T_STRING); + if (ext) Check_Type(ext, T_STRING); + p = strrchr(fname->ptr, '/'); + if (p == Qnil) { + if (ext) { + f = rmext(fname->ptr, ext->ptr); + if (f) return str_new(fname->ptr, f); + } + return (VALUE)fname; + } + p++; /* skip last `/' */ + if (ext) { + f = rmext(p, ext->ptr); + if (f) return str_new(p, f); + } + return str_new2(p); +} + +static VALUE +file_s_dirname(obj, fname) + VALUE obj; + struct RString *fname; +{ + char *p; + Check_Type(fname, T_STRING); + p = strrchr(fname->ptr, '/'); + if (p == Qnil) return (VALUE)fname; + return str_new(fname->ptr, p - fname->ptr); +} + +static void +test_check(n, argc, argv) + int n, argc; + VALUE *argv; +{ + int i; + + n+=1; + if (n < argc) Fail("Wrong # of arguments(%d for %d)", argc, n); + for (i=1; i<n; i++) { + Check_Type(argv[i], T_STRING); + } +} + +#define CHECK(n) test_check((n), argc, argv) + +static VALUE +f_test(argc, argv) + int argc; + VALUE *argv; +{ + int cmd; + + if (argc == 0) Fail("Wrong # of arguments"); + Need_Fixnum(argv[0]); + cmd = FIX2INT(argv[0]); + if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) { + CHECK(1); + switch (cmd) { + case 'b': + return test_b(0, argv[1]); + + case 'c': + return test_c(0, argv[1]); + + case 'd': + return test_d(0, argv[1]); + + case 'a': + case 'e': + return test_e(0, argv[1]); + + case 'f': + return test_f(0, argv[1]); + + case 'g': + return test_sgid(0, argv[1]); + + case 'G': + return test_grpowned(0, argv[1]); + + case 'k': + return test_sticky(0, argv[1]); + + case 'l': + return test_l(0, argv[1]); + case 'o': + return test_owned(0, argv[1]); + + case 'O': + return test_rowned(0, argv[1]); + + case 'p': + return test_p(0, argv[1]); + + case 'r': + return test_r(0, argv[1]); + + case 'R': + return test_R(0, argv[1]); + + case 's': + return test_s(0, argv[1]); + + case 'S': + return test_S(0, argv[1]); + + case 'u': + return test_suid(0, argv[1]); + + case 'w': + return test_w(0, argv[1]); + + case 'W': + return test_W(0, argv[1]); + + case 'x': + return test_x(0, argv[1]); + + case 'X': + return test_X(0, argv[1]); + + case 'z': + return test_z(0, argv[1]); + } + } + + if (strchr("MAC", cmd)) { + struct stat st; + + CHECK(1); + if (cache_stat(RSTRING(argv[1])->ptr, &st) == -1) { + rb_sys_fail(RSTRING(argv[1])->ptr); + } + + switch (cmd) { + case 'A': + return time_new(st.st_atime, 0); + case 'M': + return time_new(st.st_mtime, 0); + case 'C': + return time_new(st.st_ctime, 0); + } + } + + if (strchr("-=<>", cmd)) { + struct stat st1, st2; + + CHECK(2); + if (stat(RSTRING(argv[1])->ptr, &st1) < 0) return FALSE; + if (stat(RSTRING(argv[2])->ptr, &st2) < 0) return FALSE; + + switch (cmd) { + case '-': + if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) + return TRUE; + break; + + case '=': + if (st1.st_mtime == st2.st_mtime) return TRUE; + break; + + case '>': + if (st1.st_mtime > st2.st_mtime) return TRUE; + break; + + case '<': + if (st1.st_mtime < st2.st_mtime) return TRUE; + break; + } + } + return FALSE; +} + +extern VALUE cKernel; + +void Init_File() { - M_FileTest = rb_define_module("FileTest"); - - rb_define_method(M_FileTest, "d", Ftest_d, 1); - rb_define_method(M_FileTest, "isdirectory", Ftest_d, 1); - rb_define_method(M_FileTest, "a", Ftest_e, 1); - rb_define_method(M_FileTest, "e", Ftest_e, 1); - rb_define_method(M_FileTest, "exists", Ftest_e, 1); - rb_define_method(M_FileTest, "r", Ftest_r, 1); - rb_define_method(M_FileTest, "readable", Ftest_r, 1); - rb_define_method(M_FileTest, "R", Ftest_R, 1); - rb_define_method(M_FileTest, "w", Ftest_w, 1); - rb_define_method(M_FileTest, "writable", Ftest_w, 1); - rb_define_method(M_FileTest, "W", Ftest_W, 1); - rb_define_method(M_FileTest, "x", Ftest_x, 1); - rb_define_method(M_FileTest, "executable", Ftest_x, 1); - rb_define_method(M_FileTest, "X", Ftest_X, 1); - rb_define_method(M_FileTest, "f", Ftest_f, 1); - rb_define_method(M_FileTest, "isfile", Ftest_f, 1); - rb_define_method(M_FileTest, "z", Ftest_z, 1); - rb_define_method(M_FileTest, "s", Ftest_s, 1); - rb_define_method(M_FileTest, "size", Ftest_s, 1); - rb_define_method(M_FileTest, "O", Ftest_owned, 1); - rb_define_method(M_FileTest, "owned", Ftest_owned, 1); - rb_define_method(M_FileTest, "G", Ftest_grpowned, 1); - - rb_define_method(M_FileTest, "p", Ftest_p, 1); - rb_define_method(M_FileTest, "ispipe", Ftest_p, 1); - rb_define_method(M_FileTest, "l", Ftest_l, 1); - rb_define_method(M_FileTest, "issymlink", Ftest_l, 1); - rb_define_method(M_FileTest, "S", Ftest_S, 1); - rb_define_method(M_FileTest, "issocket", Ftest_S, 1); - - rb_define_method(M_FileTest, "b", Ftest_b, 1); - rb_define_method(M_FileTest, "c", Ftest_c, 1); - - rb_define_method(M_FileTest, "u", Ftest_suid, 1); - rb_define_method(M_FileTest, "setuid", Ftest_suid, 1); - rb_define_method(M_FileTest, "g", Ftest_sgid, 1); - rb_define_method(M_FileTest, "setgid", Ftest_sgid, 1); - rb_define_method(M_FileTest, "k", Ftest_sticky, 1); - - C_File = rb_define_class("File", C_IO); - rb_extend_object(C_File, M_FileTest); - - rb_define_single_method(C_File, "stat", Sfile_stat, 1); - rb_define_single_method(C_File, "lstat", Sfile_lstat, 1); - rb_define_single_method(C_File, "type", Sfile_type, 1); - - rb_define_single_method(C_File, "atime", Sfile_atime, 1); - rb_define_single_method(C_File, "mtime", Sfile_mtime, 1); - rb_define_single_method(C_File, "ctime", Sfile_ctime, 1); - - rb_define_single_method(C_File, "utime", Sfile_utime, -1); - rb_define_single_method(C_File, "chmod", Sfile_chmod, -1); - rb_define_single_method(C_File, "chown", Sfile_chown, -1); - - rb_define_single_method(C_File, "link", Sfile_link, 2); - rb_define_single_method(C_File, "symlink", Sfile_symlink, 2); - rb_define_single_method(C_File, "readlink", Sfile_readlink, 1); - - rb_define_single_method(C_File, "unlink", Sfile_unlink, -2); - rb_define_single_method(C_File, "delete", Sfile_unlink, -2); - rb_define_single_method(C_File, "rename", Sfile_rename, 2); - rb_define_single_method(C_File, "umask", Sfile_umask, -1); - rb_define_single_method(C_File, "truncate", Sfile_truncate, 2); - - rb_define_method(C_File, "stat", Ffile_stat, 0); - rb_define_method(C_File, "lstat", Ffile_lstat, 0); - - rb_define_method(C_File, "atime", Ffile_atime, 0); - rb_define_method(C_File, "mtime", Ffile_mtime, 0); - rb_define_method(C_File, "ctime", Ffile_ctime, 0); - - rb_define_method(C_File, "chmod", Ffile_chmod, 1); - rb_define_method(C_File, "chown", Ffile_chown, 2); - rb_define_method(C_File, "truncate", Ffile_truncate, 1); - - rb_define_method(C_File, "tell", Ffile_tell, 0); - rb_define_method(C_File, "seek", Ffile_seek, 2); - - - rb_define_method(C_File, "pos", Ffile_tell, 0); - rb_define_method(C_File, "pos=", Ffile_set_pos, 1); - - rb_define_method(C_File, "rewind", Ffile_rewind, 0); - rb_define_method(C_File, "isatty", Ffile_isatty, 0); - rb_define_method(C_File, "eof", Ffile_eof, 0); - - rb_define_method(C_IO, "fcntl", Ffile_fcntl, 2); - - rb_define_method(C_File, "path", Ffile_path, 0); + mFileTest = rb_define_module("FileTest"); + + rb_define_module_function(mFileTest, "directory?", test_d, 1); + rb_define_module_function(mFileTest, "exists?", test_e, 1); + rb_define_module_function(mFileTest, "readable?", test_r, 1); + rb_define_module_function(mFileTest, "readable_real?", test_R, 1); + rb_define_module_function(mFileTest, "writable?", test_w, 1); + rb_define_module_function(mFileTest, "writable_real?", test_W, 1); + rb_define_module_function(mFileTest, "executable?", test_x, 1); + rb_define_module_function(mFileTest, "executable_real?", test_X, 1); + rb_define_module_function(mFileTest, "file?", test_f, 1); + rb_define_module_function(mFileTest, "zero?", test_z, 1); + rb_define_module_function(mFileTest, "size", test_s, 1); + rb_define_module_function(mFileTest, "owned?", test_owned, 1); + rb_define_module_function(mFileTest, "grpowned?", test_grpowned, 1); + + rb_define_module_function(mFileTest, "pipe?", test_p, 1); + rb_define_module_function(mFileTest, "symlink?", test_l, 1); + rb_define_module_function(mFileTest, "socket?", test_S, 1); + + rb_define_module_function(mFileTest, "blockdev?", test_b, 1); + rb_define_module_function(mFileTest, "chardev?", test_c, 1); + + rb_define_module_function(mFileTest, "setuid?", test_suid, 1); + rb_define_module_function(mFileTest, "setgid?", test_sgid, 1); + rb_define_module_function(mFileTest, "sticky?", test_sticky, 1); + + cFile = rb_define_class("File", cIO); + rb_extend_object(cFile, CLASS_OF(mFileTest)); + + rb_define_singleton_method(cFile, "stat", file_s_stat, 1); + rb_define_singleton_method(cFile, "lstat", file_s_lstat, 1); + rb_define_singleton_method(cFile, "type", file_s_type, 1); + + rb_define_singleton_method(cFile, "atime", file_s_atime, 1); + rb_define_singleton_method(cFile, "mtime", file_s_mtime, 1); + rb_define_singleton_method(cFile, "ctime", file_s_ctime, 1); + + rb_define_singleton_method(cFile, "utime", file_s_utime, -1); + rb_define_singleton_method(cFile, "chmod", file_s_chmod, -1); + rb_define_singleton_method(cFile, "chown", file_s_chown, -1); + + rb_define_singleton_method(cFile, "link", file_s_link, 2); + rb_define_singleton_method(cFile, "symlink", file_s_symlink, 2); + rb_define_singleton_method(cFile, "readlink", file_s_readlink, 1); + + rb_define_singleton_method(cFile, "unlink", file_s_unlink, -2); + rb_define_singleton_method(cFile, "delete", file_s_unlink, -2); + rb_define_singleton_method(cFile, "rename", file_s_rename, 2); + rb_define_singleton_method(cFile, "umask", file_s_umask, -1); +#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE) + rb_define_singleton_method(cFile, "truncate", file_s_truncate, 2); +#endif + rb_define_singleton_method(cFile, "expand_path", file_s_expand_path, 1); + rb_define_singleton_method(cFile, "basename", file_s_basename, -1); + rb_define_singleton_method(cFile, "dirname", file_s_dirname, 1); + + rb_define_method(cFile, "stat", file_stat, 0); + rb_define_method(cFile, "lstat", file_lstat, 0); + + rb_define_method(cFile, "atime", file_atime, 0); + rb_define_method(cFile, "mtime", file_mtime, 0); + rb_define_method(cFile, "ctime", file_ctime, 0); + + rb_define_method(cFile, "chmod", file_chmod, 1); + rb_define_method(cFile, "chown", file_chown, 2); +#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE) + rb_define_method(cFile, "truncate", file_truncate, 1); +#endif + + rb_define_method(cFile, "tell", file_tell, 0); + rb_define_method(cFile, "seek", file_seek, 2); + + rb_define_method(cFile, "pos", file_tell, 0); + rb_define_method(cFile, "pos=", file_set_pos, 1); + + rb_define_method(cFile, "rewind", file_rewind, 0); + rb_define_method(cFile, "isatty", file_isatty, 0); + rb_define_method(cFile, "tty?", file_isatty, 0); + rb_define_method(cFile, "eof", file_eof, 0); + rb_define_method(cFile, "eof?", file_eof, 0); + +#ifdef HAVE_FCNTL + rb_define_method(cIO, "fcntl", file_fcntl, 2); +#endif + + rb_define_method(cFile, "path", file_path, 0); + + rb_define_method(cKernel, "test", f_test, -1); + + sStat = struct_define("Stat", "dev", "ino", "mode", + "nlink", "uid", "gid", "rdev", + "size", "blksize", "blocks", + "atime", "mtime", "ctime", Qnil); } @@ -14,6 +14,7 @@ #include "env.h" #include "st.h" #include "node.h" +#include "re.h" #include <stdio.h> #include <setjmp.h> @@ -115,16 +116,16 @@ Cambridge, MA 02138 static int dont_gc; VALUE -Sgc_enable() +gc_s_enable() { int old = dont_gc; - dont_gc = Qnil; + dont_gc = FALSE; return old; } VALUE -Sgc_disable() +gc_s_disable() { int old = dont_gc; @@ -132,22 +133,7 @@ Sgc_disable() return old; } -#include <sys/types.h> -#include <sys/times.h> - -static -Fgc_begin() -{ - return Qnil; -} - -static -Fgc_end() -{ - return Qnil; -} - -VALUE M_GC; +VALUE mGC; static struct gc_list { int n; @@ -161,7 +147,7 @@ rb_global_variable(var) { struct gc_list *tmp; - tmp = (struct gc_list*)xmalloc(sizeof(struct gc_list)); + tmp = ALLOC(struct gc_list); tmp->next = Global_List; tmp->varptr = var; tmp->n = 1; @@ -186,12 +172,13 @@ typedef struct RVALUE { struct RStruct rstruct; struct RBignum bignum; struct RNode node; - struct RAssoc assoc; + struct RMatch match; + struct RVarmap varmap; struct SCOPE scope; } as; } RVALUE; -RVALUE *freelist = Qnil; +RVALUE *freelist = 0; #define HEAPS_INCREMENT 10 static RVALUE **heaps; @@ -201,6 +188,8 @@ static int heaps_used = 0; #define HEAP_SLOTS 10000 #define FREE_MIN 512 +static RVALUE *himem, *lomem; + static void add_heap() { @@ -212,12 +201,14 @@ add_heap() heaps = (heaps_used)? (RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE)): (RVALUE**)malloc(heaps_length*sizeof(RVALUE)); - if (heaps == Qnil) Fatal("can't alloc memory"); + if (heaps == 0) Fatal("can't alloc memory"); } p = heaps[heaps_used++] = (RVALUE*)malloc(sizeof(RVALUE)*HEAP_SLOTS); - if (p == Qnil) Fatal("can't alloc memory"); + if (p == 0) Fatal("can't alloc memory"); pend = p + HEAP_SLOTS; + if (lomem == 0 || lomem > p) lomem = p; + if (himem < pend) himem = pend; while (p < pend) { p->as.free.flag = 0; @@ -245,15 +236,15 @@ newobj() } VALUE -data_new(datap, dfree, dmark) - VALUE *datap; +data_new(datap, dmark, dfree) + void *datap; void (*dfree)(); void (*dmark)(); { - extern VALUE C_Data; + extern VALUE cData; struct RData *data = (struct RData*)newobj(); - OBJSETUP(data, C_Data, T_DATA); + OBJSETUP(data, cData, T_DATA); data->data = datap; data->dfree = dfree; data->dmark = dmark; @@ -271,7 +262,10 @@ looks_pointerp(p) register RVALUE *heap_org; register long i; - /* if p looks as a SCM pointer mark location */ + if (p < lomem) return FALSE; + if (p > himem) return FALSE; + + /* check if p looks like a pointer */ for (i=0; i < heaps_used; i++) { heap_org = heaps[i]; if (heap_org <= p && p < heap_org + HEAP_SLOTS @@ -310,7 +304,7 @@ mark_locations(start, end) mark_locations_array(start,n); } -static +static int mark_entry(key, value) ID key; VALUE value; @@ -319,14 +313,14 @@ mark_entry(key, value) return ST_CONTINUE; } -static +static int mark_tbl(tbl) st_table *tbl; { st_foreach(tbl, mark_entry, 0); } -static +static int mark_hashentry(key, value) ID key; VALUE value; @@ -336,7 +330,7 @@ mark_hashentry(key, value) return ST_CONTINUE; } -static +static int mark_hash(tbl) st_table *tbl; { @@ -393,8 +387,8 @@ gc_mark(obj) break; case T_CLASS: - gc_mark(obj->as.class.super); case T_MODULE: + gc_mark(obj->as.class.super); mark_tbl(obj->as.class.m_tbl); if (obj->as.class.iv_tbl) mark_tbl(obj->as.class.iv_tbl); break; @@ -405,7 +399,7 @@ gc_mark(obj) VALUE *ptr = obj->as.array.ptr; for (i=0; i < len; i++) - gc_mark(ptr[i]); + gc_mark(*ptr++); } break; @@ -425,40 +419,37 @@ gc_mark(obj) if (obj->as.object.iv_tbl) mark_tbl(obj->as.object.iv_tbl); break; + case T_MATCH: case T_REGEXP: case T_FLOAT: case T_BIGNUM: break; - case T_STRUCT: - { - int i, len = obj->as.rstruct.len; - struct kv_pair *ptr = obj->as.rstruct.tbl; - - for (i=0; i < len; i++) - gc_mark(ptr[i].value); - } + case T_VARMAP: + gc_mark(obj->as.varmap.next); break; case T_SCOPE: - { - struct SCOPE *scope = (struct SCOPE*)obj; - if (scope->local_vars) { - int n = scope->local_tbl[0]; - VALUE *tbl = scope->local_vars; - - while (n--) { - gc_mark(*tbl); - tbl++; - } + if (obj->as.scope.local_vars) { + int n = obj->as.scope.local_tbl[0]; + VALUE *tbl = obj->as.scope.local_vars; + + while (n--) { + gc_mark(*tbl); + tbl++; } } break; - case T_ASSOC: - gc_mark(obj->as.assoc.car); - obj = (RVALUE*)obj->as.assoc.cdr; - goto Top; + case T_STRUCT: + { + int i, len = obj->as.rstruct.len; + VALUE *ptr = obj->as.rstruct.ptr; + + for (i=0; i < len; i++) + gc_mark(*ptr++); + } + break; default: Bug("gc_mark(): unknown data type %d", obj->as.basic.flags & T_MASK); @@ -475,7 +466,7 @@ gc_sweep() int freed = 0; int i; - freelist = Qnil; + freelist = 0; for (i = 0; i < heaps_used; i++) { RVALUE *p, *pend; RVALUE *nfreelist; @@ -542,14 +533,15 @@ obj_free(obj) if (obj->as.data.dfree) (*obj->as.data.dfree)(DATA_PTR(obj)); free(DATA_PTR(obj)); break; + case T_MATCH: + re_free_registers(obj->as.match.regs); + free(obj->as.match.regs); + if (obj->as.match.ptr) free(obj->as.match.ptr); + break; case T_ICLASS: /* iClass shares table with the module */ case T_FLOAT: - case T_ASSOC: - break; - case T_STRUCT: - free(obj->as.rstruct.name); - free(obj->as.rstruct.tbl); + case T_VARMAP: break; case T_BIGNUM: free(obj->as.bignum.digits); @@ -561,13 +553,14 @@ obj_free(obj) return; /* no need to free iv_tbl */ case T_SCOPE: - { - struct SCOPE *scope = (struct SCOPE*)obj; - if (scope->local_vars) - free(scope->local_vars); - if (scope->local_tbl) - free(scope->local_tbl); - } + if (obj->as.scope.local_vars) + free(obj->as.scope.local_vars); + if (obj->as.scope.local_tbl) + free(obj->as.scope.local_tbl); + break; + + case T_STRUCT: + free(obj->as.rstruct.ptr); break; default: @@ -576,11 +569,11 @@ obj_free(obj) } void -gc_mark_env(env) - struct ENVIRON *env; +gc_mark_frame(frame) + struct FRAME *frame; { - int n = env->argc; - VALUE *tbl = env->argv; + int n = frame->argc; + VALUE *tbl = frame->argv; while (n--) { gc_mark(*tbl); @@ -592,7 +585,7 @@ void gc() { struct gc_list *list; - struct ENVIRON *env; + struct FRAME *frame; jmp_buf save_regs_gc_mark; VALUE stack_end; @@ -603,9 +596,9 @@ gc() alloca(0); #endif - /* mark env stack */ - for (env = the_env; env; env = env->prev) { - gc_mark_env(env); + /* mark frame stack */ + for (frame = the_frame; frame; frame = frame->prev) { + gc_mark_frame(frame); } gc_mark(the_scope); @@ -627,7 +620,6 @@ gc() gc_mark_global_tbl(); mark_tbl(rb_class_tbl); - gc_mark_trap_list(); gc_sweep(); @@ -649,11 +641,12 @@ init_heap() add_heap(); } +void Init_GC() { - M_GC = rb_define_module("GC"); - rb_define_single_method(M_GC, "start", gc, 0); - rb_define_single_method(M_GC, "enable", Sgc_enable, 0); - rb_define_single_method(M_GC, "disable", Sgc_disable, 0); - rb_define_method(M_GC, "garbage_collect", gc, 0); + mGC = rb_define_module("GC"); + rb_define_singleton_method(mGC, "start", gc, 0); + rb_define_singleton_method(mGC, "enable", gc_s_enable, 0); + rb_define_singleton_method(mGC, "disable", gc_s_disable, 0); + rb_define_method(mGC, "garbage_collect", gc, 0); } @@ -21,15 +21,6 @@ #include "config.h" -#if defined (SHELL) -# if defined (HAVE_STDLIB_H) -# include <stdlib.h> -# else -# include "ansi_stdlib.h" -# endif /* HAVE_STDLIB_H */ -# include <config.h> -#endif - #include <sys/types.h> #if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3)) @@ -13,23 +13,19 @@ #include "ruby.h" #include "st.h" -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#else -char *getenv(); -#endif - #ifdef HAVE_STRING_H # include <string.h> #else char *strchr(); #endif -VALUE C_Hash; +char *getenv(); + +VALUE cHash; static VALUE envtbl; static ID hash; -VALUE Fgetenv(), Fsetenv(); +VALUE f_getenv(), f_setenv(); static VALUE rb_cmp(a, b) @@ -50,7 +46,7 @@ rb_hash(a, mod) #define ASSOC_VAL(a) RASSOC(a)->cdr static VALUE -Shash_new(class) +hash_s_new(class) VALUE class; { NEWOBJ(hash, struct RHash); @@ -61,10 +57,10 @@ Shash_new(class) return (VALUE)hash; } -static VALUE Fhash_clone(); +static VALUE hash_clone(); static VALUE -Shash_create(argc, argv, class) +hash_s_create(argc, argv, class) int argc; VALUE *argv; VALUE class; @@ -86,7 +82,7 @@ Shash_create(argc, argv, class) if (argc % 2 != 0) { Fail("odd number args for Hash"); } - hash = (struct RHash*)Shash_new(class); + hash = (struct RHash*)hash_s_new(class); for (i=0; i<argc; i+=2) { st_insert(hash->tbl, argv[i], argv[i+1]); @@ -98,11 +94,11 @@ Shash_create(argc, argv, class) VALUE hash_new() { - return Shash_new(C_Hash); + return hash_s_new(cHash); } static VALUE -Fhash_clone(hash) +hash_clone(hash) struct RHash *hash; { NEWOBJ(hash2, struct RHash); @@ -114,11 +110,11 @@ Fhash_clone(hash) } static VALUE -Fhash_aref(hash, key) +hash_aref(hash, key) struct RHash *hash; VALUE key; { - VALUE val = Qnil; + VALUE val; if (!st_lookup(hash->tbl, key, &val)) { return Qnil; @@ -127,7 +123,7 @@ Fhash_aref(hash, key) } static VALUE -Fhash_indexes(hash, args) +hash_indexes(hash, args) struct RHash *hash; struct RArray *args; { @@ -151,14 +147,14 @@ Fhash_indexes(hash, args) p = args->ptr; pend = p + args->len; while (p < pend) { - new_hash->ptr[i++] = Fhash_aref(hash, *p++); + new_hash->ptr[i++] = hash_aref(hash, *p++); } new_hash->len = i; return (VALUE)new_hash; } static VALUE -Fhash_delete(hash, key) +hash_delete(hash, key) struct RHash *hash; VALUE key; { @@ -176,7 +172,7 @@ struct shift_var { }; static -hash_shift(key, value, var) +shift_i(key, value, var) VALUE key, value; struct shift_var *var; { @@ -188,20 +184,20 @@ hash_shift(key, value, var) } static VALUE -Fhash_shift(hash) +hash_shift(hash) struct RHash *hash; { struct shift_var var; var.stop = 0; - st_foreach(hash->tbl, hash_shift, &var); + st_foreach(hash->tbl, shift_i, &var); if (var.stop == 0) return Qnil; return assoc_new(var.key, var.val); } static int -hash_delete_if(key, value) +delete_if_i(key, value) VALUE key, value; { if (rb_yield(assoc_new(key, value))) @@ -210,52 +206,55 @@ hash_delete_if(key, value) } static VALUE -Fhash_delete_if(hash) +hash_delete_if(hash) struct RHash *hash; { - st_foreach(hash->tbl, hash_delete_if, Qnil); + st_foreach(hash->tbl, delete_if_i, Qnil); return (VALUE)hash; } -static -hash_clear(key, value) +static int +clear_i(key, value) VALUE key, value; { return ST_DELETE; } static VALUE -Fhash_clear(hash) +hash_clear(hash) struct RHash *hash; { - st_foreach(hash->tbl, hash_clear); + st_foreach(hash->tbl, clear_i); return (VALUE)hash; } VALUE -Fhash_aset(hash, key, val) +hash_aset(hash, key, val) struct RHash *hash; VALUE key, val; { if (val == Qnil) { - Fhash_delete(hash, key); + hash_delete(hash, key); return Qnil; } + if (TYPE(key) == T_STRING) { + key = str_dup_freezed(key); + } st_insert(hash->tbl, key, val); return val; } static VALUE -Fhash_length(hash) +hash_length(hash) struct RHash *hash; { return INT2FIX(hash->tbl->num_entries); } -static -hash_each_value(key, value) +static int +each_value_i(key, value) VALUE key, value; { rb_yield(value); @@ -263,15 +262,15 @@ hash_each_value(key, value) } static VALUE -Fhash_each_value(hash) +hash_each_value(hash) struct RHash *hash; { - st_foreach(hash->tbl, hash_each_value); + st_foreach(hash->tbl, each_value_i); return (VALUE)hash; } -static -hash_each_key(key, value) +static int +each_key_i(key, value) VALUE key, value; { rb_yield(key); @@ -279,15 +278,15 @@ hash_each_key(key, value) } static VALUE -Fhash_each_key(hash) +hash_each_key(hash) struct RHash *hash; { - st_foreach(hash->tbl, hash_each_key); + st_foreach(hash->tbl, each_key_i); return (VALUE)hash; } -static -hash_each_pair(key, value) +static int +each_pair_i(key, value) VALUE key, value; { rb_yield(assoc_new(key, value)); @@ -295,15 +294,15 @@ hash_each_pair(key, value) } static VALUE -Fhash_each_pair(hash) +hash_each_pair(hash) struct RHash *hash; { - st_foreach(hash->tbl, hash_each_pair); + st_foreach(hash->tbl, each_pair_i); return (VALUE)hash; } -static -hash_to_a(key, value, ary) +static int +to_a_i(key, value, ary) VALUE key, value, ary; { ary_push(ary, assoc_new(key, value)); @@ -311,59 +310,59 @@ hash_to_a(key, value, ary) } static VALUE -Fhash_to_a(hash) +hash_to_a(hash) struct RHash *hash; { VALUE ary; ary = ary_new(); - st_foreach(hash->tbl, hash_to_a, ary); + st_foreach(hash->tbl, to_a_i, ary); return ary; } -static -hash_inspect(key, value, str) +static int +inspect_i(key, value, str) VALUE key, value; struct RString *str; { VALUE str2; - ID inspect = rb_intern("_inspect"); + ID inspect = rb_intern("inspect"); if (str->len > 1) { str_cat(str, ", ", 2); } - str2 = rb_funcall(key, inspect, 0, Qnil); + str2 = rb_funcall(key, inspect, 0, 0); str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); str_cat(str, "=>", 2); - str2 = rb_funcall(value, inspect, 0, Qnil); + str2 = rb_funcall(value, inspect, 0, 0); str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); return ST_CONTINUE; } static VALUE -Fhash_inspect(hash) +hash_inspect(hash) struct RHash *hash; { VALUE str; str = str_new2("{"); - st_foreach(hash->tbl, hash_inspect, str); + st_foreach(hash->tbl, inspect_i, str); str_cat(str, "}", 1); return str; } static VALUE -Fhash_to_s(hash) +hash_to_s(hash) VALUE hash; { - return Fary_to_s(Fhash_to_a(hash)); + return ary_to_s(hash_to_a(hash)); } -static -hash_keys(key, value, ary) +static int +keys_i(key, value, ary) VALUE key, value, ary; { ary_push(ary, key); @@ -371,49 +370,37 @@ hash_keys(key, value, ary) } static VALUE -Fhash_keys(hash) +hash_keys(hash) struct RHash *hash; { VALUE ary; ary = ary_new(); - st_foreach(hash->tbl, hash_keys, ary); + st_foreach(hash->tbl, keys_i, ary); return ary; } -static -hash_values(key, value, ary) +static int +values_i(key, value, ary) VALUE key, value, ary; { - ary_push(ary, key); + ary_push(ary, value); return ST_CONTINUE; } static VALUE -Fhash_values(hash) +hash_values(hash) struct RHash *hash; { VALUE ary; ary = ary_new(); - st_foreach(hash->tbl, hash_values, ary); + st_foreach(hash->tbl, values_i, ary); return ary; } -static VALUE -Fhash_has_key(hash, key) - struct RHash *hash; - VALUE key; -{ - VALUE val; - - if (st_lookup(hash->tbl, key, &val)) - return TRUE; - return FALSE; -} - static int hash_search_value(key, value, data) VALUE key, value, *data; @@ -426,7 +413,18 @@ hash_search_value(key, value, data) } static VALUE -Fhash_has_value(hash, val) +hash_has_key(hash, key) + struct RHash *hash; + VALUE key; +{ + if (st_lookup(hash->tbl, key, 0)) { + return TRUE; + } + return FALSE; +} + +static VALUE +hash_has_value(hash, val) struct RHash *hash; VALUE val; { @@ -444,7 +442,7 @@ struct equal_data { }; static int -hash_equal(key, val1, data) +equal_i(key, val1, data) VALUE key, val1; struct equal_data *data; { @@ -462,7 +460,7 @@ hash_equal(key, val1, data) } static VALUE -Fhash_equal(hash1, hash2) +hash_equal(hash1, hash2) struct RHash *hash1, *hash2; { struct equal_data data; @@ -473,13 +471,13 @@ Fhash_equal(hash1, hash2) data.tbl = hash2->tbl; data.result = TRUE; - st_foreach(hash1->tbl, hash_equal, &data); + st_foreach(hash1->tbl, equal_i, &data); return data.result; } static int -hash_hash(key, val, data) +hash_i(key, val, data) VALUE key, val; int *data; { @@ -489,21 +487,19 @@ hash_hash(key, val, data) } static VALUE -Fhash_hash(hash) +hash_hash(hash) struct RHash *hash; { int h; - st_foreach(hash->tbl, hash_hash, &h); + st_foreach(hash->tbl, hash_i, &h); return INT2FIX(h); } -extern VALUE rb_readonly_hook(); - extern char **environ; static VALUE -Fenv_each(hash) +env_each(hash) VALUE hash; { char **env; @@ -522,12 +518,12 @@ Fenv_each(hash) } static VALUE -Fenv_delete(obj, name) +env_delete(obj, name) VALUE obj; struct RString *name; { int i, len; - char *nam, *val = Qnil; + char *nam, *val = 0; Check_Type(name, T_STRING); nam = name->ptr; @@ -549,7 +545,7 @@ Fenv_delete(obj, name) } VALUE -Fgetenv(obj, name) +f_getenv(obj, name) VALUE obj; struct RString *name; { @@ -568,13 +564,13 @@ Fgetenv(obj, name) } VALUE -Fsetenv(obj, name, value) +f_setenv(obj, name, value) VALUE obj; struct RString *name, *value; { Check_Type(name, T_STRING); if (value == Qnil) { - Fenv_delete(obj, name); + env_delete(obj, name); return Qnil; } @@ -585,86 +581,69 @@ Fsetenv(obj, name, value) if (strlen(value->ptr) != value->len) Fail("Bad environment value"); -#ifdef HAVE_SETENV - if (setenv(name->ptr, value->ptr, 1) == 0) return TRUE; -#else -#ifdef HAVE_PUTENV - { - char *str; - int len; - - str = ALLOC_N(char, name->len + value->len + 2); - sprintf("%s=%s", name->ptr, value->ptr); - if (putenv(str) == 0) return TRUE; - } -#else - Fail("setenv is not supported on this system"); -#endif -#endif - - Fail("setenv failed"); - return FALSE; /* not reached */ + setenv(name->ptr, value->ptr, 1); + return TRUE; } static VALUE -Fenv_to_s() +env_to_s() { return str_new2("$ENV"); } +void Init_Hash() { - extern VALUE C_Kernel; - extern VALUE M_Enumerable; + extern VALUE cKernel; + extern VALUE mEnumerable; hash = rb_intern("hash"); - C_Hash = rb_define_class("Hash", C_Object); + cHash = rb_define_class("Hash", cObject); - rb_include_module(C_Hash, M_Enumerable); + rb_include_module(cHash, mEnumerable); - rb_define_single_method(C_Hash, "new", Shash_new, 0); - rb_define_single_method(C_Hash, "[]", Shash_create, -1); + rb_define_singleton_method(cHash, "new", hash_s_new, 0); + rb_define_singleton_method(cHash, "[]", hash_s_create, -1); - rb_define_method(C_Hash,"clone", Fhash_clone, 0); + rb_define_method(cHash,"clone", hash_clone, 0); - rb_define_method(C_Hash,"to_a", Fhash_to_a, 0); - rb_define_method(C_Hash,"to_s", Fhash_to_s, 0); - rb_define_method(C_Hash,"_inspect", Fhash_inspect, 0); + rb_define_method(cHash,"to_a", hash_to_a, 0); + rb_define_method(cHash,"to_s", hash_to_s, 0); + rb_define_method(cHash,"inspect", hash_inspect, 0); - rb_define_method(C_Hash,"==", Fhash_equal, 1); - rb_define_method(C_Hash,"hash", Fhash_hash, 0); - rb_define_method(C_Hash,"[]", Fhash_aref, 1); - rb_define_method(C_Hash,"[]=", Fhash_aset, 2); - rb_define_method(C_Hash,"indexes", Fhash_indexes, -2); - rb_define_method(C_Hash,"length", Fhash_length, 0); - rb_define_alias(C_Hash, "size", "length"); - rb_define_method(C_Hash,"each", Fhash_each_pair, 0); - rb_define_method(C_Hash,"each_value", Fhash_each_value, 0); - rb_define_method(C_Hash,"each_key", Fhash_each_key, 0); - rb_define_method(C_Hash,"each_pair", Fhash_each_pair, 0); + rb_define_method(cHash,"==", hash_equal, 1); + rb_define_method(cHash,"hash", hash_hash, 0); + rb_define_method(cHash,"[]", hash_aref, 1); + rb_define_method(cHash,"[]=", hash_aset, 2); + rb_define_method(cHash,"indexes", hash_indexes, -2); + rb_define_method(cHash,"length", hash_length, 0); + rb_define_alias(cHash, "size", "length"); + rb_define_method(cHash,"each", hash_each_pair, 0); + rb_define_method(cHash,"each_value", hash_each_value, 0); + rb_define_method(cHash,"each_key", hash_each_key, 0); + rb_define_method(cHash,"each_pair", hash_each_pair, 0); - rb_define_method(C_Hash,"keys", Fhash_keys, 0); - rb_define_method(C_Hash,"values", Fhash_values, 0); + rb_define_method(cHash,"keys", hash_keys, 0); + rb_define_method(cHash,"values", hash_values, 0); - rb_define_method(C_Hash,"shift", Fhash_shift, 0); - rb_define_method(C_Hash,"delete", Fhash_delete, 1); - rb_define_method(C_Hash,"delete_if", Fhash_delete_if, 0); - rb_define_method(C_Hash,"clear", Fhash_clear, 0); + rb_define_method(cHash,"shift", hash_shift, 0); + rb_define_method(cHash,"delete", hash_delete, 1); + rb_define_method(cHash,"delete_if", hash_delete_if, 0); + rb_define_method(cHash,"clear", hash_clear, 0); - rb_define_method(C_Hash,"includes", Fhash_has_key, 1); - rb_define_method(C_Hash,"has_key", Fhash_has_key, 1); - rb_define_method(C_Hash,"has_value", Fhash_has_value, 1); + rb_define_method(cHash,"has_key?", hash_has_key, 1); + rb_define_method(cHash,"has_value?", hash_has_value, 1); - envtbl = obj_alloc(C_Object); - rb_extend_object(envtbl, M_Enumerable); + envtbl = obj_alloc(cObject); + rb_extend_object(envtbl, mEnumerable); - rb_define_single_method(envtbl,"[]", Fgetenv, 1); - rb_define_single_method(envtbl,"[]=", Fsetenv, 2); - rb_define_single_method(envtbl,"each", Fenv_each, 0); - rb_define_single_method(envtbl,"delete", Fenv_delete, 1); - rb_define_single_method(envtbl,"to_s", Fenv_to_s, 0); + rb_define_singleton_method(envtbl,"[]", f_getenv, 1); + rb_define_singleton_method(envtbl,"[]=", f_setenv, 2); + rb_define_singleton_method(envtbl,"each", env_each, 0); + rb_define_singleton_method(envtbl,"delete", env_delete, 1); + rb_define_singleton_method(envtbl,"to_s", env_to_s, 0); - rb_define_variable("$ENV", &envtbl, Qnil, rb_readonly_hook, 0); - rb_define_const(C_Kernel, "ENV", envtbl); + rb_define_readonly_variable("$ENV", &envtbl); + rb_define_const(cKernel, "ENV", envtbl); } diff --git a/ident.h b/ident.h deleted file mode 100644 index 1e28098576..0000000000 --- a/ident.h +++ /dev/null @@ -1,26 +0,0 @@ -/************************************************ - - ident.h - - - $Author: matz $ - $Revision: 1.2 $ - $Date: 1994/08/12 04:47:29 $ - created at: Mon Jan 31 16:23:19 JST 1994 - - Copyright (C) 1993-1995 Yukihiro Matsumoto - -************************************************/ - -#ifndef IDENT_H -#define IDENT_H - -#define ID_SCOPE_SHIFT 3 -#define ID_SCOPE_MASK 0x07 -#define ID_LOCAL 0x00 -#define ID_INSTANCE 0x01 -#define ID_GLOBAL 0x02 -#define ID_ATTRSET 0x03 -#define ID_CONST 0x04 -#define ID_NTHREF 0x05 - -#endif @@ -12,6 +12,7 @@ #include "ruby.h" +void rb_call_inits() { Init_sym(); @@ -23,7 +24,6 @@ rb_call_inits() Init_Enumerable(); Init_Numeric(); Init_Bignum(); - Init_Assoc(); Init_Array(); Init_Hash(); Init_Struct(); @@ -37,12 +37,9 @@ rb_call_inits() Init_Random(); Init_signal(); Init_process(); - Init_Etc(); Init_load(); - Init_Block(); + Init_Proc(); Init_Math(); - /* new Inits comes between here.. */ - - /* .. and here. */ + Init_ext(); Init_version(); } @@ -14,15 +14,27 @@ #include "io.h" #include <ctype.h> #include <errno.h> -#include <sys/time.h> + #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#else +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif +#ifdef HAVE_VFORK_H +#include <vfork.h> +#endif + VALUE rb_ad_string(); -VALUE C_IO; -extern VALUE C_File; +VALUE cIO; +extern VALUE cFile; VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout; @@ -46,9 +58,6 @@ io_write(obj, str) VALUE out; int n; - if (TYPE(str) != T_STRING) - str = (struct RString*)obj_as_string(str); - GetOpenFile(obj, fptr); if (!(fptr->mode & FMODE_WRITABLE)) { Fail("not opened for writing"); @@ -57,6 +66,8 @@ io_write(obj, str) f = (fptr->f2) ? fptr->f2 : fptr->f; if (f == NULL) Fail("closed stream"); + if (TYPE(str) != T_STRING) + str = (struct RString*)obj_as_string(str); if (str->len == 0) return INT2FIX(0); n = fwrite(str->ptr, sizeof(char), str->len, f); @@ -71,7 +82,7 @@ io_write(obj, str) } static VALUE -Fio_puts(obj, str) +io_puts(obj, str) VALUE obj, str; { io_write(obj, str); @@ -79,7 +90,7 @@ Fio_puts(obj, str) } static VALUE -Fio_flush(obj) +io_flush(obj) VALUE obj; { OpenFile *fptr; @@ -98,7 +109,7 @@ Fio_flush(obj) } static VALUE -Fio_eof(obj) +io_eof(obj) VALUE obj; { OpenFile *fptr; @@ -126,7 +137,7 @@ Fio_eof(obj) } static VALUE -Fio_sync(obj) +io_sync(obj) VALUE obj; { OpenFile *fptr; @@ -136,7 +147,7 @@ Fio_sync(obj) } static VALUE -Fio_set_sync(obj, mode) +io_set_sync(obj, mode) VALUE obj, mode; { OpenFile *fptr; @@ -152,7 +163,7 @@ Fio_set_sync(obj, mode) } static VALUE -Fio_fileno(obj) +io_fileno(obj) VALUE obj; { OpenFile *fptr; @@ -194,7 +205,7 @@ read_all(port) } static VALUE -Fio_read(argc, argv, obj) +io_read(argc, argv, obj) int argc; VALUE *argv; VALUE obj; @@ -234,7 +245,7 @@ VALUE rb_lastline; static VALUE lineno; static VALUE -Fio_gets(obj) +io_gets(obj) VALUE obj; { OpenFile *fptr; @@ -264,7 +275,7 @@ Fio_gets(obj) rslen = 1; } - if (rslen == 0 && c == '\n') { + if (rslen == 0) { do { TRAP_BEG; c = getc(f); @@ -279,7 +290,6 @@ Fio_gets(obj) { char buf[8192]; char *bp, *bpe = buf + sizeof buf - 3; - char *ptr; int append = 0; again: @@ -323,7 +333,7 @@ Fio_gets(obj) } return_gets: - if (rslen == 0 && c == '\n') { + if (rslen == 0) { while (c != EOF) { TRAP_BEG; c = getc(f); @@ -343,19 +353,19 @@ Fio_gets(obj) } static VALUE -Fio_each(obj) +io_each_line(obj) VALUE obj; { VALUE str; - while (str = Fio_gets(obj)) { + while (str = io_gets(obj)) { rb_yield(str); } return Qnil; } static VALUE -Fio_each_byte(obj) +io_each_byte(obj) VALUE obj; { OpenFile *fptr; @@ -381,7 +391,7 @@ Fio_each_byte(obj) } static VALUE -Fio_getc(obj) +io_getc(obj) VALUE obj; { OpenFile *fptr; @@ -407,43 +417,78 @@ Fio_getc(obj) } static VALUE -Fio_isatty(obj) +io_isatty(obj) VALUE obj; { OpenFile *fptr; +#ifndef NT GetOpenFile(obj, fptr); if (fptr->f == NULL) Fail("closed stream"); if (isatty(fileno(fptr->f)) == 0) return FALSE; - +#endif return TRUE; } -static VALUE -Fio_close(obj) - VALUE obj; -{ +static void +fptr_finalize(fptr) OpenFile *fptr; - - GetOpenFile(obj, fptr); - +{ + if (fptr->f != NULL) { + fclose(fptr->f); + } if (fptr->f2 != NULL) { fclose(fptr->f2); } - if (fptr->f != NULL) { - fclose(fptr->f); + if (fptr->path) { + free(fptr->path); + fptr->path = NULL; } - fptr->f = fptr->f2 = NULL; if (fptr->pid) { rb_syswait(fptr->pid); fptr->pid = 0; } +} + +void +io_fptr_finalize(fptr) + OpenFile *fptr; +{ + if (fptr->finalize) { + (*fptr->finalize)(fptr); + fptr->finalize = 0; + } + else { + fptr_finalize(fptr); + } + fptr->f = fptr->f2 = NULL; +} + +VALUE +io_close(obj) + VALUE obj; +{ + OpenFile *fptr; + + GetOpenFile(obj, fptr); + io_fptr_finalize(fptr); + return Qnil; } static VALUE -Fio_syswrite(obj, str) +io_closed(obj) + VALUE obj; +{ + OpenFile *fptr; + + GetOpenFile(obj, fptr); + return fptr->f?FALSE:TRUE; +} + +static VALUE +io_syswrite(obj, str) VALUE obj, str; { OpenFile *fptr; @@ -468,7 +513,7 @@ Fio_syswrite(obj, str) } static VALUE -Fio_sysread(obj, len) +io_sysread(obj, len) VALUE obj, len; { OpenFile *fptr; @@ -496,29 +541,11 @@ Fio_sysread(obj, len) return str; } -void -io_free_OpenFile(fptr) - OpenFile *fptr; -{ - if (fptr->f != NULL) { - fclose(fptr->f); - } - if (fptr->f2 != NULL) { - fclose(fptr->f2); - } - if (fptr->path) { - free(fptr->path); - } - if (fptr->pid) { - rb_syswait(fptr->pid); - } -} - static VALUE -Fio_binmode(obj) +io_binmode(obj) VALUE obj; { -#ifdef MSDOS +#ifdef NT OpenFile *fptr; GetOpenFile(obj, fptr); @@ -530,6 +557,7 @@ Fio_binmode(obj) VALUE obj_alloc(); +int io_mode_flags(mode) char *mode; { @@ -564,8 +592,7 @@ rb_fdopen(fd, mode) f = fdopen(fd, mode); if (f == NULL) { - if (errno = EMFILE) { - gc(); + if (errno == EMFILE) { f = fdopen(fd, mode); } if (f == NULL) { @@ -575,22 +602,45 @@ rb_fdopen(fd, mode) return f; } +#ifdef NT +static void +pipe_finalize(fptr) + OpenFile *fptr; +{ + if (fptr->f != NULL) { + pclose(fptr->f); + } + fptr->f = fptr->f2 = NULL; +} +#endif + static VALUE pipe_open(pname, mode) char *pname, *mode; { + int modef = io_mode_flags(mode); VALUE port; OpenFile *fptr; - int pid, pr[2], pw[2]; - int doexec; +#ifdef NT + FILE *f = popen(pname, mode); + + if (f == NULL) rb_sys_fail(pname); - port = obj_alloc(C_IO); + port = obj_alloc(cIO); MakeOpenFile(port, fptr); - fptr->mode = io_mode_flags(mode); + fptr->finalize = pipe_finalize; + + if (modef & FMODE_READABLE) fptr->f = f; + if (modef & FMODE_WRITABLE) fptr->f2 = f; + fptr->mode = modef | FMODE_SYNC; + return port; +#else + int pid, pr[2], pw[2]; + volatile int doexec; - if (((fptr->mode & FMODE_READABLE) && pipe(pr) == -1) || - ((fptr->mode & FMODE_WRITABLE) && pipe(pw) == -1)) + if (((modef & FMODE_READABLE) && pipe(pr) == -1) || + ((modef & FMODE_WRITABLE) && pipe(pw) == -1)) rb_sys_fail(Qnil); doexec = (strcmp("-", pname) != 0); @@ -603,18 +653,26 @@ pipe_open(pname, mode) retry: switch (pid = (doexec?vfork():fork())) { case 0: /* child */ - if (fptr->mode & FMODE_READABLE) { + if (modef & FMODE_READABLE) { close(pr[0]); dup2(pr[1], 1); close(pr[1]); } - if (fptr->mode & FMODE_WRITABLE) { + if (modef & FMODE_WRITABLE) { close(pw[1]); dup2(pw[0], 0); close(pw[0]); } if (doexec) { + VALUE fd = io_fileno(rb_stderr); + int f = FIX2INT(fd); + + if (f != 2) { + close(2); + dup2(f, 2); + close(f); + } rb_proc_exec(pname); _exit(127); } @@ -622,25 +680,28 @@ pipe_open(pname, mode) case -1: /* fork failed */ if (errno == EAGAIN) { - sleep(5); + sleep(1); goto retry; } + close(pr[0]); close(pw[1]); + rb_sys_fail(pname); break; default: /* parent */ - if (fptr->mode & FMODE_READABLE) close(pr[1]); - if (fptr->mode & FMODE_WRITABLE) close(pw[0]); - } - if (pid == -1) { - close(pr[0]); close(pw[1]); - rb_sys_fail(Qnil); + port = obj_alloc(cIO); + MakeOpenFile(port, fptr); + if (modef & FMODE_READABLE) close(pr[1]); + if (modef & FMODE_WRITABLE) close(pw[0]); + fptr->mode = modef; + fptr->mode |= FMODE_SYNC; } fptr->pid = pid; - if (fptr->mode & FMODE_READABLE) fptr->f = rb_fdopen(pr[0], "r"); - if (fptr->mode & FMODE_WRITABLE) fptr->f2 = rb_fdopen(pw[1], "w"); + if (modef & FMODE_READABLE) fptr->f = rb_fdopen(pr[0], "r"); + if (modef & FMODE_WRITABLE) fptr->f2 = rb_fdopen(pw[1], "w"); return port; +#endif } static VALUE @@ -658,7 +719,7 @@ io_open(fname, mode) } static VALUE -Fopen(argc, argv, self) +f_open(argc, argv, self) int argc; VALUE *argv; VALUE self; @@ -683,7 +744,18 @@ Fopen(argc, argv, self) } static VALUE -Fprintf(argc, argv) +io_printf(argc, argv, out) + int argc; + VALUE argv[]; + VALUE out; +{ + rb_funcall(out, id_write, 1, f_sprintf(argc, argv)); + + return Qnil; +} + +static VALUE +f_printf(argc, argv) int argc; VALUE argv[]; { @@ -693,7 +765,7 @@ Fprintf(argc, argv) if (TYPE(argv[0]) == T_STRING) { out = rb_defout; } - else if (obj_responds_to(argv[0], INT2FIX(id_write))) { + else if (rb_responds_to(argv[0], id_write)) { out = argv[0]; argv++; argc--; @@ -701,63 +773,78 @@ Fprintf(argc, argv) else { Fail("output must responds to `write'"); } - rb_funcall(out, id_write, 1, Fsprintf(argc, argv)); + rb_funcall(out, id_write, 1, f_sprintf(argc, argv)); return Qnil; } static VALUE -Fprint(argc, argv, self) +io_print(argc, argv, out) int argc; VALUE *argv; - VALUE self; + VALUE out; { int i; + VALUE line; - /* if no argument given, print recv */ + /* if no argument given, print `$_' */ if (argc == 0) { - rb_funcall(self, id_print_on, 1, rb_defout); + argc = 1; + if (rb_lastline) + argv = &rb_lastline; + else { + line = str_new(0,0); + argv = &line; + } } - else { - for (i=0; i<argc; i++) { - if (OFS && i>0) { - io_write(rb_defout, OFS); - } - switch (TYPE(argv[i])) { - case T_STRING: - io_write(rb_defout, argv[i]); - break; - case T_ARRAY: - Fary_print_on(argv[i], rb_defout); - break; - default: - rb_funcall(argv[i], id_print_on, 1, rb_defout); - break; - } + for (i=0; i<argc; i++) { + if (OFS && i>0) { + io_write(out, OFS); + } + switch (TYPE(argv[i])) { + case T_STRING: + io_write(out, argv[i]); + break; + case T_ARRAY: + ary_print_on(argv[i], out); + break; + default: + rb_funcall(argv[i], id_print_on, 1, out); + break; } } if (ORS) { - io_write(rb_defout, ORS); + io_write(out, ORS); } return Qnil; } static VALUE -io_defset(obj, val) - VALUE obj, val; +f_print(argc, argv) + int argc; + VALUE *argv; +{ + io_print(argc, argv, rb_defout); + return Qnil; +} + +static VALUE +io_defset(val, id) + VALUE val; + ID id; { if (TYPE(val) == T_STRING) { val = io_open(RSTRING(val)->ptr, "w"); } - if (!obj_is_kind_of(val, C_IO)) { + if (!obj_is_kind_of(val, cIO)) { Fail("$< must be a file, %s given", rb_class2name(CLASS_OF(val))); } return rb_defout = val; } static VALUE -Fprint_on(obj, port) +f_print_on(obj, port) VALUE obj, port; { return io_write(port, obj); @@ -768,7 +855,7 @@ prep_stdio(f, mode) FILE *f; int mode; { - VALUE obj = obj_alloc(C_IO); + VALUE obj = obj_alloc(cIO); OpenFile *fp; MakeOpenFile(obj, fp); @@ -815,18 +902,23 @@ next_argv() else { FILE *fr = fopen(fn, "r"); + if (!fr) rb_sys_fail(fn); if (inplace) { struct stat st, st2; VALUE str; FILE *fw; if (rb_defout != rb_stdout) { - Fio_close(rb_defout); + io_close(rb_defout); } fstat(fileno(fr), &st); if (*inplace) { str = str_new2(fn); +#ifdef NT + add_suffix(str, inplace); +#else str_cat(str, inplace, strlen(inplace)); +#endif if (rename(fn, RSTRING(str)->ptr) < 0) { Warning("Can't rename %s to %s: %s, skipping file", fn, RSTRING(str)->ptr, strerror(errno)); @@ -860,15 +952,15 @@ next_argv() } static VALUE -Fgets() +f_gets() { VALUE line; retry: if (!next_argv()) return Qnil; - line = Fio_gets(file); + line = io_gets(file); if (line == Qnil && next_p != -1) { - Fio_close(file); + io_close(file); next_p = 1; goto retry; } @@ -880,11 +972,11 @@ Fgets() } static VALUE -Feof() +f_eof() { if (init_p == 0 && !next_argv()) return TRUE; - if (Fio_eof(file)) { + if (io_eof(file)) { next_p = 1; return TRUE; } @@ -892,19 +984,19 @@ Feof() } static VALUE -Fgetc() +f_getc() { - return Fio_getc(rb_stdin); + return io_getc(rb_stdin); } static VALUE -Freadlines(obj) +f_readlines(obj) VALUE obj; { VALUE line, ary; ary = ary_new(); - while (line = Fgets(obj)) { + while (line = f_gets(obj)) { ary_push(ary, line); } @@ -912,15 +1004,15 @@ Freadlines(obj) } VALUE -rb_check_str(val, id) +rb_str_setter(val, id, var) VALUE val; ID id; + VALUE *var; { - if (val == Qnil) return TRUE; - if (TYPE(val) != T_STRING) { + if (val && TYPE(val) != T_STRING) { Fail("value of %s must be String", rb_id2name(id)); } - return TRUE; + return *var = val; } VALUE @@ -929,15 +1021,12 @@ rb_xstring(str) { VALUE port, result; OpenFile *fptr; - int mask; Check_Type(str, T_STRING); port = pipe_open(str->ptr, "r"); result = read_all(port); - GetOpenFile(port, fptr); - rb_syswait(fptr->pid); - fptr->pid = 0; + io_close(port); return result; } @@ -945,25 +1034,22 @@ rb_xstring(str) struct timeval *time_timeval(); #ifdef _STDIO_USES_IOSTREAM /* GNU libc */ -# ifdef _other_gbase +# ifdef _IO_fpos_t # define READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr < (fp)->_IO_read_end) # else # define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr) # endif #else -# if __SLBF -# define READ_DATA_PENDING(fp) (fp->_r > 0) +# ifdef FILE_COUNT +# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0) # else -# if STDSTDIO -# define READ_DATA_PENDING(fp) (fp->_cnt != 0) -# else ---------------> You Lose <-------------- -# endif +extern int ReadDataPending(); +# define READ_DATA_PENDING(fp) ReadDataPending(fp) # endif #endif static VALUE -Fselect(argc, argv, obj) +f_select(argc, argv, obj) int argc; VALUE *argv; VALUE obj; @@ -971,7 +1057,7 @@ Fselect(argc, argv, obj) VALUE read, write, except, timeout, res, list; fd_set rset, wset, eset, pset; fd_set *rp, *wp, *ep; - struct timeval time, *tp, timerec; + struct timeval *tp, timerec; OpenFile *fptr; int i, max = 0, n; int interrupt = 0; @@ -1049,21 +1135,17 @@ Fselect(argc, argv, obj) n = select(max, rp, wp, ep, tp); TRAP_END; if (n < 0) { - if (errno == EINTR) { - if (tp == NULL) goto retry; - interrupt = 1; + if (errno != EINTR) { + rb_sys_fail(Qnil); } - rb_sys_fail(Qnil); + if (tp == NULL) goto retry; + interrupt = 1; } - if (n == 0) return Qnil; res = ary_new2(3); - RARRAY(res)->ptr[0] = rp?ary_new():Qnil; - RARRAY(res)->len++; - RARRAY(res)->ptr[1] = wp?ary_new():Qnil; - RARRAY(res)->len++; - RARRAY(res)->ptr[2] = ep?ary_new():Qnil; - RARRAY(res)->len++; + ary_push(res, rp?ary_new():ary_new2(0)); + ary_push(res, wp?ary_new():ary_new2(0)); + ary_push(res, ep?ary_new():ary_new2(0)); if (interrupt == 0) { @@ -1139,16 +1221,23 @@ io_ctl(obj, req, arg, io_p) } arg->ptr[len] = 17; fd = fileno(fptr->f); +#ifdef HAVE_FCNTL if ((io_p?ioctl(fd, cmd, arg->ptr):fcntl(fd, cmd, arg->ptr))<0) { rb_sys_fail(fptr->path); } +#else + if (!io_p) { + Bug("fcntl() not implemented"); + } + if (ioctl(fd, cmd, arg->ptr)<0) rb_sys_fail(fptr->path); +#endif if (arg->ptr[len] != 17) { Fail("Return value overflowed string"); } } static VALUE -Fio_ioctl(obj, req, arg) +io_ioctl(obj, req, arg) VALUE obj, req; struct RString *arg; { @@ -1157,7 +1246,7 @@ Fio_ioctl(obj, req, arg) } static VALUE -Fsyscall(argc, argv) +f_syscall(argc, argv) int argc; VALUE *argv; { @@ -1251,7 +1340,7 @@ Fsyscall(argc, argv) } static VALUE -Farg_read(obj) +arg_read(obj) VALUE obj; { VALUE str, str2; @@ -1260,9 +1349,9 @@ Farg_read(obj) for (;;) { retry: if (!next_argv()) return Qnil; - str2 = Fio_read(0, Qnil, file); + str2 = io_read(0, Qnil, file); if (str2 == Qnil && next_p != -1) { - Fio_close(file); + io_close(file); next_p = 1; goto retry; } @@ -1274,15 +1363,15 @@ Farg_read(obj) } static VALUE -Farg_getc() +arg_getc() { VALUE byte; retry: if (!next_argv()) return Qnil; - byte = Fio_getc(file); + byte = io_getc(file); if (byte == Qnil && next_p != -1) { - Fio_close(file); + io_close(file); next_p = 1; goto retry; } @@ -1291,144 +1380,151 @@ Farg_getc() } static VALUE -Farg_each() +arg_each_line() { VALUE str; - while (str = Fgets()) { + while (str = f_gets()) { rb_yield(str); } return Qnil; } static VALUE -Farg_each_byte() +arg_each_byte() { VALUE byte; - while (byte = Farg_getc()) { + while (byte = arg_getc()) { rb_yield(byte); } return Qnil; } static VALUE -Farg_filename() +arg_filename() { return filename; } static VALUE -Farg_file() +arg_file() { return file; } -extern VALUE M_Enumerable; -VALUE rb_readonly_hook(); +extern VALUE mEnumerable; +void Init_IO() { - extern VALUE C_Kernel; + extern VALUE cKernel; id_write = rb_intern("write"); id_fd = rb_intern("fd"); id_print_on = rb_intern("print_on"); - rb_define_private_method(C_Kernel, "syscall", Fsyscall, -1); + rb_define_private_method(cKernel, "syscall", f_syscall, -1); - rb_define_private_method(C_Kernel, "open", Fopen, -1); - rb_define_private_method(C_Kernel, "printf", Fprintf, -1); - rb_define_private_method(C_Kernel, "gets", Fgets, 0); - rb_define_alias(C_Kernel,"readline", "gets"); - rb_define_private_method(C_Kernel, "eof", Feof, 0); - rb_define_private_method(C_Kernel, "getc", Fgetc, 0); - rb_define_private_method(C_Kernel, "select", Fselect, -1); + rb_define_private_method(cKernel, "open", f_open, -1); + rb_define_private_method(cKernel, "printf", f_printf, -1); + rb_define_private_method(cKernel, "print", f_print, -1); + rb_define_private_method(cKernel, "gets", f_gets, 0); + rb_define_alias(cKernel,"readline", "gets"); + rb_define_private_method(cKernel, "eof", f_eof, 0); + rb_define_private_method(cKernel, "getc", f_getc, 0); + rb_define_private_method(cKernel, "select", f_select, -1); - rb_define_private_method(C_Kernel, "readlines", Freadlines, 0); + rb_define_private_method(cKernel, "readlines", f_readlines, 0); - rb_define_method(C_Kernel, "print_on", Fprint_on, 1); - rb_define_method(C_Kernel, "print", Fprint, -1); + rb_define_method(cKernel, "print_on", f_print_on, 1); - C_IO = rb_define_class("IO", C_Object); - rb_include_module(C_IO, M_Enumerable); + cIO = rb_define_class("IO", cObject); + rb_include_module(cIO, mEnumerable); - rb_define_variable("$;", &FS, Qnil, rb_check_str, 0); - rb_define_variable("$,", &OFS, Qnil, rb_check_str, 0); + rb_define_hooked_variable("$;", &FS, 0, rb_str_setter); + rb_define_hooked_variable("$,", &OFS, 0, rb_str_setter); RS = str_new2("\n"); - rb_define_variable("$/", &RS, Qnil, rb_check_str, 0); - rb_define_variable("$\\", &ORS, Qnil, rb_check_str, 0); + rb_define_hooked_variable("$/", &RS, 0, rb_str_setter); + rb_define_hooked_variable("$\\", &ORS, 0, rb_str_setter); + + rb_define_variable("$.", &lineno); + rb_define_variable("$_", &rb_lastline); - rb_define_variable("$.", &lineno, Qnil, Qnil, 0); - rb_define_variable("$_", &rb_lastline, Qnil, Qnil, 0); + rb_define_method(cIO, "print", io_print, -1); - rb_define_method(C_IO, "each", Fio_each, 0); - rb_define_method(C_IO, "each_byte", Fio_each_byte, 0); + rb_define_method(cIO, "each", io_each_line, 0); + rb_define_method(cIO, "each_line", io_each_line, 0); + rb_define_method(cIO, "each_byte", io_each_byte, 0); - rb_define_method(C_IO, "syswrite", Fio_syswrite, 1); - rb_define_method(C_IO, "sysread", Fio_sysread, 1); + rb_define_method(cIO, "syswrite", io_syswrite, 1); + rb_define_method(cIO, "sysread", io_sysread, 1); - rb_define_method(C_IO, "fileno", Fio_fileno, 0); - rb_define_alias(C_IO, "to_i", "fileno"); + rb_define_method(cIO, "fileno", io_fileno, 0); + rb_define_alias(cIO, "to_i", "fileno"); - rb_define_method(C_IO, "sync", Fio_sync, 0); - rb_define_method(C_IO, "sync=", Fio_set_sync, 1); + rb_define_method(cIO, "sync", io_sync, 0); + rb_define_method(cIO, "sync=", io_set_sync, 1); - rb_define_alias(C_IO, "readlines", "to_a"); + rb_define_alias(cIO, "readlines", "to_a"); - rb_define_method(C_IO, "read", Fio_read, -2); - rb_define_method(C_IO, "write", io_write, 1); - rb_define_method(C_IO, "gets", Fio_gets, 0); - rb_define_alias(C_IO, "readline", "gets"); - rb_define_method(C_IO, "getc", Fio_getc, 0); - rb_define_method(C_IO, "puts", Fio_puts, 1); - rb_define_method(C_IO, "<<", Fio_puts, 1); - rb_define_method(C_IO, "flush", Fio_flush, 0); - rb_define_method(C_IO, "eof", Fio_eof, 0); + rb_define_method(cIO, "read", io_read, -2); + rb_define_method(cIO, "write", io_write, 1); + rb_define_method(cIO, "gets", io_gets, 0); + rb_define_alias(cIO, "readline", "gets"); + rb_define_method(cIO, "getc", io_getc, 0); + rb_define_method(cIO, "puts", io_puts, 1); + rb_define_method(cIO, "<<", io_puts, 1); + rb_define_method(cIO, "flush", io_flush, 0); + rb_define_method(cIO, "eof", io_eof, 0); - rb_define_method(C_IO, "close", Fio_close, 0); + rb_define_method(cIO, "close", io_close, 0); + rb_define_method(cIO, "closed?", io_closed, 0); - rb_define_method(C_IO, "isatty", Fio_isatty, 0); - rb_define_method(C_IO, "binmode", Fio_binmode, 0); + rb_define_method(cIO, "isatty", io_isatty, 0); + rb_define_method(cIO, "tty?", io_isatty, 0); + rb_define_method(cIO, "binmode", io_binmode, 0); - rb_define_method(C_IO, "ioctl", Fio_ioctl, 2); + rb_define_method(cIO, "ioctl", io_ioctl, 2); rb_stdin = prep_stdio(stdin, FMODE_READABLE); - rb_define_variable("$stdin", &rb_stdin, Qnil, rb_readonly_hook, 0); + rb_define_readonly_variable("$stdin", &rb_stdin); rb_stdout = prep_stdio(stdout, FMODE_WRITABLE); - rb_define_variable("$stdout", &rb_stdout, Qnil, rb_readonly_hook, 0); + rb_define_readonly_variable("$stdout", &rb_stdout); rb_stderr = prep_stdio(stderr, FMODE_WRITABLE); - rb_define_variable("$stderr", &rb_stderr, Qnil, rb_readonly_hook, 0); + rb_define_readonly_variable("$stderr", &rb_stderr); rb_defout = rb_stdout; - rb_define_variable("$>", &rb_defout, Qnil, io_defset, 0); + rb_define_hooked_variable("$>", &rb_defout, 0, io_defset); - rb_define_const(C_Object, "STDIN", rb_stdin); - rb_define_const(C_Object, "STDOUT", rb_stdout); - rb_define_const(C_Object, "STDERR", rb_stderr); + rb_define_const(cObject, "STDIN", rb_stdin); + rb_define_const(cObject, "STDOUT", rb_stdout); + rb_define_const(cObject, "STDERR", rb_stderr); - argf = obj_alloc(C_Object); - rb_extend_object(argf, M_Enumerable); + argf = obj_alloc(cObject); + rb_extend_object(argf, mEnumerable); - rb_define_variable("$<", &argf, Qnil, rb_readonly_hook, 0); - rb_define_variable("$ARGF", &argf, Qnil, rb_readonly_hook, 0); + rb_define_readonly_variable("$<", &argf); + rb_define_readonly_variable("$ARGF", &argf); - rb_define_single_method(argf, "each", Farg_each, 0); - rb_define_single_method(argf, "each_byte", Farg_each_byte, 0); + rb_define_singleton_method(argf, "each", arg_each_line, 0); + rb_define_singleton_method(argf, "each_line", arg_each_line, 0); + rb_define_singleton_method(argf, "each_byte", arg_each_byte, 0); - rb_define_single_method(argf, "read", Farg_read, 0); - rb_define_single_method(argf, "readlines", Freadlines, 0); - rb_define_single_method(argf, "gets", Fgets, 0); - rb_define_single_method(argf, "readline", Fgets, 0); - rb_define_single_method(argf, "getc", Farg_getc, 0); - rb_define_single_method(argf, "eof", Feof, 0); + rb_define_singleton_method(argf, "read", arg_read, 0); + rb_define_singleton_method(argf, "readlines", f_readlines, 0); + rb_define_singleton_method(argf, "gets", f_gets, 0); + rb_define_singleton_method(argf, "readline", f_gets, 0); + rb_define_singleton_method(argf, "getc", arg_getc, 0); + rb_define_singleton_method(argf, "eof", f_eof, 0); + rb_define_singleton_method(argf, "eof?", f_eof, 0); - rb_define_single_method(argf, "to_s", Farg_filename, 0); - rb_define_single_method(argf, "filename", Farg_filename, 0); - rb_define_single_method(argf, "file", Farg_file, 0); + rb_define_singleton_method(argf, "to_s", arg_filename, 0); + rb_define_singleton_method(argf, "filename", arg_filename, 0); + rb_define_singleton_method(argf, "file", arg_file, 0); filename = str_new2("-"); - rb_define_variable("$FILENAME", &filename, Qnil, rb_readonly_hook, 0); + rb_define_readonly_variable("$FILENAME", &filename); file = rb_stdin; rb_global_variable(&file); @@ -14,6 +14,7 @@ #ifndef IO_H #define IO_H +#include "sig.h" #include <stdio.h> #include <errno.h> @@ -24,6 +25,7 @@ typedef struct { int pid; /* child's pid (for pipes) */ int lineno; /* number of lines read */ char *path; /* pathname for file */ + void (*finalize)(); /* finalize proc */ } OpenFile; #define FMODE_READABLE 1 @@ -35,15 +37,16 @@ extern ID id_fd; #define GetOpenFile(obj,fp) Get_Data_Struct(obj, id_fd, OpenFile, fp) -void io_free_OpenFile(); +void io_fptr_finalize(); -#define MakeOpenFile(obj, fp) {\ - Make_Data_Struct(obj, id_fd, OpenFile, Qnil, io_free_OpenFile, fp);\ +#define MakeOpenFile(obj, fp) do {\ + Make_Data_Struct(obj, id_fd, OpenFile, 0, io_fptr_finalize, fp);\ fp->f = fp->f2 = NULL;\ fp->mode = 0;\ fp->pid = 0;\ fp->lineno = 0;\ fp->path = NULL;\ -} + fp->finalize = 0;\ +} while (0) #endif diff --git a/lib/base64.rb b/lib/base64.rb new file mode 100644 index 0000000000..a6bf1adf92 --- /dev/null +++ b/lib/base64.rb @@ -0,0 +1,55 @@ +def decode64(str) + e = -1; + c = "," + string='' + for line in str.split("\n") + line.sub!(/=+$/, '') + line.tr! 'A-Za-z0-9+/', "\000-\377" + line.each_byte { |ch| + n +=1 + e +=1 + if e==0 + c = ch << 2 + elsif e==1 + c |= ch >>4 + string += [c].pack('c') + c = ch << 4 + elsif e == 2 + c |= ch >> 2 + string += [c].pack('c'); + c = ch << 6 + elsif e==3 + c |= ch + string += [c].pack('c') + e = -1 + end + } + end + return string +end + +def j2e(str) + while str =~ /\033\$B([^\033]*)\033\(B/ + s = $1 + pre, post = $`, $' + s.gsub!(/./) { |ch| + (ch[0]|0x80).chr + } + str = pre + s + post + end +# str.gsub!(/\033\$B([^\033]*)\033\(B/) { +# $1.gsub!(/./) { |ch| +# (ch[0]|0x80).chr +# } +# } + str +end + +def decode_b(str) + str.gsub!(/=\?ISO-2022-JP\?B\?([!->@-~]+)\?=/) { + decode64($1) + } + str.gsub!(/\n/, ' ') + str.gsub!(/\0/, '') + j2e(str) +end diff --git a/lib/find.rb b/lib/find.rb new file mode 100644 index 0000000000..340461c653 --- /dev/null +++ b/lib/find.rb @@ -0,0 +1,38 @@ +# Usage: +# require "find.rb" +# +# Find.find('/foo','/bar') {|f| ...} +# or +# include Find +# find('/foo','/bar') {|f| ...} +# + +module Find + extend Find + + def findpath(path, ary) + ary.push(path) + d = Dir.open(path) + for f in d + continue if f =~ /^\.\.?$/ + f = path + "/" + f + if File.directory? f + findpath(f, ary) + else + ary.push(f) + end + end + end + private :findpath + + def find(*path) + ary = [] + for p in path + findpath(p, ary) + for f in ary + yield f + end + end + end + module_function :find +end diff --git a/sample/getopts.rb b/lib/getopts.rb index 37fd3dc69d..37fd3dc69d 100644 --- a/sample/getopts.rb +++ b/lib/getopts.rb diff --git a/lib/mailread.rb b/lib/mailread.rb new file mode 100644 index 0000000000..4b04445beb --- /dev/null +++ b/lib/mailread.rb @@ -0,0 +1,45 @@ +class Mail + + def Mail.new(f) + if !f.is_kind_of?(IO) + f = open(f, "r") + me = super + f.close + else + me = super + end + return me + end + + def initialize(f) + @header = {} + @body = [] + while f.gets() + $_.chop! + continue if /^From / # skip From-line + break if /^$/ # end of header + if /^(\S+):\s*(.*)/ + @header[attr = $1.capitalize] = $2 + elsif attr + sub(/^\s*/, '') + @header[attr] += "\n" + $_ + end + end + + return if ! $_ + + while f.gets() + break if /^From / + @body.push($_) + end + end + + def header + return @header + end + + def body + return @body + end + +end diff --git a/sample/parsearg.rb b/lib/parsearg.rb index e7e2b7a7f3..e7e2b7a7f3 100644 --- a/sample/parsearg.rb +++ b/lib/parsearg.rb diff --git a/lib/parsedate.rb b/lib/parsedate.rb new file mode 100644 index 0000000000..3f4612ebe5 --- /dev/null +++ b/lib/parsedate.rb @@ -0,0 +1,42 @@ +module ParseDate + MONTHS = { + 'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4, + 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8, + 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12 } + MONTHPAT = MONTHS.keys.join('|') + DAYPAT = 'mon|tue|wed|thu|fri|sat|sun' + + def parsedate(date) + if date.sub!(/(#{DAYPAT})/i, ' ') + dayofweek = $1 + end + if date.sub!(/\s+(\d+:\d+(:\d+)?)/, ' ') + time = $1 + end + if date =~ /19(\d\d)/ + year = $1 + end + if date.sub!(/\s*(\d+)\s+(#{MONTHPAT})\S*\s+/i, ' ') + dayofmonth = $1 + monthname = $2 + elsif date.sub!(/\s*(#{MONTHPAT})\S*\s+(\d+)\s+/i, ' ') + monthname = $1 + dayofmonth = $2 + elsif date.sub!(/\s*(#{MONTHPAT})\S*\s+(\d+)\D+/i, ' ') + monthname = $1 + dayofmonth = $2 + elsif date.sub!(/\s*(\d\d?)\/(\d\d?)/, ' ') + month = $1 + dayofmonth = $2 + end + if monthname + month = MONTHS[monthname.downcase] + end + if ! year && date =~ /\d\d/ + year = $& + end + return year, month, dayofmonth + end + + module_function :parsedate +end diff --git a/lib/tk.rb b/lib/tk.rb new file mode 100644 index 0000000000..9c61269881 --- /dev/null +++ b/lib/tk.rb @@ -0,0 +1,1215 @@ +# +# tk.rb - Tk interface for ruby +# $Date: 1995/11/03 08:17:15 $ +# by Yukihiro Matsumoto <matz@caelum.co.jp> + +require "tkutil" + +trap "PIPE", proc{exit 0} +trap "EXIT", proc{Tk.tk_exit} + +module Tk + include TkUtil + extend Tk + + $0 =~ /\/(.*$)/ + + PORT = open(format("|%s -n %s", WISH_PATH, $1), "w+"); + def tk_write(*args) + printf PORT, *args; + PORT.print "\n" + PORT.flush + end + tk_write '\ +wm withdraw . +proc rb_out args { + puts [format %%s $args] + flush stdout +} +proc tkerror args { exit } +proc keepalive {} { rb_out alive; after 120000 keepalive} +after 120000 keepalive' + + READABLE = [] + READ_CMD = {} + + def file_readable(port, cmd) + READABLE.push port + READ_CMD[port] = cmd + end + + WRITABLE = [] + WRITE_CMD = {} + def file_writable + WRITABLE.push port + WRITE_CMD[port] = cmd + end + module_function :file_readable, :file_writable + + file_readable PORT, proc { + exit if not PORT.gets + Tk.dispatch($_.chop!) + } + + def tk_exit + PORT.print "exit\n" + PORT.close + end + + def error_at + n = 1 + while c = caller(n) + break if c !~ /tk\.rb:/ + n+=1 + end + c + end + + def tk_tcl2ruby(val) + case val + when /^-?\d+$/ + val.to_i + when /^\./ + $tk_window_list[val] + when /^rb_out (c\d+)/ + $tk_cmdtbl[$1] + when / / + val.split.collect{|elt| + tk_tcl2ruby(elt) + } + when /^-?\d+\.\d*$/ + val.to_f + else + val + end + end + + def tk_split_list(str) + idx = str.index('{') + return tk_tcl2ruby(str) if not idx + + list = tk_tcl2ruby(str[0,idx]) + str = str[idx+1..-1] + i = -1 + brace = 1 + str.each_byte {|c| + i += 1 + brace += 1 if c == ?{ + brace -= 1 if c == ?} + break if brace == 0 + } + if str[0, i] == ' ' + list.push ' ' + else + list.push tk_split_list(str[0, i]) + end + list += tk_split_list(str[i+1..-1]) + list + end + private :tk_tcl2ruby, :tk_split_list + + def bool(val) + case bool + when "1", 1, 'yes', 'true' + TRUE + else + FALSE + end + end + def number(val) + case val + when /^-?\d+$/ + val.to_i + when /^-?\d+\.\d*$/ + val.to_f + else + val + end + end + def string(val) + if val == "{}" + '' + elsif val[0] == ?{ + val[1..-2] + else + val + end + end + def list(val) + tk_split_list(val) + end + def window(val) + $tk_window_list[val] + end + def procedure(val) + if val =~ /^rb_out (c\d+)/ + $tk_cmdtbl[$1] + else + nil + end + end + private :bool, :number, :string, :list, :window, :procedure + + # mark for non-given arguments + None = Object.new + def None.to_s + 'None' + end + + $tk_event_queue = [] + def tk_call(*args) + args = args.collect{|s| + continue if s == None + if s == FALSE + s = "0" + elsif s == TRUE + s = "1" + elsif s.is_kind_of?(TkObject) + s = s.path + else + s = s.to_s + s.gsub!(/[{}]/, '\\\\\0') + end + "{#{s}}" + } + str = args.join(" ") + tk_write 'if [catch {%s} var] {puts "!$var"} {puts "=$var@@"};flush stdout', str + while PORT.gets + $_.chop! + if /^=(.*)@@$/ + val = $1 + break + elsif /^=/ + val = $' + "\n" + while TRUE + PORT.gets + fail 'wish closed' if not $_ + if ~/@@$/ + val += $' + return val + else + val += $_ + end + end + elsif /^!/ + $@ = error_at + msg = $' + if msg =~ /unknown option "-(.*)"/ + fail format("undefined method `%s' for %s(%s)'", $1, self, self.type) + else + fail format("%s - %s", self.type, msg) + end + end + $tk_event_queue.push $_ + end + + while ev = $tk_event_queue.shift + Tk.dispatch ev + end + fail 'wish closed' if not $_ +# tk_split_list(val) + val + end + + def hash_kv(keys) + conf = [] + if keys + for k, v in keys + conf.push("-#{k}") + v = install_cmd(v) if v.type == Proc + conf.push(v) + end + end + conf + end + private :tk_call, :error_at, :hash_kv + + $tk_cmdid = "c00000" + def install_cmd(cmd) + return '' if cmd == '' # uninstall cmd + id = $tk_cmdid + $tk_cmdid = $tk_cmdid.next + $tk_cmdtbl[id] = cmd + @cmdtbl = [] if not @cmdtbl + @cmdtbl.push id + return format('rb_out %s', id) + end + def uninstall_cmd(id) + $tk_cmdtbl[id] = nil + end + private :install_cmd, :uninstall_cmd + + $tk_window_list = {} + class Event + def initialize(seq,b,f,h,k,s,t,w,x,y,aa,ee,kk,nn,ww,tt,xx,yy) + @serial = seq + @num = b + @focus = (f == 1) + @height = h + @keycode = k + @state = s + @time = t + @width = w + @x = x + @y = y + @char = aa + @send_event = (ee == 1) + @keysym = kk + @keysym_num = nn + @type = tt + @widget = ww + @x_root = xx + @y_root = yy + end + attr :serial + attr :num + attr :focus + attr :height + attr :keycode + attr :state + attr :time + attr :width + attr :x + attr :y + attr :char + attr :send_event + attr :keysym + attr :keysym_num + attr :type + attr :widget + attr :x_root + attr :y_root + end + + def install_bind(cmd) + id = install_cmd(proc{|args| + TkUtil.eval_cmd cmd, Event.new(*args) + }) + id + " %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y" + end + + def _bind(path, context, cmd) + begin + id = install_bind(cmd) + tk_call 'bind', path, "<#{context}>", id + rescue + $tk_cmdtbl[id] = nil + fail + end + end + private :install_bind, :_bind + + def bind_all(context, cmd=Proc.new) + _bind 'all', context, cmd + end + + $tk_cmdtbl = {} + + def after(ms, cmd=Proc.new) + myid = $tk_cmdid + tk_call 'after', ms, + install_cmd(proc{ + TkUtil.eval_cmd cmd + uninstall_cmd myid + }) + end + + def update(idle=nil) + if idle + tk_call 'update', 'idletasks' + else + tk_call 'update' + end + end + + def dispatch(line) + if line =~ /^c\d+/ + cmd = $& + fail "no command `#{cmd}'" if not $tk_cmdtbl[cmd] + args = tk_split_list($') + TkUtil.eval_cmd $tk_cmdtbl[cmd], *args + elsif line =~ /^alive$/ + # keep alive, do nothing + else + fail "malformed line <#{line}>" + end + end + + def mainloop + begin + tk_write 'after idle {wm deiconify .}' + while TRUE + rf, wf = select(READABLE, WRITABLE) + for f in rf + READ_CMD[f].call(f) if READ_CMD[f] + if f.closed? + READABLE.delete f + READ_CMD[f] = nil + end + end + for f in wf + WRITE_CMD[f].call(f) if WRITE_CMD[f] + if f.closed? + WRITABLE.delete f + WRITE_CMD[f] = nil + end + end + end + rescue + exit if $! =~ /^Interrupt/ + fail + ensure + tk_exit + end + end + + def root + $tk_root + end + + module_function :after, :update, :dispatch, :mainloop, :root + + module Scrollable + def xscrollcommand(cmd) + configure_cmd 'xscrollcommand', cmd + end + def yscrollcommand(cmd) + configure_cmd 'yscrollcommand', cmd + end + end + + module Wm + def aspect(*args) + w = window(tk_call('wm', 'grid', path, *args)) + w.split.collect{|s|s.to_i} if args.length == 0 + end + def client(name=None) + tk_call 'wm', 'client', path, name + end + def colormapwindows(*args) + list(tk_call('wm', 'colormapwindows', path, *args)) + end + def wm_command(value=None) + string(tk_call('wm', 'command', path, value)) + end + def deiconify + tk_call 'wm', 'deiconify', path + end + def focusmodel(*args) + tk_call 'wm', 'focusmodel', path, *args + end + def frame + tk_call 'wm', 'frame', path + end + def geometry(*args) + list(tk_call('wm', 'geometry', path, *args)) + end + def grid(*args) + w = tk_call('wm', 'grid', path, *args) + list(w) if args.size == 0 + end + def group(*args) + tk_call 'wm', 'path', path, *args + end + def iconbitmap(*args) + tk_call 'wm', 'bitmap', path, *args + end + def iconify + tk_call 'wm', 'iconify' + end + def iconmask(*args) + tk_call 'wm', 'iconmask', path, *args + end + def iconname(*args) + tk_call 'wm', 'iconname', path, *args + end + def iconposition(*args) + w = tk_call('wm', 'iconposition', path, *args) + list(w) if args.size == 0 + end + def iconwindow(*args) + tk_call 'wm', 'iconwindow', path, *args + end + def maxsize(*args) + w = tk_call('wm', 'maxsize', path, *args) + list(w) if not args.size == 0 + end + def minsize(*args) + w = tk_call('wm', 'minsize', path, *args) + list(w) if args.size == 0 + end + def overrideredirect(bool=None) + if bool == None + bool(tk_call('wm', 'overrideredirect', path)) + else + tk_call 'wm', 'overrideredirect', path, bool + end + end + def positionfrom(*args) + tk_call 'wm', 'positionfrom', path, *args + end + def protocol(name, func=None) + func = install_cmd(func) if not func == None + tk_call 'wm', 'command', path, name, func + end + def resizable(*args) + w = tk_call('wm', 'resizable', path, *args) + if args.length == 0 + list(w).collect{|e| bool(e)} + end + end + def sizefrom(*args) + list(tk_call('wm', 'sizefrom', path, *args)) + end + def state + tk_call 'wm', 'state', path + end + def title(*args) + tk_call 'wm', 'title', path, *args + end + def transient(*args) + tk_call 'wm', 'transient', path, *args + end + def withdraw + tk_call 'wm', 'withdraw', path + end + end +end + +module TkSelection + include Tk + extend Tk + def clear(win=Tk.root) + tk_call 'selection', 'clear', win.path + end + def get(type=None) + tk_call 'selection', 'get', type + end + def TkSelection.handle(win, func, type=None, format=None) + id = install_cmd(func) + tk_call 'selection', 'handle', win.path, id, type, format + end + def handle(func, type=None, format=None) + TkSelection.handle self, func, type, format + end + def TkSelection.own(win, func=None) + id = install_cmd(func) + tk_call 'selection', 'own', win.path, id + end + def own(func=None) + TkSelection.own self, func + end + + module_function :clear, :get +end + +module TkWinfo + include Tk + extend Tk + def TkWinfo.atom(name) + tk_call 'winfo', name + end + def winfo_atom(name) + TkWinfo.atom name + end + def TkWinfo.atomname(id) + tk_call 'winfo', id + end + def winfo_atomname(id) + TkWinfo.atomname id + end + def TkWinfo.cells(window) + number(tk_call('winfo', window.path)) + end + def winfo_cells + TkWinfo.cells self + end + def TkWinfo.children(window) + c = tk_call('winfo', 'children', window.path) + list(c) + end + def winfo_children + TkWinfo.children self + end + def TkWinfo.classname(window) + tk_call 'winfo', 'class', window.path + end + def winfo_classname + TkWinfo.classname self + end + def TkWinfo.containing(rootX, rootY) + path = tk_call('winfo', 'class', window.path) + window(path) + end + def winfo_containing(x, y) + TkWinfo.containing x, y + end + def TkWinfo.depth(window) + number(tk_call('winfo', 'depth', window.path)) + end + def winfo_depth(window) + TkWinfo.depth self + end + def TkWinfo.exists(window) + bool(tk_call('winfo', 'exists', window.path)) + end + def winfo_exists(window) + TkWinfo.exists self + end + def TkWinfo.fpixels(window, number) + number(tk_call('winfo', 'fpixels', window.path, number)) + end + def winfo_fpixels(window, number) + TkWinfo.fpixels self + end + def TkWinfo.geometry(window) + list(tk_call('winfo', 'geometry', window.path)) + end + def winfo_geometry(window) + TkWinfo.geometry self + end + def TkWinfo.height(window) + number(tk_call('winfo', 'height', window.path)) + end + def winfo_height(window) + TkWinfo.height self + end + def TkWinfo.id(window) + number(tk_call('winfo', 'id', window.path)) + end + def winfo_id(window) + TkWinfo.id self + end + def TkWinfo.ismapped(window) + bool(tk_call('winfo', 'ismapped', window.path)) + end + def winfo_ismapped(window) + TkWinfo.ismapped self + end + def TkWinfo.parent(window) + window(tk_call('winfo', 'parent', window.path)) + end + def winfo_parent(window) + TkWinfo.parent self + end + def TkWinfo.widget(id) + window(tk_call('winfo', 'pathname', id)) + end + def winfo_widget(id) + TkWinfo.widget id + end + def TkWinfo.pixels(window, number) + number(tk_call('winfo', 'pixels', window.path, number)) + end + def winfo_pixels(window, number) + TkWinfo.pixels self, number + end + def TkWinfo.reqheight(window) + number(tk_call('winfo', 'reqheight', window.path)) + end + def winfo_reqheight(window) + TkWinfo.reqheight self + end + def TkWinfo.reqwidth(window) + number(tk_call('winfo', 'reqwidth', window.path)) + end + def winfo_reqwidth(window) + TkWinfo.reqwidth self + end + def TkWinfo.rgb(window, color) + list(tk_call('winfo', 'rgb', window.path, color)) + end + def winfo_rgb(window, color) + TkWinfo.rgb self, color + end + def TkWinfo.rootx(window) + number(tk_call('winfo', 'rootx', window.path)) + end + def winfo_rootx(window) + TkWinfo.rootx self + end + def TkWinfo.rooty(window) + number(tk_call('winfo', 'rooty', window.path)) + end + def winfo_rooty(window) + TkWinfo.rooty self + end + def TkWinfo.screen(window) + tk_call 'winfo', 'screen', window.path + end + def winfo_screen(window) + TkWinfo.screen self + end + def TkWinfo.screencells(window) + number(tk_call('winfo', 'screencells', window.path)) + end + def winfo_screencells(window) + TkWinfo.screencells self + end + def TkWinfo.screendepth(window) + number(tk_call('winfo', 'screendepth', window.path)) + end + def winfo_screendepth(window) + TkWinfo.screendepth self + end + def TkWinfo.screenheight (window) + number(tk_call('winfo', 'screenheight', window.path)) + end + def winfo_screenheight(window) + TkWinfo.screenheight self + end + def TkWinfo.screenmmheight(window) + number(tk_call('winfo', 'screenmmheight', window.path)) + end + def winfo_screenmmheight(window) + TkWinfo.screenmmheight self + end + def TkWinfo.screenmmwidth(window) + number(tk_call('winfo', 'screenmmwidth', window.path)) + end + def winfo_screenmmwidth(window) + TkWinfo.screenmmwidth self + end + def TkWinfo.screenvisual(window) + tk_call 'winfo', 'screenvisual', window.path + end + def winfo_screenvisual(window) + TkWinfo.screenvisual self + end + def TkWinfo.screenwidth(window) + number(tk_call('winfo', 'screenwidth', window.path)) + end + def winfo_screenwidth(window) + TkWinfo.screenwidth self + end + def TkWinfo.toplevel(window) + window(tk_call('winfo', 'toplevel', window.path)) + end + def winfo_toplevel(window) + TkWinfo.toplevel self + end + def TkWinfo.visual(window) + tk_call 'winfo', 'visual', window.path + end + def winfo_visual(window) + TkWinfo.visual self + end + def TkWinfo.vrootheigh(window) + number(tk_call('winfo', 'vrootheight', window.path)) + end + def winfo_vrootheight(window) + TkWinfo.vrootheight self + end + def TkWinfo.vrootwidth(window) + number(tk_call('winfo', 'vrootwidth', window.path)) + end + def winfo_vrootwidth(window) + TkWinfo.vrootwidth self + end + def TkWinfo.vrootx(window) + number(tk_call('winfo', 'vrootx', window.path)) + end + def winfo_vrootx(window) + TkWinfo.vrootx self + end + def TkWinfo.vrooty(window) + number(tk_call('winfo', 'vrooty', window.path)) + end + def winfo_vrooty(window) + TkWinfo.vrooty self + end + def TkWinfo.width(window) + number(tk_call('winfo', 'width', window.path)) + end + def winfo_width(window) + TkWinfo.width self + end + def TkWinfo.x(window) + number(tk_call('winfo', 'x', window.path)) + end + def winfo_x(window) + TkWinfo.x self + end + def TkWinfo.y(window) + number(tk_call('winfo', 'y', window.path)) + end + def winfo_y(window) + TkWinfo.y self + end +end + +module TkPack + include Tk + extend Tk + def configure(win, *args) + if args[-1].is_kind_of(Hash) + keys = args.pop + end + wins = [win.epath] + for i in args + wins.push i.epath + end + tk_call "pack", 'configure', *(wins+hash_kv(keys)) + end + + def forget(*args) + tk_call 'pack', 'forget' *args + end + + def propagate(master, bool=None) + bool(tk_call('pack', 'propagate', mastaer.epath, bool)) + end + module_function :configure, :forget, :propagate +end + +module TkOption + include Tk + extend Tk + def add pat, value, pri=None + tk_call 'option', 'add', pat, value, pri + end + def clear + tk_call 'option', 'clear' + end + def get win, classname, name + tk_call 'option', 'get', classname, name + end + def readfile file, pri=None + tk_call 'option', 'readfile', file, pri + end + module_function :add, :clear, :get, :readfile +end + +class TkObject:TkKernel + include Tk + + def path + return @path + end + + def epath + return @path + end + + def tk_send(cmd, *rest) + tk_call path, cmd, *rest + end + private :tk_send + + def method_missing(id, *args) + if (args.length == 1) + configure id.id2name, args[0] + else + $@ = error_at + super + end + end + + def []=(id, val) + configure id, val + end + + def configure(slot, value) + if value == FALSE + value = "0" + elsif value.type == Proc + value = install_cmd(value) + end + tk_call path, 'configure', "-#{slot}", value + end + + def configure_cmd(slot, value) + configure slot, install_cmd(value) + end + + def bind(context, cmd=Proc.new) + _bind path, context, cmd + end +end + +class TkWindow:TkObject + $tk_window_id = "w00000" + def initialize(parent=nil, keys=nil) + id = $tk_window_id + $tk_window_id = $tk_window_id.next + if !parent or parent == Tk.root + @path = format(".%s", id); + else + @path = format("%s.%s", parent.path, id) + end + $tk_window_list[@path] = self + create_self + if keys + tk_call @path, 'configure', *hash_kv(keys) + end + end + + def create_self + end + private :create_self + + def pack(keys = nil) + tk_call 'pack', epath, *hash_kv(keys) + self + end + + def unpack(keys = nil) + tk_call 'pack', 'forget', epath + self + end + + def focus + tk_call 'focus', path + self + end + + def grab(*args) + if !args or args.length == 0 + tk_call 'grab', 'set', path + elsif args.length == 1 + case args[0] + when 'global' + tk_call 'grab', 'set', '-global', path + else + val = tk_call('grab', arg[0], path) + end + case args[0] + when 'current' + return window(val) + when 'status' + return val + end + else + fail 'wrong # of args' + end + end + + def lower(below=None) + tk_call 'lower', path, below + self + end + def raise(above=None) + tk_call 'raise', path, above + self + end + + def command(cmd) + configure_cmd 'command', cmd + end + + def colormodel model=None + tk_call 'tk', 'colormodel', path, model + self + end + + def destroy + tk_call 'destroy', path + if @cmdtbl + for id in @cmdtbl + uninstall_cmd id + end + end + $tk_window_list[path] = nil + end +end + +class TkRoot:TkWindow + include Wm + def TkRoot.new + return $tk_root if $tk_root + super + end + def path + "." + end + $tk_root = TkRoot.new + $tk_window_list['.'] = $tk_root +end + +class TkToplevel:TkWindow + include Wm + def initialize(parent=nil, screen=nil, classname=nil) + @screen = screen if screen + @classname = classname if classname + super + end + + def create_self + s = [] + s.push "-screen #@screen" if @screen + s.push "-class #@classname" if @classname + tk_call 'toplevel', path, *s + end +end + +class TkFrame:TkWindow + def create_self + tk_call 'frame', @path + end +end + +class TkLabel:TkWindow + def create_self + tk_call 'label', @path + end + def textvariable(v) + vn = @path + v.id2name + vset = format("global {%s}; set {%s}", vn, vn) + tk_call vset, eval(v.id2name).inspect + trace_var v, proc{|val| + tk_call vset, val.inspect + } + configure 'textvariable', vn + end +end + +class TkButton:TkLabel + def create_self + tk_call 'button', @path + end + def invoke + tk_send 'invoke' + end + def flash + tk_send 'flash' + end +end + +class TkRadioButton:TkButton + def create_self + tk_call 'radiobutton', @path + end + def deselect + tk_send 'deselect' + end + def select + tk_send 'select' + end + def variable(v) + vn = v.id2name; vn =~ /^./ + vn = 'btns_selected_' + $' + trace_var v, proc{|val| + tk_call 'set', vn, val + } + @var_id = install_cmd(proc{|name1,| + val = tk_call('set', name1) + eval(format("%s = '%s'", v.id2name, val)) + }) + tk_call 'trace variable', vn, 'w', @var_id + configure 'variable', vn + end + def destroy + tk_call 'trace vdelete', vn, 'w', @var_id + super + end +end + +class TkCheckButton:TkRadioButton + def create_self + tk_call 'checkbutton', @path + end + def toggle + tk_send 'toggle' + end +end + +class TkMessage:TkLabel + def create_self + tk_call 'message', @path + end +end + +class TkScale:TkWindow + def create_self + tk_call 'scale', path + end + + def get + number(tk_send('get')) + end + + def set(val) + tk_send "set", val + end + + def value + get + end + + def value= (val) + set val + end +end + +class TkScrollbar:TkWindow + def create_self + tk_call 'scrollbar', path + end + + def get + ary1 = tk_send('get', path).split + ary2 = [] + for i in ary1 + push number(i) + end + ary2 + end + + def set(first, last) + tk_send "set", first, last + end +end + +# abstract class for Text and Listbox +class TkTextWin:TkWindow + def bbox(index) + tk_send 'bbox', index + end + def delete(first, last=None) + tk_send 'delete', first, last + end + def get(*index) + tk_send 'get', *index + end + def insert(index, *rest) + tk_send 'insert', index, *rest + end + def index(index) + tk_send 'index', index + end + def insert(index, chars, *args) + tk_send 'insert', index, chars, *args + end + def scan_mark(x, y) + tk_send 'scan', 'mark', x, y + end + def scan_dragto(x, y) + tk_send 'scan', 'dragto', x, y + end + def see(index) + tk_send 'see', index + end +end + +class TkListbox:TkTextWin + def create_self + tk_call 'listbox', path + end + + def nearest(y) + tk_send 'nearest', y + end + def selection_anchor(index) + tk_send 'selection', 'anchor', index + end + def selection_clear(first, last=None) + tk_send 'selection', 'clear', first, last + end + def selection_includes + bool(tk_send('selection', 'includes')) + end + def selection_set(first, last=None) + tk_send 'selection', 'set', first, last + end + def xview(cmd, index, *more) + tk_send 'xview', cmd, index, *more + end + def yview(cmd, index, *more) + tk_send 'yview', cmd, index, *more + end +end + +class TkMenu:TkWindow + def create_self + tk_call 'menu', path + end + def activate(index) + tk_send 'activate', index + end + def add(type, keys=nil) + tk_send 'add', type, *kv_hash(keys) + end + def index(index) + tk_send 'index', index + end + def invoke + tk_send 'invoke' + end + def insert(index, type, keys=nil) + tk_send 'add', index, type, *kv_hash(keys) + end + def post(x, y) + tk_send 'post', x, y + end + def postcascade(index) + tk_send 'postcascade', index + end + def postcommand(cmd) + configure_cmd 'postcommand', cmd + end + def menutype(index) + tk_send 'type', index + end + def unpost + tk_send 'unpost' + end + def yposition(index) + number(tk_send('yposition', index)) + end +end + +class TkMenubutton:TkLabel + def create_self + tk_call 'menubutton', path + end +end + +module TkComposite + def initialize(parent=nil, *args) + @frame = TkFrame.new(parent) + @path = @epath = @frame.path + initialize_composite(*args) + end + + def epath + @epath + end + + def initialize_composite(*args) end + private :initialize_composite + + def delegate(option, *wins) + @delegates = {} if not @delegates + @delegates['DEFAULT'] = @frame + if option.is_kind_of? String + @delegates[option] = wins + else + for i in option + @delegates[i] = wins + end + end + end + + def configure(slot, value) + if @delegates and @delegates[slot] + for i in @delegates[slot] + if not i + i = @delegates['DEFALUT'] + redo + else + last = i.configure(slot, value) + end + end + last + else + super + end + end +end + +autoload :TkCanvas, 'tkcanvas' +autoload :TkImage, 'tkcanvas' +autoload :TkBitmapImage, 'tkcanvas' +autoload :TkPhotoImage, 'tkcanvas' +autoload :TkEntry, 'tkentry' +autoload :TkText, 'tktext' diff --git a/lib/tkcanvas.rb b/lib/tkcanvas.rb new file mode 100644 index 0000000000..33b28e3eff --- /dev/null +++ b/lib/tkcanvas.rb @@ -0,0 +1,318 @@ +# +# tkcanvas.rb - Tk canvas classes +# $Date: 1995/11/11 11:17:15 $ +# by Yukihiro Matsumoto <matz@caelum.co.jp> + +require "tk" + +class TkCanvas:TkWindow + def create_self + tk_call 'canvas', path + end + def tagid(tag) + if tag.is_kind_of?(TkcItem) + tag.id + else + tag + end + end + private :tagid + def addtag(tag, *args) + tk_send 'addtag', tagid(tag), *args + end + def addtag_above(tagOrId) + addtag('above', tagOrId) + end + def addtag_all + addtag('all') + end + def addtag_below(tagOrId) + addtag('below', tagOrId) + end + def addtag_closest(x, y, halo=None, start=None) + addtag('closest', x, y, halo, start) + end + def addtag_enclosed(x1, y1, x2, y2) + addtag('enclosed', x1, y1, x2, y2) + end + def addtag_overlapping(x1, y1, x2, y2) + addtag('overlapping', x1, y1, x2, y2) + end + def addtag_withtag(tagOrId) + addtag('withtag', tagOrId) + end + def bbox(tag) + list(tk_send('bbox', tagid(tag))) + end + def itembind(tag, seq, cmd=Proc.new) + id = install_cmd(cmd) + tk_send 'bind', tagid(tag), "<#{seq}>", id + @cmdtbl.push id + end + def canvasx(x, *args) + tk_send 'canvasx', x, *args + end + def canvasy(y, *args) + tk_send 'canvasy', y, *args + end + def coords(tag, *args) + tk_send 'coords', tagid(tag), *args + end + def dchars(tag, first, last=None) + tk_send 'dchars', tagid(tag), first, last + end + def delete(*args) + tk_send 'delete', *args + end + alias remove delete + def dtag(tag, tag_to_del=None) + tk_send 'dtag', tagid(tag), tag_to_del + end + def find(*args) + tk_send 'find', *args + end + def itemfocus(tag) + tk_send 'find', tagid(tag) + end + def gettags(tag) + tk_send 'gettags', tagid(tag) + end + def icursor(tag, index) + tk_send 'icursor', tagid(tag), index + end + def index(tag) + tk_send 'index', tagid(tag), index + end + def lower(tag, below=None) + tk_send 'lower', tagid(tag), below + end + def move(tag, x, y) + tk_send 'move', tagid(tag), x, y + end + def postscript(keys=None) + tk_call "pack", *hash_kv(keys) + end + def raise(tag, above=None) + tk_send 'raise', tagid(tag), above + end + def scale(tag, x, y, xs, ys) + tk_send 'scale', tagid(tag), x, y, xs, ys + end + def scan_mark(x, y) + tk_send 'scan', 'mark', x, y + end + def scan_dragto(x, y) + tk_send 'scan', 'dragto', x, y + end + def select(*args) + tk_send 'select', *args + end + def xview(index) + tk_send 'xview', index + end + def yview(index) + tk_send 'yview', index + end +end + +class TkcItem:TkObject + def initialize(parent, *args) + if not parent.is_kind_of?(TkCanvas) + fail format("%s need to be TkCanvas", parent.inspect) + end + @c = parent + @path = parent.path + if args[-1].type == Hash + keys = args.pop + end + @id = create_self(*args) + if keys + tk_call @path, 'itemconfigure', *hash_kv(keys) + end + end + def create_self(*args) end + private :create_self + def id + return @id + end + + def configure(slot, value) + tk_call path, 'itemconfigure', id, "-#{slot}", value + end + + def addtag(tag) + @c.addtag(tag, 'withtag', @id) + end + def bbox + @c.bbox(@id) + end + def bind(seq, cmd=Proc.new) + @c.itembind @id, seq, cmd + end + def coords(*args) + @c.coords @id, *args + end + def dchars(first, last=None) + @c.dchars @id, first, last + end + def dtag(ttd) + @c.dtag @id, ttd + end + def focus + @c.focus @id + end + def gettags + @c.gettags @id + end + def icursor + @c.icursor @id + end + def index + @c.index @id + end + def insert(beforethis, string) + @c.insert @id, beforethis, string + end + def lower(belowthis=None) + @c.lower @id, belowthis + end + def move(xamount, yamount) + @c.move @id, xamount, yamount + end + def raise(abovethis=None) + @c.raise @id, abovethis + end + def scale(xorigin, yorigin, xscale, yscale) + @c.scale @id, xorigin, yorigin, xscale, yscale + end + def type + @c.type @id + end + def destroy + tk_call path, 'delete', @id + end +end + +class TkcArc:TkcItem + def create_self(*args) + tk_call(@path, 'create', 'arc', *args) + end +end +class TkcBitmap:TkcItem + def create_self(*args) + tk_call(@path, 'create', 'bitmap', *args) + end +end +class TkcImage:TkcItem + def create_self(*args) + tk_call(@path, 'create', 'image', *args) + end +end +class TkcLine:TkcItem + def create_self(*args) + tk_call(@path, 'create', 'line', *args) + end +end +class TkcOval:TkcItem + def create_self(*args) + tk_call(@path, 'create', 'oval', *args) + end +end +class TkcPolygon:TkcItem + def create_self(*args) + tk_call(@path, 'create', 'polygon', *args) + end +end +class TkcText:TkcItem + def create_self(*args) + tk_call(@path, 'create', 'text', *args) + end +end +class TkcWindow:TkcItem + def create_self(*args) + tk_call(@path, 'create', 'window', *args) + end +end +class TkcGroup:TkcItem + $tk_group_id = 'tkg00000' + def create_self(*args) + @id = $tk_group_id + $tk_group_id = $tk_group_id.next + end + + def add(*tags) + for i in tags + i.addtag @id + end + end + def add(*tags) + for i in tags + i.addtag @id + end + end + def delete(*tags) + for i in tags + i.delete @id + end + end + def list + @c.find 'withtag', @id + end + alias remove delete +end + + +class TkImage:TkObject + include Tk + + $tk_image_id = 'i00000' + def initialize(keys=nil) + @path = $tk_image_id + $tk_image_id = $tk_image_id.next + tk_call 'image', @type, @path, *hash_kv(keys) + end + + def height + number(tk_call('image', 'height', @path)) + end + def type + tk_call('image', 'type', @path) + end + def width + number(tk_call('image', 'height', @path)) + end + + def TkImage.names + tk_call('image', 'names', @path).split + end + def TkImage.types + tk_call('image', 'types', @path).split + end +end + +class TkBitmapImage:TkImage + def initialize(*args) + @type = 'bitmap' + super + end +end + +class TkPhotoImage:TkImage + def initialize(*args) + @type = 'bitmap' + super + end + + def blank + tk_send 'blank' + end + def cget + tk_send 'cget' + end + def get(x, y) + tk_send 'get', x, y + end + def put(data, to=None) + tk_send 'put', data, to + end +end diff --git a/lib/tkclass.rb b/lib/tkclass.rb new file mode 100644 index 0000000000..10ecc80b20 --- /dev/null +++ b/lib/tkclass.rb @@ -0,0 +1,36 @@ +# +# tkclass.rb - Tk classes +# $Date: 1995/11/11 19:17:15 $ +# by Yukihiro Matsumoto <matz@caelum.co.jp> + +require "tk" + +TopLevel = TkToplevel +Frame = TkFrame +Label = TkLabel +Button = TkButton +Radiobutton = TkRadioButton +Checkbutton = TkCheckButton +Message = TkMessage +Entry = TkEntry +Text = TkText +Scale = TkScale +Scrollbar = TkScrollbar +Listbox = TkListbox +Menu = TkMenu +Menubutton = TkMenubutton +Canvas = TkCanvas +Arc = TkcArc +Bitmap = TkcBitmap +Line = TkcLine +Oval = TkcOval +Polygon = TkcPolygon +TextItem = TkcText +WindowItem = TkcWindow +Selection = TkSelection +Winfo = TkWinfo +Pack = TkPack + +def Mainloop + Tk.mainloop +end diff --git a/lib/tkentry.rb b/lib/tkentry.rb new file mode 100644 index 0000000000..dbd848d0ca --- /dev/null +++ b/lib/tkentry.rb @@ -0,0 +1,74 @@ +# +# tkentry.rb - Tk entry classes +# $Date: 1995/12/07 15:01:10 $ +# by Yukihiro Matsumoto <matz@caelum.co.jp> + +require 'tk.rb' + +class TkEntry:TkLabel + def create_self + tk_call 'entry', @path + end + def scrollcommand(cmd) + configure 'scrollcommand', cmd + end + + def delete(s, e=None) + if e + tk_send 'delete', s + else + tk_send 'delete', s, e + end + end + + def cursor + tk_send 'index', 'insert' + end + def cursor=(index) + tk_send 'icursor', index + end + def index(index) + tk_send 'index', index + end + def insert(text, pos=None) + if pos + tk_send 'icursor', pos + end + tk_send 'insert', 'insert', text + end + def mark(pos) + tk_send 'scan', 'mark', pos + end + def dragto(pos) + tk_send 'scan', 'dragto', pos + end + def select_adjust(index) + tk_send 'select', 'adjust', index + end + def select_clear + tk_send 'select', 'clear', 'end' + end + def select_from(index) + tk_send 'select', 'from', index + end + def select_present() + tk_send('select', 'present') == 1 + end + def select_range(s, e) + tk_send 'select', 'range', s, e + end + def select_to(index) + tk_send 'select', 'to', index + end + def xview(*index) + tk_send 'xview', *index + end + + def value + tk_send 'get' + end + def value= (val) + tk_send 'delete', 0, 'end' + tk_send 'insert', 0, val + end +end diff --git a/lib/tktext.rb b/lib/tktext.rb new file mode 100644 index 0000000000..e7a2be950f --- /dev/null +++ b/lib/tktext.rb @@ -0,0 +1,160 @@ +# +# tktext.rb - Tk text classes +# $Date: 1995/12/07 08:37:10 $ +# by Yukihiro Matsumoto <matz@caelum.co.jp> + +require 'tk.rb' + +class TkText:TkTextWin + include Scrollable + def create_self + tk_call 'text', @path + @tags = {} + end + def index(index) + tk_send 'index', index + end + def value + tk_send 'get', "1.0", "end" + end + def value= (val) + tk_send 'delete', "1.0", 'end' + tk_send 'insert', "1.0", val + end + def _addcmd(cmd) + @cmdtbl.push id + end + def _addtag(cmd) + @cmdtbl.push id + end + private :_addcmd, :_addtag + def tag_names + tk_send('tag', 'names').collect{|elt| + if not @tags[elt] + elt + else + @tags[elt] + end + } + end + def window_names + tk_send('window', 'names').collect{|elt| + if not @tags[elt] + elt + else + @tags[elt] + end + } + end + + def destroy + for t in @tags + t.destroy + end + super + end + + def backspace + self.delete 'insert' + end + + def compare(idx1, op, idx2) + bool(tk_send('compare', idx1, op, idx2)) + end + + def debug + bool(tk_send('debug')) + end + def debug=(boolean) + tk_send 'debug', boolean + end + + def yview(*what) + tk_send 'yview', *what + end + def yview_pickplace(*what) + tk_send 'yview', '-pickplace', *what + end +end + +class TkTextTag:TkObject + $tk_text_tag = 'tag0000' + def initialize(parent) + if not parent.is_kind_of?(TkText) + fail format("%s need to be TkText", parent.inspect) + end + @t = parent + @path = parent.path + @id = $tk_text_tag + $tk_text_tag = $tk_text_tag.next + @t._addtag id, self + end + def id + return @id + end + + def add(*index) + tk_call path, 'tag', 'add', @id, *index + end + + def configure(slot, value) + tk_call path, 'tag', 'configure', id, "-#{slot}", value + end + + def bind(seq, cmd=Proc.new) + id = install_cmd(cmd) + tk_call path, 'tag', 'bind', tag, "<#{seq}>", id + @t._addcmd cmd + end + + def lower(below=None) + tk_call path, 'tag', 'lower', below + end + + def destroy + tk_call path, 'tag', 'delete', @id + end +end + +class TkTextMark:TkObject + $tk_text_mark = 'mark0000' + def initialize(parent, index) + if not parent.is_kind_of?(TkText) + fail format("%s need to be TkText", parent.inspect) + end + @t = parent + @path = parent.path + @id = $tk_text_mark + $tk_text_mark = $tk_text_mark.next + tk_call @t, 'set', @id, index + @t._addtag id, self + end + def id + return @id + end + + def set(where) + tk_call path, 'mark', 'unset', @id, where + end + + def unset + tk_call path, 'mark', 'unset', @id + end + alias destroy unset +end + +class TkTextWindow:TkObject + def initialize(parent, index, *args) + if not parent.is_kind_of?(TkText) + fail format("%s need to be TkText", parent.inspect) + end + @t = parent + @path = parent.path + @index = index + tk_call @path, 'window', 'create', index, *args + end + + def configure(slot, value) + tk_call path, 'window', 'configure', @index, "-#{slot}", value + end +end @@ -8,6 +8,7 @@ ************************************************/ +void main(argc, argv, envp) int argc; char **argv, **envp; @@ -13,7 +13,7 @@ #include "ruby.h" #include <math.h> -VALUE M_Math; +VALUE mMath; VALUE float_new(); #define Need_Float(x) \ @@ -29,7 +29,7 @@ if (FIXNUM_P(x)) {\ } static VALUE -Fmath_atan2(obj, x, y) +math_atan2(obj, x, y) VALUE obj; struct RFloat *x, *y; { @@ -38,7 +38,7 @@ Fmath_atan2(obj, x, y) } static VALUE -Fmath_cos(obj, x) +math_cos(obj, x) VALUE obj; struct RFloat *x; { @@ -48,7 +48,7 @@ Fmath_cos(obj, x) } static VALUE -Fmath_sin(obj, x) +math_sin(obj, x) VALUE obj; struct RFloat *x; { @@ -58,7 +58,7 @@ Fmath_sin(obj, x) } static VALUE -Fmath_tan(obj, x) +math_tan(obj, x) VALUE obj; struct RFloat *x; { @@ -68,7 +68,7 @@ Fmath_tan(obj, x) } static VALUE -Fmath_exp(obj, x) +math_exp(obj, x) VALUE obj; struct RFloat *x; { @@ -77,7 +77,7 @@ Fmath_exp(obj, x) } static VALUE -Fmath_log(obj, x) +math_log(obj, x) VALUE obj; struct RFloat *x; { @@ -86,7 +86,7 @@ Fmath_log(obj, x) } static VALUE -Fmath_log10(obj, x) +math_log10(obj, x) VALUE obj; struct RFloat *x; { @@ -95,7 +95,7 @@ Fmath_log10(obj, x) } static VALUE -Fmath_sqrt(obj, x) +math_sqrt(obj, x) VALUE obj; struct RFloat *x; { @@ -105,30 +105,30 @@ Fmath_sqrt(obj, x) return float_new(sqrt(x->value)); } +void Init_Math() { - M_Math = rb_define_module("Math"); - rb_extend_object(M_Math, M_Math); + mMath = rb_define_module("Math"); #ifdef M_PI - rb_define_const(M_Math, "PI", float_new(M_PI)); + rb_define_const(mMath, "PI", float_new(M_PI)); #else - rb_define_const(M_Math, "PI", float_new(atan(1.0)*4.0)); + rb_define_const(mMath, "PI", float_new(atan(1.0)*4.0)); #endif #ifdef M_E - rb_define_const(M_Math, "E", float_new(M_E)); + rb_define_const(mMath, "E", float_new(M_E)); #else - rb_define_const(M_Math, "E", float_new(exp(1.0))); + rb_define_const(mMath, "E", float_new(exp(1.0))); #endif - rb_define_method(M_Math, "atan2", Fmath_atan2, 2); - rb_define_method(M_Math, "cos", Fmath_cos, 1); - rb_define_method(M_Math, "sin", Fmath_sin, 1); - rb_define_method(M_Math, "tan", Fmath_tan, 1); + rb_define_module_function(mMath, "atan2", math_atan2, 2); + rb_define_module_function(mMath, "cos", math_cos, 1); + rb_define_module_function(mMath, "sin", math_sin, 1); + rb_define_module_function(mMath, "tan", math_tan, 1); - rb_define_method(M_Math, "exp", Fmath_exp, 1); - rb_define_method(M_Math, "log", Fmath_log, 1); - rb_define_method(M_Math, "log10", Fmath_log10, 1); - rb_define_method(M_Math, "sqrt", Fmath_sqrt, 1); + rb_define_module_function(mMath, "exp", math_exp, 1); + rb_define_module_function(mMath, "log", math_log, 1); + rb_define_module_function(mMath, "log10", math_log10, 1); + rb_define_module_function(mMath, "sqrt", math_sqrt, 1); } diff --git a/missing/MANIFEST b/missing/MANIFEST deleted file mode 100644 index 52640c2720..0000000000 --- a/missing/MANIFEST +++ /dev/null @@ -1,10 +0,0 @@ -MANIFEST -alloca.c -memmove.c -mkdir.c -strdup.c -strerror.c -strftime.c -strstr.c -strtol.c -strtoul.c diff --git a/missing/crypt.c b/missing/crypt.c new file mode 100644 index 0000000000..9f9b562c36 --- /dev/null +++ b/missing/crypt.c @@ -0,0 +1,276 @@ +/* From Andy Tanenbaum's book "Computer Networks", + rewritten in C +*/ + +struct block { + unsigned char b_data[64]; +}; + +struct ordering { + unsigned char o_data[64]; +}; + +static struct block key; + +static struct ordering InitialTr = { + 58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4, + 62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8, + 57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3, + 61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7, +}; + +static struct ordering FinalTr = { + 40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31, + 38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29, + 36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27, + 34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25, +}; + +static struct ordering swap = { + 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, + 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, + 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16, + 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, +}; + +static struct ordering KeyTr1 = { + 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18, + 10, 2,59,51,43,35,27,19,11, 3,60,52,44,36, + 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, + 14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4, +}; + +static struct ordering KeyTr2 = { + 14,17,11,24, 1, 5, 3,28,15, 6,21,10, + 23,19,12, 4,26, 8,16, 7,27,20,13, 2, + 41,52,31,37,47,55,30,40,51,45,33,48, + 44,49,39,56,34,53,46,42,50,36,29,32, +}; + +static struct ordering etr = { + 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, + 8, 9,10,11,12,13,12,13,14,15,16,17, + 16,17,18,19,20,21,20,21,22,23,24,25, + 24,25,26,27,28,29,28,29,30,31,32, 1, +}; + +static struct ordering ptr = { + 16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10, + 2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25, +}; + +static unsigned char s_boxes[8][64] = { +{ 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, + 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, + 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, + 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13, +}, + +{ 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, + 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, + 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, + 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9, +}, + +{ 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, + 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, + 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12, +}, + +{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, + 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, + 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, + 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14, +}, + +{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, + 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, + 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, + 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3, +}, + +{ 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, + 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8, + 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, + 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13, +}, + +{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, + 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, + 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, + 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12, +}, + +{ 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, + 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, + 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, + 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11, +}, +}; + +static int rots[] = { + 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, +}; + +static void transpose(struct block *data, struct ordering *t, int n) +{ + struct block x; + + x = *data; + + while (n-- > 0) { + data->b_data[n] = x.b_data[t->o_data[n] - 1]; + } +} + +static void rotate(struct block *key) +{ + register unsigned char *p = key->b_data; + register unsigned char *ep = &(key->b_data[55]); + int data0 = key->b_data[0], data28 = key->b_data[28]; + + while (p++ < ep) *(p-1) = *p; + key->b_data[27] = (char) data0; + key->b_data[55] = (char) data28; +} + +static struct ordering *EP = &etr; + +static void f(int i, struct block *key, struct block *a, struct block *x) +{ + struct block e, ikey, y; + int k; + register unsigned char *p, *q, *r; + + e = *a; + transpose(&e, EP, 48); + for (k = rots[i]; k; k--) rotate(key); + ikey = *key; + transpose(&ikey, &KeyTr2, 48); + p = &(y.b_data[48]); + q = &(e.b_data[48]); + r = &(ikey.b_data[48]); + while (p > y.b_data) { + *--p = *--q ^ *--r; + } + q = x->b_data; + for (k = 0; k < 8; k++) { + register int xb, r; + + r = *p++ << 5; + r += *p++ << 3; + r += *p++ << 2; + r += *p++ << 1; + r += *p++; + r += *p++ << 4; + + xb = s_boxes[k][r]; + + *q++ = (char) (xb >> 3) & 1; + *q++ = (char) (xb>>2) & 1; + *q++ = (char) (xb>>1) & 1; + *q++ = (char) (xb & 1); + } + transpose(x, &ptr, 32); +} + +void definekey(char *k) +{ + + key = *((struct block *) k); + transpose(&key, &KeyTr1, 56); +} + +void encrypt(char *blck, int edflag) +{ + register struct block *p = (struct block *) blck; + register int i; + + transpose(p, &InitialTr, 64); + for (i = 15; i>= 0; i--) { + int j = edflag ? i : 15 - i; + register int k; + struct block b, x; + + b = *p; + for (k = 31; k >= 0; k--) { + p->b_data[k] = b.b_data[k + 32]; + } + f(j, &key, p, &x); + for (k = 31; k >= 0; k--) { + p->b_data[k+32] = b.b_data[k] ^ x.b_data[k]; + } + } + transpose(p, &swap, 64); + transpose(p, &FinalTr, 64); +} + +char *crypt(char *pw, char *salt) +{ + + char pwb[66]; + static char result[16]; + register char *p = pwb; + struct ordering new_etr; + register int i; + + while (*pw && p < &pwb[64]) { + register int j = 7; + + while (j--) { + *p++ = (*pw >> j) & 01; + } + pw++; + *p++ = 0; + } + while (p < &pwb[64]) *p++ = 0; + + definekey(p = pwb); + + while (p < &pwb[66]) *p++ = 0; + + new_etr = etr; + EP = &new_etr; + for (i = 0; i < 2; i++) { + register char c = *salt++; + register int j; + + result[i] = c; + if ( c > 'Z') c -= 6 + 7 + '.'; /* c was a lower case letter */ + else if ( c > '9') c -= 7 + '.';/* c was upper case letter */ + else c -= '.'; /* c was digit, '.' or '/'. */ + /* now, 0 <= c <= 63 */ + for (j = 0; j < 6; j++) { + if ((c >> j) & 01) { + int t = 6*i + j; + int temp = new_etr.o_data[t]; + new_etr.o_data[t] = new_etr.o_data[t+24]; + new_etr.o_data[t+24] = (char) temp; + } + } + } + + if (result[1] == 0) result[1] = result[0]; + + for (i = 0; i < 25; i++) encrypt(pwb,0); + EP = &etr; + + p = pwb; + pw = result+2; + while (p < &pwb[66]) { + register int c = 0; + register int j = 6; + + while (j--) { + c <<= 1; + c |= *p++; + } + c += '.'; /* becomes >= '.' */ + if (c > '9') c += 7; /* not in [./0-9], becomes upper */ + if (c > 'Z') c += 6; /* not in [A-Z], becomes lower */ + *pw++ = (char) c; + } + *pw = 0; + return result; +} diff --git a/missing/dup2.c b/missing/dup2.c new file mode 100644 index 0000000000..c541149d4b --- /dev/null +++ b/missing/dup2.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1991, Larry Wall + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + */ + +#include "defines.h" + +#if defined(HAVE_FCNTL) && defined(F_DUPFD) +# include <fcntl.h> +#endif + +int +dup2(oldfd,newfd) +int oldfd; +int newfd; +{ +#if defined(HAVE_FCNTL) && defined(F_DUPFD) + close(newfd); + return fcntl(oldfd, F_DUPFD, newfd); +#else + int fdtmp[256]; + int fdx = 0; + int fd; + + if (oldfd == newfd) + return 0; + close(newfd); + while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */ + fdtmp[fdx++] = fd; + while (fdx > 0) + close(fdtmp[--fdx]); + return 0; +#endif +} diff --git a/missing/nt.c b/missing/nt.c new file mode 100644 index 0000000000..e553abbe70 --- /dev/null +++ b/missing/nt.c @@ -0,0 +1,1732 @@ +/*
+ * Copyright (c) 1993, Intergraph Corporation
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Artistic License, as specified in the perl README file.
+ *
+ * Various Unix compatibility functions and NT specific functions.
+ *
+ * Some of this code was derived from the MSDOS port(s) and the OS/2 port.
+ *
+ */
+
+#include "ruby.h"
+#include <fcntl.h>
+#include <process.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <assert.h>
+
+bool NtSyncProcess = FALSE;
+extern char **environ;
+
+static bool NtHasRedirection (char *);
+static int valid_filename(char *s);
+
+FILE *fdopen(int, char *);
+
+void
+sleep(unsigned int len)
+{
+ time_t end;
+
+ end = time((time_t *)0) + len;
+ while (time((time_t *)0) < end)
+ ;
+}
+
+//
+// Initialization stuff
+//
+void
+NtInitialize(int *argc, char ***argv) {
+
+ WORD version;
+ WSADATA retdata;
+ int ret;
+
+ //
+ // subvert cmd.exe\'s feeble attempt at command line parsing
+ //
+ *argc = NtMakeCmdVector((char *)GetCommandLine(), argv, TRUE);
+
+ //
+ // Now set up the correct time stuff
+ //
+
+ tzset();
+}
+
+
+char *getlogin()
+{
+ char buffer[200];
+ int len = 200;
+ extern char *NTLoginName;
+
+ if (NTLoginName == NULL) {
+ if (GetUserName(buffer, &len)) {
+ NTLoginName = ALLOC_N(char, len+1);
+ strncpy(NTLoginName, buffer, len);
+ NTLoginName[len] = '\0';
+ }
+ else {
+ NTLoginName = "<Unknown>";
+ }
+ }
+ return NTLoginName;
+}
+
+
+
+// popen stuff
+
+//
+// use these so I can remember which index is which
+//
+
+#define NtPipeRead 0 // index of pipe read descriptor
+#define NtPipeWrite 1 // index of pipe write descriptor
+
+#define NtPipeSize 1024 // size of pipe buffer
+
+#define MYPOPENSIZE 256 // size of book keeping structure
+
+struct {
+ int inuse;
+ int pid;
+ FILE *pipe;
+} MyPopenRecord[MYPOPENSIZE];
+
+FILE *
+mypopen (char *cmd, char *mode)
+{
+ FILE *fp;
+ int saved, reading;
+ int pipemode;
+ int pipes[2];
+ int pid;
+ int slot;
+ static initialized = 0;
+
+ //
+ // if first time through, intialize our book keeping structure
+ //
+
+ if (!initialized++) {
+ for (slot = 0; slot < MYPOPENSIZE; slot++)
+ MyPopenRecord[slot].inuse = FALSE;
+ }
+
+ //
+ // find a free popen slot
+ //
+
+ for (slot = 0; slot < MYPOPENSIZE && MyPopenRecord[slot].inuse; slot++)
+ ;
+
+ if (slot > MYPOPENSIZE) {
+ return NULL;
+ }
+
+ //
+ // Figure out what we\'re doing...
+ //
+
+ reading = (*mode == 'r') ? TRUE : FALSE;
+ pipemode = (*(mode+1) == 'b') ? O_BINARY : O_TEXT;
+
+ //
+ // Now get a pipe
+ //
+
+ if (_pipe(pipes, NtPipeSize, pipemode) == -1) {
+ return NULL;
+ }
+
+ if (reading) {
+
+ //
+ // we\'re reading from the pipe, so we must hook up the
+ // write end of the pipe to the new processes stdout.
+ // To do this we must save our file handle from stdout
+ // by _dup\'ing it, then setting our stdout to be the pipe\'s
+ // write descriptor. We must also make the write handle
+ // inheritable so the new process can use it.
+
+ if ((saved = _dup(fileno(stdout))) == -1) {
+ _close(pipes[NtPipeRead]);
+ _close(pipes[NtPipeWrite]);
+ return NULL;
+ }
+ if (_dup2 (pipes[NtPipeWrite], fileno(stdout)) == -1) {
+ _close(pipes[NtPipeRead]);
+ _close(pipes[NtPipeWrite]);
+ return NULL;
+ }
+ }
+ else {
+ //
+ // must be writing to the new process. Do the opposite of
+ // the above, i.e. hook up the processes stdin to the read
+ // end of the pipe.
+ //
+
+ if ((saved = _dup(fileno(stdin))) == -1) {
+ _close(pipes[NtPipeRead]);
+ _close(pipes[NtPipeWrite]);
+ return NULL;
+ }
+ if (_dup2(pipes[NtPipeRead], fileno(stdin)) == -1) {
+ _close(pipes[NtPipeRead]);
+ _close(pipes[NtPipeWrite]);
+ return NULL;
+ }
+ }
+
+ //
+ // Start the new process. Must set _fileinfo to non-zero value
+ // for file descriptors to be inherited. Reset after the process
+ // is started.
+ //
+
+ if (NtHasRedirection(cmd)) {
+ docmd:
+ pid = spawnlpe(_P_NOWAIT, "cmd.exe", "/c", cmd, 0, environ);
+ if (pid == -1) {
+ _close(pipes[NtPipeRead]);
+ _close(pipes[NtPipeWrite]);
+ return NULL;
+ }
+ }
+ else {
+ char **vec;
+ int vecc = NtMakeCmdVector(cmd, &vec, FALSE);
+
+ pid = spawnvpe (_P_NOWAIT, vec[0], vec, environ);
+ if (pid == -1) {
+ goto docmd;
+ }
+ Safefree (vec);
+ }
+
+ if (reading) {
+
+ //
+ // We need to close our instance of the inherited pipe write
+ // handle now that it's been inherited so that it will actually close
+ // when the child process ends.
+ //
+
+ if (_close(pipes[NtPipeWrite]) == -1) {
+ _close(pipes[NtPipeRead]);
+ return NULL;
+ }
+ if (_dup2 (saved, fileno(stdout)) == -1) {
+ _close(pipes[NtPipeRead]);
+ return NULL;
+ }
+ _close(saved);
+
+ //
+ // Now get a stream pointer to return to the calling program.
+ //
+
+ if ((fp = (FILE *) fdopen(pipes[NtPipeRead], mode)) == NULL) {
+ return NULL;
+ }
+ }
+ else {
+
+ //
+ // need to close our read end of the pipe so that it will go
+ // away when the write end is closed.
+ //
+
+ if (_close(pipes[NtPipeRead]) == -1) {
+ _close(pipes[NtPipeWrite]);
+ return NULL;
+ }
+ if (_dup2 (saved, fileno(stdin)) == -1) {
+ _close(pipes[NtPipeWrite]);
+ return NULL;
+ }
+ _close(saved);
+
+ //
+ // Now get a stream pointer to return to the calling program.
+ //
+
+ if ((fp = (FILE *) fdopen(pipes[NtPipeWrite], mode)) == NULL) {
+ _close(pipes[NtPipeWrite]);
+ return NULL;
+ }
+ }
+
+ //
+ // do the book keeping
+ //
+
+ MyPopenRecord[slot].inuse = TRUE;
+ MyPopenRecord[slot].pipe = fp;
+ MyPopenRecord[slot].pid = pid;
+
+ return fp;
+}
+
+int
+mypclose(FILE *fp)
+{
+ int i;
+ int exitcode;
+
+ for (i = 0; i < MYPOPENSIZE; i++) {
+ if (MyPopenRecord[i].inuse && MyPopenRecord[i].pipe == fp)
+ break;
+ }
+ if (i >= MYPOPENSIZE) {
+ fprintf(stderr,"Invalid file pointer passed to mypclose!\n");
+ abort();
+ }
+
+ //
+ // get the return status of the process
+ //
+
+ if (_cwait(&exitcode, MyPopenRecord[i].pid, WAIT_CHILD) == -1) {
+ if (errno == ECHILD) {
+ fprintf(stderr, "mypclose: nosuch child as pid %x\n",
+ MyPopenRecord[i].pid);
+ }
+ }
+
+ //
+ // close the pipe
+ //
+
+ fclose(fp);
+
+ //
+ // free this slot
+ //
+
+ MyPopenRecord[i].inuse = FALSE;
+
+ return exitcode;
+}
+
+
+/*
+ * The following code is based on the do_exec and do_aexec functions
+ * in file doio.c
+ */
+
+int
+do_spawn(cmd)
+char *cmd;
+{
+ register char **a;
+ register char *s;
+ char **argv;
+ int status;
+ char *shell, *cmd2;
+ int mode = NtSyncProcess ? P_WAIT : P_NOWAIT;
+
+ /* save an extra exec if possible */
+ if ((shell = getenv("COMSPEC")) == 0)
+ shell = "cmd.exe";
+
+ /* see if there are shell metacharacters in it */
+ if (NtHasRedirection(cmd)) {
+ doshell:
+ return spawnle(mode, shell, shell, "/c", cmd, (char*)0, environ);
+ }
+
+ argv = ALLOC_N(char*, strlen(cmd) / 2 + 2);
+ cmd2 = ALOOC_N(char, strlen(cmd) + 1);
+ strcpy(cmd2, cmd);
+ a = argv;
+ for (s = cmd2; *s;) {
+ while (*s && isspace(*s)) s++;
+ if (*s)
+ *(a++) = s;
+ while (*s && !isspace(*s)) s++;
+ if (*s)
+ *s++ = '\0';
+ }
+ *a = Qnil;
+ if (argv[0]) {
+ if ((status = spawnvpe(mode, argv[0], argv, environ)) == -1) {
+ free(argv);
+ free(cmd2);
+ goto doshell;
+ }
+ }
+ free(cmd2);
+ free(argv);
+ return status;
+}
+
+
+
+typedef struct _NtCmdLineElement {
+ struct _NtCmdLineElement *next, *prev;
+ char *str;
+ int len;
+ int flags;
+} NtCmdLineElement;
+
+//
+// Possible values for flags
+//
+
+#define NTGLOB 0x1 // element contains a wildcard
+#define NTMALLOC 0x2 // string in element was malloc'ed
+#define NTSTRING 0x4 // element contains a quoted string
+
+NtCmdLineElement *NtCmdHead = NULL, *NtCmdTail = NULL;
+
+void
+NtFreeCmdLine(void)
+{
+ NtCmdLineElement *ptr;
+
+ while(NtCmdHead) {
+ ptr = NtCmdHead;
+ NtCmdHead = NtCmdHead->next;
+ free(ptr);
+ }
+ NtCmdHead = NtCmdTail = NULL;
+}
+
+//
+// This function expands wild card characters that were spotted
+// during the parse phase. The idea here is to call FindFirstFile and
+// FindNextFile with the wildcard pattern specified, and splice in the
+// resulting list of new names. If the wildcard pattern doesn\'t match
+// any existing files, just leave it in the list.
+//
+
+void
+NtCmdGlob (NtCmdLineElement *patt)
+{
+ WIN32_FIND_DATA fd;
+ HANDLE fh;
+ char buffer[512];
+ NtCmdLineElement *tmphead, *tmptail, *tmpcurr;
+
+ strncpy(buffer, patt->str, patt->len);
+ buffer[patt->len] = '\0';
+ if ((fh = FindFirstFile (buffer, &fd)) == INVALID_HANDLE_VALUE) {
+ return;
+ }
+ tmphead = tmptail = NULL;
+ do {
+ tmpcurr = ALLOC(NtCmdLineElement);
+ if (tmpcurr == NULL) {
+ fprintf(stderr, "Out of Memory in globbing!\n");
+ while (tmphead) {
+ tmpcurr = tmphead;
+ tmphead = tmphead->next;
+ free(tmpcurr->str);
+ free(tmpcurr);
+ }
+ return;
+ }
+ memset (tmpcurr, 0, sizeof(*tmpcurr));
+ tmpcurr->len = strlen(fd.cFileName);
+ tmpcurr->str = ALLOC_N(char, tmpcurr->len+1);
+ if (tmpcurr->str == NULL) {
+ fprintf(stderr, "Out of Memory in globbing!\n");
+ while (tmphead) {
+ tmpcurr = tmphead;
+ tmphead = tmphead->next;
+ free(tmpcurr->str);
+ free(tmpcurr);
+ }
+ return;
+ }
+ strcpy(tmpcurr->str, fd.cFileName);
+ tmpcurr->flags |= NTMALLOC;
+ if (tmptail) {
+ tmptail->next = tmpcurr;
+ tmpcurr->prev = tmptail;
+ tmptail = tmpcurr;
+ }
+ else {
+ tmptail = tmphead = tmpcurr;
+ }
+ } while(FindNextFile(fh, &fd));
+
+ //
+ // ok, now we\'ve got a list of files that matched the wildcard
+ // specification. Put it in place of the pattern structure.
+ //
+
+ tmphead->prev = patt->prev;
+ tmptail->next = patt->next;
+
+ if (tmphead->prev)
+ tmphead->prev->next = tmphead;
+
+ if (tmptail->next)
+ tmptail->next->prev = tmptail;
+
+ //
+ // Now get rid of the pattern structure
+ //
+
+ if (patt->flags & NTMALLOC)
+ free(patt->str);
+ free(patt);
+}
+
+//
+// Check a command string to determine if it has I/O redirection
+// characters that require it to be executed by a command interpreter
+//
+
+static bool
+NtHasRedirection (char *cmd)
+{
+ int inquote = 0;
+ char quote = '\0';
+ char *ptr ;
+
+ //
+ // Scan the string, looking for redirection (< or >) or pipe
+ // characters (|) that are not in a quoted string
+ //
+
+ for (ptr = cmd; *ptr; ptr++) {
+
+ switch (*ptr) {
+
+ case '\'':
+ case '\"':
+ if (inquote) {
+ if (quote == *ptr) {
+ inquote = 0;
+ quote = '\0';
+ }
+ }
+ else {
+ quote = *ptr;
+ inquote++;
+ }
+ break;
+
+ case '>':
+ case '<':
+
+ if (!inquote)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+int
+NtMakeCmdVector (char *cmdline, char ***vec, int InputCmd)
+{
+ int cmdlen = strlen(cmdline);
+ int done, instring, globbing, quoted, len;
+ int newline, need_free = 0, i;
+ int elements, strsz;
+ int slashes = 0;
+ char *ptr, *base, *buffer;
+ char **vptr;
+ char quote;
+ NtCmdLineElement *curr;
+
+ //
+ // just return if we don\'t have a command line
+ //
+
+ if (cmdlen == 0) {
+ *vec = NULL;
+ return 0;
+ }
+
+ //
+ // strip trailing white space
+ //
+
+ ptr = cmdline+(cmdlen - 1);
+ while(ptr >= cmdline && isspace(*ptr))
+ --ptr;
+ *++ptr = '\0';
+
+ //
+ // check for newlines and formfeeds. If we find any, make a new
+ // command string that replaces them with escaped sequences (\n or \f)
+ //
+
+ for (ptr = cmdline, newline = 0; *ptr; ptr++) {
+ if (*ptr == '\n' || *ptr == '\f')
+ newline++;
+ }
+
+ if (newline) {
+ base = ALLOC_N(char, strlen(cmdline) + 1 + newline + slashes);
+ if (base == NULL) {
+ fprintf(stderr, "malloc failed!\n");
+ return 0;
+ }
+ for (i = 0, ptr = base; (unsigned) i < strlen(cmdline); i++) {
+ switch (cmdline[i]) {
+ case '\n':
+ *ptr++ = '\\';
+ *ptr++ = 'n';
+ break;
+ default:
+ *ptr++ = cmdline[i];
+ }
+ }
+ *ptr = '\0';
+ cmdline = base;
+ need_free++;
+ }
+
+ //
+ // Ok, parse the command line, building a list of CmdLineElements.
+ // When we\'ve finished, and it\'s an input command (meaning that it\'s
+ // the processes argv), we\'ll do globing and then build the argument
+ // vector.
+ // The outer loop does one interation for each element seen.
+ // The inner loop does one interation for each character in the element.
+ //
+
+ for (done = 0, ptr = cmdline; *ptr;) {
+
+ //
+ // zap any leading whitespace
+ //
+
+ while(isspace(*ptr))
+ ptr++;
+ base = ptr;
+
+ for (done = newline = globbing = instring = quoted = 0;
+ *ptr && !done; ptr++) {
+
+ //
+ // Switch on the current character. We only care about the
+ // white-space characters, the wild-card characters, and the
+ // quote characters.
+ //
+
+ switch (*ptr) {
+ case ' ':
+ case '\t':
+#if 0
+ case '/': // have to do this for NT/DOS option strings
+
+ //
+ // check to see if we\'re parsing an option switch
+ //
+
+ if (*ptr == '/' && base == ptr)
+ continue;
+#endif
+ //
+ // if we\'re not in a string, then we\'re finished with this
+ // element
+ //
+
+ if (!instring)
+ done++;
+ break;
+
+ case '*':
+ case '?':
+
+ //
+ // record the fact that this element has a wildcard character
+ // N.B. Don\'t glob if inside a single quoted string
+ //
+
+ if (!(instring && quote == '\''))
+ globbing++;
+ break;
+
+ case '\n':
+
+ //
+ // If this string contains a newline, mark it as such so
+ // we can replace it with the two character sequence "\n"
+ // (cmd.exe doesn\'t like raw newlines in strings...sigh).
+ //
+
+ newline++;
+ break;
+
+ case '\'':
+ case '\"':
+
+ //
+ // if we\'re already in a string, see if this is the
+ // terminating close-quote. If it is, we\'re finished with
+ // the string, but not neccessarily with the element.
+ // If we\'re not already in a string, start one.
+ //
+
+ if (instring) {
+ if (quote == *ptr) {
+ instring = 0;
+ quote = '\0';
+ }
+ }
+ else {
+ instring++;
+ quote = *ptr;
+ quoted++;
+ }
+ break;
+ }
+ }
+
+ //
+ // need to back up ptr by one due to last increment of for loop
+ // (if we got out by seeing white space)
+ //
+
+ if (*ptr)
+ ptr--;
+
+ //
+ // when we get here, we\'ve got a pair of pointers to the element,
+ // base and ptr. Base points to the start of the element while ptr
+ // points to the character following the element.
+ //
+
+ curr = ALLOC(NtCmdLineElement);
+ if (curr == NULL) {
+ NtFreeCmdLine();
+ fprintf(stderr, "Out of memory!!\n");
+ *vec = NULL;
+ return 0;
+ }
+ memset (curr, 0, sizeof(*curr));
+
+ len = ptr - base;
+
+ //
+ // if it\'s an input vector element and it\'s enclosed by quotes,
+ // we can remove them.
+ //
+
+ if (InputCmd &&
+ ((base[0] == '\"' && base[len-1] == '\"') ||
+ (base[0] == '\'' && base[len-1] == '\''))) {
+ base++;
+ len -= 2;
+ }
+
+ curr->str = base;
+ curr->len = len;
+ curr->flags |= (globbing ? NTGLOB : 0);
+
+ //
+ // Now put it in the list of elements
+ //
+ if (NtCmdTail) {
+ NtCmdTail->next = curr;
+ curr->prev = NtCmdTail;
+ NtCmdTail = curr;
+ }
+ else {
+ NtCmdHead = NtCmdTail = curr;
+ }
+ }
+
+ if (InputCmd) {
+
+ //
+ // When we get here we\'ve finished parsing the command line. Now
+ // we need to run the list, expanding any globbing patterns.
+ //
+
+ for(curr = NtCmdHead; curr; curr = curr->next) {
+ if (curr->flags & NTGLOB) {
+ NtCmdGlob(curr);
+ }
+ }
+ }
+
+ //
+ // Almost done!
+ // Count up the elements, then allocate space for a vector of pointers
+ // (argv) and a string table for the elements.
+ //
+
+ for (elements = 0, strsz = 0, curr = NtCmdHead; curr; curr = curr->next) {
+ elements++;
+ strsz += (curr->len + 1);
+ }
+
+ len = (elements+1)*sizeof(char *) + strsz;
+ buffer = ALLOC_N(char, len);
+ if (buffer == NULL) {
+ fprintf(stderr, "Out of memory!!\n");
+ NtFreeCmdLine();
+ *vec = NULL;
+ return 0;
+ }
+
+ memset (buffer, 0, len);
+
+ //
+ // make vptr point to the start of the buffer
+ // and ptr point to the area we\'ll consider the string table.
+ //
+
+ vptr = (char **) buffer;
+
+ ptr = buffer + (elements+1) * sizeof(char *);
+
+ for (curr = NtCmdHead; curr; curr = curr->next) {
+ strncpy (ptr, curr->str, curr->len);
+ ptr[curr->len] = '\0';
+ *vptr++ = ptr;
+ ptr += curr->len + 1;
+ }
+ NtFreeCmdLine();
+ *vec = (char **) buffer;
+ return elements;
+}
+
+
+//
+// UNIX compatible directory access functions for NT
+//
+
+//
+// File names are converted to lowercase if the
+// CONVERT_TO_LOWER_CASE variable is defined.
+//
+
+#define CONVERT_TO_LOWER_CASE
+#define PATHLEN 1024
+
+//
+// The idea here is to read all the directory names into a string table
+// (separated by nulls) and when one of the other dir functions is called
+// return the pointer to the current file name.
+//
+
+DIR *
+opendir(char *filename)
+{
+ DIR *p;
+ long len;
+ long idx;
+ char scannamespc[PATHLEN];
+ char *scanname = scannamespc;
+ struct stat sbuf;
+ WIN32_FIND_DATA FindData;
+ HANDLE fh;
+ char root[PATHLEN];
+ char volname[PATHLEN];
+ DWORD serial, maxname, flags;
+ BOOL downcase;
+ char *dummy;
+
+ //
+ // check to see if we\'ve got a directory
+ //
+
+ if (stat (filename, &sbuf) < 0 ||
+ sbuf.st_mode & _S_IFDIR == 0) {
+ return NULL;
+ }
+
+ //
+ // check out the file system characteristics
+ //
+ if (GetFullPathName(filename, PATHLEN, root, &dummy)) {
+ if (dummy = strchr(root, '\\'))
+ *++dummy = '\0';
+ if (GetVolumeInformation(root, volname, PATHLEN,
+ &serial, &maxname, &flags, 0, 0)) {
+ downcase = !(flags & FS_CASE_SENSITIVE);
+ }
+ }
+ else {
+ downcase = TRUE;
+ }
+
+ //
+ // Get us a DIR structure
+ //
+
+ p = xcalloc(sizeof(DIR), 1);
+ if (p == NULL)
+ return NULL;
+
+ //
+ // Create the search pattern
+ //
+
+ strcpy(scanname, filename);
+
+ if (index("/\\", *(scanname + strlen(scanname) - 1)) == NULL)
+ strcat(scanname, "/*");
+ else
+ strcat(scanname, "*");
+
+ //
+ // do the FindFirstFile call
+ //
+
+ fh = FindFirstFile (scanname, &FindData);
+ if (fh == INVALID_HANDLE_VALUE) {
+ return NULL;
+ }
+
+ //
+ // now allocate the first part of the string table for the
+ // filenames that we find.
+ //
+
+ idx = strlen(FindData.cFileName)+1;
+ p->start = ALLOC_N(char, idx);
+ strcpy (p->start, FindData.cFileName);
+ if (downcase)
+ strlwr(p->start);
+ p->nfiles++;
+
+ //
+ // loop finding all the files that match the wildcard
+ // (which should be all of them in this directory!).
+ // the variable idx should point one past the null terminator
+ // of the previous string found.
+ //
+ while (FindNextFile(fh, &FindData)) {
+ len = strlen (FindData.cFileName);
+
+ //
+ // bump the string table size by enough for the
+ // new name and it's null terminator
+ //
+
+ Renew (p->start, idx+len+1, char);
+ if (p->start == NULL) {
+ fatal ("opendir: malloc failed!\n");
+ }
+ strcpy(&p->start[idx], FindData.cFileName);
+ if (downcase)
+ strlwr(&p->start[idx]);
+ p->nfiles++;
+ idx += len+1;
+ }
+ FindClose(fh);
+ p->size = idx;
+ p->curr = p->start;
+ return p;
+}
+
+
+//
+// Readdir just returns the current string pointer and bumps the
+// string pointer to the next entry.
+//
+
+struct direct *
+readdir(DIR *dirp)
+{
+ int len;
+ static int dummy = 0;
+
+ if (dirp->curr) {
+
+ //
+ // first set up the structure to return
+ //
+
+ len = strlen(dirp->curr);
+ strcpy(dirp->dirstr.d_name, dirp->curr);
+ dirp->dirstr.d_namlen = len;
+
+ //
+ // Fake inode
+ //
+ dirp->dirstr.d_ino = dummy++;
+
+ //
+ // Now set up for the next call to readdir
+ //
+
+ dirp->curr += len + 1;
+ if (dirp->curr >= (dirp->start + dirp->size)) {
+ dirp->curr = NULL;
+ }
+
+ return &(dirp->dirstr);
+
+ } else
+ return NULL;
+}
+
+//
+// Telldir returns the current string pointer position
+//
+
+long
+telldir(DIR *dirp)
+{
+ return (long) dirp->curr; /* ouch! pointer to long cast */
+}
+
+//
+// Seekdir moves the string pointer to a previously saved position
+// (Saved by telldir).
+
+void
+seekdir(DIR *dirp, long loc)
+{
+ dirp->curr = (char *) loc; /* ouch! long to pointer cast */
+}
+
+//
+// Rewinddir resets the string pointer to the start
+//
+
+void
+rewinddir(DIR *dirp)
+{
+ dirp->curr = dirp->start;
+}
+
+//
+// This just free\'s the memory allocated by opendir
+//
+
+void
+closedir(DIR *dirp)
+{
+ free(dirp->start);
+ free(dirp);
+}
+
+
+
+//
+// 98.2% of this code was lifted from the OS2 port. (JCW)
+//
+
+/*
+ * Suffix appending for in-place editing under MS-DOS and OS/2 (and now NT!).
+ *
+ * Here are the rules:
+ *
+ * Style 0: Append the suffix exactly as standard perl would do it.
+ * If the filesystem groks it, use it. (HPFS will always
+ * grok it. So will NTFS. FAT will rarely accept it.)
+ *
+ * Style 1: The suffix begins with a '.'. The extension is replaced.
+ * If the name matches the original name, use the fallback method.
+ *
+ * Style 2: The suffix is a single character, not a '.'. Try to add the
+ * suffix to the following places, using the first one that works.
+ * [1] Append to extension.
+ * [2] Append to filename,
+ * [3] Replace end of extension,
+ * [4] Replace end of filename.
+ * If the name matches the original name, use the fallback method.
+ *
+ * Style 3: Any other case: Ignore the suffix completely and use the
+ * fallback method.
+ *
+ * Fallback method: Change the extension to ".$$$". If that matches the
+ * original name, then change the extension to ".~~~".
+ *
+ * If filename is more than 1000 characters long, we die a horrible
+ * death. Sorry.
+ *
+ * The filename restriction is a cheat so that we can use buf[] to store
+ * assorted temporary goo.
+ *
+ * Examples, assuming style 0 failed.
+ *
+ * suffix = ".bak" (style 1)
+ * foo.bar => foo.bak
+ * foo.bak => foo.$$$ (fallback)
+ * foo.$$$ => foo.~~~ (fallback)
+ * makefile => makefile.bak
+ *
+ * suffix = "~" (style 2)
+ * foo.c => foo.c~
+ * foo.c~ => foo.c~~
+ * foo.c~~ => foo~.c~~
+ * foo~.c~~ => foo~~.c~~
+ * foo~~~~~.c~~ => foo~~~~~.$$$ (fallback)
+ *
+ * foo.pas => foo~.pas
+ * makefile => makefile.~
+ * longname.fil => longname.fi~
+ * longname.fi~ => longnam~.fi~
+ * longnam~.fi~ => longnam~.$$$
+ *
+ */
+
+
+static char suffix1[] = ".$$$";
+static char suffix2[] = ".~~~";
+
+#define ext (&buf[1000])
+
+#define strEQ(s1,s2) (strcmp(s1,s2) == 0)
+
+void
+add_suffix(struct RString *str, char *suffix)
+{
+ int baselen;
+ int extlen = strlen(suffix);
+ char *s, *t, *p;
+ int slen;
+ char buf[1024];
+
+ if (str->len > 1000)
+ Fatal("Cannot do inplace edit on long filename (%d characters)", str->len);
+
+ /* Style 0 */
+ slen = str->len;
+ str_cat(str, suffix, extlen);
+ if (valid_filename(str->ptr)) return;
+
+ /* Fooey, style 0 failed. Fix str before continuing. */
+ str->ptr[str->len = slen] = '\0';
+
+ slen = extlen;
+ t = buf; baselen = 0; s = str->ptr;
+ while ( (*t = *s) && *s != '.') {
+ baselen++;
+ if (*s == '\\' || *s == '/') baselen = 0;
+ s++; t++;
+ }
+ p = t;
+
+ t = ext; extlen = 0;
+ while (*t++ = *s++) extlen++;
+ if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; }
+
+ if (*suffix == '.') { /* Style 1 */
+ if (strEQ(ext, suffix)) goto fallback;
+ strcpy(p, suffix);
+ } else if (suffix[1] == '\0') { /* Style 2 */
+ if (extlen < 4) {
+ ext[extlen] = *suffix;
+ ext[++extlen] = '\0';
+ } else if (baselen < 8) {
+ *p++ = *suffix;
+ } else if (ext[3] != *suffix) {
+ ext[3] = *suffix;
+ } else if (buf[7] != *suffix) {
+ buf[7] = *suffix;
+ } else goto fallback;
+ strcpy(p, ext);
+ } else { /* Style 3: Panic */
+fallback:
+ (void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
+ }
+ str_grow(str, strlen(buf));
+ memcpy(str->ptr, buf, str->len);
+}
+
+static int
+valid_filename(char *s)
+{
+ int fd;
+
+ //
+ // if the file exists, then it\'s a valid filename!
+ //
+
+ if (_access(s, 0) == 0) {
+ return 1;
+ }
+
+ //
+ // It doesn\'t exist, so see if we can open it.
+ //
+
+ if ((fd = _open(s, _O_CREAT, 0666)) >= 0) {
+ close(fd);
+ _unlink (s); // don\'t leave it laying around
+ return 1;
+ }
+ return 0;
+}
+
+
+//
+// This is a clone of fdopen so that we can handle the
+// brain damaged version of sockets that NT gets to use.
+//
+// The problem is that sockets are not real file handles and
+// cannot be fdopen\'ed. This causes problems in the do_socket
+// routine in doio.c, since it tries to create two file pointers
+// for the socket just created. We\'ll fake out an fdopen and see
+// if we can prevent perl from trying to do stdio on sockets.
+//
+
+FILE *
+fdopen (int fd, char *mode)
+{
+ FILE *fp;
+ char sockbuf[80];
+ int optlen;
+ int retval;
+ extern int errno;
+
+ retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
+ if (retval == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) {
+ return (_fdopen(fd, mode));
+ }
+
+ //
+ // If we get here, then fd is actually a socket.
+ //
+ fp = xcalloc(sizeof(FILE), 1);
+#if _MSC_VER < 800
+ fileno(fp) = fd;
+#else
+ fp->_file = fd;
+#endif
+ if (*mode = 'r')
+ fp->_flag = _IOREAD;
+ else
+ fp->_flag = _IOWRT;
+ return fp;
+}
+
+
+//
+// Since the errors returned by the socket error function
+// WSAGetLastError() are not known by the library routine strerror
+// we have to roll our own.
+//
+
+#undef strerror
+
+char *
+mystrerror(int e)
+{
+ static char buffer[512];
+ extern int sys_nerr;
+ DWORD source = 0;
+
+ if (e < 0 || e > sys_nerr) {
+ if (e < 0)
+ e = GetLastError();
+ if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, &source, e, 0,
+ buffer, 512, NULL) == 0) {
+ strcpy (buffer, "Unknown Error");
+ }
+ return buffer;
+ }
+ return strerror(e);
+
+}
+
+//
+// various stubs
+//
+
+
+// Ownership
+//
+// Just pretend that everyone is a superuser. NT will let us know if
+// we don\'t really have permission to do something.
+//
+
+#define ROOT_UID 0
+#define ROOT_GID 0
+
+UIDTYPE
+getuid(void)
+{
+ return ROOT_UID;
+}
+
+UIDTYPE
+geteuid(void)
+{
+ return ROOT_UID;
+}
+
+GIDTYPE
+getgid(void)
+{
+ return ROOT_GID;
+}
+
+GIDTYPE
+getegid(void)
+{
+ return ROOT_GID;
+}
+
+int
+setuid(int uid)
+{
+ return (uid == ROOT_UID ? 0 : -1);
+}
+
+int
+setgid(int gid)
+{
+ return (gid == ROOT_GID ? 0 : -1);
+}
+
+//
+// File system stuff
+//
+
+int
+ioctl(int i, unsigned int u, char *data)
+{
+ return -1;
+}
+
+
+//
+// Networking trampolines
+// These are used to avoid socket startup/shutdown overhead in case
+// the socket routines aren\'t used.
+//
+
+#undef select
+
+static int NtSocketsInitialized = 0;
+
+long
+myselect (int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
+ struct timeval *timeout)
+{
+ long r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = select (nfds, rd, wr, ex, timeout)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+static void
+StartSockets () {
+ WORD version;
+ WSADATA retdata;
+ int ret;
+
+ //
+ // initalize the winsock interface and insure that it\'s
+ // cleaned up at exit.
+ //
+ version = MAKEWORD(1, 1);
+ if (ret = WSAStartup(version, &retdata))
+ fatal ("Unable to locate winsock library!\n");
+ if (LOBYTE(retdata.wVersion) != 1)
+ fatal("could not find version 1 of winsock dll\n");
+
+ if (HIBYTE(retdata.wVersion) != 1)
+ fatal("could not find version 1 of winsock dll\n");
+
+ atexit((void (*)(void)) WSACleanup);
+}
+
+#undef accept
+
+SOCKET
+myaccept (SOCKET s, struct sockaddr *addr, int *addrlen)
+{
+ SOCKET r;
+
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = accept (s, addr, addrlen)) == INVALID_SOCKET)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef bind
+
+int
+mybind (SOCKET s, struct sockaddr *addr, int addrlen)
+{
+ int r;
+
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = bind (s, addr, addrlen)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef connect
+
+int
+myconnect (SOCKET s, struct sockaddr *addr, int addrlen)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = connect (s, addr, addrlen)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+
+#undef getpeername
+
+int
+mygetpeername (SOCKET s, struct sockaddr *addr, int *addrlen)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = getpeername (s, addr, addrlen)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef getsockname
+
+int
+mygetsockname (SOCKET s, struct sockaddr *addr, int *addrlen)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = getsockname (s, addr, addrlen)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef getsockopt
+
+int
+mygetsockopt (SOCKET s, int level, int optname, char *optval, int *optlen)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = getsockopt (s, level, optname, optval, optlen)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef ioctlsocket
+
+int
+myioctlsocket (SOCKET s, long cmd, u_long *argp)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = ioctlsocket (s, cmd, argp)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef listen
+
+int
+mylisten (SOCKET s, int backlog)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = listen (s, backlog)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef recv
+
+int
+myrecv (SOCKET s, char *buf, int len, int flags)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = recv (s, buf, len, flags)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef recvfrom
+
+int
+myrecvfrom (SOCKET s, char *buf, int len, int flags,
+ struct sockaddr *from, int *fromlen)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = recvfrom (s, buf, len, flags, from, fromlen)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef send
+
+int
+mysend (SOCKET s, char *buf, int len, int flags)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = send (s, buf, len, flags)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef sendto
+
+int
+mysendto (SOCKET s, char *buf, int len, int flags,
+ struct sockaddr *to, int tolen)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = sendto (s, buf, len, flags, to, tolen)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef setsockopt
+
+int
+mysetsockopt (SOCKET s, int level, int optname, char *optval, int optlen)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = setsockopt (s, level, optname, optval, optlen)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef shutdown
+
+int
+myshutdown (SOCKET s, int how)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = shutdown (s, how)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef socket
+
+SOCKET
+mysocket (int af, int type, int protocol)
+{
+ SOCKET s;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((s = socket (af, type, protocol)) == INVALID_SOCKET)
+ errno = WSAGetLastError();
+ return s;
+}
+
+#undef gethostbyaddr
+
+struct hostent *
+mygethostbyaddr (char *addr, int len, int type)
+{
+ struct hostent *r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = gethostbyaddr (addr, len, type)) == NULL)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef gethostbyname
+
+struct hostent *
+mygethostbyname (char *name)
+{
+ struct hostent *r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = gethostbyname (name)) == NULL)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef gethostname
+
+int
+mygethostname (char *name, int len)
+{
+ int r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = gethostname (name, len)) == SOCKET_ERROR)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef getprotobyname
+
+struct protoent *
+mygetprotobyname (char *name)
+{
+ struct protoent *r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = getprotobyname (name)) == NULL)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef getprotobynumber
+
+struct protoent *
+mygetprotobynumber (int num)
+{
+ struct protoent *r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = getprotobynumber (num)) == NULL)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef getservbyname
+
+struct servent *
+mygetservbyname (char *name, char *proto)
+{
+ struct servent *r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = getservbyname (name, proto)) == NULL)
+ errno = WSAGetLastError();
+ return r;
+}
+
+#undef getservbyport
+
+struct servent *
+mygetservbyport (int port, char *proto)
+{
+ struct servent *r;
+ if (!NtSocketsInitialized++) {
+ StartSockets();
+ }
+ if ((r = getservbyport (port, proto)) == NULL)
+ errno = WSAGetLastError();
+ return r;
+}
+
+//
+// Networking stubs
+//
+
+void endhostent() {}
+void endnetent() {}
+void endprotoent() {}
+void endservent() {}
+
+struct netent *getnetent (void) {return (struct netent *) NULL;}
+
+struct netent *getnetbyaddr(char *name) {return (struct netent *)NULL;}
+
+struct netent *getnetbyname(long net, int type) {return (struct netent *)NULL;}
+
+struct protoent *getprotoent (void) {return (struct protoent *) NULL;}
+
+struct servent *getservent (void) {return (struct servent *) NULL;}
+
+void sethostent (int stayopen) {}
+
+void setnetent (int stayopen) {}
+
+void setprotoent (int stayopen) {}
+
+void setservent (int stayopen) {}
+
+
+pid_t
+waitpid (pid_t pid, int *stat_loc, int options)
+{
+ DWORD timeout;
+
+ if (options == WNOHANG) {
+ timeout = 0;
+ } else {
+ timeout = INFINITE;
+ }
+ if (WaitForSingleObject((HANDLE) pid, timeout) == WAIT_OBJECT_0) {
+ pid = _cwait(stat_loc, pid, 0);
+ return pid;
+ }
+ return 0;
+}
+
+#include <sys/timeb.h>
+
+void _cdecl
+gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ struct timeb tb;
+
+ ftime(&tb);
+ tv->tv_sec = tb.time;
+ tv->tv_usec = tb.millitm * 1000;
+}
+
+char *
+getcwd(buffer, size)
+ char *buffer;
+ int size;
+{
+ int length;
+ char *pb;
+
+ if (_getcwd(buffer, size) == NULL) {
+ return NULL;
+ }
+ length = strlen(buffer);
+ if (length >= size) {
+ return NULL;
+ }
+
+ for (bp = buffer; *bp != '\0'; bp++) {
+ if (*bp == '\\') {
+ *bp = '/';
+ }
+ }
+ return buffer;
+}
diff --git a/missing/nt.h b/missing/nt.h new file mode 100644 index 0000000000..8b208594b6 --- /dev/null +++ b/missing/nt.h @@ -0,0 +1,246 @@ +#ifndef EXT_NT_H +#define EXT_NT_H + +/* + * Copyright (c) 1993, Intergraph Corporation + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the perl README file. + * + */ + +// +// Definitions for NT port of Perl +// + +// +// GRRRR!!!! Windows Nonsense. +// Define the following so we don't get tons of extra stuff +// when we include windows.h +// + +#define NOGDICAPMASKS +#define NOVIRTUALKEYCODES +#define NOWINMESSAGES +#define NOWINSTYLES +#define NOSYSMETRICS +#define NOMENUS +#define NOICONS +#define NOKEYSTATES +#define NOSYSCOMMANDS +#define NORASTEROPS +#define NOSHOWWINDOW +#define OEMRESOURCE +#define NOATOM +#define NOCLIPBOARD +#define NOCOLOR +#define NOCTLMGR +#define NODRAWTEXT +#define NOGDI +//#define NOKERNEL +//#define NOUSER +#define NONLS +#define NOMB +#define NOMEMMGR +#define NOMETAFILE +#define NOMINMAX +#define NOMSG +#define NOOPENFILE +#define NOSCROLL +#define NOSERVICE +#define NOSOUND +#define NOTEXTMETRIC +#define NOWH +#define NOWINOFFSETS +#define NOCOMM +#define NOKANJI +#define NOHELP +#define NOPROFILER +#define NODEFERWINDOWPOS + + +// +// Ok now we can include the normal include files. +// + +#include <stdarg.h> +#include <windows.h> +// +// We\'re not using Microsoft\'s "extensions" to C for +// Structured Exception Handling (SEH) so we can nuke these +// +#undef try +#undef except +#undef finally +#undef leave +#include <winsock.h> +#include <sys/types.h> +#include <direct.h> +#include <process.h> +#include <io.h> +#include <time.h> +#include <sys/utime.h> + +// +// Grrr... +// + +#define access _access +#define chmod _chmod +#define chsize _chsize +#define close _close +#define creat _creat +#define dup _dup +#define dup2 _dup2 +#define eof _eof +#define filelength _filelength +#define isatty _isatty +#define locking _locking +#define lseek _lseek +#define mktemp _mktemp +#define open _open +#define read _read +#define setmode _setmode +#define sopen _sopen +#define tell _tell +#define umask _umask +#define unlink _unlink +#define write _write +#define execl _execl +#define execle _execle +#define execlp _execlp +#define execlpe _execlpe +#define execv _execv +#define execve _execve +#define execvp _execvp +#define execvpe _execvpe +#define getpid _getpid +#define spawnl _spawnl +#define spawnle _spawnle +#define spawnlp _spawnlp +#define spawnlpe _spawnlpe +#define spawnv _spawnv +#define spawnve _spawnve +#define spawnvp _spawnvp +#define spawnvpe _spawnvpe +#if _MSC_VER < 800 +#define fileno _fileno +#endif +#define utime _utime +#define pipe _pipe + +#define popen mypopen +#define pclose mypclose + +/* these are defined in nt.c */ + +extern int NtMakeCmdVector(char *, char ***, int); +extern void NtInitialize(int *, char ***); + +extern char *NtGetLib(void); +extern char *NtGetBin(void); + +// +// define this so we can do inplace editing +// + +#define SUFFIX + +// +// stubs +// +extern int ioctl (int, unsigned int, char *); +#if 0 +extern void sleep (unsigned int); +#else +#define sleep(x) Sleep(x*1000) +#endif + +extern UIDTYPE getuid (void); +extern UIDTYPE geteuid (void); +extern GIDTYPE getgid (void); +extern GIDTYPE getegid (void); +extern int setuid (int); +extern int setgid (int); + + +// +// Got the idea and some of the code from the MSDOS implementation +// + +/* + * (C) Copyright 1987, 1990 Diomidis Spinellis. + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + * + * Included in the nt header file for use by nt port + * + * $Log: dir.h,v $ + * Revision 4.0.1.1 91/06/07 11:22:10 lwall + * patch4: new copyright notice + * + * Revision 4.0 91/03/20 01:34:20 lwall + * 4.0 baseline. + * + * Revision 3.0.1.1 90/03/27 16:07:08 lwall + * patch16: MSDOS support + * + * Revision 1.1 90/03/18 20:32:29 dds + * Initial revision + * + * + */ +/* + * defines the type returned by the directory(3) functions + */ + +/*Directory entry size */ +#ifdef DIRSIZ +#undef DIRSIZ +#endif +#define DIRSIZ(rp) (sizeof(struct direct)) + +/* need this so that directory stuff will compile! */ +#define DIRENT direct + +/* + * Structure of a directory entry + */ +struct direct { + ino_t d_ino; /* inode number (not used by MS-DOS) */ + int d_namlen; /* Name length */ + char d_name[257]; /* file name */ +}; + +struct _dir_struc { /* Structure used by dir operations */ + char *start; /* Starting position */ + char *curr; /* Current position */ + long size; /* Size of string table */ + long nfiles; /* number if filenames in table */ + struct direct dirstr; /* Directory structure to return */ +}; + +typedef struct _dir_struc DIR; /* Type returned by dir operations */ + +DIR *cdecl opendir(char *filename); +struct direct *readdir(DIR *dirp); +long telldir(DIR *dirp); +void seekdir(DIR *dirp,long loc); +void rewinddir(DIR *dirp); +void closedir(DIR *dirp); + +extern int sys_nerr; +extern char *sys_errlist[]; +extern char *mystrerror(int); + +#define strerror(e) mystrerror(e) + +#define PIPE_BUF 1024 + +#define HAVE_STDLIB_H 1 +#define HAVE_GETLOGIN 1 +#define HAVE_WAITPID 1 +#define HAVE_GETCWD 1 + +#endif diff --git a/missing/setenv.c b/missing/setenv.c new file mode 100644 index 0000000000..6211bcf02b --- /dev/null +++ b/missing/setenv.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1991, Larry Wall + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + */ + +#include "ruby.h" + +extern char **environ; +extern char **origenviron; + +char *strdup(); + +int +envix(nam) +char *nam; +{ + register int i, len = strlen(nam); + + for (i = 0; environ[i]; i++) { + if (memcmp(environ[i],nam,len) && environ[i][len] == '=') + break; /* strnEQ must come first to avoid */ + } /* potential SEGV's */ + return i; +} + +void +setenv(nam,val) +char *nam, *val; +{ + register int i=envix(nam); /* where does it go? */ + + if (environ == origenviron) { /* need we copy environment? */ + int j; + int max; + char **tmpenv; + + /*SUPPRESS 530*/ + for (max = i; environ[max]; max++) ; + tmpenv = ALLOC_N(char*, max+2); + for (j=0; j<max; j++) /* copy environment */ + tmpenv[j] = strdup(environ[j]); + tmpenv[max] = 0; + environ = tmpenv; /* tell exec where it is now */ + } + if (!val) { + while (environ[i]) { + environ[i] = environ[i+1]; + i++; + } + return; + } + if (!environ[i]) { /* does not exist yet */ + REALLOC_N(environ, char*, i+2); /* just expand it a bit */ + environ[i+1] = 0; /* make sure it's null terminated */ + } + else { + free(environ[i]); + } + environ[i] = ALLOC_N(char, strlen(nam) + strlen(val) + 2); +#ifndef MSDOS + (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */ +#else + /* MS-DOS requires environment variable names to be in uppercase */ + /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but + * some utilities and applications may break because they only look + * for upper case strings. (Fixed strupr() bug here.)] + */ + strcpy(environ[i],nam); strupr(environ[i]); + (void)sprintf(environ[i] + strlen(nam),"=%s",val); +#endif /* MSDOS */ +} @@ -13,6 +13,8 @@ #ifndef NODE_H #define NODE_H +struct global_entry* rb_global_entry(); + enum node_type { NODE_METHOD, NODE_FBODY, @@ -32,6 +34,7 @@ enum node_type { NODE_NOT, NODE_MASGN, NODE_LASGN, + NODE_DASGN, NODE_GASGN, NODE_IASGN, NODE_CASGN, @@ -52,12 +55,13 @@ enum node_type { NODE_FAIL, NODE_YIELD, NODE_LVAR, - NODE_LVAR2, + NODE_DVAR, NODE_GVAR, NODE_IVAR, NODE_CVAR, NODE_CONST, NODE_NTH_REF, + NODE_BACK_REF, NODE_LIT, NODE_STR, NODE_STR2, @@ -71,11 +75,16 @@ enum node_type { NODE_UNDEF, NODE_CLASS, NODE_MODULE, + NODE_COLON2, NODE_CREF, + NODE_DOT2, NODE_DOT3, + NODE_FLIP2, + NODE_FLIP3, NODE_ATTRSET, NODE_SELF, NODE_NIL, + NODE_DEFINED, }; typedef struct RNode { @@ -148,6 +157,7 @@ typedef struct RNode { #define nd_frml u1.node #define nd_rest u2.argc +#define nd_opt u1.node #define nd_recv u1.node #define nd_mid u2.id @@ -206,19 +216,21 @@ typedef struct RNode { #define NEW_AND(a,b) newnode(NODE_AND,a,b,0) #define NEW_OR(a,b) newnode(NODE_OR,a,b,0) #define NEW_NOT(a) newnode(NODE_NOT,0,a,0) -#define NEW_MASGN(l,r) newnode(NODE_MASGN,l,r,0) +#define NEW_MASGN(l,r) newnode(NODE_MASGN,l,0,r) #define NEW_GASGN(v,val) newnode(NODE_GASGN,v,val,rb_global_entry(v)) #define NEW_LASGN(v,val) newnode(NODE_LASGN,v,val,local_cnt(v)) +#define NEW_DASGN(v,val) newnode(NODE_DASGN,v,val,0); #define NEW_IASGN(v,val) newnode(NODE_IASGN,v,val,0) #define NEW_CASGN(v,val) newnode(NODE_CASGN,v,val,0) #define NEW_OP_ASGN1(p,id,a) newnode(NODE_OP_ASGN1,p,id,a) #define NEW_OP_ASGN2(r,i,val) newnode(NODE_OP_ASGN1,r,val,i) #define NEW_GVAR(v) newnode(NODE_GVAR,v,0,rb_global_entry(v)) #define NEW_LVAR(v) newnode(NODE_LVAR,v,0,local_cnt(v)) -#define NEW_LVAR2(v) newnode(NODE_LVAR2,v,0,0) +#define NEW_DVAR(v) newnode(NODE_DVAR,v,0,0); #define NEW_IVAR(v) newnode(NODE_IVAR,v,0,0) #define NEW_CVAR(v) newnode(NODE_CVAR,v,0,cref_list) -#define NEW_NTH_REF(n) newnode(NODE_NTH_REF,0,n,0) +#define NEW_NTH_REF(n) newnode(NODE_NTH_REF,0,n,local_cnt('~')) +#define NEW_BACK_REF(n) newnode(NODE_BACK_REF,0,n,local_cnt('~')) #define NEW_LIT(l) newnode(NODE_LIT,l,0,0) #define NEW_STR(s) newnode(NODE_STR,s,0,0) #define NEW_STR2(s) newnode(NODE_STR2,s,0,0) @@ -228,20 +240,26 @@ typedef struct RNode { #define NEW_FCALL(m,a) newnode(NODE_FCALL,0,m,a) #define NEW_SUPER(a) newnode(NODE_SUPER,0,0,a) #define NEW_ZSUPER() newnode(NODE_ZSUPER,0,0,0) -#define NEW_ARGS(f,r) newnode(NODE_ARGS,0,r,f) +#define NEW_ARGS(f,o,r) newnode(NODE_ARGS,o,r,f) #define NEW_ALIAS(n,o) newnode(NODE_ALIAS,0,n,o) #define NEW_UNDEF(i) newnode(NODE_UNDEF,0,i,0) #define NEW_CLASS(n,b,s) newnode(NODE_CLASS,n,NEW_CBODY(b),s) #define NEW_MODULE(n,b) newnode(NODE_MODULE,n,NEW_CBODY(b),0) +#define NEW_COLON2(c,i) newnode(NODE_COLON2,c,i,0) #define NEW_CREF0() (cref_list=newnode(NODE_CREF,the_class,0,0)) #define NEW_CREF(b) (cref_list=newnode(NODE_CREF,0,0,cref_list)) #define NEW_CBODY(b) (cref_list->nd_body=NEW_SCOPE(b),cref_list) +#define NEW_DOT2(b,e) newnode(NODE_DOT2,b,e,0) #define NEW_DOT3(b,e) newnode(NODE_DOT3,b,e,0) #define NEW_ATTRSET(a) newnode(NODE_ATTRSET,a,0,0) #define NEW_SELF() newnode(NODE_SELF,0,0,0) #define NEW_NIL() newnode(NODE_NIL,0,0,0) +#define NEW_DEFINED(e) newnode(NODE_DEFINED,e,0,0) NODE *newnode(); VALUE rb_method_booundp(); +#define NOEX_PUBLIC 0 +#define NOEX_PRIVATE 1 + #endif @@ -11,17 +11,17 @@ ************************************************/ #include "ruby.h" -#include "env.h" #include <math.h> static ID coerce; static ID to_i; -VALUE C_Numeric; -VALUE C_Float; -VALUE C_Integer; -VALUE C_Fixnum; +VALUE cNumeric; +VALUE cFloat; +VALUE cInteger; +VALUE cFixnum; +ID rb_frame_last_func(); double big2dbl(); VALUE @@ -29,45 +29,36 @@ float_new(d) double d; { NEWOBJ(flt, struct RFloat); - OBJSETUP(flt, C_Float, T_FLOAT); + OBJSETUP(flt, cFloat, T_FLOAT); flt->value = d; return (VALUE)flt; } -static +static VALUE num_coerce_bin(x, y) VALUE x, y; { return rb_funcall(rb_funcall(y, coerce, 1, x), - the_env->last_func, 1, y); + rb_frame_last_func(), 1, y); } static VALUE -Fnum_uplus(num) +num_uplus(num) VALUE num; { return num; } static VALUE -Fnum_uminus(num) +num_uminus(num) VALUE num; { return rb_funcall(rb_funcall(num, coerce, 1, INT2FIX(0)), 1, num); } static VALUE -Fnum_dot2(left, right) - VALUE left, right; -{ - Need_Fixnum(left); - Need_Fixnum(right); - return range_new(left, right); -} - -static VALUE -Fnum_next(num) +num_next(num) VALUE num; { num = rb_funcall(num, rb_intern("to_i"), 0); @@ -75,7 +66,7 @@ Fnum_next(num) } VALUE -Fnum_upto(from, to) +num_upto(from, to) VALUE from, to; { int i, end; @@ -89,7 +80,7 @@ Fnum_upto(from, to) } static VALUE -Fnum_downto(from, to) +num_downto(from, to) VALUE from, to; { int i, end; @@ -103,8 +94,8 @@ Fnum_downto(from, to) } static VALUE -Fnum_step(from, to, step) - VALUE from, to; +num_step(from, to, step) + VALUE from, to, step; { int i, end, diff; @@ -128,7 +119,7 @@ Fnum_step(from, to, step) } static VALUE -Fnum_dotimes(num) +num_dotimes(num) VALUE num; { int i, end; @@ -141,7 +132,7 @@ Fnum_dotimes(num) } static VALUE -Fnum_divmod(x, y) +num_divmod(x, y) VALUE x, y; { VALUE div, mod; @@ -159,14 +150,14 @@ Fnum_divmod(x, y) } static VALUE -Fnum_is_int(num) +num_int_p(num) VALUE num; { return FALSE; } static VALUE -Fnum_chr(num) +num_chr(num) VALUE num; { char c; @@ -179,7 +170,7 @@ Fnum_chr(num) } static VALUE -Fflo_to_s(flt) +flo_to_s(flt) struct RFloat *flt; { char buf[32]; @@ -190,7 +181,7 @@ Fflo_to_s(flt) } static VALUE -Fflo_coerce(x, y) +flo_coerce(x, y) VALUE x, y; { switch (TYPE(y)) { @@ -199,7 +190,7 @@ Fflo_coerce(x, y) case T_FLOAT: return y; case T_BIGNUM: - return Fbig_to_f(y); + return big_to_f(y); default: Fail("can't coerce %s to Float", rb_class2name(CLASS_OF(y))); } @@ -208,14 +199,14 @@ Fflo_coerce(x, y) } static VALUE -Fflo_uminus(flt) +flo_uminus(flt) struct RFloat *flt; { return float_new(-flt->value); } static VALUE -Fflo_plus(x, y) +flo_plus(x, y) struct RFloat *x, *y; { switch (TYPE(y)) { @@ -226,14 +217,14 @@ Fflo_plus(x, y) case T_FLOAT: return float_new(x->value + y->value); case T_STRING: - return Fstr_plus(obj_as_string(x), y); + return str_plus(obj_as_string(x), y); default: return num_coerce_bin(x, y); } } static VALUE -Fflo_minus(x, y) +flo_minus(x, y) struct RFloat *x, *y; { switch (TYPE(y)) { @@ -249,7 +240,7 @@ Fflo_minus(x, y) } static VALUE -Fflo_mul(x, y) +flo_mul(x, y) struct RFloat *x, *y; { switch (TYPE(y)) { @@ -260,14 +251,14 @@ Fflo_mul(x, y) case T_FLOAT: return float_new(x->value * y->value); case T_STRING: - return Fstr_times(y, INT2FIX((int)x->value)); + return str_times(y, INT2FIX((int)x->value)); default: return num_coerce_bin(x, y); } } static VALUE -Fflo_div(x, y) +flo_div(x, y) struct RFloat *x, *y; { int f_y; @@ -291,7 +282,7 @@ Fflo_div(x, y) } static VALUE -Fflo_mod(x, y) +flo_mod(x, y) struct RFloat *x, *y; { double value; @@ -326,7 +317,8 @@ Fflo_mod(x, y) return float_new(value); } -Fflo_pow(x, y) +VALUE +flo_pow(x, y) struct RFloat *x, *y; { switch (TYPE(y)) { @@ -341,8 +333,34 @@ Fflo_pow(x, y) } } +struct xy { + VALUE x, y; +}; + +static VALUE +eq(arg) + struct xy *arg; +{ + return rb_funcall(arg->y, rb_intern("=="), 1, arg->x); +} + +static VALUE +eq_rescue() +{ + return FALSE; +} + static VALUE -Fflo_eq(x, y) +num_equal(x, y) + VALUE x, y; +{ + struct xy arg; + arg.x = x; arg.y = y; + return rb_rescue(eq, &arg, eq_rescue, Qnil); +} + +static VALUE +flo_eq(x, y) struct RFloat *x, *y; { switch (TYPE(y)) { @@ -356,12 +374,12 @@ Fflo_eq(x, y) case T_FLOAT: return (x->value == y->value)?TRUE:FALSE; default: - return num_coerce_bin(x, y); + return num_equal(x, y); } } static VALUE -Fflo_hash(num) +flo_hash(num) struct RFloat *num; { double d; @@ -378,7 +396,7 @@ Fflo_hash(num) } static VALUE -Fflo_cmp(x, y) +flo_cmp(x, y) struct RFloat *x, *y; { double a, b; @@ -406,7 +424,7 @@ Fflo_cmp(x, y) } static VALUE -Fflo_to_i(num) +flo_to_i(num) struct RFloat *num; { double f = num->value; @@ -420,14 +438,14 @@ Fflo_to_i(num) } static VALUE -Fflo_to_f(num) +flo_to_f(num) VALUE num; { return num; } static VALUE -Fflo_abs(flt) +flo_abs(flt) struct RFloat *flt; { double val = fabs(flt->value); @@ -457,7 +475,6 @@ num2int(val) switch (TYPE(val)) { case T_FIXNUM: return FIX2INT(val); - break; case T_FLOAT: if (RFLOAT(val)->value <= (double) LONG_MAX @@ -466,14 +483,14 @@ num2int(val) } else { Fail("float %g out of rang of integer", RFLOAT(val)->value); + return Qnil; /* not reached */ } - break; case T_BIGNUM: return big2int(val); default: - val = rb_resque(to_integer, val, fail_to_integer, val); + val = rb_rescue(to_integer, val, fail_to_integer, val); return NUM2INT(val); } } @@ -500,14 +517,14 @@ num2fix(val) } static VALUE -Fint_is_int(num) +int_int_p(num) VALUE num; { return TRUE; } static VALUE -Ffix_uminus(num) +fix_uminus(num) VALUE num; { return int2inum(-FIX2INT(num)); @@ -531,14 +548,14 @@ fix2str(x, base) } VALUE -Ffix_to_s(in) +fix_to_s(in) VALUE in; { return fix2str(in, 10); } static VALUE -Ffix_plus(x, y) +fix_plus(x, y) VALUE x; struct RFloat *y; { @@ -554,7 +571,7 @@ Ffix_plus(x, y) r = INT2FIX(c); if (FIX2INT(r) != c) { - r = Fbig_plus(int2big(a), int2big(b)); + r = big_plus(int2big(a), int2big(b)); } return r; } @@ -566,7 +583,7 @@ Ffix_plus(x, y) } static VALUE -Ffix_minus(x, y) +fix_minus(x, y) VALUE x; struct RFloat *y; { @@ -582,7 +599,7 @@ Ffix_minus(x, y) r = INT2FIX(c); if (FIX2INT(r) != c) { - r = Fbig_minus(int2big(a), int2big(b)); + r = big_minus(int2big(a), int2big(b)); } return r; } @@ -594,7 +611,7 @@ Ffix_minus(x, y) } static VALUE -Ffix_mul(x, y) +fix_mul(x, y) VALUE x; struct RFloat *y; { @@ -606,7 +623,7 @@ Ffix_mul(x, y) VALUE r = INT2FIX(c); if (FIX2INT(r) != c) { - r = Fbig_mul(int2big(a), int2big(b)); + r = big_mul(int2big(a), int2big(b)); } return r; } @@ -618,7 +635,7 @@ Ffix_mul(x, y) } static VALUE -Ffix_div(x, y) +fix_div(x, y) VALUE x; struct RFloat *y; { @@ -634,10 +651,10 @@ Ffix_div(x, y) } static VALUE -Ffix_mod(x, y) +fix_mod(x, y) VALUE x, y; { - int mod, i; + int i; if (TYPE(y) == T_FIXNUM) { i = FIX2INT(y); @@ -649,7 +666,7 @@ Ffix_mod(x, y) } static VALUE -Ffix_pow(x, y) +fix_pow(x, y) VALUE x, y; { extern double pow(); @@ -661,7 +678,7 @@ Ffix_pow(x, y) if (b == 0) return INT2FIX(1); a = FIX2INT(x); if (b > 0) { - return Fbig_pow(int2big(a), y); + return big_pow(int2big(a), y); } return float_new(pow((double)a, (double)b)); } @@ -672,7 +689,7 @@ Ffix_pow(x, y) } static VALUE -Ffix_equal(x, y) +fix_equal(x, y) VALUE x, y; { if (FIXNUM_P(y)) { @@ -682,12 +699,12 @@ Ffix_equal(x, y) return Qnil; } else { - return num_coerce_bin(x, y); + return num_equal(x, y); } } static VALUE -Ffix_cmp(x, y) +fix_cmp(x, y) VALUE x, y; { if (FIXNUM_P(y)) { @@ -703,7 +720,7 @@ Ffix_cmp(x, y) } static VALUE -Ffix_gt(x, y) +fix_gt(x, y) VALUE x, y; { if (FIXNUM_P(y)) { @@ -718,7 +735,7 @@ Ffix_gt(x, y) } static VALUE -Ffix_ge(x, y) +fix_ge(x, y) VALUE x, y; { if (FIXNUM_P(y)) { @@ -733,7 +750,7 @@ Ffix_ge(x, y) } static VALUE -Ffix_lt(x, y) +fix_lt(x, y) VALUE x, y; { if (FIXNUM_P(y)) { @@ -748,7 +765,7 @@ Ffix_lt(x, y) } static VALUE -Ffix_le(x, y) +fix_le(x, y) VALUE x, y; { if (FIXNUM_P(y)) { @@ -763,15 +780,7 @@ Ffix_le(x, y) } static VALUE -Ffix_dot2(left, right) - VALUE left, right; -{ - Need_Fixnum(right); - return range_new(left, right); -} - -static VALUE -Ffix_rev(num) +fix_rev(num) VALUE num; { unsigned long val = FIX2UINT(num); @@ -781,46 +790,46 @@ Ffix_rev(num) } static VALUE -Ffix_and(x, y) +fix_and(x, y) VALUE x, y; { long val; if (TYPE(y) == T_BIGNUM) { - return Fbig_and(y, x); + return big_and(y, x); } val = NUM2INT(x) & NUM2INT(y); return int2inum(val); } static VALUE -Ffix_or(x, y) +fix_or(x, y) VALUE x, y; { long val; if (TYPE(y) == T_BIGNUM) { - return Fbig_or(y, x); + return big_or(y, x); } val = NUM2INT(x) | NUM2INT(y); return INT2FIX(val); } static VALUE -Ffix_xor(x, y) +fix_xor(x, y) VALUE x, y; { long val; if (TYPE(y) == T_BIGNUM) { - return Fbig_xor(y, x); + return big_xor(y, x); } val = NUM2INT(x) ^ NUM2INT(y); return INT2FIX(val); } static VALUE -Ffix_lshift(x, y) +fix_lshift(x, y) VALUE x, y; { long val, width; @@ -829,14 +838,14 @@ Ffix_lshift(x, y) width = NUM2INT(y); if (width > (sizeof(VALUE)*CHAR_BIT-1) || (unsigned)val>>(sizeof(VALUE)*CHAR_BIT-width) > 0) { - return Fbig_lshift(int2big(val), y); + return big_lshift(int2big(val), y); } val = val << width; return int2inum(val); } static VALUE -Ffix_rshift(x, y) +fix_rshift(x, y) VALUE x, y; { long val; @@ -846,7 +855,7 @@ Ffix_rshift(x, y) } static VALUE -Ffix_aref(fix, idx) +fix_aref(fix, idx) VALUE fix, idx; { unsigned long val = FIX2INT(fix); @@ -860,14 +869,14 @@ Ffix_aref(fix, idx) } static VALUE -Ffix_to_i(num) +fix_to_i(num) VALUE num; { return num; } static VALUE -Ffix_to_f(num) +fix_to_f(num) VALUE num; { double val; @@ -878,25 +887,25 @@ Ffix_to_f(num) } static VALUE -Ffix_class(fix) +fix_type(fix) VALUE fix; { - return C_Fixnum; + return cFixnum; } -static -Ffix_abs(fix) +static VALUE +fix_abs(fix) VALUE fix; { int i = FIX2INT(fix); - if (fix < 0) i = -i; + if (i < 0) i = -i; - return int2inum(fix); + return int2inum(i); } static VALUE -Ffix_id2name(fix) +fix_id2name(fix) VALUE fix; { char *name = rb_id2name(FIX2UINT(fix)); @@ -905,7 +914,7 @@ Ffix_id2name(fix) } static VALUE -Ffix_next(fix) +fix_next(fix) VALUE fix; { int i = FIX2INT(fix) + 1; @@ -913,91 +922,87 @@ Ffix_next(fix) return int2inum(i); } -extern VALUE M_Comparable; -extern Fkrn_inspect(); +extern VALUE mComparable; +void Init_Numeric() { coerce = rb_intern("coerce"); to_i = rb_intern("to_i"); - C_Numeric = rb_define_class("Numeric", C_Object); - - rb_undef_method(CLASS_OF(C_Numeric), "new"); - rb_undef_method(C_Numeric, "clone"); - - rb_include_module(C_Numeric, M_Comparable); - rb_define_method(C_Numeric, "+@", Fnum_uplus, 0); - rb_define_method(C_Numeric, "-@", Fnum_uminus, 0); - rb_define_method(C_Numeric, "..", Fnum_dot2, 1); - rb_define_method(C_Numeric, "divmod", Fnum_divmod, 1); - - rb_define_method(C_Numeric, "next", Fnum_next, 0); - rb_define_method(C_Numeric, "upto", Fnum_upto, 1); - rb_define_method(C_Numeric, "downto", Fnum_downto, 1); - rb_define_method(C_Numeric, "step", Fnum_step, 2); - rb_define_method(C_Numeric, "times", Fnum_dotimes, 0); - rb_define_method(C_Numeric, "is_integer", Fnum_is_int, 0); - rb_define_method(C_Numeric, "chr", Fnum_chr, 0); - rb_define_method(C_Numeric, "_inspect", Fkrn_inspect, 0); - - C_Integer = rb_define_class("Integer", C_Numeric); - rb_define_method(C_Integer, "is_integer", Fint_is_int, 0); - - C_Fixnum = rb_define_class("Fixnum", C_Integer); - - rb_define_method(C_Fixnum, "to_s", Ffix_to_s, 0); - rb_define_method(C_Fixnum, "class", Ffix_class, 0); - - rb_define_method(C_Fixnum, "id2name", Ffix_id2name, 0); - - rb_define_method(C_Fixnum, "-@", Ffix_uminus, 0); - rb_define_method(C_Fixnum, "+", Ffix_plus, 1); - rb_define_method(C_Fixnum, "-", Ffix_minus, 1); - rb_define_method(C_Fixnum, "*", Ffix_mul, 1); - rb_define_method(C_Fixnum, "/", Ffix_div, 1); - rb_define_method(C_Fixnum, "%", Ffix_mod, 1); - rb_define_method(C_Fixnum, "**", Ffix_pow, 1); - - rb_define_method(C_Fixnum, "abs", Ffix_abs, 0); - - rb_define_method(C_Fixnum, "==", Ffix_equal, 1); - rb_define_method(C_Fixnum, "<=>", Ffix_cmp, 1); - rb_define_method(C_Fixnum, ">", Ffix_gt, 1); - rb_define_method(C_Fixnum, ">=", Ffix_ge, 1); - rb_define_method(C_Fixnum, "<", Ffix_lt, 1); - rb_define_method(C_Fixnum, "<=", Ffix_le, 1); - rb_define_method(C_Fixnum, "..", Ffix_dot2, 1); - - rb_define_method(C_Fixnum, "~", Ffix_rev, 0); - rb_define_method(C_Fixnum, "&", Ffix_and, 1); - rb_define_method(C_Fixnum, "|", Ffix_or, 1); - rb_define_method(C_Fixnum, "^", Ffix_xor, 1); - rb_define_method(C_Fixnum, "[]", Ffix_aref, 1); - - rb_define_method(C_Fixnum, "<<", Ffix_lshift, 1); - rb_define_method(C_Fixnum, ">>", Ffix_rshift, 1); - - rb_define_method(C_Fixnum, "to_i", Ffix_to_i, 0); - rb_define_method(C_Fixnum, "to_f", Ffix_to_f, 0); - - rb_define_method(C_Fixnum, "next", Ffix_next, 0); - - C_Float = rb_define_class("Float", C_Numeric); - - rb_define_method(C_Float, "to_s", Fflo_to_s, 0); - rb_define_method(C_Float, "coerce", Fflo_coerce, 1); - rb_define_method(C_Float, "-@", Fflo_uminus, 0); - rb_define_method(C_Float, "+", Fflo_plus, 1); - rb_define_method(C_Float, "-", Fflo_minus, 1); - rb_define_method(C_Float, "*", Fflo_mul, 1); - rb_define_method(C_Float, "/", Fflo_div, 1); - rb_define_method(C_Float, "%", Fflo_mod, 1); - rb_define_method(C_Float, "**", Fflo_pow, 1); - rb_define_method(C_Float, "==", Fflo_eq, 1); - rb_define_method(C_Float, "<=>", Fflo_cmp, 1); - rb_define_method(C_Float, "hash", Fflo_hash, 0); - rb_define_method(C_Float, "to_i", Fflo_to_i, 0); - rb_define_method(C_Float, "to_f", Fflo_to_f, 0); - rb_define_method(C_Float, "abs", Fflo_abs, 0); + cNumeric = rb_define_class("Numeric", cObject); + + rb_undef_method(CLASS_OF(cNumeric), "new"); + + rb_include_module(cNumeric, mComparable); + rb_define_method(cNumeric, "+@", num_uplus, 0); + rb_define_method(cNumeric, "-@", num_uminus, 0); + rb_define_method(cNumeric, "divmod", num_divmod, 1); + + rb_define_method(cNumeric, "next", num_next, 0); + rb_define_method(cNumeric, "upto", num_upto, 1); + rb_define_method(cNumeric, "downto", num_downto, 1); + rb_define_method(cNumeric, "step", num_step, 2); + rb_define_method(cNumeric, "times", num_dotimes, 0); + rb_define_method(cNumeric, "integer?", num_int_p, 0); + rb_define_method(cNumeric, "chr", num_chr, 0); + + cInteger = rb_define_class("Integer", cNumeric); + rb_define_method(cInteger, "integer?", int_int_p, 0); + + cFixnum = rb_define_class("Fixnum", cInteger); + + rb_define_method(cFixnum, "to_s", fix_to_s, 0); + rb_define_method(cFixnum, "type", fix_type, 0); + + rb_define_method(cFixnum, "id2name", fix_id2name, 0); + + rb_define_method(cFixnum, "-@", fix_uminus, 0); + rb_define_method(cFixnum, "+", fix_plus, 1); + rb_define_method(cFixnum, "-", fix_minus, 1); + rb_define_method(cFixnum, "*", fix_mul, 1); + rb_define_method(cFixnum, "/", fix_div, 1); + rb_define_method(cFixnum, "%", fix_mod, 1); + rb_define_method(cFixnum, "**", fix_pow, 1); + + rb_define_method(cFixnum, "abs", fix_abs, 0); + + rb_define_method(cFixnum, "==", fix_equal, 1); + rb_define_method(cFixnum, "<=>", fix_cmp, 1); + rb_define_method(cFixnum, ">", fix_gt, 1); + rb_define_method(cFixnum, ">=", fix_ge, 1); + rb_define_method(cFixnum, "<", fix_lt, 1); + rb_define_method(cFixnum, "<=", fix_le, 1); + + rb_define_method(cFixnum, "~", fix_rev, 0); + rb_define_method(cFixnum, "&", fix_and, 1); + rb_define_method(cFixnum, "|", fix_or, 1); + rb_define_method(cFixnum, "^", fix_xor, 1); + rb_define_method(cFixnum, "[]", fix_aref, 1); + + rb_define_method(cFixnum, "<<", fix_lshift, 1); + rb_define_method(cFixnum, ">>", fix_rshift, 1); + + rb_define_method(cFixnum, "to_i", fix_to_i, 0); + rb_define_method(cFixnum, "to_f", fix_to_f, 0); + + rb_define_method(cFixnum, "next", fix_next, 0); + + cFloat = rb_define_class("Float", cNumeric); + + rb_define_method(cFloat, "to_s", flo_to_s, 0); + rb_define_method(cFloat, "coerce", flo_coerce, 1); + rb_define_method(cFloat, "-@", flo_uminus, 0); + rb_define_method(cFloat, "+", flo_plus, 1); + rb_define_method(cFloat, "-", flo_minus, 1); + rb_define_method(cFloat, "*", flo_mul, 1); + rb_define_method(cFloat, "/", flo_div, 1); + rb_define_method(cFloat, "%", flo_mod, 1); + rb_define_method(cFloat, "**", flo_pow, 1); + rb_define_method(cFloat, "==", flo_eq, 1); + rb_define_method(cFloat, "<=>", flo_cmp, 1); + rb_define_method(cFloat, "hash", flo_hash, 0); + rb_define_method(cFloat, "to_i", flo_to_i, 0); + rb_define_method(cFloat, "to_f", flo_to_f, 0); + rb_define_method(cFloat, "abs", flo_abs, 0); } @@ -11,53 +11,42 @@ ************************************************/ #include "ruby.h" -#include "env.h" #include "st.h" #include <stdio.h> -VALUE C_Kernel; -VALUE C_Object; -VALUE C_Module; -VALUE C_Class; -VALUE C_Nil; -VALUE C_Data; +VALUE cKernel; +VALUE cObject; +VALUE cModule; +VALUE cClass; +VALUE cNil; +VALUE cData; struct st_table *new_idhash(); -VALUE Fsprintf(); +VALUE f_sprintf(); -VALUE obj_responds_to(); VALUE obj_alloc(); -static ID eq, match; - -static ID init_object; +static ID eq; static ID init; -static VALUE -P_true(obj) - VALUE obj; +VALUE +rb_equal(obj1, obj2) + VALUE obj1, obj2; { - return TRUE; + return rb_funcall(obj1, eq, 1, obj2); } static VALUE -P_false(obj) +krn_nil_p(obj) VALUE obj; { return FALSE; } -VALUE -rb_equal(obj1, obj2) - VALUE obj1, obj2; -{ - return rb_funcall(obj1, eq, 1, obj2); -} - static VALUE -Fkrn_equal(obj1, obj2) +krn_equal(obj1, obj2) VALUE obj1, obj2; { if (obj1 == obj2) return TRUE; @@ -65,45 +54,71 @@ Fkrn_equal(obj1, obj2) } static VALUE -Fkrn_to_a(obj) +krn_to_a(obj) VALUE obj; { return ary_new3(1, obj); } static VALUE -Fkrn_id(obj) +krn_id(obj) VALUE obj; { return obj | FIXNUM_FLAG; } static VALUE -Fkrn_class(obj) +krn_type(obj) struct RBasic *obj; { return obj->class; } +static VALUE +krn_clone(obj) + VALUE obj; +{ + VALUE clone; + + if (TYPE(obj) != T_OBJECT) { + Fail("can't clone %s", rb_class2name(CLASS_OF(obj))); + } + + clone = obj_alloc(RBASIC(obj)->class); + if (ROBJECT(obj)->iv_tbl) { + ROBJECT(clone)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl); + } + RBASIC(clone)->class = singleton_class_clone(RBASIC(obj)->class); + + return clone; +} + +static VALUE +krn_dup(obj) + VALUE obj; +{ + return rb_funcall(obj, rb_intern("clone"), 0, 0); +} + VALUE -Fkrn_to_s(obj) +krn_to_s(obj) VALUE obj; { char buf[256]; - sprintf(buf, "#<%s: 0x%x>", rb_class2name(CLASS_OF(obj)), obj); + sprintf(buf, "#<%s:0x%x>", rb_class2name(CLASS_OF(obj)), obj); return str_new2(buf); } VALUE -Fkrn_inspect(obj) +krn_inspect(obj) VALUE obj; { - return rb_funcall(obj, rb_intern("to_s"), 0, Qnil); + return rb_funcall(obj, rb_intern("to_s"), 0, 0); } -static -obj_inspect(id, value, str) +static int +inspect_i(id, value, str) ID id; VALUE value; struct RString *str; @@ -120,31 +135,39 @@ obj_inspect(id, value, str) ivname = rb_id2name(id); str_cat(str, ivname, strlen(ivname)); str_cat(str, "=", 1); - str2 = rb_funcall(value, rb_intern("_inspect"), 0, Qnil); + str2 = rb_funcall(value, rb_intern("inspect"), 0, 0); str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); return ST_CONTINUE; } static VALUE -Fobj_inspect(obj) +obj_inspect(obj) struct RObject *obj; { VALUE str; char buf[256]; - if (FIXNUM_P(obj) || !obj->iv_tbl) return Fkrn_to_s(obj); + switch (TYPE(obj)) { + case T_OBJECT: + case T_MODULE: + case T_CLASS: + if (obj->iv_tbl) break; + /* fall through */ + default: + return krn_inspect(obj); + } sprintf(buf, "-<%s: ", rb_class2name(CLASS_OF(obj))); str = str_new2(buf); - st_foreach(obj->iv_tbl, obj_inspect, str); + st_foreach(obj->iv_tbl, inspect_i, str); str_cat(str, ">", 1); return str; } VALUE -obj_is_member_of(obj, c) +obj_is_instance_of(obj, c) VALUE obj, c; { struct RClass *class = (struct RClass*)CLASS_OF(obj); @@ -187,52 +210,42 @@ obj_is_kind_of(obj, c) } static VALUE -Fobj_clone(obj) +obj_initialize(obj) VALUE obj; { - VALUE clone; - - Check_Type(obj, T_OBJECT); - - clone = obj_alloc(RBASIC(obj)->class); - if (ROBJECT(obj)->iv_tbl) { - ROBJECT(clone)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl); - } - RBASIC(clone)->class = single_class_clone(RBASIC(obj)->class); - - return clone; + return Qnil; } static VALUE -Fobj_initialize(obj) - VALUE obj; +obj_s_added(obj, id) + VALUE obj, id; { return Qnil; } static VALUE -Fobj_s_added(obj, id) - VALUE obj, id; +nil_nil_p(obj) + VALUE obj; { - return Qnil; + return TRUE; } static VALUE -Fnil_to_s(obj) +nil_to_s(obj) VALUE obj; { return str_new2("nil"); } static VALUE -Fnil_class(nil) +nil_type(nil) VALUE nil; { - return C_Nil; + return cNil; } static VALUE -Fnil_plus(x, y) +nil_plus(x, y) VALUE x, y; { switch (TYPE(y)) { @@ -250,14 +263,14 @@ Fnil_plus(x, y) } static VALUE -Fmain_to_s(obj) +main_to_s(obj) VALUE obj; { return str_new2("main"); } static VALUE -Ftrue_to_s(obj) +true_to_s(obj) VALUE obj; { return str_new2("t"); @@ -274,7 +287,7 @@ obj_alloc(class) } static VALUE -Fcls_new(argc, argv, class) +mod_new(argc, argv, class) int argc; VALUE *argv; VALUE class; @@ -286,78 +299,65 @@ Fcls_new(argc, argv, class) } static VALUE -Fcls_to_s(class) - VALUE class; +mod_clone(module) + struct RClass *module; { - return str_new2(rb_class2name(class)); + NEWOBJ(clone, struct RClass); + OBJSETUP(clone, CLASS_OF(module), TYPE(module)); + + clone->super = module->super; + clone->m_tbl = st_copy(module->m_tbl); + + return (VALUE)clone; } +char *rb_class2path(); + static VALUE -Fcls_attr(argc, argv, class) - int argc; - VALUE *argv; +mod_to_s(class) VALUE class; { - VALUE name, pub; - - rb_scan_args(argc, argv, "11", &name, &pub); - Check_Type(name, T_STRING); - rb_define_attr(class, RSTRING(name)->ptr, pub); - return Qnil; + return rb_class_path(class); } -void -method_visibility(argc, argv, ex) - int argc; - VALUE *argv; - int ex; +ID +rb_to_id(name) + VALUE name; { - VALUE self = Qself; - int i; - ID id; - - for (i=0; i<argc; i++) { - if (FIXNUM_P(argv[i])) { - id = FIX2INT(argv[i]); - } - else { - Check_Type(argv[i], T_STRING); - id = rb_intern(RSTRING(argv[i])->ptr); - } - rb_export_method(self, id, ex); + if (TYPE(name) == T_STRING) { + return rb_intern(RSTRING(name)->ptr); } + return NUM2INT(name); } static VALUE -Fcls_public(argc, argv) +mod_attr(argc, argv, class) int argc; VALUE *argv; + VALUE class; { - method_visibility(argc, argv, NOEX_PUBLIC); - return Qnil; -} + VALUE name, pub; + ID id; -static VALUE -Fcls_private(argc, argv) - int argc; - VALUE *argv; -{ - method_visibility(argc, argv, NOEX_PRIVATE); + rb_scan_args(argc, argv, "11", &name, &pub); + rb_define_attr(class, rb_to_id(name), pub); return Qnil; } static VALUE -Fcant_clone(obj) - VALUE obj; +mod_public_attr(class, name) + VALUE class, name; { - Fail("can't clone %s", rb_class2name(CLASS_OF(obj))); + rb_define_attr(class, rb_to_id(name), 1); + return Qnil; } static VALUE -Fdata_class(data) - VALUE data; +mod_private_attr(class, name) + VALUE class, name; { - return C_Data; + rb_define_attr(class, rb_to_id(name), 0); + return Qnil; } static @@ -376,21 +376,22 @@ VALUE boot_defclass(name, super) } VALUE TopSelf; -VALUE TRUE = 1; +VALUE TRUE = INT2FIX(1); +void Init_Object() { VALUE metaclass; - C_Kernel = boot_defclass("Kernel", Qnil); - C_Object = boot_defclass("Object", C_Kernel); - C_Module = boot_defclass("Module", C_Object); - C_Class = boot_defclass("Class", C_Module); + cKernel = boot_defclass("Kernel", Qnil); + cObject = boot_defclass("Object", cKernel); + cModule = boot_defclass("Module", cObject); + cClass = boot_defclass("Class", cModule); - metaclass = RBASIC(C_Kernel)->class = single_class_new(C_Class); - metaclass = RBASIC(C_Object)->class = single_class_new(metaclass); - metaclass = RBASIC(C_Module)->class = single_class_new(metaclass); - metaclass = RBASIC(C_Class)->class = single_class_new(metaclass); + metaclass = RBASIC(cKernel)->class = singleton_class_new(cClass); + metaclass = RBASIC(cObject)->class = singleton_class_new(metaclass); + metaclass = RBASIC(cModule)->class = singleton_class_new(metaclass); + metaclass = RBASIC(cClass)->class = singleton_class_new(metaclass); /* * Ruby's Class Hierarchy Chart @@ -423,63 +424,60 @@ Init_Object() */ - rb_define_method(C_Kernel, "is_nil", P_false, 0); - rb_define_method(C_Kernel, "==", Fkrn_equal, 1); - rb_define_alias(C_Kernel, "equal", "=="); - rb_define_method(C_Kernel, "hash", Fkrn_id, 0); - rb_define_method(C_Kernel, "id", Fkrn_id, 0); - rb_define_method(C_Kernel, "class", Fkrn_class, 0); - rb_define_alias(C_Kernel, "=~", "=="); + rb_define_method(cKernel, "nil?", krn_nil_p, 0); + rb_define_method(cKernel, "==", krn_equal, 1); + rb_define_alias(cKernel, "equal?", "=="); + rb_define_alias(cKernel, "=~", "=="); - rb_define_method(C_Kernel, "to_a", Fkrn_to_a, 0); - rb_define_method(C_Kernel, "to_s", Fkrn_to_s, 0); - rb_define_method(C_Kernel, "_inspect", Fkrn_inspect, 0); + rb_define_method(cKernel, "hash", krn_id, 0); + rb_define_method(cKernel, "id", krn_id, 0); + rb_define_method(cKernel, "type", krn_type, 0); - rb_define_private_method(C_Kernel, "sprintf", Fsprintf, -1); - rb_define_alias(C_Kernel, "format", "sprintf"); + rb_define_method(cKernel, "clone", krn_clone, 0); + rb_define_method(cKernel, "dup", krn_dup, 0); - rb_define_private_method(C_Object, "initialize", Fobj_initialize, -1); - rb_define_private_method(C_Object, "single_method_added", Fobj_s_added, 1); + rb_define_method(cKernel, "to_a", krn_to_a, 0); + rb_define_method(cKernel, "to_s", krn_to_s, 0); + rb_define_method(cKernel, "inspect", krn_inspect, 0); - rb_define_method(C_Object, "clone", Fobj_clone, 0); + rb_define_private_method(cKernel, "sprintf", f_sprintf, -1); + rb_define_alias(cKernel, "format", "sprintf"); - rb_define_method(C_Object, "responds_to", obj_responds_to, 1); - rb_define_method(C_Object, "is_member_of", obj_is_member_of, 1); - rb_define_method(C_Object, "is_kind_of", obj_is_kind_of, 1); - rb_define_method(C_Object, "clone", Fobj_clone, 0); + rb_define_private_method(cObject, "initialize", obj_initialize, -1); + rb_define_private_method(cObject, "singleton_method_added", obj_s_added, 1); - rb_define_method(C_Module, "to_s", Fcls_to_s, 0); - rb_define_method(C_Module, "clone", Fcant_clone, 0); - rb_define_private_method(C_Module, "attr", Fcls_attr, -1); + rb_define_method(cObject, "is_instance_of?", obj_is_instance_of, 1); + rb_define_method(cObject, "is_kind_of?", obj_is_kind_of, 1); + rb_define_method(cObject, "inspect", obj_inspect, 0); - rb_define_method(C_Module, "public", Fcls_public, -1); - rb_define_method(C_Module, "private", Fcls_private, -1); + rb_define_method(cModule, "to_s", mod_to_s, 0); + rb_define_method(cModule, "clone", mod_clone, 0); + rb_define_private_method(cModule, "attr", mod_attr, -1); + rb_define_private_method(cModule, "public_attr", mod_public_attr, -1); + rb_define_private_method(cModule, "private_attr", mod_private_attr, -1); - rb_define_method(C_Class, "new", Fcls_new, -1); + rb_define_method(cClass, "new", mod_new, -1); - C_Nil = rb_define_class("Nil", C_Kernel); - rb_define_method(C_Nil, "to_s", Fnil_to_s, 0); - rb_define_method(C_Nil, "clone", P_false, 0); - rb_define_method(C_Nil, "class", Fnil_class, 0); + cNil = rb_define_class("Nil", cKernel); + rb_define_method(cNil, "to_s", nil_to_s, 0); + rb_define_method(cNil, "type", nil_type, 0); - rb_define_method(C_Nil, "is_nil", P_true, 0); + rb_define_method(cNil, "nil?", nil_nil_p, 0); /* default addition */ - rb_define_method(C_Nil, "+", Fnil_plus, 1); + rb_define_method(cNil, "+", nil_plus, 1); - C_Data = rb_define_class("Data", C_Kernel); - rb_define_method(C_Data, "clone", Fcant_clone, 0); - rb_define_method(C_Data, "class", Fdata_class, 0); + cData = rb_define_class("Data", cKernel); eq = rb_intern("=="); - Qself = TopSelf = obj_alloc(C_Object); - rb_define_single_method(TopSelf, "to_s", Fmain_to_s, 0); + Qself = TopSelf = obj_alloc(cObject); + rb_define_singleton_method(TopSelf, "to_s", main_to_s, 0); - TRUE = obj_alloc(C_Object); - rb_define_single_method(TRUE, "to_s", Ftrue_to_s, 0); - rb_define_const(C_Kernel, "TRUE", TRUE); - rb_define_const(C_Kernel, "FALSE", FALSE); + TRUE = obj_alloc(cObject); + rb_define_singleton_method(TRUE, "to_s", true_to_s, 0); + rb_define_const(cKernel, "TRUE", TRUE); + rb_define_const(cKernel, "FALSE", FALSE); init = rb_intern("initialize"); } @@ -39,7 +39,7 @@ #define vtohl(x) (x) #endif -extern VALUE C_String, C_Array; +extern VALUE cString, cArray; double atof(); static char *toofew = "too few arguments"; @@ -48,7 +48,7 @@ int strtoul(); static void encodes(); static VALUE -Fpck_pack(ary, fmt) +pack_pack(ary, fmt) struct RArray *ary; struct RString *fmt; { @@ -70,7 +70,7 @@ Fpck_pack(ary, fmt) items = ary->len; idx = 0; -#define NEXTFROM (items-- > 0 ? ary->ptr[idx++] : Fail(toofew)) +#define NEXTFROM (items-- > 0 ? ary->ptr[idx++] : (Fail(toofew),0)) while (p < pend) { type = *p++; /* get data type */ @@ -92,7 +92,7 @@ Fpck_pack(ary, fmt) case 'H': case 'h': from = NEXTFROM; if (from == Qnil) { - ptr = Qnil; + ptr = 0; plen = 0; } else { @@ -110,7 +110,7 @@ Fpck_pack(ary, fmt) str_cat(res, ptr, len); else { str_cat(res, ptr, plen); - len == plen; + len = plen; while (len >= 10) { str_cat(res, nul10, 10); len -= 10; @@ -124,7 +124,7 @@ Fpck_pack(ary, fmt) str_cat(res, ptr, len); else { str_cat(res, ptr, plen); - len == plen; + len = plen; while (len >= 10) { str_cat(res, spc10, 10); len -= 10; @@ -479,7 +479,7 @@ encodes(str, s, len) } static VALUE -Fpck_unpack(str, fmt) +pack_unpack(str, fmt) struct RString *str, *fmt; { static char *hexdigits = "0123456789abcdef0123456789ABCDEFx"; @@ -498,7 +498,6 @@ Fpck_unpack(str, fmt) ary = ary_new(); while (p < pend) { - retry: type = *p++; if (*p == '*') { len = send - s; @@ -840,8 +839,9 @@ Fpck_unpack(str, fmt) return ary; } +void Init_pack() { - rb_define_method(C_Array, "pack", Fpck_pack, 1); - rb_define_method(C_String, "unpack", Fpck_unpack, 1); + rb_define_method(cArray, "pack", pack_pack, 1); + rb_define_method(cString, "unpack", pack_unpack, 1); } @@ -24,21 +24,27 @@ # undef const #endif -#include "ident.h" +#define ID_SCOPE_SHIFT 3 +#define ID_SCOPE_MASK 0x07 +#define ID_LOCAL 0x00 +#define ID_INSTANCE 0x01 +#define ID_GLOBAL 0x02 +#define ID_ATTRSET 0x03 +#define ID_CONST 0x04 + #define is_id_nonop(id) ((id)>LAST_TOKEN) #define is_local_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL) #define is_global_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL) #define is_instance_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE) #define is_attrset_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET) #define is_const_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_CONST) -#define is_nthref_id(id) (((id)&ID_SCOPE_MASK)==ID_NTHREF) struct op_tbl { ID token; char *name; }; -NODE *eval_tree = Qnil; +NODE *eval_tree = 0; char *sourcefile; /* current source file */ int sourceline; /* current line no. */ @@ -49,16 +55,16 @@ static enum lex_state { EXPR_BEG, /* ignore newline, +/- is a sign. */ EXPR_MID, /* newline significant, +/- is a sign. */ EXPR_END, /* newline significant, +/- is a operator. */ + EXPR_ARG, /* newline significant, +/- is a sign(meybe). */ EXPR_FNAME, /* ignore newline, +/- is a operator. */ } lex_state; static int class_nest = 0; static int in_single = 0; -static ID cur_mid = Qnil; +static ID cur_mid = 0; static int value_expr(); static NODE *cond(); -static NODE *cond2(); static NODE *block_append(); static NODE *list_append(); @@ -66,11 +72,13 @@ static NODE *list_concat(); static NODE *list_copy(); static NODE *expand_op(); static NODE *call_op(); +static int in_defined = 0; static NODE *gettable(); static NODE *asignable(); static NODE *aryset(); static NODE *attrset(); +static void backref_error(); static void local_push(); static void local_pop(); @@ -78,12 +86,17 @@ static int local_cnt(); static int local_id(); static ID *local_tbl(); +static struct RVarmap *dyna_push(); +static void dyna_pop(); +static int dyna_in_block(); + +VALUE dyna_var_ref(); +#define dyna_id(id) dyna_var_ref(id) + #define cref_push() NEW_CREF(0) static void cref_pop(); static NODE *cref_list; -struct global_entry* rb_global_entry(); - static void top_local_init(); static void top_local_setup(); %} @@ -93,6 +106,7 @@ static void top_local_setup(); VALUE val; ID id; int num; + struct RVarmap *vars; } %token CLASS @@ -100,7 +114,7 @@ static void top_local_setup(); DEF UNDEF BEGIN - RESQUE + RESCUE ENSURE END IF @@ -124,24 +138,27 @@ static void top_local_setup(); NIL AND OR + NOT _FILE_ _LINE_ IF_MOD WHILE_MOD ALIAS + DEFINED -%token <id> IDENTIFIER GVAR IVAR CONSTANT NTH_REF +%token <id> IDENTIFIER FID GVAR IVAR CONSTANT %token <val> INTEGER FLOAT STRING XSTRING REGEXP -%token <node> STRING2 XSTRING2 DREGEXP +%token <node> STRING2 XSTRING2 DREGEXP NTH_REF BACK_REF %type <node> singleton %type <val> literal numeric %type <node> compexpr exprs expr arg primary var_ref -%type <node> if_tail opt_else case_body cases resque ensure +%type <node> if_tail opt_else case_body cases rescue ensure %type <node> call_args call_args0 args args2 opt_args -%type <node> f_arglist f_args array assoc_list assocs assoc -%type <node> mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var -%type <id> superclass variable symbol +%type <node> superclass f_arglist f_args f_optarg f_opt +%type <node> array assoc_list assocs assoc undef_list +%type <node> mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var backref +%type <id> variable symbol operation %type <id> cname fname op rest_arg %type <num> f_arg %token UPLUS /* unary+ */ @@ -160,7 +177,10 @@ static void top_local_setup(); %token COLON2 /* :: */ %token <id> OP_ASGN /* +=, -= etc. */ %token ASSOC /* => */ -%token LPAREN LBRACK LBRACE +%token LPAREN /* ( */ +%token LBRACK /* [ */ +%token LBRACE /* { */ +%token STAR /* * */ %token SYMBEG /* @@ -168,10 +188,9 @@ static void top_local_setup(); */ %left IF_MOD WHILE_MOD +%right NOT %left OR AND -%left YIELD RETURN FAIL %right '=' OP_ASGN -%right COLON2 %nonassoc DOT2 DOT3 %left OROP %left ANDOP @@ -184,6 +203,7 @@ static void top_local_setup(); %left '*' '/' '%' %right '!' '~' UPLUS UMINUS %right POW +%left COLON2 %token LAST_TOKEN @@ -246,24 +266,29 @@ expr : mlhs '=' args2 value_expr($2); $$ = NEW_YIELD($2); } - | IDENTIFIER call_args0 + | DEFINED {in_defined = 1;} arg + { + in_defined = 0; + $$ = NEW_DEFINED($3); + } + | operation call_args0 { $$ = NEW_FCALL($1, $2); } - | primary '.' IDENTIFIER call_args0 + | primary '.' operation call_args0 { value_expr($1); $$ = NEW_CALL($1, $3, $4); } | SUPER call_args0 { - if (!cur_mid && !in_single) + if (!cur_mid && !in_single && !in_defined) Error("super called outside of method"); $$ = NEW_SUPER($2); } - | UNDEF fname + | UNDEF undef_list { - $$ = NEW_UNDEF($2); + $$ = $2; } | ALIAS fname {lex_state = EXPR_FNAME;} fname { @@ -271,27 +296,41 @@ expr : mlhs '=' args2 } | expr IF_MOD expr { + value_expr($3); $$ = NEW_IF(cond($3), $1, Qnil); } | expr WHILE_MOD expr { - $$ = NEW_WHILE2(cond($3), $1); + value_expr($3); + if (nd_type($1) == NODE_BEGIN) { + $$ = NEW_WHILE2(cond($3), $1); + } + else { + $$ = NEW_WHILE(cond($3), $1); + } } | expr AND expr { + value_expr($1); $$ = NEW_AND(cond($1), cond($3)); } | expr OR expr { + value_expr($1); $$ = NEW_OR(cond($1), cond($3)); } + | NOT expr + { + value_expr($2); + $$ = NEW_NOT(cond($2)); + } | arg mlhs : mlhs_head { $$ = NEW_MASGN(NEW_LIST($1), Qnil); } - | mlhs_head '*' lhs + | mlhs_head STAR lhs { $$ = NEW_MASGN(NEW_LIST($1), $3); } @@ -299,7 +338,7 @@ mlhs : mlhs_head { $$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),Qnil); } - | mlhs_head mlhs_tail comma '*' lhs + | mlhs_head mlhs_tail comma STAR lhs { $$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),$5); } @@ -327,6 +366,11 @@ lhs : variable { $$ = attrset($1, $3, Qnil); } + | backref + { + backref_error($1); + $$ = Qnil; + } cname : IDENTIFIER { @@ -335,6 +379,7 @@ cname : IDENTIFIER | CONSTANT fname : IDENTIFIER + | FID | CONSTANT | op { @@ -342,8 +387,16 @@ fname : IDENTIFIER $$ = $1; } -op : COLON2 { $$ = COLON2; } - | DOT2 { $$ = DOT2; } +undef_list : fname + { + $$ = NEW_UNDEF($1); + } + | undef_list ',' fname + { + $$ = block_append($1, NEW_UNDEF($3)); + } + +op : DOT2 { $$ = DOT2; } | '|' { $$ = '|'; } | '^' { $$ = '^'; } | '&' { $$ = '&'; } @@ -359,6 +412,7 @@ op : COLON2 { $$ = COLON2; } | '+' { $$ = '+'; } | '-' { $$ = '-'; } | '*' { $$ = '*'; } + | STAR { $$ = '*'; } | '/' { $$ = '/'; } | '%' { $$ = '%'; } | POW { $$ = POW; } @@ -381,13 +435,20 @@ arg : variable '=' arg { $$ = attrset($1, $3, $5); } + | backref '=' arg + { + value_expr($3); + backref_error($1); + $$ = Qnil; + } | variable OP_ASGN arg { NODE *val; value_expr($3); if (is_local_id($1)) { - val = NEW_LVAR($1); + if (local_id($1)) val = NEW_LVAR($1); + else val = NEW_DVAR($1); } else if (is_global_id($1)) { val = NEW_GVAR($1); @@ -411,33 +472,22 @@ arg : variable '=' arg { $$ = NEW_OP_ASGN2($1, $4, $5); } + | backref OP_ASGN arg + { + backref_error($1); + $$ = Qnil; + } | arg DOT2 arg { - $$ = call_op($1, DOT2, 1, $3); + $$ = NEW_DOT2($1, $3); } | arg DOT3 arg { - $$ = NEW_DOT3(cond2($1), cond2($3)); + $$ = NEW_DOT3($1, $3); } | arg '+' arg { - $$ = Qnil; - if ($1 && $3 - && (nd_type($3) == NODE_LIT - || nd_type($3) == NODE_STR) - && nd_type($1) == NODE_CALL && $1->nd_mid == '+') { - if ($1->nd_args->nd_head == Qnil) - Bug("bad operand for `+'"); - if (nd_type($1->nd_args->nd_head) == NODE_LIT - || nd_type($1->nd_args->nd_head) == NODE_STR) { - $1->nd_args->nd_head = - expand_op($1->nd_args->nd_head, '+', $3); - $$ = $1; - } - } - if ($$ == Qnil) { - $$ = call_op($1, '+', 1, $3); - } + $$ = call_op($1, '+', 1, $3); } | arg '-' arg { @@ -517,20 +567,12 @@ arg : variable '=' arg } | '!' arg { + value_expr($2); $$ = NEW_NOT(cond($2)); } | '~' arg { - if ($2 - && (nd_type($2) == NODE_STR - || (nd_type($2) == NODE_LIT - && (TYPE($2->nd_lit) == T_REGEXP - || TYPE($2->nd_lit) == T_STRING)))) { - $$ = NEW_CALL($2, '~', Qnil); - } - else { - $$ = call_op($2, '~', 0); - } + $$ = call_op($2, '~', 0); } | arg LSHFT arg { @@ -540,16 +582,18 @@ arg : variable '=' arg { $$ = call_op($1, RSHFT, 1, $3); } - | arg COLON2 arg + | arg COLON2 cname { - $$ = call_op($1, COLON2, 1, $3); + $$ = NEW_COLON2($1, $3); } | arg ANDOP arg { + value_expr($1); $$ = NEW_AND(cond($1), cond($3)); } | arg OROP arg { + value_expr($1); $$ = NEW_OR(cond($1), cond($3)); } | primary @@ -562,10 +606,6 @@ call_args : /* none */ $$ = Qnil; } | call_args0 opt_nl - | '*' arg opt_nl - { - $$ = $2; - } call_args0 : args | assocs @@ -576,10 +616,19 @@ call_args0 : args { $$ = list_append($1, NEW_HASH($3)); } - | args comma '*' arg + | args comma assocs comma STAR arg + { + $$ = list_append($1, NEW_HASH($3)); + $$ = call_op($$, '+', 1, $6); + } + | args comma STAR arg { $$ = call_op($1, '+', 1, $4); } + | STAR arg + { + $$ = $2; + } opt_args : /* none */ { @@ -630,15 +679,16 @@ primary : literal | XSTRING2 | DREGEXP | var_ref + | backref | SUPER '(' call_args rparen { - if (!cur_mid && !in_single) + if (!cur_mid && !in_single && !in_defined) Error("super called outside of method"); $$ = NEW_SUPER($3); } | SUPER { - if (!cur_mid && !in_single) + if (!cur_mid && !in_single && !in_defined) Error("super called outside of method"); $$ = NEW_ZSUPER(); } @@ -710,25 +760,39 @@ primary : literal { $$ = NEW_YIELD(Qnil); } - | primary '{' opt_iter_var compexpr rbrace + | DEFINED '(' {in_defined = 1;} arg ')' + { + in_defined = 0; + $$ = NEW_DEFINED($4); + } + | primary '{' + { + $<vars>$ = dyna_push(); + } + opt_iter_var + compexpr rbrace { if (nd_type($1) == NODE_LVAR - || nd_type($1) == NODE_LVAR2 || nd_type($1) == NODE_CVAR) { $1 = NEW_FCALL($1->nd_vid, Qnil); } - $$ = NEW_ITER($3, $1, $4); + $$ = NEW_ITER($4, $1, $5); + dyna_pop($<vars>3); + } + | FID + { + $$ = NEW_FCALL($1, Qnil); } - | IDENTIFIER '(' call_args rparen + | operation '(' call_args rparen { $$ = NEW_FCALL($1, $3); } - | primary '.' IDENTIFIER '(' call_args rparen + | primary '.' operation '(' call_args rparen { value_expr($1); $$ = NEW_CALL($1, $3, $5); } - | primary '.' IDENTIFIER + | primary '.' operation { value_expr($1); $$ = NEW_CALL($1, $3, Qnil); @@ -738,10 +802,12 @@ primary : literal if_tail END { + value_expr($2); $$ = NEW_IF(cond($2), $4, $5); } | WHILE expr term compexpr END { + value_expr($2); $$ = NEW_WHILE(cond($2), $4); } | CASE compexpr @@ -751,29 +817,20 @@ primary : literal value_expr($2); $$ = NEW_CASE($2, $3); } - | FOR iter_var IN expr term - compexpr - END + | FOR iter_var IN expr term compexpr END { - value_expr($4); + value_expr($2); $$ = NEW_FOR($2, $4, $6); } | BEGIN compexpr - resque + rescue ensure END { - if ($3 == Qnil && $4 == Qnil) { - $$ = $2; - } - else { - $$ = NEW_BEGIN($2, $3, $4); - } + $$ = NEW_BEGIN($2, $3, $4); } - | LPAREN expr - opt_nl - rparen + | LPAREN exprs opt_nl rparen { $$ = $2; } @@ -823,13 +880,14 @@ primary : literal { $$ = NEW_DEFN($2, $4, $5, class_nest?0:1); local_pop(); - cur_mid = Qnil; + cur_mid = 0; } | DEF singleton '.' fname { value_expr($2); in_single++; local_push(); + lex_state = EXPR_END; /* force for args */ } f_arglist compexpr @@ -849,6 +907,7 @@ if_tail : opt_else compexpr if_tail { + value_expr($2); $$ = NEW_IF(cond($2), $4, $5); } @@ -864,7 +923,11 @@ opt_else : /* none */ iter_var : lhs | mlhs -opt_iter_var : '|' /* none */ '|' +opt_iter_var : /* node */ + { + $$ = Qnil; + } + | '|' /* none */ '|' { $$ = Qnil; } @@ -887,11 +950,11 @@ case_body : WHEN args then cases : opt_else | case_body -resque : /* none */ +rescue : /* none */ { $$ = Qnil; } - | RESQUE compexpr + | RESCUE compexpr { if ($2 == Qnil) $$ = (NODE*)1; @@ -926,7 +989,6 @@ variable : IDENTIFIER | IVAR | GVAR | CONSTANT - | NTH_REF | NIL { $$ = NIL; @@ -941,6 +1003,9 @@ var_ref : variable $$ = gettable($1); } +backref : NTH_REF + | BACK_REF + superclass : term { $$ = Qnil; @@ -949,7 +1014,7 @@ superclass : term { lex_state = EXPR_BEG; } - CONSTANT + expr term { $$ = $3; } @@ -958,36 +1023,47 @@ f_arglist : '(' f_args rparen { $$ = $2; } - | term + | f_args term { - $$ = NEW_ARGS(0, -1); + $$ = $1; } f_args : /* no arg */ { - $$ = NEW_ARGS(0, -1); + $$ = NEW_ARGS(0, 0, -1); } | f_arg { - $$ = NEW_ARGS($1, -1); + $$ = NEW_ARGS($1, 0, -1); } | f_arg comma rest_arg { - $$ = NEW_ARGS($1, $3); + $$ = NEW_ARGS($1, 0, $3); } - | rest_arg + | f_arg comma f_optarg { - $$ = NEW_ARGS(Qnil, $1); + $$ = NEW_ARGS($1, $3, -1); } - | f_arg error + | f_arg comma f_optarg comma rest_arg { - lex_state = EXPR_BEG; - $$ = NEW_ARGS($1, -1); + $$ = NEW_ARGS($1, $3, $5); + } + | f_optarg + { + $$ = NEW_ARGS(0, $1, -1); + } + | f_optarg comma rest_arg + { + $$ = NEW_ARGS(0, $1, $3); + } + | rest_arg + { + $$ = NEW_ARGS(0, 0, $1); } | error { lex_state = EXPR_BEG; - $$ = NEW_ARGS(0, -1); + $$ = NEW_ARGS(0, 0, -1); } f_arg : IDENTIFIER @@ -1005,7 +1081,23 @@ f_arg : IDENTIFIER $$ += 1; } -rest_arg : '*' IDENTIFIER +f_opt : IDENTIFIER '=' arg + { + if (!is_local_id($1)) + Error("formal argument must be local variable"); + $$ = asignable($1, $3); + } + +f_optarg : f_opt + { + $$ = NEW_BLOCK($1); + } + | f_optarg comma f_opt + { + $$ = block_append($1, $3); + } + +rest_arg : STAR IDENTIFIER { if (!is_local_id($2)) Error("rest argument must be local variable"); @@ -1025,7 +1117,7 @@ singleton : var_ref $$ = $1; } } - | LPAREN compexpr rparen + | LPAREN expr opt_nl rparen { switch (nd_type($2)) { case NODE_STR: @@ -1048,6 +1140,9 @@ assoc_list : /* none */ $$ = Qnil; } | assocs trailer + { + $$ = $1; + } | args trailer { if ($1->nd_alen%2 != 0) { @@ -1067,6 +1162,9 @@ assoc : arg ASSOC arg $$ = list_append(NEW_LIST($1), $3); } +operation : IDENTIFIER + | FID + opt_term : /* none */ | term @@ -1109,7 +1207,6 @@ VALUE newinteger(); char *strdup(); static NODE *var_extend(); -static void read_escape(); #define LEAVE_BS 1 @@ -1122,7 +1219,7 @@ lex_setsrc(src, ptr, len) char *ptr; int len; { - sourcefile = (char*)strdup(src); + sourcefile = strdup(src); sourceline = 1; lex_p = ptr; @@ -1151,7 +1248,7 @@ do { \ #define tokfix() (tokenbuf[tokidx]='\0') #define tok() tokenbuf #define toklen() tokidx -#define toknow() &toknbuf[tokidx] +#define toklast() (tokidx>0?tokenbuf[tokidx-1]:0) char * newtok() @@ -1179,6 +1276,88 @@ tokadd(c) } static int +read_escape() +{ + int c; + + switch (c = nextc()) { + case '\\': /* Backslash */ + return c; + + case 'n': /* newline */ + return '\n'; + + case 't': /* horizontal tab */ + return '\t'; + + case 'r': /* carriage-return */ + return '\r'; + + case 'f': /* form-feed */ + return '\f'; + + case 'v': /* vertical tab */ + return '\13'; + + case 'a': /* alarm(bell) */ + return '\007'; + + case 'e': /* escape */ + return 033; + + case '0': case '1': case '2': case '3': /* octal constant */ + case '4': case '5': case '6': case '7': + pushback(); + SCAN_OCT(c); + return c; + + case 'x': /* hex constant */ + SCAN_HEX(c); + return c; + + case 'b': /* backspace */ + return '\b'; + + case 'M': + if ((c = nextc()) != '-') { + Error("Invalid escape character syntax"); + return '\0'; + } + if ((c = nextc()) == '\\') { + return read_escape() | 0x80; + } + else if (c == -1) goto eof; + else { + return ((c & 0xff) | 0x80); + } + + case 'C': + if ((c = nextc()) != '-') { + Error("Invalid escape character syntax"); + return '\0'; + } + case 'c': + case '^': + if ((c = nextc())== '\\') { + c = read_escape(); + } + else if (c == '?') + return 0177; + else if (c == -1) goto eof; + return c & 0x9f; + + eof: + case -1: + Error("Invalid escape character syntax"); + pushback(); + return '\0'; + + default: + return c; + } +} + +static int parse_regx() { register int c; @@ -1188,7 +1367,7 @@ parse_regx() NODE *list = Qnil; newtok(); - while (c = nextc()) { + while ((c = nextc()) != -1) { switch (c) { case '[': in_brack = 1; @@ -1235,7 +1414,8 @@ parse_regx() /* fall through */ default: pushback(); - read_escape(LEAVE_BS); + tokadd('\\'); + tokadd(read_escape()); } continue; @@ -1247,6 +1427,7 @@ parse_regx() casefold = 1; } else { + casefold = 0; pushback(); } @@ -1263,7 +1444,7 @@ parse_regx() return DREGEXP; } else { - yylval.val = regexp_new(tok(), toklen(), casefold); + yylval.val = reg_new(tok(), toklen(), casefold); return REGEXP; } case -1: @@ -1279,6 +1460,8 @@ parse_regx() } tokadd(c); } + Error("unterminated regexp"); + return 0; } static int @@ -1287,7 +1470,6 @@ parse_string(term) { int c; NODE *list = Qnil; - ID id; int strstart; strstart = sourceline; @@ -1320,10 +1502,9 @@ parse_string(term) tokadd(c); } else { - int flags = 0; - if (term != '"') flags = LEAVE_BS; pushback(); - read_escape(flags); + if (term != '"') tokadd('\\'); + tokadd(read_escape()); } continue; } @@ -1369,6 +1550,7 @@ static struct kwtable { "class", CLASS, EXPR_BEG, "continue", CONTINUE, EXPR_END, "def", DEF, EXPR_FNAME, + "defined?", DEFINED, EXPR_END, "else", ELSE, EXPR_BEG, "elsif", ELSIF, EXPR_BEG, "end", END, EXPR_END, @@ -1379,9 +1561,10 @@ static struct kwtable { "in", IN, EXPR_BEG, "module", MODULE, EXPR_BEG, "nil", NIL, EXPR_END, + "not", NOT, EXPR_BEG, "or", OR, EXPR_BEG, "redo", REDO, EXPR_END, - "resque", RESQUE, EXPR_BEG, + "rescue", RESCUE, EXPR_BEG, "retry", RETRY, EXPR_END, "return", RETURN, EXPR_MID, "self", SELF, EXPR_END, @@ -1393,10 +1576,17 @@ static struct kwtable { "yield", YIELD, EXPR_END, }; +static void +arg_ambiguous() +{ + Warning("ambiguous first argument; make sure"); +} + static int yylex() { register int c; + int space_seen = 0; struct kwtable *low = kwtable, *mid, *high = LAST(kwtable); retry: @@ -1410,6 +1600,7 @@ retry: /* white spaces */ case ' ': case '\t': case '\f': case '\r': case '\13': /* '\v' */ + space_seen = 1; goto retry; case '#': /* it's a comment */ @@ -1424,14 +1615,15 @@ retry: /* fall through */ case '\n': sourceline++; - if (lex_state == EXPR_BEG || lex_state == EXPR_FNAME) + if (lex_state == EXPR_BEG + || lex_state == EXPR_FNAME) goto retry; lex_state = EXPR_BEG; return '\n'; case '*': - lex_state = EXPR_BEG; if ((c = nextc()) == '*') { + lex_state = EXPR_BEG; if (nextc() == '=') { yylval.id = POW; return OP_ASGN; @@ -1439,11 +1631,21 @@ retry: pushback(); return POW; } - else if (c == '=') { + if (c == '=') { yylval.id = '*'; + lex_state = EXPR_BEG; return OP_ASGN; } pushback(); + if (lex_state == EXPR_ARG && space_seen && !isspace(c)){ + arg_ambiguous(); + lex_state = EXPR_BEG; + return STAR; + } + if (lex_state == EXPR_BEG) { + return STAR; + } + lex_state = EXPR_BEG; return '*'; case '!': @@ -1558,9 +1760,7 @@ retry: case '?': if ((c = nextc()) == '\\') { - newtok(); - read_escape(0); - c = tok()[0]; + c = read_escape(); } c &= 0xff; yylval.val = INT2FIX(c); @@ -1592,21 +1792,27 @@ retry: return '|'; case '+': + c = nextc(); if (lex_state == EXPR_FNAME) { - if ((c = nextc()) == '@') { + if (c == '@') { return UPLUS; } pushback(); return '+'; } - c = nextc(); + if (lex_state == EXPR_ARG) { + if (!space_seen || c == '=' || isspace(c)) { + arg_ambiguous(); + lex_state = EXPR_END; + } + } if (lex_state != EXPR_END) { pushback(); if (isdigit(c)) { goto start_num; } lex_state = EXPR_BEG; - return UMINUS; + return UPLUS; } lex_state = EXPR_BEG; if (c == '=') { @@ -1617,21 +1823,28 @@ retry: return '+'; case '-': + c = nextc(); if (lex_state == EXPR_FNAME) { - if ((c = nextc()) == '@') { + if (c == '@') { return UMINUS; } pushback(); return '-'; } - c = nextc(); + if (lex_state == EXPR_ARG) { + if (!space_seen || c == '=' || isspace(c)) { + arg_ambiguous(); + lex_state = EXPR_END; + } + } if (lex_state != EXPR_END) { - pushback(); if (isdigit(c)) { + pushback(); c = '-'; goto start_num; } lex_state = EXPR_BEG; + pushback(); return UMINUS; } lex_state = EXPR_BEG; @@ -1774,16 +1987,25 @@ retry: return SYMBEG; case '/': - if (lex_state == EXPR_BEG || lex_state == EXPR_MID) { + if (lex_state == EXPR_BEG + || lex_state == EXPR_MID) { return parse_regx(); } + c = nextc(); + if (lex_state == EXPR_ARG) { + if (space_seen && c != '=' && !isspace(c)) { + pushback(); + arg_ambiguous(); + return parse_regx(); + } + } lex_state = EXPR_BEG; - if (nextc() == '=') { + if (c == '=') { yylval.id = '/'; return OP_ASGN; } pushback(); - return c; + return '/'; case '^': lex_state = EXPR_BEG; @@ -1795,6 +2017,9 @@ retry: return c; case ',': + lex_state = EXPR_BEG; + return c; + case ';': lex_state = EXPR_BEG; return c; @@ -1809,15 +2034,23 @@ retry: return c; case '(': - if (lex_state != EXPR_END) + if (lex_state == EXPR_BEG + || lex_state == EXPR_MID) { c = LPAREN; - lex_state = EXPR_BEG; + lex_state = EXPR_BEG; + } + else if (lex_state == EXPR_ARG && space_seen) { + arg_ambiguous(); + c = LPAREN; + lex_state = EXPR_BEG; + } + else { + lex_state = EXPR_BEG; + } return c; case '[': - if (lex_state == EXPR_BEG || lex_state == EXPR_MID) - c = LBRACK; - else if (lex_state == EXPR_FNAME) { + if (lex_state == EXPR_FNAME) { if ((c = nextc()) == ']') { if ((c = nextc()) == '=') { return ASET; @@ -1828,11 +2061,19 @@ retry: pushback(); return '['; } + else if (lex_state == EXPR_BEG + || lex_state == EXPR_MID) { + c = LBRACK; + } + else if (lex_state == EXPR_ARG && space_seen) { + arg_ambiguous(); + c = LBRACK; + } lex_state = EXPR_BEG; return c; case '{': - if (lex_state != EXPR_END) + if (lex_state != EXPR_END && lex_state != EXPR_ARG) c = LBRACE; lex_state = EXPR_BEG; return c; @@ -1841,6 +2082,7 @@ retry: c = nextc(); if (c == '\n') { sourceline++; + space_seen = 1; goto retry; /* skip \\n */ } pushback(); @@ -1860,6 +2102,9 @@ retry: newtok(); c = nextc(); switch (c) { + case '~': /* $~: match-data */ + local_cnt('~'); + /* fall through */ case '*': /* $*: argv */ case '$': /* $$: pid */ case '?': /* $?: last status */ @@ -1870,51 +2115,42 @@ retry: case ',': /* $,: output field separator */ case '.': /* $.: last read line number */ case '_': /* $_: last read line string */ - case '&': /* $&: last match */ - case '`': /* $&: string before last match */ - case '\'': /* $&: string after last match */ - case '+': /* $&: string matches last paren. */ - case '~': /* $~: match-data */ case '=': /* $=: ignorecase */ case ':': /* $:: load path */ case '<': /* $<: reading filename */ case '>': /* $>: default output handle */ - case '"': /* $": already loaded files */ + case '\"': /* $": already loaded files */ tokadd('$'); tokadd(c); tokfix(); yylval.id = rb_intern(tok()); return GVAR; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': + case '&': /* $&: last match */ + case '`': /* $`: string before last match */ + case '\'': /* $': string after last match */ + case '+': /* $+: string matches last paren. */ + yylval.node = NEW_BACK_REF(c); + return BACK_REF; + + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': while (isdigit(c)) { tokadd(c); c = nextc(); } pushback(); tokfix(); - { - ID id = atoi(tok()); - id <<= ID_SCOPE_SHIFT; - id |= ID_NTHREF; - yylval.id = id; - return NTH_REF; - } + yylval.node = NEW_NTH_REF(atoi(tok())); + return NTH_REF; - case '0': default: if (!is_identchar(c)) { pushback(); return '$'; } + case '0': tokadd('$'); } break; @@ -1947,7 +2183,12 @@ retry: } c = nextc(); } - pushback(); + if (c == '!' || c == '?') { + tokadd(c); + } + else { + pushback(); + } tokfix(); { @@ -1955,9 +2196,11 @@ retry: switch (tok()[0]) { case '$': + lex_state = EXPR_END; result = GVAR; break; case '@': + lex_state = EXPR_END; result = IVAR; break; default: @@ -1967,7 +2210,8 @@ retry: if (( c = strcmp(mid->name, tok())) == 0) { enum lex_state state = lex_state; lex_state = mid->state; - if (state != EXPR_BEG) { + if (state != EXPR_BEG + && state != EXPR_BEG) { if (mid->id == IF) return IF_MOD; if (mid->id == WHILE) return WHILE_MOD; } @@ -1982,6 +2226,7 @@ retry: } if (lex_state == EXPR_FNAME) { + lex_state = EXPR_END; if ((c = nextc()) == '=') { tokadd(c); } @@ -1989,14 +2234,21 @@ retry: pushback(); } } + else if (lex_state == EXPR_BEG){ + lex_state = EXPR_ARG; + } + else { + lex_state = EXPR_END; + } if (isupper(tok()[0])) { result = CONSTANT; } - else { + else if (toklast() == '!' || toklast() == '?') { + result = FID; + } else { result = IDENTIFIER; } } - lex_state = EXPR_END; yylval.id = rb_intern(tok()); return result; } @@ -2007,16 +2259,16 @@ var_extend(list, term) NODE *list; char term; { - int c, t; + int c, t, brace; VALUE ss; + NODE *node; ID id; c = nextc(); switch (c) { - default: - tokadd('#'); - pushback(); - return list; + case '$': + case '{': + break; case '@': t = nextc(); pushback(); @@ -2025,9 +2277,10 @@ var_extend(list, term) tokadd(c); return list; } - case '$': - case '{': - break; + default: + tokadd('#'); + pushback(); + return list; } ss = str_new(tok(), toklen()); @@ -2038,49 +2291,64 @@ var_extend(list, term) list_append(list, NEW_STR(ss)); } newtok(); - if (c == '{') { - while ((c = nextc()) != '}') { - if (c == -1) { - return (NODE*)-1; - } - if (isspace(c)) { - Error("Invalid variable name in string"); - break; - } - if (c == term) { - Error("Inmature variable name in string"); - pushback(); - return list; - } - tokadd(c); - } + if (c == '{') { + brace = 1; + c = nextc(); } else { + brace = 0; + } + + switch (c) { + case '$': + c = nextc(); + if (c == -1) return (NODE*)-1; switch (c) { - case '$': - tokadd(c); + case '&': + case '`': + case '\'': + case '+': + node = NEW_BACK_REF(c); c = nextc(); - if (c == -1) return (NODE*)-1; - if (!is_identchar(c)) { + goto append_node; + + case '~': + local_cnt('~'); + id = '~'; + goto id_node; + + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + while (isdigit(c)) { tokadd(c); - goto fetch_id; + c = nextc(); } - /* through */ - case '@': - tokadd(c); - c = nextc(); - break; + tokfix(); + node = NEW_NTH_REF(atoi(tok())); + goto append_node; } - while (is_identchar(c)) { + + tokadd('$'); + if (!is_identchar(c)) { tokadd(c); - if (ismbchar(c)) { - c = nextc(); - tokadd(c); - } + goto fetch_id; + } + /* through */ + case '@': + tokadd(c); + c = nextc(); + break; + } + while (is_identchar(c)) { + tokadd(c); + if (ismbchar(c)) { c = nextc(); + tokadd(c); } - pushback(); + c = nextc(); } + fetch_id: tokfix(); if (strcmp("__LINE__", tok()) == 0) @@ -2089,90 +2357,21 @@ var_extend(list, term) id = _FILE_; else id = rb_intern(tok()); - list_append(list, gettable(id)); + id_node: + node = gettable(id); + + append_node: + if (brace) { + if (c != '}') + Error("Invalid variable name in string"); + } + else pushback(); + + list_append(list, node); newtok(); return list; } -static void -read_escape(flag) - int flag; -{ - char c; - - switch (c = nextc()) { - case '\\': /* Backslash */ - tokadd('\\'); - break; - - case 'n': /* newline */ - tokadd('\n'); - break; - - case 't': /* horizontal tab */ - tokadd('\t'); - break; - - case 'r': /* carriage-return */ - tokadd('\r'); - break; - - case 'f': /* form-feed */ - tokadd('\f'); - break; - - case 'v': /* vertical tab */ - tokadd('\13'); - break; - - case 'a': /* alarm(bell) */ - tokadd('\007'); - break; - - case 'e': /* escape */ - tokadd(033); - break; - - case 'c': - if ((c = nextc()) == '?') - tokadd(0177); - else { - if (islower(c)) - c = toupper(c); - c = c - '@'; - tokadd(c); - } - break; - - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - { /* octal constant */ - pushback(); - SCAN_OCT(c); - tokadd(c); - } - break; - - case 'x': /* hex constant */ - { - SCAN_HEX(c); - tokadd(c); - } - break; - - case 'b': /* backspace */ - tokadd('\b'); - return; - - default: - if (flag & LEAVE_BS) { - tokadd('\\'); - } - case '#': - tokadd(c); - break; - } -} NODE* newnode(type, a0, a1, a2) @@ -2282,72 +2481,6 @@ list_concat(head, tail) return head; } -static NODE* -list_copy(list) - NODE *list; -{ - NODE *tmp; - - if (list == Qnil) return Qnil; - - tmp = Qnil; - while(list) { - tmp = list_append(tmp, list->nd_head); - list = list->nd_next; - } - return tmp; -} - -struct call_arg { - ID id; - VALUE recv; - int narg; - VALUE arg; -}; - -static VALUE -call_lit(arg) - struct call_arg *arg; -{ - return rb_funcall(arg->recv, arg->id, arg->narg, arg->arg); -} - -static VALUE -except_lit() -{ - extern VALUE errstr; - - Error("%s", RSTRING(errstr)->ptr); - return Qnil; -} - -static NODE * -expand_op(recv, id, arg) - NODE *recv, *arg; - ID id; -{ - struct call_arg arg_data; - VALUE val; - NODE *result; - - arg_data.recv = recv->nd_lit; - arg_data.id = id; - arg_data.narg = arg?1:0; - arg_data.arg = arg->nd_lit; - - val = rb_resque(call_lit, &arg_data, except_lit, Qnil); - if (TYPE(val) == T_STRING) { - result = NEW_STR(val); - } - else { - result = NEW_LIT(val); - } - - return result; -} - -#define NODE_IS_CONST(n) (nd_type(n) == NODE_LIT || nd_type(n) == NODE_STR) - static NODE * call_op(recv, id, narg, arg1) NODE *recv; @@ -2360,9 +2493,6 @@ call_op(recv, id, narg, arg1) value_expr(arg1); } - if (NODE_IS_CONST(recv) && (narg == 0 || NODE_IS_CONST(arg1))) { - return expand_op(recv, id, (narg == 1)?arg1:Qnil); - } return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):Qnil); } @@ -2385,10 +2515,10 @@ gettable(id) return NEW_STR(s); } else if (is_local_id(id)) { - if (local_id(id)) - return NEW_LVAR(id); - else - return NEW_LVAR2(id); + if (local_id(id)) return NEW_LVAR(id); + if (dyna_id(id)) return NEW_DVAR(id); + /* method call without arguments */ + return NEW_FCALL(id, Qnil); } else if (is_global_id(id)) { return NEW_GVAR(id); @@ -2399,9 +2529,8 @@ gettable(id) else if (is_const_id(id)) { return NEW_CVAR(id); } - else if (is_nthref_id(id)) { - return NEW_NTH_REF(id>>ID_SCOPE_SHIFT); - } + Bug("invalid id for gettable"); + return Qnil; } static NODE* @@ -2409,6 +2538,7 @@ asignable(id, val) ID id; NODE *val; { + extern VALUE dyna_var_asgn(); NODE *lhs = Qnil; if (id == SELF) { @@ -2421,7 +2551,12 @@ asignable(id, val) Error("Can't asign to special identifier"); } else if (is_local_id(id)) { - lhs = NEW_LASGN(id, val); + if (local_id(id) || !dyna_in_block()) + lhs = NEW_LASGN(id, val); + else{ + dyna_var_asgn(id, TRUE); + lhs = NEW_DASGN(id, val); + } } else if (is_global_id(id)) { lhs = NEW_GASGN(id, val); @@ -2434,9 +2569,6 @@ asignable(id, val) Error("class constant asigned in method body"); lhs = NEW_CASGN(id, val); } - else if (is_nthref_id(id)) { - Error("Can't set variable $%d", id>>ID_SCOPE_SHIFT); - } else { Bug("bad id for variable"); } @@ -2452,6 +2584,15 @@ aryset(recv, idx, val) return NEW_CALL(recv, ASET, list_append(idx, val)); } +ID +id_attrset(id) + ID id; +{ + id &= ~ID_SCOPE_MASK; + id |= ID_ATTRSET; + return id; +} + static NODE * attrset(recv, id, val) NODE *recv, *val; @@ -2460,12 +2601,26 @@ attrset(recv, id, val) value_expr(recv); value_expr(val); - id &= ~ID_SCOPE_MASK; + id &= ~ID_SCOPE_MASK; id |= ID_ATTRSET; return NEW_CALL(recv, id, NEW_LIST(val)); } +static void +backref_error(node) + NODE *node; +{ + switch (nd_type(node)) { + case NODE_NTH_REF: + Error("Can't set variable $%d", node->nd_nth); + break; + case NODE_BACK_REF: + Error("Can't set variable $%c", node->nd_nth); + break; + } +} + static int value_expr(node) NODE *node; @@ -2503,6 +2658,8 @@ value_expr(node) } } +static NODE *cond2(); + static NODE* cond0(node) NODE *node; @@ -2515,6 +2672,12 @@ cond0(node) else if (type == NODE_LIT && TYPE(node->nd_lit) == T_REGEXP) { return call_op(node,MATCH,1,NEW_GVAR(rb_intern("$_"))); } + else if (type == NODE_DOT2 || type == NODE_DOT3) { + node->nd_beg = cond2(node->nd_beg); + node->nd_end = cond2(node->nd_end); + if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2); + else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3); + } return node; } @@ -2524,10 +2687,10 @@ cond(node) { enum node_type type = nd_type(node); - value_expr(node); switch (type) { case NODE_MASGN: case NODE_LASGN: + case NODE_DASGN: case NODE_GASGN: case NODE_IASGN: case NODE_CASGN: @@ -2561,6 +2724,7 @@ st_table *new_idhash(); static struct local_vars { ID *tbl; int cnt; + int dlev; struct local_vars *prev; } *lvtbl; @@ -2572,7 +2736,8 @@ local_push() local = ALLOC(struct local_vars); local->prev = lvtbl; local->cnt = 0; - local->tbl = Qnil; + local->tbl = 0; + local->dlev = 0; lvtbl = local; } @@ -2600,11 +2765,11 @@ local_cnt(id) if (id == 0) return lvtbl->cnt; - for (cnt=0, max=lvtbl->cnt; cnt<max ;cnt++) { - if (lvtbl->tbl[cnt+1] == id) return cnt; + for (cnt=1, max=lvtbl->cnt+1; cnt<max ;cnt++) { + if (lvtbl->tbl[cnt] == id) return cnt-1; } - if (lvtbl->tbl == Qnil) { + if (lvtbl->tbl == 0) { lvtbl->tbl = ALLOC_N(ID, 2); lvtbl->tbl[0] = 0; } @@ -2622,7 +2787,7 @@ local_id(id) { int i, max; - if (lvtbl == Qnil) return FALSE; + if (lvtbl == 0) return FALSE; for (i=1, max=lvtbl->cnt+1; i<max; i++) { if (lvtbl->tbl[i] == id) return TRUE; } @@ -2632,7 +2797,7 @@ local_id(id) static void top_local_init() { - if (lvtbl == Qnil) { + if (lvtbl == 0) { local_push(); } else if (the_scope->local_tbl) { @@ -2643,12 +2808,13 @@ top_local_init() } if (lvtbl->cnt > 0) { lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+1); - MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt); + MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt+1); } else { - lvtbl->tbl = Qnil; + lvtbl->tbl = 0; } NEW_CREF0(); /* initialize constant c-ref */ + lvtbl->dlev = (the_dyna_vars?1:0); } static void @@ -2661,14 +2827,7 @@ top_local_setup() i = lvtbl->tbl[0]; if (i < len) { - if (the_scope->flags & SCOPE_MALLOCED) { - VALUE *vars = the_scope->local_vars; - - REALLOC_N(the_scope->local_vars, VALUE, len); - MEMZERO(the_scope->local_vars+i, VALUE, len-i); - free(the_scope->local_tbl); - } - else { + if (the_scope->flag == SCOPE_ALLOCA) { VALUE *vars = the_scope->local_vars; the_scope->local_vars = ALLOC_N(VALUE, len); if (vars) { @@ -2678,10 +2837,15 @@ top_local_setup() else { MEMZERO(the_scope->local_vars, VALUE, len); } + the_scope->flag = SCOPE_MALLOC; + } + else { + REALLOC_N(the_scope->local_vars, VALUE, len); + MEMZERO(the_scope->local_vars+i, VALUE, len-i); + free(the_scope->local_tbl); } lvtbl->tbl[0] = len; the_scope->local_tbl = lvtbl->tbl; - the_scope->flags |= SCOPE_MALLOCED; } else if (lvtbl->tbl) { free(lvtbl->tbl); @@ -2690,6 +2854,27 @@ top_local_setup() cref_list = Qnil; } +static struct RVarmap* +dyna_push() +{ + lvtbl->dlev++; + return the_dyna_vars; +} + +static void +dyna_pop(vars) + struct RVarmap* vars; +{ + lvtbl->dlev--; + the_dyna_vars = vars; +} + +static int +dyna_in_block() +{ + return (lvtbl->dlev > 0); +} + static void cref_pop() { @@ -2721,7 +2906,7 @@ yywhole_loop(chop, split) if (chop) { eval_tree = block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")), - rb_intern("chop"), Qnil), eval_tree); + rb_intern("chop!"), Qnil), eval_tree); } eval_tree = NEW_WHILE(NEW_FCALL(rb_intern("gets"),0),eval_tree); } @@ -2808,14 +2993,14 @@ rb_intern(name) /* operator */ int i; - id = Qnil; + id = 0; for (i=0; rb_op_tbl[i].token; i++) { if (strcmp(rb_op_tbl[i].name, name) == 0) { id = rb_op_tbl[i].token; break; } } - if (id == Qnil) Bug("Unknown operator `%s'", name); + if (id == 0) Bug("Unknown operator `%s'", name); break; } @@ -2844,7 +3029,7 @@ rb_intern(name) static char *find_ok; -static +static int id_find(name, id1, id2) char *name; ID id1, id2; @@ -2860,7 +3045,7 @@ char * rb_id2name(id) ID id; { - find_ok = Qnil; + find_ok = 0; if (id < LAST_TOKEN) { int i = 0; @@ -2897,7 +3082,7 @@ const_check(id, val, class) VALUE val; struct RClass *class; { - if (is_const_id(id) && rb_const_bound(class, id)) { + if (is_const_id(id) && rb_const_defined(class, id)) { Warning("constant redefined for %s", rb_class2name(class)); return ST_STOP; } @@ -11,11 +11,20 @@ ************************************************/ #include "ruby.h" +#include "sig.h" #include <stdio.h> #include <errno.h> #include <ctype.h> #include <signal.h> -#include <sys/time.h> +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#else +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif + #include <sys/resource.h> #ifdef HAVE_VFORK_H #include <vfork.h> @@ -31,9 +40,17 @@ get_pid() static VALUE get_ppid() { +#ifdef NT + return INT2FIX(0); +#else return INT2FIX(getppid()); +#endif } +#ifdef NT +#define HAVE_WAITPID +#endif + static VALUE status; #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4) @@ -96,7 +113,7 @@ static wait_each(key, value) #endif static VALUE -Fwait(obj) +f_wait() { int pid, state; @@ -118,12 +135,12 @@ Fwait(obj) } static VALUE -Fwaitpid(obj, vpid, vflags) +f_waitpid(obj, vpid, vflags) VALUE obj, vpid, vflags; { int pid, flags; - if (vflags == Qnil) flags = Qnil; + if (vflags == Qnil) flags = 0; else flags = FIX2UINT(vflags); if ((pid = rb_waitpid(FIX2UINT(vpid), flags)) < 0) @@ -133,6 +150,7 @@ Fwaitpid(obj, vpid, vflags) char *strtok(); +int rb_proc_exec(str) char *str; { @@ -161,7 +179,7 @@ rb_proc_exec(str) } static VALUE -Fexec(obj, str) +f_exec(obj, str) VALUE obj; struct RString *str; { @@ -171,18 +189,22 @@ Fexec(obj, str) } static VALUE -Ffork(obj) +f_fork(obj) VALUE obj; { int pid; switch (pid = fork()) { case 0: - return INT2FIX(0); + if (iterator_p()) { + rb_yield(Qnil); + _exit(0); + } + return Qnil; case -1: rb_sys_fail("fork(2)"); - break; + return Qnil; default: return INT2FIX(pid); @@ -190,7 +212,7 @@ Ffork(obj) } static VALUE -F_exit(obj, status) +f_exit_bang(obj, status) VALUE obj, status; { int code = -1; @@ -223,11 +245,21 @@ rb_syswait(pid) } static VALUE -Fsystem(obj, str) +f_system(obj, str) VALUE obj; struct RString *str; { - int pid, w; +#ifdef NT + int state; + + Check_Type(str, T_STRING); + state = do_spawn(str->ptr); + status = INT2FIX(state); + + if (state == 0) return TRUE; + return FALSE; +#else + int pid; Check_Type(str, T_STRING); @@ -255,10 +287,13 @@ Fsystem(obj, str) rb_syswait(pid); } - return status; + if (status == INT2FIX(0)) return TRUE; + return FALSE; +#endif } -Fsleep(argc, argv) +VALUE +f_sleep(argc, argv) int argc; VALUE *argv; { @@ -269,7 +304,9 @@ Fsleep(argc, argv) sleep((32767<<16)+32767); } else if (argc == 1) { + TRAP_BEG; sleep(NUM2INT(argv[0])); + TRAP_END; } else { Fail("wrong # of arguments"); @@ -280,8 +317,9 @@ Fsleep(argc, argv) return int2inum(end); } +#ifndef NT static VALUE -Fproc_getpgrp(argc, argv, obj) +proc_getpgrp(argc, argv, obj) int argc; VALUE *argv; VALUE obj; @@ -302,7 +340,7 @@ Fproc_getpgrp(argc, argv, obj) } static VALUE -Fproc_setpgrp(obj, pid, pgrp) +proc_setpgrp(obj, pid, pgrp) VALUE obj, pid, pgrp; { int ipid, ipgrp; @@ -316,7 +354,7 @@ Fproc_setpgrp(obj, pid, pgrp) } static VALUE -Fproc_getpriority(obj, which, who) +proc_getpriority(obj, which, who) VALUE obj, which, who; { #ifdef HAVE_GETPRIORITY @@ -334,7 +372,7 @@ Fproc_getpriority(obj, which, who) } static VALUE -Fproc_setpriority(obj, which, who, prio) +proc_setpriority(obj, which, who, prio) VALUE obj, which, who, prio; { #ifdef HAVE_GETPRIORITY @@ -351,9 +389,10 @@ Fproc_setpriority(obj, which, who, prio) Fail("The setpriority() function is unimplemented on this machine"); #endif } +#endif static VALUE -Fproc_getuid(obj) +proc_getuid(obj) VALUE obj; { int uid = getuid(); @@ -361,7 +400,7 @@ Fproc_getuid(obj) } static VALUE -Fproc_setuid(obj, id) +proc_setuid(obj, id) VALUE obj, id; { int uid; @@ -385,7 +424,7 @@ Fproc_setuid(obj, id) } static VALUE -Fproc_getgid(obj) +proc_getgid(obj) VALUE obj; { int gid = getgid(); @@ -393,7 +432,7 @@ Fproc_getgid(obj) } static VALUE -Fproc_setgid(obj, id) +proc_setgid(obj, id) VALUE obj, id; { int gid; @@ -417,7 +456,7 @@ Fproc_setgid(obj, id) } static VALUE -Fproc_geteuid(obj) +proc_geteuid(obj) VALUE obj; { int euid = geteuid(); @@ -425,7 +464,7 @@ Fproc_geteuid(obj) } static VALUE -Fproc_seteuid(obj, euid) +proc_seteuid(obj, euid) VALUE obj, euid; { #ifdef HAVE_SETEUID @@ -445,7 +484,7 @@ Fproc_seteuid(obj, euid) } static VALUE -Fproc_getegid(obj) +proc_getegid(obj) VALUE obj; { int egid = getegid(); @@ -453,7 +492,7 @@ Fproc_getegid(obj) } static VALUE -Fproc_setegid(obj, egid) +proc_setegid(obj, egid) VALUE obj, egid; { #ifdef HAVE_SETEGID @@ -472,53 +511,58 @@ Fproc_setegid(obj, egid) return egid; } -VALUE rb_readonly_hook(); -VALUE M_Process; +VALUE mProcess; -extern VALUE Fkill(); +extern VALUE f_kill(); +void Init_process() { - extern VALUE C_Kernel; - - rb_define_variable("$$", Qnil, get_pid, Qnil, 0); - rb_define_variable("$?", &status, Qnil, rb_readonly_hook, 0); - rb_define_private_method(C_Kernel, "exec", Fexec, 1); - rb_define_private_method(C_Kernel, "fork", Ffork, 0); - rb_define_private_method(C_Kernel, "_exit", Ffork, 1); - rb_define_private_method(C_Kernel, "wait", Fwait, 0); - rb_define_private_method(C_Kernel, "waitpid", Fwaitpid, 2); - rb_define_private_method(C_Kernel, "system", Fsystem, 1); - rb_define_private_method(C_Kernel, "sleep", Fsleep, -1); - - M_Process = rb_define_module("Process"); - rb_extend_object(M_Process, M_Process); - - rb_define_single_method(M_Process, "fork", Ffork, 0); - rb_define_single_method(M_Process, "_exit", Ffork, 1); - rb_define_single_method(M_Process, "wait", Fwait, 0); - rb_define_single_method(M_Process, "waitpid", Fwaitpid, 2); - rb_define_single_method(M_Process, "kill", Fkill, -1); - - rb_define_method(M_Process, "pid", get_pid, 0); - rb_define_method(M_Process, "ppid", get_ppid, 0); - - rb_define_method(M_Process, "getpgrp", Fproc_getpgrp, -1); - rb_define_method(M_Process, "setpgrp", Fproc_setpgrp, 2); - - rb_define_method(M_Process, "getpriority", Fproc_getpriority, 2); - rb_define_method(M_Process, "setpriority", Fproc_setpriority, 3); - - rb_define_const(M_Process, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS)); - rb_define_const(M_Process, "PRIO_PGRP", INT2FIX(PRIO_PGRP)); - rb_define_const(M_Process, "PRIO_USER", INT2FIX(PRIO_USER)); - - rb_define_method(M_Process, "uid", Fproc_getuid, 0); - rb_define_method(M_Process, "uid=", Fproc_setuid, 1); - rb_define_method(M_Process, "gid", Fproc_getgid, 0); - rb_define_method(M_Process, "gid=", Fproc_setgid, 1); - rb_define_method(M_Process, "euid", Fproc_geteuid, 0); - rb_define_method(M_Process, "euid=", Fproc_seteuid, 1); - rb_define_method(M_Process, "egid", Fproc_getegid, 0); - rb_define_method(M_Process, "egid=", Fproc_setegid, 1); + extern VALUE cKernel; + + rb_define_virtual_variable("$$", get_pid, Qnil); + rb_define_readonly_variable("$?", &status); +#ifndef NT + rb_define_private_method(cKernel, "exec", f_exec, 1); + rb_define_private_method(cKernel, "fork", f_fork, 0); + rb_define_private_method(cKernel, "exit!", f_exit_bang, 1); + rb_define_private_method(cKernel, "wait", f_wait, 0); + rb_define_private_method(cKernel, "waitpid", f_waitpid, 2); +#endif + rb_define_private_method(cKernel, "system", f_system, 1); + rb_define_private_method(cKernel, "sleep", f_sleep, -1); + + mProcess = rb_define_module("Process"); + +#ifndef NT + rb_define_singleton_method(mProcess, "fork", f_fork, 0); + rb_define_singleton_method(mProcess, "exit!", f_exit_bang, 1); + rb_define_singleton_method(mProcess, "wait", f_wait, 0); + rb_define_singleton_method(mProcess, "waitpid", f_waitpid, 2); + rb_define_singleton_method(mProcess, "kill", f_kill, -1); +#endif + + rb_define_module_function(mProcess, "pid", get_pid, 0); + rb_define_module_function(mProcess, "ppid", get_ppid, 0); + +#ifndef NT + rb_define_module_function(mProcess, "getpgrp", proc_getpgrp, -1); + rb_define_module_function(mProcess, "setpgrp", proc_setpgrp, 2); + + rb_define_module_function(mProcess, "getpriority", proc_getpriority, 2); + rb_define_module_function(mProcess, "setpriority", proc_setpriority, 3); + + rb_define_const(mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS)); + rb_define_const(mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP)); + rb_define_const(mProcess, "PRIO_USER", INT2FIX(PRIO_USER)); + + rb_define_module_function(mProcess, "uid", proc_getuid, 0); + rb_define_module_function(mProcess, "uid=", proc_setuid, 1); + rb_define_module_function(mProcess, "gid", proc_getgid, 0); + rb_define_module_function(mProcess, "gid=", proc_setgid, 1); + rb_define_module_function(mProcess, "euid", proc_geteuid, 0); + rb_define_module_function(mProcess, "euid=", proc_seteuid, 1); + rb_define_module_function(mProcess, "egid", proc_getegid, 0); + rb_define_module_function(mProcess, "egid=", proc_setegid, 1); +#endif } @@ -16,7 +16,7 @@ static int first = 1; static char state[256]; static VALUE -Fsrand(argc, argv, obj) +f_srand(argc, argv, obj) int argc; VALUE *argv; VALUE obj; @@ -54,7 +54,7 @@ Fsrand(argc, argv, obj) } static VALUE -Frand(obj, max) +f_rand(obj, max) VALUE obj, max; { int val; @@ -73,10 +73,11 @@ Frand(obj, max) return int2inum(val); } +void Init_Random() { - extern VALUE C_Kernel; + extern VALUE cKernel; - rb_define_private_method(C_Kernel, "srand", Fsrand, -1); - rb_define_private_method(C_Kernel, "rand", Frand, 1); + rb_define_private_method(cKernel, "srand", f_srand, -1); + rb_define_private_method(cKernel, "rand", f_rand, 1); } @@ -12,18 +12,21 @@ #include "ruby.h" -VALUE M_Comparable; -VALUE C_Range; +VALUE mComparable; +static VALUE cRange; -static ID next; +static ID upto; static VALUE -Srng_new(class, start, end) +range_s_new(class, start, end) VALUE class, start, end; { VALUE obj; - if (!obj_is_kind_of(start, M_Comparable) || TYPE(start) != TYPE(end)) { + if (!(FIXNUM_P(start) && FIXNUM_P(end)) + && (TYPE(start) != TYPE(end) + || CLASS_OF(start) != CLASS_OF(end) + || !rb_responds_to(start, upto))) { Fail("bad value for range"); } @@ -39,11 +42,11 @@ VALUE range_new(start, end) VALUE start, end; { - return Srng_new(C_Range, start, end); + return range_s_new(cRange, start, end); } static VALUE -Frng_match(rng, obj) +range_match(rng, obj) VALUE rng, obj; { VALUE beg, end; @@ -71,13 +74,15 @@ struct upto_data { VALUE end; }; -static rng_upto(data) +static VALUE +range_upto(data) struct upto_data *data; { - return rb_funcall(data->beg, rb_intern("upto"), 1, data->end); + return rb_funcall(data->beg, upto, 1, data->end); } -static rng_upto_yield(v) +static VALUE +range_upto_yield(v) VALUE v; { rb_yield(v); @@ -85,19 +90,19 @@ static rng_upto_yield(v) } static VALUE -Frng_each(obj) +range_each(obj) VALUE obj; { - VALUE b, e, current; + VALUE b, e; b = rb_iv_get(obj, "start"); e = rb_iv_get(obj, "end"); if (FIXNUM_P(b)) { /* fixnum is a special case(for performance) */ - Fnum_upto(b, e); + num_upto(b, e); } else if (TYPE(b) == T_STRING) { - Fstr_upto(b, e); + str_upto(b, e); } else { struct upto_data data; @@ -105,14 +110,14 @@ Frng_each(obj) data.beg = b; data.end = e; - rb_iterate(rng_upto, &data, rng_upto_yield, Qnil); + rb_iterate(range_upto, &data, range_upto_yield, Qnil); } return Qnil; } static VALUE -Frng_start(obj) +range_start(obj) VALUE obj; { VALUE b; @@ -122,7 +127,7 @@ Frng_start(obj) } static VALUE -Frng_end(obj) +range_end(obj) VALUE obj; { VALUE e; @@ -132,7 +137,7 @@ Frng_end(obj) } static VALUE -Frng_to_s(obj) +range_to_s(obj) VALUE obj; { VALUE args[4]; @@ -140,21 +145,36 @@ Frng_to_s(obj) args[0] = str_new2("%d..%d"); args[1] = rb_iv_get(obj, "start"); args[2] = rb_iv_get(obj, "end"); - return Fsprintf(3, args); + return f_sprintf(3, args); +} + +VALUE +range_beg_end(range, begp, endp) + VALUE range; + int *begp, *endp; +{ + int beg, end; + + if (!obj_is_kind_of(range, cRange)) return FALSE; + + beg = rb_iv_get(range, "start"); *begp = NUM2INT(beg); + end = rb_iv_get(range, "end"); *endp = NUM2INT(end); + return TRUE; } -extern VALUE M_Enumerable; +extern VALUE mEnumerable; +void Init_Range() { - C_Range = rb_define_class("Range", C_Object); - rb_include_module(C_Range, M_Enumerable); - rb_define_single_method(C_Range, "new", Srng_new, 2); - rb_define_method(C_Range, "=~", Frng_match, 1); - rb_define_method(C_Range, "each", Frng_each, 0); - rb_define_method(C_Range, "start", Frng_start, 0); - rb_define_method(C_Range, "end", Frng_end, 0); - rb_define_method(C_Range, "to_s", Frng_to_s, 0); - - next = rb_intern("next"); + cRange = rb_define_class("Range", cObject); + rb_include_module(cRange, mEnumerable); + rb_define_singleton_method(cRange, "new", range_s_new, 2); + rb_define_method(cRange, "=~", range_match, 1); + rb_define_method(cRange, "each", range_each, 0); + rb_define_method(cRange, "start", range_start, 0); + rb_define_method(cRange, "end", range_end, 0); + rb_define_method(cRange, "to_s", range_to_s, 0); + + upto = rb_intern("upto"); } @@ -13,6 +13,9 @@ #include "ruby.h" #include "re.h" +#define BEG(no) regs->beg[no] +#define END(no) regs->end[no] + #if 'a' == 97 /* it's ascii */ static char casetable[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', @@ -77,20 +80,37 @@ str_cicmp(str1, str2) p1 = str1->ptr; p2 = str2->ptr; for (i = 0; i < len; i++, p1++, p2++) { - if (casetable[*p1] != casetable[*p2]) - return casetable[*p1] - casetable[*p2]; + if (casetable[(int)*p1] != casetable[(int)*p2]) + return casetable[(int)*p1] - casetable[(int)*p2]; } return str1->len - str2->len; } +#define REG_IGNORECASE FL_USER0 + +#define KCODE_NONE 0 +#define KCODE_EUC FL_USER1 +#define KCODE_SJIS FL_USER2 +#define KCODE_MASK (KCODE_EUC|KCODE_SJIS) + +static int reg_kcode = +#ifdef EUC + KCODE_EUC; +#else +# ifdef SJIS + KCODE_SJIS; +# else + KCODE_NONE; +# endif +#endif + static Regexp* make_regexp(s, len) -char *s; -int len; + char *s; + int len; { Regexp *rp; char *err; - register int c; /* Handle escaped characters first. */ @@ -111,20 +131,36 @@ int len; return rp; } -struct match last_match; +static VALUE +match_alloc() +{ + NEWOBJ(match, struct RMatch); + OBJSETUP(match, cData, T_MATCH); + + match->ptr = 0; + match->len = 0; + match->regs = ALLOC(struct re_registers); + MEMZERO(match->regs, struct re_registers, 1); + + return (VALUE)match; +} + VALUE ignorecase; int -research(reg, str, start) +reg_search(reg, str, start, regs) struct RRegexp *reg; struct RString *str; int start; + struct re_registers *regs; { int result; int casefold = ignorecase; + VALUE match = 0; + struct re_registers *regs0 = 0; /* case-flag set for the object */ - if (FL_TEST(reg, FL_USER1)) { + if (FL_TEST(reg, REG_IGNORECASE)) { casefold = TRUE; } if (casefold) { @@ -139,142 +175,113 @@ research(reg, str, start) } if (start > str->len) return -1; - result = re_search(reg->ptr, str->ptr, str->len, - start, str->len - start, &last_match.regs); - if (result >= 0) { - last_match.len = str->len; - if (last_match.ptr == Qnil) { - last_match.ptr = ALLOC_N(char, str->len+1); - } - else { - REALLOC_N(last_match.ptr, char, str->len+1); + if (regs == (struct re_registers *)-1) { + regs = 0; + } + else if (match = backref_get()) { + if (match == 1) { + match = match_alloc(); + backref_set(match); } - memcpy(last_match.ptr, str->ptr, last_match.len); - last_match.ptr[last_match.len] = '\0'; + regs0 = RMATCH(match)->regs; + } + + if (regs && !match) regs0 = regs; + + if ((RBASIC(reg)->flags & KCODE_MASK) != reg_kcode) { + char *err; + + if ((err = re_compile_pattern(reg->str, reg->len, reg->ptr)) != NULL) + Fail("%s: /%s/", err, reg->str); + RBASIC(reg)->flags = RBASIC(reg)->flags & ~KCODE_MASK; + RBASIC(reg)->flags |= reg_kcode; + } + + result = re_search(reg->ptr, str->ptr, str->len, + start, str->len - start, regs0); + + if (match && result >= 0) { + RMATCH(match)->len = str->len; + REALLOC_N(RMATCH(match)->ptr, char, str->len+1); + memcpy(RMATCH(match)->ptr, str->ptr, str->len); + RMATCH(match)->ptr[str->len] = '\0'; } + if (regs && regs0 && regs0 != regs) re_copy_registers(regs, regs0); return result; } VALUE -re_nth_match(nth) +reg_nth_defined(nth, match) int nth; + struct RMatch *match; +{ + if (!match) return FALSE; + if (nth >= match->regs->num_regs) { + return FALSE; + } + if (match->BEG(nth) == -1) return FALSE; + return TRUE; +} + +VALUE +reg_nth_match(nth, match) + int nth; + struct RMatch *match; { int start, end, len; - if (nth >= last_match.regs.num_regs) { + if (!match) return Qnil; + if (nth >= match->regs->num_regs) { return Qnil; } - start = BEG(nth); + start = match->BEG(nth); if (start == -1) return Qnil; - end = END(nth); + end = match->END(nth); len = end - start; - return str_new(last_match.ptr + start, len); + return str_new(match->ptr + start, len); } VALUE -re_last_match(id) - ID id; +reg_last_match(match) + struct RMatch *match; { - return re_nth_match(0); + return reg_nth_match(0, match); } -static VALUE -re_match_pre() +VALUE +reg_match_pre(match) + struct RMatch *match; { - struct match *match; - - if (BEG(0) == -1) return Qnil; - return str_new(last_match.ptr, BEG(0)); + if (!match) return Qnil; + if (match->BEG(0) == -1) return Qnil; + return str_new(match->ptr, match->BEG(0)); } -static VALUE -re_match_post() +VALUE +reg_match_post(match) + struct RMatch *match; { - struct match *match; - - if (BEG(0) == -1) return Qnil; - return str_new(last_match.ptr+END(0), - last_match.len-END(0)); + if (!match) return Qnil; + if (match->BEG(0) == -1) return Qnil; + return str_new(match->ptr+match->END(0), + match->len-match->END(0)); } -static VALUE -re_match_last() +VALUE +reg_match_last(match) + struct RMatch *match; { - int i, len; + int i; - if (BEG(0) == -1) return Qnil; + if (!match) return Qnil; + if (match->BEG(0) == -1) return Qnil; - for (i=last_match.regs.num_regs-1; BEG(i) == -1 && i > 0; i--) { - } + for (i=match->regs->num_regs-1; match->BEG(i) == -1 && i > 0; i--) + ; if (i == 0) return Qnil; - return re_nth_match(i); -} - -static VALUE -get_match_data(id, nth) - ID id; - int nth; -{ - return re_nth_match(nth); -} - -static void -free_match(data) - struct match *data; -{ - free(data->ptr); - if (data->regs.allocated > 0) { - free(data->regs.beg); - free(data->regs.end); - } -} - -static VALUE -get_match() -{ - struct match *data; - int beg, i; - - data = ALLOC(struct match); - - data->len = last_match.len; - data->ptr = ALLOC_N(char, last_match.len+1); - memcpy(data->ptr, last_match.ptr, data->len+1); - data->regs.allocated = 0; - re_copy_registers(&data->regs, &last_match.regs); - - return data_new(data, free_match, Qnil); -} - -static VALUE -set_match(val) - struct RArray *val; -{ - struct match *match; - - Check_Type(val, T_DATA); - match = (struct match*)DATA_PTR(val); - last_match.len = match->len; - if (last_match.len == 0) { - if (last_match.ptr) { - free(last_match.ptr); - last_match.ptr = Qnil; - } - } - else { - if (last_match.ptr == Qnil) { - last_match.ptr = ALLOC_N(char, match->len+1); - } - else { - REALLOC_N(last_match.ptr, char, match->len+1); - } - } - memcpy(last_match.ptr, match->ptr, last_match.len+1); - last_match.regs = match->regs; - - return (VALUE)val; + return reg_nth_match(i, match); } void @@ -293,10 +300,10 @@ const char *s; Fail(s); } -VALUE C_Regexp; +VALUE cRegexp; static VALUE -regexp_new_1(class, s, len, ci) +reg_new_1(class, s, len, ci) VALUE class; char *s; int len, ci; @@ -310,41 +317,44 @@ regexp_new_1(class, s, len, ci) re->str[len] = '\0'; re->len = len; - if (ci) FL_SET(re, FL_USER1); + FL_SET(re, reg_kcode); + if (ci) FL_SET(re, REG_IGNORECASE); + return (VALUE)re; } VALUE -regexp_new(s, len, ci) +reg_new(s, len, ci) char *s; int len, ci; { - return regexp_new_1(C_Regexp, s, len, ci); + return reg_new_1(cRegexp, s, len, ci); } -static VALUE str_cache, reg_cache; +static VALUE reg_cache, ign_cache; VALUE -re_regcomp(str) +reg_regcomp(str) struct RString *str; { - if (str_cache && RSTRING(str_cache)->len == str->len && - memcmp(RSTRING(str_cache)->ptr, str->ptr, str->len)) + if (reg_cache && RREGEXP(reg_cache)->len == str->len + && ign_cache == ignorecase + && memcmp(RREGEXP(reg_cache)->str, str->ptr, str->len) == 0) return reg_cache; - str_cache = (VALUE)str; - return reg_cache = regexp_new(str->ptr, str->len, ignorecase); + ign_cache = ignorecase; + return reg_cache = reg_new(str->ptr, str->len, ignorecase); } VALUE -Freg_match(re, str) +reg_match(re, str) struct RRegexp *re; struct RString *str; { int start; - Check_Type(str, T_STRING); - start = research(re, str, 0); + if (TYPE(str) != T_STRING) return FALSE; + start = reg_search(re, str, 0, 0); if (start < 0) { return Qnil; } @@ -352,7 +362,7 @@ Freg_match(re, str) } VALUE -Freg_match2(re) +reg_match2(re) struct RRegexp *re; { extern VALUE rb_lastline; @@ -361,7 +371,7 @@ Freg_match2(re) if (TYPE(rb_lastline) != T_STRING) Fail("$_ is not a string"); - start = research(re, rb_lastline, 0); + start = reg_search(re, rb_lastline, 0, 0); if (start == -1) { return Qnil; } @@ -369,7 +379,7 @@ Freg_match2(re) } static VALUE -Sreg_new(argc, argv, self) +reg_s_new(argc, argv, self) int argc; VALUE *argv; VALUE self; @@ -387,10 +397,10 @@ Sreg_new(argc, argv, self) src = argv[0]; switch (TYPE(src)) { case T_STRING: - reg = regexp_new_1(self, RREGEXP(src)->ptr, RREGEXP(src)->len, ci); + reg = reg_new_1(self, RREGEXP(src)->ptr, RREGEXP(src)->len, ci); case T_REGEXP: - reg = regexp_new_1(self, RREGEXP(src)->str, RREGEXP(src)->len, ci); + reg = reg_new_1(self, RREGEXP(src)->str, RREGEXP(src)->len, ci); default: Check_Type(src, T_STRING); @@ -400,7 +410,7 @@ Sreg_new(argc, argv, self) } static VALUE -Sreg_quote(re, str) +reg_s_quote(re, str) VALUE re; struct RString *str; { @@ -430,20 +440,22 @@ Sreg_quote(re, str) } static VALUE -Freg_clone(re) +reg_clone(re) struct RRegexp *re; { - int ci = FL_TEST(re, FL_USER1); - return regexp_new_1(CLASS_OF(re), re->str, re->len, ci); + int ci = FL_TEST(re, REG_IGNORECASE); + return reg_new_1(CLASS_OF(re), re->str, re->len, ci); } VALUE -re_regsub(str) +reg_regsub(str, src, regs) struct RString *str; + struct RString *src; + struct re_registers *regs; { VALUE val = Qnil; char *p, *s, *e, c; - int no, len; + int no; p = s = str->ptr; e = s + str->len; @@ -471,10 +483,10 @@ re_regsub(str) if (no < 0) { /* Ordinary character. */ if (c == '\\' && (*s == '\\' || *s == '&')) - p = ++s; + p = s++; } else { if (BEG(no) == -1) continue; - str_cat(val, last_match.ptr+BEG(no), END(no)-BEG(no)); + str_cat(val, src->ptr+BEG(no), END(no)-BEG(no)); } } @@ -489,12 +501,26 @@ re_regsub(str) } static VALUE -kcode() +reg_to_s(re) + struct RRegexp *re; { - switch (re_syntax_options & RE_MBCTYPE_MASK) { - case RE_MBCTYPE_SJIS: + VALUE str = str_new2("/"); + + str_cat(str, re->str, re->len); + str_cat(str, "/", 1); + if (FL_TEST(re, REG_IGNORECASE)) { + str_cat(str, "i", 1); + } + return str; +} + +static VALUE +kcode_getter() +{ + switch (reg_kcode) { + case KCODE_SJIS: return str_new2("SJIS"); - case RE_MBCTYPE_EUC: + case KCODE_EUC: return str_new2("EUC"); default: return str_new2("NONE"); @@ -502,19 +528,21 @@ kcode() } void -rb_set_kanjicode(code) +rb_set_kcode(code) char *code; { - if (code == Qnil) goto set_no_conversion; + if (code == 0) goto set_no_conversion; switch (code[0]) { case 'E': case 'e': + reg_kcode = KCODE_EUC; re_syntax_options &= ~RE_MBCTYPE_MASK; re_syntax_options |= RE_MBCTYPE_EUC; break; case 'S': case 's': + reg_kcode = KCODE_SJIS; re_syntax_options &= ~RE_MBCTYPE_MASK; re_syntax_options |= RE_MBCTYPE_SJIS; break; @@ -522,25 +550,57 @@ rb_set_kanjicode(code) case 'N': case 'n': set_no_conversion: + reg_kcode = KCODE_NONE; re_syntax_options &= ~RE_MBCTYPE_MASK; break; } re_set_syntax(re_syntax_options); } -void -rb_setup_kcode() +static VALUE +kcode_setter(val) + struct RString *val; { - rb_define_const(C_Object, "KCODE", kcode()); + Check_Type(val, T_STRING); + rb_set_kcode(val->ptr); + return (VALUE)val; +} + +static VALUE +match_getter() +{ + VALUE match = backref_get(); + + if (match && match != 1) { + NEWOBJ(m, struct RMatch); + OBJSETUP(m, cData, T_MATCH); + + m->len = RMATCH(match)->len; + if (RMATCH(match)->ptr) { + m->ptr = ALLOC_N(char, m->len+1); + memcpy(m->ptr, RMATCH(match)->ptr, m->len); + m->ptr[m->len] = '\0'; + } + else { + m->ptr = 0; + } + m->regs = ALLOC(struct re_registers); + re_copy_registers(m->regs, RMATCH(match)->regs); + return (VALUE)m; + } + return Qnil; } -VALUE rb_readonly_hook(); +static void +match_setter(val) +{ + Check_Type(val, T_MATCH); + backref_set(val); +} void Init_Regexp() { - int i; - re_set_syntax(RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_AWK_CLASS_HACK | RE_INTERVALS @@ -551,23 +611,20 @@ Init_Regexp() #endif ); - rb_define_variable("$~", Qnil, get_match, set_match, 0); - - rb_define_variable("$&", Qnil, re_last_match, Qnil, 0); - rb_define_variable("$`", Qnil, re_match_pre, Qnil, 0); - rb_define_variable("$'", Qnil, re_match_post, Qnil, 0); - rb_define_variable("$+", Qnil, re_match_last, Qnil, 0); + rb_define_virtual_variable("$~", match_getter, match_setter); - rb_define_variable("$=", &ignorecase, Qnil, Qnil, 0); + rb_define_variable("$=", &ignorecase, 0); + rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter); - C_Regexp = rb_define_class("Regexp", C_Object); - rb_define_single_method(C_Regexp, "new", Sreg_new, -1); - rb_define_single_method(C_Regexp, "compile", Sreg_new, -1); - rb_define_single_method(C_Regexp, "quote", Sreg_quote, 1); + cRegexp = rb_define_class("Regexp", cObject); + rb_define_singleton_method(cRegexp, "new", reg_s_new, -1); + rb_define_singleton_method(cRegexp, "compile", reg_s_new, -1); + rb_define_singleton_method(cRegexp, "quote", reg_s_quote, 1); - rb_define_method(C_Regexp, "=~", Freg_match, 1); - rb_define_method(C_Regexp, "~", Freg_match2, 0); + rb_define_method(cRegexp, "clone", reg_clone, 0); + rb_define_method(cRegexp, "=~", reg_match, 1); + rb_define_method(cRegexp, "~", reg_match2, 0); + rb_define_method(cRegexp, "to_s", reg_to_s, 0); - rb_global_variable(&str_cache); rb_global_variable(®_cache); } @@ -21,16 +21,14 @@ typedef struct re_pattern_buffer Regexp; -struct match { +struct RMatch { + struct RBasic basic; UINT len; char *ptr; - struct re_registers regs; + struct re_registers *regs; }; -extern struct match last_match; - -#define BEG(no) last_match.regs.beg[no] -#define END(no) last_match.regs.end[no] +#define RMATCH(obj) (R_CAST(RMatch)(obj)) VALUE re_regcomp(); VALUE re_regsub(); @@ -1743,7 +1743,6 @@ re_search(pbufp, string, size, startpos, range, regs) { register char *fastmap = pbufp->fastmap; register unsigned char *translate = (unsigned char *) pbufp->translate; - int endpos = startpos + range; int val; /* Check for out-of-range starting position. */ @@ -1811,9 +1810,9 @@ re_search(pbufp, string, size, startpos, range, regs) return -2; #ifndef NO_ALLOCA -#ifdef C_ALLOCA +#ifdef cALLOCA alloca(0); -#endif /* C_ALLOCA */ +#endif /* cALLOCA */ #endif /* NO_ALLOCA */ advance: @@ -1968,10 +1967,6 @@ struct register_info } \ } -/* Test if at very beginning or at very end of the virtual concatenation - of string1 and string2. If there is only one string, we've put it in - string2. */ - #define AT_STRINGS_BEG (d == string) #define AT_STRINGS_END (d == dend) @@ -2667,6 +2662,7 @@ re_copy_registers(regs1, regs2) { int i; + if (regs1 == regs2) return; if (regs1->allocated == 0) { regs1->beg = TMALLOC(regs2->num_regs, int); regs1->end = TMALLOC(regs2->num_regs, int); @@ -2680,3 +2676,11 @@ re_copy_registers(regs1, regs2) regs1->end[i] = regs2->end[i]; } } + +void +re_free_registers(regs) + struct re_registers *regs; +{ + if (regs->beg) free(regs->beg); + if (regs->end) free(regs->end); +} @@ -275,6 +275,7 @@ extern int re_search (); extern int re_match (); extern long re_set_syntax(); extern void re_copy_registers (); +extern void re_free_registers (); #endif /* __STDC__ */ diff --git a/ruby.1 b/ruby.1 deleted file mode 100644 index b8c6162554..0000000000 --- a/ruby.1 +++ /dev/null @@ -1,248 +0,0 @@ -.\"ruby.1 - -*- Nroff -*- -.\" $Author: matz $ -.\" $Date: 1994/11/22 01:22:40 $ -.\" created at: Tue Apr 12 01:45:04 JST 1994 -.TH RUBY 1 "\*(RP" -.UC -.SH NAME -ruby \- ֥Ȼظץȸ -.SH SYNOPSIS -.B ruby -[ -.B options -] filename args -.SH DESCRIPTION -.B Ruby -, ڤʥ֥Ȼظץߥ¸뤿μ -εǽĥ֥ȻظץȸǤ롥߷פ -ܸ§, ʲ̤Ǥ. - -.IP ǽ -֥ȻظץߥȥץȥץߥΤ -ɬפʵǽʬ. ä˥ƥȽطεǽ˭ -٤˻ġޤ, ʥ֥ȻظǤʤ, ɬ -Ǥм³ץߥǽǤ. -.IP ĥ -ɬפ˱ưפ˵ǽĥǤ. 饹ͳɲäǤ -Ȥ, CץΥˤäƥץˤ -뵡ǽɲäǤ. ˥ץåȥեˤäƤ, ưŪ -֥ȥɤ뵡ǽ. -.IP -θ§ΤŬѤ褦ʰΤͤ. -ˤäơ֥ѥγڤפϸΤʤ. , -ΤȤ䤹ˤ뤳ȤϤʤ. -.PP -.B Ruby -shperlΤäƤͤˤȤäƤξQˤǤ¤꽾äΤ, -θ̤ƤͤˤȤäƤϽ(¿ʬ)ưפ. -.SH OPTIONS -.B ruby -ץϰʲΰդ. -.TP 5 -.B \-0 -ϥ쥳ɥѥ졼(`$/')8ʿǻꤹ. - -ꤷʤϥ̥륭饯ѥ졼ˤʤ롣 -¾ΥåäƤ褤 - -\-00, ѥ饰ե⡼, \-0777(Υɤʸ¸ -ߤʤΤ)ե٤ɤ߹⡼ɤǤ. -.TP 5 -.B \-a -`\-n'`\-p'ȤȤѤ, ȥץåȥ⡼ɤONˤ. -ȥץåȥ⡼ɤǤϳƥ롼פƬ, -.nf -.ne 2 - - $F = $_.split - -.fi -¹Ԥ. `\-n'`\-p'ץƱ˻ꤵʤ¤, -Υץϰ̣ʤ. -.TP 5 -.B \-c -ץȤؤΥѥΤߤԤ, ¹Ԥʤ. -ѥ뽪λ, ʸˡ顼̵, "Syntax OK"ȽϤ. -.TP 5 -.B \-K " c" -.B ruby -νɤꤹ. -.B ruby -ϻꤷʸ `E'ޤ`e'ξʸ䥢ե -뤬EUCǵҤƤȲꤹ. Ʊͤ`S'ޤ`s'ξ -SJISȤƽ. `N'ϴʤ. ǥեȤ -EUC. -.nf -.ne 2 - - ruby -CE -e 'print "ƥ"' - ruby -Cs -e 'print "ƥ"' - ruby -Cn -e 'print "ƥ"' - -.fi -ΥץϾʸɤμưȽ̵ǽɲä줿 -ˤѹ. -.TP 5 -.B \-d, \-\-debug -ǥХå⡼ɤonˤ. Υե饰åȤȥƥ -ѿ$DEBUGåȤ. -.TP 5 -.B \-e " script" -ޥɥ饤饹ץȤꤹ. \-eץդ -ˤϰ饹ץȥե̾ʤ. -.TP 5 -.B \-F" ʸ" -ϥեɥѥ졼(`$;')ͤʸ˥åȤ. awk -Ʊ̾ΥץƱƯ. -.TP 5 -.B \-i" extension" -ǻꤵ줿եƤ֤(in-place edit) -Ȥꤹ. ΥեϳĥҤĤ¸. -.nf -: -.ne 2 - - % echo matz > /tmp/junk - % cat /tmp/junk - matz - % ruby -p -i.bak -e '$_.upcase' /tmp/junk - % cat /tmp/junk - MATZ - % cat /tmp/junk.bak - matz - -.fi -.TP 5 -.B \-I" directory" -եɤѥ(ɲ). ꤵ줿ǥ쥯 -ȥ -.B ruby -ѿ$LOAD_PATHɲä. -.TP 5 -.B \-l -`$\\'`$/'Ʊͤꤷ, print()Ǥνϻ˲Ԥղä -. ޤ, \-nޤ\-pȤȤѤ, Ϥ줿ƹԤ -Ǹʸchop. -.TP 5 -.B \-n -Υե饰åȤȥץΤ -.nf -.ne 2 - - while gets() - \.\.\. - end - -.fi -ǰϤޤƤ褦ư. -.TP 5 -.B \-p -`\-n'ե饰Ʊ, ƥ롼פκǸѿ`$_'ͤϤ. -.nf -: -.ne 2 - - % echo matz | ruby \-p \-e '$_\.tr "a-z", "A-Z"' - MATZ - -.fi -.TP 5 -.B \-s -ץ̾³, \-ǻϤޤᤷ, Ʊ̾ѿ -ͤꤹ. `\-\-'ʤʹߤϲԤʤʤ. -$ARGV. -.nf -: -.ne 2 - - #! /usr/local/bin/ruby \-s - # \-xyzץͿ"true"ɽ. - print "true\n" if $xyz - -.fi -.TP 5 -.B \-S -ץ̾`/'ǻϤޤäƤʤ, Ķѿ`PATH'ͤ -ȤäƥץȤõ. ϡ#! ݡȤƤʤޥ -ǡ#! ˤ¹Ԥߥ졼Ȥ뤿ˡʲΤ褦ˤ -ƻȤȤǤ: - - #! /usr/local/bin/ruby - # This line makes the next one a comment in ruby \ - eval "exec /usr/local/bin/ruby -S $0 $*" - -ƥϺǽιԤ̵뤷ץȤ`/bin/sh'Ϥ -`/bin/sh'rubyץȤ륹ץȤȤƼ¹Ԥ褦 -Ȥ롥2ܤȤǤȲᤷ3ܤ -Υ륳ޥɤȤƼ¹Ԥrubyץư롥 - -ƥˤäƤ`$0'ɬեѥޤޤʤΤǡ`-S' -Ѥrubyɬפ˱ƥץȤõ褦˻ؼ롥 -rubyץȤĤȡιԤβϤϤ뤬 -ruby2ܤιˤХååˤꡤ2ܤΥ -Ȥ3ܤޤǷ³Ȥߤʤơ3ܤ̵뤹롥 - -ե̾˴ޤޤ륹ڡʤɤˤϡ`$*' -`${1+"$@"}'Τۤ褤csh᤹ˤư -ʤ - -.TP 5 -.B \-v, \-\-verbose -Ĺ⡼. ư˥СֹɽԤ, ƥѿ -$VERBOSEåȤ. ѿåȤƤ, Ĥ -Υåɤϼ¹Ի˾ĹʥåϤ. \-v ץ -ꤵq, ץʳΰʤˤϥС -ɽ, ¹Ԥλ(ɸϤΥץȤԤ -ʤ). -.TP 5 -.B \-\-version -.B ruby -ΥСɽ. -.nf -ɽ: -.ne 2 - - ruby - version 0.56 (94/11/19) - -.fi -.TP 5 -.B \-x"directory" -åΥץȤФƼ¹Ԥ. #!ǻϤޤ, -"ruby"ȤʸޤԤޤǤɤФ. ץȤν -EOF(եν), ^D(ȥD), ^Z(ȥZ) -ޤͽ``__END__''ǻꤹ. - -ǥ쥯ȥ̾ꤹȡץȼ¹˻ꤵ줿ǥ -쥯ȥ˰ܤ. -.TP 5 -.B \-y, \-\-yydebug -ѥǥХå⡼. ѥιʸϤβɽ -. ɽ˾ĹʤΤ, ѥ餽ΤΤǥХ -ͰʳɽʤɤȻפ. - -.SH BUGS -.PP -٤. ñʽξperlawkʤɤ2,3ܤμ¹Ի֤. -θȰۤʤ, 뵡ǽΤۤȤɤåɸ -ӽФ𤹤뤳Ȥ, ¾θǤؿƤӽФ¿ -ʤ褦ʽǤϥåɥåʬ -.B ruby -ͭˤʤ뤷, ǡ¤ʣˤʤ, ֥Ȼظ -åȤ褫Τ, ޤ뤫Τʤ. -.PP -perl국̤¿. -.B ruby -ɵᤷ̤Ǥ. , η, -.B ruby -ץȤperlɤߤ䤹Ϥ, 㴳ε̤ -䤹ȲƤȻפäߤ. -.PP -ɥȤԽʬ. ɬפʾ뤿ˤϥɤ -ߤ. -.PP -ƥȤԽʬ. ХˤĤä, Ǥмʬľ, -ä˶ߤ. ̵ʤ, ƥХƸ -ΤˤƥݡȤߤ. - -.SH AUTHOR - Թ (matz@caelum.co.jp) @@ -31,7 +31,7 @@ int debug = 0; int verbose = 0; static int sflag = FALSE; -char *inplace = Qnil; +char *inplace = 0; char *strdup(); extern int yydebug; @@ -39,10 +39,6 @@ extern int nerrs; int xflag = FALSE; -#ifdef USE_DL -char *rb_dln_argv0; -#endif - static void load_stdin(); static void load_file(); @@ -52,6 +48,37 @@ static int do_split = FALSE; static char *script; +#ifndef RUBY_LIB +#define RUBY_LIB ".:/usr/local/lib/ruby" +#endif + +#define RUBY_LIB_SEP ':' + +extern VALUE rb_load_path; +VALUE Frequire(); + +static void +addpath(path) + char *path; +{ + char *p, *s; + + if (path == 0) return; + + p = s = path; + while (*p) { + while (*p == RUBY_LIB_SEP) p++; + if (s = strchr(p, RUBY_LIB_SEP)) { + ary_push(rb_load_path, str_new(p, (int)(s-p))); + p = s + 1; + } + else { + ary_push(rb_load_path, str_new2(p)); + break; + } + } +} + static void proc_options(argcp, argvp) int *argcp; @@ -62,7 +89,6 @@ proc_options(argcp, argvp) int script_given, do_search; char *s; - extern VALUE rb_load_path; extern VALUE RS, ORS, FS; if (argc == 0) return; @@ -81,7 +107,7 @@ proc_options(argcp, argvp) do_split = TRUE; s++; goto reswitch; - + case 'p': do_print = TRUE; /* through */ @@ -121,7 +147,7 @@ proc_options(argcp, argvp) ORS = RS; s++; goto reswitch; - + case 'S': do_search = TRUE; s++; @@ -140,6 +166,16 @@ proc_options(argcp, argvp) yyparse(); break; + case 'r': + if (*++s) { + f_require(Qnil, str_new2(s)); + } + else if (argv[1]) { + f_require(Qnil, str_new2(argv[1])); + argc--,argv++; + } + break; + case 'i': inplace = strdup(s+1); break; @@ -152,18 +188,34 @@ proc_options(argcp, argvp) } break; + case 'X': + s++; + if (!*s) { + s = argv[1]; + argc--,argv++; + } + if (*s && chdir(s) < 0) { + Fatal("Can't chdir to %s", s); + } + break; + case 'F': FS = str_new2(s+1); break; case 'K': s++; - rb_set_kanjicode(s); + rb_set_kcode(s); s++; goto reswitch; case 'I': - ary_unshift(rb_load_path, str_new2(s+1)); + if (*++s) + ary_push(rb_load_path, str_new2(s)); + else if (argv[1]) { + ary_push(rb_load_path, str_new2(argv[1])); + argc--,argv++; + } break; case '0': @@ -185,9 +237,6 @@ proc_options(argcp, argvp) } goto reswitch; - case 'u': - case 'U': - case '-': if (!s[1]) { argc--,argv++; @@ -218,7 +267,7 @@ proc_options(argcp, argvp) } switch_end: - if (*argvp[0] == Qnil) return; + if (*argvp[0] == 0) return; if (version) { show_version(); @@ -228,8 +277,6 @@ proc_options(argcp, argvp) show_copyright(); } - rb_setup_kcode(); - if (script_given == 0) { if (argc == 0) { /* no more args */ if (verbose) exit(0); @@ -263,10 +310,10 @@ proc_options(argcp, argvp) argv[0][0] = '$'; if (s = strchr(argv[0], '=')) { *s++ = '\0'; - rb_gvar_set2((*argvp)[0], str_new2(s)); + rb_gvar_set2(argv[0], str_new2(s)); } else { - rb_gvar_set2((*argvp)[0], TRUE); + rb_gvar_set2(argv[0], TRUE); } } *argcp = argc; *argvp = argv; @@ -281,7 +328,7 @@ readin(fd, fname, script) int script; { struct stat st; - char *ptr, *p, *pend, *s; + char *ptr, *p, *pend; if (fstat(fd, &st) < 0) rb_sys_fail(fname); if (!S_ISREG(st.st_mode)) @@ -351,7 +398,6 @@ load_file(fname, script) int script; { int fd; - char *ptr; if (fname[0] == '\0') { load_stdin(); @@ -391,7 +437,7 @@ load_stdin() readin(fd, "-"); } -static VALUE Progname; +VALUE Progname; VALUE Argv; static int origargc; @@ -454,13 +500,13 @@ ruby_options(argc, argv, envp) origargc = argc; origargv = argv; origenvp = envp; - rb_define_variable("$@", &errat, Qnil, Qnil, 0); + rb_define_variable("$@", &errat); errat = str_new2(argv[0]); - rb_define_variable("$VERBOSE", &verbose, Qnil, Qnil, 0); - rb_define_variable("$DEBUG", &debug, Qnil, Qnil, 0); + rb_define_variable("$VERBOSE", &verbose); + rb_define_variable("$DEBUG", &debug); -#ifdef USE_DL - rb_dln_argv0 = argv[0]; +#if defined(USE_DLN_A_OUT) + dln_argv0 = argv[0]; #endif proc_options(&argc, &argv); @@ -475,11 +521,14 @@ ruby_options(argc, argv, envp) yywhole_loop(do_line, do_split); } - rb_define_variable("$0", &Progname, Qnil, set_arg0, 0); + rb_define_hooked_variable("$0", &Progname, 0, set_arg0); ruby_script(script); - rb_define_variable("$ARGV", &Argv, Qnil, Qnil, 0); - rb_define_variable("$*", &Argv, Qnil, Qnil, 0); + addpath(getenv("RUBYLIB")); + addpath(RUBY_LIB); + + rb_define_readonly_variable("$ARGV", &Argv); + rb_define_readonly_variable("$*", &Argv); Argv = ary_new2(argc); for (i=0; i < argc; i++) { ary_push(Argv, str_new2(argv[i])); @@ -13,16 +13,19 @@ #ifndef RUBY_H #define RUBY_H -#include "config.h" +#ifndef NT +# include "config.h" +#endif + #include "defines.h" #ifndef __STDC__ -#define volatile -#ifdef __GNUC__ -#define const __const__ -#else -#define const -#endif +# define volatile +# ifdef __GNUC__ +# define const __const__ +# else +# define const +# endif #endif #if defined(HAVE_ALLOCA_H) && !defined(__GNUC__) @@ -39,9 +42,11 @@ typedef unsigned short USHORT; # include <limits.h> #else # ifndef LONG_MAX -# if !defined(LONG_MAX) || !defined(CHAR_BIT) -# include <limits.h> -# endif +# ifdef HAVE_LIMITS_H +# include <limits.h> +# else +# define LONG_MAX 2147483647 /* assuming 32bit(2's compliment) LONG */ +# endif # endif # ifndef LONG_MIN # if (0 != ~0) @@ -50,17 +55,17 @@ typedef unsigned short USHORT; # define LONG_MIN (-LONG_MAX) # endif # endif +# ifndef CHAR_BIT +# define CHAR_BIT 8 +# endif #endif -#ifndef CHAR_BIT -# define CHAR_BIT 8 -#endif - -# define FIXNUM_MAX (LONG_MAX>>1) -# define FIXNUM_MIN RSHIFT((long)LONG_MIN,1) +#define FIXNUM_MAX (LONG_MAX>>1) +#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1) #define FIXNUM_FLAG 0x01 #define INT2FIX(i) (VALUE)(((int)(i))<<1 | FIXNUM_FLAG) +VALUE int2inum(); #if (-1==(((-1)<<1)&FIXNUM_FLAG)>>1) # define RSHIFT(x,y) ((x)>>y) @@ -69,25 +74,24 @@ typedef unsigned short USHORT; #endif #define FIX2INT(x) RSHIFT((int)x,1) -#define FIX2UINT(f) ((unsigned int)(f)>>1) +#define FIX2UINT(f) ((UINT)(f)>>1) #define FIXNUM_P(f) (((int)(f))&FIXNUM_FLAG) #define POSFIXABLE(f) ((f) <= FIXNUM_MAX) #define NEGFIXABLE(f) ((f) >= FIXNUM_MIN) #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) -#define POINTER(p) (p) #define NIL_P(p) ((p) == Qnil) #undef TRUE extern VALUE TRUE; #define FALSE Qnil -extern VALUE C_Object; -extern VALUE C_Nil; -extern VALUE C_Fixnum; -extern VALUE C_Data; +extern VALUE cObject; +extern VALUE cNil; +extern VALUE cFixnum; +extern VALUE cData; -#define CLASS_OF(obj) (FIXNUM_P(obj)?C_Fixnum: NIL_P(obj)?C_Nil:\ +#define CLASS_OF(obj) (FIXNUM_P(obj)?cFixnum: NIL_P(obj)?cNil:\ RBASIC(obj)->class) #define T_NIL 0x00 @@ -103,9 +107,11 @@ extern VALUE C_Data; #define T_HASH 0x0a #define T_STRUCT 0x0b #define T_BIGNUM 0x0c -#define T_ASSOC 0x0f + #define T_DATA 0x10 +#define T_MATCH 0x11 +#define T_VARMAP 0xfd #define T_SCOPE 0xfe #define T_NODE 0xff @@ -122,10 +128,10 @@ int num2int(); #define NEWOBJ(obj,type) type *obj = (type*)newobj() #define OBJSETUP(obj,c,t) {\ RBASIC(obj)->class = (c);\ - RBASIC(obj)->flags |= (t);\ + RBASIC(obj)->flags = (t);\ } #define CLONESETUP(obj1,obj2) \ - OBJSETUP(obj1,RBASIC(obj2)->class,RBASIC(obj2)->flags&T_MASK); + OBJSETUP(obj1,RBASIC(obj2)->class,RBASIC(obj2)->flags); struct RBasic { UINT flags; @@ -178,18 +184,18 @@ struct RData { struct RBasic basic; void (*dmark)(); void (*dfree)(); - VALUE *data; + void *data; }; #define DATA_PTR(dta) (RDATA(dta)->data) VALUE data_new(); -VALUE rb_ivar_get_1(); -VALUE rb_ivar_set_1(); +VALUE rb_ivar_get(); +VALUE rb_ivar_set(); #define Get_Data_Struct(obj, iv, type, sval) {\ VALUE _data_;\ - _data_ = rb_ivar_get_1(obj, iv);\ + _data_ = rb_ivar_get(obj, iv);\ Check_Type(_data_, T_DATA);\ sval = (type*)DATA_PTR(_data_);\ } @@ -197,19 +203,15 @@ VALUE rb_ivar_set_1(); #define Make_Data_Struct(obj, iv, type, mark, free, sval) {\ VALUE _new_;\ sval = ALLOC(type);\ - _new_ = data_new(sval,free,mark);\ + _new_ = data_new(sval,mark,free);\ memset(sval, 0, sizeof(type));\ - rb_ivar_set_1(obj, iv, _new_);\ + rb_ivar_set(obj, iv, _new_);\ } struct RStruct { struct RBasic basic; UINT len; - struct kv_pair { - ID key; - VALUE value; - } *tbl; - char *name; + VALUE *ptr; }; struct RBignum { @@ -219,14 +221,6 @@ struct RBignum { USHORT *digits; }; -struct RAssoc { - struct RBasic basic; - VALUE car, cdr; -}; - -#define CAR(c) (RASSOC(c)->car) -#define CDR(c) (RASSOC(c)->cdr) - #define R_CAST(st) (struct st*) #define RBASIC(obj) (R_CAST(RBasic)(obj)) #define ROBJECT(obj) (R_CAST(RObject)(obj)) @@ -239,7 +233,6 @@ struct RAssoc { #define RDATA(obj) (R_CAST(RData)(obj)) #define RSTRUCT(obj) (R_CAST(RStruct)(obj)) #define RBIGNUM(obj) (R_CAST(RBignum)(obj)) -#define RASSOC(obj) (R_CAST(RAssoc)(obj)) #define FL_SINGLE (1<<8) #define FL_MARK (1<<9) @@ -271,38 +264,75 @@ extern VALUE Qself; #define MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(n)) #define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(n)) +#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n)) -#ifdef SAFE_SIGHANDLE -extern int trap_immediate; -# define TRAP_BEG (trap_immediate=1) -# define TRAP_END (trap_immediate=0) -#else -# define TRAP_BEG -# define TRAP_END -#endif +void *xmalloc(); +void *xcalloc(); +void *xrealloc(); VALUE rb_define_class(); VALUE rb_define_module(); +void rb_include_module(); +void rb_extend_object(); void rb_define_variable(); void rb_define_const(); void rb_define_method(); -void rb_define_single_method(); +void rb_define_singleton_method(); void rb_undef_method(); void rb_define_alias(); void rb_define_attr(); ID rb_intern(); char *rb_id2name(); +ID rb_to_id(); + +char *rb_class2name(); +VALUE rb_method_boundp(); VALUE rb_eval_string(); VALUE rb_funcall(); VALUE rb_funcall2(); int rb_scan_args(); +VALUE rb_iv_get(); +VALUE rb_iv_set(); +void rb_const_set(); + VALUE rb_yield(); +VALUE iterator_p(); + +VALUE rb_equal(); extern int verbose, debug; +#ifdef __GNUC__ +typedef void voidfn (); +volatile voidfn Fail; +volatile voidfn Fatal; +volatile voidfn Bug; +volatile voidfn WrongType; +volatile voidfn rb_sys_fail; +volatile voidfn rb_break; +volatile voidfn rb_exit; +volatile voidfn rb_fail; +#else +void Fail(); +void Fatal(); +void Bug(); +void WrongType(); +void rb_sys_fail(); +void rb_break(); +void rb_exit(); +void rb_fail(); +#endif + +void Warning(); + +#if defined(EXTLIB) && defined(USE_DLN_A_OUT) +/* hook for external modules */ +static char *libs_to_be_linked[] = { EXTLIB, 0 }; +#endif + #endif diff --git a/ruby.texi b/ruby.texi new file mode 100644 index 0000000000..50ffb63a16 --- /dev/null +++ b/ruby.texi @@ -0,0 +1,5044 @@ +\input texinfo @c -*-texinfo-*- created at: Tue Jun 20 16:58:39 JST 1995 +@setfilename ruby.info +@settitle Ruby Reference Manual + +@titlepage +@title Ruby Reference Manual +@subtitle The Object-Oriented Scripting Language +@author Yukihiro Matsumoto +@author matz@@caelum.co.jp +@end titlepage + +@node Top, Ϥ, (dir), (dir) + +Ruby Reference Manual + +@menu +* Ϥ:: +* ޥɥ饤ץ:: +* rubyʸˡ:: +* Ȥ߹ߴؿ:: +* Ȥ߹ѿ:: +* Ȥ߹ߥ饹ȥ⥸塼:: +* CȤΥե:: +* ռ:: +* ʸˡ:: +* Variables Index:: +* Concept Index:: +* Function Index:: +@end menu + +@node Ϥ, ޥɥ饤ץ, Top, Top +@comment node-name, next, previous, up +@chapter Ϥ + +Ruby, ڤʥ֥Ȼظץߥ¸뤿μεǽ +ĥ֥ȻظץȸǤ롥ܳŪʥ֥Ȼظ +ǤSmalltalk, EiffelC++ʤɤǤ礲˻פ褦ΰǤΥ +֥Ȼظץߥٱ礹뤳ȤŪȤ롥߷פδ +§, ʲ̤Ǥ. + +@itemize @bullet +@item + +ǽ + +ñ㳰ξʤʸˡǡ֥Ȼظץߥȥץȥ +ߥΤɬפʵǽʬ. + +@item + +ĥ + +ɬפ˱ưפ˵ǽĥǤ롥饹ͳɲäǤ뤳Ȥ, +CץΥˤäƥץˤ뵡ǽɲäǤ롥 +˥ץåȥեˤäƤ, ưŪ˥֥ȥɤ뵡 +ǽ. + +@item + + + +θ§ΤŬѤ褦ʰΤͤġ +äơ֥ѥγڤפϸΤʤ,Τ +䤹ˤ뤳ȤϤʤ. +@end itemize + +RubyϡּڡפǤϤ뤬ܳŪʥ֥ȻظǽĤΤǡperl, +tcl, pythonʤɥץȸ˥֥Ȼظǽɲä褦ʽ +Ϥ⼫˥֥ȻظǤ롥˥١쥯㳰 +ǽϤŬʥץߥٱ礹롥 + +RubyϥƥȽطεǽ˭٤(perlƱ餤)OSľ +褦ʽҤǤ롥ޤ, ʥ֥ȻظǤ +, ɬפǤм³ץߥǽǤ. + +RubyshperlΤäƤͤˤȤäƤξQˤǤ¤꽾äΤ, +θ̤ƤͤˤȤäƤϽ(¿ʬ)ưפץޤ +RubyΥ֥ȻظǽˤĤƳؤ٤С궯ϤʤȤǤ褦 +ʤ + +@node ޥɥ饤ץ, rubyʸˡ, Ϥ, Top +@comment node-name, next, previous, up +@chapter ޥɥ饤ץ + +rubyץϰʲΰդ. + +@table @samp + +@item -0 + +ϥ쥳ɥѥ졼(@code{$/})8ʿǻꤹ롥 + +ꤷʤϥ̥륭饯ѥ졼ˤʤ롣θ¾Υ +åäƤ褤 + +-00, ѥ饰ե⡼, -0777(Υɤʸ¸ߤʤΤ) +ե٤ɤ߹⡼ɤǤ. + +@item -a +@cindex{ȥץåȥ⡼} + +@code{-n}@code{-p}ȤȤѤ, ȥץåȥ⡼ɤONˤ롥 +ȥץåȥ⡼ɤǤϳƥ롼פƬ, + +@example +$F = $_.split +@end example + +¹Ԥ롥@code{-n}@code{-p}ץƱ˻ꤵʤ¤, +Υץϰ̣ʤ. + +@item -c + +ץȤؤΥѥΤߤԤ, ¹Ԥʤѥ뽪 +λ, ʸˡ顼̵, @samp{"Syntax OK"}ȽϤ. + +@item -K c + +rubyνɤꤹ롥 rubyϻꤵ줿ʸ @code{E} +@code{e}ξʸ䥢եƤΥɤEUC +Ȳꤹ롥Ʊͤ@code{S}ޤ@code{s}ξSJISȤƽ롥 +@code{N}ϴʤǥեȤEUC. + +@example +ruby -CE -e 'print "ƥ"' +ruby -Cs -e 'print "ƥ"' +ruby -Cn -e 'print "ƥ"' +@end example + +ΥץϾʸɤμưȽ̵ǽɲä줿ˤѹ +. + +@item -d +@itemx --debug + +ǥХå⡼ɤonˤ롥Υե饰åȤȥƥѿ +@code{$DEBUG}åȤ. + +@item -e @var{script} + +ޥɥ饤饹ץȤꤹ롥-eץդˤϰ +饹ץȥե̾ʤ. + +@item -F @var{ʸ} + +ϥեɥѥ졼(@code{$;})ͤʸ˥åȤ롥awkƱ̾ +ΥץƱƯ. + +@item -i @var{extension} + +ǻꤵ줿եƤ֤(in-place edit)Ȥꤹ +롥ΥեϳĥҤĤ¸. + +: + +@example +% echo matz > /tmp/junk +% cat /tmp/junk +matz +% ruby -p -i.bak -e '$_.upcase' /tmp/junk +% cat /tmp/junk +MATZ +% cat /tmp/junk.bak +matz +@end example + +ĥҤʤСХååפϤ줺ѹ줿եĤ롥 + +@item -I @var{directory} + +եɤѥ(ɲ)롥ꤵ줿ǥ쥯ȥruby +ѿ@code{$:}ɲä. + +@item -l + +@code{$\}@code{$/}Ʊͤꤷ, @code{print}Ǥνϻ˲Ԥ +ä롥ޤ, @samp{-n}ޤ@samp{-p}ȤȤѤ, Ϥ줿 +ƹԤκǸʸ@code{chop!}. + +@item -n + +Υե饰åȤȥץΤ + +@example +while gets + @dots{} +end +@end example + +ǰϤޤƤ褦ư. +@item -p + +@code{-n}ե饰Ʊ, ƥ롼פκǸѿ@code{$_}ͤϤ. + +: + +@example +% echo matz | ruby -p -e '$_.tr! "a-z", "A-Z"' +MATZ +@end example + +@item -r ե̾ + +ץȼ¹˥ե̾ǻꤵե@code{require}롥 +@samp{-n}ץ@samp{-p}ץȤȤ˻ȤäͭǤ롥 + +@xref{Ȥ߹ߴؿ} + +@item -s + +ץ̾³, @code{-}ǻϤޤᤷ, Ʊ̾ѿ +ꤹ롥@code{--}ʤʹߤϲԤʤʤ +@code{$ARGV}. + +: +@example +#! /usr/local/bin/ruby -s +# -xyzץͿ"true"ɽ. +print "true\n" if $xyz +@end example + +@item -S + +ץ̾@code{/}ǻϤޤäƤʤ, Ķѿ@code{PATH}ͤ +ȤäƥץȤõ ϡ@samp{#!} ݡȤƤʤޥ +ǡ@samp{#!} ˤ¹Ԥߥ졼Ȥ뤿ˡʲΤ褦ˤƻȤ +ȤǤ: + +: +@example +#! /usr/local/bin/ruby +# This line makes the next one a comment in ruby \ + exec /usr/local/bin/ruby -S $0 $* +@end example + +ƥϺǽιԤ̵뤷ץȤ@code{/bin/sh}Ϥ +@code{/bin/sh}rubyץȤ륹ץȤȤƼ¹Ԥ褦Ȥ롥 +2ܤȤǤȲᤷ3ܤ̾Υ륳ޥ +ȤƼ¹Ԥrubyץư롥 + +ƥˤäƤ@code{$0}ɬեѥޤޤʤΤǡ@code{-S} +Ѥrubyɬפ˱ƥץȤõ褦˻ؼ롥ruby +ץȤĤȡιԤβϤϤ뤬ruby2ܤιˤ +Хååˤꡤ2ܤΥȤ3ܤޤǷ³Ȥߤʤơ +3ܤ̵뤹롥 + +ե̾˴ޤޤ륹ڡʤɤˤϡ@code{$*} +@code{$@{1+"$@@"@}}Τۤ褤csh᤹ˤư +@cindex{OS#!ᤷʤк} + +@item -v +@itemx --verbose + +Ĺ⡼ɡư˥СֹɽԤ, ƥѿ +@code{$VERBOSE}åȤ롥ѿåȤƤ, Ĥ +åɤϼ¹Ի˾ĹʥåϤ롥@samp{-v}ץ +ꤵ, ʳΰʤˤϥСɽ, ¹Ԥλ +(ɸϤΥץȤԤʤ). + +@item --version + +rubyΥСɽ. + +ɽ: + +@example +ruby - version 0.87 (95/09/23) +@end example + +@item -x[directory] + +åΥץȤФƼ¹Ԥ롥ץȤɤ߹ˡ +@code{#!}ǻϤޤ, @code{ruby}ȤʸޤԤޤǤɤФ +ץȤν@samp{EOF}(եν), @samp{^D}(ȥD), +@samp{^Z}(ȥZ)ޤͽ@code{__END__}ǻꤹ. + +ǥ쥯ȥ̾ꤹȡץȼ¹˻ꤵ줿ǥ쥯ȥ +ܤ. + +@item -X directory + +ץȼ¹˻ꤵ줿ǥ쥯ȥ˰ܤ. + +@item -y +@itemx --yydebug + +ѥǥХå⡼ɡץȤɽ˥ѥ뤹ιʸ +Ϥβɽ롥ɽ˾ĹʤΤ, ѥ餽ΤΤ +ǥХåͰʳɽʤɤȻפ. +@end table + +@node rubyʸˡ, Ȥ߹ߴؿ, ޥɥ饤ץ, Top +@comment node-name, next, previous, up +@chapter rubyʸˡ + +@menu +* Lexical structure:: +* ץ:: +* :: +@end menu + +@node Lexical structure, ץ, rubyʸˡ, rubyʸˡ +@comment node-name, next, previous, up +@section Lexical structure + +ߤrubyμϥ饯åȤȤASCIIѤ롥rubyʸ +ʸ̤롥̻ҤǤʤǤդΤȤ˶ʸ +Ȥ롥ʸϥڡ(space)(tab)ľ(vertical +tab) CR(carriage return)(form feed)Ǥ롥(newline) +˼³ˤ϶ʸȤơʳǤʸζڤȤƲ +ᤵ롥 + +̻Ҥϱʸ(@samp{"_"}ޤ)Ϥޤꡤѿ³ΤǤ롥 +rubyμ̻ҤŤϤʤߤμϼ̻ҤȤƥޥХȥ +(EUC,SJIS)̤ʤ + +̻Ҥ + +@example +foobar +ruby_is_simple +@end example + +@menu +* :: +* ͽ:: +* ڤʸ:: +@end menu + +@node , ͽ, Lexical structure, Lexical structure +@comment node-name, next, previous, up +@subsection + + + +@example +# this is a comment line +@end example + +ץȸνˤʤ餤ʸʸɽ(@code{?#})ʳ +@code{#}ޤǤϥȤȸʤȹΥХåå +ϼιԤؤΥȤη³̣롥 + +@node ͽ, ڤʸ, , Lexical structure +@comment node-name, next, previous, up +@subsection ͽ + +ͽϰʲ̤Ǥ + +@display +alias def for redo undef +and defined? if rescue when +begin else in retry while +break elsif module return yield +case end nil self __END__ +class ensure not super __FILE__ +continue fail or then __LINE__ +@end display + +ͽϥ饹̾å̾ѿ̾ʤɤѤ뤳ȤϤǤʤ +@samp{$}, @samp{@@}ƬˤĤΤͽȸʤʤΤǡ +ХѿѿˤĤƤʤ + +@node ڤʸ, , ͽ, Lexical structure +@comment node-name, next, previous, up +@subsection ڤʸ + +ʸʤɤΥƥʳξζʸ(֤ȥڡ)Ӳ +(@samp{\n})ڤ국Ȥʤ롥˲Ԥ + +@example +a + +b +@end example + +Τ褦˹ԤǽꡤιԤ³Ȥ(Ǹʸ +黻Ҥ뤤@code{,}Ǥ)ζڤȤǧ롥 + +@node ץ, , Lexical structure, rubyʸˡ +@comment node-name, next, previous, up +@section ץ + + + +@example +print "hello world!\n" +@end example + +ץϼ¤٤ΤǤ롥ȼδ֤ϥߥ(@code{;})ޤ +ϲԤǶڤ롥 + +@node , , ץ, rubyʸˡ +@comment node-name, next, previous, up +@section + + + +@example +TRUE +(1+2)*3 +foo() +if test then ok else ng end +@end example + +RubyǤ@code{nil}ʳɾ롥CPerlʤɤȤϰۤ +ꡤ0@code{""}(ʸ)ϵȤɾʤΤǵĤ뤳ȡ + +ϳ̤ˤäƥ롼ԥ뤳ȤǤ롥 + +@menu +* ʸ:: +* ޥɽ:: +* ɽ:: +* ѿŸ:: +* ͥƥ:: +* ѿ:: +* Хѿ:: +* ѿ:: +* 饹:: +* ѿ:: +* ѿ:: +* :: +* Ϣ:: +* åɸƽм:: +* SUPER:: +* :: +* 黻Ҽ:: +* 湽¤:: +* 饹:: +* ⥸塼:: +* å:: +* ðۥå:: +* ALIAS:: +* UNDEF:: +* DEFINED?:: +@end menu + +@node ʸ, ޥɽ, , +@comment node-name, next, previous, up +@subsection ʸ +@cindex ʸ + + + +@example +"this is a string expression\n" +'ʸ' +@end example + +֥륯(@code{"})dz줿ʸϥХåå³ʸ +ʲΤ褦˲ᤵ롥 + +Хåå嵭ˡ + +@table @samp +@item \t +(0x09) +@item \n +ʸ(0x0a) +@item \r +ʸ(0x0d) +@item \f +ڡʸ(0x0c) +@item \b +Хåڡ(0x08) +@item \a +٥(0x07) +@item \e +(0x1b) +@item \nnn +8ʿɽ(n0-7) +@item \xnn +16ʿɽ(n0-9,a-f) +@item \cx +ȥʸ(xASCIIʸ) +@item \x +ʸxΤ +@end table + +ޤ@code{#}ˤѿŸԤ롥 + +@xref{ѿŸ} + +륯(@code{'})dz줿ʸϡ@code{\\}(Хå +å夽Τ)@code{\'}(륯)ơʸȤ +Ԥʤ + +ʸʸ֥ȤΤǡʸƤ +Ƥ⡤ȤȤʸѤʤ + +@node ޥɽ, ɽ, ʸ, +@comment node-name, next, previous, up +@subsection ޥɽ +@cindex ޥɽ + + + +@example +`date` +@end example + +RubyǤshΤ褦˥ޥɤμ¹Է̤ʸƥΤ褦˻ȤȤ +Ǥ롥@code{``}ǰϤޤ줿ʸϡ֥륯ȤǰϤޤ줿ʸ +Ʊͤ˥Хåå嵭ˡβѿŸԤʤ줿塤ޥɤȤ +Ƽ¹Ԥ졤μ¹Է̤ʸȤͿ롥ޥɤɾ +Ӥ˼¹Ԥ롥 + +@node ɽ, ѿŸ, ޥɽ, +@comment node-name, next, previous, up +@subsection ɽ +@cindex ɽ + + + +@example +/^ruby the OOPL/ +/ruby/i +@end example + +@code{/}ǰϤޤ줿ʸɽɽ@code{/}θʸ +@code{i}Ϳ줿ˤϡɽϥޥåʸʸζ +̤ʤ + +@table @code +@item ^ +Ƭ +@item $ + +@item . +Ǥդ1ʸ +@item \w +ѿ[0-9A-Za-z_]Ʊ +@item \W +ѿ +@item \s +ʸ[ \t\n\r\f]Ʊ +@item \S +ʸ +@item \d +[0-9] Ʊ +@item \D + +@item \b +춭ʸ(ʸ饹) +@item \B +춭ʸ +@item \b +(0x08)(ʸ饹) +@item [ ] +ʸ饹 +@item * +ľɽ0ʾη֤ +@item + +ľɽ1ʾη֤ +@item {m,n} +mnη֤ +@item ? +0ޤ1 +@item | + +@item ( ) +ɽޤȤ +@end table + +¾ʸƱХåå嵭ˡѿŸͭǤ롥 + +@node ѿŸ, ͥƥ, ɽ, +@comment node-name, next, previous, up +@subsection ѿŸ +@cindex ѿŸ + + + +@example +"my name is #@{$ruby@}" +@end example + +֥륯(@code{"})ǰϤޤ줿ʸޥʸɽ +ӥ磻ɥɼǤ@code{#{ѿ̾}}ȤѿƤ +Ÿ뤳ȤǤ롥ѿѿ(@code{$},@code{@@})ǻϤޤ +@code{#ѿ̾}ȤǤŸǤ롥ʸ@code{#}³ʸ +@code{@{},@code{$},@code{@@}ǤʤСΤޤʸ@code{#}ȤƲ +롥 + +@node ͥƥ, ѿ, ѿŸ, +@comment node-name, next, previous, up +@subsection ͥƥ + +@table @samp +@item 123 + +@item -123 +(Ĥ) +@item 1_234 +(10ʿ@code{_}ޤळȤǤ) +@item 123.45 +ư +@item 1.2e-3 +ư +@item 0xffff +16 +@item 0377 +8 +@item ?a +ʸ@code{a}Υ(97) +@item ?\C-a +ȥaΥ(1) +@item ?\M-a +aΥ(225) +@item ?\M-\C-a +-ȥaΥ(129) +@item :ܥ +̻/ѿ̾/黻ҤȰабsendʤɤǥåɤꤹ +ʤɤ˻Ȥ +@end table + +?ɽǤƤΥХåå嵭ˡͭǤ롥 + +@node ѿ, , ͥƥ, +@comment node-name, next, previous, up +@subsection ѿ + +Rubyѿϥ(ͭϰ)ȼ̿(ͭ)ˤä4ʬव졤 +μѿ̾κǽΰʸǷꤵ롥̾ѿ2ʸܰʹߤ +ѿޤ@code{_}Ǥ뤬ƥѿΰϡ@code{$}+1ʸε +פȤѿ롥ѿ̾Ĺ˴ؤ̤¤Ϥʤ + +@menu +* Хѿ:: +* ѿ:: +* 饹:: +* ѿ:: +* ѿ:: +@end menu + +@node Хѿ, ѿ, ѿ, ѿ +@comment node-name, next, previous, up +@subsection Хѿ + + + +@example +$foobar +$/ +@end example + +@code{$}ǻϤޤѿΥפϥХǤꡤץΤɤ +Ǥ⻲ȤǤ롥μ̿ϥץμ̿Хѿˤ +ɬפʤƤʤХѿȤͤ +@code{nil}Ǥ롥 + +@node ѿ, 饹, Хѿ, ѿ +@comment node-name, next, previous, up +@subsection ѿ + + + +@example +@@foobar +@end example + +@code{@@}ǻϤޤѿϥѿǤꡤΥ饹ޤϥ֥ +饹Υåɤ黲ȤǤ롥פϥåǤꡤμ̿ϥ +֥Ȥμ̿ѿˤɬפʤ +ƤʤѿȤͤ@code{nil}Ǥ롥 + +@node 饹, ѿ, ѿ, ѿ +@comment node-name, next, previous, up +@subsection 饹 + + + +@example +FOOBAR +@end example + +ʸǻϤޤ뼱̻ҤؤΥǤꡤǽ줿饹 +ƤΥ֥饹ΥǻȤǤ롥 +Ƥ⥸塼롼ɤ뤳ȤˤäƹԤʤ롥ؤ +ϥȥåץ٥롤ʤåɤǤ٥ǤΤ߲ǽǤ롥 +ϥ饹֤ͤͭ졤ͤѹ뤳ȤǤʤ +(㳰ȯ)饹μ̿ϥ饹μ̿ +Ƥʤ饹Ȥͤ@code{nil}Ǥ롥 + +饹ϼưŪΤǡ饹̾Ǥ롥 + +륯饹ޤϥ⥸塼°黲Ȥ뤿ˤ +@code{::}黻ҤѤ롥 + + +@example +Foo::Bar +@end example + +@code{::}黻ҤѤϤǤʤ + +@node ѿ, ѿ, 饹, ѿ +@comment node-name, next, previous, up +@subsection ѿ + + + +@example +foobar +@end example + +ʸޤ@code{_}ǻϤޤ뼱̻ҤϥѿޤϥåɸƽФ +롥ѿפˤ뾮ʸǻϤޤ뼱̻Ҥؤκǽ +Υפ°ѿˤʤ롥Ƥʤ̻Ҥ +Ȥϰ̵åɸƤӽФȤߤʤ롥 + +ѿΥפϡѿ줿ƥ졼֥å +ޤϥ饹/⥸塼֥åνޤǤǤ롥̿⤽ +Υ֥åνޤ(ȥåץ٥Υѿϥץνλޤ) +Ǥ뤬㳰Ȥƥƥ졼֥å³֥Ȳ줿 +ϡΥ֥ȤǤޤ¸ߤ롥ƱפȤ³ +֥ȴ֤Ǥϥѿ϶ͭ롥 + +@node ѿ, ѿ, ѿ, ѿ +@comment node-name, next, previous, up +@subsection ѿ + +̾ѿʳ˵ѿȸƤФüѿ4Ĥ롥 + +@table @code +@item self +ߤΥåɤμ¹Լ +@item nil +Nil饹ͣΥ(ɽ) +@item __FILE__ +ץȤΥե̾(ʸ) +@item __LINE__ +ߤιֹ() +@end table + +εѿˤäƤͤѹ뤳ȤϤǤʤ +ѿؤ㳰ȯ롥 + +@node , Ϣ, ѿ, +@comment node-name, next, previous, up +@subsection + + + +@example +[1, 2, 3] +@end example + +Array饹ΥǤ롥뼰ϰʲη +롥 + +@example +@code{[} ,@dots{}@code{]} +@end example + +줾μɾ̤ޤ֤ǿ0ζ +뤿ˤ϶ + +@example +@code{[} @code{]} +@end example + +Ѥ롥 + +@node Ϣ, åɸƽм, , +@comment node-name, next, previous, up +@subsection Ϣ + + + +@example +@{1=>2, 2=>4, 3=>6@} +@end example + +ϢȤǤդΥ֥Ȥ(ź)ȤƻǤ롥Ruby +ϢHash(Ϣ)饹ΥǤ롥ܺ٤ϥ饹 +@code{Hash}ιȤ줿@xref{Hash} + +ϢϢϰʲηǤ롥 + +@example +@code{@{} @code{=>} @dots{}@code{@}} +@end example + +줾μɾ̤ͤȤϢ֥Ȥ֤ +ǿ0Ϣ뤿ˤ϶Ϣ + +@example +@code{@{} @code{@}} +@end example + +Ѥ롥Ǥ1İʾ夢硤ۣǤʤ@code{@{}, @code{@}} +άǤ롥 + +@node åɸƽм, SUPER, Ϣ, +@comment node-name, next, previous, up +@subsection åɸƽм + + + +@example +foo.bar() +foo.bar +bar() +print "hello world\n" +print +@end example + +֥Ȥ˥åŪʹʸåǤꡤδ +ܷϰʲ̤Ǥ롥 + +@display +1 `.' å̾ [`(' @dots{}[`*' ] `)'] +@end display + +1ɾ륪֥ȤΡ̻ҤǻꤵåɤƤ +Ф + +å̾ˤ̾μ̻Ҥ¾̻Ҥ@code{?}ޤ@code{!}³ +Τ롥ȤơҸ(֤ͤå)ˤ@code{?} +Ʊ̾Υåɤ٤Ƥ˲ŪʺѤĥå(:@code{tr} +@code{tr!})ˤ@code{!}Ĥ롥 + +åǡ쥷Ф@code{self}ξ硤쥷Фά̾ +ץߥˤؿΤ褦ʷǥåɤƤӽФȤ +롥 + +@display +å̾ `(' @dots{}[`*' ]`)' +@end display + +åɸƤӽФΰμγ̤άǤ뤬Ȥʤ뼰 +ʸޤͽǻϤޤϡۣ롥 + +@example +(, [, @{, /, +, -, if, while, * +@end example + +ruby1Τ褦˸ʬʹ֤ˤȤäƼȻפ褦 +黻Ҥζʤ顤㴳ʣʥ롼Dz᤹롥ͽ̤η +̤ʤäꡤɤΤ褦ɾ뤫ʬʤϾά +̤Ĥ + + + +@example +foo bar+baz # åɸƤӽФfoo(bar+baz) +foo(1+2)*5 # åɸƤӽФ(foo(1+2)) * 5 +foo (1+2)*5 # åɸƤӽФfoo((1+2) * 5) +foo 1 # åɸƤӽФfoo(1) +foo -1 # åɸƤӽФfoo(-1) +foo - 1 # ѿfoo - 1 +@end example + +åɸƤӽФǤϰ1Ĥʤˤ̤άǤ롥 +ФꤷʤåɸƤӽФξϥѿλȤȲᤵ +롥 + +å̾ȤƤǤդμ̻ҤѤ뤳ȤǤ롥ǽʸʸ +Ǥ⾮ʸǤʤѿ̾Ȥϼ̻Ҥ֤̾㤦ΤǽʣƤ +ʤ + +饹ModuleƤå(@code{public},@code{private})ǥ +åɤθƤӽФ椹뤳Ȥ롥@code{private}ǻꤵ줿 +¤줿åɤϴؿǤƤӽФȤʤ + +@node SUPER, ,åɸƽм, Ϣ, +@comment node-name, next, previous, up +@subsection SUPER + + + +@example +super +super(1,2,3) +@end example + +åüʥȤƥѡ饹ΥåɤθƤӽФ +롥ηϥåɤ˥ѡ饹Ѥ뤿 +˻Ȥ + +@display +super +@end display + + +ߤΥåɤͿ줿Τޤޥѥ饹Ʊ̾ΥåɤƤ +ФȤͿ줿ѿͤѹƤ⡤ϤΤϸΰ +ͤǤ롥 + +@display +super`(' @dots{}`)' +@end display + +ȤȤ˥ѡ饹Ʊ̾ΥåɤƤӽФֺǸΰ +@code{*}³̾ΥåɸƤӽФƱͤŸϤ롥 + +@node , 黻Ҽ, SUPER, +@comment node-name, next, previous, up +@subsection + + + +@example +foo = bar +foo[0] = bar +foo.bar = baz +@end example + +ѿʤɤͤꤹ뤿Ѥ롥ϱ黻ҷȤ +Ƥ뤬åɤǤϤʤΤǺ뤳ȤϤǤʤդˤʤ뤳 +Τϰʲ3μǤ롥 + +ѿ(`$'̻ | `@@'̻ | ̻) + +@display +ѿ `=' +@end display + +ѿؤϱդμɾ줿ͤդǻꤵ줿ѿ +롥 + +([@dots{}]) + +@display +1`[' 2@dots{}`]' `=' n +@end display + +ȼؤϡ1ɾ륪֥Ȥˡ2鼰n +ޤǤȤơ@code{[]=} ȤåɤƤӽФ + +°(`.'̻) + +@display +1 `.' ̻ `=' 2 +@end display + +°(ʤΥåɸƤӽФ)ؤϡ1ɾ +֥(쥷Фά줿@code{self})Фơ +@code{̻=}Ȥåɤ2ȤƸƤӽФ + +@menu +* :: +* ¿:: +@end menu + +@node , ¿, , +@comment node-name, next, previous, up +@subsubsection + + + +@example +foo += 12 +@end example + +ͤΤΤ˱黻ä뤿˼롥 + +@display +1 op= 2 # 1ǽǤʤФʤʤ +@end display + +ηŪ@code{1 = 1 op 2}Ʊͤɾ롥 +11ɾʤΤǡ1Ѥϡ +@code{1 = 1 op 2}Ȥưۤʤ̤Ȥʤ롥 +opȤƻȤ黻Ҥ + +@display + +, -, *, /, %, **, &, |, ^, <<, >> +@end display + +11Ǥ롥黻Ҥ@code{=}δ֤˥ڡƤϤʤ + +@node ¿, , , +@comment node-name, next, previous, up +@subsubsection ¿ + + + +@example +foo, bar, baz = 1, 2, 3 +foo, = list() +foo, *rest = list2() +@end example + +ƱʣѿԤʤȤǤ롥ηϰʲ̤Ǥ롥 + +@display + `,' [ `,'@dots{}] [`*' ]= [, @dots{}] +@end display + +դˤ3μ롥դμĤʤϡ +Ȥ(ɬפʤ@code{to_a}åɤѴ)Ǥ +줾캸դ롥ʳξˤϡ줾μͤդ +롥դοȱդǤοʤˤʤѿˤ +@code{nil}졤;äǤ̵뤵롥¿κǸǤ +@code{*}硤ĤưȤ롥 + + + +@example +foo, bar = [1, 2] # foo = 1; bar = 2 +foo, bar = 1, 2 # foo = 1; bar = 2 +foo, bar = 1 # foo = 1; bar = nil + +foo, bar, baz = 1, 2 # foo = 1; bar = 2; baz = nil +foo, bar = 1, 2, 3 # foo = 1; bar = 2 +foo,*bar = 1, 2, 3 # foo = 1; bar = [2, 3] +@end example + +¿ͤ(Ѵ줿)դǤ롥 + +@node 黻Ҽ, 湽¤, , +@comment node-name, next, previous, up +@subsection 黻Ҽ + + + +@example +1+2*3/4 +@end example + +ץߥؤΤ˰ΥåɸƤӽФ湽¤ϱ黻ҷ +Ȥ롥Rubyˤϰʲˤ黻Ҥ롥ΤΤۤɷ̤ +Ʊα黻Ҥη̤ƱǤ롥 +@cindex{絬§} + +@display + :: + [](), []=() + ** + -(unary) +(unary) ! ~ + * / % + + - + << >> + & + | ^ + > >= < <= + <=> == != =~ !~ + && + || + .. ... + =() (+=, -=@dots{}) + and or + not + if while +@end display + +ۤȤɤα黻ˤϥåɸƤӽФȤƲᤵ(饹˺ +Ǥ)ǤʤüʤΤ롥Ǥʤü黻 +Ҥ + +@display + =, .., ..., !, not, &&, and, |, or, if, while +@end display + +γƱ黻ҤȡȤȤ߹碌ˤʤ !=, !~ Ӽ黻Ҥ +롥 + +Ǥü黻Ұʳα黻ҷϰʲΤ褦ʥåɸƤӽФȸ +ʤ롥 + +ñ黻(+, -, ~) + +@display +1. 黻 () +@end display + +(Ϣޤ)Ǥλ(1 `[' 2@dots{}`]') + +@display +1. `[]' (2@dots{}) +@end display + +Ǥ( 1 `[' 2@dots{}`]' `=' n) + +@display +1. `[]=' (2@dots{}, n) +@end display + +ʳ2黻(1 黻 2) + +@display +1. 黻 (2) +@end display + +ϤޤǤ⤽ΥåɸƤӽФȤƲᤵȤ +ǡrubyץǤҤȤ櫓ǤϤʤ + +@node 湽¤, 饹, 黻Ҽ, +@comment node-name, next, previous, up +@subsection 湽¤ + +RubyǤ(CʤɤȤϰۤʤ)湽¤ϼǤꡤ餫ͤġ +lispʤɤ˻ƤȤ롥RubyCPerlѤ湽¤ +ĤħŪ湽¤Ȥƥƥ졼ġƥ졼Ϸ֤Ϥ +Ȥ桼ΤǤ. +@xref{ƥ졼(֤)} + +@menu +* IF:: +* IF:: +* CASE:: +* AND:: +* OR:: +* ϰϻ꼰:: +* NOT:: +* WHILE:: +* WHILE:: +* ƥ졼(֤):: +* FOR:: +* YIELD:: +* FAIL:: +* BEGIN:: +* RETRY:: +* RETURN:: +* BREAK:: +* CONTINUE:: +* REDO:: +@end menu + +@node IF, IF, 湽¤, 湽¤ +@comment node-name, next, previous, up +@subsubsection IF + + + +@example +if age >= 12 then print "adult fee\n" else print "child fee\n" end +gender = if foo.gender == "male" then "male" else "female" end +@end example + +ʸ + +@display +if 1 [then] + @dots{} +[elsif 2 [then] + @dots{}]@dots{} +[else + @dots{}] +end +@end display + +ȽǼRuby@code{if}@code{else if}Ǥ@code{elif}Ǥʤ +@code{elsif}@code{if}Ϣ³ԤʤȤդ뤳ȡ郎Ω +Ƽ¹Ԥ֤ͤ¹Ԥʤäͤ@code{nil} + +@code{if}ξȽμǤʸɽƥϼ +@example +$_=~ ƥ +@end example +ξάǤȤߤʤ롥 + +@node IF, CASE, IF, 湽¤ +@comment node-name, next, previous, up +@subsubsection IF + + + +@example +print "debug\n" if $debug +@end example + +ʸ + +@display + if +@end display + +、(@code{if})μԤ뼰äɾ롥ưб +@code{if}ƱͤǤ롥@code{if}ҤΤĤͤϾ郎Ω +ˤϼ͡Ωξˤ@code{nil}Ǥ롥 + +@node CASE, AND, IF, 湽¤ +@comment node-name, next, previous, up +@subsubsection CASE + + + +@example +case $age +when 0 .. 2 + "baby" +when 3 .. 6 + "little child" +when 7 .. 12 + "child" +when 12 .. 18 + "youth" +else + "adult" +end +@end example + +ʸ + +@display +case 0 +[when 1 [, 2]@dots{}[then] + @dots{}]@dots{} +[else + @dots{}] +end +@end display + +ʬC@code{switch}Pascal@code{case}˻Ƥ롥 +@code{break}æФ뤳Ȥμ˷³뤳ȤʤΤա + +ΰפ@code{n =~ 0}ǹԤʤ롥Ĥޤꡤ + +@example +case expr0 +when expr1, expr2 + stmt1 +when expr3, expr4 + stmt2 +else + stmt3 +end +@end example + +ϰʲ@code{if}ȤۤǤ롥 + +@example +_tmp = expr0 +if expr1 =~ _tmp || expr2 =~ _tmp + stmt1 +elsif expr3 =~ _tmp || expr4 =~ _tmp + stmt2 +else + stmt3 +end +@end example + +@node AND, OR, CASE, 湽¤ +@comment node-name, next, previous, up +@subsubsection AND + + + +@example +test && set +test and set +@end example + +ʸ + +@display +1 `&&' 2 +1 `and' 2 +@end display + +1ɾͤ(@code{nil}ʳ)ǤС2ɾ롥 +@code{and}̤ͥ㤤̾Ǥ롥 + +@code{and}ξդμǤʸɽƥϼ +@code{$_ =~ ƥ} ξάǤȤߤʤ롥 + +@node OR, ϰϻ꼰, AND, 湽¤ +@comment node-name, next, previous, up +@subsubsection OR + + + +@example +demo || die +demo or die +@end example + +ʸ + +@display +1 `||' 2 +1 'or 2 +@end display + +1ɾͤǤС2ɾ롥@code{or}̤ͥ +㤤̾Ǥ롥 + +@code{or}ξդμǤʸɽƥϼ +@code{$_ =~ ƥ}ξά +ǤȤߤʤ롥 + +@node ϰϻ꼰, NOT, OR, 湽¤ +@comment node-name, next, previous, up +@subsubsection ϰϻ꼰 + + + +@example +1 .. 20 +/first/ ... /second/ +@end example + +ʸ + +@display +1 `..' 2 +1 `...' 2 +@end display + +PʳξǤϼ1鼰2ޤǤϰϥ֥Ȥ֤ + +PȤϰϻ꼰Ѥ줿ϡ1ˤʤޤǤϵ֤ +θϼ2֤ޤǤϿ֤2ˤʤо֤ϵ롥 +@code{..}ϼ1ˤʤä˼2ɾ(awkΤ褦)@code{...}ϼ +ɾޤǼ2ɾʤ(sedΤ褦) + +Pϰϻ꼰ξդȤʤ뼰Ǥϡʸɽƥϼ +@code{$_ =~ ƥ}ξά@code{$. == }ξάȲᤵ +롥 + +@node NOT, WHILE, ϰϻ꼰, 湽¤ +@comment node-name, next, previous, up +@subsubsection NOT + + + +@example +! me +not me +i != you +@end example + +ʸ + +@display +`!' +not +@end display + +ǤеǤп֤ + +@code{!}Ǥʸɽƥϼ@code{$_ =~ ƥ}ξά +ǤȤߤʤ롥 + +@display +1 `!=' 2 +@end display + +@code{!(1 == 2)}ξά + +@display +1 `!~' 2 +@end display + +@code{!(1 ~= 2)}ξά + +@node WHILE, WHILE, NOT, 湽¤ +@comment node-name, next, previous, up +@subsubsection WHILE + + + +@example +while sunshine() + work() +end +@end example + +ʸ + +@display +while + @dots{} +end +@end display + +ɾͤδ֡Τ֤¹Ԥ롥@code{while}ͤ +@code{nil}Ǥ롥 + +whileξȽμǤʸɽƥϼ +@code{$_ =~ ƥ} ξάǤȤߤʤ롥 + +@node WHILE, ƥ졼(֤), WHILE, 湽¤ +@comment node-name, next, previous, up +@subsubsection WHILE + + + +@example +sleep while idle +@end example + +ʸ + +@display +ñ㼰 while +@end display + +μɾͤδ֡ñ㼰֤¹Ԥ롥ñ㼰 +@code{begin}ǤϤޤ@code{begin}ɾƤPɾ +(٤begin¹Ԥ)@code{while}ҤΤĤͤ +@code{nil}Ǥ롥 + +@node ƥ졼(֤), FOR, WHILE, 湽¤ +@comment node-name, next, previous, up +@subsubsection ƥ졼(֤) + + + +@example +[1,2,3].each@{|i| print i*2, "\n"@} +@end example + +ƥ졼Ȥ湽¤(ä˥롼)ݲΤѤåɤ +Ǥ롥ɤ(֥åȸƤФ)ꤷƥƥ졼Ƥ +Фȡƥ졼ŬͤåȤƥ֥åɾ(餯 +ʣ)ƥ졼Υ֥åθƤӽФ@code{yield}Ѥ( +) + +ƥ졼θƤӽФϰʲιʸǹԤʤ롥 + +@display + `@{' [`|' ռ@dots{}`|'] @dots{}`@}' +@end display + +ּפ֥åȤꤷּפΥåɤƥ졼Ȥɾ +롥ּפΥȥåץ٥Υåɤƥ졼ȤƸƤӽФ졤 +쥷Фɽ䡤μϥƥ졼ȤƤϸƤӽФʤּ +ʣμޤơƥ졼Ȥƽ˸ƤФ롥 + +ƥ졼@code{yield}¹Ԥȡǻꤵ줿ͤռ +ǻꤵ줿ѿ졤֥å¹Ԥ롥֥åμ¹Ԥλ +Ȥͤ @code{yield}ͤȤ֤롥åɤƥ졼 +ȤƸƤӽФ줿ɤϥå@code{iterator?}ͤΤ뤳 +ȤǤ롥ˤ@code{Enumerable:grep}åɤΤ褦˥ƥ졼Ȥ +ƸƤФ줿̤ΥåɤȤƸƤФ줿Ȥưۤʤåɤ +롥 + +@node FOR, YIELD, ƥ졼(֤), 湽¤ +@comment node-name, next, previous, up +@subsubsection FOR + + + +@example +for i in [1, 2, 3] + print i*2, "\n" +end +@end example + +֥ȤγǤФԤʤηƤ롥 +ϰʲ̤ꡥ + +@display +for ռ@dots{} in + +end +@end display + +γǤФ¹Ԥ롥ϰʲμȤۤǤ롥֤ۤܡ +ȤΤϡƥ졼֥åϿѿͭϰϤƳ +ΤФ@code{for}ʸϥѿΥפ˱ƶڤܤʤ +ʤ뤫Ǥ + +@display +().each `@{' `|' ռ@dots{}`|' `@}' +@end display + +äƼͤΥ֥Ȥå@code{each}ʤ硤 +@code{for}¹Ԥ㳰ȯ롥 + +@node YIELD, FAIL, FOR, 湽¤ +@comment node-name, next, previous, up +@subsubsection YIELD + + + +@example +yield data +@end example + +ʸ + +@display +yield `(' [ [`,' @dots{}]]) +@end display + +ƥ졼ǥ֥åθƤӽФԤʤ@code{yield}¹Ԥ +ɤƥ졼ȤƸƤӽФƤʤˤ㳰ȯ롥 +@code{yield} ͤϥ֥åͤǤ롥 + +@code{yield}ΰγ̤ۣǤʤ¤άǤ롥 + +@node FAIL, BEGIN, YIELD, 湽¤ +@comment node-name, next, previous, up +@subsubsection FAIL + + + +@example +fail +fail "you lose" +@end example + +ʸ + +@display +fail `(' [å] `)' +@end display + +㳰ȯ롥åͿ줿ˤȯե +ֹ̾ƥѿ@code{$@@}ˡå@code{$!}˥åȤ롥 + +@code{fail}ΰγ̤ϾάǤ롥 + +@node BEGIN, RETRY, FAIL, 湽¤ +@comment node-name, next, previous, up +@subsubsection BEGIN + + + +@example +begin + do_something() +rescue + recover() +ensure + must_to_do() +end +@end example + +ʣμޤȤ뤿㳰Τ@code{begin}롥 +@code{begin}ηϰʲ̤Ǥ롥 + +@display +begin + @dots{} +[rescue + @dots{}] +[ensure + @dots{}] +end +@end display + +@code{begin}ͤϰֺǸɾ줿ͤǤ롥@code{begin} +ȯ㳰@code{rescue}ͤ뤳Ȥ롥 +@code{begin}ͤϤ@code{rescue}ǺǸɾͤ +롥@code{ensure}¸ߤ@code{begin}λɬ +(ェλǤʤ㳰, @code{return}, @code{break}, +@code{continue}, @code{redo}ʤɤˤæФǤ)@code{ensure}μɾ +롥 + +@node RETRY, RETURN, BEGIN, 湽¤ +@comment node-name, next, previous, up +@subsubsection RETRY + + + +@example +retry +@end example + +ʸ + +@display +retry +@end display + +Ƽ¹ԡ@code{begin}@code{rescue}ǻȤ줿硤@code{begin} +Ϥᤫ⤦ټ¹Ԥ롥㳰ԤʤäƤƻԤΤ˻Ȥ + +@example +begin + 餫ν(㳰ȯ) +rescue + 㳰 + retry # 㳰бƺƼ¹ +end +@end example + +ƥ졼ƥ졼֥åޤforʸǻȤ줿ˤϡ +ƥ졼ɾΤǽ餫¹Ԥ롥ƥ졼ΰɾ롥 + +@example +for i in 1..5 + retry if some_condition # i == 1 ľ +end +@end example + +@example +# 桼until loop +def until(cond) + yield + retry if not cond +end +@end example + +@code{rescue}䥤ƥ졼ʳretryѤ줿㳰ȯ롥 + +@node RETURN, BREAK, RETRY, 湽¤ +@comment node-name, next, previous, up +@subsubsection RETURN + + + +@example +return +return 12 +return 1,2,3 +@end example + +ʸ + +@display +return [[`,' @dots{}]] +@end display + +ͤͤȤƥåɤμ¹Ԥλ롥2İʾͿ줿 +ˤϡǤȤåɤͤȤ롥Ĥʤ +ˤ @code{nil} ͤȤʤ롥 + +@node BREAK, CONTINUE, RETURN, 湽¤ +@comment node-name, next, previous, up +@subsubsection BREAK + + + +@example +break +@end example + +ʸ + +@display +break +@end display + +@code{break} ϥ롼פæФ롥CȰ㤤@code{break}ϤäȤ¦ +롼פæФѤ@code{case} ȴѤϻʤ + +@node CONTINUE, REDO, BREAK, 湽¤ +@comment node-name, next, previous, up +@subsubsection CONTINUE + + + +@example +continue +@end example + +ʸ + +@display +continue +@end display + +@code{continue}ϤäȤ¦Υ롼פμη֤Ϥ롥 + +@node REDO, 湽¤, CONTINUE, 湽¤ +@comment node-name, next, previous, up +@subsubsection REDO + + + +@example +redo +@end example + +ʸ + +@display +redo +@end display + +@findex redo +@code{redo}ϥ롼ΥåԤʤ鷺ߤη֤ľ + +@node 饹, ⥸塼, 湽¤, +@comment node-name, next, previous, up +@subsection 饹 +@cindex 饹 + + + +@example +class Foo:Super + def test + : + end + : +end +@end example + +ʸ + +@display +class 饹̾ [`:' ѡ饹̾ ] + +end +@end display + +@findex class +饹̾ʸǻϤޤ뼱̻ҤǤ롥 + +@node ⥸塼, å, 饹, +@comment node-name, next, previous, up +@subsection ⥸塼 +@cindex ⥸塼 + + + +@example +module Foo + def test + : + end + : +end +@end example + +ʸ + +@display +module 饹̾ + +end +@end display + +@findex module +⥸塼̾ʸǻϤޤ뼱̻ҤǤ롥 + +@node å, ðۥå, ⥸塼, +@comment node-name, next, previous, up +@subsection å +@cindex åɤ + + + +@example +def fact(n) + if n == 1 then + 1 + else + n * fact(n-1) + end +end +@end example + +ʸ + +@display +def å̾ [`(' [ [= ǥե]]@dots{}[`,' `*' ]`)'] + +end +@end display +@findex def + +˥ǥեȼͿ줿硤åɸƤӽФ˰Ϳ +ʤäˤϥǥեȼɾ̤ǽ(ǥեȼ +ɾϸƤӽФ˹Ԥ)ֺǸΰ@code{*}³(ñ) +Ǥ硤μɾ(ǤʤѴ)Ÿơ +Ȥɲä롥 + +̾åϥͥȤǤʤΤǡåǤϥå +ƤӸƤӽФʤ + +å̾ϼ̻ҤޤʸǤ롥黻Ҥκˤʸ +ǻꤹ롥¤ӤκǸ@code{*}硤¿Ϳ +줿°ϡǸΰȤͿ(ʤˤϥ顼) + +åɤˤϸƤӽФ¤ä뤳ȤǤ¤ä줿åɤϡ +ؿǤƤӽФʤ(privateå) + +˥åɤ硤饹γˤdefϥǥե +Ǥprivateåɤ饹ˤdefpublic +ɤ롥ѡ饹Υåɤˤ +åɤβĻϥѡ饹ΥåɤΤΤѤ + +åɤβĻѹˤ@code{Module}饹Ƥ +@code{public}, @code{private}γƥåɤѤ롥 + +@node ðۥå, ALIAS, å, +@comment node-name, next, previous, up +@subsection ðۥå + + + +@example +def foo.test() + print "this is foo\n" +end +@end example + +ʸ + +@display +def `.' å̾ [`(' [ [= ǥե]]@dots{}[`,' `*' ]`)'] + +end +@end display + +ðۥåɤȤϤΥ֥Ȥ˸ͭΥåɤǤ롥 + +ηϼͤǤ륪֥Ȥðۥåɤ롥ͤ +(ӥȥ饹Ǥʤ)̾索֥Ȥ饹ޤϥ⥸塼Ǥ +ɬפ롥̾åȤϰۤʤꡤðۥåɤϥå +ǤͥȤ뤳ȤǤ롥 + +ðۥåɤ̾ϷѾʤ㳰Ȥƥ饹ðۥåɤϤ +֥饹ˤѾ롥ؤХ饹ðۥåɤ¾Υ֥ +Ȼظƥˤ륯饹åɤƯ롥 + +: 롼ɤ⥸塼ðۥåɤϷѾʤ + +@node ALIAS, UNDEF, ðۥå, +@comment node-name, next, previous, up +@subsection ALIAS +@cindex åɤ̾Ĥ + + + +@example +alias foo bar +@end example + +ʸ + +@display +alias å̾1 å̾2 +@end display + +@findex alias +@code{alias}ʸǥåɤ̾Ĥ뤳ȤǤ롥̾դ줿 +åɤϡλǤΥåѤΥåɤ +Ƥ⡤θŤåɤƤӽФ줿ΤƱƯ롥 + +@node UNDEF, DEFINED?, ALIAS, +@comment node-name, next, previous, up +@subsection UNDEF +@cindex åɤä + + + +@example +undef bar +@end example + +ʸ + +@display +undef å̾ +@end display + +@findex undef +åɤäˤundefѤ롥 + +defˤ̾@code{undef}ˤäˤäƥ饹Υ +եѡ饹Ωѹ뤳ȤǤ롥 +ɤself˥åäƤ⤢Τǡ褯դʤȴ¸ +åɤưʤʤǽ롥 + +@node DEFINED?, , UNDEF, +@comment node-name, next, previous, up +@subsection DEFINED? +@cindex åɤƤ뤫ɤ +@cindex ѿƤ뤫ɤ +@cindex Ƥ뤫ɤ + + + +@example +defined? print +defined? File.print +defined?(foobar) +defined?($foobar) +defined?(@@foobar) +defined?(Foobar) +@end example + +ʸ + +@display +defined? +@end display + +@findex defined? +åɸƤӽФξ硤ΥåɤƤ˿֤ +ѿλȤǤϡѿƤ +˿֤ʳμξϼɾơ㳰ȯʤп +֤ + +@node Ȥ߹ߴؿ, Ȥ߹ѿ, rubyʸˡ, Top +@comment node-name, next, previous, up +@chapter Ȥ߹ߴؿ + +Rubyˤϸ̩ʰ̣ǤϴؿϤʤ@code{Kernel}饹δؿåɤ +(Ƥ̾說饹ؿǸƤӽФΤ)ؿŪѤ롥 +ŪѤåɤʲˤ롥Υåɤ +ˤϸߴͤƹԤʤ٤Ǥ롥 + +@ftable @code +@item autoload(@var{module}, @var{file}) + +@var{module}˺ǽ˥@var{file}@code{require}褦 +ꤹ롥@var{module}ʸޤϥܥǻꤹ롥 + +@item caller([@var{level}]) + +@var{level}ʾθƽФξ@code{$@@}η롥ȥåץ٥ +Ǥ@code{nil}֤callerͤ@code{$@@}뤳Ȥ㳰 +ȯ֤Ǥ롥ޤʲΤ褦ʥɤǸƽФطΥХåȥ졼 +ɽǤ롥 + +@example +n = 0 +while c = caller(n) + print c, "\n" +end +@end example + +@item eof +@itemx eof? + +ޥɥ饤Ϥ@code{EOF}ãƤ硤֤ + +@item eval(@var{expr}) + +@var{expr}ȤͿ줿ʸrubyץȤƲᡤ¹Ԥ롥 + +@item exec(@var{command}) + +ץμ¹Ԥλ롥@var{status}ȤͿ줿硤 +ͤrubyޥɤνλơȤ롥ǥեȤ0 + +@item exit!(@var{status}) + +ץμ¹Ԥλ롥@var{status}λơȤ롥 +@code{exit}Ȥϰäơ㳰ʤɤϰڹԤʤʤ@code{fork}θ塤 +ҥץλʤɤѤ롥 + +@item fork + +@samp{fork}ƥॳ¹Ԥҥץ롥ܺ٤ +@samp{fork(2)}ȤΤȡƥץ¦ǤϻҥץΥץid +ҥץ¦Ǥ@code{nil}֤餫θǻҥץ +Ԥˤ㳰ȯ롥ƥ졼ȤƸƤФ줿ϡ +ץͿ줿֥åɾ֥åɾλǻ +ץェλ롥 + +@item format(@var{format}@dots{}) + +եޥåȤȤͿ줿ʸC@samp{sprintf}Ʊ褦 +ᤷŸʸ֤å@code{sprintf}̾ + +Rubyˤ@samp{format}ҤγĥˤĤƤ@code{sprintf}ι +ȤΤȡ + +@item getc + +ɸϤʸФͤɤ߹ʸʸ(ASCII) +ɽ@code{Fixnum}Ǥ롥 + +@item gets + +ȤͿ줿ե(ʤɸ)ǹ벾 +Ūʥե(ƥѿ@code{$<}ǥǤ)ɤ߹ +ǡɤ߹ߤˤϤʸ֤եν +ãˤ@code{nil}֤Ԥζڤϥƥѿ@code{$/}ˤä +ѹǤ롥ɤ߹ʸϥƥѿ@code{$_}ˤ⥻åȤ롥 + +@item gsub(@var{pattern}[, @var{replace}]) +@itemx gsub!(@var{pattern}[, @var{replace}]) + +ƥѿ@code{$_}λؤʸ @var{pattern}˥ޥåʬ +@var{replace}֤롥@code{String}饹@code{gsub} +ɤβȤΤȡ@var{replace}ά줿ˤϥƥ졼 +ư֥åɾִ̤롥@code{gsub}åɤ +@code{$_}ͤԡơԡ@code{$_}롥 + +@code{gsub!}@code{$_}λؤƤʸΤΤ롥 + +@item iterator? + +åɤƥ졼ȤƸƤӽФ줿ˤϿǤʤ˵֤ +Ҹ졥 + +@item kill(@var{signal}, @var{pid}@dots{}) + +@var{pid}ǻꤵ줿ץ˥ʥ롥@var{signal}ϥʥ +ֹ椫̾ǻꤹ롥ͤĥʥ(뤤ϥʥ̾ +@code{-})ͿȥץǤϤʤץ롼פ˥ʥ롥 + +@item load(@var{file}) + +@var{file}ɤ롥@var{file}ɤѥϥƥѿ +@code{$:}Ƿꤵ롥 + +@item loop + +̵¥롼פ륤ƥ졼(Ǥʤ¤)ʵפ˥ƥ졼֥å +ɾ³롥 + +@item open(@var{file}[, @var{mode}]) + +@var{file}ץơ@code{File}֥Ȥ֤ե̾ +ץեե̾@code{|}ǻϤޤˤ³ʸ +ޥɤȤƵưѥץ饤롥 + +ޥ̾@samp{"-"}Ǥ@code{open}rubyλҥץ +λҥץȤΥѥפ֤ + +@var{mode}ϥեΥ⡼ɤꤹ롥ϰʲΤΤ +줫ʸǤ롥 + +@table @samp +@item r +ɤ߹ѡ@code{open}եϤ餫¸ߤƤɬפ +롥 + +@item r+ +ɤ߽ξѡ@code{open}եϤ餫¸ߤƤɬפ +롥 + +@item w +ѡե뤬¸ߤƤ硤Ĺ0ˤ롥¸ߤƤ +п˥ե롥 + +@item w+ +ɤ߽ξѡɤ߹ߤԤʤ뤳Ȱʳ@samp{"w"}ƱƯ롥 + +@item a +ɲýѡեϤ餫¸ߤƤɬפ롥 +ϥեκǸɲä롥 + +@item a+ +ɤ߽ξѡե뤬¸ߤƤʤп˺롥 +ϥեκǸ˽롥 +@end table + +⡼ɤά줿ΥǥեȤ@samp{"r"}Ǥ롥 + +@item print(@var{arg}1@dots{}) + +˽Ϥ롥Ϳʤˤ@code{$_}ͤϤ롥 +ʸʳΥ֥ȤȤͿ줿ˤϡ֥ +Ȥ@code{to_s}åɤˤäʸѴƤϤ롥 +ѿ@code{$;}(ϥեɥѥ졼)@code{nil}Ǥʤͤå +Ƥˤϡưδ֤ˤʸϤ롥ƥѿ +@code{$\}(ϥեɥѥ졼)@code{nil}ǤʤͤåȤƤ +ˤϡǸˤϤ롥 + +@item printf([@var{port}, ]@var{format}, @var{arg}@dots{}) + +CprintfƱ褦@var{format}˽ʸѴ +롥1IOΥ֥饹ΥǤäϤΥ֥ +ȤФƽϤԤʤǥեȤ@code{$stdout}˽Ϥ롥 + +RubyˤformatҤγĥˤĤƤsprintfιȤΤȡ + +@item proc +@itemx lambda + +Ϳ줿ƥ졼֥å³֥(饹@code{Proc}Υ +)Ȥ֤ + +@item rand(@var{max}) + +0@var{max}ۤʤϰϤȯ롥ͤ +@code{Fixnum} + +@item require(@var{feature}) + +@var{feature}ǻꤵfileɤ롥@var{feature}ϥɤե +ꤹʸǡĥ@code{.rb}ꤵƤruby +ץȡĥ@code{.o}ꤵƤϡХʥ⥸塼 +롥ĤΥƥǤϥХʥ⥸塼Υɤ +ʤХʥ⥸塼μºݤΥեγĥҤϥƥ +˰ۤʤ뤬@var{feature}̾γĥҤϤĤ@code{.o}Ѥ롥 + +ĥҤꤵʤϡޤ@code{.rb}@code{.o}äơե +롥 + +requireϼºݤ˥ɤˤ @code{TRUE}˥ɤƤ +@code{FALSE}֤ޤɤ@var{feature}̾(ĥҤޤ +)ѿ@code{$"}ɲä롥 + +@item select(@var{reads}[, @var{writes}[, @var{execpts}[, @var{timeout}]]]) + +@samp{select(2)}¹Ԥ롥@var{reads}/@var{writes}/@var{execpts}ˤ +IO(ޤϤΥ֥饹)ΥͿ롥@var{timeout} +Fixnum/Float/TimeΤ줫ǻꤹ롥ͤ@var{timeout}Ω +ˤ@code{nil}ǤʤȤ3Ǥ֤γǤ +//㳰ԤΥ֥ȤǤ(ꤷΥ֥åȡ +Ԥ֥Ȥꤷʤä@code{nil})ƥॳ +¹˳ߤäˤϳ϶ˤʤ롥 + +@item sleep([@var{sec}]) + +@var{sec}äץμ¹Ԥߤ롥@var{sec}ά줿硤 +ץ@code{SIGALRM}ʤ¤ꡤʵפ˥פ롥ºݤ˥ +פÿ֤ + +@item sprintf(@var{format}@dots{}) + +@var{format}ʸC@samp{sprintf}Ʊ褦˲ᤷŸ +ʸ֤å@code{format}̾ + +@var{format}ҤC@samp{sprintf}()դ( +Rubyˤ unsignedʤΤǡ%uϽ)˲ä, %b, %B, %O, %XȤ +ȤǤ롥%bϿͤ2ɽ%B, %O, %XϤ줾2ʡ8ʡ16ʿ +ɽԤʤονκݤ2ɽǤϤʤɽ +Ƭ@code{-}ĤΤɽ롥 + +@item srand([@var{seed}]) + +@var{seed}ꤷŤ֤ͤͤά줿ˤ +@samp{time(3)}֤ͤǥեȤȤ롥 + +@item sub(@var{pattern}[, @var{replace}]) +@itemx sub!(@var{pattern}[, @var{replace}]) + +ƥѿ@code{$_}λؤʸǺǽ@var{pattern}˥ޥåʬ +@var{replace}֤롥@var{replace} ά줿ˤϥ +졼Ȥư֥åɾִ̤롥subåɤ +@code{$_}ͤԡơԡ@code{$_}롥 +¾ξܺ٤˴ؤƤ@code{String}饹@code{sub}åɤβ +ȤΤȡ + +@code{sub!}@code{$_}λؤƤʸΤΤ롥 + +@item syscall(@var{num}, @var{arg}@dots{}) + +@var{num}ǻꤵ줿ֹΥƥॳ¹Ԥ롥2ʹߤ +ƥॳΰȤϤʸޤǤʤФʤʤ + +@item system(@var{command}) + +@var{command}¹Ԥ(֥ץstatus 0ǽλ) +ˤϿԤˤϵ֤λơѿ@code{$?} ǻ +ȤǤ롥 + +@item test(@var{cmd}, @var{file} [, @var{file}]) + +եƥȤԤ@var{cmd}ϰʲ˼ʸƥǤ롥ե +̾Ȥ@code{"&"}ꤹȡľΥեؤ@samp{stat(2)}η +̤Ѥ롥 + + +1Ĥΰ + +@display +?r ե¸ uid ɤळȤǤ +?w ե˼¸ uid ǽȤǤ +?x ե¸ uid Ǽ¹Ԥ뤳ȤǤ +?o եνͭԤ¸ uid Ǥ + +?R ե uid ɤळȤǤ +?W ե˼ uid ǽȤǤ +?X ե uid Ǽ¹Ԥ뤳ȤǤ +?O եνͭԤ uid Ǥ + +?e ե뤬¸ߤ + +?z ե륵 0 Ǥ +?s ե륵 0 Ǥʤ(ե륵֤) + +?f եϥץ졼եǤ +?d եϥǥ쥯ȥǤ +?l եϥܥåǤ +?p ե̾Ĥѥ(FIFO)Ǥ +?S եϥåȤǤ +?b եϥ֥åüեǤ +?c եϥ饯üեǤ + +?u ե setuid ӥåȤåȤƤ +?g ե setgid ӥåȤåȤƤ +?k ե sticky ӥåȤåȤƤ + +?M ץȤμ¹ԤϤǤΥեθŤ +?A ץȤμ¹ԤϤǤΥեΥ +?C ץȤμ¹ԤϤǤΥե inode ѹ +@end display + +2Ĥΰ + +@display +?= ե1ȥե2Υॹפ +?> ե1ե2깹֤ +?< ե1ե2깹֤Ť +?- ե1ե2˥ϡɥƤ +@end display + +@item trace_var(@var{var}, @var{command}) + +@var{var}ǻꤵ줿ѿͤѹ줿ɾ +@var{command}ꤹ롥@var{command}ʸޤϥ֥åǻꤹ +롥trace뤿ˤ@code{untrace_var}Ѥ롥 + +@item trap(@var{signal}, @var{command}) +@itemx trap(@var{signal}) @{@dots{}@} + +@var{signal}γߤä@var{command}¹Ԥ롥 +@var{signal}ϥʥ̾ʥֹ桥@var{command}ʸޤ +ϥ֥åǻꤹ롥commandȤ@samp{"SIG_IGN"}ޤ +@samp{"IGNORE"}ꤷˤϤΥʥ̵뤹(ǽʤ) +@samp{"SIG_DFL"}ޤ@samp{"DEFAULT"}ꤷϥǥեȤư +Ԥʤ@samp{"EXIT"}ꤷϥʥ(λԤ +)exit status 1ǽλ롥 + +@item untrace_var(@var{var}) + +@var{var}ФƤtrace롥traceȤƻꤵƤ륪 +Ȥˤ֤ + +@item wait + +ҥץλΤԤλҥץpid֤ҥץ +Ĥʤ@code{nil}֤ + +@item waitpid(@var{pid}, @var{flags}) + +@var{pid}ǻꤵλҥץνλԤΥץλ +˿֤ҥץ¸ߤʤΥ֥å⡼ɤǻ +ץޤλƤʤˤ@code{nil}֤@samp{waitpid(2)} +@samp{wait4(2)}μƤʤޥǤ@var{flags}ϤĤ@code{nil}ޤ +0ǤʤФʤʤ +@end ftable + +@node Ȥ߹ѿ, Ȥ߹ߥ饹ȥ⥸塼, Ȥ߹ߴؿ, Top +@comment node-name, next, previous, up +@chapter Ȥ߹ѿ +@cindex{ȹѿ} + +@table @samp + +@item $! +顼åfailꤹ롥 + +@item $@@ +顼ȯΥե̾ȹֹ椬 +@example +"ե:ֹ[:å̾()]" +@end display +ηdzǼ롥 + +@item $& +Ǹѥޥå + +@item $` +ǸΥѥޥåǥޥåʸʸ + +@item $' +ǸΥѥޥåǥޥåʸθ³ʸ + +@item $+ +ǸθѥǥޥåǸγ + +@item $1@dots{}$9 +Ǹѥޥånܤγ̤˥ޥåͤǼ롥 +̤ʤ@code{nil}äƤ롥 + +@item $~ +ǸΥޥå˴ؤåȤ@code{$&} +@samp{$1@dots{}$9}ͤѲ롥 + +@item $= +ѿͤ@code{nil}ǤʤѥޥåʸӤǥե٥ +Ȥʸʸ̤ʤǥեȤ@code{nil}(̤) + +@item $/ +ϥ쥳ɥѥ졼եʸФ@code{each}Ԥʤ +ʬʸꤹ롥$/˶ʸ(@code{""})ꤹñ̤ +ϤԤʤ@code{nil}ꤹΤ٤ɤ߹ࡥ@code{$/}ˤ +ɽϻȤʤǥեȤ@samp{"\n"} + +@item $\ +ϥ쥳ɥѥ졼ѿʸꤹ@code{write} +@code{print}٤˺ǸˤʸղäƽϤ롥ǥեȤ +@code{nil} (ʤˤɲäʤ) + +@item $, +@code{Array:join}ΥǥեȤζڤʸ@code{print}γưδ +˽Ϥʸ + +@item $; +@code{String:split}ΥǥեȤζڤʸ + +@item $. +Ǹɤϥեιֹ桥 + +@item $< +(ʤɸ)ǹ벾ۥե롥Ĥޤ@code{gets} +@code{$<.gets}Ʊ̣Ǥ롥@code{$<.file}Ǹɤ߹Υե +륪֥Ȥ@code{$<.filename}ǤΥե̾롥(Ф +: @code{<}ϥϸ) + +@item $> +@code{print}@code{printf}ΥǥեȤν补ͤ +@code{$stdout}@samp{-i}ץꤷˤɤ߹߸Ʊ +̾Υե롥(Ф: @code{>}ϥν) + +@item $_ +Ǹ@code{gets}ʤɤɤ߹ʸ + +@item $0 +rubyץȤ̾ѿ@samp{ps(1)}νϤѲ롥 + +@item $* +rubyץȤͿ줿rubyȤФϼƤ롥 + +@item $$ +¹rubyץpid + +@item $? +Ǹ˼¹Ԥҥץstatus + +@item $: +եɤ˸ǥ쥯ȥؤΥѥޤư +ˤϥǥե(ѥ˻ꤹ)˲äơĶѿ +@var{RUBYLIB}ͤrubyư@samp{-I}ץǻꤵ줿ͤɲ +롥(Ф: ϴĶѿ@var{PATH}ζڤʸǤ) + +@item $" +@code{require}ǥɤ줿ե̾ޤ@code{require}Ʊ +ե2ɤʤѤ롥(Ф: prevent files to +be doubly quoted(loaded)) + +@item $ARGF +@code{$<}̾ + +@item $ARGV +@code{$*}̾ + +@item $DEBUG +@code{-d}ե饰ξ() + +@item $FILENAME +ۥե@code{$<}Ǹɤ߹(ågetsɤǤ)ե +̾@code{$<.filename}Ʊ + +@item $KCODE +߽оݤȤƤɤɽʸ@samp{"EUC"} +@samp{"SJIS"}ޤ@samp{"NONE"}ѿͤѹɽΥޥ +ľɽκƥѥ뤬Ԥ롥 + +@item $LOAD_PATH +@code{$:}̾ + +@item $stdin +ɸ + +@item $stdout +ɸ + +@item $stderr +ɸ२顼 + +@item $VERBOSE +@code{-v}ե饰ξ() + +@item TRUE +@itemx FALSE +줾쿿ͤɽ(@code{TRUE}ͤt@code{FALSE}ͤ@code{nil}) +ȽǤ@code{nil}ʳƤͤȤȽǤ뤿ᡤ +@code{TRUE}ͤɽŪʿͤȤʾΰ̣ʤäơ +åɤͤǤȤȤȡ줬@code{TRUE}֤Ȥ +Ȥϸ̩ˤƱǤϤʤ(ҸŪѤåɤͤȤ +@code{TRUE}֤褦ˤϤʤäƤ뤬)Ĥޤ + +@example +if some.method() then @dots{} else @dots{} end +@end example + + + +@example +if some.method() == TRUE then @dots{} else @dots{} end +@end example + +ϴˤƱǤϤʤ@code{FALSE}˴ؤƤϡΤ褦 +ʤ + +@item STDIN +ɸ($stdinν) +@item STDOUT +ɸ($stdoutν) +@item STDERR +ɸ२顼($stderrν) + +@item ENV +Ķѿ˥ϢʸȤͿбĶ +ѿͤ롥Ķѿ¸ߤʤ@code{nil}֤롥 + +@item VERSION +rubyΥСʸ +@end table + +@node Ȥ߹ߥ饹ȥ⥸塼, CȤΥե, Ȥ߹ѿ, Top +@comment node-name, next, previous, up +@chapter Ȥ߹ߥ饹ȥ⥸塼 + +@menu +饹 +* Array:: +* Bignum:: +* Class:: +* Dir:: +* File:: +* Fixnum:: +* Float:: +* Hash:: +* Integer:: +* IO:: +* Kernel:: +* Module:: +* Nil:: +* Numeric:: +* Object:: +* Proc:: +* Range:: +* Regexp:: +* String:: +* Struct:: +* Time:: + +⥸塼 + +* Comparable:: +* Enumerable:: +* Etc:: +* FileTest:: +* GC:: +* Math:: +* Process:: +@end menu + +@node Array, Bignum, Ȥ߹ߥ饹ȥ⥸塼, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Array + +źȤΥ饹Ǥ롥ϰŪˤ``[@dots{}]'' +Ԥʤ롥 + +SuperClass: Object + +Included Modules: Enumerable + +Methods: + +@ftable @code +@item self[@var{nth}] +@itemx self[@var{start}..@var{end}] +@itemx self[@var{start}, @var{length}] + +Ǥ˥롥ǽηǤ@var{nth}ܤǤ +2ܤηǤ@var{start}ܤǤ@var{end}ܤǤޤ +ʬ֤3ܤηǤ@var{start}ܤ@var{length}Ĥ +ޤʬ֤ + +@item self[@var{nth}] = @var{val} +@itemx self[@var{start}..@var{end}] = @var{val} +@itemx self[@var{start}, @var{length}] = @var{val} + +Ǥѹ롥ǽηǤ@var{nth}ܤǤ +@var{val}ѹ롥2ܤη@var{start}ܤǤ@var{end} +ܤǤޤǤ@var{val}ѹ롥3ܤηǤ@var{start}ܤ +@var{length}ĤǤ@var{val}ѹ롥 + +2ܡ3ܤηǤ@var{val}ǤʤФʤʤ + + + +@example +ary = [1, 2, 3, 4, 5] +ary[0..2] = [0, 0] # Ƥ [0, 0, 4, 5] +ary[1, 0] = [7] # Ƥ [0, 7, 0, 6, 5] +@end example + +@item self + @var{other} + +Ϣ롥@code{self}@var{other}ξƤҤ +֤ + +@item self * @var{times} + +η֤ + +@item self - @var{other} + +κ黻@code{self}@var{other}ǤƤο +֤ʣǤ1٤롥 + +@item self * @var{other} + +ѱ黻ξ˴ޤޤǤʤ뿷֤ +ʣǤ1٤롥 + +@item self | @var{other} + +±黻ξˤ줫˴ޤޤǤƴޤ +֤ʣǤ1٤롥 + +@item self << @var{obj} + +objɲä롥@code{self}֤Τ@code{C++}ŪϢǤ +롥 + +@item assoc(@var{key}) + +Ϣۥꥹ(2ǤǤȤ)1Ǥ@var{key} + (@code{==}Ӥ)֤ + +@item clear + +礭0ˤ롥 + +@item delete(@var{val}) + +@var{val}ȰפǤ롥 + +@item delete_if @{@dots{}@} + +Ǥ륤ƥ졼֥åɾͤλбǤ +롥 + +@item each @{@dots{}@} + +γǤͿ륤ƥ졼 + +@item fill(@var{val}) +@itemx fill(@var{val}, @var{start}[, @var{length}]) +@itemx fill(@var{val}, @var{start}..@var{end}) + +(λꤵ줿ʬ)Ǥͤ@var{val}ꤹ롥2֤η +@var{length}ά줿νޤǤĹȤ롥ꤵ줿ʬ +ϰϤۤϼưŪ˳ĥ롥 + +@item index(@var{val}) + +@var{val}ǽǤΥǥå֤Ǥ¸ߤ +ʤ@code{nil}֤ + +@item indexes(@var{ary}) +@itemx indexes(@var{index_}1,@dots{}, @var{index_n}) + +1ܤηǤȤƼơǤǥå +Ǥޤ֤2ܤηǤϳưͤǥåȤ +Ǥޤ֤ + +@item join([@var{sep}]) + +ǤϢ뤷ʸ֤ǤʸѴ졤֤ +@var{sep}Ϣ뤵롥@var{sep}ά줿ˤϥƥѿ +@code{$,}ͤѤ롥 + +@item length +@itemx size + +Ĺ(ǿ)֤ + +@item pack(@var{template}) + +Ƥ@var{template}ʸˤäơ1Ĥʸ˥ѥå롥 +ѥåʸ֤ƥץ졼ȤϷʸȤĹ(ά +1)¤٤ΤǤ롥ĹȤ@code{*}ꤵ줿ϡֻĤΥǡ +ơפĹɽ + +ʸϰʲΤΤ롥 + +@display +a ASCIIʸ(nullʸͤ) +A ASCIIʸ(ڡͤ) +b ӥåȥȥ(̥ӥåȤ̥ӥå) +B ӥåȥȥ(̥ӥåȤ鲼̥ӥå) +h 16ʸ(̥˥֥뤬) +H 16ʸ(̥˥֥뤬) +c char +C unsigned char +s sort +S unsigned sort +i int +I unsigned int +l long +L unsigned int +n ͥåȥХȥshort +N ͥåȥХȥlong +f ñư(¸) +d ư(¸) +x ʥХ +X 1Хȸ +@@ а֤ؤΰư +@end display + +@item pop + +Ǥơ֤ + +@item push(@var{obj}) + +@var{obj}ɲä롥 + +@item rassoc(@var{value}) + +Ϣۥꥹ(2ǤǤȤ)2Ǥ@var{value} +(@code{==}Ӥ)֤ + +@item shift + +ƬǤơ֤ + +@item sort +@itemx sort @{|@var{a}, @var{b}|@dots{}@} + +ƤȤ롥ƥ졼ȤƸƤӽФ줿ϥ֥åɾ +ͤǤ羮ꤹ롥礭0 +顥̾ΥåɤȤƸƤӽФ줿ϳǤ@code{<=>}Ӥ롥 + +@item to_a + +ʬȤ֤оΤѰդƤåɤǤޤʤ + +@item unshift(@var{obj}) + +@var{obj}Ƭɲä롥 +@end ftable + +Single Methods: + +@ftable @code +@item Array[@var{item}@dots{}] + +ǤȤ롥 +@end ftable + +@xref{Object} +@xref{Enumerable} + +@node Bignum, Class, Array, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Bignum + +̵¿ĹΥ饹黻η̤@code{Fixnum}ϰǤ +ˤϼưŪ˥饹@code{Fixnum}Ѵ롥Ūrubyץ +Ǥ@code{Fixnum}@code{Bignum}ѴϰۤΤ˹ԤΤǡ +ɬפ̵@code{Float}Ȥκ˴ؤƤϡ@code{Bignum} +@code{Float}genericity⤤Τˤؤ餺@code{Bignum} +礭ͤɽǤΤǡѴ˷ǽ롥 + +SuperClass: Integer + +Methods: + +@ftable @code +@item self + @var{other} +@itemx self - @var{other} +@itemx self * @var{other} +@itemx self / @var{other} +@itemx self % @var{other} +@itemx self ** @var{other} + +ѱ黻줾¡ѡ;Ѿ֤ + +@item ~ self +@itemx self | @var{other} +@itemx self & @var{other} +@itemx self ^ @var{other} + +ӥåȱ黻줾ӥåȿž¡ѡ¾Ū¤֤ + +@item self << @var{bits} +@itemx self >> @var{bits} + +եȱ黻줾@var{bits}ӥåȤ˥ӥåȥեȤԤʤ + +@item divmod(@var{other}) + +Ⱦ;ʤ֤ +@end ftable + +@xref{Integer} + +@node Class, Comparable, Bignum, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Class + +饹Υ饹긷̩ȥ饹ðۥåɤѾ뤿 +ˡ줾饹ȸƤФ̾Τʤ饹饹Ȥƻ +@code{Class}ϤΥ饹Υ饹Ǥ(ʬä?)β +⤬ǤʤƤ⡤rubyȤȤ˲λپʤ饹ˤðۥ +åɤǤȡѡ饹줿ðۥåɤϤΥ +֥饹ǤͭǤΤнʬǤ롥 + +SuperClass: Module + +Private Methods: + +@ftable @code +@item attr(@var{name}[, @var{public}]) + +Υ饹ΥФ@var{name}ǻꤵ°롥 +ܤ@code{Module}@code{attr}åɤιȤΤȡ +@end ftable + +Methods: + +@ftable @code +@item new(@dots{}) + +饹Υ롥¿ξ礳Υåɤϥ֥饹 +ۥåɤˤäƥС饤ɤ졤饹ˤäưۤʤ롥 +@end ftable + +@xref{Module} + +@node Comparable, Dir, Class, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Comparable + +ӱ黻饹Τ@code{Mixin}Υ⥸塼롼 +뤳Ȥˤäơ@code{<=>}黻Ҥ¾α黻ҤϤ +ѤǤ롥 + +Methods: + +@ftable @code +@item self == @var{other} + +@code{self}@var{other}֤ + +@item self > other + +@code{self}@var{other}礭֤ + +@item self >= @var{other} + +@code{self}@var{other}礭֤ + +@item self < @var{other} + +@code{self}@var{other}꾮֤ + +@item self <= @var{other} + +@code{self}@var{other}꾮֤ + +@item between?(min, max) + +@code{self}@var{min}@var{max}ϰˤ֤ +@end ftable + +@node Dir, Enumerable, Comparable, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Dir + +ǥ쥯ȥǤ֤ǥ쥯ȥꥹȥΤΥ饹 + +SuperClass: Object + +Included Modules: Enumerable + +Methods: + +@ftable @code + +@item close + +ǥ쥯ȥꥹȥ롥ʸ㳰ȯ롥 + +@item each @{|@var{item}|@dots{}@} + +ǥ쥯ȥγǤͿ륤ƥ졼 + +@item getwd +@itemx pwd + +ȥǥ쥯ȥ֤ + +@item rewind + +ǥ쥯ȥꥹȥƬ˥ꥻåȤ롥 + +@item seek(@var{pos}) + +ǥ쥯ȥꥹȥΰ֤@var{pos}ꤹ롥 + +@item tell + +ǥ쥯ȥꥹȥθߤΰ֤֤ + +Single Methods: + +@item self[@var{pat}] +@itemx glob(@var{pat}) + +ʸ@var{pat}@samp{sh}Υ磻ɥɤȤŸ̤ʸ +Ȥ֤ϰʲ̤Ǥ롥 + +@ftable @samp +@item * +Ǥդʸ(ʸޤ)Ȱ +@item ? +Ǥդ1ʸȰ +@item [ ] +[]Τ줫1ʸȰ +@item {@dots{}} +{}(ޤǶڤ줿)줫ʸȰ +@end ftable + +@item chdir(@var{path}) + +ȥǥ쥯ȥ@var{path}ѹ롥 + +@item chroot(@var{path}) + +ץΥ롼ȥǥ쥯ȥѹ롤Ʊ̾ΥƥॳƱƯ +롥ϼ¸uidѥ桼Ǥ¤Ƥ롥 +롼ȥǥ쥯ȥ᤹(롼ȥǥ쥯ȥѹ)ˡ +Ƥʤ + +@item mkdir(@var{path}[, @var{mode}]) + +@var{mode}ǻꤵ줿⡼ɤĥǥ쥯ȥ@var{path}롥⡼ +ɤ@code{umask}ˤäƽ롥@var{mode}Υǥեͤ0777 + +@item open(@var{path}) + +@var{path}Фǥ쥯ȥꥹȥץ롥 + +@item rmdir(@var{path}) + +@var{path}ǻꤵ줿ǥ쥯ȥ롥ǥ쥯ȥ϶Ǥɬ +פ롥 +@end ftable + +@xref{Object} +@xref{Enumerable} + +@node Enumerable, File, Dir, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Enumerable + +ǤФ뷫֤Ԥʤ饹Τ@code{Mixin}Υ⥸塼 +롼ɤ뤿ˤϡå@code{each}ɬפ롥 + +Methods: + +@ftable @code + +@item collect @{|@var{item}|@dots{}@} + +ǤФƥ֥åɾ̤ƴޤ֤ + +@item find @{|@var{item}|@dots{}@} + +ǤФƥ֥åɾͤˤʤäǽǤ֤ + +@item find_all @{|@var{item}|@dots{}@} + +ǤФƥ֥åɾͤǤäǤƴޤ֤ + +@item grep(pattern) +@itemx grep(pattern) @{|@var{item}|@dots{}@} + +@code{ =~ @var{pattern}}ΩƤǤޤ֤ +졼ȤѤ줿Ͼ嵭ξΩǤФƥ֥å +Ԥ롥 + +@item member?(@var{val}) + +@var{val}@code{==}δطˤǤĻ֤ + +@item index(@var{val}) + +@var{val}@code{==}δطˤ륪֥Ȥܤ˸줿֤ +ֺǽǤ0ˤʤ롥Ǥ¸ߤʤˤ@code{nil}֤ +Τʤ饹ФƤϤޤ̣ʤ + +@item length + +Ǥο֤ + +@item min + +ǾǤ֤ƤǤߤ@code{<=>}åɤӤǤ뤳 +ȤꤷƤ롥 + +@item max + +Ǥ֤Ǥ@code{<=>}åɤӤǤ뤳Ȥꤷ +롥 + +@item reverse + +ƤǤս¤٤֤ + +@item sort +@itemx sort @{|@var{a}, @var{b}|@dots{}@} + +ƤǤȤ֤ +@end ftable + +@node File, FileTest, Enumerable, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section File + +ե륢ΤΥ饹å@code{open}롥ޤ +Υ饹ðۥåɤȤ@code{test}Υեƥȱ黻 +åɤƤ(@code{FileTest}⥸塼Υåɷ) + +SuperClass: IO + +Methods: + +@ftable @code + +@item atime + +եκǽ֤ + +@item ctime + +եκǽơѹ֤ + +@item chmod(@var{mode}) + +եΥѡߥåѹ(cf @samp{chmod(2)}) + +@item chown(@var{owner}, @var{group}) + +եνͭԤȥ롼פѹ(cf @samp{chown(2)})@code{nil} +@code{-1}ꤹ뤳ȤˤäƽͭԤ䥰롼פߤΤޤѤʤ +ȤǤ롥 + +@item eof +@itemx eof? + +եνüã˿֤ + +@item lstat + +ե˴ؤ@code{Stat}¤Τ֤@code{lstat}ϥե뤬 +ܥåǤХΤΤ˴ؤ@code{Stat}¤Τ֤ +¤ΤƤˤĤƤ@code{stat}ȤΤȡ + +@item mtime + +եκǽ֤ + +@item rewind + +եΥեݥΰ֤Ƭ˰ư롥 + +@item path + +եΥѥ֤̾ + +@item seek(@var{offset}, @var{ptrname}) + +եΥեݥΰ֤@var{offset}˰ư롥 +@var{ptrname}012Τ줫Ǥäơ줾եƬ +֡եνüФ + +@item stat + +ե˴ؤ@code{Stat}¤Τ֤(@xref{Struct}) + +@display +struct stat + dev # ե¸ߤǥХ + ino # եi-nodeֹ + mode # ⡼ + nlink # ϡɥο + uid # ͭԤΥ桼ID + gid # ͭԤΥ롼ID + rdev # ǥХID(ڥեΤ) + size # ե륵(byte) + blksize # ե륷ƥˤŬڤʥ֥å + blocks # ֥å + atime # ǽ + mtime # ǽ + ctime # ǽѹ +end +@end display + +ܺ٤@samp{stat(2)}ȤΤȡƥƤ +@code{Stat}¤Τ˳Фʤ0ꤵƤ롥 + +@item tell + +եθߤΥեݥΰ֤֤ + +@item truncate(@var{length}) + +եڤΤƤƺ@var{length}ХȤˤ롥ե +@code{write}⡼ɤǥץƤʤФʤʤ + +Single Methods: + +@item atime(@var{filename}) + +@var{filename}κǽ֤ + +@item basename(@var{filename}[, @var{suffix}]) + +@var{filename}κǸǤ֤@var{suffix}Ϳ줿ϡ +ĥҤ + +@example +basename("ruby/ruby.c") + @result{} "ruby.c" +basename("ruby/ruby.c", ".c") + @result{} "ruby" +@end example + +@item ctime(@var{filename}) + +@var{filename}κǽơѹ֤ + +@item chmod(@var{mode}, @var{path}, @var{file}@dots{}) + +եΥѡߥåѹ(cf @samp{chmod(2)})ѹե +֤ + +@item chown(@var{owner}, @var{group}, @var{file}@dots{}) + +եνͭԤȥ롼פѹ(cf @samp{chown(2)})@code{nil} +@code{-1}ꤹ뤳ȤˤäƽͭԤ䥰롼פߤΤޤѤʤ +ȤǤ롥ѹե֤ + +@item dirname(@var{fname}) + +ե̾κǸǰʳ֤ + +@item expand_path(@var{path}) + +ե̾ХѥŸ롥@samp{~}ϥۡǥ쥯ȥŸ +롥 + +@example +expand_file_name("..") + @result{} "/home/matz/work" +expand_file_name("~") + @result{} "/home/matz" +expand_file_name("~matz") + @result{} "/home/matz" +@end example + +@item link(@var{old}, @var{new}) + +@var{old}ؤΥϡɥ@var{new}롥@samp{link(2)}Ʊ +롥 + +@item mtime(@var{filename}) + +@var{filename}κǽ֤ + +@item readlink(@var{path}) + +ܥå@var{path}ƤʸȤ֤ + +@item rename(@var{from}, @var{to}) + +ե̾@var{from}@var{to}ѹ롥@samp{rename(2)}ȡ +@var{to}Ȥ̾Υե뤬¸ߤˤϤޤΥե뤬 +롥 + +@item stat(@var{filename}) + +@var{filename}Υե@code{Stat}¤Τ֤ + +@item symlink(@var{old}, @var{new}) + +@var{old}ؤΥܥå@var{new}롥 + +@item truncate(@var{path}, @var{length}) + +@var{path}ǻꤵ줿եڤΤƤƺ@var{length}ХȤˤ롥 + +@item type(@var{filename}) + +@var{filename}ΥեΥפɽʸ֤ʸ +@code{"file"}@code{"directory"}@code{"characterSpecial"} +@code{"blockSpecial"}@code{"fifo"}@code{"link"}@code{"socket"} +Τ줫ĤǤ롥 + +@item unlink(@var{file}@dots{}) + +ե롥ǥ쥯ȥκˤ@code{Dir.rmdir}Ȥȡ + +@item utime(@var{atime}, @var{mtime}, @var{file}@dots{}) + +եΥ@var{atime}ˡ@var{mtime}ꤹ롥 +@var{atime}@var{mtime}Ͽޤ@code{Time}饹ΥǤ +Фʤʤ +@end ftable + +ʳ@code{FileTest}⥸塼ΥåɤðۥåɤȤƻġ + +@xref{IO} + +@node FileTest, Fixnum, File, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section FileTest + +եƥѥåɤ⥸塼롥롼ɤѤ뤳 +Ǥ롥Υ⥸塼Υåɤ˥ե̾Ȥ@code{"&"}ꤹ +ȡľΥեؤ@samp{stat(2)}η̤Ѥ롥 + +Methods: +Single Methods: + +@ftable @code +@item blockdev?(@var{filename}) + +@var{filename}Υե뤬֥åڥեǤ֤ + +@item chardev?(@var{filename}) + +@var{filename}Υե뤬饯ڥեǤ + + +@item executable?(@var{filename}) + +@var{filename}Υե뤬¹Բǽλ֤ + +@item executable_real?(@var{filename}) + +@var{filename}Υե뤬uid/gidǼ¹Բǽλ֤ + +@item exists?(@var{filename}) + +@var{filename}Υե뤬¸ߤ֤ + +@item grpowned?(@var{filename}) + +@var{filename}Υեgid¸롼פgidƱ֤ + +@item directory?(@var{filename}) + +@var{filename}ǥ쥯ȥλ֤ + +@item file?(@var{filename}) + +@var{filename}Υե뤬̾եλ֤ + +@item link?(@var{filename}) + +@var{filename}Υե뤬ܥåǤ֤ + +@item pipe?(@var{filename}) + +@var{filename}Υե뤬̾Ĥѥ(@code{FIFO})Ǥ + + +@item socket?(@var{filename}) + +@var{filename}Υե뤬åȤǤ֤ + +@item owned?(@var{filename}) + +@var{filename}Υե¸桼ͭƤ֤ + +@item readable?(@var{filename}) + +@var{filename}ΥեɤߤȤǽλ֤ + +@item readable_real?(@var{filename}) + +@var{filename}Υեuid/gidɤߤȤǽλ֤ + +@item setuid?(@var{filename}) + +@var{filename}ΥեsetuidӥåȤåȤƤ֤ + +@item setgid?(@var{filename}) + +@var{filename}ΥեsetgidӥåȤåȤƤ֤ + +@item size(@var{filename}) + +@var{filename}Υե뤬¸ߤե礭֤¸ߤ +@code{nil}֤ + +@item sticky?(@var{filename}) + +@var{filename}ΥեstickyӥåȤåȤƤ֤ + +@item symlink?(@var{filename}) + +@var{filename}ܥåǤ֤ + +@item writable?(@var{filename}) + +@var{filename}Υե뤬uid/gidǽ߲ǽλ֤ + +@item writable_real?(@var{filename}) + +@var{filename}Υե뤬߲ǽλ֤ + +@item zero?(@var{filename}) + +@var{filename}Υե뤬¸ߤ礭0Ǥ֤ +@end ftable + +@node Fixnum, Float, FileTest, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Fixnum + +31bit(ޥlongĹ-1 bit)Υ饹builtin classǤ롥 +饹pointer¨ͤǤ뤿call by valueǸƤӽФħŪ +Ǥ(¾Υ饹call by reference)黻η̤31bitۤ +ϼưŪ@code{Bignum}(̵¿Ĺ)˳ĥ롥 + +ƥ졼@code{upto}@code{downto}@code{step}Ϸ֤Τ +졤̤@code{Range}饹Ѥ®Ǥ롥 + +SuperClass: Integer + +Methods: + +@ftable @code +@item self + @var{other} +@itemx self - @var{other} +@itemx self * @var{other} +@itemx self / @var{other} +@itemx self % @var{other} +@itemx self ** @var{other} + +ѱ黻줾¡ѡ;Ѿ֤ + +@item ~ self +@itemx self | @var{other} +@itemx self & @var{other} +@itemx self ^ @var{other} + +ӥåȱ黻줾ӥåȿž¡ѡ¾Ū¤֤ + +@item self << @var{bits} +@itemx self >> @var{bits} + +եȱ黻줾@var{bits}ӥåȤ˥ӥåȥեȤԤʤ + +@item downto(@var{min}) @{@dots{}@} + +ƥ졼@code{self}@var{min}ޤDz˷֤ + +@item id2name + +ͤIDȤߤʤơʸ֤ʸ¸ߤ +@code{nil}֤ + +@item step(@var{max}, @var{step}) @{@dots{}@} + +ƥ졼@code{self}@var{max}ޤ@var{step}Ѳʤ顤 +֤ + +@item to_f + +@code{self}@code{Float}ѴΤ֤ + +@item to_i + +@code{self}Τޤ֤ + +@item upto(@var{max}) @{@dots{}@} + +ƥ졼@code{self}@var{max}ޤǷ֤ +@end ftable + +@xref{Integer} + +@node Float, GC, Fixnum, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Float + +ưΥ饹 + +SuperClass: Numeric + +Methods: + +@ftable @code +@item self + @var{other} +@itemx self - @var{other} +@itemx self * @var{other} +@itemx self / @var{other} +@itemx self % @var{other} +@itemx self ** @var{other} + +ѱ黻줾¡ѡ;Ѿ֤ + +@item self == @var{other} +@itemx self > @var{other} + +ӱ黻 + +@item coerce(@var{num}) + +@var{num}@code{Float}Ѵ롥@code{Float} +¾ο@code{Fixnum}@code{Bignum}Ǥ롥 + +@item to_f + +@code{self}Τޤ֤ + +@item to_i + +@code{self}Ѵ̤֤ +@end ftable + +Single Methods: + +@ftable @code +@item new(@var{float}) + +@var{float}ƱͤĿ@code{Float}֥Ȥ֤ +@end ftable + +@xref{Numeric} + +@node GC, Hash, Float, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section GC + +RubyȤ߹ߤgarbage collectorԤʤΥ⥸塼롥Υ +塼ΥåɤѤ뤳ȤˤäơŪGCߤꡤGCε +륿ߥ椷Ǥ롥 + +Methods: + +@ftable @code +@item garbage_collect + +GCϤ롥@code{GC.start}Ʊ +@end ftable + +Single Methods: + +@ftable @code +@item disable + +GCػߤ롥 + +@item enable + +GCĤ롥 + +@item start + +GCϤ롥 +@end ftable + +@node Hash, Integer, GC, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Hash + +Ϣ뤤ϥϥåɽǤդΥ֥ȤźȤǤΥ +Ǥ롥Ϣ֥ȤϰŪˤϢ + +@display +{a=>b,@dots{}} +@end display + +ǹԤʤ롥 + +ȤͿ֥ȤƤѲå@code{hash}֤ +ͤѤ@code{Hash}ưʤ(ͤФʤʤ) +ˤä@code{hash}ͤѲ륯饹(Ȥ@code{Array}, +@code{Hash}ʤ)Υϥ˸ʤƤ +@code{hash}ͤ˱ƶ륪֥ȤΤʸ̤˰ +롥ʸȤͿȡʸԡԡԲĤ +ꤷǡȤƻѤ롥äơʸƤ⥭ʸ +Ѳʤ@code{each}, @code{each_key}, @code{keys}ʤɤΥ +ɤȤʸ֤ʸϹǤʤ(㳰ȯ) + +SuperClass: Object + +Included Modules: Enumerable + +Methods: + +@ftable @code +@item self [@var{key}] + +@var{key}Ȥ֤ͤ + +@item self [@var{key}]= @var{value} + +@var{key}Ȥơ@var{value}Ǽ롥@var{value}Ȥ +@code{nil}ꤹȤ@var{key}ФܤκȤʤ롥Ĥޤꡤ +@code{Hash}ͤȤ@code{nil}ĤȤϤǤʤ + +@item clear + +Ϣˤ롥 + +@item delete(@var{key}) + +@var{key}ȤȤ롥 + +@item delete_if @{|@var{item}|@dots{}@} + +Ǥ륤ƥ졼@code{[key,value]}ȤͿơ֥ +ɾͤλܤ롥 + +@item each @{|@var{key}, @var{value}|@dots{}@} +@itemx each_pair @{|@var{key}, @var{value}|@dots{}@} + +@code{[key,value]}ʤ2ǤͿ륤ƥ졼 + +@item each_key @{|@var{key}|@dots{}@} + +ƤkeyФƷ֤ƥ졼 + +@item each_value @{|@var{value}|@dots{}@} + +ƤvalueФƷ֤ƥ졼 + +@item has_key?(@var{key}) + +@var{key}ȤȤϢ¸ߤ֤ + +@item has_value?(@var{value}) + +@var{value}ͤȤȤϢ¸ߤ֤ + +@item indexes(@var{ary}) +@itemx indexes(@var{key_}1,@dots{}, @var{key_n}) + +1ܤηǤȤƼơǤȤǤޤ +֤2ܤηǤϳưͤȤǤޤ֤ + +@item keys + +Ϣ¸ߤ륭Ƥޤ֤ +@item length +@itemx size + +ϢǤο֤ + +@item shift + +ϢǤļФ()@code{[key,value]}ʤ2 +֤ + +@item to_a + +Ϣ@code{key-value}2ǤǤȤ֤ + +@item values + +Ϣ¸ߤƤޤ֤ +@end ftable + +Single Methods: + +@ftable @code +@item Hash[@var{key}, @var{value}@dots{}] + +ܤΰ@var{key}ܤΰ@var{value}ȤϢ +롥 + +@item new + +()Ϣ֥Ȥ֤ +@end ftable + +@xref{Object} +@xref{Enumerable} + +@node Integer, IO, Hash, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Integer + +饹ºݤϤ礭ˤä@code{Fixnum}@code{Bignum} +ĤΥ֥饹Ǽ¸Ƥ롥@code{Integer}ϤΥѡ饹 +Ȥʤݥ饹Ǥ롥RubyǤϤۤȤɤξ硤@code{Fixnum} +@code{Bignum}ζ̤ɬפʤߤѴϼưŪ˹Ԥʤ롥 +ӥåȤߤʤˤϡ̵¤Ĺĥӥåȹͤƹʤ + +SuperClass: Numeric + +Methods: + +@ftable @code +@item self[@var{idx}] + +@var{idx}ӥåܤåȤƤ1åȤƤʤ0 +֤ + +@item chr + +οɤȤʸޤ1ʸʸ֤̤Ĺ1ʾ +ʸˤĤơδطΩ롥 + +@example +str[0].chr == str[0,1] +@end example + +ʸϰ(0@dots{}255)ˤʤ㳰ȯ롥 + +@item integer? + +Ĥ֤ +@end ftable + +@xref{Numeric} + +@node IO, Kernel, Integer, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section IO + +ϤΤδܥ饹 + +SuperClass: Object + +Included Modules: Enumerable + +Methods: + +@ftable @code +@item self << @var{object} + +@var{object}Ϥ롥@var{object}ʸǤʤˤϥå +@code{to_s}ѤʸѴ롥@code{self}ͤȤΤǡ +@code{C++}Τ褦@code{<<}ϢȤ롥 + + + +@example +$stdout << 1 << " is a " << Fixnum << "\n" +@end example + +@item close + +ϥݡȤ롥ʸΤΥ֥ȤФ +顼ˤʤ롥 + +@item closed? + +ݡȤƤ֤ + +@item each @{|@var{line}|@dots{}@} +@item each_line @{|@var{line}|@dots{}@} + +Ԥɤ߹Ǥ뤿Υƥ졼Ԥζڤϥƥѿ +@code{$/}ˤäѹǤ롥ɤ߹ʸϥƥѿ@code{$_} +⥻åȤ롥 + +@itemx each_byte @{|@var{ch}|@dots{}@} + +ʸɤ߹Ǥ뤿Υƥ졼ʸʸɤɽ +@code{Fixnum}Ǥ롥 + +@item fileno +@itemx to_i + +@code{IO}֥ȤȤäƤեǥץ(@code{Fixnum}) +֤ + +@item flush + +Хåեեå夹롥 + +@item getc + +ɤ߹ǡɤ߹ߤˤϤʸ֤եν +ãˤ@code{nil}֤ͥå@code{getc} +@code{$stdin.getc}Ʊ̣Ǥ롥 + +@item gets + +ɤ߹ǡɤ߹ߤˤϤʸ֤եν +ãˤ@code{nil}֤ + +@item isatty +@itemx tty? + +ϥݡȤttyǤ֤ + +@item print(@var{arg}@dots{}) + +˽Ϥ롥褬@code{$>}Ǥʤ쥷ФǤʳ +@code{Kernel}饹@code{print}åɤƱư롥 + +@item printf(@var{format}, @var{arg}@dots{}) + +@code{C}@code{printf()}Ʊ@var{format}˽ʸ +쥷Ф˽Ϥ롥 + +@item puts(@var{obj}) + +@var{obj}Ϥ롥@code{self << obj}Ʊ̣Ǥ롥 + +@item read([@var{length}]) + +@var{length}Хɤ߹ǡʸ֤@var{length}ά +ˤϡ@code{EOF}ޤǤƤΥǡɤ߹ࡥ + +@item readlines + +եɤ߹dzƹԤǤȤƤ֤ + +@item sync + +ߤνƱ⡼ɤ֤ͤƱ⡼ɤλϽϴؿθƽ +˥Хåեեå夵롥 + +@item sync= @var{newstate} + +Ʊ⡼ɤꤹ롥 + +@item sysread(@var{length}) + +@samp{stdio}ͳ@samp{read(2)}ѤϤԤʤϤ줿 +ǡޤʸ֤եνãˤ@code{nil} +@samp{read(2)}ˤɬ@var{length}ХȤʸɤ߹ +櫓ǤϤʤ@code{gets}@code{getc}ʤ@samp{stdio}ͳ +åɤȺѤ뤳ȤϥХåեʤɤǻפư뤳 +롥 + +@item syswrite(@var{str}) + +@samp{stdio}ͳˡ@samp{write(2)}ѤƽϤԤʤΥ +åɤϥХåեʤ@samp{stdio}Ƥ뤳ȤϰڹԤʤʤ +@code{syswrite}ϼºݤ˽Хȿ֤@code{print} +@code{printf}@code{syswrite}ѤΤϿ侩Ǥʤ + +@item write(@var{str}) + +@var{str}Ϥ롥ϤХȿ֤ +@end ftable + +@xref{Object} +@xref{Enumerable} + +@node Kernel, Math, IO, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Kernel + +ƤΥ饹δ쥯饹RubyȤ߹ߤƤδؿåɤϤΥ饹 +Ƥ롥ؿåɤˤĤƤϡִؿפιܤȤΤȡ + +SuperClass: ʤ + +Methods: + +@ftable @code +@item self == @var{other} +@itemx equal?(@var{other}) + +֥ȤΰȽꡥ쥷ФȰΰפ֤ +@code{Kernel}饹ǤΥ֥ȤƱλ֤ +@code{==}åɤϳƥ֥Ȥ˱ƺɬפ롥 +@code{==}åɤˤϡ@code{hash}åɤ⤽˹碌 +ƺɬפ롥 + +equal?åɤ@code{==}åɤ̾ǡ@code{==}Ǥ +֥ȤƱȽԤʤѤ롥ä@code{equal?} +åɤϥ֥饹Ǻ٤ǤϤʤ + +@item self =~ @var{other} + +ޥåǥեȤư@code{==}ƱǤ롥@code{=~} +@code{case}ʸǤӤˤѤ롥 + +@item hash + +֥ȤΥϥå(@code{Fixnum})֤@code{Hash}饹ǥ +Ȥʤ륪֥ȤǼΤѤƤ.@code{A == B}Ω +ɬ@code{A.hash == B.hash}ΩɬפΤǡ@code{==} +ˤɬ⤽˹碌ƺ뤳ȡ + +@item id + +ƥ֥ȤФưդ@code{Fixnum}֤@code{Fixnum}ϼ +ʬȤ֤Τǡ@code{id}פƤƱ֥ȤǤ뤳Ȥ +ڤʤĤޤꡤ@code{obj1.id == obj2.id}ΩƤ⡤ɤ餫 +@code{Fixnum}ǤС@code{obj1}@code{obj2}ƱǤȤϸ¤ +ξ@code{Fixnum}ǤʤȤݾڤǤС2ĤΥ֥ +ȤƱǤ뤳Ȥϳμ¤Ǥ롥 + +@item inspect + +֥Ȥʹ֤ɤʸѴ롥 + +@item nil? + +֥Ȥ@code{nil}Ǥ뤫ɤ@code{Kernel}饹Ǥ +֤@code{Nil}饹ǵ֤褦Ƥ롥 + + +@item type + +֥ȤưŪʷ(饹)֤ + +@example +obj.is_kind_of?(obj.type) +@end example + +ϾΩ롥 + +@item send(@var{symbol}[, @var{args}@dots{}]) + +@var{symbol}ǻꤵåɤ@var{args}ȤȤ˸ƤӽФ + +@end ftable + +@node Math, Module, Kernel, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Math + +ư黻ݡȤ륯饹Math⥸塼ƱΥå +ðۥåɤȤξƤΤǡðۥåɤƤӽФƻ +Ȥȡ饹˥롼ɤƻȤȤȤξǤ롥 + + + +@example +pi = Math.atan2(1, 1) * 4; +include Math +pi2 = atan2(1, 1) +@end example + +Methods: +Single Methods: + +@ftable @code +@item atan2(@var{x}, @var{y}) + +С-ФϰϤ@var{x}/@var{y}ΥȤ֤ + +@item cos(@var{x}) +@itemx sin(@var{x}) +@itemx tan(@var{x}) + +饸ɽ줿@var{x}λѴؿ֤ͤ + +@item exp(@var{x}) + +@var{x}λؿؿ֤ͤ + +@item log(@var{x}) + +@var{x}μп֤ + +@item log10(@var{x}) + +@var{x}ξп֤ + +@item sqrt(@var{x}) + +@var{x}ʿ֤@var{x}ͤǤˤ㳰ȯ롥 + +@item cbrt(@var{x}) + +@var{x}Ω֤ +@end ftable + +@node Module, Nil, Math, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Module + +⥸塼Υ饹 + +SuperClass: Object + +Private Methods: + +@ftable @code +@item attr(@var{name}[, @var{public}]) + +Υ⥸塼롼ɤ饹ΥФ@var{name} +ǻꤵ°ղä°Ф륢åɤ롥 +@code{attr("attr")}ϥ饹˰ʲ˼ɤɲäΤȤۤƱ +Ǥ롥 + +@example +def attr; @@attr; end +@end example + +άǽ2@var{public}ͿơĤͤ@code{nil}Ǥ +ˤϤ°ˤ°åɤѰդ졤ǽˤʤ롥 + +@code{attr("attr", TRUE)}ϥ饹˰ʲΥɤɲäΤȤۤ +ƱǤ롥 + +@example +def attr; @@attr; end +def attr=(val); @@attr = val; end +@end example + +°åɤ뤳Ȥˤäơưѹ +Ǥ롥㤨 + +@example +attr("test", TRUE) +def test=(val) + print("test was ", @@test, "\n") + print("and now is ", @@test = val, "\n") +end +@end example + +Τ褦°ͤɽ褦ʤȤǽǤ롥@var{attr} +åɤǤƤϡǥեȤΥ +ɤʤ +@end ftable + +Methods: + +@ftable @code +@item include(@var{module}@dots{}) + +ǻꤷ⥸塼롼ɤơåɡɲä롥 +饹⥸塼̤Υ⥸塼롼ɤ뤳Ȥˤäơ +줿¿ŷѾ(@code{Mixin})¸Ǥ롥 + +@item module_function(@var{name}@dots{}) + +@var{name}ǻꤵ줿åɤ@samp{module function}˻ꤹ롥 +@samp{Module function}Ȥϥ⥸塼ðۥåɤǤꡤĤΥ⥸塼 +롼ɤ饹privateåɤˤʤ褦ʥåɤλ +Ǥ롥㤨СMath⥸塼δؿ@samp{module function}Ǥ롥 + +@item private(@var{name}@dots{}) + +@var{name}ǻꤵ줿åɤؿǤƤӽФǽˤ롥 +privateåɤǤˤϲ⤷ʤ + +@item public(@var{name}@dots{}) + +@var{name}ǻꤵ줿åɤ̾ǸƤӽФǽˤ롥Ǥ +publicåɤǤˤϲ⤷ʤ + +@example +def foo() 1 end +foo + @result{} 1 +self.foo + @result{} 1 + +def bar() 2 end +private :bar +bar + @result{} 2 +self.bar + @error{} method `bar' not available for "main"(Object) + +Module Baz + def baz() 3 end + module_function :baz +end +Baz.baz + @result{} 3 +include Baz +baz + @result{} 3 +self.baz + @error{} method `baz' not available for "main"(Object) +@end example + +@item to_s + +⥸塼ʸɽǤ⥸塼֤̾ +@end ftable + +@xref{Object} + +@node Nil, Numeric, Module, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Nil + +ɽ֥@code{nil}Υ饹ѿ()@code{nil} +@code{Nil}饹ͣΥǤ롥 + +SuperClass: Kernel + +Methods: + +@ftable @code +@item self + @var{other} + +@var{other}ưʸǤ@var{other} + + +@item nil? + +˿֤ +@end ftable + +@xref{Kernel} + +@node Numeric, Object, Nil, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Numeric + +̤ɽݥ饹 + +SuperClass: Object + +Included Modules: Comparable + +Methods: + +@ftable @code +@item + self + +֥@code{self}ΤΤ֤ + +@item - self + +@code{0 - self}֤֥ͤ饹ǤΨŪ˺뤳Ȥ +Ԥ롥 + +@item abs + +֤ͤ + +@item divmod(@var{other}) + +Ⱦ;2Ǥ֤ + +@item next + +ο֤οȤϤοۤǾǤ롥 +@end ftable + +@xref{Object} +@xref{Comparable} + +@node Object, Proc, Numeric, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Object + +Ƥ̾說饹Υѥ饹̾說饹ΥΰŪʿ +Ƥ롥Υ饹Υ֥饹Ǥʤ饹@code{Kernel} +@code{Nil}Ǥ롥 + +SuperClass: Kernel + +Methods: + +@ftable @code +@item extened(module@dots{}) + +ǻꤷ⥸塼@code{self}˥롼ɤ롥⥸塼 +ƤåɤðۥåɤȤɲä롥 + +@item initialize(@dots{}) + +@code{Class:new}饪֥Ȥ˼ưŪ˸ƤӽФ롥ǥե +Ȥϲ⤷ʤ֥饹ɬפ˱ƺ뤳Ȥ +Ƥ롥@code{Class:new}Ϳ줿ΤޤϤ롥 + +@item is_instance_of?(@var{class}) + +֥@code{self}饹@var{class}ΥǤ +֤@code{obj.is_instance_of?(c)}ΩĤ +@code{obj.is_kind_of?(c)}Ω롥 + +@item is_kind_of?(@var{class}) + +֥@code{self}饹@var{class}Υ֥饹Υ +Ǥ֤ + +@item clone +@item dup + +֥Ȥʣ롥¨ͤǤFixnum饹ʳΥ +饹ξ硤@code{obj.equal?(obj.clone)}ϵǤ뤬¿ξ +@code{obj == obj.clone}ϿǤ롥 + +String饹ʳǤ(ä˺ʤ¤)dupclone̾Ǥ롥 + +@item to_s + +֥Ȥʸɽ֤ΥåɤŪprintformat +åɤѤƤ롥 + +@item to_a + +֥ȤѴ롥@code{Kernel}饹Ƥǥե +ȤϡΥ֥ȼȤޤ1Ǥ֤ +@end ftable + +@xref{Kernel} + +@node Proc, Process, Object, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Proc + +ƥ졼Ϥ줿ƥ졼֥å³Ȥƥ֥Ȳ +Ρ¹Ԥ륳ɤǤʤƥ(ѿ)ʤɤ¸롥 +֥å֥Ȥϡ@code{call}åɤˤäơ줿ΤƱ +Ķɾ뤳ȤǤ롥æ(@code{return}, +@code{break}, @code{continue}, @code{redo}, @code{retry})δĶ¸ +ʤΤǡ֥å֥ȤæФμ¹Ԥ㳰ȯ +뤳Ȥˤʤ롥 + +SuperClass: Object + +Methods: + +@ftable @code +@item call(@var{arg}[,@dots{}]) + +֥å¹Ԥ롥 +@end ftable + +Single Methods: + +@ftable @code +@item new + +֥å롥@code{yield}¹ԤǤǤΥåɤ +ƤФȡλǼ¹Ԥ٤ɤƥȤȤȤ߹ +֥(@code{Proc})롥 +@end ftable + +@xref{Object} + +@node Process, Range, Proc, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Process + +ץ˴ؤԤʤΥ⥸塼롥@code{Math}⥸塼 +ƱͤƤΥåɤðۥåɤȤƤ̾ΥåɤȤƤȤ롥 +@code{Process}ϥץ֥ȤΥ饹ǤϤʤơץ +åɤޤȤΤǤ뤳Ȥդ뤳ȡ + +Methods: +Single Methods: + +@ftable @code +@item egid + +ץθߤμ¸GID֤ + +@item egid= @var{gid} + +ץθߤμ¸GID@var{gid}˥åȤ롥 + +@item euid + +ץθߤμ¸UID֤ + +@item euid= @var{uid} + +ץθߤμ¸UID@var{uid}˥åȤ롥 + +@item getpgrp([@var{pid}]) + +@var{pid}ǻꤵ줿ץ߽°Ƥץ롼פid +֤@var{pid}ά@var{pid}0Ϳϸ¹ԤƤ +ץоݤˤ롥 + +@item getpriority(@var{which}, @var{who}) + +@var{which}@var{who}ǻꤵץץ롼ס桼 +ߤ̤֤ͥܺ٤@samp{getpriority(2)}ȡProcess⥸塼 +ǤwhichȤƻǤ@var{PRIO_PROCESS}@var{PRIO_PGRP} +@var{PRIO_USER}Ƥ롥 + +@item gid + +ץθߤμGID֤ + +@item gid= @var{gid} + +ץθߤμGIDgid˥åȤ. + +@item pid + +ץΥץID֤ϥƥѿ@code{$$}ͤƱǤ +롥 + +@item ppid + +ƥץΥץΥץID֤UNIXǤľܤοƥץλ +硤ƥץpid1(initpid)ˤʤ롥 + +@item setpgrp(@var{pid}, @var{pgrp}) + +@var{pid}ǻꤵ줿ץΥץ롼פ@var{pgrp}ˤ롥 +@var{pid}0Ϳȸ¹Υץоݤˤ롥 + +@item setpriority(@var{which}, @var{who}, @var{prio}) + +@var{which}@var{who}ǻꤵץץ롼ס桼 +ߤ̤ͥ@var{prio}ꤹ롥ܺ٤@samp{setpriority(2)} +ȤΤȡ + +@item uid + +ץθߤμUID֤ + +@item uid= @var{uid} + +ץθߤμUID@var{uid}˥åȤ. +@end ftable + +@node Range, Regexp, Process, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Range + +ϰϥ֥ȤΥ饹ϰϥ֥Ȥ@code{..}黻Ҥˤä +졤ŪˤϰʲΤ褦ʻȤ + +@example +for i in 1..5 + @dots{} +end +@end example + +ξϰʲ®. + +@example +1.upto(5) { + @dots{} +} +@end example + +ϰϥ֥Ȥ@code{..}黻Ҥξդ@code{Comparable} +९饹ΥǤвǤʤϰϤϻȽޤळ +Ȥդ뤳. + +SuperClass: Object + +Included Modules: Enumerable + +Methods: + +@ftable @code +@item self =~ @var{other} + +@code{self}@var{other}Ʊ饹Фϰϥ֥Ȥǡ +@var{other}(@code{start <= @var{other} <= end}) +@code{case}ϰϻꤹǤ롥㤨 + +@example +case i +when 1, 3..5 + @dots{} +end case +@end example + +Τ褦ʥɤȤǤ롥 + +@item each + +ϰ¸ߤ륪֥ȤͿ륤ƥ졼@code{for}Τ +Ѥ롥 + +@item end + +ϰϤν֤ + +@item start + +ϰϤλ֤ +@end ftable + +@xref{Object} +@xref{Enumerable} + +@node Regexp, String, Range, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Regexp + +ɽΥ饹ɽΥƥ@code{/@dots{}/}Ȥɽ +ưŪ뤿ˤ + +@example +Regexp.new(ʸ) +@end example + +Ȥ롥String饹@code{=~}ϤȤ¿Υåɤ +ɽؤʸͿ줿ˤŪɽΤǡ +ȤȻפ䡤ɽʸʸζ̤Ū +˻ꤷʤɰʳŪȻפȤϾʤϤ + +SuperClass: Object + +Methods: + +@ftable @code +@item self =~ @var{string} + +ɽʸ˥ޥå硤ޥå֤֤ޥåʤ +@code{nil}֤ + +@item ~ self + +@code{$_ =~ self}Ʊ +@end ftable + +Single Methods: + +@ftable @code +@item compile(@var{string}[, @var{casefold}]) +@itemx new(@var{string}[, @var{casefold}]) + +ʸɽѴ֥Ȥ֤άǽ2Ϳ +졤ͤ@code{nil}Ǥʤˤϡ줿ɽ֥Ȥ +ƥѿ@code{$=}ͤ˴ؤ餺ޥåʸʸΰ㤤 +̵뤹롥 + +@item quote(@var{str}) + +ʸɽǰ̣ʸפ롥ʸ + +@end ftable + +@xref{Object} + +@node String, Struct, Regexp, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section String + +ʸ饹Rubyʸϥ̥륿ߥ͡ȤǤϤʤΤǡХʥǡ +ⰷ롥äƤɤ餫ȤñʤʸȤХǤ롥 +λۤ˴Ťơɽ˴ؤåɰʳ2byteϤʸռ +ƤʤϺԤμȴǤϤʤտŪˤƤΤǤ( +Ƥ) + +String饹ΥåɤΤ@code{!}ǽΤϥ쥷Ф롥 +Ʊ̾@code{!}̵Τϥ쥷ФΥԡäƤ顤 +롥@code{!}ΤΤ®ͽ̷̤䤹 +ǡ̵ΤǤ롥 + +@example +f = "string" +print f, sub("str", "ski"), f + @result{} string, skiing, string +print f, sub!("str", "ski"), f + @result{} skiing, skiing, skiing +@end example + +SuperClass: Object + +Included Modules: Comparable, Enumerable + +Methods: + +@ftable @code +@item self + @var{other} + +ʸϢ롥Ϣ뤵줿ʸ֤ + +@item self * @var{times} + +ʸη֤㤨@code{x" * 4 == "xxxx"}Ǥ롥 + +@item self == @var{other} +@item self > @var{other} + +ʸӡƥѿ@code{$=}@code{nil}Ǥʤˤʸʸ +̤ӤԤʤ + +@item self =~ @var{other} + +ʸΥޥå@var{other}ɽʸ@var{other}ʸξ +ˤưŪɽѴ롥ޥåϥޥå֡ +ä@code{nil}֤롥 + +@item ~ self + +@code{$_ =~ self}Ʊ + +@item self[@var{nth}] +@item self[@var{beg}..@var{end}] +@item self[@var{beg}, @var{len}] + +ƤμФ1ܤηǤ@var{nth}ХܤΥǡFixnumȤ +֤2ܤηǤ@var{beg}Хܤ@var{end}ХܤޤǤʬ +ʸ֤(ξüޤ)3ܤηǤ@var{beg}Хܤ +@var{len}Хʬʬʸ֤ + +@item self[@var{nth}] = @var{val} +@item self[@var{beg}..@var{end}] = @var{val} +@item self[@var{beg}, @var{len}] = @var{val} + +Ƥι1ܤηǤ@var{nth}ХܤΥǡ@var{val}() +ѹ롥2ܤη@var{beg}Хܤ@var{end}ХܤޤǤ +ʬʸ@var{val}ȤͿ줿ʸ֤롥3ܤη +@var{beg}Хܤ@var{len}Хʬʬʸ@var{val}ȤͿ +줿ʸ֤롥 + +@item capitalize +@itemx capitalize! + +ʸκǽʸ(줬ե٥åȤǤ)ʸѴ +ĤʸΥե٥åȤʸ֤롥 + +@item chop +@itemx chop! + +ʸκǸΥХȤڤȤʸѹ뤳Ȥդ뤳 +ȡ@code{chop!}ϸʸ롥 + +@item crypt(@var{salt}) + +@samp{crypt(3)}ѤưŹ沽ʸ֤@var{salt}2ХȰʾ +ĹǤդʸǤ롥 + +@item delete(@var{str}) +@itemx delete!(@var{str}) + +ʸΤ@var{str}˴ޤޤʸ롥ʸλ +@code{tr}ƱͤǤꡤ@code{a-b}@code{a}@code{b}ޤǤϰϤ +Ƭ@code{^}ʸ(ޤޤƤʤΤ)̣롥 + +@item dup + +@code{self}ƱƤʸ롥@code{clone} +@code{freeze}֤⥳ԡ뤬@code{dup}Ƥʸ +롥 + +@item downcase +@itemx downcase! + +ʸΥե٥åȤƾʸ֤ʸ֤ +@code{tr("A-Z", "a-z")}꾯® + +@item each @{|@var{char}|@dots{}@} +@itemx each_byte @{|@var{char}|@dots{}@} + +ʸΤ줾ΥХȤˤĤƷ֤ƥ졼 + +@item each_line @{|@var{line}|@dots{}@} + +ʸ1Ԥɤ߹Ǥ륤ƥ졼 + +@item freeze + +ʸԲĤˤ롥ٹԲĤꤵ줿ʸƤѹ +Ȥ㳰ȯ롥 + +@item gsub(@var{pattern}, @var{replace}) +@itemx gsub(@var{pattern}) @{@dots{}@} +@itemx gsub!(@var{pattern}, @var{replace}) +@itemx gsub!(@var{pattern}) @{@dots{}@} + +ʸ@var{pattern}˥ޥåʬ@var{replace}֤롥 +ִʸ@var{replace}@samp{&}@samp{\0}ϥޥåʸˡ +@samp{\1@dots{}\9}nܤγ̤Ƥ֤롥 +@var{replace}ά줿ˤϥƥ졼Ȥư֥åɾ +ִ̤롥 + +@code{gsub}ִ줿ʸ֤(ִԤʤʤäϸʸ +֤)@code{gsub!}ִԤʤ줿ˤоݤȤʤʸ +Ԥʤʤäˤ@code{nil}֤ + +@item hex + +ʸ16ʿɽʸȲᤷơѴ롥 + +@item index(@var{substr}[, @var{pos}]) + +@var{substr}ǽ˽и֤֤@var{pos}ͿȤΰ֤ +鸡Ϥ롥Ĥʤˤ@code{nil}֤ + +@item intern + +ʸ˰դб֤ʸϥʥʸޤǤϤʤʤ + +@item length +@itemx size + +ʸĹ(Хȿ)֤ + +@item ljust(@var{width}) +@itemx rjust(@var{width}) +@itemx center(@var{width}) + +ʸ줾졤ͤᡤͤᡤ@var{width}ʸ +֤ʸĹ@var{width}Ĺϸʸ֤ڤͤ + + +@item next + +@code{self}ΡּΡʸ֤ʸȤϿϿȤơ +ʸϱʸȤä夬νԤʤ줿ΤǤ롥 + +@example +"aa".next @result{} "ab" +"99".next @result{} "100" +"a9".next @result{} "b0" +@end example + +@item oct + +ʸ8ʿɽʸȲᤷơѴ롥8ʿ +@code{/[0-7]+/}ǤꡤʸƬ餳Υѥ˥ޥåʬ +Ѵ롥ƤϤޤʤʸФƤ0֤ +perlȤϰäʸ0xϤޤäƤ뤫Ȥä 16ʿȸʤ +Ƥ줿ϤʤƬ08ʿǧ졤0֤ + +@item reverse +@itemx reverse! + +ʸγƥХȤս¤٤ʸ֤ʸ2ХȤǹ +ʸޤǤƤ⤪ʤ˥Хñ̤ȿž롥@code{split}2 +ХʸΤǡ2Хʸޤʸʸñ̤ȿž +ˤ + +@example +"ʸ".split(//).reverse.join("") +@end example + +ȤФ褤 + +@item rindex(@var{substr}[, @var{pos}]) + +ʸ@var{substr}Ǹ˽и֤֤@var{pos}ͿȤ +֤Ǹλ롥Ĥʤˤ@code{nil}֤@code{index} +Ȥ + +@itemize +@item +ʸ鸡롥 +@item +substrȤɽդʤ +@end itemize + +2Ǥ롥 + +@item split([@var{sep}[, @var{limit}]]) + +ʸ@var{sep}ǻꤵ줿ѥˤäơեɤʬ䤹롥 +@var{sep}ά줿ΥǥեȤϥƥѿ@code{$;}ͤѤ +롥@var{limit}ꤵ줿ˤϺ@var{limit}ĤΥեɤʬ +롥s@code{plit}ʬ䤵줿ʸޤ֤@var{sep}ǻ +줿ѥʸȥޥåʸ1ʸĤʬ䤵 +롥 + +@item squeeze([@var{str}]) +@itemx squeeze!([@var{str}]) + +ʸΤ@var{str}˴ޤޤʸϢ³Ƥ硤ʸ˰ +롥@var{str}ά줿硤٤ƤʸоݤȤ롥ʸλ +trƱͤǤꡤ@code{a-b}@code{a}@code{b}ޤǤϰϤƬ +@code{^}ʸ(ޤޤƤʤΤ)̣롥 + +@item strip +@itemx strip! + +ʸζ + +@item sub(@var{pattern}, @var{replace}) +@itemx sub(@var{pattern}) @{@dots{}@} +@itemx sub!(@var{pattern}, @var{replace}) +@itemx sub!(@var{pattern}) @{@dots{}@} + +ʸ@var{pattern}˥ޥåǽʬ@var{replace}֤롥 +ִʸ@var{replace}@samp{&}@samp{\0}ϥޥåʸˡ +@samp{\1@dots{}\9} nܤγ̤Ƥ֤롥 +@var{replace}Τʤλˤϥƥ졼Ȥư֥åɾ +ִ̤롥 + +@code{sub}ִ줿ʸ֤(ִԤʤʤäϸʸ +֤)@code{sub!}ִԤʤ줿ˤоݤȤʤʸ +ʤʤäˤ@code{nil}֤ + +@item sum([@var{bits}]) + +ʸ@var{bits}ӥåȤΥå롥άͤ16Ǥ롥ruby +ϰʲΥɤSystem V@code{sum}ץƱͤ롥 + +@example +while gets() + sum += $_.sum +end +sum %= 65536 +@end example + +@item swapcase +@itemx swapcase! + +ʸΥե٥åȤΤʸʸˡʸʸ֤ +롥 + +@item to_f + +ʸFloatѴ롥 + +@item to_i + +ʸ10ʿɽʸȲᤷơѴ롥 + +@item tr(@var{search}, @var{replace}) +@itemx tr!(@var{search}, @var{replace}) + +ʸ@var{search}ʸ˴ޤޤʸ¸ߤС +@var{replace}ʸбʸ֤롥@var{replace}ʸ +ά줿϶ʸͿ줿ȸʤ@var{replace}ʸ +@var{search}ʸû@var{replace}ʸκǸʸ +֤Ƥȸʤ@var{search}ʸûˤбʸ +ʤ@var{replace}ñ̵뤵(BSD@samp{tr}ư) + +@var{search}ʸ@var{replace}ʸ@code{a-b}Ȥ +硤@code{a}@code{b}ޤǤϰϤʸASCIIξǻꤷ +Ȥˤʤ롥ޤ@var{search}ʸκǽʸ@code{^}Ǥ硤 +³ʸ*ޤޤʤ*ʸִоݤˤʤ롥 + +@samp{tr(1)}εǽΤʸ뵡ǽϢ³ʸ̤뵡 +ǽ̤Υåɤʬ䤵Ƥ롥εǽˤĤƤ@code{delete} +@code{squeeze}ȤΤȡ + +ؤΤᡤ@code{str.tr(src,repl).squeeze(repl)}å +@code{tr_s(src,repl)}Ƥ롥 + +@item unpack(@var{template}) + +ʸ@var{template}ʸˤäƥѥåǤ +֤@var{template}ʸArray饹packåɤȤۤƱ +ͤǤ롥 + +@display +a ASCIIʸ(³nullʸ䥹ڡĤ) +A ASCIIʸ(³nullʸ䥹ڡ) +b ӥåȥȥ(̥ӥåȤ̥ӥå) +B ӥåȥȥ(̥ӥåȤ鲼̥ӥå) +h 16ʸ(̥˥֥뤬) +H 16ʸ(̥˥֥뤬) +c char +C unsigned char +s sort +S unsigned sort +i int +I unsigned int +l long +L unsigned int +n ͥåȥХȥshort +N ͥåȥХȥlong +f ñư(¸) +d ư(¸) +x 1ХɤФ +X 1Хȸ +@@ а֤ؤΰư +@end display + +ruby@code{unpack}perlȰäƥåηǽʤȤ +դ뤳ȡ + + +@item upcase +@itemx upcase! + +ʸΥե٥åȤʸ֤ʸ֤ +@code{tr("a-z", "A-Z")}꾯® + +@item upto(@var{end}) @{@dots{}@} + +@code{self}Ϥޤäơ@var{end}ޤǡּΡʸͿ륤ƥ졼 +ʸȤ@code{str.next}ͿʸǤ롥 + +Υåɤ@code{Range:each}ѤƤΤǡʲΤ褦ʽ +ǽǤ롥 + +@example +for i in "a" .. "ba" + print(i, "\n"); +end +@end example + +@samp{a, b, c,@dots{}aa,@dots{}az, ba}ޤǤƹԤ˽Ϥ롥 +@end ftable + +Single Methods: + +@ftable @code +@item new(@var{string}) + +@var{string}ƱƤĿʸ֤ +@end ftable + +@xref{Object} +@xref{Enumerable} +@xref{Comparable} + +@node Struct, Time, String, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Struct + +¤Υ饹Υ饹Υ֥饹ʣΥǡޤȤѤ +(: @code{Time:times})ǡޤȤˤ饹Ѥ +뤳Ȥ⤢뤬(: @code{select})¤ΤȤ٤ϰʲΤ褦 +Ǥ롥@code{Struct:new}@code{Struct}Υ֥饹 +ơ֤¤ΤϤΥ֥饹ΥȤʤ롥 + +@enumerate +@item +Ǥο + +ǤοưΤϹ¤ΤȤΤˤϸʤ + +@item +Ǥο¿ + +ʹ֤٤ưפ˰복ǰο7ĤޤǤǤȤ⤬롥 +˽СǤ4İʾ夢ǡξѤ硤ǿ +2(ĤޤꥪեåȤȤΰ̣)7ۤ롥äơΤ褦 +ˤϹ¤ΤȤä䤹Ȼפ롥 + +@item +Ʊ̤ʤ + +¤Τ㴳Ȥ⤤Τǡ®٤ˤʤ (㤨 +Ʊ̤ʤ)Ϲ¤ΤλѤŬڤǤʤǽ +롥 +@end enumerate + +ƹ¤Τˤϥ̾Ʊ̾ΰΤʤåɤ롥 + +ܥɥǡ¤Τɽ뤿ˤϰʲηȤ + +@display +struct ¤̾ + @dots{} +end +@end display + +ץǤηǹ¤Τ櫓ǤϤʤ + +SuperClass: Object + +Included Modules: Enumerable + +Methods: + +@ftable @code +@item self[@var{idx}] + +@var{idx}λ@var{idx}ܤǤ֤ + +@item values +@itemx to_a + +¤ΤΥФͤǤ˻֤㤨аʲΥɤǼʬ +passwdȥϤ뤳ȤǤ롥 + +@example +print(Etc.getpwuid().values.join(":"), "\n") +@end example + +νϤ@samp{grep "$USER" /etc/passwd}νϤ;ʬʥեɤ +Ĥ(ƥˤäưۤʤ)ʳƱǤ롥 +@end ftable + +Single Methods: + +@ftable @code +@item new(@var{name}, @var{member}@dots{}) + +@var{name}Ȥ̾ŤΤΥ饹롥@var{member_value} +Ϲ¤ΤΥФɽʸǤ롥줿¤Υ饹ˤϥФ +ꤵ줿̾ΥåɤƤơΥåɤˤäƥФ +Ƥ뤳ȤǤ롥 +@end ftable + +Single Methods for subclasses: + +@ftable @code +@item new(@var{value}@dots{}) + +¤Υ饹Υ롥@var{value}Ϲ¤ΤΥФ +Ǥ롥Фο¤Υ饹줿Ȱۤʤˤ㳰ȯ +롥 +@end ftable + +@xref{Object} +@xref{Enumerable} + +@node Time, , Struct, Ȥ߹ߥ饹ȥ⥸塼 +@comment node-name, next, previous, up +@section Time + +֤ɽ饹羮ӤʤɤǤ롥@code{Time.now}Ǹߤλ֤ +뤳ȤǤ롥ޤեΥॹפåɤͤ +Υ饹ΥǤ롥 + +SuperClass: Object + +Included Modules: Comparable + +Methods: + +@ftable @code +@item self <=> @var{other} + +@var{other}TimeΥͿ줿ˤ +@samp{1970ǯ1 1 00:00:00 GMT}ÿǤȤƻȤӤ +Ԥʤ + +@item asctime +@itemx ctime +@itemx to_s + +@samp{date(1)}ʸѴ롥 + +@item gmtime + +ॾνԤʤʤGMTǤλ롥ΥåɤȤ +Time饹ΥϡʸλѴGMTǹԤʤ +@code{gmtime}ϼʬȤ֤ + +ɥλɽˤ@code{print(Time.now.gmtime, "\n")}Ȥ +Ф褤 + +@item localtime + +ॾνԤʤä(ǥե)@code{localtime} +ʬȤ֤ + +@item to_i +@itemx tv_sec + +@samp{1970ǯ 1 1 00:00:00 GMT}ޤǤÿ֤ +secondʬǤ⤢롥 + +@item sec +@itemx min +@itemx hour +@itemx mday +@itemx year +@itemx wday +@itemx yday +@itemx zone +@itemx isdst + +ŪݻƤ@code{tm}¤ΤƤ֤@code{zone}ʳ +֤@code{zone}ϥॾɽʸ֤(cf +@samp{localtime(3)}) + +@item strftime(@var{format}) + +@var{format}ʸ˽äʸѴ̤֤ +@var{format}ʸȤƻǤΤ ʲ̤Ǥ롥 + +@display +%A ̾(Sunday, Monday@dots{}) +%a ξά̾(Sun, Mon@dots{}) +%B ̾(January, February@dots{}) +%b ξά̾(Jan, Feb@dots{}) +%c ɽ(cf @samp{ctime(3)}) +%d ʿǤ(01-31) +%H 24λ(00-23) +%I 12λ(01-12) +%j ǯ̻(001-366) +%M ʬ(00-59) +%m ɽ(01-12) +%p ޤϸ(AM,PM) +%S (00-61) +%U ɽǽ1 + Ϥޤ(00-53) +%W ɽǽη1 + Ϥޤ(00-53) +%w ɽ0(0-6) +%X (: 15:01:06) +%x (: Fri Jan 14 1994) +%Y ɽ +%y β2(00-99) +%Z ॾ +%% % +@end display + +@item usec +@itemx tv_usec + +micro secondʬ֤ +@end ftable + +Single Methods: + +@ftable @code +@item now + +ߤλɽ@code{Time}饹Υ롥 + +@item at(@var{time}) + +@var{time}Ʊɽ@code{Time}饹Υ롥 +@var{time}@code{Time}饹Υ뤤Ͽ(/ư +)Ǥꡤξ@samp{1970ǯ 1 1 00:00:00 GMT}ÿ +Ȥƻ롥 + +@item times + +ߤΥץȤλҥץ桼/ƥCPUѻ +¤ΤȤ֤(@xref{Struct}) + +@display +struct tms + utime # ץΥ桼 + stime # ץΥƥ + cutime # ҥץΥ桼 + cstime # ҥץΥƥ +end +@end display + +֤ñ̤äǤꡤưͿ롥ܺ٤@samp{times(3)} +ȤΤȡ +@end ftable + +@xref{Object} +@xref{Comparable} + +@node CȤΥե, ռ, Ȥ߹ߥ饹ȥ⥸塼, Top +@comment node-name, next, previous, up +@chapter CȤΥե + +rubyCȤΥեC줫Υ饹⥸塼 +CǵҤåɤrubyΥåɤθƤӽФ +졼θƤӽФ㳰ʤɤԤʤȤ롥ޤOSм +ԻCǽ줿⥸塼ɤ뤳Ȥ롥 + +Ūʥե˴ؤƤϡ̥ɥ(źեե C-IF) +ȤΤȡ + +@node ռ, ʸˡ, CȤΥե, Top +@comment node-name, next, previous, up +@chapter ռ + +RubyθͤϿ¿θαƶƤ롥ʲˤΤϤμ +ʸǤ롥 + + C, Perl, CLU, Sather, CLOS, Eiffel, Icon, tcl, AWK, bourne shell, + Smalltalk, Emacs Lisp. + +ޤrubyθͤꤹ뤿˶ϤƲäʲˤ롥 + + ͷƣϺ¼Σţáغܣģţá + ʤֺ.ٻ(ɾά) + +@node ʸˡ, Variables Index, ռ, Top +@comment node-name, next, previous, up +@chapter ʸˡ + +ʲϵBNFǵҤrubyʸˡǤ롥ΤʵҤparse.y +줿 + +@example +PROGRAM : COMPEXPR + +COMPEXPR : EXPR (TERM EXPR)* [TERM] + +EXPR : MLHS `=' ARGS + | return ARGS + | fail ARGS + | yield ARGS + | defined? ARG + | identifier CALL_ARGS0 + | PRIMARY `.' identifier CALL_ARGS0 + | super CALL_ARGS + | undef FNAME + | alias FNAME FNAME + | include identifier (`,' identifier)* + | EXPR if EXPR + | EXPR while EXPR + | EXPR and EXPR + | EXPR or EXPR + | ASSOCS + | ARG + +ARG : LHS `=' ARG + | LHS OP_ASGN ARG + | ARG `..' ARG + | ARG `...' ARG + | ARG `+' ARG + | ARG `-' ARG + | ARG `*' ARG + | ARG `/' ARG + | ARG `%' ARG + | ARG `**' ARG + | `+' ARG + | `-' ARG + | ARG `|' ARG + | ARG `^' ARG + | ARG `&' ARG + | ARG `<=>' ARG + | ARG `>' ARG + | ARG `>=' ARG + | ARG `<' ARG + | ARG `<=' ARG + | ARG `==' ARG + | ARG `!=' ARG + | ARG `=~' ARG + | ARG `!~' ARG + | `!' ARG + | `~' ARG + | ARG `<<' ARG + | ARG `>>' ARG + | ARG `&&' ARG + | ARG `||' ARG + | ARG `::' identifier + | PRIMARY + +PRIMARY : `(' COMPEXPR `)' + | LITERAL + | VARIABLE + | super `(' [CALL_ARGS] `)' + | super + | PRIMARY `[' [ARGS] `]' + | `[' [ARGS [`,']] `]' + | `@{' [ (ARGS|ASSOCS) [`,'] ] `@}' + | redo + | break + | continue + | retry + | return + | fail [`(' [ARGS] `)'] + | yield [`(' [ARGS] `)'] + | defined? `(' ARG `)' + | PRIMARY `@{' [`|' [ITER_VAR] `|'] COMPEXPR `@}' + | OPERATION `(' [CALL_ARGS] `)' + | PRIMARY `.' OPERATION `(' [CALL_ARGS] `)' + | PRIMARY `.' OPERATION + | if EXPR THEN + COMPEXPR + (elsif EXPR THEN COMPEXPR)* + [else COMPEXPR] + end + | while EXPR TERM COMPEXPR end + | case COMPEXPR + (when ARGS THEN)+ + [else COMPEXPR] + end + | for ITER_VAR in EXPR TERM + COMPEXPR + end + | begin + COMPEXPR + [rescue COMPEXPR] + [ensure COMPEXPR] + end + | class identifier `:' identifier + COMPEXPR + end + | module identifier + COMPEXPR + end + | def FNAME ARGLIST + COMPEXPR + end + | def SINGLETON `.' FNAME ARGLIST + COMPEXPR + end + +THEN : TERM + | then + | TERM then + +ITER_VAR : LHS + | MLHS + +MLHS : LHS `,' [LHS (`,' LHS)*] [`*' LHS] + +LHS : VARIABLE + | PRIMARY `[' [ARGS] `]' + | PRIMARY `.' identifier + +CALL_ARGS : ARGS + | ASSOCS + | ARGS [`,' ASSOCS] [`,' `*' ARG] + | `*' ARG + +ARGS : ARG (`,' ARG)* + +ARGLIST : `('[identifier(`,'identifier)*][`*'identifier]`)' + | TERM + +SINGLETON : VARIABLE + | `(' EXPR `)' + +ASSOCS : ASSOC (`,' ASSOC)* + +ASSOC : ARG `=>' ARG + +VARIABLE : VARNAME + | nil + | self + | `__FILE__' + | `__LINE__' + +LITERAL : numeric + | SYMBOL + | STRING + | REGEXP + +TERM : `;' + | `\n' + +@end example + +겼ϻǧ롥 + +@example + +SYMBOL : `:'FNAME + | `:'VARNAME + +FNAME : identifier | `..' | `|' | `^' | `&' + | `<=>' | `==' | `=~' | `>' | `>=' | `<' | `<=' + | `<<' | `>>' | `+' | `-' | `*' | `/' | `%' | `**' + | `~' | `+@@' | `-@@' | `[]' | `[]=' + +OPERATION : identifier + | identifier'!' + | identifier'?' + +VARNAME : GLOBAL + | `@@'identifier + | identifier + +GLOBAL : `$'identifier + | `$'any_char + +STRING : `"' any_char* `"' + | `'' any_char* `'' + | ``' any_char* ``' + +REGEXP : `/' any_char* `/'[i] + +@end example + +@node Variables Index, Concept Index, Function Index, Top +@comment node-name, next, previous, up +@unnumbered Variable Index + +@printindex vr + +@node Concept Index, Function Index , Variables Index, Top +@comment node-name, next, previous, up +@unnumbered Concept Index + +@printindex cp + +@node Function Index, Top , Concept Index, Top +@comment node-name, next, previous, up +@unnumbered Function Index + +@printindex fn + +@summarycontents +@contents +@bye + +Local variables: +fill-column: 70 +end: diff --git a/sample/MANIFEST b/sample/MANIFEST deleted file mode 100644 index 93c971b114..0000000000 --- a/sample/MANIFEST +++ /dev/null @@ -1,63 +0,0 @@ -MANIFEST -aset.rb -attr.rb -biorhythm.rb -blk.rb -case.rb -cat.rb -cat2.rb -cbreak.rb -clnt.rb -clone.rb -const.rb -dbm.rb -dir.rb -evaldef.rb -export.rb -exyacc.rb -fib.awk -fib.pl -fib.rb -fib.scm -freq.rb -from.rb -fullpath.pl -fullpath.rb -gctest.rb -gctest2.rb -getopts.rb -getopts.test -hash.rb -io.rb -less.rb -list.rb -list2.rb -list3.rb -math.rb -mpart.rb -occur.pl -occur.rb -occur2.rb -opt_s.rb -opt_x.test -parsearg.rb -rcs.awk -rcs.dat -rcs.rb -ruby-mode.el -samp.rb -sieve.rb -split.rb -struct.rb -svr.rb -system.rb -t1.rb -t2.rb -test.rb -time.rb -trap.pl -trap.rb -trojan.pl -trojan.rb -tt.rb -uumerge.rb diff --git a/sample/aset.rb b/sample/aset.rb deleted file mode 100644 index 414c13ba70..0000000000 --- a/sample/aset.rb +++ /dev/null @@ -1,7 +0,0 @@ -# array set example -# output: -# 07045 - -ary = [0, 0, 4, 5] -ary[1, 0] = [7] -print ary, "\n" diff --git a/sample/attr.rb b/sample/attr.rb deleted file mode 100644 index 1d329ea06a..0000000000 --- a/sample/attr.rb +++ /dev/null @@ -1,14 +0,0 @@ -# attribute access example -# output: -# 10 -# #<Foo: @test=10> - -class Foo - attr "test", TRUE -end - -foo = Foo.new -foo.test = 10 -print foo.test, "\n" -foo._inspect.print -print "\n" diff --git a/sample/blk.rb b/sample/blk.rb deleted file mode 100644 index e11cc026ea..0000000000 --- a/sample/blk.rb +++ /dev/null @@ -1,9 +0,0 @@ -def foo() - $block = Block.new -end - -foo(){|i| print "i = ", i, "\n"} -$block.call(2) - -foo(){|i| print "i*2 = ", i*2, "\n"} -$block.call(2) diff --git a/sample/case.rb b/sample/case.rb deleted file mode 100644 index e844cddfd6..0000000000 --- a/sample/case.rb +++ /dev/null @@ -1,14 +0,0 @@ -# case statement example -# output: -# 3..5 - -case "t" -when /1/ - print 1, "\n" -when /t/ - print 3..5, "\n" -when /./ - print 2, "\n" -else - print "else\n" -end diff --git a/sample/cat.rb b/sample/cat.rb deleted file mode 100644 index a3243d308d..0000000000 --- a/sample/cat.rb +++ /dev/null @@ -1,5 +0,0 @@ -# cat -n & `...' operator test -while gets() - if $. == 1 ... ~ /^\*/; print("--") end - printf("%5d: %s", $., $_) -end diff --git a/sample/cat2.rb b/sample/cat2.rb deleted file mode 100644 index bbc1ebb0ff..0000000000 --- a/sample/cat2.rb +++ /dev/null @@ -1,5 +0,0 @@ -# cat -n & `...' operator test -while gets() - if 1 ... /^\*/; print("--") end - printf("%5d: %s", $., $_) -end diff --git a/sample/clnt.rb b/sample/clnt.rb index d2c71ec563..c8c4b2db9f 100644 --- a/sample/clnt.rb +++ b/sample/clnt.rb @@ -1,5 +1,8 @@ # socket example - client side # usage: ruby clnt.rb [host] port + +require "socket" + host=(if $ARGV.length == 2; $ARGV.shift; else "localhost"; end) print("Trying ", host, " ...") STDOUT.flush diff --git a/sample/clone.rb b/sample/clone.rb deleted file mode 100644 index e7d6b00a31..0000000000 --- a/sample/clone.rb +++ /dev/null @@ -1,18 +0,0 @@ -# object cloning & single method test -# output: -# test2 -# test -# test -# clone.rb:18: undefined method `test2' for "#<Object: 0xbfca4>"(Object) -foo = Object.new -def foo.test - print("test\n") -end -bar = foo.clone -def bar.test2 - print("test2\n") -end -bar.test2 -bar.test -foo.test -foo.test2 diff --git a/sample/const.rb b/sample/const.rb deleted file mode 100644 index 50780407b8..0000000000 --- a/sample/const.rb +++ /dev/null @@ -1,24 +0,0 @@ -# constant access test -# output: -# 1234 -# 1268 -TEST1 = 1 -TEST2 = 2 - -module Const - TEST3 = 3 - TEST4 = 4 -end - -module Const2 - TEST3 = 6 - TEST4 = 8 -end - -include Const - -print(TEST1,TEST2,TEST3,TEST4,"\n") - -include Const2 - -print(TEST1,TEST2,TEST3,TEST4,"\n") diff --git a/sample/dbm.rb b/sample/dbm.rb index a2e0659bf5..c77cc2065b 100644 --- a/sample/dbm.rb +++ b/sample/dbm.rb @@ -1,4 +1,6 @@ # ruby dbm acess +require "dbm" + d = DBM.open("test") keys = d.keys if keys.length > 0 then diff --git a/sample/exyacc.rb b/sample/exyacc.rb index cd1170feb4..dafcb037cc 100644 --- a/sample/exyacc.rb +++ b/sample/exyacc.rb @@ -8,15 +8,15 @@ while gets() sbeg = $_.index("\n%%") + 1 send = $_.rindex("\n%%") + 1 $_ = $_[sbeg, send-sbeg] - sub(/.*\n/, "") - gsub(/'{'/, "'\001'") - gsub(/'}'/, "'\002'") - gsub('\*/', "\003\003") - gsub("/\\*[^\003]*\003\003", '') - while gsub(/{[^}{]*}/, ''); end - gsub(/'\001'/, "'{'") - gsub(/'\002'/, "'}'") - while gsub(/^[ \t]*\n(\s)/, '\1'); end - gsub(/([:|])[ \t\n]+(\w)/, '\1 \2') + sub!(/.*\n/, "") + gsub!(/'{'/, "'\001'") + gsub!(/'}'/, "'\002'") + gsub!('\*/', "\003\003") + gsub!("/\\*[^\003]*\003\003", '') + while gsub!(/{[^}{]*}/, ''); end + gsub!(/'\001'/, "'{'") + gsub!(/'\002'/, "'}'") + while gsub!(/^[ \t]*\n(\s)/, '\1'); end + gsub!(/([:|])[ \t\n]+(\w)/, '\1 \2') print $_ end diff --git a/sample/from.rb b/sample/from.rb index f21b1d10f5..2f5fcebe12 100755 --- a/sample/from.rb +++ b/sample/from.rb @@ -1,97 +1,10 @@ #! /usr/local/bin/ruby -module ParseDate - MONTHS = { - 'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4, - 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8, - 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12 } - MONTHPAT = MONTHS.keys.join('|') - DAYPAT = 'mon|tue|wed|thu|fri|sat|sun' - - def parsedate(date) - if date.sub(/(#{DAYPAT})/i, ' ') - dayofweek = $1 - end - if date.sub(/\s+(\d+:\d+(:\d+)?)/, ' ') - time = $1 - end - if date =~ /19(\d\d)/ - year = $1 - end - if date.sub(/\s*(\d+)\s+(#{MONTHPAT})\S*\s+/i, ' ') - dayofmonth = $1 - monthname = $2 - elsif date.sub(/\s*(#{MONTHPAT})\S*\s+(\d+)\s+/i, ' ') - monthname = $1 - dayofmonth = $2 - elsif date.sub(/\s*(#{MONTHPAT})\S*\s+(\d+)\D+/i, ' ') - monthname = $1 - dayofmonth = $2 - elsif date.sub(/\s*(\d\d?)\/(\d\d?)/, ' ') - month = $1 - dayofmonth = $2 - end - if monthname - month = MONTHS[monthname.tolower] - end - if ! year && date =~ /\d\d/ - year = $& - end - return year, month, dayofmonth - end - -end +require "parsedate" +require "base64" include ParseDate -def decode64(str) - e = -1; - c = "," - for line in str.split("\n") - line.tr 'A-Za-z0-9+/', "\000-\377" - line.each_byte { |ch| - e+=1 - if e==0 - c = ch << 2 - elsif e==1 - c |= ch >>4 - string += [c].pack('c') - c = ch << 4 - elsif e == 2 - c |= ch >> 2 - string += [c].pack('c'); - c = ch << 6 - elsif e==3 - c |= ch - string += [c].pack('c') - e = -1; - end - } - end - return string; -end - -def j2e(str) - while str =~ /\033\$B([^\033]*)\033\(B/ - s = $1 - pre, post = $`, $' - s.gsub(/./) { |ch| - (ch[0]|0x80).chr - } - str = pre + s + post - end - str -end - -def decode_b(str) - while str =~ /=\?ISO-2022-JP\?B\?(.*)=\?=/ - pre, post = $`, $' - s = decode64($1) - str = pre + s + post - end - j2e(str) -end - if $ARGV[0] == '-w' wait = TRUE $ARGV.shift @@ -100,7 +13,7 @@ end class Mail def Mail.new(f) - if !f.is_kind_of(IO) + if !f.is_kind_of?(IO) f = open(f, "r") me = super f.close @@ -114,9 +27,9 @@ class Mail @header = {} @body = [] while f.gets() - $_.chop + $_.chop! continue if /^From / # skip From-line - break if /^[ \t]*$/ # end of header + break if /^$/ # end of header if /^(\S+):\s*(.*)/ @header[attr = $1.capitalize] = $2 elsif attr @@ -149,17 +62,18 @@ $outcount = 0; def fromout(date, from, subj) return if !date y = m = d = 0 + esc = "\033\(B" y, m, d = parsedate(date) if date from = "sombody@somewhere" if ! from subj = "(nil)" if ! subj from = decode_b(from) subj = decode_b(subj) - printf "%-02d/%02d/%02d [%-28.28s] %-40.40s\n", y, m, d, from, subj + printf "%-02d/%02d/%02d [%-28.28s%s] %-40.40s%s\n",y,m,d,from,esc,subj,esc $outcount += 1 end for file in $ARGV - continue if !File.exists(file) + continue if !File.exists?(file) f = open(file, "r") while !f.eof mail = Mail.new(f) diff --git a/sample/gctest.rb b/sample/gctest.rb deleted file mode 100644 index 6810b95481..0000000000 --- a/sample/gctest.rb +++ /dev/null @@ -1,67 +0,0 @@ -# GC stress test -def cons(car, cdr) - [car, cdr] -end - -def car(x) - if x == nil ; nil else x[0] end -end - -def cdr(x) - if x == nil ; nil else x[1] end -end - -def reverse1(x, y) - if x == nil ; y else reverse1(cdr(x), cons(car(x), y)) end -end - -def reverse(x) - reverse1(x, nil) -end - -def ints(low, up) - if low > up - nil - else - cons(low, ints(low+1, up)) - end -end - -def print_int_list(x) - if x == nil - print("NIL\n") - else - print(car(x)) - if nil != cdr(x) - print(", ") - print_int_list(cdr(x)) - else - print("\n") - end - end -end - -print("start\n") - -a = ints(1, 100) -print_int_list(a) -b = ints(1, 50) -print_int_list(b) -print_int_list(reverse(a)) -print_int_list(reverse(b)) -for i in 1 .. 100 - b = reverse(reverse(b)) -# print(i, ": ") -# print_int_list(b) -end -print("a: ") -print_int_list(a) -print("b: ") -print_int_list(b) -print("reverse(a): ") -print_int_list(reverse(a)) -print("reverse(b): ") -print_int_list(reverse(b)) -a = b = nil -print("finish\n") -GC.start() diff --git a/sample/gctest2.rb b/sample/gctest2.rb deleted file mode 100644 index 851d14f217..0000000000 --- a/sample/gctest2.rb +++ /dev/null @@ -1,71 +0,0 @@ -# GC stress test -def cons(car, cdr) - car::cdr -end - -def car(x) - x.car -end - -def cdr(x) - x.cdr -end - -def reverse1(x, y) - if x == nil then - y - else - reverse1(cdr(x), cons(car(x), y)) - end -end - -def reverse(x) - reverse1(x, nil) -end - -def ints(low, up) - if low > up - nil - else - cons(low, ints(low+1, up)) - end -end - -def print_int_list(x) - if x == nil - print("NIL\n") - else - print(car(x)) - if cdr(x) - print(", ") - print_int_list(cdr(x)) - else - print("\n") - end - end -end - -print("start\n") - -a = ints(1, 100) -print_int_list(a) -b = ints(1, 50) -print_int_list(b) -print_int_list(reverse(a)) -print_int_list(reverse(b)) -for i in 1 .. 100 - b = reverse(reverse(b)) -# print(i, ": ") -# print_int_list(b) -end -print("a: ") -print_int_list(a) -print("b: ") -print_int_list(b) -print("reverse(a): ") -print_int_list(reverse(a)) -print("reverse(b): ") -print_int_list(reverse(b)) -a = b = nil -print("finish\n") -GC.start() diff --git a/sample/hash.rb b/sample/hash.rb deleted file mode 100644 index 85f719e7eb..0000000000 --- a/sample/hash.rb +++ /dev/null @@ -1,11 +0,0 @@ -# hash value -# output: -# 78651 -# 78651 -# 78651 -# -45637 - -print(+-1.0.hash,"\n") -print(-1.0.hash,"\n") -print((-1.0).hash,"\n") -print(-(1.0.hash),"\n") diff --git a/sample/list3.rb b/sample/list3.rb index 2c1beb6fa2..1d756fdff0 100644 --- a/sample/list3.rb +++ b/sample/list3.rb @@ -1,5 +1,5 @@ # Linked list example -- short version -# using _inspect +# using inspect class Point def initialize(x, y) @@ -14,5 +14,5 @@ end list1 = [10, 20, Point.new(2, 3), Point.new(4, 5)] list2 = [20, Point.new(4, 5), list1] -print("list1: ", list1._inspect, "\n") -print("list2: ", list2._inspect, "\n") +print("list1: ", list1.inspect, "\n") +print("list2: ", list2.inspect, "\n") diff --git a/sample/marshal.rb b/sample/marshal.rb new file mode 100644 index 0000000000..3d399ffe68 --- /dev/null +++ b/sample/marshal.rb @@ -0,0 +1,13 @@ +require "marshal" +include Marshal +a = 25.6; +pt = Struct.new('point', :x,:y); +x = pt.new(10, 10) +y = pt.new(20, 20) +rt = Struct.new('rectangle', :origin,:corner); +z = rt.new(x, y) +c = Object.new +s = [a, x, z, c, c, "fff"]; +print s.inspect; +d = dumps(s); +print load(d).inspect diff --git a/sample/math.rb b/sample/math.rb deleted file mode 100644 index c0b5225080..0000000000 --- a/sample/math.rb +++ /dev/null @@ -1,4 +0,0 @@ -# math example -include Math -sqrt(4) -print(Math.sqrt(257), "\n") diff --git a/sample/mkproto.rb b/sample/mkproto.rb new file mode 100644 index 0000000000..1d9c9faccb --- /dev/null +++ b/sample/mkproto.rb @@ -0,0 +1,27 @@ +$/ = nil +while gets() + if /^((void|VALUE|int|char *\*|ID|struct [\w_]+ *\*|st_table *\*) *)?\n([\w\d_]+)\(.*\)\n\s*((.+;\n)*){/ + $_ = $' + printf "%s %s(", $2, $3 + args = [] + for arg in $4.split(/;\n\s*/) + arg.gsub! ' +', ' ' + if arg =~ /,/ + if arg =~ /(([^*]+) *\** *[\w\d_]+),/ + type = $2.strip! + args.push $1.strip! + arg = $' + else + type = "" + end + while arg.sub!(/(\** *[\w\d_]+)(,|$)/, "") + args.push type + " " + $1.strip! + end + else + args.push arg.strip! + end + end + printf "%s);\n", args.join(', ') + redo + end +end diff --git a/sample/occur2.rb b/sample/occur2.rb index 8cd5acbe5e..c450c30b0f 100644 --- a/sample/occur2.rb +++ b/sample/occur2.rb @@ -5,7 +5,7 @@ while gets() for word in $_.split(/\W+/) begin freq[word] = freq[word] + 1 - resque + rescue freq[word] = 1 end end diff --git a/sample/opt_s.rb b/sample/opt_s.rb deleted file mode 100644 index 56ff0eea15..0000000000 --- a/sample/opt_s.rb +++ /dev/null @@ -1,12 +0,0 @@ -#! ./ruby -s -# test for option `-s' - -if ($xyz) - print("xyz = TRUE\n") -end -if ($zzz) - print("zzz = ", $zzz, "\n") -end -if ($ARGV.length > 0) - print($ARGV.join(", "), "\n") -end diff --git a/sample/opt_x.test b/sample/opt_x.test deleted file mode 100644 index 47a67f6cfa..0000000000 --- a/sample/opt_x.test +++ /dev/null @@ -1,10 +0,0 @@ -test for option `-x' - -this is a forwarding header -this is a header too. - -from here script starts -#! ./ruby -v -print("tt\n") -__END__ -this is a trailer diff --git a/sample/rcs.rb b/sample/rcs.rb index faa4606788..13476267b2 100644 --- a/sample/rcs.rb +++ b/sample/rcs.rb @@ -16,7 +16,7 @@ while gets() s = ""; while xr < hdw x = xr * (1 + y) - y * w / 2 - i = (x / (1 + h) + sw /2) + i = (x / (1 + h) + sw / 2) if (1 < i && i < $_.length); c = $_[i, 1].to_i else diff --git a/sample/ruby-mode.el b/sample/ruby-mode.el index bcbbdc35f3..b555994fea 100644 --- a/sample/ruby-mode.el +++ b/sample/ruby-mode.el @@ -12,21 +12,24 @@ ) (defconst ruby-block-mid-re - "else\\|elsif\\|when\\|resque\\|ensure" + "then\\|else\\|elsif\\|when\\|rescue\\|ensure" ) (defconst ruby-block-end-re "end") (defconst ruby-delimiter - (concat "[$/<(){}#\"'`]\\|\\[\\|\\]\\|\\b\\(" - ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\b") + (concat "[?$/(){}#\"'`]\\|\\[\\|\\]\\|\\<\\(" + ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\>") ) (defconst ruby-negative (concat "^[ \t]*\\(\\b\\(" ruby-block-mid-re "\\)\\|\\(" - ruby-block-end-re "\\)\\b\\|\\}\\|\\]\\)") + ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)") ) +(defconst ruby-operator-chars "[,.+*/%-&|^~=<>:]") +(defconst ruby-symbol-chars "[a-zA-Z0-9_]") + (defvar ruby-mode-abbrev-table nil "Abbrev table in use in ruby-mode buffers.") @@ -53,17 +56,16 @@ (setq ruby-mode-syntax-table (make-syntax-table)) (modify-syntax-entry ?\' "\"" ruby-mode-syntax-table) (modify-syntax-entry ?\" "\"" ruby-mode-syntax-table) -;;(modify-syntax-entry ?\n ">" ruby-mode-syntax-table) -;;(modify-syntax-entry ?\f ">" ruby-mode-syntax-table) (modify-syntax-entry ?# "<" ruby-mode-syntax-table) - (modify-syntax-entry ?$ "/" ruby-mode-syntax-table) + (modify-syntax-entry ?\n ">" ruby-mode-syntax-table) (modify-syntax-entry ?\\ "'" ruby-mode-syntax-table) - (modify-syntax-entry ?_ "w" ruby-mode-syntax-table) + (modify-syntax-entry ?$ "/" ruby-mode-syntax-table) + (modify-syntax-entry ?? "/" ruby-mode-syntax-table) + (modify-syntax-entry ?_ "_" ruby-mode-syntax-table) (modify-syntax-entry ?< "." ruby-mode-syntax-table) (modify-syntax-entry ?> "." ruby-mode-syntax-table) (modify-syntax-entry ?& "." ruby-mode-syntax-table) (modify-syntax-entry ?| "." ruby-mode-syntax-table) - (modify-syntax-entry ?$ "." ruby-mode-syntax-table) (modify-syntax-entry ?% "." ruby-mode-syntax-table) (modify-syntax-entry ?= "." ruby-mode-syntax-table) (modify-syntax-entry ?/ "." ruby-mode-syntax-table) @@ -152,6 +154,19 @@ The variable ruby-indent-level controls the amount of indentation. (indent-to x) (if (> p 0) (forward-char p))))) +(defun ruby-expr-beg () + (save-excursion + (skip-chars-backward " \t") + (or (bolp) (forward-char -1)) + (or (looking-at ruby-operator-chars) + (looking-at "[\\[({]") + (bolp) + (and (looking-at ruby-symbol-chars) + (forward-word -1) + (or + (looking-at ruby-block-beg-re) + (looking-at ruby-block-mid-re)))))) + (defun ruby-parse-region (start end) (let ((indent-point end) (indent 0) @@ -163,113 +178,97 @@ The variable ruby-indent-level controls the amount of indentation. (if start (goto-char start) (ruby-beginning-of-defun)) - (while (and (> indent-point (point)) - (re-search-forward ruby-delimiter indent-point t)) - (let ((w (buffer-substring (match-beginning 0) (match-end 0))) - (pnt (match-beginning 0))) - (cond - ((or (string= "\"" w) ;skip string - (string= "'" w) - (string= "`" w)) - (cond - ((string= w (char-to-string (char-after (point)))) - (forward-char 1)) - ((re-search-forward (format "[^\\]%s" w) indent-point t) + (save-restriction + (narrow-to-region (point) end) + (while (and (> indent-point (point)) + (re-search-forward ruby-delimiter indent-point t)) + (let ((pnt (point)) w) + (goto-char (match-beginning 0)) + (cond + + ((or (looking-at "\"") ;skip string + (looking-at "'") + (looking-at "`")) + (setq w (char-after (point))) + (cond + ((and (not (eobp)) + (equal w (char-after (point))) + (re-search-forward (format "[^\\]%c" w) indent-point t)) nil) - (t - (goto-char indent-point) - (setq in-string t)))) - ((or (string= "/" w) - (string= "<" w)) - (if (string= "<" w) (setq w ">")) - (let (c) - (save-excursion - (goto-char pnt) - (skip-chars-backward " \t") - (setq c (char-after (1- (point)))) - (if c - (setq c (char-syntax c)))) + (t + (goto-char indent-point) + (setq in-string t)))) + ((looking-at "/") + (if (and (ruby-expr-beg) + (goto-char pnt) + (looking-at "\\([^/\n]\\|\\\\/\\)*") + (eq ?/ (char-after (match-end 0)))) + (goto-char (1+ (match-end 0))) + (goto-char indent-point) + (setq in-string t))) + ((looking-at "\\?") ;skip ?char (cond - ((or (eq c ?.) - (and (eq c ?w) - (save-excursion - (forward-word -1) - (or - (looking-at ruby-block-beg-re) - (looking-at ruby-block-mid-re))))) - (if (search-forward w indent-point t) - nil - (goto-char indent-point) - (setq in-string t)))))) - ((string= "$" w) ;skip $char - (forward-char 1)) - ((string= "#" w) ;skip comment - (forward-line 1)) - ((string= "(" w) ;skip to matching paren - (let ((orig depth)) - (setq nest (cons (point) nest)) - (setq depth (1+ depth)) - (while (and (/= depth orig) - (re-search-forward "[()]" indent-point t)) - (cond - ((= (char-after (match-beginning 0)) ?\( ) - (setq nest (cons (point) nest)) - (setq depth (1+ depth))) - (t - (setq nest (cdr nest)) - (setq depth (1- depth))))) - (if (> depth orig) (setq in-paren ?\()))) - ((string= "[" w) ;skip to matching paren - (let ((orig depth)) - (setq nest (cons (point) nest)) - (setq depth (1+ depth)) - (while (and (/= depth orig) - (re-search-forward "\\[\\|\\]" indent-point t)) - (cond - ((= (char-after (match-beginning 0)) ?\[ ) - (setq nest (cons (point) nest)) - (setq depth (1+ depth))) - (t - (setq nest (cdr nest)) - (setq depth (1- depth))))) - (if (> depth orig) (setq in-paren ?\[)))) - ((string= "{" w) ;skip to matching paren - (let ((orig depth)) - (setq nest (cons (point) nest)) + ((ruby-expr-beg) + (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.") + (goto-char (match-end 0))) + (t + (goto-char pnt)))) + ((looking-at "\\$") ;skip $char + (goto-char pnt) + (forward-char 1)) + ((looking-at "#") ;skip comment + (forward-line 1) + (goto-char pnt)) + ((looking-at "[\\[({]") + (setq nest (cons (cons (char-after (point)) pnt) nest)) (setq depth (1+ depth)) - (while (and (/= depth orig) - (re-search-forward "[{}]" indent-point t)) - (cond - ((= (char-after (match-beginning 0)) ?{ ) - (setq nest (cons (point) nest)) - (setq depth (1+ depth))) - (t - (setq nest (cdr nest)) - (setq depth (1- depth))))) - (if (> depth orig) (setq in-paren ?{)))) - ((string-match ruby-block-end-re w) - (setq nest (cdr nest)) - (setq depth (1- depth))) - ((string-match ruby-block-beg-re w) - (let (c) - (save-excursion - (goto-char pnt) - (skip-chars-backward " \t") - (setq c (char-after (1- (point))))) - (if (or (null c) (= c ?\n) (= c ?\;)) - (progn - (setq nest (cons (point) nest)) - (setq depth (1+ depth)))))) - (t - (error (format "bad string %s" w))))))) - (list in-string in-paren (car nest) depth))) + (goto-char pnt)) + ((looking-at "[])}]") + (setq nest (cdr nest)) + (setq depth (1- depth)) + (goto-char pnt)) + ((looking-at ruby-block-end-re) + (if (and (not (bolp)) + (progn + (forward-char -1) + (eq ?_ (char-after (point)))) + (progn + (goto-char pnt) + (eq ?_ (char-after (point))))) + nil + (setq nest (cdr nest)) + (setq depth (1- depth))) + (goto-char pnt)) + ((looking-at ruby-block-beg-re) + (and + (or (bolp) + (progn + (forward-char -1) + (not (eq ?_ (char-after (point)))))) + (save-excursion + (goto-char pnt) + (not (eq ?_ (char-after (point))))) + (skip-chars-backward " \t") + (or (bolp) + (save-excursion + (forward-char -1) + (looking-at ruby-operator-chars))) + (progn + (setq nest (cons (cons nil pnt) nest)) + (setq depth (1+ depth)))) + (goto-char pnt)) + (t + (error (format "bad string %s" + (buffer-substring (point) pnt) + ))))))) + (list in-string (car nest) depth)))) (defun ruby-calculate-indent (&optional parse-start) (save-excursion (beginning-of-line) (let ((indent-point (point)) (case-fold-search nil) - state eol + state bol eol (indent 0)) (if parse-start (goto-char parse-start) @@ -281,25 +280,74 @@ The variable ruby-indent-level controls the amount of indentation. (setq indent nil)) ; do nothing ((nth 1 state) ; in paren - (goto-char (nth 2 state)) + (goto-char (cdr (nth 1 state))) (setq indent - (if (and (eq (nth 1 state) ?\( ) (not (looking-at "$"))) + (if (and (eq (car (nth 1 state)) ?\( ) + (not (looking-at "(\\s *$"))) (current-column) (+ (current-indentation) ruby-indent-level)))) - ((> (nth 3 state) 0) ; in nest - (goto-char (nth 2 state)) + ((> (nth 2 state) 0) ; in nest + (goto-char (cdr (nth 1 state))) (forward-word -1) ; skip back a keyword (setq indent (+ (current-column) ruby-indent-level))) (t ; toplevel (setq indent 0))) - (goto-char indent-point) - (end-of-line) - (setq eol (point)) - (beginning-of-line) - (if (re-search-forward ruby-negative eol t) + + (cond + (indent + (goto-char indent-point) + (end-of-line) + (setq eol (point)) + (beginning-of-line) + (cond + ((re-search-forward ruby-negative eol t) (setq indent (- indent ruby-indent-level))) + ;;operator terminated lines + ((and + (save-excursion + (beginning-of-line) + (not (bobp))) + (or (null (car (nth 1 state))) ;not in parens + (and (eq (car (nth 1 state)) ?\{) + (save-excursion ;except non-block braces + (goto-char (cdr (nth 1 state))) + (or (bobp) (forward-char -1)) + (not (ruby-expr-beg)))))) + (beginning-of-line) + (skip-chars-backward " \t\n") + (beginning-of-line) ; goto beginning of non-empty line + (setq bol (point)) + (end-of-line) + (setq eol (point)) + (and (search-backward "#" bol t) ; check for comment line + (not (eq ?? (char-after (1- (point))))) + (not (nth 0 (ruby-parse-region parse-start (point)))) + (setq eol (point))) + (goto-char eol) + (skip-chars-backward " \t") + (or (bobp) (forward-char -1)) + (and (looking-at ruby-operator-chars) +;; (or (not (eq ?/ (char-after (point)))) +;; (progn +;; (not (nth 0 (ruby-parse-region parse-start (point)))))) + (or (not (eq ?/ (char-after (point)))) + (null (nth 0 (ruby-parse-region parse-start (point))))) + (save-excursion + (goto-char parse-start) + (sit-for 1)) + (not (eq (char-after (1- (point))) ?$)) + (or (not (eq ?| (char-after (point)))) + (save-excursion + (or (eolp) (forward-char -1)) + (and (search-backward "|" bol t) + (skip-chars-backward " \t\n") + (and (not (eolp)) + (progn + (forward-char -1) + (not (looking-at "\\{"))))))) + (setq indent (+ indent ruby-indent-level))))))) indent))) (defun ruby-electric-brace (arg) @@ -329,7 +377,7 @@ An end of a defun is found by moving forward from the beginning of one." (interactive "*") (save-excursion (delete-region (point) (progn (skip-chars-backward " \t") (point)))) - (insert ?\n) + (newline) (save-excursion (forward-line -1) (indent-according-to-mode)) @@ -348,3 +396,26 @@ An end of a defun is found by moving forward from the beginning of one." (goto-char beg) (while (re-search-forward "^\\([ \t]*\\)#" end t) (replace-match "\\1" nil nil)))) + +(if (featurep 'hilit19) + (hilit-set-mode-patterns + 'ruby-mode + '(("\\s #.*$" nil comment) + ("^#.*$" nil comment) + ("\\$\\(.\\|\\sw+\\)" nil type) + ("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string) + ("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string) + ("^/\\([^/\n]\\|\\\\/\\)*/" nil string) + ("[^a-zA-Z_]\\s *\\(/\\([^/\n]\\|\\\\/\\)*/\\)" 1 string) + ("\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|rescue\\|then\\|when\\|while\\)\\s *\\(/\\([^/\n]\\|\\\\/\\)*/\\)" 2 string) + ("^\\s *require.*$" nil include) + ("^\\s *load.*$" nil include) + ("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl) + ("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun) + ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|rescue\\|then\\|when\\|while\\)\\>[^_]" 1 defun) + ("[^_]\\<\\(and\\|break\\|continue\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\)\\>[^_]" 1 keyword) + ("[^_]\\<\\(self\\|nil\\|TRUE\\|FALSE\\|__LINE__\\|__FILE__\\)\\>[^_]" 1 define) + ("$.[a-zA-Z_0-9]*" nil struct) + ("@[a-zA-Z_0-9]+" nil struct) + ("[^_]\\<[A-Z].[a-zA-Z_0-9]*" nil define) + ("^__END__" nil label)))) diff --git a/sample/samp.rb b/sample/samp.rb deleted file mode 100644 index 4052a308c1..0000000000 --- a/sample/samp.rb +++ /dev/null @@ -1,15 +0,0 @@ -# Sp܂ރXNvg -# g: samp.rb file.. - -P = 0 -while gets() - printf("%3d: %s", $., $_) - while sub(/\w+/, '') - if $& != ""; - P += 1 - end - end - if ($. >= 10); break; end -end -printf("line: %d\n", $.) -printf("word: %d\n", P) diff --git a/sample/sieve.rb b/sample/sieve.rb index 640cc32b08..a953784284 100644 --- a/sample/sieve.rb +++ b/sample/sieve.rb @@ -12,7 +12,7 @@ for i in 2 .. max print ", " print i sieve.push(i) - resque + rescue end end print "\n" diff --git a/sample/split.rb b/sample/split.rb deleted file mode 100644 index 2b6f3921ce..0000000000 --- a/sample/split.rb +++ /dev/null @@ -1,13 +0,0 @@ -# split test -print("1 byte string", "\n") -print("1 byte string".reverse, "\n") - -print("ʸ", "\n") -print("ʸ".reverse, "\n") - -print("1 byte string", "\n") -print("1 byte string".split(//).reverse.join(":"), "\n") -print("ʸ", "\n") -print("ʸ".split(//).reverse.join(":"), "\n") -print("Ѥ1byteκ", "\n") -print("Ѥ1byteκ".split(//).reverse.join(":"), "\n") diff --git a/sample/struct.rb b/sample/struct.rb deleted file mode 100644 index 322764d02f..0000000000 --- a/sample/struct.rb +++ /dev/null @@ -1,8 +0,0 @@ -#output: -# struct test -# 1 - -foo = Struct.new("test", "a1"::1, "a2"::2) -print(foo, "\n") -bar = foo.clone -print(bar.a1, "\n") diff --git a/sample/svr.rb b/sample/svr.rb index 23b2bf71f6..460c16bedf 100644 --- a/sample/svr.rb +++ b/sample/svr.rb @@ -1,6 +1,8 @@ # socket example - server side # usage: ruby svr.rb +require "socket" + gs = TCPserver.open(0) addr = gs.addr addr.shift diff --git a/sample/system.rb b/sample/system.rb deleted file mode 100644 index 02f3782b39..0000000000 --- a/sample/system.rb +++ /dev/null @@ -1,2 +0,0 @@ -# command string -print(`echo foobar`) diff --git a/sample/t1.rb b/sample/t1.rb deleted file mode 100644 index 701a1cd389..0000000000 --- a/sample/t1.rb +++ /dev/null @@ -1,20 +0,0 @@ -def test(a1, *a2) - while 1 - case gets() - when nil - break - when /^-$/ - print("-\n") - return - when /^-help/ - print("-help\n") - break - end - end - print(a1, a2, "\n") -end - -print($ARGV, "\n") -print("in: ") -test(1) -print("end\n") diff --git a/sample/t2.rb b/sample/t2.rb deleted file mode 100644 index 2e3741e8f1..0000000000 --- a/sample/t2.rb +++ /dev/null @@ -1,23 +0,0 @@ -#print("in Print\n") -def t2() end - -def println(*args) - for a in args - t2() - print(a) - end - print("\n") -end - -def tt - for i in 1..10 - println("i:", i); - yield(i); - end -end - -test = tt{|i| - if i == 3; break end - println("ttt: ", i); -} -#exit() diff --git a/sample/test.rb b/sample/test.rb index 9c422cc94a..7f26433181 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -1,5 +1,1040 @@ -index = 1 -for argument in $ARGV - printf("%d:%s\n", index, argument) - index = index + 1 +#! /usr/local/bin/ruby + +$testnum=0 + +def check(what) + printf "%s\n", what + $what = what + $testnum = 0 end + +def ok + $testnum+=1 + printf "ok %d\n", $testnum +end + +def notok + $testnum+=1 + printf "not ok %s %d\n", $what, $testnum + $failed = TRUE +end + +# make sure conditional operators work + +check "condition" + +$x = '0'; + +$x == $x && ok +$x != $x && notok +$x == $x || notok +$x != $x || ok + +# first test to see if we can run the tests. + +check "if"; + +$x = 'test'; +if $x == $x then ok else notok end +if $x != $x then notok else ok end + +check "case" + +case 5 +when 1, 2, 3, 4, 6, 7, 8 + notok +when 5 + ok +end + +case 5 +when 5 + ok +when 1..10 + notok +end + +case 5 +when 5 + ok +else + notok +end + +case "foobar" +when /^f.*r$/ + ok +else + notok +end + +check "while"; + +tmp = open("while_tmp", "w") +tmp.print "tvi925\n"; +tmp.print "tvi920\n"; +tmp.print "vt100\n"; +tmp.print "Amiga\n"; +tmp.print "paper\n"; +tmp.close + +# test break + +tmp = open("while_tmp", "r") + +while tmp.gets() + break if /vt100/ +end + +if !tmp.eof && /vt100/ then + ok +else + notok +end +tmp.close + +# test continue +$bad = FALSE +tmp = open("while_tmp", "r") +while tmp.gets() + continue if /vt100/; + $bad = 1 if /vt100/; +end +if !tmp.eof || /vt100/ || $bad + notok +else + ok +end +tmp.close + +# test redo +$bad = FALSE +tmp = open("while_tmp", "r") +while tmp.gets() + if gsub!('vt100', 'VT100') + gsub!('VT100', 'Vt100') + redo; + end + $bad = 1 if /vt100/; + $bad = 1 if /VT100/; +end +if !tmp.eof || $bad + notok +else + ok +end +tmp.close + +# test interval +$bad = FALSE +tmp = open("while_tmp", "r") +while tmp.gets() + break if not 1..2 + if /vt100/ || /Amiga/ || /paper/ + $bad = TRUE + notok + break + end +end +ok if not $bad +tmp.close + +File.unlink "while_tmp" or `/bin/rm -f "while_tmp"` + +# exception handling +check "exception"; + +begin + fail "this must be handled" + notok +rescue + ok +end + +$bad = TRUE +begin + fail "this must be handled no.2" +rescue + if $bad + $bad = FALSE + retry + notok + end +end +ok + +$bad = TRUE +$string = "this must be handled no.3" +begin + fail $string +rescue +ensure + $bad = FALSE + ok +end +notok if $bad || $! != $string + +# exception in rescue clause +begin + begin + fail "this must be handled no.4" + rescue + fail "exception in rescue clause" + end + notok +rescue + ok +end + +check "array" +$x = [0, 1, 2, 3, 4, 5] +if $x[2] == 2 + ok +else + notok +end + +if $x[1..3] == [1, 2, 3] + ok +else + notok +end + +if $x[1,3] == [1, 2, 3] + ok +else + notok +end + +if [1, 2] + [3, 4] == [1, 2, 3, 4] + ok +else + notok +end + +$x[0, 2] = 10 +if $x[0] == 10 && $x[1] == 2 + ok +else + notok +end + +$x[0, 0] = -1 +if $x[0] == -1 && $x[1] == 10 + ok +else + notok +end + +$x[-1, 1] = 20 +if $x[-1] == 20 && $x.pop == 20 + ok +else + notok +end + +$x = ["it", "came", "to", "pass", "that", "..."] +$x = $x.sort.join(" ") +if $x == "... came it pass that to" + ok +else + notok +end + +# split test +if "1 byte string".split(//).reverse.join(":") == "g:n:i:r:t:s: :e:t:y:b: :1" + ok +else + notok +end + +$x = [1] +if ($x * 5).join(":") == '1:1:1:1:1' then ok else notok end +if ($x * 1).join(":") == '1' then ok else notok end +if ($x * 0).join(":") == '' then ok else notok end + +check "hash" +$x = {1=>2, 2=>4, 3=>6} +$y = {1, 2, 2, 4, 3, 6} + +if $x[1] == 2 + ok +else + notok +end + +begin + for k,v in $y + fail if k*2 != v + end + ok +rescue + notok +end + +if $x.length == 3 + ok +else + notok +end + +if $x.has_key?(1) + ok +else + notok +end + +if $x.has_value?(4) + ok +else + notok +end + +if $x.indexes(2,3) == [4,6] + ok +else + notok +end + +$z = $y.keys.join(":") +if $z == "1:2:3" + ok +else + notok +end + +$z = $y.values.join(":") +if $z == "2:4:6" + ok +else + notok +end + +if $x == $y + ok +else + notok +end + +$y.shift +if $y.length == 2 + ok +else + notok +end + +check "iterator" + +if iterator? then notok else ok end + +def ttt + if iterator? then ok else notok end +end +ttt{} + +# yield at top level +begin + yield + notok +rescue + ok +end + +$x = [1, 2, 3, 4] +$y = [] + +# iterator over array +for i in $x + $y.push i +end +if $x == $y + ok +else + notok +end + +# nested iterator +def tt + 1.upto(10) {|i| + yield i + } +end + +tt{|i| break if i == 5} +if i == 5 + ok +else + notok +end + +# iterator break/redo/continue/retry +done = TRUE +loop{ + break + done = FALSE + notok +} +ok if done + +done = TRUE +$bad = FALSE +loop { + break if not done + done = FALSE + continue + $bad = TRUE +} +if $bad + notok +else + ok +end + +done = TRUE +$bad = FALSE +loop { + break if not done + done = FALSE + redo + $bad = TRUE +} +if $bad + notok +else + ok +end + +$x = [] +for i in 1 .. 7 + $x.push(i) +end +if $x.size == 7 + ok +else + notok +end +# $x == [1, 2, 3, 4, 5, 6, 7] +$done = FALSE +$x = [] +for i in 1 .. 7 # see how retry works in iterator loop + if i == 4 and not $done + $done = TRUE + retry + end + $x.push(i) +end +# $x == [1, 2, 3, 1, 2, 3, 4, 5, 6, 7] +if $x.size == 10 + ok +else + notok +end + +check "bignum" +def fact(n) + return 1 if n == 0 + return n*fact(n-1) +end +if fact(40) == 815915283247897734345611269596115894272000000000 + ok +else + notok +end +if fact(40) == 815915283247897734345611269596115894272000000001 + notok +else + ok +end + +check "string & char" + +if "abcd" == "abcd" + ok +else + notok +end + +if "abcd" =~ "abcd" + ok +else + notok +end + +$foo = "abc" +if "#$foo = abc" == "abc = abc" + ok +else + notok +end + +if "#{$foo} = abc" == "abc = abc" + ok +else + notok +end + +foo = "abc" +if "#{foo} = abc" == "abc = abc" + ok +else + notok +end + +if '-' * 5 == '-----' then ok else notok end +if '-' * 1 == '-' then ok else notok end +if '-' * 0 == '' then ok else notok end + +foo = '-' +if foo * 5 == '-----' then ok else notok end +if foo * 1 == '-' then ok else notok end +if foo * 0 == '' then ok else notok end + +# character constants(assumes ASCII) +if "a"[0] == ?a + ok +else + notok +end + +if ?a == ?a + ok +else + notok +end + +if ?\C-a == 1 + ok +else + notok +end + +if ?\M-a == 225 + ok +else + notok +end + +if ?\M-\C-a == 129 + ok +else + notok +end + +$x = "abcdef" +$y = [ ?a, ?b, ?c, ?d, ?e, ?f ] +$bad = FALSE +$x.each_byte {|i| + if i != $y.shift + $bad = TRUE + break + end +} +if not $bad + ok +else + notok +end + +check "asignment" +a = nil +if a == nil + ok +else + notok +end + +a, b = 1, 2 +if a == 1 and b == 2 then + ok +else + notok +end + +a, *b = 1, 2, 3 +if a == 1 and b == [2, 3] then + ok +else + notok +end + +check "call" +def aaa(a, b=100, *rest) + res = [a, b] + res += rest if rest + return res +end + +begin + aaa() + notok +rescue + ok +end + +begin + aaa + notok +rescue + ok +end + +begin + if aaa(1) == [1, 100] + ok + else + fail + end +rescue + notok +end + +begin + if aaa(1, 2) == [1, 2] + ok + else + fail + end +rescue + notok +end + +begin + if aaa(1, 2, 3, 4) == [1, 2, 3, 4] + ok + else + fail + end +rescue + notok +end + +begin + if aaa(1, *[2, 3, 4]) == [1, 2, 3, 4] + ok + else + fail + end +rescue + notok +end + +check "proc" +$proc = proc{|i| i} +if $proc.call(2) == 2 + ok +else + notok +end + +$proc = proc{|i| i*2} +if $proc.call(2) == 4 + ok +else + notok +end + +proc{ + iii=5 # dynamic local variable + $proc = proc{ |i| + iii = i + } + $proc2 = proc { + $x = iii # dynamic variables shared by procs + } + if defined?(iii) # dynamic variables' scope + ok + else + notok + end +}.call +if defined?(iii) # out of scope + notok +else + ok +end +$x=0 +$proc.call(5) +$proc2.call +if $x == 5 + ok +else + notok +end + +check "signal" +begin + kill "SIGINT", $$ + sleep 1 + notok +rescue + ok +end + +$x = 0 +trap "SIGINT", proc{|sig| $x = sig;fail} +begin + kill "SIGINT", $$ + sleep 1 + notok +rescue + if $x == 2 + ok + else + notok + end +end + +$x = FALSE +trap "SIGINT", "$x = TRUE;fail" +begin + kill "SIGINT", $$ + sleep 1 + notok +rescue + if $x + ok + else + notok + end +end + +check "eval" +$bad=FALSE +eval 'while FALSE; $bad = TRUE; print "foo\n" end +if not $bad then ok else notok end' + +$foo = 'ok' +begin + eval $foo +rescue + notok +end + +check "system" +if `echo foobar` == "foobar\n" + ok +else + notok +end + +if `./ruby -e 'print "foobar"'` == 'foobar' + ok +else + notok +end + +tmp = open("script_tmp", "w") +tmp.print "print $zzz\n"; +tmp.close + +if `./ruby -s script_tmp -zzz` == 't' + ok +else + notok +end + +if `./ruby -s script_tmp -zzz=555` == '555' + ok +else + notok +end + +tmp = open("script_tmp", "w") +tmp.print "#! /usr/local/bin/ruby -s\n"; +tmp.print "print $zzz\n"; +tmp.close + +if `./ruby script_tmp -zzz=678` == '678' + ok +else + notok +end + +tmp = open("script_tmp", "w") +tmp.print "this is a leading junk\n"; +tmp.print "#! /usr/local/bin/ruby -s\n"; +tmp.print "print $zzz\n"; +tmp.print "__END__\n"; +tmp.print "this is a trailing junk\n"; +tmp.close + +if `./ruby -x script_tmp` == 'nil' + ok +else + notok +end + +if `./ruby -x script_tmp -zzz=555` == '555' + ok +else + notok +end + +tmp = open("script_tmp", "w") +for i in 1..5 + tmp.print i, "\n" +end +tmp.close + +`./ruby -i.bak -pe 'sub(/^[0-9]+$/){$&.to_i * 5}' script_tmp` +done = TRUE +tmp = open("script_tmp", "r") +while tmp.gets + if $_.to_i % 5 != 0 + done = FALSE + notok + break + end +end +ok if done + +File.unlink "script_tmp" or `/bin/rm -f "script_tmp"` +File.unlink "script_tmp.bak" or `/bin/rm -f "script_tmp.bak"` + +check "const" +TEST1 = 1 +TEST2 = 2 + +module Const + TEST3 = 3 + TEST4 = 4 +end + +module Const2 + TEST3 = 6 + TEST4 = 8 +end + +include Const + +if [TEST1,TEST2,TEST3,TEST4] == [1,2,3,4] + ok +else + notok +end + +include Const2 + +if [TEST1,TEST2,TEST3,TEST4] == [1,2,6,8] + ok +else + notok +end + +check "clone" +foo = Object.new +def foo.test + "test" +end +bar = foo.clone +def bar.test2 + "test2" +end + +if bar.test2 == "test2" + ok +else + notok +end + +if bar.test == "test" + ok +else + notok +end + +if foo.test == "test" + ok +else + notok +end + +begin + foo.test2 + notok +rescue + ok +end + +check "pack" + +$format = "c2x5CCxsdila6"; +# Need the expression in here to force ary[5] to be numeric. This avoids +# test2 failing because ary2 goes str->numeric->str and ary doesn't. +ary = [1,-100,127,128,32767,987.654321098 / 100.0,12345,123456,"abcdef"] +$x = ary.pack($format) +ary2 = $x.unpack($format) + +if ary.length == ary2.length then ok else notok end + +if ary.join(':') == ary2.join(':') then ok else notok end + +if $x =~ /def/ then ok else notok end + +check "math" +if Math.sqrt(4) == 2 + ok +else + notok +end + +include Math +if sqrt(4) == 2 + ok +else + notok +end + +check "struct" +struct_test = Struct.new("Test", :foo, :bar) +if struct_test == Struct::Test + ok +else + notok +end +test = struct_test.new(1, 2) +if test.foo == 1 && test.bar == 2 + ok +else + notok +end +if test[0] == 1 && test[1] == 2 + ok +else + notok +end +a, b = test +if a == 1 && b == 2 + ok +else + notok +end +test[0] = 22 +if test.foo == 22 + ok +else + notok +end +test.bar = 47 +if test.bar == 47 + ok +else + notok +end + +check "variable" +if $$.is_instance_of? Fixnum + ok +else + notok +end + +begin + $$ = 5 + notok +rescue + ok +end + +foobar = "foobar" +$_ = foobar +if $_ == foobar + ok +else + notok +end + +check "trace" +$x = 1234 +$y = 0 +trace_var :$x, proc{$y = $x} +$x = 40414 +if $y == $x + ok +else + notok +end + +untrace_var :$x +$x = 19660208 +if $y != $x + ok +else + notok +end + +trace_var :$x, proc{$x *= 2} +$x = 5 +if $x == 10 + ok +else + notok +end +untrace_var :$x + +check "defined?" +if defined? $x + ok +else + notok +end + +foo=5 +if defined? foo + ok +else + notok +end + +if defined? Array + ok +else + notok +end + +if defined? Object.new + ok +else + notok +end + +if defined? 1 == 2 + ok +else + notok +end + +if defined? fail + ok +else + notok +end + +def defined_test + return defined?(yield) +end + +if defined_test + notok +else + ok +end + +if defined_test{} + ok +else + notok +end + +check "gc" +begin + 1.upto(10000) { + tmp = [0,1,2,3,4,5,6,7,8,9] + } + tmp = nil + ok +rescue + notok +end + +print "end of test\n" if not $failed diff --git a/sample/tkbiff.rb b/sample/tkbiff.rb new file mode 100644 index 0000000000..9b406010cb --- /dev/null +++ b/sample/tkbiff.rb @@ -0,0 +1,121 @@ +#! /usr/local/bin/ruby + +if $ARGV.length == 0 + if ENV['MAIL'] + $spool = ENV['MAIL'] + else + $spool = '/usr/spool/mail/' + ENV['USER'] + end +else + $spool = $ARGV[0] +end + +exit if fork + +require "parsedate" +require "base64" + +include ParseDate + +class Mail + def Mail.new(f) + if !f.is_kind_of?(IO) + f = open(f, "r") + me = super + f.close + else + me = super + end + return me + end + + def initialize(f) + @header = {} + @body = [] + while f.gets() + $_.chop! + continue if /^From / # skip From-line + break if /^$/ # end of header + if /^(\S+):\s*(.*)/ + @header[attr = $1.capitalize] = $2 + elsif attr + sub(/^\s*/, '') + @header[attr] += "\n" + $_ + end + end + + return if ! $_ + + while f.gets() + break if /^From / + @body.push($_) + end + end + + def header + return @header + end + + def body + return @body + end + +end + +require "tkscrollbox" + +$top = TkRoot.new +$top.withdraw +$list = TkScrollbox.new($top) { + relief 'raised' + width 80 + height 8 + setgrid 'yes' + pack +} +TkButton.new($top) { + text 'Dismiss' + command proc {$top.withdraw} + pack('fill'=>'both','expand'=>'yes') +} +$top.bind "Control-c", proc{exit} +$top.bind "Control-q", proc{exit} +$top.bind "space", proc{exit} + +$spool_size = 0 +def check + size = File.size($spool) + if size and size != $spool_size + pop_up if size > 0 + end + Tk.after 5000, proc{check} +end + +def pop_up + outcount = 0; + $spool_size = File.size($spool) + $list.delete 0, 'end' + f = open($spool, "r") + while !f.eof + mail = Mail.new(f) + date, from, subj = mail.header['Date'], mail.header['From'], mail.header['Subject'] + continue if !date + y = m = d = 0 + y, m, d = parsedate(date) if date + from = "sombody@somewhere" if ! from + subj = "(nil)" if ! subj + from = decode_b(from) + subj = decode_b(subj) + $list.insert 'end', format('%-02d/%02d/%02d [%-28.28s] %s',y,m,d,from,subj) + outcount += 1 + end + f.close + if outcount == 0 + $list.insert 'end', "You have no mail." + end + $top.deiconify + Tk.after 2000, proc{$top.withdraw} +end + +check +Tk.mainloop diff --git a/sample/tkbrowse.rb b/sample/tkbrowse.rb new file mode 100644 index 0000000000..dbaa132d1f --- /dev/null +++ b/sample/tkbrowse.rb @@ -0,0 +1,69 @@ +#!/usr/local/bin/ruby +# +# This script generates a directory browser, which lists the working +# directory and allows you to open files or subdirectories by +# double-clicking. + +# Create a scrollbar on the right side of the main window and a listbox +# on the left side. + +require "tkscrollbox" + +list = TkScrollbox.new { + relief 'raised' + width 20 + height 20 + setgrid 'yes' + pack +} + +# The procedure below is invoked to open a browser on a given file; if the +# file is a directory then another instance of this program is invoked; if +# the file is a regular file then the Mx editor is invoked to display +# the file. + +def browse (dir, file) + if dir != "." + file="#{dir}/#{file}" + if File.isdirectory? file + system "browse #{file} &" + else + if File.isfile? file + if ENV['EDITOR'] + system format("%s %s&", ENV['EDITOR'], file) + else + sysmte "xedit #{file}&" + end + else + STDERR.print "\"#{file}\" isn't a directory or regular file" + end + end + end +end + +# Fill the listbox with a list of all the files in the directory (run +# the "ls" command to get that information). + +if $ARGV.length>0 + dir = $ARGV[0] +else + dir="." +end +list.insert 'end', *`ls #{dir}`.split + +# Set up bindings for the browser. + +list.focus +list.bind "Control-q", proc{exit} +list.bind "Control-c", proc{exit} +list.bind "Control-p", proc{ + print "selection <", TkSelection.get, ">\n" +} + +list.bind "Double-Button-1", proc{ + for i in TkSelection.get.split + print "clicked ", i, "\n" + browse dir, i + end +} +Tk.mainloop diff --git a/sample/tkdialog.rb b/sample/tkdialog.rb new file mode 100644 index 0000000000..e83e16d0a8 --- /dev/null +++ b/sample/tkdialog.rb @@ -0,0 +1,62 @@ +#! /usr/local/bin/ruby +require "tk" + +root = TkFrame.new +top = TkFrame.new(root) { + relief 'raised' + border 1 +} +msg = TkMessage.new(top) { + text "File main.c hasn't been saved to disk since \ +it was last modified. What should I do?" + justify 'center' + aspect 200 + font '-Adobe-helvetica-medium-r-normal--*-240*' + pack('padx'=>5, 'pady'=>5, 'expand'=>'yes') +} +top.pack('fill'=>'both') +root.pack + +bot = TkFrame.new(root) { + relief 'raised' + border 1 +} + +TkFrame.new(bot) { |left| + relief 'sunken' + border 1 + pack('side'=>'left', 'expand'=>'yes', 'padx'=>10, 'pady'=> 10) + TkButton.new(left) { + text "Save File" + command "quit 'save'" + pack('expand'=>'yes','padx'=>6,'pady'=> 6) + top.bind "Enter", proc{state 'active'} + msg.bind "Enter", proc{state 'active'} + bot.bind "Enter", proc{state 'active'} + top.bind "Leave", proc{state 'normal'} + msg.bind "Leave", proc{state 'normal'} + bot.bind "Leave", proc{state 'normal'} + Tk.root.bind "ButtonRelease-1", proc{quit 'save'} + Tk.root.bind "Return", proc{quit 'save'} + } +} +TkButton.new(bot) { + text "Quit Anyway" + command "quit 'quit'" + pack('side'=>'left', 'expand'=>'yes', 'padx'=>10) +} +TkButton.new(bot) { + text "Return To Editor" + command "quit 'return'" + pack('side'=>'left', 'expand'=>'yes', 'padx'=>10) +} +bot.pack +root.pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes') + +def quit(button) + print "aaa\n" + print "You pressed the \"#{button}\" button; bye-bye!\n" + exit +end + +Tk.mainloop diff --git a/sample/tkfrom.rb b/sample/tkfrom.rb new file mode 100644 index 0000000000..4a0d8c2b5d --- /dev/null +++ b/sample/tkfrom.rb @@ -0,0 +1,115 @@ +#! /usr/local/bin/ruby + +require "parsedate" +require "base64" + +include ParseDate + +class Mail + def Mail.new(f) + if !f.is_kind_of?(IO) + f = open(f, "r") + me = super + f.close + else + me = super + end + return me + end + + def initialize(f) + @header = {} + @body = [] + while f.gets() + $_.chop! + continue if /^From / # skip From-line + break if /^$/ # end of header + if /^(\S+):\s*(.*)/ + @header[attr = $1.capitalize] = $2 + elsif attr + sub(/^\s*/, '') + @header[attr] += "\n" + $_ + end + end + + return if ! $_ + + while f.gets() + break if /^From / + @body.push($_) + end + end + + def header + return @header + end + + def body + return @body + end + +end + +$ARGV[0] = '/usr/spool/mail/' + ENV['USER'] if $ARGV.length == 0 + +require "tk" +list = scroll = nil +TkFrame.new{|f| + list = TkListbox.new(f) { + yscroll proc{|idx| + scroll.set *idx + } + relief 'raised' +# geometry "80x5" + width 80 + height 5 + setgrid 'yes' + pack('side'=>'left','fill'=>'both','expand'=>'yes') + } + scroll = TkScrollbar.new(f) { + command proc{|idx| + list.yview *idx + } + pack('side'=>'right','fill'=>'y') + } + pack +} +root = Tk.root +TkButton.new(root) { + text 'Dismiss' + command proc {exit} + pack('fill'=>'both','expand'=>'yes') +} +root.bind "Control-c", proc{exit} +root.bind "Control-q", proc{exit} +root.bind "space", proc{exit} + +$outcount = 0; +for file in $ARGV + continue if !File.exists?(file) + f = open(file, "r") + while !f.eof + mail = Mail.new(f) + date, from, subj = mail.header['Date'], mail.header['From'], mail.header['Subject'] + continue if !date + y = m = d = 0 + y, m, d = parsedate(date) if date + from = "sombody@somewhere" if ! from + subj = "(nil)" if ! subj + from = decode_b(from) + subj = decode_b(subj) + list.insert 'end', format('%-02d/%02d/%02d [%-28.28s] %s',y,m,d,from,subj) + $outcount += 1 + end + f.close +end + +limit = 10000 +if $outcount == 0 + list.insert 'end', "You have no mail." + limit = 2000 +end +Tk.after limit, proc{ + exit +} +Tk.mainloop diff --git a/sample/tkhello.rb b/sample/tkhello.rb new file mode 100644 index 0000000000..1ff1403e71 --- /dev/null +++ b/sample/tkhello.rb @@ -0,0 +1,13 @@ +require "tk" + +TkButton.new { + text 'hello' + command proc{print "hello\n"} + pack('fill'=>'x') +} +TkButton.new { + text 'quit' + command 'exit' + pack('fill'=>'x') +} +Tk.mainloop diff --git a/sample/tkline.rb b/sample/tkline.rb new file mode 100644 index 0000000000..843893b5d9 --- /dev/null +++ b/sample/tkline.rb @@ -0,0 +1,29 @@ +require "tkclass" + +$c = Canvas.new +$c.pack +$start_x = start_y = 0 + +def do_press(x, y) + $start_x = x + $start_y = y + $current_line = Line.new($c, x, y, x, y, 'fill' => 'gray') +end +def do_motion(x, y) + if $current_line + $current_line.coords $start_x, $start_y, x, y + end +end + +def do_release(x, y) + if $current_line + $current_line.coords $start_x, $start_y, x, y + $current_line.fill 'black' + $current_line = nil + end +end + +$c.bind("1", proc{|e| do_press e.x,e.y}) +$c.bind("B1-Motion", proc{|e| do_motion e.x,e.y}) +$c.bind("ButtonRelease-1", proc{|e| do_release e.x,e.y}) +Tk.mainloop diff --git a/sample/tktimer.rb b/sample/tktimer.rb new file mode 100644 index 0000000000..b8b3617646 --- /dev/null +++ b/sample/tktimer.rb @@ -0,0 +1,49 @@ +#!/usr/local/bin/ruby +# This script generates a counter with start and stop buttons. + +require "tk" +$label = TkLabel.new { + text '0.00' + relief 'raised' + width 10 + pack('side'=>'bottom', 'fill'=>'both') +} + +TkButton.new { + text 'Start' + command proc { + if $stopped + $stopped = FALSE + tick + end + } + pack('side'=>'left','fill'=>'both','expand'=>'yes') +} +TkButton.new { + text 'Stop' + command proc{ + $stopped = TRUE + } + pack('side'=>'right','fill'=>'both','expand'=>'yes') +} + +$seconds=0 +$hundredths=0 +$stopped=TRUE + +def tick + if $stopped then return end + Tk.after 50, proc{tick} + $hundredths+=5 + if $hundredths >= 100 + $hundredths=0 + $seconds+=1 + end + $label.text format("%d.%02d", $seconds, $hundredths) +end + +root = Tk.root +root.bind "Control-c", proc{root.destroy} +root.bind "Control-q", proc{root.destroy} +Tk.root.focus +Tk.mainloop diff --git a/sample/trap.pl b/sample/trap.pl deleted file mode 100644 index ce022d4062..0000000000 --- a/sample/trap.pl +++ /dev/null @@ -1,6 +0,0 @@ -$SIG{'INT'} = 'test'; - -while (<>) { - print; -} -sub test { print "C-c handled\n"; } diff --git a/sample/trap.rb b/sample/trap.rb deleted file mode 100644 index e552a0fddc..0000000000 --- a/sample/trap.rb +++ /dev/null @@ -1,3 +0,0 @@ -trap('print("C-c handled\n")', 'INT', 'HUP') -print("---\n") -while gets(); print($_) end diff --git a/sample/tt.rb b/sample/tt.rb deleted file mode 100644 index f4960feaea..0000000000 --- a/sample/tt.rb +++ /dev/null @@ -1,100 +0,0 @@ -module Print - print("in Print\n") - def println(*args) - for a in args - print(a) - end - print("\n") - end - - def println2(*args) - print(*args) - print("\n") - end -end - -module Print2 - def println(*args) - print("pr2: "); - super - end -end - -module Print3 - include Print2 - def println(*args) - print("pr3: "); - super - end -end - -include Print, Print2, Print3 - -println2("in TopLevel") - -print("a: ", $OPT_test, "\n") -printf("%10.5g: %*s -> 0x%x\n", 123345, -10, Print, Print.id); - -println("a+ matches aaa at ", "bccAAaaa" =~ /a+/) -ttt = "this is a " -if offset = (ttt =~ /this ([^ ]*) (.*)/) - println("0 = ", $&); - println("1 = ", $1); - println("2 = ", $2); -end - -class Fib : Object - print("in Fib:Object\n") - - def Fib.test(*args) - println("in Fib.test") - - if args; println(*args) end - args = args.grep(/^c/) - super(*args) - end - - def init - println("in Fib.init"); - end - - def fib(n) - a =0; b = 1 - - while b <= n - c = a; a = b; b = c+b - end - return b - end -end - -def Object.test(*args) - println("in Object.test") - if args; println(*args) end -end - -Fib.test("abc", "def", "aaa", "ccc") -println("1:", 0x3fffffffa) -println("2:", 0x3ffffffa) -#println("3:", 0x40000000+0x40000000) - -fib = Fib.new - -fib.init -print(Fib, ":") - -#for i in 1 .. 100 -# fib.fib(90000) -#end - -println(fib.fib(9000)) - -def tt - for i in 1..10 - println("i:", i); - yield(i); - end -end - -test = tt() {|i|break if i == 2} -println([1,2,3,4].join(":")) @@ -0,0 +1,28 @@ +/************************************************ + + sig.h - + + $Author$ + $Date$ + created at: Wed Aug 16 01:15:38 JST 1995 + +************************************************/ +#ifndef SIG_H +#define SIG_H + +#ifdef SAFE_SIGHANDLE +extern int trap_immediate; +# define TRAP_BEG (trap_immediate=1) +# define TRAP_END (trap_immediate=0) +#else +# define TRAP_BEG +# define TRAP_END +#endif + +typedef RETSIGTYPE(*SIGHANDLE)(); +SIGHANDLE sig_beg(); +void sig_end(); + +extern int trap_pending; + +#endif @@ -9,6 +9,7 @@ ************************************************/ #include "ruby.h" +#include "sig.h" #include <signal.h> #include <stdio.h> @@ -162,7 +163,7 @@ signm2signo(nm) } VALUE -Fkill(argc, argv) +f_kill(argc, argv) int argc; VALUE *argv; { @@ -251,7 +252,7 @@ static RETSIGTYPE sighandle(sig) int sig; { - if (sig >= NSIG || trap_list[sig] == Qnil) + if (sig >= NSIG ||(sig != SIGINT && trap_list[sig] == Qnil)) Fail("trap_handler: Bad signal %d", sig); #ifndef HAVE_BSD_SIGNALS @@ -260,14 +261,16 @@ sighandle(sig) #ifdef SAFE_SIGHANDLE if (trap_immediate) { - rb_trap_eval(trap_list[sig]); + if (sig == SIGINT && !trap_list[sig]) Fail("Interrupt"); + rb_trap_eval(trap_list[sig], sig); } else { trap_pending++; trap_pending_list[sig]++; } #else - rb_trap_eval(trap_list[sig]); + if (sig == SIGINT && !trap_list[sig]) Fail("Interrupt"); + rb_trap_eval(trap_list[sig], sig); #endif } @@ -275,119 +278,184 @@ void rb_trap_exit() { if (trap_list[0]) - rb_trap_eval(trap_list[0]); + rb_trap_eval(trap_list[0], 0); } #ifdef SAFE_SIGHANDLE +void rb_trap_exec() { int i; - trap_pending = 0; for (i=0; i<NSIG; i++) { if (trap_pending_list[i]) { trap_pending_list[i] = 0; - rb_trap_eval(trap_list[i]); + if (i == SIGINT && trap_list[SIGINT] == 0) + Fail("Interrupt"); + rb_trap_eval(trap_list[i], i); } } + trap_pending = 0; } #endif -static VALUE -Ftrap(argc, argv) - int argc; - VALUE *argv; -{ - RETSIGTYPE (*func)(); - VALUE command; - int i, sig; -#ifdef HAVE_SIGPROCMASK +struct trap_arg { +#ifndef NT +# ifdef HAVE_SIGPROCMASK sigset_t mask; -#else +# else int mask; +# endif #endif + VALUE sig, cmd; +}; - if (argc < 2) - Fail("wrong # of arguments -- kill(cmd, sig...)"); +static RETSIGTYPE +sigexit() +{ + rb_exit(1); +} - /* disable interrupt */ -#ifdef HAVE_SIGPROCMASK - sigfillset(&mask); - sigprocmask(SIG_BLOCK, &mask, &mask); -#else - mask = sigblock(~0); -#endif +static VALUE +trap(arg) + struct trap_arg *arg; +{ + RETSIGTYPE (*func)(); + VALUE command; + int i, sig; func = sighandle; - - if (argv[0] == Qnil) { + command = arg->cmd; + if (command == Qnil) { func = SIG_IGN; - command = Qnil; } - else { - Check_Type(argv[0], T_STRING); - command = argv[0]; - if (RSTRING(argv[0])->len == 0) { + else if (TYPE(command) == T_STRING) { + if (RSTRING(command)->len == 0) { func = SIG_IGN; } - else if (RSTRING(argv[0])->len == 7) { - if (strncmp(RSTRING(argv[0])->ptr, "SIG_IGN", 7) == 0) { + else if (RSTRING(command)->len == 7) { + if (strncmp(RSTRING(command)->ptr, "SIG_IGN", 7) == 0) { func = SIG_IGN; } - else if (strncmp(RSTRING(argv[0])->ptr, "SIG_DFL", 7) == 0) { + else if (strncmp(RSTRING(command)->ptr, "SIG_DFL", 7) == 0) { func = SIG_DFL; } - else if (strncmp(RSTRING(argv[0])->ptr, "DEFAULT", 7) == 0) { + else if (strncmp(RSTRING(command)->ptr, "DEFAULT", 7) == 0) { func = SIG_DFL; } } - else if (RSTRING(argv[0])->len == 6) { - if (strncmp(RSTRING(argv[0])->ptr, "IGNORE", 6) == 0) { + else if (RSTRING(command)->len == 6) { + if (strncmp(RSTRING(command)->ptr, "IGNORE", 6) == 0) { func = SIG_IGN; } } + else if (RSTRING(command)->len == 4) { + if (strncmp(RSTRING(command)->ptr, "EXIT", 4) == 0) { + func = sigexit; + } + } } - if (func == SIG_IGN || func == SIG_DFL) + if (func == SIG_IGN || func == SIG_DFL) { command = Qnil; + } - for (i=1; i<argc; i++) { - if (TYPE(argv[i]) == T_STRING) { - char *s = RSTRING(argv[i])->ptr; + if (TYPE(arg->sig) == T_STRING) { + char *s = RSTRING(arg->sig)->ptr; - if (strncmp("SIG", s, 3) == 0) - s += 3; - sig = signm2signo(s); - if (sig == 0 && strcmp(s, "EXIT") != 0) - Fail("Invalid signal SIG%s", s); - } - else { - sig = NUM2INT(argv[i]); - } - if (sig < 0 || sig > NSIG) - Fail("Invalid signal no %d", sig); + if (strncmp("SIG", s, 3) == 0) + s += 3; + sig = signm2signo(s); + if (sig == 0 && strcmp(s, "EXIT") != 0) + Fail("Invalid signal SIG%s", s); + } + else { + sig = NUM2INT(arg->sig); + } + if (sig < 0 || sig > NSIG) { + Fail("Invalid signal no %d", sig); + } + signal(sig, func); + trap_list[sig] = command; + /* enable at least specified signal. */ +#ifdef HAVE_SIGPROCMASK + sigdelset(&arg->mask, sig); +#else + arg->mask &= ~sigmask(sig); +#endif + return Qnil; +} - signal(sig, sighandle); - trap_list[sig] = command; - /* enable at least specified signal. */ +#ifndef NT +static void +trap_ensure(arg) + struct trap_arg *arg; +{ + /* enable interrupt */ #ifdef HAVE_SIGPROCMASK - sigdelset(&mask, sig); + sigprocmask(SIG_SETMASK, &arg->mask, NULL); #else - mask &= ~sigmask(sig); + sigsetmask(arg->mask); #endif +} +#endif + +static VALUE +f_trap(argc, argv) + int argc; + VALUE *argv; +{ + struct trap_arg arg; + + if (argc == 0 || argc > 2) { + Fail("wrong # of arguments -- trap(sig, cmd)/trap(sig){...}"); } + + arg.sig = argv[0]; + if (argc == 1) { + arg.cmd = f_lambda(); + } + else if (argc == 2) { + arg.cmd = argv[1]; + } + +#ifndef NT /* disable interrupt */ -#ifdef HAVE_SIGPROCMASK - sigprocmask(SIG_SETMASK, &mask, NULL); +# ifdef HAVE_SIGPROCMASK + sigfillset(&arg.mask); + sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask); +# else + arg.mask = sigblock(~0); +# endif + + return rb_ensure(trap, &arg, trap_ensure, &arg); #else - sigsetmask(mask); + return trap(&arg); #endif - return Qnil; } +SIGHANDLE +sig_beg() +{ + if (!trap_list[SIGINT]) { + return signal(SIGINT, sighandle); + } + return 0; +} + +void +sig_end(handle) + SIGHANDLE handle; +{ + if (!trap_list[SIGINT]) { + signal(SIGINT, handle); + } +} + +void Init_signal() { - extern VALUE C_Kernel; + extern VALUE cKernel; - rb_define_method(C_Kernel, "kill", Fkill, -1); - rb_define_method(C_Kernel, "trap", Ftrap, -1); + rb_define_method(cKernel, "kill", f_kill, -1); + rb_define_method(cKernel, "trap", f_trap, -1); } @@ -1,3538 +0,0 @@ -.\" spec - -*- Indented-Text -*- created at: Tue May 25 15:18:26 JST 1993 - -* Ϥ - -RubyϡUNIXǼڤ˥֥ȻظץߥפȤ˾ -¸뤿ޤ줿ΤɬפȻפ줿: - - * ʸˡ䵡ǽñǤ롥 - * ֥ȻظץߥݡȤ뵡ǽ - ĸȤ߷פƤ롥 - * 饦ɥबû(ץǤ) - * OS(UNIX)εǽñѤǤ롥 - * ץȸȤƻȤ롥 - * ϤfreeǤ롥 - -ʤɤǤ롥֥ȻظȤưŪǤSmalltalkC++ʤɤ -ξΰƤϤ뤬ä˼ڤʥץߥȤ˷ -ƤꡤʾξƤΤǤϤʤäץȸ -ǤPerl Tcl˥֥Ȼظǽɲäƥ¸ߤ뤬 -ϡּڤ˥ץߥפȤƤϤƤ⡤դ˥ -Ȼظǽääơξ -߷פ줿Rubyħ: - - * ץǤ롥 - * ñ㳰ξʤʸˡ - * ʬʥ֥Ȼظǽġ - * Ǥ䤹(黻ҷʤ) - * ١쥯롥 - * 㳰ǽ롥 - * ʬ˶Ϥʥ饹Ȥ߹ޤƤ롥 - * OS뵡ǽ롥 - * ĥ䤹 - -ʤɤǤ롥RubyshPerlΤäƤͤˤȤäƤξQˤʤ뤿ä -Τǡθ줫μʰܹԤǽǤȻפ롥ץޤ -RubyΥ֥ȻظǽˤĤƳؤ٤С궯ϤʤȤǤ褦 -ʤ - -Cǥ饹åɤҤɲä뤳ȤRuby˶Ϥˤ -뤳ȤǤ롥ΥץåȥեǤRubyưŪ˥֥ȥե -Ǥ뤷ǤʤƤRubyƥѥ뤷Ȥ߹ߥ -ɲäΤưפǤ(PerlʤɤϤ뤫ưפǤ) - -* Lexical structure - -ߤrubyμϥ饯åȤȤASCIIѤ롥rubyʸ -ʸ̤롥̻ҤǤʤǤդΤȤ˶ʸ -Ȥ롥ʸϥڡ(space)(tab)ľ(vertical -tab) CR(carriage return)(form feed)Ǥ롥(newline) -˼³ˤ϶ʸȤơʳǤʸζڤȤƲ -ᤵ롥 - -̻Ҥϱʸ("_"ޤ)Ϥޤꡤѿ³ΤǤ롥ruby -̻ҤŤϤʤߤμϼ̻ҤȤƥޥХȥ -(EUC,SJIS)̤ʤ - -Хѿ̾"$"³̻Ҥޤϵ1ʸѿ -"@"³̻ҡˤʸǻϤޤ뼱̻ҡѿ̾Ͼʸ -ǻϤޤ뼱̻ҤǤ롥å̾ˤñʤ뼱̻ҤѤ(å̾ -ʸǤ⾮ʸǤϤ) - -** - -ץȸνˤʤ餤ʸʸɽ(?#)ʳ`#' -ޤǤϥȤȸʤ - -** ͽ - -ͽϰʲ̤Ǥ - - alias def if retry while - and else in return yield - begin elsif module self __END__ - break end nil super __FILE__ - case ensure or then __LINE__ - class fail redo undef - continue for resque when - -ͽϥ饹̾å̾ѿ̾ʤɤѤ뤳ȤϤǤʤ - -** ڤʸ - -ʸʤɤΥƥʳξζʸ(֤ȥڡ)Ӳ -(\n)ڤ국Ȥʤ롥˲Ԥ - - a + - b - -Τ褦˹ԤǽꡤιԤ³Ȥ(Ǹʸ -黻Ҥ뤤`,'Ǥ)ζڤȤǧ롥 - -* ץ - -: - - print "hello world!\n" - -ץϼ¤٤ΤǤ롥ȼδ֤ϥߥ(`;')ޤϲ -ԤǶڤ롥 - -* - -RubyǤnilʳɾ롥CPerlʤɤȤϰۤʤꡤ0 -""(ʸ)ϵȤɾʤΤǵĤ뤳ȡ - -** ʸ - -֥륯(`"')dz줿ʸϥХåå³ʸʲ -Τ褦˲ᤵ롥 - -Хåå嵭ˡ - - \t (0x09) - \n ʸ(0x0a) - \r ʸ(0x0d) - \f ڡʸ(0x0c) - \b Хåڡ(0x08) - \a ٥(0x07) - \e (0x1b) - \# ʸ`#'Τ - \nnn 8ʿɽ(n0-7) - \xnn 16ʿɽ(n0-9,a-f) - \cx ȥʸ(xASCIIʸ) - \x ʸxΤ - -ޤ`#'ˤѿŸԤ롥륯(`'')dz -ʸϡ`\\'(Хåå夽Τ)`\''(륯) -ơʸȤβԤʤ - -ʸʸ֥ȤΤǡʸƤ -Ƥ⡤ȤȤʸѤʤ - -** ޥɽ - -RubyǤshΤ褦˥ޥɤμ¹Է̤ʸƥΤ褦˻ȤȤ -Ǥ롥``ǰϤޤ줿ʸϡ֥륯ȤƱͤ˥Хåå嵭 -ˡβѿŸԤʤ줿塤ޥɤȤƼ¹Ԥ졤μ¹Է -ʸȤͿ롥ޥɤɾ뤿Ӥ˼¹Ԥ롥 - -** ɽ - -`/'ǰϤޤ줿ʸɽɽ`/'θʸ`i'Ϳ -줿ˤϡɽϥޥåʸʸζ̤ʤ - - ^ Ƭ - $ - . Ǥդ1ʸ - \w ѿ[0-9A-Za-z_]Ʊ - \W ѿ - \s ʸ[ \t\n\r\f]Ʊ - \S ʸ - \d [0-9] Ʊ - \D - \b 춭ʸ(ʸ饹) - \B 춭ʸ - \b (0x08)(ʸ饹) - [ ] ʸ饹 - * ľɽ0ʾη֤ - + ľɽ1ʾη֤ - {m,n} mnη֤ - ? 0ޤ1 - | - ( ) ɽޤȤ - -¾ʸƱХåå嵭ˡѿŸͭǤ롥 - -** ѿŸ - -֥륯(`"')ǰϤޤ줿ʸޥʸɽ -ӥ磻ɥɼǤ`#{ѿ̾}'ȤѿƤŸ -ȤǤ롥ѿѿ(`$',`@')ǻϤޤˤ`#ѿ̾'Ȥ -ǤŸǤ롥ʸ`#'³ʸ `{',`$',`@'ǤʤСΤޤ -ʸ`#'ȤƲᤵ롥 - -** ͥƥ - - 123 - -123 (Ĥ) - 1_234 (10ʿ`_'ޤळȤǤ) - 123.45 ư - 1.2e-3 ư - 0xffff 16 - 0377 8 - ?a ʸ`a'Υ(97) - ?\C-a ȥaΥ(1) - ?\M-a aΥ(225) - ?\M-\C-a -ȥaΥ(129) - - :ܥ ̻/ѿ̾/黻ҤȰабapplyʤ - ǥåɤꤹʤɤ˻Ȥ - -?ɽǤƤΥХåå嵭ˡͭǤ롥 - -** ѿ - -Rubyѿϥ(ͭϰ)ȼ̿(ͭ)ˤä4ʬव졤 -μѿ̾κǽΰʸǷꤵ롥̾ѿ2ʸܰʹߤ -ѿޤ`_'Ǥ뤬ƥѿΰϡ`$'+1ʸεפȤ -ѿ롥ѿ̾Ĺ˴ؤ̤¤Ϥʤ - -ѿΥפ˴ؤ餺ƤʤѿȤͤnil -Ǥ롥μѿɬפʤ - -*** Хѿ - -: - - $foobar - $/ - -`$'ǻϤޤѿΥפϥХǤꡤץΤɤǤ -ȤǤ롥μ̿ϥץμ̿ - -*** ѿ - -: - - @foobar - -`@'ǻϤޤѿϥѿǤꡤΥ饹ޤϥ֥饹 -åɤ黲ȤǤ롥פϥåǤꡤμ̿ϥ֥ -Ȥμ̿ - -*** 饹 - -: - - FOOBAR - -ʸǻϤޤ뼱̻ҤؤΥǤꡤǽ줿饹 -ƤΥ֥饹ΥǻȤǤ롥 -Ƥ⥸塼롼ɤ뤳ȤˤäƹԤʤ롥ؤ -ϥȥåץ٥롤ʤåɤǤ٥ǤΤ߲ǽǤ롥 -ϥ饹֤ͤͭ졤ͤѹ뤳ȤǤʤ -(㳰ȯ)饹μ̿ϥ饹μ̿ - -饹ϼưŪΤǡ饹̾Ǥ롥 - -*** ѿ - -: - - foobar - -ʸޤ`_'ǻϤޤ뼱̻ҤϥѿؤΥǤ롥 -ʤѿͤnilǤ - -ѿΥפϥ֥åϰ(åǤϥåɤν -ޤǡ饹/⥸塼ǤϤνޤ)Ǥ롥̿⤽ -֥åνޤ(ȥåץ٥Υѿϥץνλޤ) -롥 - -*** ѿ - -̾ѿʳ˵ѿȸƤФüѿ4Ĥ롥 - - self | ߤΥåɤμ¹Լ - nil | Nil饹ͣΥ(ɽ) - __FILE__ | ץȤΥե̾(ʸ) - __LINE__ | ߤιֹ() - -εѿˤäƤͤѹ뤳ȤϤǤʤ -ѿؤ㳰ȯ롥 - -** - -: - - [1, 2, 3] - -Array饹ΥǤ롥뼰ϰʲη -롥 - - `[' , .. `]' - -줾μɾ̤ޤ֤ǿ0ζ -뤿ˤ϶ - - `[' `]' - -Ѥ롥 - -** Ϣ - -: - - {1=>2, 2=>4, 3=>6} - -ϢȤǤդΥ֥Ȥ(ź)ȤƻǤ롥Ruby -ϢHash(Ϣ)饹ΥǤ롥ܺ٤ϥ饹 -HashιȤ줿ϢϢϰʲηǤ롥 - - `{' `=>' .. `}' - -줾μɾ̤ͤȤϢ֥Ȥ֤ -ǿ0Ϣ뤿ˤ϶Ϣ - - `{' `}' - -Ѥ롥Ǥ1İʾ夢硤ۣǤʤ`{', `}'ϾάǤ롥 - -** åɸƽм - -: - - foo.bar() - foo.bar - bar() - -֥Ȥ˥åŪʹʸåǤꡤδ -ܷϰʲ̤Ǥ롥 - - 1 `.' å̾ `(' 1.. [`,' `*' n ]`)' - -1ɾ륪֥ȤΡ̻ҤǻꤵåɤƤ -ФֺǸΰ`*'³(ñ)Ǥ硤μɾ -(ǤʤѴ)ŸơȤɲä롥 - -åǡ쥷Фselfξ硤쥷Фά̾Υץ -ߥˤؿΤ褦ʷǥåɤƤӽФȤǤ롥 - -åɸƤӽФΰμγ̤άǤ뤬Ȥʤ뼰 -ʸޤͽǻϤޤϡ̤ͥδطͽ̤η̤ -ʤ礬롥 - - (, [, {, /, +, -, if, while - -ɤΤ褦ɾ뤫ۣʾˤϳ̤Ĥ - -㡧 - foo bar+baz # åɸƤӽФfoo(bar+baz) - foo (1+2)*5 # åɸƤӽФ(foo(1+2)) * 5 - foo 1 # åɸƤӽФfoo(1) - foo -1 # ѿfoo - 1 - -쥷ФꤷåɸƤӽФǤϤξ1Ĥʤˤ -άǤ(쥷Фꤷʤ硤̤Ĥʤȥѿ -ȤȤƲᤵ) - -å̾ȤƤǤդμ̻ҤѤ뤳ȤǤ롥ǽʸʸ -Ǥ⾮ʸǤʤѿ̾Ȥϼ̻Ҥ֤̾㤦ΤǽʣƤ -ʤ - -饹ModuleƤå(public,private)ǥåɤθƤӽ -椹뤳Ȥ롥privateǻꤵ줿¤줿åɤϴ -ǤƤӽФȤʤ - -** SUPER - -: - - super - super(1,2,3) - -åüʥȤƥѡ饹ΥåɤθƤӽФ -롥ηϥåɤ˥ѡ饹Ѥ뤿 -˻Ȥ - - super - -ߤΥåɤͿ줿Τޤޥѥ饹Ʊ̾ΥåɤƤ -ФȤͿ줿ѿͤѹƤ⡤ϤΤϸΰ -ͤǤ롥 - - super`(' .. `)' - -ȤȤ˥ѡ饹Ʊ̾ΥåɤƤӽФֺǸΰ -`*'³̾ΥåɸƤӽФƱͤŸϤ롥 - -** - -: - - foo = bar - foo[0] = bar - foo.bar = baz - -ѿʤɤͤꤹ뤿Ѥ롥ϱ黻ҷȤ -Ƥ뤬åɤǤϤʤΤǺ뤳ȤϤǤʤդˤʤ뤳 -Τϰʲ3μǤ롥 - -ѿ(`$'̻ | `@'̻ | ̻) - - ѿ `=' - -ѿؤϱդμɾ줿ͤդǻꤵ줿ѿ -롥 - -([..]) - - 1`[' 2.. `]' `=' n - -ȼؤϡ1ɾ륪֥Ȥˡ2鼰n -ޤǤȤơ"[]=" ȤåɤƤӽФ - -°(`.'̻) - - 1 `.' ̻ `=' 2 - -°(ʤΥåɸƤӽФ)ؤϡ1ɾ -֥(쥷Фά줿`self')Фơ"̻="Ȥ -åɤ 2ȤƸƤӽФ - -** - -: - - foo += 12 - -ͤΤΤ˱黻ä뤿˼롥 - - 1 op= 2 # 1ǽǤʤФʤʤ - -ηŪˡּ1 = 1 op 2פƱͤɾ롥1 -1ɾʤΤǡ1Ѥϡּ1 = 1 op 2 -Ȥưۤʤ̤Ȥʤ롥opȤƻȤ黻Ҥ - - +, -, *, /, %, **, &, |, ^, <<, >> - -11Ǥ롥黻Ҥ`='δ֤˥ڡƤϤʤ - -** ¿ - -: - - foo, bar, baz = 1, 2, 3 - foo, = list() - foo, *rest = list2() - -ƱʣѿԤʤȤǤ롥ηϰʲ̤Ǥ롥 - - `,' [ `,'..] [`*' ]= [, ..] - -դˤ3μ롥դμĤʤϡ -Ȥ(ɬפʤto_aåɤѴ)Ǥ줾캸 -դ롥ʳξˤϡ줾μͤդ롥 -դοȱդǤοʤˤʤѿˤ nil졤 -;äǤ̵뤵롥¿κǸǤ`*'硤Ĥ -ưȤ롥 - - foo, bar = [1, 2] # foo = 1; bar = 2 - foo, bar = 1, 2 # foo = 1; bar = 2 - foo, bar = 1 # foo = 1; bar = nil - - foo, bar, baz = 1, 2 # foo = 1; bar = 2; baz = nil - foo, bar = 1, 2, 3 # foo = 1; bar = 2 - foo,*bar = 1, 2, 3 # foo = 1; bar = [2, 3] - -¿ͤ(Ѵ줿)դǤ롥 - -** 黻Ҽ - -: - - 1+2*3/4 - -ץߥؤΤ˰ΥåɸƤӽФ湽¤ϱ黻ҷ -Ȥ롥Rubyˤϰʲˤ黻Ҥ롥ΤΤۤɷ̤ -Ʊα黻Ҥη̤ƱǤ롥 - - [](), []=() - -(unary) +(unary) ! ~ - ** - * / % - + - - << >> - & - | ^ - > >= < <= - <=> == != =~ !~ - && - || - .. ... - :: - =() (+=, -=,..) - and - or - if while - -ۤȤɤα黻ˤϥåɸƤӽФȤƲᤵ(饹˺ -Ǥ)ǤʤüʤΤ롥Ǥʤü黻 -Ҥ - - =(), ...(ϰ), !(), &&(), and, |(), or, - if, while - -9Ĥα黻ҤȤȤȤ߹碌ˤʤ !=, !~ Ӽ黻 -Ǥ롥 - -Ǥü黻Ұʳα黻ҷϰʲΤ褦ʥåɸƤӽФȸ -ʤ롥 - -ñ黻(+, -, ~) - - 1. 黻 () - -(Ϣޤ)Ǥλ(1 `[' 2.. `]') - - 1. `[]' (2..) - -Ǥ( 1 `[' 2.. `]' `=' n) - - 1. `[]=' (2.., n) - -ʳ2黻(1 黻 2) - - 1. 黻 (2) - -ϤޤǤ⤽ΥåɸƤӽФȤƲᤵȤ -ǡrubyץǤҤȤ櫓ǤϤʤ - -** ̤ˤ륰롼ԥ - -: - - (1+2)*3 - -ϳ̤ˤäƥ롼ԥ뤳ȤǤ롥 - - `(' `)' - -** IF - - if 1 [then] - .. - [elsif 2 [then] - .. ].. - [else - .. ] - end - -ȽǼRubyifelse ifǤelifǤʤelsififϢ³Ԥʤ -Ȥդ뤳ȡ郎ΩƼ¹Ԥ֤ͤ¹Ԥʤä -ͤnil - -ifξȽμǤʸɽƥϼ$_=~ ƥפ -άǤȤߤʤ롥 - -** IF - - if - -、(if)μԤ뼰äɾ롥ưбif -ƱͤǤ롥ifҤΤĤͤϾ郎Ωˤϼ͡ -ΩξˤnilǤ롥 - -** CASE - - case 0 - [when 1 [, 2].. [then] - .. ].. - [else - .. ] - end - -ʬCswitchPascalcase˻Ƥ롥breakæФ뤳Ȥ -μ˷³뤳ȤʤΤա - -ΰפϡּn =~ 0]ǹԤʤ롥Ĥޤꡤ - - case expr0 - when expr1, expr2 - stmt1 - when expr3, expr4 - stmt2 - else - stmt3 - end - -ϰʲifȤۤǤ롥 - - _tmp = expr0 - if expr1 =~ _tmp || expr2 =~ _tmp - stmt1 - elsif expr3 =~ _tmp || expr4 =~ _tmp - stmt2 - else - stmt3 - end - -** AND - - 1 `&&' 2 - 1 `and' 2 - -1ɾͤ(nilʳ)ǤС2ɾ롥`and'ͥ -̤㤤̾Ǥ롥 - -andξդμǤʸɽƥϼ$_=~ ƥפξά -Ȥߤʤ롥 - -** OR - - 1 `||' 2 - 1 'or 2 - -1ɾͤǤС2ɾ롥`or'̤ͥ㤤 -̾Ǥ롥 - -orξդμǤʸɽƥϼ$_=~ ƥפξά -Ȥߤʤ롥 - -** ϰϻ꼰 - - 1 `...' 2 - -1ˤʤޤǤϵ֤θϼ2֤ޤǤϿ֤2 -ˤʤо֤ϵ롥 - -`...'ξդμǤʸɽƥϼ$_=~ ƥפξά -ϡ$.==פξάȲᤵ롥 - -** NOT - - `!' - -ǤеǤп֤ - -`!'Ǥʸɽƥϼ$_=~ ƥפξάǤȤ -ʤ롥 - - 1 `!=' 2 - -!(1 == 2)פξά - - 1 `!~' 2 - -!(1 ~= 2)פξά - -** WHILE - - while - .. - end - -ɾͤδ֤֡¹Ԥ롥whileͤnilǤ롥 - -whileξȽμǤʸɽƥϼ$_=~ ƥ -ξάǤȤߤʤ롥 - -** WHILE - - ñ㼰 while - -֤(while)ϤޤԤ뼰ɾƤPɾ -ǡ٤ϼ¹Ԥ뤳Ȥˤʤ롥whileҤΤĤͤnil -롥 - -** ƥ졼(֤) - -ƥ졼Ȥ湽¤(ä˥롼)ݲΤѤåɤ -Ǥ롥ɤ(֥åȸƤФ)ꤷƥƥ졼Ƥ -Фȡƥ졼ŬͤåȤƥ֥åɾ(餯 -ʣ)ƥ졼Υ֥åθƤӽФyieldѤ() - -ƥ졼θƤӽФϰʲιʸǹԤʤ롥 - - `{' ռ.. `|' .. `}' - -ּפ֥åȤꤷּפΥåɤƥ졼Ȥɾ -롥ּפΥȥåץ٥Υåɤƥ졼ȤƸƤӽФ졤 -쥷Фɽ䡤μϥƥ졼ȤƤϸƤӽФʤּ -ʣμޤơƥ졼Ȥƽ˸ƤФ롥 - -ƥ졼yield¹Ԥȡǻꤵ줿ͤռǻꤵ -줿ѿ졤֥å¹Ԥ롥֥åμ¹ԤλȤ -ͤ yieldͤȤ֤롥åɤƥ졼ȤƸƤӽ -줿ɤϥåiterator_p()ͤΤ뤳ȤǤ롥ˤ -Enumerable⥸塼grepåɤΤ褦˥ƥ졼ȤƸƤФ줿 -̤ΥåɤȤƸƤФ줿Ȥưۤʤåɤ⤢롥 - -** FOR - -֥ȤγǤФԤʤηƤ롥 -ϰʲ̤ꡥ - - for ռ.. in - - end - -γǤФ¹Ԥ롥ϰʲμǤ롥 - - ().each `{' ռ.. `|' `}' - -äƼͤΥ֥Ȥåeachʤ硤for¹Ԥ -㳰ȯ롥 - -** YIELD - - yield `(' [ [`,' ..]]) - yield - -ƥ졼ǥ֥åθƤӽФԤʤyield¹Ԥåɤ -ƥ졼ȤƸƤӽФƤʤˤ㳰ȯ롥yield ͤϥ -åͤǤ롥 - -yieldΰγ̤ۣǤʤ¤άǤ롥 - -** FAIL - - fail `(' [å] `)' - -㳰ȯ롥åͿ줿ˤȯե -ֹ̾ƥѿ`$@'ˡå`$!'˥åȤ롥 - -failΰγ̤ϾάǤ롥 - -** BEGIN - -ʣμޤȤ뤿㳰Τbegin롥beginη -ʲ̤Ǥ롥 - - begin - .. - [resque - .. ] - [ensure - ..] - end - -beginͤϰֺǸɾ줿ͤǤ롥beginνȯ -㳰resqueͤ뤳Ȥ롥ξbeginͤ -resqueǺǸɾͤǤ롥ensure¸ߤ -beginλɬ(ェλǤʤ㳰, return, break, -continue, redoʤɤˤæФǤ)ensureμɾ롥 - -** RETRY - - retry - -beginresqueǻȤbeginϤᤫ⤦ټ¹Ԥ롥㳰 -ԤʤäƤƻԤΤ˻ȤresqueʳretryѤ줿 -ȯ롥 - -** RETURN - - return [[`,' ..]] - -ͤͤȤƥåɤμ¹Ԥλ롥2İʾͿ줿 -ˤϡǤȤåɤͤȤ롥Ĥʤ -ˤ nil ͤȤʤ롥 - -** BREAK - - break - -break ϥ롼פæФ롥CȰ㤤breakϤäȤ¦Υ롼פæФ -Ѥcase ȴѤϻʤ - -** CONTINUE - - continue - -continueϤäȤ¦Υ롼פμη֤Ϥ롥 - -** REDO - - redo - -redoϥ롼ΥåԤʤ鷺ߤη֤ľ - -** 饹 - -饹빽ϰʲ̤Ǥ롥 - - class 饹̾ [`:' ѡ饹̾ ] - - end - -饹̾ʸǻϤޤ뼱̻ҤǤ롥 - -** ⥸塼 - -⥸塼빽ϰʲ̤Ǥ롥 - - module 饹̾ - - end - -⥸塼̾ʸǻϤޤ뼱̻ҤǤ롥 - -** å - -̾(ðۥåɤǤʤ)åηϰʲ̤Ǥ롥̾ -ϥͥȤǤʤΤǡåǤϥåƤӸ -ӽФʤ - - def å̾ [`(' [`,' ..][`,' `*' ] `)'] - - end - -å̾ϼ̻ҤޤʸǤ롥黻Ҥκˤʸ -ǻꤹ롥¤ӤκǸ`*'硤¿Ϳ줿 -°ϡǸΰȤͿ(ʤˤϥ顼) - - -åɤˤϸƤӽФ¤ä뤳ȤǤ¤ä줿åɤϡ -ؿǤƤӽФʤ(privateå) - -˥åɤ硤饹γˤdefϥǥե -Ǥprivateåɤ饹ˤdefpublic -ɤ롥ѡ饹Υåɤˤ -åɤβĻϥѡ饹ΥåɤΤΤѤ - -åɤβĻѹˤModule饹Ƥpublic, -privateγƥåɤѤ롥 - -** ðۥå - -åˤϤ⤦ðۥåɤ롥ðۥåɤȤϤ -Υ֥Ȥ˸ͭΥåɤǤ롥ϰʲ̤Ǥ롥 - - def `.' å̾ [`(' [`,' ..][`,' `*' ] `)'] - - end - -ηϼͤǤ륪֥Ȥðۥåɤ롥ͤ -(ӥȥ饹Ǥʤ)̾索֥Ȥ饹ޤϥ⥸塼Ǥ -ɬפ롥̾åȤϰۤʤꡤðۥåɤϥå -ǤͥȤ뤳ȤǤ롥 - -ðۥåɤ̾ϷѾʤ㳰Ȥƥ饹ðۥåɤϤ -֥饹ˤѾ롥ؤХ饹ðۥåɤ¾Υ֥ -Ȼظƥˤ륯饹åɤƯ롥 - -: 롼ɤ⥸塼ðۥåɤϷѾʤ - -** ALIAS - -ʲηǥåɤ̾Ĥ뤳ȤǤ롥 - - alias å̾1 å̾2 - -̾դ줿åɤϡλǤΥåѤΥ -åɤƤ⡤θŤåɤƤӽФ줿ΤƱ -Ư롥 - -** UNDEF - -åɤäˤundefѤ롥 - - undef å̾ - -ꤷåɤä - -defˤ̾undefˤäˤäƥ饹Υե -ѡ饹Ωѹ뤳ȤǤ롥åɤself - ˥åäƤ⤢Τǡ褯դʤȴ¸Υ -ɤưʤʤǽ롥 - -* Ȥ߹ߴؿ - -Rubyˤϸ̩ʰ̣ǤϴؿϤʤKernel饹δؿåɤ(Ƥ -̾說饹ؿǸƤӽФΤ)ؿŪѤ롥ؿŪ -Ѥåɤʲˤ롥Υåɤݤˤϸ -ͤƹԤʤ٤Ǥ롥 - - _exit(status) - - ץμ¹Ԥλ롥statusλơȤ롥 - exit()Ȥϰäơ㳰ʤɤϰڹԤʤʤfork()θ塤 - ץλʤɤѤ롥 - - eof() - - ޥɥ饤ϤEOFãƤ硤֤ - - eval(expr) - - exprȤͿ줿ʸrubyץȤƲᡤ¹Ԥ롥 - - exec(command) - - ¹ԤƤץλơcommandʸǻꤵ - ̥ץư롥 - - exit([status]) - - ץμ¹Ԥλ롥statusȤͿ줿硤 - ͤRubyޥɤνλơȤ롥ǥեȤ0 - - fork() - - forkƥॳ¹Ԥҥץ롥ܺ٤ - fork(2)ȤΤȡƥץ¦ǤϻҥץΥץid - ֤ҥץ¦Ǥnil֤餫θǻҥץ - ˼Ԥˤ㳰ȯ롥 - - format(format, ...) - - եޥåȤȤͿ줿ʸCsprintfƱ褦 - ᤷŸʸ֤åsprintf()̾ - - RubyˤformatҤγĥˤĤƤsprintf()ιȤ - ȡ - - getc() - - ɸϤʸФͤɤ߹ʸʸ - (ASCII)ɽFixnumǤ롥 - - gets() - - ȤͿ줿ե(ʤɸ)ǹ벾 - Ūʥե(ƥѿ`$<'ǥǤ)ɤ߹ - ǡɤ߹ߤˤϤʸ֤եν - ãˤnil֤Ԥζڤϥƥѿ`$/'ˤä - ѹǤ롥ɤ߹ʸϥƥѿ`$_'ˤ⥻åȤ롥 - - gsub(pattern[, replace]) - - ƥѿ`$_'λؤʸ pattern˥ޥåʬ - replace֤롥String饹gsubåɤβȤ - ȡreplaceά줿ˤϥƥ졼Ȥư - åɾִ̤롥 gsubåɤ`$_'ͤ - 롥 - - iterator_p() - - åɤƥ졼ȤƸƤӽФ줿˿Ǥʤ˵ - ֤Ҹ졥 - - kill(signal, pid..) - - pidǻꤵ줿ץ˥ʥ롥ʥϥʥ - 椫̾ǻꤹ롥ͤĥʥ(뤤ϥʥ̾ - `-')ͿȥץǤϤʤץ롼פ˥ʥ - 롥 - - load(file) - - fileɤ롥fileɤѥϥƥѿ$LOAD_PATH - Ƿꤵ롥 - - open(file[, mode]) - - fileץơFile֥Ȥ֤ե̾ϥ - եե̾`|'ǻϤޤˤ³ʸ - ޥɤȤƵưѥץ饤롥 - - ޥ̾"-"Ǥopen()Rubyλҥץ - λҥץȤΥѥפ֤ - - modeϥեΥ⡼ɤꤹ롥ϰʲΤΤ - 줫ʸǤ롥 - - r ɤ߹ѡopenեϤ餫¸ߤƤ - ɬפ롥 - - r+ ɤ߽ξѡopenեϤ餫¸ߤƤ - ɬפ롥 - - w ѡե뤬¸ߤƤ硤Ĺ0ˤ - 롥¸ߤƤʤп˥ե롥 - - w+ ɤ߽ξѡɤ߹ߤԤʤ뤳Ȱʳ"w"ƱƯ - 롥 - - a ɲýѡեϤ餫¸ߤƤɬ - 롥ߤϥեκǸɲä롥 - - a+ ɤ߽ξѡե뤬¸ߤƤʤп˺ - 롥֤ϥեκǸ˽롥 - - ⡼ɤά줿ΥǥեȤ"r"Ǥ롥 - - print(arg1, ..., argn) - - ˽Ϥ롥Ϳʤˤϥ쥷ФϤ롥 - ʸʳΥ֥ȤȤͿ줿ˤϡ - ֥Ȥto_såɤˤäʸѴƤϤ롥 - ƥѿ`$;'(ϥեɥѥ졼)nilǤʤͤ - ȤƤˤϡưδ֤ˤʸϤ롥ƥ - ѿ`$\'(ϥեɥѥ졼)nil ǤʤͤåȤ - ˤϡǸˤϤ롥 - - printf([port, ]format, arg1, ..., argn) - - Cprintf()Ʊformat˽ʸѴϤ - 롥1IOΥ֥饹ΥǤäϤΥ - ֥ȤФƽϤԤʤǥեȤ$stdout˽Ϥ롥 - - RubyˤformatҤγĥˤĤƤsprintf()ιȤ - ȡ - - rand(max) - - 0maxۤʤϰϤȯ롥ͤFixnum - - require(file) - - fileɤ롥loadȤưΰ㤤ϳĥҤäƤ - ɤեΥեѥѿ`$"'˳ФƤƴ˥ɤ - եϺƥɤʤȥʥߥåǥб - Ƥ(OS ˤ)Ǥ롥ºݤ˥ɤˤ TRUE˥ - ɤƤˤFALSE֤ - - select(reads[, writes[, execpts[, timeout]]]) - - select(2)¹Ԥ롥reads/writes/execptsˤIO(ޤϤΥ - 饹)ΥͿ롥timeoutFixnum / Float - / TimeΤ줫ǻꤹ롥ͤtimeoutΩˤ - nilǤʤȤ3Ǥ֤γǤ// - 㳰ԤΥ֥ȤǤȤƻġ - - sleep([sec]) - - secäץμ¹Ԥߤ롥secά줿硤ץ - SIGALRMʤ¤ꡤʵפ˥פ롥ºݤ˥ - פÿ֤ - - sprintf(format, ...) - - formatʸCsprintfƱ褦˲ᤷŸ - ʸ֤åformat()̾ - - - formatҤCsprintf()դ(Ruby - unsignedʤΤǡ%uϽ)˲ä, %b, %B, %O, %XȤ - ȤǤ롥%bϿͤ2ɽ%B, %O, %XϤ줾2ʡ8ʡ - 16ʿɽԤʤονκݤ2ɽǤϤʤ - ɽƬ`-'ĤΤɽ롥 - - srand([]) - - νͤꤷŤ֤ͤͤά줿 - time(3)֤ͤǥեȤȤ롥 - - sub(pattern[, replace]) - - ƥѿ`$_'λؤʸǺǽpattern˥ޥåʬ - replace֤롥replace ά줿ˤϥƥ졼 - Ȥư֥åɾִ̤롥subåɤ - `$_'ͤ롥¾ξܺ٤˴ؤƤString饹sub - åɤβȤΤȡ - - syscall(num, arg..) - - numǻꤵ줿ֹΥƥॳ¹Ԥ롥2ʹߤ - ƥॳΰȤϤʸޤǤʤ - ʤʤ - - system(command) - - ޥɤ¹Ԥνλơ֤ - - trap(command, signal..) - - signalγߤäcommand¹Ԥ롥signalϥ - ʥ̾ʥֹ桥commandȤ"SIG_IGN"ޤ"IGNORE" - ꤷˤϤΥʥ̵뤹(ǽʤ)"SIG_DFL" - "DEFAULT"ꤷϥǥեȤưԤʤ - - wait() - - ҥץλΤԤλҥץpid֤ - ҥץĤʤnil֤ - - waitpid(pid, flags) - - λҥץνλԤΥץλ˿ - ҥץ¸ߤʤΥ֥å⡼ɤǻҥץ - ޤλƤʤˤnil֤waitpid(2)wait4(2) - ƤʤޥǤflagsϤĤnilޤ0ǤʤФ - ʤ - -* Ȥ߹ѿ - - $! 顼åfailꤹ롥 - - $@ 顼ȯΥե̾ȹֹ椬 - - "ե:ֹ[:å̾()]" - - ηdzǼ롥 - - $& Ǹѥޥå - - $` ǸΥѥޥåǥޥåʸʸ - - $' ǸΥѥޥåǥޥåʸθ³ʸ - - $+ ǸθѥǥޥåǸγ - - $1..$9 Ǹѥޥånܤγ̤˥ޥå - ͤǼ롥̤ʤniläƤ롥 - - $~ ǸΥޥå˴ؤåȤ$&$1..$9 - ͤѲ롥 - - $= ѿͤnilǤʤѥޥåʸ - Ӥǥե٥åȤʸʸ̤ʤǥե - Ȥnil(̤) - - $/ ϥ쥳ɥѥ졼եʸФeach - Ԥʤʬʸꤹ롥$/˶ʸ("")ꤹ - ñ̤ϤԤʤnilꤹΤ - ɤ߹ࡥ$/ˤɽϻȤʤǥեȤ - "\n" - - $\ ϥ쥳ɥѥ졼ѿʸꤹ - write()print()٤˺ǸˤʸղäƽϤ - 롥ǥեȤnil(ʤˤɲäʤ) - - $, Array:join()ΥǥեȤζڤʸprint()γư - δ֤˽Ϥʸ - - $; String:split()ΥǥեȤζڤʸ - - $. Ǹɤϥեιֹ桥 - - $< (ʤɸ)ǹ벾ۥե롥Ĥޤ - gets()$<.gets()Ʊ̣Ǥ롥$<.fileǸɤ߹ - Υե륪֥Ȥ$<.filenameǤΥե - ̾롥(Ф: `<'ϥϸ) - - $> printprintfΥǥեȤν补ͤ$stdout-i - ץꤷˤɤ߹߸Ʊ̾Υե - 롥(Ф: `>'ϥν) - - $_ Ǹgets()ʤɤɤ߹ʸ - - $0 rubyץȤ̾ѿps(1)ν - Ѳ롥 - - $* rubyץȤͿ줿rubyȤФ - Ƥ롥 - - $$ ¹rubyץpid - - $? Ǹ˼¹Ԥҥץstatus - - $: եɤ˸ǥ쥯ȥؤΥѥ - ޤưˤϥǥե(ѥ˻ꤹ - )˲äơĶѿRUBYLIBͤrubyư-Iץ - ǻꤵ줿ͤɲä롥(Ф: ϴĶ - PATHζڤʸǤ) - - $" ˥ɤ줿ե̾ޤrequire()Ʊ - ե2ɤʤѤ롥(Ф: - prevent files to be doubly quoted(loaded)) - - $ARGF $<̾ - - $ARGV $*̾ - - $DEBUG `-d'ե饰ξ() - - $FILENAME ۥե`$<'Ǹɤ߹(ågets() - ɤǤ)ե̾$<.filenameƱ - - $LOAD_PATH $:̾ - - $stdin ɸ - $stdout ɸ - $stderr ɸ२顼 - - $VERBOSE `-v'ե饰ξ() - - TRUE t - FALSE nil - - 줾쿿ͤɽȽǤnilʳƤͤ - ȤȽǤ뤿ᡤTRUEͤɽŪʿͤȤʾΰ̣ - ʤäơåɤͤǤȤȤȡ - 줬TRUE֤ȤȤϸ̩ˤƱǤϤʤ(ҸŪѤ - åɤͤȤTRUE֤褦ˤϤʤäƤ뤬) - Ĥޤ - - if some.method() then ... else ... end - - - - if some.method() == TRUE then ... else ... end - - ϴˤƱǤϤʤFALSE˴ؤƤϡΤ褦 - ʤ - - STDIN ɸ - STDOUT ɸ - STDERR ɸ२顼 - - ENV Ķѿ˥ϢʸȤͿ - бĶѿͤ롥Ķѿ¸ߤ - nil֤롥 - - KCODE бƤɤɽʸ"EUC","SJIS"ޤ - "NONE" - - VERSION rubyΥСʸ - -* Ȥ߹ߥ饹ȥ⥸塼 - -** Array(饹) - -źȤΥ饹Ǥ롥ϰŪˤ``[..]'' -Ԥʤ롥 - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - self[nth] - self[start..end] - self[start, length] - - Ǥ˥롥ǽηǤnthܤǤ - ֤2ܤηǤstartܤǤendܤǤޤ - ʬ֤3ܤηǤstartܤlengthĤǤޤ - ʬ֤ - - self[nth] = val - self[start..end] = val - self[start, length] = val - - Ǥѹ롥ǽηǤnthܤǤval - ѹ롥2ܤηstartܤǤendܤǤޤǤ - valѹ롥3ܤηǤstartܤlengthĤǤval - ѹ롥 - - 2ܡ3ܤηǤvalǤʤФʤʤ - - : - - ary = [1, 2, 3, 4, 5] - ary[0..2] = [0, 0] # Ƥ [0, 0, 4, 5] - ary[1, 0] = [7] # Ƥ [0, 7, 0, 6, 5] - - self + other - - Ϣ롥selfotherξƤҤ - ֤ - - self * times - - η֤ - - self - other - - κ黻selfotherǤƤο - ֤ʣǤ1٤롥 - - self * other - - ѱ黻ξ˴ޤޤǤʤ뿷֤ - ʣǤ1٤롥 - - self | other - - ±黻ξˤ줫˴ޤޤǤƴޤ - ֤ʣǤ1٤롥 - - self << obj - - objɲä롥self֤ΤC++ŪϢǤ롥 - - assoc(key) - - Ϣۥꥹ(assocڥǤȤ)1Ǥkey - ("=="Ӥ)֤ - - clear - - 礭0ˤ롥 - - delete(val) - - valȰפǤ롥 - - delete_if - - Ǥ륤ƥ졼֥åɾͤλб - Ǥ롥 - - each - - γǤͿ륤ƥ졼 - - fill(val) - fill(val, start[, length]) - fill(val, start..end) - - (λꤵ줿ʬ)Ǥͤvalꤹ롥2֤η - lengthά줿νޤǤĹȤ롥ꤵ줿 - ʬϰϤۤϼưŪ˳ĥ롥 - - index(val) - - valǽǤΥǥå֤Ǥ¸ - ʤnil֤ - - indexes(ary) - indexes(index-1, ..., index-n) - - 1ܤηǤȤƼơǤǥ - ȤǤޤ֤2ܤηǤϳưͤ - ǥåȤǤޤ֤ - - join([sep]) - - ǤϢ뤷ʸ֤ǤʸѴ졤 - sepϢ뤵롥sepά줿ˤϥƥѿ`$,' - ͤѤ롥 - - length - size - - Ĺ(ǿ)֤ - - push(obj) - - objɲä롥 - - pack(template) - - Ƥtemplateʸˤäơ1Ĥʸ˥ѥå - 롥ѥåʸ֤ƥץ졼ȤϷʸȤĹ - (ά1)¤٤ΤǤ롥ĹȤ`*'ꤵ줿 - ֻĤΥǡơפĹɽ - - ʸϰʲΤΤ롥 - - a ASCIIʸ(nullʸͤ) - A ASCIIʸ(ڡͤ) - b ӥåȥȥ(̥ӥåȤ̥ӥå) - B ӥåȥȥ(̥ӥåȤ鲼̥ӥå) - h 16ʸ(̥˥֥뤬) - H 16ʸ(̥˥֥뤬) - c char - C unsigned char - s sort - S unsigned sort - i int - I unsigned int - l long - L unsigned int - n ͥåȥХȥshort - N ͥåȥХȥlong - f ñư(¸) - d ư(¸) - x ʥХ - X 1Хȸ - @ а֤ؤΰư - - pop - - Ǥơ֤ - - rassoc(value) - - Ϣۥꥹ(2ǤǤȤ)2Ǥ - value("=="Ӥ)֤ - - shift - - ƬǤơ֤ - - sort - - ƤȤ롥ƥ졼ȤƸƤӽФ줿ϥ֥ - ɾͤǤ羮ꤹ롥礭 - 0顥̾ΥåɤȤƸƤӽФ줿ϳ - `<=>'Ӥ롥 - - to_a - - ʬȤ֤оΤѰդƤåɤǤޤ - ʤ - - unshift(obj) - - objƬɲä롥 - -Single Methods: - - Array[item..] - - ǤȤ롥 - -** Assoc(饹) - -ǡ(ڥ)ɽ륯饹̾`::'黻ҤѤƹԤʤ -롥 - -SuperClass: Object - -Methods: - - car - - CONSڥΥǡCAR֤ - - car=(val) - - CONSڥCARΥǡѹ롥 - - cdr - - CONSڥΥǡCDR֤ - - cdr=(val) - - CONSڥCDRΥǡѹ롥 - -** Bignum(饹) - -̵¿ĹΥ饹黻η̤FixnumϰǤˤϼ -ưŪ˥饹FixnumѴ롥ŪRubyץǤFixnum -BignumѴϰۤΤ˹ԤΤǡռɬפ̵FloatȤ -˴ؤƤϡBignum Floatgenericity⤤Τˤؤ餺 -Bignum礭ͤɽǤΤǡѴ˷ǽ -롥 - - -SuperClass: Integer - -Methods: - - self + other - self - other - self * other - self / other - self % other - self ** other - - ѱ黻줾¡ѡ;Ѿ֤ - - ~ self - self | other - self & other - self ^ other - - ӥåȱ黻줾ӥåȿž¡ѡ¾Ū¤ - ֤ - - self << bits - self >> bits - - եȱ黻줾bitsӥåȤ˥ӥåȥեȤԤʤ - - divmod(other) - - Ⱦ;2Ǥ֤ - -** Block(饹) - -ƥ졼Ϥ³ޤȤ֥ȡ¹Ԥ륳ɤ -ʤƥ(ѿ)ʤɤ¸롥 - -SuperClass: Object - -Methods: - - call(arg[,..]) - - ֥å¹Ԥ롥 - -Single Methods: - - new - - ֥å롥yield¹ԤǤǤΥå - ƤФȡλǼ¹Ԥ٤ɤ߹֥ - (Block)롥 - -** Class(饹) - -饹Υ饹긷̩ȥ饹ðۥåɤѾ뤿 -ˡ줾饹ȸƤФ̾Τʤ饹饹Ȥƻ -ClassϤΥ饹Υ饹Ǥ(ʬä?)β⤬ -ǤʤƤ⡤RubyȤȤ˲λپʤ饹ˤðۥåɤ -Ǥȡѡ饹줿ðۥåɤϤΥ֥饹 -ǤͭǤΤнʬǤ롥 - -SuperClass: Module - -Private Methods: - - attr(name[, public]) - - Υ饹ΥФnameǻꤵ°롥 - ܤModuleattråɤιȤΤȡ - -Methods: - - new(..) - - 饹Υ롥¿ξ礳Υåɤϥ֥ - 饹ðۥåɤˤäƥС饤ɤ졤饹ˤäư - ۤʤ롥 - -** Comparable(⥸塼) - -ӱ黻饹ΤMixinΥ⥸塼롼ɤ뤳 -Ȥˤäơ`<=>'黻Ҥ¾α黻ҤϤѤ -Ǥ롥 - -Methods: - - self == other - - selfother֤ - - self > other - - selfother礭֤ - - self >= other - - selfother礭֤ - - self < other - - selfother꾮֤ - - self <= other - - selfother꾮֤ - - between(min, max) - - selfminmaxϰˤ֤ - -** Dir(饹) - -ǥ쥯ȥǤ֤ǥ쥯ȥꥹȥΤΥ饹 - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - close - - ǥ쥯ȥꥹȥ롥ʸ㳰ȯ - 롥 - - each - - ǥ쥯ȥγǤͿ륤ƥ졼 - - getwd - pwd - - ȥǥ쥯ȥ֤ - - rewind - - ǥ쥯ȥꥹȥƬ˥ꥻåȤ롥 - - seek(pos) - - ǥ쥯ȥꥹȥΰ֤posꤹ롥 - - tell - - ǥ쥯ȥꥹȥθߤΰ֤֤ - -Single Methods: - - self[pat] - glob(pat) - - ʸpatshΥ磻ɥɤȤŸ̤ʸ - Ȥ֤ϰʲ̤Ǥ롥 - - * Ǥդʸ(ʸޤ)Ȱ - ? Ǥդ1ʸȰ - [ ] []Τ줫1ʸȰ - {..} {}(ޤǶڤ줿)줫ʸ - - - chdir(path) - - ȥǥ쥯ȥpathѹ롥 - - chroot(path) - - ץΥ롼ȥǥ쥯ȥѹ롤Ʊ̾Υƥॳ - ƱƯ롥ϼ¸uidѥ桼Ǥ - ¤Ƥ롥롼ȥǥ쥯ȥ᤹(롼ȥǥ쥯 - ѹ)ˡƤʤ - - mkdir(path[, mode]) - - modeǻꤵ줿⡼ɤĥǥ쥯ȥpath롥⡼ - umaskˤäƽ롥modeΥǥեͤ0777 - - open(path) - - pathФǥ쥯ȥꥹȥץ롥 - - rmdir(path) - - pathǻꤵ줿ǥ쥯ȥ롥ǥ쥯ȥ϶Ǥ - ɬפ롥 - -** Enumerable(⥸塼) - -ǤФ뷫֤Ԥʤ饹ΤMixinΥ⥸塼 -롼ɤ뤿ˤϡå`each'ɬפ롥 - -Methods: - - collect - - ǤФƥ֥åɾ̤ƴޤ֤ - - find - - ǤФƥ֥åɾͤˤʤäǽǤ֤ - - find_all - - ǤФƥ֥åɾͤǤäǤƴޤ - ֤ - - grep(pattern) - - =~ patternפΩƤǤޤ֤ - 졼ȤѤ줿Ͼ嵭ξΩǤФƥ֥ - ¹Ԥ롥 - - includes(val) - - val`=='δطˤǤĻ֤ - - index(val) - - val`=='δطˤ륪֥Ȥܤ˸줿֤ - ֺǽǤ0ˤʤ롥Ǥ¸ߤʤˤnil֤ - ʤ饹ФƤϤޤ̣ʤ - - length - - Ǥο֤ - - min - - ǾǤ֤ƤǤߤ`<=>'åɤӤǤ - 뤳ȤꤷƤ롥 - - max - - Ǥ֤Ǥ`<=>'åɤӤǤ뤳Ȥ - Ƥ롥 - - reverse - - ƤǤս¤٤֤ - - sort - - ƤǤȤ֤ - -** Etc(⥸塼) - -/etcǥ쥯ȥʲξ뤿Υ⥸塼롥饹˥롼 -ƻȤȤǤ롥 - -Methods: -Single Methods: - - 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ȥ˥뤿Υƥ졼 - -** File(饹) - -ե륢ΤΥ饹åopen()롥ޤ -饹ðۥåɤȤtestΥեƥȱ黻Υåɤ -Ƥ(FileTest⥸塼Υåɷ) - -SuperClass: IO - -Methods: - - atime - - եκǽ֤ - - ctime - - եκǽơѹ֤ - - chmod(mode) - - եΥѡߥåѹ(cf chmod(2)) - - chown(owner, group) - - եνͭԤȥ롼פѹ(cf chown(2))nil-1 - ꤹ뤳ȤˤäƽͭԤ䥰롼פߤΤޤѤʤǤ - ȤǤ롥 - - eof - - եνüã˿֤ - - lstat - - ե˴ؤStat¤Τ֤lstatϥե뤬ܥ - ǤХΤΤ˴ؤStat¤Τ֤¤ - ƤˤĤƤstatȤΤȡ - - mtime - - եκǽ֤ - - rewind - - եΥեݥΰ֤Ƭ˰ư롥 - - path - - եΥѥ֤̾ - - seek(offset, ptrname) - - եΥեݥΰ֤offset˰ư롥ptrname - 012Τ줫Ǥäơ줾եƬ߰֡ - եνüΤΤ줫Ф - - stat - - ե˴ؤStat¤Τ֤(Struct ) - - struct stat - dev # ե¸ߤǥХ - ino # եi-nodeֹ - mode # ⡼ - nlink # ϡɥο - uid # ͭԤΥ桼ID - gid # ͭԤΥ롼ID - rdev # ǥХID(ڥեΤ) - size # ե륵(byte) - blksize # ե륷ƥˤŬڤʥ֥å - blocks # ֥å - atime # ǽ - mtime # ǽ - ctime # ǽѹ - end - - ܺ٤fstat(2)ȤΤȡƥƤ - stat¤Τ˳Фʤ0ꤵƤ롥 - - tell - - եθߤΥեݥΰ֤֤ - - truncate(length) - - եڤΤƤƺlengthХȤˤ롥եwrite⡼ - ɤǥץƤʤФʤʤ - -Single Methods: - - atime(filename) - - filenameκǽ֤ - - ctime(filename) - - filenameκǽơѹ֤ - - chmod(mode, path, file..) - - եΥѡߥåѹ(cf chmod(2))ѹե - ֤fileˤϥ磻ɥɤ - - chown(owner, group, file..) - - եνͭԤȥ롼פѹ(cf chown(2))nil-1 - ꤹ뤳ȤˤäƽͭԤ䥰롼פߤΤޤѤʤǤ - ȤǤ롥ѹե֤fileˤϥ磻ɥɤ - - - link(old, new) - - oldؤΥϡɥnew롥link(2)Ʊ¤롥 - - mtime(filename) - - filenameκǽ֤ - - readlink(path) - - ܥåpathƤʸȤ֤ - - rename(from, to) - - ե̾fromtoѹ롥rename(2)ȡtoȤ̾ - Υե뤬¸ߤˤϤޤΥե뤬롥 - - stat(filename) - - filenameΥեStat¤Τ֤ - - symlink(old, new) - - oldؤΥܥånew롥 - - truncate(path, length) - - pathǻꤵ줿եڤΤƤƺlengthХȤˤ롥 - - type(filename) - - filenameΥեΥפɽʸ֤ʸ"file" - "directory""characterSpecial""blockSpecial""fifo" - "link""socket"ΤΤ줫ĤǤ롥 - - unlink(file..) - - ե롥ǥ쥯ȥκˤDir.rmdirȤȡ - fileˤϥ磻ɥɤ - - utime(atime, mtime, file..) - - եΥatimeˡmtimeꤹ롥 - atimemtimeϿޤTime饹ΥǤʤФʤ - fileˤϥ磻ɥɤ - - - ʳFileTest⥸塼ΥåɤðۥåɤȤƻġ - -** FileTest(⥸塼) - -եƥѥåɤ⥸塼롥롼ɤѤ뤳 -Ǥ롥 - -Methods: -Single Methods: - - b(filename) - - filenameΥե뤬֥åڥեǤ - - - c(filename) - - filenameΥե뤬饯ڥեǤ - ֤ - - executable(filename) - x(filename) - - filenameΥե뤬¹Բǽλ֤ - - exists(filename) - e(filename) - a(filename) - - filenameΥե뤬¸ߤ֤ - - G(filename) - - filenameΥեgid¸롼פgidƱ֤ - - isdirectory(filename) - d(filename) - - filenameǥ쥯ȥλ֤ - - isfile(filename) - f(filename) - - filenameΥե뤬̾եλ֤ - - islink(filename) - l(filename) - - filenameΥե뤬ܥåǤ֤ - - ispipe(filename) - p(filename) - - filenameΥե뤬̾Ĥѥ(FIFO)Ǥ֤ - - issocket(filename) - S(filename) - - filenameΥե뤬åȤǤ֤ - - owned(filename) - O(filename) - - filenameΥե¸桼ͭƤ֤ - - readable(filename) - r(filename) - - filenameΥեɤߤȤǽλ֤ - - R(filename) - - filenameΥեuid/gidɤߤȤǽλ֤ - - setuid(filename) - u(filename) - - filenameΥեsetuidӥåȤåȤƤ֤ - - setuid(filename) - g(filename) - - filenameΥեsetuidӥåȤåȤƤ֤ - - size(filename) - s(filename) - - filenameΥե뤬¸ߤե礭֤¸ߤ - ʤnil֤ - - sticky(filename) - g(filename) - - filenameΥեstickyӥåȤåȤƤ֤ - - writable(filename) - w(filename) - - filenameΥե뤬uid/gidǽ߲ǽλ֤ - - W(filename) - - filenameΥե뤬߲ǽλ֤ - - z(filename) - - filenameΥե뤬¸ߤ礭0Ǥ֤ - -** Fixnum(饹) - -31bit(ޥlongĹ-1 bit)Υ饹builtin classǤ롥 -饹pointer¨ͤǤ뤿call by valueǸƤӽФħŪ -Ǥ(¾Υ饹call by reference)黻η̤31bitۤ -ϼưŪBignum(̵¿Ĺ)˳ĥ롥 - -ƥ졼upto()downto()step()Ϸ֤ΤѤ졤̤ -Range饹Ѥ®Ǥ롥 - -SuperClass: Integer - -Methods: - - self + other - self - other - self * other - self / other - self % other - self ** other - - ѱ黻줾¡ѡ;Ѿ֤ - - ~ self - self | other - self & other - self ^ other - - ӥåȱ黻줾ӥåȿž¡ѡ¾Ū¤ - ֤ - - self << bits - self >> bits - - եȱ黻줾bitsӥåȤ˥ӥåȥեȤԤʤ - - self .. max - - ϰϻꡥself maxޤǤϰϥ֥Ȥ֤ - - downto(min) - - ƥ졼selfminޤDz˷֤ - - id2name - - ͤIDȤߤʤơʸ֤ʸ - ¸ߤʤnil֤ - - step(max, step) - - ƥ졼selfmaxޤstepѲʤ顤֤ - - to_f - - selfFloatѴΤ֤ - - to_i - - selfΤޤ֤ - - upto(max) - - ƥ졼selfmaxޤǷ֤ - -** Float(饹) - - ưΥ饹 - -SuperClass: Numeric - -Methods: - - self + other - self - other - self * other - self / other - self % other - self ** other - - ѱ黻줾¡ѡ;Ѿ֤ - - self == other - self > other - - ӱ黻 - - coerce(num) - - numfloatѴ롥FloatǤ¾ο - FixnumBignumǤ롥 - - to_f - - selfΤޤ֤ - - to_i - - selfѴ̤֤ - -Single Methods: - - new(float) - - floatƱͤĿFloat֥Ȥ֤ - -** GC(⥸塼) - -RubyȤ߹ߤgarbage collectorԤʤΥ⥸塼롥Υ -塼ΥåɤѤ뤳ȤˤäơŪGCߤꡤGCε -륿ߥ椷Ǥ롥 - -Methods: - - garbage_collect - - GCϤ롥GC.startפƱ - -Single Methods: - - disable - - GCػߤ롥 - - enable - - GCĤ롥 - - start - - GCϤ롥 - -** Glob(饹) - -磻ɥɤΥ饹磻ɥɤΥƥ<..>ȤǤ -롥ɽȤۤƱ褦˻Ȥ뤬ϵǽʤ -ɥɤŸǽ롥 - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - self =~ string - - 磻ɥɤʸ˥ޥåˤϿʤ - nil֤ - - each - - 磻ɥɤ˥ޥåե̾Ϳ륤ƥ졼 - -Single Methods: - - new(string) - - ʸ磻ɥɤѴ֥Ȥ֤ - -** Hash(饹) - -Ϣ뤤ϥϥåɽǤդΥ֥ȤźȤǤΥ -Ǥ롥Ϣ֥ȤϰŪˤϢ - - ``{a=>b,..}'' - -ǹԤʤ롥 - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - self [key] - - keyȤ֤ͤ - - self [key]= value - - keyȤơvalueǼ롥valueȤnilꤹȤ - keyФܤκȤʤ롥ĤޤꡤHashͤȤnil - ȤϤǤʤ - - clear - - Ϣˤ롥 - - delete(key) - - keyȤȤ롥 - - delete_if - - Ǥ륤ƥ졼key::valueȤڥͿơ֥ - ɾͤλܤ롥 - - each - each_pair - - key::valueʤڥͿ륤ƥ졼 - - each_key - - ƤkeyФƷ֤ƥ졼 - - each_value - - ƤvalueФƷ֤ƥ졼 - - has_key(key) - includes(key) - - keyϢ¸ߤ֤ - - has_value(value) - - valueͤȤȤϢ¸ߤ֤ - - indexes(ary) - indexes(key-1, ..., key-n) - - 1ܤηǤȤƼơǤȤ - Ǥޤ֤2ܤηǤϳưͤȤ - ޤ֤ - - keys - - Ϣ¸ߤ륭Ƥޤ֤ - - length - size - - ϢǤο֤ - - shift - - ϢǤļФ()key::valueʤڥ - ֤ - - to_a - - Ϣkey-valueڥǤȤ֤ - - values - - Ϣ¸ߤƤޤ֤ - -Single Methods: - - Hash[key, value..] - - ܤΰkeyܤΰvalueȤϢ - 롥 - - new - - ()Ϣ֥Ȥ֤ - -** Integer(饹) - -饹ºݤϤ礭ˤäFixnumBignumĤΥ֥饹 -Ǽ¸Ƥ롥IntegerϤΥѡ饹Ȥʤݥ饹Ǥ -롥RubyǤϤۤȤɤξ硤FixnumBignumζ̤ɬפʤߤѴ -ϼưŪ˹Ԥʤ롥ӥåȤߤʤˤϡ̵¤Ĺ -ĥӥåȹͤƹʤ - -SuperClass: Numeric - -Methods: - - self[idx] - - idxӥåܤåȤƤ1åȤƤʤ - 0֤ - - chr - - οɤȤʸޤ1ʸʸ֤̤ - Ĺ1ʾʸˤĤơδطΩ롥 - - str[0].chr == str[0,1] - - ʸϰ(0..255)ˤʤ㳰ȯ롥 - - is_integer - - Ĥ֤ - -** IO(饹) - -ϤΤδܥ饹 - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - self << object - - objectϤ롥objectʸǤʤˤϥåto_sѤ - ʸѴ롥selfͤȤΤǡC++Τ褦`<<' - ϢȤ롥 - - : - - $stdout << 1 << " is a " << Fixnum << "\n" - - close - - ϥݡȤ롥ʸΤΥ֥ȤФ - ϥ顼ˤʤ롥 - - each - - Ԥɤ߹Ǥ뤿Υƥ졼Ԥζڤϥƥ - `$/'ˤäѹǤ롥ɤ߹ʸϥƥѿ`$_' - ⥻åȤ롥 - - each_byte() - - ʸɤ߹Ǥ뤿Υƥ졼ʸʸɤɽ - FixnumǤ롥 - - fileno - to_i - - IO֥ȤȤäƤեǥץ(Fixnum)֤ - - flush - - Хåեեå夹롥 - - getc - - ɤ߹ǡɤ߹ߤˤϤʸ֤ե - νãˤnil֤ͥågetc() - $stdin.getcƱ̣Ǥ롥 - - gets - - ɤ߹ǡɤ߹ߤˤϤʸ֤ե - νãˤnil֤ - - isatty - - ϥݡȤttyǤ֤ - - puts(obj) - - objϤ롥self << objפƱ̣Ǥ롥 - - read([length]) - - lengthХɤ߹ǡʸ֤lengthά줿 - ˤϡƤΥǡɤ߹ࡥ - - readlines - - եɤ߹dzƹԤǤȤƤ֤ - - sync - - ߤνƱ⡼ɤ֤ͤƱ⡼ɤλϽϴ - θƽ˥Хåեեå夵롥 - - sync=(newstate) - - Ʊ⡼ɤꤹ롥 - - sysread(length) - - stdioͳread(2)ѤϤԤʤϤ줿ǡ - ޤʸ֤եνãˤnil֤ - read(2)ˤɬlengthХȤʸɤ߹ޤ櫓 - ǤϤʤgets()getc()ʤstdioͳåɤȺѤ - ȤϥХåեʤɤǻפư뤳Ȥ롥 - - syswrite(str) - - stdioͳˡwrite(2)ѤƽϤԤʤΥå - ϥХåեʤstdioƤ뤳ȤϰڹԤʤʤ - syswriteϼºݤ˽Хȿ֤print()printf() - syswrite()ѤΤϿ侩Ǥʤ - - write(str) - - strϤ롥ϤХȿ֤ - -** Kernel(饹) - -ƤΥ饹δ쥯饹RubyȤ߹ߤƤδؿåɤϤΥ饹 -Ƥ롥ؿåɤˤĤƤϡִؿפιܤȤΤȡ - -SuperClass: ʤ - -Methods: - - ! self - - ꡥNon-nilΥ֥Ȥξ˵(nil)֤Υ - ɤNil饹ǤϺ쿿֤ - - self == other - equal(other) - - ֥ȤΰȽꡥ쥷ФȰΰפ - ֤Kernel饹ǤΥ֥ȤƱλ - "=="åɤϳƥ֥Ȥ˱ƺɬפ - 롥"=="åɤˤϡhashåɤ⤽˹ - ƺɬפ롥 - - equal()åɤ"=="åɤ̾ǡ"=="Ǥ - ֥ȤƱȽԤʤѤ롥ä - equal()åɤϥ֥饹Ǻ٤ǤϤʤ - - self != other - - "=="ꡥ"=="åɤƤӽФƤΤǡϺ - ɬפϤʤ - - self =~ other - - ޥåǥեȤư"=="ƱǤ롥"=~"caseӤ - Ѥ롥 - - !~ - - "=~"ꡥ"=~"åɤƤӽФƤΤǡϺ - ɬפϤʤ - - self :: other - - selfotherǤȤassocڥ֤α黻ҤϱǤ - Τǡa::b::c (a::(b::c)) Ȳᤵ롥 - - is_nil - - ֥ȤnilǤ뤫ɤKernel饹ǤϿ - Nil饹ǺƤ롥 - - id - - ƥ֥ȤФưդFixnum֤FixnumϼʬȤ - ΤǡidפƤƱ֥ȤǤ뤳Ȥݾڤʤ - Ĥޤꡤ - - obj1.id == obj2.id - - ΩƤ⡤ɤ餫FixnumǤСobj1obj2ƱǤ - Ȥϸ¤ʤξFixnumǤʤȤݾڤǤС2 - ĤΥ֥ȤƱǤ뤳Ȥϳμ¤Ǥ롥 - - hash - - ֥ȤΥϥå(Fixnum)֤Hash饹ǥȤʤ - ֥ȤǼΤѤƤ.A == BפΩ - ɬA.hash == B.hashפΩɬפΤǡ"==" - ˤɬ⤽˹碌ƺ뤳ȡ - - -** Math(⥸塼) - -ư黻ݡȤ륯饹Math⥸塼ƱΥå -ðۥåɤȤξƤΤǡðۥåɤƤӽФƻ -Ȥȡ饹˥롼ɤƻȤȤȤξǤ롥 - - : - - pi = Math.atan2(1, 1) * 4; - include Math - pi2 = atan2(1, 1) - -Methods: -Single Methods: - - atan2(x, y) - - С-ФϰϤX/YΥȤ֤ - - cos(x) - sin(x) - tan(x) - - 饸ɽ줿xλѴؿ֤ͤ - - exp(x) - - xλؿؿ֤ͤ - - log(x) - - xμп֤ - - log10(x) - - xξп֤ - - sqrt(x) - - xʿ֤xͤǤˤ㳰ȯ롥 - - cbrt(x) - - xΩ֤ - -** Module(饹) - -⥸塼Υ饹 - -SuperClass: Object - -Private Methods: - - attr(name[, public]) - - Υ⥸塼롼ɤ饹ΥФ - nameǻꤵ°ղä°Ф륢åɤ - 롥attr("attr")ϥ饹˰ʲ˼ɤɲä - ȤۤƱǤ롥 - - def attr; @attr; end - - άǽ2publicͿơĤͤnilǤʤ - Ϥ°ˤ°åɤѰդ졤ǽˤ - 롥attr("attr", TRUE)ϥ饹˰ʲΥɤɲä - ȤۤƱǤ롥 - - def attr; @attr; end - def attr=(val); @attr = val; end - - °åɤ뤳Ȥˤäơư - ѹǤ롥㤨 - - attr("test", TRUE) - def test=(val) - print("test was ", @test, "\n") - print("and now is ", @test = val, "\n") - end - - Τ褦°ͤɽ褦ʤȤǽǤ롥attr - ϥåɤǤƤϡǥեȤΥ - åɤʤ - -Methods: - - include(module[, module..]) - - ǻꤷ⥸塼롼ɤơåɡ - ä롥饹⥸塼̤Υ⥸塼롼ɤ뤳 - Ȥˤäơꤵ줿¿ŷѾ(Mixin)¸Ǥ롥 - - to_s - - ⥸塼ʸɽ֤⥸塼ξʸɽϥ - 塼̾Ǥ롥 - - private(name[, name..]) - - nameǻꤵ줿åɤؿǤƤӽФǽˤ롥 - ǤprivateåɤǤˤϲ⤷ʤ - - public(name[, name..]) - - nameǻꤵ줿åɤ̾ǸƤӽФǽˤ롥Ǥ - publicåɤǤˤϲ⤷ʤ - -** Nil(饹) - -ɽ֥nilΥ饹ѿ()nilNil饹ͣΥ -Ǥ롥 - -SuperClass: Kernel - -Methods: - - self + other - - otherưʸǤother֤ - - ! self - - ˿֤ - - is_nil - - ˿֤ - -** Numeric(饹) - -̤ɽݥ饹 - -SuperClass: Object - -Included Modules: Comparable - -Methods: - - + self - - ֥selfΤΤ֤ - - - self - - 0 - selfפ֤֥ͤ饹ǤΨŪ˺뤳 - ȤԤ롥 - - abs - - ֤ͤ - - divmod(other) - - Ⱦ;Υڥ֤ - - next - - ο֤οȤϤοۤǾǤ롥 - -** Object(饹) - -Ƥ̾說饹Υѥ饹̾說饹ΥΰŪʿ -Ƥ롥Υ饹Υ֥饹Ǥʤ饹KernelNilȡ -Ȥ߹ߴؿƤBuiltinǤ롥 - -SuperClass: Builtin - -Methods: - - extened(module[, module..]) - - ǻꤷ⥸塼self˥롼ɤ롥⥸塼 - ƤåɤðۥåɤȤɲä롥 - - initialize - - ֥Ȥ˸ƤӽФ롥ǥեȤϲ⤷ - ֥饹ɬפ˱ƺ뤳ȤԤƤ롥 - - is_member_of(class) - - ֥self饹classΥǤ֤ - - is_kind_of(class) - - ֥self饹classΥ֥饹Υ - ֤ - - clone - - ֥Ȥʣ롥¨ͤǤFixnum饹 - ʳΥ饹ξ硤obj.equal(obj.clone)פϵǤ뤬¿ - ξobj == obj.cloneפϿǤ롥 - - to_s - - ֥Ȥʸɽ֤ΥåɤŪprint() - format()åɤѤƤ롥 - - to_a - - ֥ȤѴ롥ͥ륯饹Ƥ - եȤϡΥ֥ȼȤޤ1Ǥ֤ - -** Process(⥸塼) - -ץ˴ؤԤʤΥ⥸塼롥Math⥸塼Ʊͤ -ƤΥåɤðۥåɤȤƤ̾ΥåɤȤƤȤ롥 -Processϥץ֥ȤΥ饹ǤϤʤơץΥ -ɤޤȤΤǤ뤳Ȥդ뤳ȡ - -Methods: -Single Methods: - - egid - - ץθߤμ¸GID֤ - - egid=(gid) - - ץθߤμ¸GIDgid˥åȤ롥 - - euid - - ץθߤμ¸UID֤ - - euid=(uid) - - ץθߤμ¸UIDuid˥åȤ롥 - - getpgrp([pid]) - - pidǻꤵ줿ץ߽°Ƥץ롼פid - ֤pidάpid0Ϳϸ¹ԤƤ - оݤˤ롥 - - getpriority(which, who) - - whichwhoǻꤵץץ롼ס桼θ - ̤֤ͥܺ٤getpriority(2)ȡProcess⥸塼 - ǤwhichȤƻǤPRIO_PROCESSPRIO_PGRP - PRIO_USERƤ롥 - - gid - - ץθߤμGID֤ - - gid= - - ץθߤμGIDgid˥åȤ. - - pid - - ץΥץID֤ϥƥѿ`$$'ͤƱ - 롥 - - ppid - - ƥץΥץΥץID֤UNIXǤľܤοƥץ - λ硤ƥץpid1(initpid)ˤʤ롥 - - setpgrp(pid, pgrp) - - pidǻꤵ줿ץΥץ롼פpgrpˤ롥pid0 - Ϳȸ¹Υץоݤˤ롥 - - setpriority(which, who, prio) - - whichwhoǻꤵץץ롼ס桼θ - ̤ͥprioꤹ롥ܺ٤setpriority(2)ȤΤȡ - - uid - - ץθߤμUID֤ - - uid= - - ץθߤμUIDuid˥åȤ. - -** Range(饹) - -ϰϥ֥ȤΥ饹ϰϥ֥Ȥ`..'黻Ҥˤä졤 -ŪˤϰʲΤ褦ʻȤ - - for i in 1..5 - ... - end - -ξϰʲ®. - - 1.upto(5) { - ... - } - -ϰϥ֥Ȥ`..'黻ҤξդComparableޤ९饹Υ -ǤвǤʤϰϤϻȽޤळȤդ -. - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - self =~ other - - selfotherƱ饹Фϰϥ֥Ȥǡϰ - other(start <= other <= end)֤case - ϰϻꤹǤ롥㤨 - - case i - when 1, 3..5 - ... - end case - - Τ褦ʥɤȤǤ롥 - - each - - ϰ¸ߤ륪֥ȤͿ륤ƥ졼forΤ - Ѥ롥 - - end - - ϰϤν֤ - - start - - ϰϤλ֤ - -** Regexp(饹) - -ɽΥ饹ɽΥƥ/.../ȤɽưŪ -뤿ˤ - - Regexp.new(ʸ) - -Ȥ롥String饹`=~'ϤȤ¿Υåɤɽ -ؤʸͿ줿ˤŪɽΤǡ -ȤȻפ䡤ɽʸʸζ̤Ū˻ -ꤷʤɰʳŪȻפȤϾʤϤ - -SuperClass: Object - -Methods: - - self =~ string - - ɽʸ˥ޥå硤ޥå֤֤ޥå - ʤnil֤ - - ~ self - - $_ =~ selfפƱ - -Single Methods: - - complie(string[, casefold]) - new(string[, casefold]) - - ʸɽѴ֥Ȥ֤άǽ2 - Ϳ졤ͤnilǤʤˤϡ줿ɽ - Ȥϥƥѿ`$='ͤ˴ؤ餺ޥåʸ - ʸΰ㤤̵뤹롥 - - quote(str) - - ʸɽǰ̣ʸפ롥ʸ - ֤ - -** String(饹) - -ʸ饹Rubyʸϥ̥륿ߥ͡ȤǤϤʤΤǡХʥǡ -ⰷ롥äƤɤ餫ȤñʤʸȤХǤ롥 -λۤ˴Ťơɽ˴ؤåɰʳ2byteϤʸռ -ƤʤϺԤμȴǤϤʤտŪˤƤΤǤ( -Ƥ) - -SuperClass: Object - -Included Modules: Comparable, Enumerable - -Methods: - - self + other - - ʸϢ롥Ϣ뤵줿ʸ֤ - - self * times - - ʸη֤㤨 - - "x" * 4 == "xxxx" - - Ǥ롥 - - self == other - self > other - - ʸӡƥѿ$=nilǤʤˤʸʸ - ̤ӤԤʤ - - self =~ other - - ʸΥޥåotherɽʸotherʸξ - ưŪɽѴ롥ޥåϥޥå֡ - ʤänil֤롥 - - ~ self - - $_ =~ selfפƱ - - self[nth] - self[beg..end] - self[beg,len] - - ƤμФ1ܤηǤnthХܤΥǡFixnumȤ - ֤2ܤηǤbegХܤendХܤޤǤʬʸ - ֤(ξüޤ)3ܤηǤbegХܤlenХ - ʬʬʸ֤ - - self[nth] = val - self[beg..end] = val - self[beg,len] = val - - Ƥι1ܤηǤnthХܤΥǡval () - 롥2ܤηbegХܤendХܤޤǤʬʸ - valȤͿ줿ʸ֤롥3ܤηbeg - ܤlenХʬʬʸvalȤͿ줿ʸ - ֤롥 - - capitalize - - ʸκǽʸ(줬ե٥åȤǤ)ʸ - ѴĤʸΥե٥åȤʸ֤롥 - - chop - - ʸκǸΥХȤڤȤʸѹ뤳Ȥ - դ뤳ȡ - - crypt(salt) - - crypt(3)ѤưŹ沽ʸ֤salt2ХȰʾĹ - ǤդʸǤ롥 - - delete(str) - - ʸΤstr˴ޤޤʸ롥ʸλtr - ƱͤǤꡤa-babޤǤϰϤƬ^ʸ( - ޤƤʤΤ)̣롥ʸѹ뤳Ȥ - դ뤳ȡ - - downcase - - ʸΥե٥åȤƾʸ֤ʸ֤ - - each - - ʸ1Ԥɤ߹Ǥ륤ƥ졼 - - each_byte - - ʸΤ줾ΥХȤˤĤƷ֤ƥ졼 - - gsub(pattern[, replace]) - - ʸpattern˥ޥåʬreplace֤롥 - ʸreplace&\0ϥޥåʸˡ\1..\9nܤ - ̤Ƥ֤롥replaceά줿ˤϥ - 졼Ȥư֥åɾִ̤롥 - - hex - - ʸ16ʿɽʸȲᤷơѴ롥 - - index(substr[, pos]) - - substrǽ˽и֤֤posͿȤΰ֤鸡 - Ϥ롥Ĥʤˤnil֤ - - intern - - ʸ˰դб֤ʸϥʥʸޤǤϤ - ʤ - - length - size - - ʸĹ(Хȿ)֤ - - ljust(width) - rjust(width) - center(width) - - ʸ줾졤ͤᡤͤᡤwidthʸ - ֤ʸĹwidthĹϸʸ֤ڤ - ʤ - - next - - selfendޤǡּΡʸ֤ʸȤϿϿ - ȤơʸϱʸȤä夬νԤʤ줿 - ΤǤ롥 - - "aa".next => "ab" - "99".next => "100" - "a9".next => "b0" - - oct - - ʸ8ʿɽʸȲᤷơѴ롥8ʿ - /[0-7]+/ǤꡤʸƬ餳Υѥ˥ޥå - ʬѴ롥ƤϤޤʤʸФ - Ƥ0֤perlȤϰäʸ0xϤޤäƤ뤫Ȥ - 16ʿȸʤƤ줿ϤʤƬ08ʿ - ǧ졤0֤ - - reverse - - ʸγƥХȤս¤٤ʸ֤ʸ2ХȤ - ʸޤǤƤ⤪ʤ˥Хñ̤ȿž롥 - split2ХʸΤǡ2Хʸޤʸʸ - ñ̤ȿžˤ - - "ʸ".split(//).reverse.join("") - - ȤФ褤 - - rindex(substr[, pos]) - - ʸsubstrǸ˽и֤֤posͿȤΰ - Ǹλ롥Ĥʤˤnil֤indexȤ - 1)ʸ鸡롥2)substrȤɽդ - ʤ2Ǥ롥 - - split([sep[, limit]]) - - ʸsepǻꤵ줿ѥˤäơեɤʬ䤹롥 - sepά줿ΥǥեȤϥƥѿ`$;'ͤѤ - 롥limitꤵ줿ˤϺlimitĤΥեɤʬ䤹롥 - split()ʬ䤵줿ʸޤ֤sepǻꤵ줿ѥ - ʸȥޥåʸ1ʸĤʬ䤵롥 - - squeeze([str]) - - ʸΤstr˴ޤޤʸϢ³Ƥ硤ʸ˰ - ̤롥strά줿硤٤ƤʸоݤȤ롥ʸ - λtrƱͤǤꡤ`a-b'abޤǤϰϤƬ`^' - ʸ(ޤޤƤʤΤ)̣롥ʸ - 뤳Ȥդ뤳ȡ - - strip - - ʸζ - - sub(pattern[, replace]) - - ʸpattern˥ޥåǽʬreplace֤롥 - ʸreplace&\0ϥޥåʸˡ\1..\9 nܤ - ̤Ƥ֤롥replaceά줿ˤϥ - 졼Ȥư֥åɾִ̤롥 - - sum([bits]) - - ʸbitsӥåȤΥå롥άͤ16Ǥ롥ruby - ǤϰʲΥɤSystem V`sum'ץƱͤ롥 - - while gets() - sum += $_.sum - end - sum %= 65536 - - swapcase - - ʸΥե٥åȤΤʸʸˡʸʸ - ֤롥 - - to_f - - ʸFloatѴ롥 - - to_i - - ʸ10ʿɽʸȲᤷơѴ롥 - - toupper - - ʸΥե٥åȤʸ֤ʸ֤ - tr("a-z", "A-Z")꾯® - - tolower - - ʸΥե٥åȤƾʸ֤ʸ֤ - tr("A-Z", "a-z")꾯® - - tr(search, replace) - - ʸsearchʸ˴ޤޤʸ¸ߤСreplaceʸ - бʸ֤롥replaceʸά줿 - ϶ʸͿ줿ȸʤreplaceʸsearchʸ - ûreplaceʸκǸʸ֤Ƥȸ - searchʸûˤбʸΤʤreplace - ñ̵뤵(BSDtrư) - - searchʸreplaceʸ`a-b'Ȥ줿硤 - abޤǤϰϤʸASCIIξǻꤷȤˤʤ롥 - searchʸκǽʸ`^'Ǥ硤³ʸ*ޤ - ʤ*ʸִоݤˤʤ롥 - - tr(1)εǽΤʸ뵡ǽϢ³ʸ̤ - ǽ̤Υåɤʬ䤵Ƥ롥εǽˤĤƤ - deletesqueezeȤΤȡ - - ؤΤᡤstr.tr(src,repl).squeeze(repl)å - tr_s(src,repl) Ƥ롥 - - unpack(template) - - ʸtemplateʸˤäƥѥåǤ - ޤ֤templateʸArray饹packåɤȤ - ƱͤǤ롥 - - a ASCIIʸ(³nullʸ䥹ڡĤ) - A ASCIIʸ(³nullʸ䥹ڡ) - b ӥåȥȥ(̥ӥåȤ̥ӥå) - B ӥåȥȥ(̥ӥåȤ鲼̥ӥå) - h 16ʸ(̥˥֥뤬) - H 16ʸ(̥˥֥뤬) - c char - C unsigned char - s sort - S unsigned sort - i int - I unsigned int - l long - L unsigned int - n ͥåȥХȥshort - N ͥåȥХȥlong - f ñư(¸) - d ư(¸) - x 1ХɤФ - X 1Хȸ - @ а֤ؤΰư - - rubyunpackperlȰäƥåηǽʤȤ - դ뤳ȡ - - - upcase - - ʸΥե٥åȤʸ֤ʸ֤ - - upto(end) - - selfϤޤäơendޤǡּΡʸͿ륤ƥ졼 - ʸȤstr.nextͿʸǤ롥 - - ΥåɤRange:eachѤƤΤǡʲΤ褦ʽ - ǽǤ롥 - - for i in "a" .. "ba" - print(i, "\n"); - end - - a, b, c, ... aa, ... az, baޤǤƹԤ˽Ϥ롥 - - - դʤФʤΤϡνλȽ羮طǤϤʤ - `=='ȽꤵƤ뤿ᡤ`..'黻Ҥκդͤ³ʸ˱ - դʸޤޤƤʤʲΤ褦ʾ̵¥롼פ - ٤äƤޤ - - for i in "0" .. "1a" - print(i, "\n"); - end - - ԤϤȤˤäǤƨƤ褦ȤƤȹͤ - ⤤뤫⤷ʤο¬ - -Single Methods: - - new(string) - - stringƱƤĿʸ֤ - -** Struct(饹) - -¤Υ饹ʣΥǡޤȤѤ(: Time::times) -ǡޤȤˤ饹Ѥ뤳Ȥ⤢뤬(: select) -¤ΤȤ٤ϰʲΤ褦ʾǤ롥 - - (1) Ǥο - - ǤοưΤϹ¤ΤȤΤˤϸʤ - - (2) Ǥο¿ - - ʹ֤٤ưפ˰복ǰο7ĤޤǤǤȤ⤬롥 - β˽СǤ4İʾ夢ǡξѤ - 硤ǿ*2(ĤޤꥪեåȤȤΰ̣)7ۤ롥äơ - Τ褦ʾˤϹ¤ΤȤä䤹Ȼפ롥 - - (3) Ʊ̤ʤ - - ¤Τ㴳Ȥ⤤Τǡ®٤ˤʤ - (㤨Ʊ̤ʤ)Ϲ¤ΤλѤŬڤǤʤ - ǽ롥 - -ƹ¤Τˤϥ̾Ʊ̾ΰΤʤåɤ롥 - -ܥɥǡ¤Τɽ뤿ˤϰʲηȤ - - struct ¤̾ - ... - end - -ץǤηǹ¤Τ櫓ǤϤʤ - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - self[idx] - - idxλidxܤǤ֤idxʸλidxƱ̾ - ΥФǤ֤ - - values - - ¤ΤΥФͤǤ˻֤㤨аʲΥɤ - ʬpasswdȥϤ뤳ȤǤ롥 - - print(Etc.getpwuid().values.join(":"), "\n") - - νϤ`grep "$USER" /etc/passwd'νϤ;ʬʥեɤ - Ĥ(ƥˤäưۤʤ)ʳƱǤ롥 - -Single Methods: - - new(name, member::value..) - - nameȤ̾ŤΤ롥memberϹ¤ΤΥФ - ɽʸǤꡤvalueϤͤǤ롥줿¤Τϥ - Фǻꤵ줿̾ðۥåɤƤơΥå - ˤäƥФƤ뤳ȤǤ롥 - -** Time(饹) - -֤ɽ饹羮ӤʤɤǤ롥Time.nowǸߤλ֤뤳 -Ǥ롥ޤեΥॹפåɤͤ⤳Υ -ΥǤ롥 - -SuperClass: Object - -Included Modules: Comparable - -Methods: - - self <=> other - - otherTimeΥͿ줿 - ˤ1970ǯ 1 1 00:00:00 GMTÿǤ - ƻȤӤԤʤ - - asctime - ctime - to_s - - date(1)ʸѴ롥 - - gmtime - - ॾνԤʤʤGMTǤλ롥Υå - ȤäTime饹ΥϡʸλѴGMT - ԤʤgmtimeϼʬȤ֤ - - ɥλɽˤ - - print(Time.now.gmtime, "\n") - - ȤФ褤 - - localtime - - ॾνԤʤä(ǥե)localtime - ϼʬȤ֤ - - to_i - tv_sec - - 1970ǯ 1 1 00:00:00 GMTޤǤÿ֤ - secondʬǤ⤢롥 - - sec - min - hour - mday - year - wday - yday - zone - isdst - - ŪݻƤtm¤ΤƤ֤zoneʳ֤ - zoneϥॾɽʸ֤(cf localtime(3)) - - strftime(format) - - formatʸ˽äʸѴ̤֤format - ʸȤƻǤΤ ʲ̤Ǥ롥 - - %A ̾(Sunday, Monday,..) - %a ξά̾(Sun, Mon,..) - %B ̾(January, February,..) - %b ξά̾(Jan, Feb,..) - %c ɽ(cf ctime(3)) - %d ʿǤ(01-31) - %H 24λ(00-23) - %I 12λ(01-12) - %j ǯ̻(001-366) - %M ʬ(00-59) - %m ɽ(01-12) - %p ޤϸ(AM,PM) - %S (00-61) - %U ɽǽ1 - Ϥޤ(00-53) - %W ɽǽη1 - Ϥޤ(00-53) - %w ɽ0(0-6) - %X (: 15:01:06) - %x (: Fri Jan 14 1994) - %Y ɽ - %y β2(00-99) - %Z ॾ - %% % - - usec - tv_usec - - micro secondʬ֤ - -Single Methods: - - now - - ߤλɽTime饹Υ롥 - - at(time) - - timeƱɽTime饹Υ롥time - Time饹Υ뤤Ͽ(/ư)Ǥꡤ - ξ1970ǯ 1 1 00:00:00 GMTÿǤȤƻ - 롥 - - times - - ߤΥץȤλҥץ桼/ƥCPU - ѻ¤ΤȤ֤(Struct) - - struct tms - utime # ץΥ桼 - stime # ץΥƥ - cutime # ҥץΥ桼 - cstime # ҥץΥƥ - end - - ֤ñ̤äǤꡤưͿ롥ܺ٤ - times(3)ȤΤȡ - -* CȤΥե - -rubyCȤΥեC줫Υ饹⥸塼 -CǵҤåɤrubyΥåɤθƤӽФ -졼θƤӽФ㳰ʤɤԤʤȤ롥ޤOSм -ԻCǽ줿⥸塼ɤ뤳Ȥ롥 - -Ūʥե˴ؤƤϡ̥ɥ(źեե C-IF) -ȤΤȡ - -* ʸˡ - -ʲϵBNFǵҤrubyʸˡǤ롥ΤʵҤparse.y -줿 - -PROGRAM : COMPEXPR - -COMPEXPR : EXPR (TERM EXPR)* [TERM] - -EXPR : MLHS `=' ARGS - | ASSOCS - | return ARGS - | fail ARGS - | yield ARGS - | identifier CALL_ARGS - | PRIMARY `.' identifier CALL_ARGS - | super CALL_ARGS - | undef FNAME - | alias FNAME FNAME - | include identifier (`,' identifier)* - | EXPR if EXPR - | EXPR while EXPR - | EXPR and EXPR - | EXPR or EXPR - | ARG - -ARG : LHS `=' ARG - | LHS OP_ASGN ARG - | ARG `..' ARG - | ARG `...' ARG - | ARG `+' ARG - | ARG `-' ARG - | ARG `*' ARG - | ARG `/' ARG - | ARG `%' ARG - | ARG `**' ARG - | `+' ARG - | `-' ARG - | ARG `|' ARG - | ARG `^' ARG - | ARG `&' ARG - | ARG `<=>' ARG - | ARG `>' ARG - | ARG `>=' ARG - | ARG `<' ARG - | ARG `<=' ARG - | ARG `==' ARG - | ARG `!=' ARG - | ARG `=~' ARG - | ARG `!~' ARG - | `!' ARG - | `~' ARG - | ARG `<<' ARG - | ARG `>>' ARG - | ARG `::' ARG - | ARG `&&' ARG - | ARG `||' ARG - | PRIMARY - -PRIMARY : `(' EXPR `)' - | LITERAL - | VARIABLE - | super `(' [CALL_ARGS] `)' - | super - | PRIMARY `[' [ARGS] `]' - | `[' [ARGS [`,']] `]' - | `{' [ (ARGS|ASSOCS) [`,'] ] `}' - | redo - | break - | continue - | retry - | return - | fail `(' ARGS `)' - | fail `(' `)' - | fail - | yield `(' ARGS `)' - | yield `(' `)' - | yield - | PRIMARY `{' [ITER_VAR] `|' COMPEXPR `}' - | identifier `(' [CALL_ARGS] `)' - | PRIMARY `.' identifier `(' [CALL_ARGS] `)' - | PRIMARY `.' identifier - | if EXPR THEN - COMPEXPR - (elsif EXPR THEN COMPEXPR)* - [else COMPEXPR] - end - | while EXPR TERM COMPEXPR end - | case COMPEXPR - (when ARGS THEN)+ - [else COMPEXPR] - end - | for ITER_VAR in EXPR TERM - COMPEXPR - end - | begin - COMPEXPR - [resque COMPEXPR] - [ensure COMPEXPR] - end - | class identifier `:' identifier - COMPEXPR - end - | module identifier - COMPEXPR - end - | def FNAME ARGLIST - COMPEXPR - end - | def SINGLETON `.' FNAME ARGLIST - COMPEXPR - end - -THEN : TERM - | then - | TERM then - -ITER_VAR : LHS - | MLHS - -MLHS : LHS `,' [LHS (`,' LHS)*] [`*' LHS] - -LHS : VARIABLE - | PRIMARY `[' [ARGS] `]' - | PRIMARY `.' identifier - -CALL_ARGS : ARGS - | ASSOCS - | ARGS `,' ASSOCS - | ARGS `,' `*' ARG - -ARGS : ARG - | ARGS `,' ARG - -ARGLIST : `('[identifier(`,'identifier)*][`*'identifier]`)' - | TERM - -SINGLETON : VARIABLE - | `(' COMPEXPR `)' - -ASSOCS : ASSOC (`,' ASSOC)* - -ASSOC : ARG `=>' ARG - -VARIABLE : VARNAME - | nil - | self - | `__FILE__' - | `__LINE__' - -LITERAL : numeric - | SYMBOL - | STRING - | REGEXP - | GLOB - -TERM : `;' - | `\n' - -겼ϻǧ롥 - -SYMBOL : `:'FNAME - | `:'VARNAME - -FNAME : identifier | `::' | `..' | `|' | `^' | `&' - | `<=>' | `==' | `=~' | `>' | `>=' | `<' | `<=' - | `<<' | `>>' | `+' | `-' | `*' | `/' | `%' | `**' - | `~' | `+@' | `-@' | `[]' | `[]=' - -VARNAME : GLOBAL - | `@'identifier - | identifier - -GLOBAL : `$'identifier - | `$'any_char - -STRING : `"' any_char* `"' - | `'' any_char* `'' - | ``' any_char* ``' - -REGEXP : `/' any_char* `/'[i] - -GLOB : `<' any_char* `>' - -* ռ - -RubyθͤϿ¿θαƶƤ. ʲˤΤϤμ -ʸǤ롥 - - C, Perl, CLU, Sather, CLOS, Eiffel, Icon, tcl, AWK, bourne shell, - Smalltalk, Emacs Lisp. - -ޤrubyθͤꤹ뤿˶ϤƲäʲˤ롥 - - ͷƣϺ¼Σţáغܣģţá - ʤֺ.ٻ(ɾά) -------------------------------------------------------- -Local variables: -fill-column: 70 -end: @@ -16,13 +16,13 @@ static void fmt_setup(); VALUE -Fsprintf(argc, argv) +f_sprintf(argc, argv) int argc; VALUE *argv; { struct RString *fmt; char *buf, *p, *end; - int i, blen, bsiz; + int blen, bsiz; VALUE result; #define FNONE 0 @@ -51,7 +51,7 @@ Fsprintf(argc, argv) } #define GETARG() \ - ((argc == 0)?Fail("too few argument."):(argc--, (argv++)[0])) + ((argc == 0)?Fail("too few argument."),0:(argc--, (argv++)[0])) fmt = (struct RString*)GETARG(); Check_Type(fmt, T_STRING); @@ -110,7 +110,7 @@ Fsprintf(argc, argv) case '5': case '6': case '7': case '8': case '9': flags |= FWIDTH; width = 0; - for (p; p < end && isdigit(*p); p++) { + for (; p < end && isdigit(*p); p++) { width = 10 * width + (*p - '0'); } if (p >= end) { @@ -150,7 +150,7 @@ Fsprintf(argc, argv) goto retry; } - for (p; p < end && isdigit(*p); p++) { + for (; p < end && isdigit(*p); p++) { prec = 10 * prec + (*p - '0'); } if (p >= end) { @@ -178,22 +178,39 @@ Fsprintf(argc, argv) { VALUE arg = GETARG(); int len; - char fbuf[32]; -#define MIN(a,b) ((a)<(b)?(a):(b)) str = obj_as_string(arg); - fmt_setup(fbuf, 's', flags, width, prec); + len = RSTRING(str)->len; if (flags&FPREC) { - CHECK(prec); - } - else if ((flags&FWIDTH) && width > RSTRING(str)->len) { - CHECK(width); + if (prec < len) { + CHECK(prec); + memcpy(&buf[blen], RSTRING(str)->ptr, prec); + blen += prec; + break; + } } - else { - CHECK(RSTRING(str)->len); + if (flags&FWIDTH) { + if (width > len) { + width -= len; + CHECK(width); + if (!(flags&FMINUS)) { + while (width--) { + buf[blen++] = ' '; + } + } + memcpy(&buf[blen], RSTRING(str)->ptr, len); + blen += len; + if (flags&FMINUS) { + while (width--) { + buf[blen++] = ' '; + } + } + break; + } } - sprintf(&buf[blen], fbuf, RSTRING(str)->ptr); - blen += strlen(&buf[blen]); + CHECK(len); + memcpy(&buf[blen], RSTRING(str)->ptr, len); + blen += len; } break; @@ -10,7 +10,7 @@ static char *rcsid = "$Header: /usr/ext/cvsroot/ruby/st.c,v 1.3 1994/12/09 01:28 #include "st.h" extern void *xmalloc(); -static rehash(); +static void rehash(); #define max(a,b) ((a) > (b) ? (a) : (b)) #define nil(type) ((type *) 0) @@ -25,8 +25,6 @@ static rehash(); * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins * allocated initially * - * DEFAULT_GROW_FACTOR is the amount the hash table is expanded after - * the density has reached max_density */ #define EQUAL(func, x, y) \ @@ -39,14 +37,13 @@ static rehash(); (table->hash == ST_NUMHASH) ? ((int) (key) % table->num_bins) :\ (*table->hash)((key), table->num_bins)) -st_table *st_init_table_with_params(compare, hash, size, density, grow_factor, - reorder_flag) -int (*compare)(); -int (*hash)(); -int size; -int density; -double grow_factor; -int reorder_flag; +st_table* +st_init_table_with_params(compare, hash, size, density, reorder_flag) + int (*compare)(); + int (*hash)(); + int size; + int density; + int reorder_flag; { st_table *tbl; @@ -55,7 +52,6 @@ int reorder_flag; tbl->hash = hash; tbl->num_entries = 0; tbl->max_density = density; - tbl->grow_factor = grow_factor; tbl->reorder_flag = reorder_flag; tbl->num_bins = size; tbl->bins = @@ -63,18 +59,19 @@ int reorder_flag; return tbl; } -st_table *st_init_table(compare, hash) -int (*compare)(); -int (*hash)(); +st_table* +st_init_table(compare, hash) + int (*compare)(); + int (*hash)(); { return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE, ST_DEFAULT_MAX_DENSITY, - ST_DEFAULT_GROW_FACTOR, ST_DEFAULT_REORDER_FLAG); } +int st_free_table(table) -st_table *table; + st_table *table; { register st_table_entry *ptr, *next; int i; @@ -111,10 +108,11 @@ if (PTR_NOT_EQUAL(table, ptr, key)) {\ }\ } +int st_lookup(table, key, value) -st_table *table; -register char *key; -char **value; + st_table *table; + register char *key; + char **value; { int hash_val; register st_table_entry *ptr; @@ -147,10 +145,11 @@ char **value; table->num_entries++;\ } +int st_insert(table, key, value) -register st_table *table; -register char *key; -char *value; + register st_table *table; + register char *key; + char *value; { int hash_val; st_table_entry *tbl; @@ -169,10 +168,11 @@ char *value; } } +int st_add_direct(table, key, value) -st_table *table; -char *key; -char *value; + st_table *table; + char *key; + char *value; { int hash_val; st_table_entry *tbl; @@ -181,10 +181,11 @@ char *value; ADD_DIRECT(table, key, value, hash_val, tbl); } +int st_find_or_add(table, key, slot) -st_table *table; -char *key; -char ***slot; + st_table *table; + char *key; + char ***slot; { int hash_val; st_table_entry *tbl, *ptr; @@ -203,13 +204,14 @@ char ***slot; } } -static rehash(table) -register st_table *table; +static void +rehash(table) + register st_table *table; { register st_table_entry *ptr, *next, **old_bins = table->bins; int i, old_num_bins = table->num_bins, hash_val; - table->num_bins = table->grow_factor*old_num_bins; + table->num_bins = 2*old_num_bins; if (table->num_bins%2 == 0) { table->num_bins += 1; @@ -234,8 +236,9 @@ register st_table *table; free((char *) old_bins); } -st_table *st_copy(old_table) -st_table *old_table; +st_table* +st_copy(old_table) + st_table *old_table; { st_table *new_table; st_table_entry *ptr, *tbl; @@ -275,10 +278,11 @@ st_table *old_table; return new_table; } +int st_delete(table, key, value) -register st_table *table; -register char **key; -char **value; + register st_table *table; + register char **key; + char **value; { int hash_val; st_table_entry *tmp; @@ -317,10 +321,11 @@ char **value; return 0; } +int st_foreach(table, func, arg) -st_table *table; -enum st_retval (*func)(); -char *arg; + st_table *table; + enum st_retval (*func)(); + char *arg; { st_table_entry *ptr, *last, *tmp; enum st_retval retval; @@ -346,14 +351,16 @@ char *arg; } ptr = ptr->next; free((char *) tmp); + table->num_entries--; } } } } +int st_strhash(string, modulus) -register char *string; -int modulus; + register char *string; + int modulus; { register int val = 0; register int c; @@ -23,7 +23,6 @@ struct st_table { int num_entries; int max_density; int reorder_flag; - double grow_factor; st_table_entry **bins; }; @@ -49,7 +48,6 @@ st_table *st_copy(); #define ST_DEFAULT_MAX_DENSITY 5 #define ST_DEFAULT_INIT_TABLE_SIZE 11 -#define ST_DEFAULT_GROW_FACTOR 2.0 #define ST_DEFAULT_REORDER_FLAG 0 int st_strhash(); @@ -13,10 +13,13 @@ #include "ruby.h" #include "re.h" +#define BEG(no) regs.beg[no] +#define END(no) regs.end[no] + #include <stdio.h> #include <ctype.h> -VALUE C_String; +VALUE cString; #define STRLEN(s) RSTRING(s)->len @@ -26,7 +29,7 @@ str_new(ptr, len) UINT len; { NEWOBJ(str, struct RString); - OBJSETUP(str, C_String, T_STRING); + OBJSETUP(str, cString, T_STRING); str->len = len; str->orig = Qnil; @@ -50,7 +53,7 @@ str_new3(str) struct RString *str; { NEWOBJ(str2, struct RString); - OBJSETUP(str2, C_String, T_STRING); + OBJSETUP(str2, cString, T_STRING); str2->len = str->len; str2->ptr = str->ptr; @@ -74,11 +77,11 @@ obj_as_string(obj) } str = rb_funcall(obj, pr_str, 0); if (TYPE(str) != T_STRING) - return Fkrn_to_s(obj); + return krn_to_s(obj); return str; } -VALUE +static VALUE str_clone(str) struct RString *str; { @@ -92,36 +95,41 @@ str_clone(str) return obj; } +VALUE +str_dup(str) + struct RString *str; +{ + return str_new(str->ptr, str->len); +} + static VALUE -Sstr_new(class, str) +str_s_new(class, str) VALUE class; struct RString *str; { - Check_Type(str, T_STRING); - { - NEWOBJ(str2, struct RString); - OBJSETUP(str2, class, T_STRING); + NEWOBJ(str2, struct RString); + OBJSETUP(str2, class, T_STRING); - str2->len = str->len; - str2->ptr = ALLOC_N(char, str->len+1); - if (str2->ptr) { - memcpy(str2->ptr, str->ptr, str->len); - } - str2->ptr[str->len] = '\0'; - str2->orig = Qnil; - return (VALUE)str2; + str = as_str(str); + str2->len = str->len; + str2->ptr = ALLOC_N(char, str->len+1); + if (str2->ptr) { + memcpy(str2->ptr, str->ptr, str->len); } + str2->ptr[str->len] = '\0'; + str2->orig = Qnil; + return (VALUE)str2; } static VALUE -Fstr_length(str) +str_length(str) struct RString *str; { return INT2FIX(str->len); } VALUE -Fstr_plus(str1, str2) +str_plus(str1, str2) struct RString *str1, *str2; { struct RString *str3; @@ -136,7 +144,7 @@ Fstr_plus(str1, str2) } VALUE -Fstr_times(str, times) +str_times(str, times) struct RString *str; VALUE times; { @@ -154,20 +162,6 @@ Fstr_times(str, times) return (VALUE)str2; } -extern VALUE C_Range; - -static VALUE -Fstr_dot2(left, right) - VALUE left, right; -{ - extern VALUE C_Range; - VALUE str; - - Check_Type(right, T_STRING); - str = range_new(left, right); - return str; -} - VALUE str_substr(str, start, len) struct RString *str; @@ -206,13 +200,6 @@ str_subseq(str, beg, end) if (end < 0) end = 0; } - if (beg > end) { - int tmp; - - Warning("start %d is bigger than end %d", beg, end); - tmp = beg; beg = end; end = tmp; - } - if (beg >= str->len) { return str_new(0, 0); } @@ -222,7 +209,7 @@ str_subseq(str, beg, end) len = end - beg + 1; if (len < 0) { - Fail("end %d too small(size %d)", end, str->len); + len = 0; } return str_substr(str, beg, len); @@ -230,10 +217,13 @@ str_subseq(str, beg, end) extern VALUE ignorecase; +#define STR_FREEZE FL_USER1 + void str_modify(str) struct RString *str; { + if (FL_TEST(str, STR_FREEZE)) Fail("can't modify frozen string"); if (str->orig == Qnil) return; str->ptr = ALLOC_N(char, str->len+1); if (str->ptr) { @@ -242,6 +232,32 @@ str_modify(str) str->orig = Qnil; } +static VALUE +str_freeze(str) + VALUE str; +{ + FL_SET(str, STR_FREEZE); + return str; +} + +static VALUE +str_frozen(str) + VALUE str; +{ + if (FL_TEST(str, STR_FREEZE)) + return TRUE; + return FALSE; +} + +VALUE +str_dup_freezed(str) + VALUE str; +{ + str = str_dup(str); + str_freeze(str); + return str; +} + VALUE str_grow(str, len) struct RString *str; @@ -275,7 +291,7 @@ str_cat(str, ptr, len) } static VALUE -Fstr_concat(str1, str2) +str_concat(str1, str2) struct RString *str1, *str2; { str2 = as_str(str2); @@ -283,7 +299,7 @@ Fstr_concat(str1, str2) return (VALUE)str1; } -static +static int str_hash(str) struct RString *str; { @@ -305,7 +321,7 @@ str_hash(str) } static VALUE -Fstr_hash(str) +str_hash_method(str) VALUE str; { int key = str_hash(str); @@ -321,7 +337,7 @@ str_cmp(str1, str2) UINT len; int retval; - if (ignorecase != Qnil) { + if (ignorecase != FALSE) { return str_cicmp(str1, str2); } @@ -334,7 +350,7 @@ str_cmp(str1, str2) } static VALUE -Fstr_equal(str1, str2) +str_equal(str1, str2) struct RString *str1, *str2; { if (TYPE(str2) != T_STRING) @@ -348,12 +364,12 @@ Fstr_equal(str1, str2) } static VALUE -Fstr_cmp(str1, str2) +str_cmp_method(str1, str2) VALUE str1, str2; { int result; - Check_Type(str2, T_STRING); + str2 = obj_as_string(str2); result = str_cmp(str1, str2); return INT2FIX(result); } @@ -361,7 +377,7 @@ Fstr_cmp(str1, str2) VALUE Freg_match(); static VALUE -Fstr_match(x, y) +str_match(x, y) struct RString *x, *y; { VALUE reg; @@ -369,11 +385,11 @@ Fstr_match(x, y) switch (TYPE(y)) { case T_REGEXP: - return Freg_match(y, x); + return reg_match(y, x); case T_STRING: - reg = re_regcomp(y); - start = research(reg, x, 0); + reg = reg_regcomp(y); + start = reg_search(reg, x, 0, 0); if (start == -1) { return FALSE; } @@ -386,7 +402,7 @@ Fstr_match(x, y) } static VALUE -Fstr_match2(str) +str_match2(str) struct RString *str; { extern VALUE rb_lastline; @@ -396,8 +412,8 @@ Fstr_match2(str) if (TYPE(rb_lastline) != T_STRING) Fail("$_ is not a string"); - reg = re_regcomp(str); - start = research(reg, rb_lastline, 0); + reg = reg_regcomp(str); + start = reg_search(reg, rb_lastline, 0, 0); if (start == -1) { return Qnil; } @@ -427,7 +443,7 @@ str_index(str, sub, offset) } static VALUE -Fstr_index(argc, argv, str) +str_index_method(argc, argv, str) int argc; VALUE *argv; struct RString *str; @@ -445,7 +461,7 @@ Fstr_index(argc, argv, str) switch (TYPE(sub)) { case T_REGEXP: - pos = research(sub, str, pos); + pos = reg_search(sub, str, pos, (struct re_registers *)-1); break; case T_STRING: @@ -461,7 +477,7 @@ Fstr_index(argc, argv, str) } static VALUE -Fstr_rindex(argc, argv, str) +str_rindex(argc, argv, str) int argc; VALUE *argv; struct RString *str; @@ -519,7 +535,7 @@ str_next(s) } static VALUE -Fstr_next(orig) +str_next_method(orig) struct RString *orig; { struct RString *str, *str2; @@ -545,7 +561,7 @@ Fstr_next(orig) } VALUE -Fstr_upto(beg, end) +str_upto(beg, end) VALUE beg, end; { VALUE current; @@ -553,8 +569,10 @@ Fstr_upto(beg, end) current = beg; for (;;) { rb_yield(current); - if (Fstr_equal(current, end)) break; - current = Fstr_next(current); + if (str_equal(current, end)) break; + current = str_next_method(current); + if (RSTRING(current)->len > RSTRING(end)->len) + break; } return Qnil; @@ -580,8 +598,8 @@ str_aref(str, indx) return (VALUE)INT2FIX(str->ptr[idx] & 0xff); case T_REGEXP: - if (Fstr_index(str, indx)) - return re_last_match(0); + if (str_index(str, indx)) + return reg_last_match(0); return Qnil; case T_STRING: @@ -590,26 +608,18 @@ str_aref(str, indx) default: /* check if indx is Range */ - if (obj_is_kind_of(indx, C_Range)) { + { int beg, end; - - beg = rb_iv_get(indx, "start"); beg = NUM2INT(beg); - end = rb_iv_get(indx, "end"); end = NUM2INT(end); - if (beg > end) { - int tmp; - - Warning("start %d is bigger than end %d", beg, end); - tmp = beg; beg = end; end = tmp; + if (range_beg_end(indx, &beg, &end)) { + return str_subseq(str, beg, end); } - - return str_subseq(str, beg, end); } Fail("Invalid index for string"); } } static VALUE -Fstr_aref(argc, argv, str) +str_aref_method(argc, argv, str) int argc; VALUE *argv; struct RString *str; @@ -674,9 +684,10 @@ str_sub(str, pat, val, once) VALUE val; int once; { - int beg, end, offset, n; + int beg, offset, n; + struct re_registers regs; - Check_Type(val, T_STRING); + val = obj_as_string(val); str_modify(str); switch (TYPE(pat)) { @@ -684,19 +695,19 @@ str_sub(str, pat, val, once) break; case T_STRING: - return str_sub(str, re_regcomp(pat), val, once); + pat = (struct RRegexp*)reg_regcomp(pat); + break; default: /* type failed */ Check_Type(pat, T_REGEXP); } + regs.allocated = 0; for (offset=0, n=0; - (beg=research(pat, str, offset)) >= 0; - offset=BEG(0)+STRLEN(val)) { - end = END(0)-1; - val = re_regsub(val); - str_replace2(str, beg, END(0)-1, val); + (beg=reg_search(pat, str, offset, ®s)) >= 0; + offset=END(0)+1) { + str_replace2(str, beg, END(0)-1, reg_regsub(val, str, ®s)); n++; if (once) break; } @@ -739,27 +750,19 @@ str_aset(str, indx, val) default: /* check if indx is Range */ - if (obj_is_kind_of(indx, C_Range)) { - Check_Type(val, T_STRING); - - beg = rb_iv_get(indx, "start"); beg = NUM2INT(beg); - end = rb_iv_get(indx, "end"); end = NUM2INT(end); - if (beg > end) { - int tmp; - - Warning("start %d is bigger than end %d", beg, end); - tmp = beg; beg = end; end = tmp; + { + int beg, end; + if (range_beg_end(indx, &beg, &end)) { + str_replace2(str, beg, end, val); + return val; } - - str_replace2(str, beg, end, val); - return val; } Fail("Invalid index for string"); } } static VALUE -Fstr_aset(argc, argv, str) +str_aset_method(argc, argv, str) int argc; VALUE *argv; struct RString *str; @@ -792,9 +795,11 @@ Fstr_aset(argc, argv, str) static VALUE str_sub_iter(str, pat, once) VALUE str, pat; + int once; { VALUE val; - int beg, end, offset, n; + int beg, offset; + struct re_registers regs; if (!iterator_p()) { Fail("Wrong # of arguments(1 for 2)"); @@ -806,7 +811,7 @@ str_sub_iter(str, pat, once) break; case T_STRING: - pat = re_regcomp(pat); + pat = reg_regcomp(pat); break; default: @@ -815,18 +820,20 @@ str_sub_iter(str, pat, once) } offset=0; - while ((beg=research(pat, str, offset)) >= 0) { - val = rb_yield(re_nth_match(0)); + regs.allocated = 0; + while ((beg=reg_search(pat, str, offset, ®s)) >= 0) { + val = rb_yield(reg_nth_match(0, backref_get())); val = obj_as_string(val); str_replace2(str, beg, END(0)-1, val); offset=BEG(0)+STRLEN(val); if (once) break; } + re_free_registers(®s); return (VALUE)str; } static VALUE -Fstr_sub(argc, argv, str) +str_sub_bang(argc, argv, str) int argc; VALUE *argv; VALUE str; @@ -840,7 +847,16 @@ Fstr_sub(argc, argv, str) } static VALUE -Fstr_gsub(argc, argv, str) +str_sub_method(argc, argv, str) + int argc; + VALUE *argv; + VALUE str; +{ + return str_sub_bang(argc, argv, str_dup(str)); +} + +static VALUE +str_gsub_bang(argc, argv, str) int argc; VALUE *argv; VALUE str; @@ -853,10 +869,21 @@ Fstr_gsub(argc, argv, str) return str_sub(str, pat, val, 0); } +static VALUE +str_gsub(argc, argv, str) + int argc; + VALUE *argv; + VALUE str; +{ + VALUE v = str_gsub_bang(argc, argv, str_dup(str)); + if (v) return v; + return str; +} + extern VALUE rb_lastline; static VALUE -Fsub(argc, argv) +f_sub_bang(argc, argv) int argc; VALUE *argv; { @@ -870,7 +897,23 @@ Fsub(argc, argv) } static VALUE -Fgsub(argc, argv) +f_sub(argc, argv) + int argc; + VALUE *argv; +{ + VALUE v; + + Check_Type(rb_lastline, T_STRING); + v = f_sub_bang(argc, argv, str_dup(rb_lastline)); + if (v) { + rb_lastline = v; + return v; + } + return rb_lastline; +} + +static VALUE +f_gsub_bang(argc, argv) int argc; VALUE *argv; { @@ -884,7 +927,41 @@ Fgsub(argc, argv) } static VALUE -Fstr_reverse(str) +f_gsub(argc, argv) + int argc; + VALUE *argv; +{ + VALUE v; + + Check_Type(rb_lastline, T_STRING); + v = f_gsub_bang(argc, argv, str_dup(rb_lastline)); + if (v) { + rb_lastline = v; + return v; + } + return rb_lastline; +} + +static VALUE +str_reverse_bang(str) + struct RString *str; +{ + char *s, *e, *p; + + s = str->ptr; + e = s + str->len - 1; + p = ALLOCA_N(char, str->len); + + while (e >= s) { + *p++ = *e--; + } + MEMCPY(str->ptr, p, char, str->len); + + return (VALUE)str; +} + +static VALUE +str_reverse(str) struct RString *str; { VALUE obj = str_new(0, str->len); @@ -901,14 +978,14 @@ Fstr_reverse(str) } static VALUE -Fstr_to_i(str) +str_to_i(str) struct RString *str; { return str2inum(str->ptr, 10); } static VALUE -Fstr_to_f(str) +str_to_f(str) struct RString *str; { double atof(); @@ -918,35 +995,50 @@ Fstr_to_f(str) } static VALUE -Fstr_to_s(str) +str_to_s(str) VALUE str; { return str; } static VALUE -Fstr_inspect(str) +str_inspect(str) struct RString *str; { - char buf[160]; + struct RString *str0; char *p, *pend; - char *b, *bend; + char *b; + int offset; -#define CHECK(n) if (b+n > bend) break; + str0 = (struct RString*)str_new2("\""); + offset = 1; +#define CHECK(n) do {\ + str_cat(str0, 0, n);\ + b = str0->ptr + offset;\ + offset += n;\ +} while (0) p = str->ptr; pend = p + str->len; - b = buf; bend = b + sizeof buf - (str->len>150?4:2); - *b++ = '"'; while (p < pend) { char c = *p++; - if (isprint(c)) { - CHECK(1); + if (ismbchar(c) && p+1 < pend) { + CHECK(2); *b++ = c; + *b++ = *p++; + } + else if (c == '"') { + CHECK(2); + *b++ = '\\'; + *b++ = '"'; } - else if (ismbchar(c)) { + else if (c == '\\') { CHECK(2); + *b++ = '\\'; + *b++ = '\\'; + } + else if (isprint(c)) { + CHECK(1); *b++ = c; - *b++ = *p++; } else if (c == '\n') { CHECK(2); @@ -973,7 +1065,7 @@ Fstr_inspect(str) *b++ = '\\'; *b++ = 'v'; } - else if (c == '\1') { + else if (c == '\007') { CHECK(2); *b++ = '\\'; *b++ = 'a'; @@ -983,28 +1075,19 @@ Fstr_inspect(str) *b++ = '\\'; *b++ = 'e'; } - else if (iscntrl(c)) { - CHECK(2); - *b++ = '^'; - *b++ = c; - } else { - CHECK(1); - *b++ = c; - } - } - *b++ = '"'; - if (p < pend) { - bend = buf + sizeof buf; - while (b < bend) { - *b++ = '.'; + CHECK(4); + *b++ = '\\'; + sprintf(b, "%03o", c); + b += 3; } } - return str_new(buf, b - buf); + str_cat(str0, "\"", 1); + return (VALUE)str0; } static VALUE -Fstr_upcase(str) +str_upcase_bang(str) struct RString *str; { char *s, *send; @@ -1022,7 +1105,14 @@ Fstr_upcase(str) } static VALUE -Fstr_downcase(str) +str_upcase(str) + struct RString *str; +{ + return str_upcase_bang(str_dup(str)); +} + +static VALUE +str_downcase_bang(str) struct RString *str; { char *s, *send; @@ -1040,7 +1130,14 @@ Fstr_downcase(str) } static VALUE -Fstr_capitalize(str) +str_downcase(str) + struct RString *str; +{ + return str_downcase_bang(str_dup(str)); +} + +static VALUE +str_capitalize_bang(str) struct RString *str; { char *s, *send; @@ -1058,7 +1155,14 @@ Fstr_capitalize(str) } static VALUE -Fstr_swapcase(str) +str_capitalize(str) + struct RString *str; +{ + return str_capitalize_bang(str_dup(str)); +} + +static VALUE +str_swapcase_bang(str) struct RString *str; { char *s, *send; @@ -1079,25 +1183,20 @@ Fstr_swapcase(str) } static VALUE -Fstr_toupper(str) +str_swapcase(str) struct RString *str; { - return Fstr_upcase(str_new(str->ptr, str->len)); + return str_swapcase_bang(str_dup(str)); } -static VALUE -Fstr_tolower(str) - struct RString *str; -{ - return Fstr_downcase(str_new(str->ptr, str->len)); -} +typedef unsigned char *USTR; struct tr { - unsigned char gen, now, max; + int gen, now, max; char *p, *pend; } trsrc, trrepl; -static char +static int trnext(t) struct tr *t; { @@ -1108,12 +1207,12 @@ trnext(t) if (t->p < t->pend && *t->p == '-') { t->p++; if (t->p < t->pend) { - if (t->now > *t->p) { + if (t->now > *(USTR)t->p) { t->p++; continue; } t->gen = 1; - t->max = *t->p++; + t->max = *(USTR)t->p++; } } return t->now; @@ -1129,13 +1228,13 @@ trnext(t) } static VALUE -Fstr_tr(str, src, repl) +str_tr_bang(str, src, repl) struct RString *str, *src, *repl; { struct tr trsrc, trrepl; int cflag = 0; char trans[256]; - int i, c, save; + int i, c; char *s, *send, *t; Check_Type(src, T_STRING); @@ -1176,7 +1275,7 @@ Fstr_tr(str, src, repl) char r; for (i=0; i<256; i++) { - trans[i] = 0; + trans[i] = i; } while ((c = trnext(&trsrc)) >= 0) { r = trnext(&trrepl); @@ -1197,6 +1296,13 @@ Fstr_tr(str, src, repl) return (VALUE)str; } +static VALUE +str_tr(str, src, repl) + struct RString *str, *src, *repl; +{ + return str_tr_bang(str_dup(str), src, repl); +} + static void tr_setup_table(str, table) struct RString *str; @@ -1222,7 +1328,7 @@ tr_setup_table(str, table) } static VALUE -Fstr_delete(str1, str2) +str_delete_bang(str1, str2) struct RString *str1, *str2; { char *s, *send, *t; @@ -1248,6 +1354,13 @@ Fstr_delete(str1, str2) } static VALUE +str_delete(str1, str2) + struct RString *str1, *str2; +{ + return str_delete_bang(str_dup(str1), str2); +} + +static VALUE tr_squeeze(str1, str2) struct RString *str1, *str2; { @@ -1284,7 +1397,7 @@ tr_squeeze(str1, str2) } static VALUE -Fstr_squeeze(argc, argv, str1) +str_squeeze_bang(argc, argv, str1) int argc; VALUE *argv; VALUE str1; @@ -1299,18 +1412,34 @@ Fstr_squeeze(argc, argv, str1) } static VALUE -Fstr_tr_s(str, src, repl) +str_squeeze(argc, argv, str) + int argc; + VALUE *argv; + VALUE str; +{ + return str_squeeze_bang(argc, argv, str_dup(str)); +} + +static VALUE +str_tr_s_bang(str, src, repl) VALUE str, src, repl; { Check_Type(src, T_STRING); Check_Type(repl, T_STRING); - Fstr_tr(str, src, repl); + str_tr(str, src, repl); tr_squeeze(str, repl); return str; } static VALUE -Fstr_split(argc, argv, str) +str_tr_s(str, src, repl) + VALUE str, src, repl; +{ + return str_tr_s_bang(str_dup(str), src, repl); +} + +static VALUE +str_split_method(argc, argv, str) int argc; VALUE *argv; struct RString *str; @@ -1343,7 +1472,7 @@ Fstr_split(argc, argv, str) char_sep = RSTRING(spat)->ptr[0]; } else { - spat = (struct RRegexp*)re_regcomp(spat); + spat = (struct RRegexp*)reg_regcomp(spat); } break; case T_REGEXP: @@ -1401,9 +1530,11 @@ Fstr_split(argc, argv, str) int start = beg; int last_null = 0; int idx; + struct re_registers regs; - while ((end = research(spat, str, start)) >= 0) { - if (start == end && BEG(0) == END(0)) { + regs.allocated = 0; + while ((end = reg_search(spat, str, start, ®s)) >= 0) { + if (start == end && regs.beg[0] == regs.end[0]) { if (last_null == 1) { if (ismbchar(str->ptr[beg])) ary_push(result, str_substr(str, beg, 2)); @@ -1420,22 +1551,23 @@ Fstr_split(argc, argv, str) } else { ary_push(result, str_substr(str, beg, end-beg)); - beg = start = END(0); + beg = start = regs.end[0]; if (limit && lim <= ++i) break; } last_null = 0; for (idx=1; idx < 10; idx++) { - if (BEG(idx) == -1) break; - if (BEG(idx) == END(idx)) + if (regs.beg[idx] == -1) break; + if (regs.beg[idx] == regs.end[idx]) tmp = str_new(0, 0); else - tmp = str_subseq(str, BEG(idx), END(idx)-1); + tmp = str_subseq(str, regs.beg[idx], regs.end[idx]-1); ary_push(result, tmp); if (limit && lim <= ++i) break; } } + re_free_registers(®s); } if (str->len > beg) { ary_push(result, str_subseq(str, beg, -1)); @@ -1444,8 +1576,19 @@ Fstr_split(argc, argv, str) return result; } +VALUE +str_split(str, sep0) + struct RString* str; + char *sep0; +{ + VALUE sep; + + sep = str_new2(sep0); + return str_split_method(1, &sep, str); +} + static VALUE -Fstr_each(str) +str_each_line(str) struct RString* str; { extern VALUE RS; @@ -1453,6 +1596,7 @@ Fstr_each(str) int rslen; char *p = str->ptr, *pend = p + str->len, *s; char *ptr = p; + int len = str->len; if (RS == Qnil) { rb_yield(str); @@ -1478,7 +1622,8 @@ Fstr_each(str) memcmp(RSTRING(RS)->ptr, p-rslen+1, rslen) == 0)) { rb_lastline = str_new(s, p - s + 1); rb_yield(rb_lastline); - if (str->ptr != ptr) Fail("string modified"); + if (str->ptr != ptr || str->len != len) + Fail("string modified"); s = p + 1; } } @@ -1492,7 +1637,7 @@ Fstr_each(str) } static VALUE -Fstr_each_byte(str) +str_each_byte(str) struct RString* str; { int i; @@ -1504,7 +1649,7 @@ Fstr_each_byte(str) } static VALUE -Fstr_chop(str) +str_chop_bang(str) struct RString *str; { str_modify(str); @@ -1516,11 +1661,20 @@ Fstr_chop(str) } static VALUE -Fstr_strip(str) +str_chop(str) + struct RString *str; +{ + return str_chop_bang(str_dup(str)); +} + +static VALUE +str_strip_bang(str) struct RString *str; { char *s, *t, *e; + str_modify(str); + s = str->ptr; e = t = s + str->len; /* remove spaces at head */ @@ -1531,49 +1685,55 @@ Fstr_strip(str) while (s <= t && isspace(*t)) t--; t++; - if (s > str->ptr || t < e) { + str->len = t-s; + if (s > str->ptr) { char *p = str->ptr; - int len = t-s; - str->ptr = ALLOC_N(char, len+1); - memcpy(str->ptr, p, len); - str->ptr[len] = '\0'; - if (str->orig) { - str->orig = Qnil; - } - else { - free(p); - } + str->ptr = ALLOC_N(char, str->len+1); + memcpy(str->ptr, s, str->len); + str->ptr[str->len] = '\0'; + free(p); + } + else if (t < e) { + str->ptr[str->len] = '\0'; } + return (VALUE)str; } static VALUE -Fstr_hex(str) +str_strip(str) + struct RString *str; +{ + return str_strip_bang(str_dup(str)); +} + +static VALUE +str_hex(str) struct RString *str; { return str2inum(str->ptr, 16); } static VALUE -Fstr_oct(str) +str_oct(str) struct RString *str; { return str2inum(str->ptr, 8); } static VALUE -Fstr_crypt(str, salt) +str_crypt(str, salt) struct RString *str, *salt; { - Check_Type(salt, T_STRING); + salt = as_str(salt); if (salt->len < 2) - Fail("salt too short(need 2 byte)"); + Fail("salt too short(need >2 bytes)"); return str_new2(crypt(str->ptr, salt->ptr)); } static VALUE -Fstr_intern(str) +str_intern(str) struct RString *str; { if (strlen(str->ptr) != str->len) @@ -1583,7 +1743,7 @@ Fstr_intern(str) } static VALUE -Fstr_sum(argc, argv, str) +str_sum(argc, argv, str) int argc; VALUE *argv; struct RString *str; @@ -1624,7 +1784,8 @@ Fstr_sum(argc, argv, str) } } -Fstr_ljust(str, w) +VALUE +str_ljust(str, w) struct RString *str; VALUE w; { @@ -1642,7 +1803,8 @@ Fstr_ljust(str, w) return (VALUE)res; } -Fstr_rjust(str, w) +VALUE +str_rjust(str, w) struct RString *str; VALUE w; { @@ -1660,7 +1822,8 @@ Fstr_rjust(str, w) return (VALUE)res; } -Fstr_center(str, w) +VALUE +str_center(str, w) struct RString *str; VALUE w; { @@ -1684,76 +1847,97 @@ Fstr_center(str, w) return (VALUE)res; } -extern VALUE C_Kernel; -extern VALUE M_Comparable; -extern VALUE M_Enumerable; +extern VALUE cKernel; +extern VALUE mComparable; +extern VALUE mEnumerable; +void Init_String() { - C_String = rb_define_class("String", C_Object); - rb_include_module(C_String, M_Comparable); - rb_include_module(C_String, M_Enumerable); - rb_define_single_method(C_String, "new", Sstr_new, 1); - rb_define_method(C_String, "clone", str_clone, 0); - rb_define_method(C_String, "<=>", Fstr_cmp, 1); - rb_define_method(C_String, "==", Fstr_equal, 1); - rb_define_method(C_String, "hash", Fstr_hash, 0); - rb_define_method(C_String, "+", Fstr_plus, 1); - rb_define_method(C_String, "*", Fstr_times, 1); - rb_define_method(C_String, "..", Fstr_dot2, 1); - rb_define_method(C_String, "[]", Fstr_aref, -1); - rb_define_method(C_String, "[]=", Fstr_aset, -1); - rb_define_method(C_String, "length", Fstr_length, 0); - rb_define_alias(C_String, "size", "length"); - rb_define_method(C_String, "=~", Fstr_match, 1); - rb_define_method(C_String, "~", Fstr_match2, 0); - rb_define_method(C_String, "next", Fstr_next, 0); - rb_define_method(C_String, "upto", Fstr_next, 1); - rb_define_method(C_String, "index", Fstr_index, -1); - rb_define_method(C_String, "rindex", Fstr_rindex, -1); - - rb_define_method(C_String, "to_i", Fstr_to_i, 0); - rb_define_method(C_String, "to_f", Fstr_to_f, 0); - rb_define_method(C_String, "to_s", Fstr_to_s, 0); - rb_define_method(C_String, "_inspect", Fstr_inspect, 0); - - rb_define_method(C_String, "toupper", Fstr_toupper, 0); - rb_define_method(C_String, "tolower", Fstr_tolower, 0); - - rb_define_method(C_String, "upcase", Fstr_upcase, 0); - rb_define_method(C_String, "downcase", Fstr_downcase, 0); - rb_define_method(C_String, "capitalize", Fstr_capitalize, 0); - rb_define_method(C_String, "swapcase", Fstr_swapcase, 0); - - rb_define_method(C_String, "hex", Fstr_hex, 0); - rb_define_method(C_String, "oct", Fstr_oct, 0); - rb_define_method(C_String, "split", Fstr_split, -1); - rb_define_method(C_String, "reverse", Fstr_reverse, 0); - rb_define_method(C_String, "concat", Fstr_concat, 1); - rb_define_method(C_String, "crypt", Fstr_crypt, 1); - rb_define_method(C_String, "intern", Fstr_intern, 0); - - rb_define_method(C_String, "ljust", Fstr_ljust, 1); - rb_define_method(C_String, "rjust", Fstr_rjust, 1); - rb_define_method(C_String, "center", Fstr_center, 1); - - rb_define_method(C_String, "sub", Fstr_sub, -1); - rb_define_method(C_String, "gsub", Fstr_gsub, -1); - rb_define_method(C_String, "chop", Fstr_chop, 0); - rb_define_method(C_String, "strip", Fstr_strip, 0); - - rb_define_method(C_String, "tr", Fstr_tr, 2); - rb_define_method(C_String, "tr_s", Fstr_tr_s, 2); - rb_define_method(C_String, "delete", Fstr_delete, 1); - rb_define_method(C_String, "squeeze", Fstr_squeeze, -1); - - rb_define_method(C_String, "each", Fstr_each, 0); - rb_define_method(C_String, "each_byte", Fstr_each_byte, 0); - - rb_define_method(C_String, "sum", Fstr_sum, -1); - - rb_define_private_method(C_Kernel, "sub", Fsub, -1); - rb_define_private_method(C_Kernel, "gsub", Fgsub, -1); + cString = rb_define_class("String", cObject); + rb_include_module(cString, mComparable); + rb_include_module(cString, mEnumerable); + rb_define_singleton_method(cString, "new", str_s_new, 1); + rb_define_method(cString, "clone", str_clone, 0); + rb_define_method(cString, "dup", str_dup, 0); + rb_define_method(cString, "<=>", str_cmp_method, 1); + rb_define_method(cString, "==", str_equal, 1); + rb_define_method(cString, "hash", str_hash_method, 0); + rb_define_method(cString, "+", str_plus, 1); + rb_define_method(cString, "*", str_times, 1); + rb_define_method(cString, "[]", str_aref_method, -1); + rb_define_method(cString, "[]=", str_aset_method, -1); + rb_define_method(cString, "length", str_length, 0); + rb_define_alias(cString, "size", "length"); + rb_define_method(cString, "=~", str_match, 1); + rb_define_method(cString, "~", str_match2, 0); + rb_define_method(cString, "next", str_next_method, 0); + rb_define_method(cString, "upto", str_next, 1); + rb_define_method(cString, "index", str_index_method, -1); + rb_define_method(cString, "rindex", str_rindex, -1); + + rb_define_method(cString, "freeze", str_freeze, 0); + rb_define_method(cString, "frozen?", str_frozen, 0); + + rb_define_method(cString, "to_i", str_to_i, 0); + rb_define_method(cString, "to_f", str_to_f, 0); + rb_define_method(cString, "to_s", str_to_s, 0); + rb_define_method(cString, "inspect", str_inspect, 0); + + rb_define_method(cString, "upcase", str_upcase, 0); + rb_define_method(cString, "downcase", str_downcase, 0); + rb_define_method(cString, "capitalize", str_capitalize, 0); + rb_define_method(cString, "swapcase", str_swapcase, 0); + + rb_define_method(cString, "upcase!", str_upcase_bang, 0); + rb_define_method(cString, "downcase!", str_downcase_bang, 0); + rb_define_method(cString, "capitalize!", str_capitalize_bang, 0); + rb_define_method(cString, "swapcase!", str_swapcase_bang, 0); + + rb_define_method(cString, "hex", str_hex, 0); + rb_define_method(cString, "oct", str_oct, 0); + rb_define_method(cString, "split", str_split_method, -1); + rb_define_method(cString, "reverse", str_reverse, 0); + rb_define_method(cString, "reverse!", str_reverse_bang, 0); + rb_define_method(cString, "concat", str_concat, 1); + rb_define_method(cString, "crypt", str_crypt, 1); + rb_define_method(cString, "intern", str_intern, 0); + + rb_define_method(cString, "ljust", str_ljust, 1); + rb_define_method(cString, "rjust", str_rjust, 1); + rb_define_method(cString, "center", str_center, 1); + + rb_define_method(cString, "sub", str_sub_method, -1); + rb_define_method(cString, "gsub", str_gsub, -1); + rb_define_method(cString, "chop", str_chop, 0); + rb_define_method(cString, "strip", str_strip, 0); + + rb_define_method(cString, "sub!", str_sub_bang, -1); + rb_define_method(cString, "gsub!", str_gsub_bang, -1); + rb_define_method(cString, "strip!", str_strip_bang, 0); + rb_define_method(cString, "chop!", str_chop_bang, 0); + + rb_define_method(cString, "tr", str_tr, 2); + rb_define_method(cString, "tr_s", str_tr_s, 2); + rb_define_method(cString, "delete", str_delete, 1); + rb_define_method(cString, "squeeze", str_squeeze, -1); + + rb_define_method(cString, "tr!", str_tr_bang, 2); + rb_define_method(cString, "tr_s!", str_tr_s_bang, 2); + rb_define_method(cString, "delete!", str_delete_bang, 1); + rb_define_method(cString, "squeeze!", str_squeeze_bang, -1); + + rb_define_method(cString, "each_line", str_each_line, 0); + rb_define_method(cString, "each_byte", str_each_byte, 0); + rb_define_method(cString, "each", str_each_byte, 0); + + rb_define_method(cString, "sum", str_sum, -1); + + rb_define_private_method(cKernel, "sub", f_sub, -1); + rb_define_private_method(cKernel, "gsub", f_gsub, -1); + + rb_define_private_method(cKernel, "sub!", f_sub_bang, -1); + rb_define_private_method(cKernel, "gsub!", f_gsub_bang, -1); pr_str = rb_intern("to_s"); } @@ -9,203 +9,263 @@ ************************************************/ #include "ruby.h" -#include "env.h" -VALUE C_Struct; -extern VALUE M_Enumerable; - -char *strdup(); +ID rb_frame_last_func(); +VALUE cStruct; +extern VALUE mEnumerable; static VALUE -struct_alloc(class, name) - VALUE class; - char *name; +struct_ref(obj) + struct RStruct *obj; { - NEWOBJ(st, struct RStruct); - OBJSETUP(st, class, T_STRUCT); - - if (name) st->name = strdup(name); - else st->name = Qnil; - st->len = 0; - st->tbl = Qnil; + VALUE nstr, member, slot; + int i; - return (VALUE)st; + nstr = CLASS_OF(obj); + member = rb_ivar_get(nstr, rb_intern("__member__")); + if (member == Qnil) { + Fail("non-initialized struct"); + } + slot = INT2FIX(rb_frame_last_func()); + for (i=0; i<RARRAY(member)->len; i++) { + if (RARRAY(member)->ptr[i] == slot) { + return obj->ptr[i]; + } + } + Fail("not struct member"); + return Qnil; /* not reached */ } +static VALUE struct_ref0(obj) struct RStruct *obj; {return obj->ptr[0];} +static VALUE struct_ref1(obj) struct RStruct *obj; {return obj->ptr[1];} +static VALUE struct_ref2(obj) struct RStruct *obj; {return obj->ptr[2];} +static VALUE struct_ref3(obj) struct RStruct *obj; {return obj->ptr[3];} +static VALUE struct_ref4(obj) struct RStruct *obj; {return obj->ptr[4];} +static VALUE struct_ref5(obj) struct RStruct *obj; {return obj->ptr[5];} +static VALUE struct_ref6(obj) struct RStruct *obj; {return obj->ptr[6];} +static VALUE struct_ref7(obj) struct RStruct *obj; {return obj->ptr[7];} +static VALUE struct_ref8(obj) struct RStruct *obj; {return obj->ptr[8];} +static VALUE struct_ref9(obj) struct RStruct *obj; {return obj->ptr[9];} + +VALUE (*ref_func[10])() = { + struct_ref0, + struct_ref1, + struct_ref2, + struct_ref3, + struct_ref4, + struct_ref5, + struct_ref6, + struct_ref7, + struct_ref8, + struct_ref9, +}; + static VALUE -struct_find(s, id) - struct RStruct *s; - ID id; +struct_set(obj, val) + struct RStruct *obj; + VALUE val; { - struct kv_pair *t, *tend; + VALUE nstr, member, slot; + int i; - t = s->tbl; - tend = t + s->len; - while (t < tend) { - if (t->key == id) return t->value; - t++; + nstr = CLASS_OF(obj); + member = rb_ivar_get(nstr, rb_intern("__member__")); + if (member == Qnil) { + Fail("non-initialized struct"); } - Fail("struct %s has no member %s", s->name, rb_id2name(id)); + for (i=0; i<RARRAY(member)->len; i++) { + slot = RARRAY(member)->ptr[i]; + if (id_attrset(FIX2INT(slot)) == rb_frame_last_func()) { + return obj->ptr[i] = val; + } + } + Fail("not struct member"); + return Qnil; /* not reached */ } -static VALUE -Fstruct_access(s) - struct RStruct *s; -{ - return struct_find(s, the_env->last_func); -} +static VALUE struct_s_new(); static VALUE -struct_add(s, mem, val) - struct RStruct *s; - char *mem; - VALUE val; +make_struct(name, member) + struct RString *name; + struct RArray *member; { - int pos = s->len; + VALUE nstr; + int i; - s->len++; - if (s->tbl == Qnil) { - s->tbl = ALLOC_N(struct kv_pair, 1); - } - else { - REALLOC_N(s->tbl, struct kv_pair, s->len); + nstr = rb_define_class_under(cStruct, name->ptr, cStruct); + rb_ivar_set(nstr, rb_intern("__size__"), INT2FIX(member->len)); + rb_ivar_set(nstr, rb_intern("__member__"), member); + + rb_define_singleton_method(nstr, "new", struct_s_new, -1); + for (i=0; i< member->len; i++) { + ID id = FIX2INT(member->ptr[i]); + if (i<10) { + rb_define_method_id(nstr, id, ref_func[i], 0); + } + else { + rb_define_method_id(nstr, id, struct_ref, 0); + } + rb_define_method_id(nstr, id_attrset(id), struct_set, 1); } - s->tbl[pos].key = rb_intern(mem); - s->tbl[pos].value = val; - rb_define_single_method(s, mem, Fstruct_access, 0); + return nstr; } #include <varargs.h> VALUE -struct_new(name, va_alist) +struct_define(name, va_alist) char *name; va_dcl { - VALUE st; - va_list args; + va_list ar; + VALUE nm, ary; char *mem; - st = struct_alloc(C_Struct,name); - va_start(args); - while (mem = va_arg(args, char*)) { - struct_add(st, mem, va_arg(args, VALUE)); + nm = str_new2(name); + ary = ary_new(); + + va_start(ar); + while (mem = va_arg(ar, char*)) { + ID slot = rb_intern(mem); + ary_push(ary, INT2FIX(slot)); } - va_end(vargs); + va_end(ar); - return st; + return make_struct(nm, ary); } -#define ASSOC_KEY(a) RASSOC(a)->car -#define ASSOC_VAL(a) RASSOC(a)->cdr - static VALUE -Sstruct_new(argc, argv, class) +struct_s_def(argc, argv) int argc; VALUE *argv; - VALUE class; { - VALUE name, st; - struct RArray *tbl; - int i, max; + struct RString *name; + struct RArray *rest; + VALUE nstr; + int i; - rb_scan_args(argc, argv, "1*", &name, &tbl); + rb_scan_args(argc, argv, "1*", &name, &rest); Check_Type(name, T_STRING); + for (i=0; i<rest->len; i++) { + Check_Type(rest->ptr[i], T_FIXNUM); + } + return make_struct(name, rest); +} - st = struct_alloc(class, RSTRING(name)->ptr); - for (i=0, max=tbl->len; i<max; i++) { - VALUE assoc = tbl->ptr[i]; +VALUE +struct_alloc(class, values) + VALUE class; + struct RArray *values; +{ + VALUE size; + int n; - Check_Type(assoc, T_ASSOC); - Check_Type(ASSOC_KEY(assoc), T_STRING); - struct_add(st, RSTRING(ASSOC_KEY(assoc))->ptr, ASSOC_VAL(assoc)); + size = rb_ivar_get(class, rb_intern("__size__")); + n = FIX2INT(size); + if (n < values->len) { + Fail("struct size differs"); } - - return st; + else { + NEWOBJ(st, struct RStruct); + OBJSETUP(st, class, T_STRUCT); + st->len = n; + st->ptr = ALLOC_N(VALUE, n); + MEMCPY(st->ptr, values->ptr, VALUE, values->len); + MEMZERO(st->ptr+values->len, VALUE, n - values->len); + + return (VALUE)st; + } + return Qnil; /* not reached */ } -static VALUE -Fstruct_each(s) - struct RStruct *s; +VALUE +struct_new(class, va_alist) + VALUE class; + va_dcl { - struct kv_pair *t, *tend; + VALUE val, mem; + va_list args; - t = s->tbl; - tend = t + s->len; - while (t < tend) { - rb_yield(t->value); - t++; + mem = ary_new(); + va_start(args); + while (val = va_arg(args, VALUE)) { + ary_push(mem, val); } + va_end(args); + + return struct_alloc(class, mem); } static VALUE -Fstruct_values(s) - struct RStruct *s; +struct_s_new(argc, argv, obj) + int argc; + VALUE *argv; { - VALUE ary; - struct kv_pair *t, *tend; + VALUE member, slot; - ary = ary_new(); - t = s->tbl; - tend = t + s->len; - while (t < tend) { - ary_push(ary, t->value); - t++; - } - - return ary; + member = ary_new4(argc, argv); + return struct_alloc(obj, member); } static VALUE -Fstruct_aref(s, idx) +struct_each(s) struct RStruct *s; - VALUE idx; { - struct RArray *ary; int i; - if (TYPE(idx) == T_STRING) - return struct_find(rb_intern(RSTRING(idx)->ptr)); - - i = NUM2INT(idx); - if (s->len <= i) - Fail("offset %d too large for struct(size:%d)", i, s->len); - return s->tbl[i].value; + for (i=0; i<s->len; i++) { + rb_yield(s->ptr[i]); + } + return Qnil; } +char *rb_class2name(); #define HDR "struct " static VALUE -Fstruct_to_s(s) +struct_to_s(s) struct RStruct *s; { - char *buf; + char *name, *buf; - buf = ALLOCA_N(char, strlen(s->name)+sizeof(HDR)+1); - sprintf(buf, "%s%s", HDR, s->name); + name = rb_class2name(CLASS_OF(s)); + buf = ALLOCA_N(char, strlen(name)+sizeof(HDR)+1); + sprintf(buf, "%s%s", HDR, name); return str_new2(buf); } static VALUE -Fstruct_inspect(s) +struct_inspect(s) struct RStruct *s; { - VALUE str, str2; - char buf[256], *p; + char *name = rb_class2name(CLASS_OF(s)); + ID inspect = rb_intern("inspect"); + VALUE str, member; + char buf[256]; int i; - ID inspect = rb_intern("_inspect"); - sprintf(buf, "#<%s%s: ", HDR, s->name); + member = rb_ivar_get(CLASS_OF(s), rb_intern("__member__")); + if (member == Qnil) { + Fail("non-initialized struct"); + } + + sprintf(buf, "#<%s%s: ", HDR, name); str = str_new2(buf); for (i=0; i<s->len; i++) { + VALUE str2, slot; + char *p; + if (i > 0) { str_cat(str, ", ", 2); } - p = rb_id2name(s->tbl[i].key); + slot = RARRAY(member)->ptr[i]; + p = rb_id2name(FIX2INT(slot)); str_cat(str, p, strlen(p)); str_cat(str, "=", 1); - str2 = rb_funcall(s->tbl[i].value, inspect, 0, Qnil); + str2 = rb_funcall(s->ptr[i], inspect, 0, 0); + str2 = obj_as_string(str2); str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); } str_cat(str, ">", 1); @@ -214,47 +274,108 @@ Fstruct_inspect(s) } static VALUE -Fstruct_to_a(s) +struct_to_a(s) + struct RStruct *s; +{ + return ary_new4(s->len, s->ptr); +} + +static VALUE +struct_clone(s) + struct RStruct *s; +{ + NEWOBJ(st, struct RStruct); + CLONESETUP(st, s); + st->len = s->len; + st->ptr = ALLOC_N(VALUE, s->len); + MEMCPY(st->ptr, s->ptr, VALUE, st->len); + + return (VALUE)st; +} + +static VALUE +struct_aref(s, idx) struct RStruct *s; + VALUE idx; { - VALUE ary; int i; - ary = ary_new2(s->len); - for (i=0; i<s->len; i++) { - ary_push(ary, s->tbl[i].value); + i = NUM2INT(idx); + if (i < 0) i = s->len - i; + if (i < 0) + Fail("offset %d too small for struct(size:%d)", i, s->len); + if (s->len <= i) + Fail("offset %d too large for struct(size:%d)", i, s->len); + return s->ptr[i]; +} + +static VALUE +struct_aset(s, idx, val) + struct RStruct *s; + VALUE idx, val; +{ + int i; + + i = NUM2INT(idx); + if (i < 0) i = s->len - i; + if (i < 0) + Fail("offset %d too small for struct(size:%d)", i, s->len); + if (s->len <= i) + Fail("offset %d too large for struct(size:%d)", i, s->len); + return s->ptr[i] = val; +} + +static VALUE +struct_equal(s, s2) + struct RStruct *s, *s2; +{ + int i; + + if (TYPE(s2) != T_STRUCT) return FALSE; + if (CLASS_OF(s) != CLASS_OF(s2)) return FALSE; + if (s->len != s2->len) { + Fail("incomsistent struct"); } - return ary; + for (i=0; i<s->len; i++) { + if (!rb_equal(s->ptr[i], s2->ptr[i])) return FALSE; + } + return TRUE; } static VALUE -Fstruct_clone(s) +struct_hash(s) struct RStruct *s; { - struct RStruct *st = (struct RStruct*)struct_alloc(s->name); + int i, h; + ID hash = rb_intern("hash"); - CLONESETUP(st, s); - st->len = s->len; - st->tbl = ALLOC_N(struct kv_pair, s->len); - MEMCPY(st->tbl, s->tbl, struct kv_pair, st->len); - RBASIC(st)->class = single_class_clone(RBASIC(s)->class); - return (VALUE)st; + h = CLASS_OF(s); + for (i=0; i<s->len; i++) { + h ^= rb_funcall(s->ptr[i], hash, 0); + } + return INT2FIX(h); } +void Init_Struct() { - C_Struct = rb_define_class("Struct", C_Object); - rb_include_module(C_Struct, M_Enumerable); + cStruct = rb_define_class("Struct", cObject); + rb_include_module(cStruct, mEnumerable); + + rb_define_singleton_method(cStruct, "new", struct_s_def, -1); + + rb_define_method(cStruct, "clone", struct_clone, 0); - rb_define_single_method(C_Struct, "new", Sstruct_new, -1); - rb_define_method(C_Struct, "clone", Fstruct_clone, 0); + rb_define_method(cStruct, "==", struct_equal, 1); + rb_define_method(cStruct, "hash", struct_hash, 0); - rb_define_method(C_Struct, "to_s", Fstruct_to_s, 0); - rb_define_method(C_Struct, "_inspect", Fstruct_inspect, 0); - rb_define_method(C_Struct, "to_a", Fstruct_to_a, 0); + rb_define_method(cStruct, "to_s", struct_to_s, 0); + rb_define_method(cStruct, "inspect", struct_inspect, 0); + rb_define_method(cStruct, "to_a", struct_to_a, 0); + rb_define_method(cStruct, "values", struct_to_a, 0); - rb_define_method(C_Struct, "each", Fstruct_each, 0); - rb_define_method(C_Struct, "values", Fstruct_values, 0); - rb_define_method(C_Struct, "[]", Fstruct_aref, 1); + rb_define_method(cStruct, "each", struct_each, 0); + rb_define_method(cStruct, "[]", struct_aref, 1); + rb_define_method(cStruct, "[]=", struct_aset, 2); } @@ -12,12 +12,27 @@ #include "ruby.h" #include <sys/types.h> -#include <sys/time.h> + +#include <time.h> +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#else +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif + +#ifdef HAVE_SYS_TIMES_H #include <sys/times.h> +#endif #include <math.h> -static VALUE C_Time; -extern VALUE M_Comparable; +static VALUE cTime; +#if defined(HAVE_TIMES) || defined(NT) +static VALUE S_Tms; +#endif +extern VALUE mComparable; struct time_object { struct timeval tv; @@ -37,12 +52,12 @@ static ID id_tv; #define MakeTimeval(obj,tobj) {\ if (!id_tv) id_tv = rb_intern("tv");\ - Make_Data_Struct(obj, id_tv, struct time_object, Qnil, Qnil, tobj);\ + Make_Data_Struct(obj, id_tv, struct time_object, 0, 0, tobj);\ tobj->tm_got=0;\ } static VALUE -Stime_now(class) +time_s_now(class) VALUE class; { VALUE obj = obj_alloc(class); @@ -59,6 +74,7 @@ Stime_now(class) static VALUE time_new_internal(class, sec, usec) + VALUE class; int sec, usec; { VALUE obj = obj_alloc(class); @@ -75,7 +91,7 @@ VALUE time_new(sec, usec) int sec, usec; { - return time_new_internal(C_Time, sec, usec); + return time_new_internal(cTime, sec, usec); } struct timeval* @@ -107,7 +123,7 @@ time_timeval(time) break; default: - if (!obj_is_kind_of(time, C_Time)) { + if (!obj_is_kind_of(time, cTime)) { Fail("Can't convert %s into Time", rb_class2name(CLASS_OF(time))); } GetTimeval(time, tobj); @@ -118,12 +134,9 @@ time_timeval(time) } static VALUE -Stime_at(class, time) +time_s_at(class, time) VALUE class, time; { - VALUE obj; - int sec, usec; - struct time_object *tobj; struct timeval *tp; tp = time_timeval(time); @@ -132,7 +145,7 @@ Stime_at(class, time) } static VALUE -Ftime_to_i(time) +time_to_i(time) VALUE time; { struct time_object *tobj; @@ -142,7 +155,7 @@ Ftime_to_i(time) } static VALUE -Ftime_to_f(time) +time_to_f(time) VALUE time; { struct time_object *tobj; @@ -152,7 +165,7 @@ Ftime_to_f(time) } static VALUE -Ftime_usec(time) +time_usec(time) VALUE time; { struct time_object *tobj; @@ -162,14 +175,14 @@ Ftime_usec(time) } static VALUE -Ftime_cmp(time1, time2) +time_cmp(time1, time2) VALUE time1, time2; { struct time_object *tobj1, *tobj2; int i; GetTimeval(time1, tobj1); - if (obj_is_member_of(time2, C_Time)) { + if (obj_is_instance_of(time2, cTime)) { GetTimeval(time2, tobj2); if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) { if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return INT2FIX(0); @@ -186,7 +199,7 @@ Ftime_cmp(time1, time2) } static VALUE -Ftime_hash(time) +time_hash(time) VALUE time; { struct time_object *tobj; @@ -198,7 +211,7 @@ Ftime_hash(time) } static VALUE -Ftime_localtime(time) +time_localtime(time) VALUE time; { struct time_object *tobj; @@ -215,7 +228,7 @@ Ftime_localtime(time) } static VALUE -Ftime_gmtime(time) +time_gmtime(time) VALUE time; { struct time_object *tobj; @@ -232,17 +245,16 @@ Ftime_gmtime(time) } static VALUE -Ftime_asctime(time) +time_asctime(time) VALUE time; { struct time_object *tobj; - char *ct; char buf[32]; int len; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } #ifndef HAVE_TM_ZONE if (tobj->gmt == 1) @@ -256,21 +268,21 @@ Ftime_asctime(time) } static VALUE -Ftime_coerce(time1, time2) +time_coerce(time1, time2) VALUE time1, time2; { return time_new(CLASS_OF(time1), NUM2INT(time2), 0); } static VALUE -Ftime_plus(time1, time2) +time_plus(time1, time2) VALUE time1, time2; { struct time_object *tobj1, *tobj2; int sec, usec; GetTimeval(time1, tobj1); - if (obj_is_member_of(time2, C_Time)) { + if (obj_is_instance_of(time2, cTime)) { GetTimeval(time2, tobj2); sec = tobj1->tv.tv_sec + tobj2->tv.tv_sec; usec = tobj1->tv.tv_usec + tobj2->tv.tv_usec; @@ -287,14 +299,14 @@ Ftime_plus(time1, time2) } static VALUE -Ftime_minus(time1, time2) +time_minus(time1, time2) VALUE time1, time2; { struct time_object *tobj1, *tobj2; int sec, usec; GetTimeval(time1, tobj1); - if (obj_is_member_of(time2, C_Time)) { + if (obj_is_instance_of(time2, cTime)) { GetTimeval(time2, tobj2); sec = tobj1->tv.tv_sec - tobj2->tv.tv_sec; usec = tobj1->tv.tv_usec - tobj2->tv.tv_usec; @@ -311,124 +323,124 @@ Ftime_minus(time1, time2) } static VALUE -Ftime_sec(time) +time_sec(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_sec); } static VALUE -Ftime_min(time) +time_min(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_min); } static VALUE -Ftime_hour(time) +time_hour(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_hour); } static VALUE -Ftime_mday(time) +time_mday(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_mday); } static VALUE -Ftime_mon(time) +time_mon(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_mon); } static VALUE -Ftime_year(time) +time_year(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_year); } static VALUE -Ftime_wday(time) +time_wday(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_wday); } static VALUE -Ftime_yday(time) +time_yday(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_yday); } static VALUE -Ftime_isdst(time) +time_isdst(time) VALUE time; { struct time_object *tobj; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } return INT2FIX(tobj->tm.tm_isdst); } static VALUE -Ftime_zone(time) +time_zone(time) VALUE time; { struct time_object *tobj; @@ -437,7 +449,7 @@ Ftime_zone(time) GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } len = strftime(buf, 10, "%Z", &(tobj->tm)); @@ -445,17 +457,15 @@ Ftime_zone(time) } static VALUE -Ftime_to_a(time) +time_to_a(time) VALUE time; { struct time_object *tobj; - struct tm *tm; - char buf[10]; VALUE ary; GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } ary = ary_new3(9, INT2FIX(tobj->tm.tm_sec), @@ -471,7 +481,7 @@ Ftime_to_a(time) } static VALUE -Ftime_strftime(time, format) +time_strftime(time, format) VALUE time, format; { struct time_object *tobj; @@ -481,12 +491,12 @@ Ftime_strftime(time, format) Check_Type(format, T_STRING); GetTimeval(time, tobj); if (tobj->tm_got == 0) { - Ftime_localtime(time); + time_localtime(time); } if (strlen(RSTRING(format)->ptr) < RSTRING(format)->len) { /* Ruby string contains \0. */ VALUE str; - int l, total = 0; + int l; char *p = RSTRING(format)->ptr, *pe = p + RSTRING(format)->len; str = str_new(0, 0); @@ -503,60 +513,89 @@ Ftime_strftime(time, format) } static VALUE -Stime_times(obj) +time_s_times(obj) VALUE obj; { +#ifdef HAVE_TIMES +#ifndef HZ +#define HZ 60 /* Universal constant :-) */ +#endif /* HZ */ struct tms buf; if (times(&buf) == -1) rb_sys_fail(Qnil); - return struct_new("tms", - "utime", float_new((double)buf.tms_utime / 60.0), - "stime", float_new((double)buf.tms_stime / 60.0), - "cutime", float_new((double)buf.tms_cutime / 60.0), - "cstime", float_new((double)buf.tms_cstime / 60.0), + return struct_new(S_Tms, + float_new((double)buf.tms_utime / HZ), + float_new((double)buf.tms_stime / HZ), + float_new((double)buf.tms_cutime / HZ), + float_new((double)buf.tms_cstime / HZ), Qnil); +#else +#ifdef NT + FILETIME create, exit, kernel, user; + HANDLE hProc; + + hProc = GetCurrentProcess(); + GetProcessTimes(hProc,&create, &exit, &kernel, &user); + return struct_new(S_Tms, + float_new((double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime)/2E6), + float_new((double)(user.dwHighDateTime*2E32+user.dwLowDateTime)/2E6), + float_new((double)0), + float_new((double)0), + Qnil); +#else + Fail("can't call times"); + return Qnil; +#endif +#endif } +void Init_Time() { - C_Time = rb_define_class("Time", C_Object); - rb_include_module(C_Time, M_Comparable); - - rb_define_single_method(C_Time, "now", Stime_now, 0); - rb_define_single_method(C_Time, "new", Stime_now, 0); - rb_define_single_method(C_Time, "at", Stime_at, 1); - - rb_define_single_method(C_Time, "times", Stime_times, 0); - - rb_define_method(C_Time, "to_i", Ftime_to_i, 0); - rb_define_method(C_Time, "to_f", Ftime_to_f, 0); - rb_define_method(C_Time, "<=>", Ftime_cmp, 1); - rb_define_method(C_Time, "hash", Ftime_hash, 0); - - rb_define_method(C_Time, "localtime", Ftime_localtime, 0); - rb_define_method(C_Time, "gmtime", Ftime_gmtime, 0); - rb_define_method(C_Time, "ctime", Ftime_asctime, 0); - rb_define_method(C_Time, "asctime", Ftime_asctime, 0); - rb_define_method(C_Time, "to_s", Ftime_asctime, 0); - rb_define_method(C_Time, "_inspect", Ftime_asctime, 0); - rb_define_method(C_Time, "to_a", Ftime_to_a, 0); - rb_define_method(C_Time, "coerce", Ftime_coerce, 1); - - rb_define_method(C_Time, "+", Ftime_plus, 1); - rb_define_method(C_Time, "-", Ftime_minus, 1); - - rb_define_method(C_Time, "sec", Ftime_sec, 0); - rb_define_method(C_Time, "min", Ftime_min, 0); - rb_define_method(C_Time, "hour", Ftime_hour, 0); - rb_define_method(C_Time, "mday", Ftime_mday, 0); - rb_define_method(C_Time, "year", Ftime_year, 0); - rb_define_method(C_Time, "wday", Ftime_wday, 0); - rb_define_method(C_Time, "yday", Ftime_yday, 0); - rb_define_method(C_Time, "isdst", Ftime_isdst, 0); - - rb_define_method(C_Time, "tv_sec", Ftime_to_i, 0); - rb_define_method(C_Time, "tv_usec", Ftime_usec, 0); - rb_define_method(C_Time, "usec", Ftime_usec, 0); - - rb_define_method(C_Time, "strftime", Ftime_strftime, 1); + cTime = rb_define_class("Time", cObject); + rb_include_module(cTime, mComparable); + + rb_define_singleton_method(cTime, "now", time_s_now, 0); + rb_define_singleton_method(cTime, "new", time_s_now, 0); + rb_define_singleton_method(cTime, "at", time_s_at, 1); + + rb_define_singleton_method(cTime, "times", time_s_times, 0); + + rb_define_method(cTime, "to_i", time_to_i, 0); + rb_define_method(cTime, "to_f", time_to_f, 0); + rb_define_method(cTime, "<=>", time_cmp, 1); + rb_define_method(cTime, "hash", time_hash, 0); + + rb_define_method(cTime, "localtime", time_localtime, 0); + rb_define_method(cTime, "gmtime", time_gmtime, 0); + rb_define_method(cTime, "ctime", time_asctime, 0); + rb_define_method(cTime, "asctime", time_asctime, 0); + rb_define_method(cTime, "to_s", time_asctime, 0); + rb_define_method(cTime, "inspect", time_asctime, 0); + rb_define_method(cTime, "to_a", time_to_a, 0); + rb_define_method(cTime, "coerce", time_coerce, 1); + + rb_define_method(cTime, "+", time_plus, 1); + rb_define_method(cTime, "-", time_minus, 1); + + rb_define_method(cTime, "sec", time_sec, 0); + rb_define_method(cTime, "min", time_min, 0); + rb_define_method(cTime, "hour", time_hour, 0); + rb_define_method(cTime, "mday", time_mday, 0); + rb_define_method(cTime, "mon", time_mon, 0); + rb_define_method(cTime, "year", time_year, 0); + rb_define_method(cTime, "wday", time_wday, 0); + rb_define_method(cTime, "yday", time_yday, 0); + rb_define_method(cTime, "isdst", time_isdst, 0); + rb_define_method(cTime, "zone", time_zone, 0); + + rb_define_method(cTime, "tv_sec", time_to_i, 0); + rb_define_method(cTime, "tv_usec", time_usec, 0); + rb_define_method(cTime, "usec", time_usec, 0); + + rb_define_method(cTime, "strftime", time_strftime, 1); + +#if defined(HAVE_TIMES) || defined(NT) + S_Tms = struct_define("Tms", "utime", "stime", "cutime", "cstime", Qnil); +#endif } @@ -3,7 +3,6 @@ util.c - $Author$ - $Revision$ $Date$ created at: Fri Mar 10 17:22:34 JST 1995 diff --git a/variable.c b/variable.c index c6b180736d..9721c1c2d4 100644 --- a/variable.c +++ b/variable.c @@ -10,16 +10,14 @@ #include "ruby.h" #include "env.h" -#include "ident.h" #include "st.h" st_table *rb_global_tbl; st_table *rb_class_tbl; #define global_tbl rb_global_tbl #define class_tbl rb_class_tbl -#define instance_tbl (RBASIC(Qself)->iv_tbl) -VALUE rb_const_bound(); +VALUE rb_const_defined(); VALUE rb_const_get(); st_table * @@ -39,11 +37,31 @@ char * rb_class2path(class) VALUE class; { - VALUE path = rb_ivar_get_1(class, rb_intern("__classpath__")); + VALUE path; + + while (TYPE(class) == T_ICLASS) { + class = (VALUE)RCLASS(class)->super; + } + path = rb_ivar_get(class, rb_intern("__classpath__")); if (TYPE(path) != T_STRING) Bug("class path does not set properly"); return RSTRING(path)->ptr; } +VALUE +rb_class_path(class) + VALUE class; +{ + char *name = rb_class2path(class); + + if (strchr(name, ':')) { + VALUE ary = str_split(str_new2(name), ":"); + ary_pop(ary); + ary = ary_reverse(ary); + return ary_join(ary, str_new2("::")); + } + return str_new2(name); +} + void rb_set_class_path(class, under, name) VALUE class, under; @@ -58,7 +76,7 @@ rb_set_class_path(class, under, name) s = rb_class2path(under); str_cat(str, s, strlen(s)); } - rb_ivar_set_1(class, rb_intern("__classpath__"), str); + rb_ivar_set(class, rb_intern("__classpath__"), str); } VALUE @@ -88,7 +106,7 @@ rb_path2class(path) } *s = '\0'; id = rb_intern(name); - if (!rb_const_bound(class, id)) + if (!rb_const_defined(class, id)) Fail("%s not defined", name); class = rb_const_get(class, id); switch (TYPE(class)) { @@ -106,7 +124,39 @@ rb_name_class(class, id) VALUE class; ID id; { - rb_ivar_set_1(class, rb_intern("__classname__"), INT2FIX(id)); + rb_ivar_set(class, rb_intern("__classname__"), INT2FIX(id)); +} + +static st_table *autoload_tbl = 0; + +static void +rb_autoload_id(id, filename) + ID id; + char *filename; +{ + if (!autoload_tbl) { + autoload_tbl = new_idhash(); + } + st_insert(autoload_tbl, id, strdup(filename)); +} + +void +rb_autoload(class, filename) + char *class, *filename; +{ + rb_autoload_id(rb_intern(class), filename); +} + +VALUE +f_autoload(obj, class, file) + VALUE obj, class; + struct RString *file; +{ + ID id = rb_to_id(class); + + Check_Type(file, T_STRING); + rb_autoload_id(id, file->ptr); + return Qnil; } char * @@ -130,7 +180,7 @@ rb_class2name(class) class = (struct RClass*)class->super; } - name = rb_ivar_get_1(class, rb_intern("__classname__")); + name = rb_ivar_get(class, rb_intern("__classname__")); if (name) { name = FIX2INT(name); return rb_id2name((ID)name); @@ -138,45 +188,33 @@ rb_class2name(class) Bug("class 0x%x not named", class); } +struct trace_var { + void (*func)(); + void *data; + struct trace_var *next; +}; + struct global_entry { - enum { GLOBAL_VAL, GLOBAL_VAR, GLOBAL_UNDEF } mode; ID id; - union { - VALUE val; - VALUE *var; - } v; - VALUE (*get_hook)(); - VALUE (*set_hook)(); void *data; + VALUE (*getter)(); + void (*setter)(); + void (*marker)(); + int block_trace; + struct trace_var *trace; }; -static -mark_global_entry(key, entry) - ID key; - struct global_entry *entry; -{ - switch (entry->mode) { - case GLOBAL_VAL: - gc_mark(entry->v.val); /* normal global value */ - break; - case GLOBAL_VAR: - if (entry->v.var) - gc_mark(*entry->v.var); /* c variable pointer */ - break; - default: - break; - } - if (entry->data) { - gc_mark_maybe(entry->data); - } - return ST_CONTINUE; -} +static VALUE undef_getter(); +static void undef_setter(); +static void undef_marker(); -void -gc_mark_global_tbl() -{ - st_foreach(global_tbl, mark_global_entry, 0); -} +static VALUE val_getter(); +static void val_setter(); +static void val_marker(); + +static VALUE var_getter(); +static void var_setter(); +static void var_marker(); struct global_entry* rb_global_entry(id) @@ -188,22 +226,129 @@ rb_global_entry(id) entry = ALLOC(struct global_entry); st_insert(global_tbl, id, entry); entry->id = id; - entry->mode = GLOBAL_UNDEF; - entry->v.var = Qnil; - entry->get_hook = entry->set_hook = Qnil; + entry->data = 0; + entry->getter = undef_getter; + entry->setter = undef_setter; + entry->marker = undef_marker; + + entry->block_trace = 0; + entry->trace = 0; } return entry; } -void -rb_define_variable(name, var, get_hook, set_hook, data) - char *name; - VALUE *var; - VALUE (*get_hook)(); - VALUE (*set_hook)(); +static VALUE +undef_getter(id) + ID id; +{ + Warning("global var %s not initialized", rb_id2name(id)); + return Qnil; +} + +static void +undef_setter(val, id, data, entry) + VALUE val; + ID id; + void *data; + struct global_entry *entry; +{ + entry->getter = val_getter; + entry->setter = val_setter; + entry->marker = val_marker; + + entry->data = (void*)val; +} + +static void +undef_marker() +{ +} + +static VALUE +val_getter(id, val) + ID id; + VALUE val; +{ + return val; +} + +static void +val_setter(val, id, data, entry) + VALUE val; + ID id; + void *data; + struct global_entry *entry; +{ + entry->data = (void*)val; +} + +static void +val_marker(data) void *data; { + if (data) gc_mark_maybe(data); +} + +static VALUE +var_getter(id, var) + ID id; + VALUE *var; +{ + if (!var || !*var) return Qnil; + return *var; +} + +static void +var_setter(val, id, var) + VALUE val; + ID id; + VALUE *var; +{ + *var = val; +} + +static void +var_marker(var) + VALUE **var; +{ + if (var) gc_mark_maybe(*var); +} + +static void +readonly_setter(id, var, val) + ID id; + void *var; + VALUE val; +{ + Fail("Can't set variable %s", rb_id2name(id)); +} + +static int +mark_global_entry(key, entry) + ID key; struct global_entry *entry; +{ + struct trace_var *trace; + + (*entry->marker)(entry->data); + trace = entry->trace; + while (trace) { + if (trace->data) gc_mark_maybe(trace->data); + trace = trace->next; + } + return ST_CONTINUE; +} + +void +gc_mark_global_tbl() +{ + st_foreach(global_tbl, mark_global_entry, 0); +} + +static ID +global_id(name) + char *name; +{ ID id; if (name[0] == '$') id = rb_intern(name); @@ -213,80 +358,143 @@ rb_define_variable(name, var, get_hook, set_hook, data) strcpy(buf+1, name); id = rb_intern(buf); } + return id; +} + +void +rb_define_hooked_variable(name, var, getter, setter) + char *name; + VALUE *var; + VALUE (*getter)(); + void (*setter)(); +{ + struct global_entry *entry; + ID id = global_id(name); entry = rb_global_entry(id); - entry->mode = GLOBAL_VAR; - entry->v.var = var; - entry->get_hook = get_hook; - entry->set_hook = set_hook; - entry->data = data; + entry->data = (void*)var; + entry->getter = getter?getter:var_getter; + entry->setter = setter?setter:var_setter; + entry->marker = var_marker; } void -rb_define_varhook(name, get_hook, set_hook, data) +rb_define_variable(name, var) char *name; - VALUE (*get_hook)(); - VALUE (*set_hook)(); - void *data; + VALUE *var; { - struct global_entry *entry; + rb_define_hooked_variable(name, var, 0, 0); +} + +void +rb_define_readonly_variable(name, var) + char *name; + VALUE *var; +{ + rb_define_hooked_variable(name, var, 0, readonly_setter); +} + +void +rb_define_virtual_variable(name, getter, setter) + char *name; + VALUE (*getter)(); + void (*setter)(); +{ + if (!getter) getter = val_getter; + if (!setter) setter = readonly_setter; + rb_define_hooked_variable(name, 0, getter, setter); +} + +void rb_trace_eval(); + +void +rb_trace_eval(cmd, val) + VALUE cmd, val; +{ + rb_eval_cmd(cmd, ary_new3(1, val)); +} + +VALUE +f_trace_var(argc, argv) + int argc; + VALUE *argv; +{ + VALUE var, cmd; ID id; + struct global_entry *entry; + struct trace_var *trace; - if (name[0] == '$') id = rb_intern(name); - else { - char *buf = ALLOCA_N(char, strlen(name)+2); - buf[0] = '$'; - strcpy(buf+1, name); - id = rb_intern(buf); + if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) { + cmd = f_lambda(); } - + id = rb_to_id(var); if (!st_lookup(global_tbl, id, &entry)) { - entry = ALLOC(struct global_entry); - entry->id = id; - entry->mode = GLOBAL_VAL; - st_insert(global_tbl, id, entry); - } - else if (entry->mode == GLOBAL_UNDEF) { - entry->mode = GLOBAL_VAL; - } - entry->v.val = Qnil; - entry->get_hook = get_hook; - entry->set_hook = set_hook; - if (data) { - entry->data = data; + Fail("undefined global variable %s", rb_id2name(id)); } + trace = ALLOC(struct trace_var); + trace->next = entry->trace; + trace->func = rb_trace_eval; + trace->data = (void*)cmd; + entry->trace = trace; + + return Qnil; } VALUE -rb_readonly_hook(val, id) - VALUE val; - ID id; +f_untrace_var(obj, var) + VALUE obj, var; { - Fail("Can't set variable %s", rb_id2name(id)); - /* not reached */ + ID id; + struct global_entry *entry; + struct trace_var *trace; + VALUE ary; + + id = rb_to_id(var); + if (!st_lookup(global_tbl, id, &entry)) { + Fail("undefined global variable %s", rb_id2name(id)); + } + ary = ary_new(); + trace = entry->trace; + while (trace) { + struct trace_var *next = trace->next; + ary_push(ary, trace->data); + free(trace); + trace = next; + } + entry->trace = 0; + + return ary; } VALUE rb_gvar_get(entry) struct global_entry *entry; { - VALUE val; - - if (entry->get_hook) - val = (*entry->get_hook)(entry->id, entry->data); - switch (entry->mode) { - case GLOBAL_VAL: - return entry->v.val; + return (*entry->getter)(entry->id, entry->data, entry); +} - case GLOBAL_VAR: - if (entry->v.var == Qnil) return val; - return *entry->v.var; +struct trace_data { + struct trace_var *trace; + VALUE val; +}; + +static void +trace_ev(data) + struct trace_data *data; +{ + struct trace_var *trace = data->trace; - default: - break; + while (trace) { + (*trace->func)(trace->data, data->val); + trace = trace->next; } - Warning("global var %s not initialized", rb_id2name(entry->id)); - return Qnil; +} + +static void +trace_en(entry) + struct global_entry *entry; +{ + entry->block_trace = 0; } VALUE @@ -294,19 +502,15 @@ rb_gvar_set(entry, val) struct global_entry *entry; VALUE val; { - if (entry->set_hook) - (*entry->set_hook)(val, entry->id, entry->data); + struct trace_data trace; - if (entry->mode == GLOBAL_VAR) { - if (entry->v.var) { - *entry->v.var = val; - } - } - else { - if (entry->mode == GLOBAL_UNDEF) { - entry->mode = GLOBAL_VAL; - } - entry->v.val = val; + (*entry->setter)(val, entry->id, entry->data, entry); + + if (!entry->block_trace) { + entry->block_trace = 1; + trace.trace = entry->trace; + trace.val = val; + rb_ensure(trace_ev, &trace, trace_en, entry); } return val; } @@ -317,19 +521,21 @@ rb_gvar_set2(name, val) VALUE val; { struct global_entry *entry; - ID id; - id = rb_intern(name); - if (!st_lookup(global_tbl, id, &entry)) { - entry = rb_global_entry(id); - } - rb_gvar_set(entry, val); + entry = rb_global_entry(global_id(name)); + return rb_gvar_set(entry, val); +} - return val; +VALUE +rb_gvar_defined(entry) + struct global_entry *entry; +{ + if (entry->getter == undef_getter) return FALSE; + return TRUE; } VALUE -rb_ivar_get_1(obj, id) +rb_ivar_get(obj, id) struct RObject *obj; ID id; { @@ -352,14 +558,7 @@ rb_ivar_get_1(obj, id) } VALUE -rb_ivar_get(id) - ID id; -{ - return rb_ivar_get_1(Qself, id); -} - -VALUE -rb_ivar_set_1(obj, id, val) +rb_ivar_set(obj, id, val) struct RObject *obj; ID id; VALUE val; @@ -368,7 +567,7 @@ rb_ivar_set_1(obj, id, val) case T_OBJECT: case T_CLASS: case T_MODULE: - if (obj->iv_tbl == Qnil) obj->iv_tbl = new_idhash(); + if (!obj->iv_tbl) obj->iv_tbl = new_idhash(); st_insert(obj->iv_tbl, id, val); break; default: @@ -380,11 +579,19 @@ rb_ivar_set_1(obj, id, val) } VALUE -rb_ivar_set(id, val) +rb_ivar_defined(obj, id) + struct RObject *obj; ID id; - VALUE val; { - return rb_ivar_set_1(Qself, id, val); + switch (TYPE(obj)) { + case T_OBJECT: + case T_CLASS: + case T_MODULE: + if (obj->iv_tbl && st_lookup(obj->iv_tbl, id, 0)) + return TRUE; + break; + } + return FALSE; } VALUE @@ -393,40 +600,58 @@ rb_const_get(class, id) ID id; { VALUE value; + struct RClass *tmp; - while (class) { - if (class->iv_tbl && st_lookup(class->iv_tbl, id, &value)) { + tmp = class; + while (tmp) { + if (tmp->iv_tbl && st_lookup(tmp->iv_tbl, id, &value)) { return value; } - if (BUILTIN_TYPE(class) == T_MODULE) { - class = RCLASS(C_Object); - } - else { - class = class->super; - } + tmp = tmp->super; + } + if (BUILTIN_TYPE(class) == T_MODULE) { + return rb_const_get(cObject, id); } /* pre-defined class */ if (st_lookup(class_tbl, id, &value)) return value; - /* here comes autoload code in the future. */ + /* autoload */ + if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) { + char *modname; + VALUE module; - Fail("Uninitialized constant %s", rb_id2name(id)); + st_delete(autoload_tbl, &id, &modname); + module = str_new2(modname); + free(modname); + f_require(Qnil, module); + return rb_const_get(class, id); + } + + /* Uninitialized constant */ + if (class && (VALUE)class != cObject) + Fail("Uninitialized constant %s::%s", + RSTRING(rb_class_path(class))->ptr, + rb_id2name(id)); + else + Fail("Uninitialized constant %s",rb_id2name(id)); /* not reached */ } VALUE -rb_const_bound(class, id) +rb_const_defined(class, id) struct RClass *class; ID id; { while (class) { - if (class->iv_tbl && st_lookup(class->iv_tbl, id, Qnil)) { + if (class->iv_tbl && st_lookup(class->iv_tbl, id, 0)) { return TRUE; } class = class->super; } - if (st_lookup(class_tbl, id, Qnil)) + if (st_lookup(class_tbl, id, 0)) + return TRUE; + if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) return TRUE; return FALSE; } @@ -437,10 +662,10 @@ rb_const_set(class, id, val) ID id; VALUE val; { - if (rb_const_bound(class, id)) - Fail("already initialized constnant"); + if (rb_const_defined(class, id)) + Fail("already initialized constnant %s", rb_id2name(id)); - if (class->iv_tbl == Qnil) class->iv_tbl = new_idhash(); + if (!class->iv_tbl) class->iv_tbl = new_idhash(); st_insert(class->iv_tbl, id, val); } @@ -460,7 +685,7 @@ rb_iv_get(obj, name) { ID id = rb_intern(name); - return rb_ivar_get_1(obj, id); + return rb_ivar_get(obj, id); } VALUE @@ -471,5 +696,35 @@ rb_iv_set(obj, name, val) { ID id = rb_intern(name); - return rb_ivar_set_1(obj, id, val); + return rb_ivar_set(obj, id, val); +} + +VALUE +backref_get() +{ + int cnt, max; + + if (!the_scope->local_vars) return Qnil; + for (cnt=1, max=the_scope->local_tbl[0]+1; cnt<max ;cnt++) { + if (the_scope->local_tbl[cnt] == '~') { + cnt--; + if (the_scope->local_vars[cnt]) + return the_scope->local_vars[cnt]; + else + return 1; + } + } + return Qnil; +} + +void +backref_set(val) + VALUE val; +{ + int cnt, max; + + for (cnt=1, max=the_scope->local_tbl[0]+1; cnt<max ;cnt++) { + if (the_scope->local_tbl[cnt] == '~') break; + } + the_scope->local_vars[cnt-1] = val; } @@ -15,18 +15,21 @@ #include "version.h" #include <stdio.h> -extern VALUE C_Kernel; +extern VALUE cKernel; +void Init_version() { - rb_define_const(C_Kernel, "VERSION", str_new2(RUBY_VERSION)); + rb_define_const(cKernel, "VERSION", str_new2(RUBY_VERSION)); } +void show_version() { fprintf(stderr, "ruby - version %s (%s)\n", RUBY_VERSION, VERSION_DATE); } +void show_copyright() { fprintf(stderr, "ruby - Copyright (C) 1993-1995 Yukihiro Matsumoto\n"); @@ -1,2 +1,2 @@ -#define RUBY_VERSION "0.76" -#define VERSION_DATE "95/05/19" +#define RUBY_VERSION "0.95" +#define VERSION_DATE "95/12/21" |