summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1995-12-21 00:56:57 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 22:09:32 +0900
commitfca49a8a69a0f6bb4feae74c6cd0e93d7fac8b36 (patch)
tree590a6d2ffcfa31212c1595e34a01d9cda56ba308
parent8bf1c909dc31fd4bcdc1488cda9fe89a62bc2830 (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-IF204
-rw-r--r--ChangeLog713
-rw-r--r--FAQ65
-rw-r--r--MANIFEST84
-rw-r--r--Makefile.in100
-rw-r--r--README182
-rw-r--r--README.EXT308
-rw-r--r--ToDo5
-rw-r--r--array.c374
-rw-r--r--assoc.c150
-rw-r--r--bignum.c147
-rw-r--r--class.c76
-rw-r--r--compar.c29
-rw-r--r--configure.in176
-rw-r--r--defines.h16
-rw-r--r--dir.c85
-rw-r--r--dln.c539
-rw-r--r--dln.h12
-rw-r--r--dmyext.c4
-rw-r--r--enum.c118
-rw-r--r--env.h22
-rw-r--r--error.c41
-rw-r--r--eval.c1537
-rw-r--r--ext/MANIFEST3
-rw-r--r--ext/Setup7
-rw-r--r--ext/dbm/MANIFEST5
-rw-r--r--ext/dbm/dbm.c435
-rw-r--r--ext/dbm/dbm.doc107
-rw-r--r--ext/dbm/depend1
-rw-r--r--ext/dbm/extconf.rb4
-rw-r--r--ext/etc/MANIFEST5
-rw-r--r--ext/etc/depend1
-rw-r--r--ext/etc/etc.c (renamed from etc.c)143
-rw-r--r--ext/etc/etc.doc73
-rw-r--r--ext/etc/extconf.rb7
-rw-r--r--ext/extmk.rb.in398
-rw-r--r--ext/marshal/MANIFEST4
-rw-r--r--ext/marshal/depend2
-rw-r--r--ext/marshal/marshal.c565
-rw-r--r--ext/marshal/marshal.doc45
-rw-r--r--ext/socket/MANIFEST5
-rw-r--r--ext/socket/depend1
-rw-r--r--ext/socket/extconf.rb6
-rw-r--r--ext/socket/socket.c785
-rw-r--r--ext/socket/socket.doc227
-rw-r--r--ext/tkutil/MANIFEST3
-rw-r--r--ext/tkutil/extconf.rb11
-rw-r--r--ext/tkutil/tkutil.c54
-rw-r--r--file.c782
-rw-r--r--gc.c161
-rw-r--r--glob.c9
-rw-r--r--hash.c283
-rw-r--r--ident.h26
-rw-r--r--inits.c9
-rw-r--r--io.c544
-rw-r--r--io.h11
-rw-r--r--lib/base64.rb55
-rw-r--r--lib/find.rb38
-rw-r--r--lib/getopts.rb (renamed from sample/getopts.rb)0
-rw-r--r--lib/mailread.rb45
-rw-r--r--lib/parsearg.rb (renamed from sample/parsearg.rb)0
-rw-r--r--lib/parsedate.rb42
-rw-r--r--lib/tk.rb1215
-rw-r--r--lib/tkcanvas.rb318
-rw-r--r--lib/tkclass.rb36
-rw-r--r--lib/tkentry.rb74
-rw-r--r--lib/tktext.rb160
-rw-r--r--main.c1
-rw-r--r--math.c46
-rw-r--r--missing/MANIFEST10
-rw-r--r--missing/crypt.c276
-rw-r--r--missing/dup2.c36
-rw-r--r--missing/nt.c1732
-rw-r--r--missing/nt.h246
-rw-r--r--missing/setenv.c73
-rw-r--r--node.h28
-rw-r--r--numeric.c367
-rw-r--r--object.c314
-rw-r--r--pack.c20
-rw-r--r--parse.y963
-rw-r--r--process.c184
-rw-r--r--random.c11
-rw-r--r--range.c80
-rw-r--r--re.c387
-rw-r--r--re.h10
-rw-r--r--regex.c18
-rw-r--r--regex.h1
-rw-r--r--ruby.1248
-rw-r--r--ruby.c107
-rw-r--r--ruby.h140
-rw-r--r--ruby.texi5044
-rw-r--r--sample/MANIFEST63
-rw-r--r--sample/aset.rb7
-rw-r--r--sample/attr.rb14
-rw-r--r--sample/blk.rb9
-rw-r--r--sample/case.rb14
-rw-r--r--sample/cat.rb5
-rw-r--r--sample/cat2.rb5
-rw-r--r--sample/clnt.rb3
-rw-r--r--sample/clone.rb18
-rw-r--r--sample/const.rb24
-rw-r--r--sample/dbm.rb2
-rw-r--r--sample/exyacc.rb20
-rwxr-xr-xsample/from.rb102
-rw-r--r--sample/gctest.rb67
-rw-r--r--sample/gctest2.rb71
-rw-r--r--sample/hash.rb11
-rw-r--r--sample/list3.rb6
-rw-r--r--sample/marshal.rb13
-rw-r--r--sample/math.rb4
-rw-r--r--sample/mkproto.rb27
-rw-r--r--sample/occur2.rb2
-rw-r--r--sample/opt_s.rb12
-rw-r--r--sample/opt_x.test10
-rw-r--r--sample/rcs.rb2
-rw-r--r--sample/ruby-mode.el305
-rw-r--r--sample/samp.rb15
-rw-r--r--sample/sieve.rb2
-rw-r--r--sample/split.rb13
-rw-r--r--sample/struct.rb8
-rw-r--r--sample/svr.rb2
-rw-r--r--sample/system.rb2
-rw-r--r--sample/t1.rb20
-rw-r--r--sample/t2.rb23
-rw-r--r--sample/test.rb1043
-rw-r--r--sample/tkbiff.rb121
-rw-r--r--sample/tkbrowse.rb69
-rw-r--r--sample/tkdialog.rb62
-rw-r--r--sample/tkfrom.rb115
-rw-r--r--sample/tkhello.rb13
-rw-r--r--sample/tkline.rb29
-rw-r--r--sample/tktimer.rb49
-rw-r--r--sample/trap.pl6
-rw-r--r--sample/trap.rb3
-rw-r--r--sample/tt.rb100
-rw-r--r--sig.h28
-rw-r--r--signal.c200
-rw-r--r--spec3538
-rw-r--r--sprintf.c49
-rw-r--r--st.c91
-rw-r--r--st.h2
-rw-r--r--string.c708
-rw-r--r--struct.c399
-rw-r--r--time.c239
-rw-r--r--util.c1
-rw-r--r--variable.c553
-rw-r--r--version.c7
-rw-r--r--version.h4
148 files changed, 21293 insertions, 9071 deletions
diff --git a/C-IF b/C-IF
deleted file mode 100644
index 5c66a20ddc..0000000000
--- a/C-IF
+++ /dev/null
@@ -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:
- */
diff --git a/ChangeLog b/ChangeLog
index ce97fa374c..9a7479823d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 document󶡡specruby.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ĴᤷƤ롥
diff --git a/FAQ b/FAQ
deleted file mode 100644
index eaa9c86056..0000000000
--- a/FAQ
+++ /dev/null
@@ -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:
diff --git a/MANIFEST b/MANIFEST
index fa904ff5d9..81c7a3a646 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -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
diff --git a/README b/README
index 9dc79e8e26..ad239f98d2 100644
--- a/README
+++ b/README
@@ -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:
+ */
diff --git a/ToDo b/ToDo
index 1f18bb9241..5322a83b25 100644
--- a/ToDo
+++ b/ToDo
@@ -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
diff --git a/array.c b/array.c
index 05bb79704d..91f7aace9f 100644
--- a/array.c
+++ b/array.c
@@ -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);
-}
diff --git a/bignum.c b/bignum.c
index 84bda92821..a9bbe9b272 100644
--- a/bignum.c
+++ b/bignum.c
@@ -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);
}
diff --git a/class.c b/class.c
index 4ad91e40ee..204c476fa7 100644
--- a/class.c
+++ b/class.c
@@ -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;
}
diff --git a/compar.c b/compar.c
index 8991d2641c..e7d1e62d79 100644
--- a/compar.c
+++ b/compar.c
@@ -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)
diff --git a/defines.h b/defines.h
index e4a11c9406..2eb509f214 100644
--- a/defines.h
+++ b/defines.h
@@ -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
diff --git a/dir.c b/dir.c
index 84feea5d79..f291b94da2 100644
--- a/dir.c
+++ b/dir.c
@@ -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);
}
diff --git a/dln.c b/dln.c
index 8e174d3c3b..84ffef3aac 100644
--- a/dln.c
+++ b/dln.c
@@ -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') {
diff --git a/dln.h b/dln.h
index ce39b29ae5..79d99e74c1 100644
--- a/dln.h
+++ b/dln.h
@@ -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()
+{
+}
diff --git a/enum.c b/enum.c
index b41f9ecec7..df277a504a 100644
--- a/enum.c
+++ b/enum.c
@@ -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);
}
diff --git a/env.h b/env.h
index cf79143429..5f31e5cebc 100644
--- a/env.h
+++ b/env.h
@@ -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 */
diff --git a/error.c b/error.c
index ff6eb9b365..6634663eb1 100644
--- a/error.c
+++ b/error.c
@@ -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;
diff --git a/eval.c b/eval.c
index a96e84ef3c..c1363a6840 100644
--- a/eval.c
+++ b/eval.c
@@ -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
diff --git a/etc.c b/ext/etc/etc.c
index 130592ec78..e4e4098f8a 100644
--- a/etc.c
+++ b/ext/etc/etc.c
@@ -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);
+}
diff --git a/file.c b/file.c
index e09ec7b21c..0691545c6a 100644
--- a/file.c
+++ b/file.c
@@ -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);
}
diff --git a/gc.c b/gc.c
index 667e020942..e3c809cded 100644
--- a/gc.c
+++ b/gc.c
@@ -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);
}
diff --git a/glob.c b/glob.c
index 68e76ad3b0..b0c750f243 100644
--- a/glob.c
+++ b/glob.c
@@ -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))
diff --git a/hash.c b/hash.c
index 387e164ce2..da4671409f 100644
--- a/hash.c
+++ b/hash.c
@@ -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
diff --git a/inits.c b/inits.c
index e6e1495562..673b6eed4b 100644
--- a/inits.c
+++ b/inits.c
@@ -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();
}
diff --git a/io.c b/io.c
index d9c93889f6..47bd4b0fb0 100644
--- a/io.c
+++ b/io.c
@@ -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);
diff --git a/io.h b/io.h
index 8fc642e8f2..b3772c9a2f 100644
--- a/io.h
+++ b/io.h
@@ -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
diff --git a/main.c b/main.c
index 0dee01c269..3630f8aa7b 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,7 @@
************************************************/
+void
main(argc, argv, envp)
int argc;
char **argv, **envp;
diff --git a/math.c b/math.c
index 4a209c71b9..41a4232083 100644
--- a/math.c
+++ b/math.c
@@ -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 */
+}
diff --git a/node.h b/node.h
index 3c9dd4b8f9..f69258ab4c 100644
--- a/node.h
+++ b/node.h
@@ -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
diff --git a/numeric.c b/numeric.c
index f50cef5a64..ba91d0de21 100644
--- a/numeric.c
+++ b/numeric.c
@@ -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);
}
diff --git a/object.c b/object.c
index 5cde809d75..74324b77e7 100644
--- a/object.c
+++ b/object.c
@@ -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)