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); |