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)
- int argc;
- VALUE *argv;
- int ex;
+ID
+rb_to_id(name)
+ VALUE name;
{
- VALUE self = Qself;
- int i;
- ID id;
-
- for (i=0; i<argc; i++) {
- if (FIXNUM_P(argv[i])) {
- id = FIX2INT(argv[i]);
- }
- else {
- Check_Type(argv[i], T_STRING);
- id = rb_intern(RSTRING(argv[i])->ptr);
- }
- rb_export_method(self, id, ex);
+ if (TYPE(name) == T_STRING) {
+ return rb_intern(RSTRING(name)->ptr);
}
+ return NUM2INT(name);
}
static VALUE
-Fcls_public(argc, argv)
+mod_attr(argc, argv, class)
int argc;
VALUE *argv;
+ VALUE class;
{
- method_visibility(argc, argv, NOEX_PUBLIC);
- return Qnil;
-}
+ VALUE name, pub;
+ ID id;
-static VALUE
-Fcls_private(argc, argv)
- int argc;
- VALUE *argv;
-{
- method_visibility(argc, argv, NOEX_PRIVATE);
+ rb_scan_args(argc, argv, "11", &name, &pub);
+ rb_define_attr(class, rb_to_id(name), pub);
return Qnil;
}
static VALUE
-Fcant_clone(obj)
- VALUE obj;
+mod_public_attr(class, name)
+ VALUE class, name;
{
- Fail("can't clone %s", rb_class2name(CLASS_OF(obj)));
+ rb_define_attr(class, rb_to_id(name), 1);
+ return Qnil;
}
static VALUE
-Fdata_class(data)
- VALUE data;
+mod_private_attr(class, name)
+ VALUE class, name;
{
- return C_Data;
+ rb_define_attr(class, rb_to_id(name), 0);
+ return Qnil;
}
static
@@ -376,21 +376,22 @@ VALUE boot_defclass(name, super)
}
VALUE TopSelf;
-VALUE TRUE = 1;
+VALUE TRUE = INT2FIX(1);
+void
Init_Object()
{
VALUE metaclass;
- C_Kernel = boot_defclass("Kernel", Qnil);
- C_Object = boot_defclass("Object", C_Kernel);
- C_Module = boot_defclass("Module", C_Object);
- C_Class = boot_defclass("Class", C_Module);
+ cKernel = boot_defclass("Kernel", Qnil);
+ cObject = boot_defclass("Object", cKernel);
+ cModule = boot_defclass("Module", cObject);
+ cClass = boot_defclass("Class", cModule);
- metaclass = RBASIC(C_Kernel)->class = single_class_new(C_Class);
- metaclass = RBASIC(C_Object)->class = single_class_new(metaclass);
- metaclass = RBASIC(C_Module)->class = single_class_new(metaclass);
- metaclass = RBASIC(C_Class)->class = single_class_new(metaclass);
+ metaclass = RBASIC(cKernel)->class = singleton_class_new(cClass);
+ metaclass = RBASIC(cObject)->class = singleton_class_new(metaclass);
+ metaclass = RBASIC(cModule)->class = singleton_class_new(metaclass);
+ metaclass = RBASIC(cClass)->class = singleton_class_new(metaclass);
/*
* Ruby's Class Hierarchy Chart
@@ -423,63 +424,60 @@ Init_Object()
*/
- rb_define_method(C_Kernel, "is_nil", P_false, 0);
- rb_define_method(C_Kernel, "==", Fkrn_equal, 1);
- rb_define_alias(C_Kernel, "equal", "==");
- rb_define_method(C_Kernel, "hash", Fkrn_id, 0);
- rb_define_method(C_Kernel, "id", Fkrn_id, 0);
- rb_define_method(C_Kernel, "class", Fkrn_class, 0);
- rb_define_alias(C_Kernel, "=~", "==");
+ rb_define_method(cKernel, "nil?", krn_nil_p, 0);
+ rb_define_method(cKernel, "==", krn_equal, 1);
+ rb_define_alias(cKernel, "equal?", "==");
+ rb_define_alias(cKernel, "=~", "==");
- rb_define_method(C_Kernel, "to_a", Fkrn_to_a, 0);
- rb_define_method(C_Kernel, "to_s", Fkrn_to_s, 0);
- rb_define_method(C_Kernel, "_inspect", Fkrn_inspect, 0);
+ rb_define_method(cKernel, "hash", krn_id, 0);
+ rb_define_method(cKernel, "id", krn_id, 0);
+ rb_define_method(cKernel, "type", krn_type, 0);
- rb_define_private_method(C_Kernel, "sprintf", Fsprintf, -1);
- rb_define_alias(C_Kernel, "format", "sprintf");
+ rb_define_method(cKernel, "clone", krn_clone, 0);
+ rb_define_method(cKernel, "dup", krn_dup, 0);
- rb_define_private_method(C_Object, "initialize", Fobj_initialize, -1);
- rb_define_private_method(C_Object, "single_method_added", Fobj_s_added, 1);
+ rb_define_method(cKernel, "to_a", krn_to_a, 0);
+ rb_define_method(cKernel, "to_s", krn_to_s, 0);
+ rb_define_method(cKernel, "inspect", krn_inspect, 0);
- rb_define_method(C_Object, "clone", Fobj_clone, 0);
+ rb_define_private_method(cKernel, "sprintf", f_sprintf, -1);
+ rb_define_alias(cKernel, "format", "sprintf");
- rb_define_method(C_Object, "responds_to", obj_responds_to, 1);
- rb_define_method(C_Object, "is_member_of", obj_is_member_of, 1);
- rb_define_method(C_Object, "is_kind_of", obj_is_kind_of, 1);
- rb_define_method(C_Object, "clone", Fobj_clone, 0);
+ rb_define_private_method(cObject, "initialize", obj_initialize, -1);
+ rb_define_private_method(cObject, "singleton_method_added", obj_s_added, 1);
- rb_define_method(C_Module, "to_s", Fcls_to_s, 0);
- rb_define_method(C_Module, "clone", Fcant_clone, 0);
- rb_define_private_method(C_Module, "attr", Fcls_attr, -1);
+ rb_define_method(cObject, "is_instance_of?", obj_is_instance_of, 1);
+ rb_define_method(cObject, "is_kind_of?", obj_is_kind_of, 1);
+ rb_define_method(cObject, "inspect", obj_inspect, 0);
- rb_define_method(C_Module, "public", Fcls_public, -1);
- rb_define_method(C_Module, "private", Fcls_private, -1);
+ rb_define_method(cModule, "to_s", mod_to_s, 0);
+ rb_define_method(cModule, "clone", mod_clone, 0);
+ rb_define_private_method(cModule, "attr", mod_attr, -1);
+ rb_define_private_method(cModule, "public_attr", mod_public_attr, -1);
+ rb_define_private_method(cModule, "private_attr", mod_private_attr, -1);
- rb_define_method(C_Class, "new", Fcls_new, -1);
+ rb_define_method(cClass, "new", mod_new, -1);
- C_Nil = rb_define_class("Nil", C_Kernel);
- rb_define_method(C_Nil, "to_s", Fnil_to_s, 0);
- rb_define_method(C_Nil, "clone", P_false, 0);
- rb_define_method(C_Nil, "class", Fnil_class, 0);
+ cNil = rb_define_class("Nil", cKernel);
+ rb_define_method(cNil, "to_s", nil_to_s, 0);
+ rb_define_method(cNil, "type", nil_type, 0);
- rb_define_method(C_Nil, "is_nil", P_true, 0);
+ rb_define_method(cNil, "nil?", nil_nil_p, 0);
/* default addition */
- rb_define_method(C_Nil, "+", Fnil_plus, 1);
+ rb_define_method(cNil, "+", nil_plus, 1);
- C_Data = rb_define_class("Data", C_Kernel);
- rb_define_method(C_Data, "clone", Fcant_clone, 0);
- rb_define_method(C_Data, "class", Fdata_class, 0);
+ cData = rb_define_class("Data", cKernel);
eq = rb_intern("==");
- Qself = TopSelf = obj_alloc(C_Object);
- rb_define_single_method(TopSelf, "to_s", Fmain_to_s, 0);
+ Qself = TopSelf = obj_alloc(cObject);
+ rb_define_singleton_method(TopSelf, "to_s", main_to_s, 0);
- TRUE = obj_alloc(C_Object);
- rb_define_single_method(TRUE, "to_s", Ftrue_to_s, 0);
- rb_define_const(C_Kernel, "TRUE", TRUE);
- rb_define_const(C_Kernel, "FALSE", FALSE);
+ TRUE = obj_alloc(cObject);
+ rb_define_singleton_method(TRUE, "to_s", true_to_s, 0);
+ rb_define_const(cKernel, "TRUE", TRUE);
+ rb_define_const(cKernel, "FALSE", FALSE);
init = rb_intern("initialize");
}
diff --git a/pack.c b/pack.c
index 7d148330d1..ed98970d36 100644
--- a/pack.c
+++ b/pack.c
@@ -39,7 +39,7 @@
#define vtohl(x) (x)
#endif
-extern VALUE C_String, C_Array;
+extern VALUE cString, cArray;
double atof();
static char *toofew = "too few arguments";
@@ -48,7 +48,7 @@ int strtoul();
static void encodes();
static VALUE
-Fpck_pack(ary, fmt)
+pack_pack(ary, fmt)
struct RArray *ary;
struct RString *fmt;
{
@@ -70,7 +70,7 @@ Fpck_pack(ary, fmt)
items = ary->len;
idx = 0;
-#define NEXTFROM (items-- > 0 ? ary->ptr[idx++] : Fail(toofew))
+#define NEXTFROM (items-- > 0 ? ary->ptr[idx++] : (Fail(toofew),0))
while (p < pend) {
type = *p++; /* get data type */
@@ -92,7 +92,7 @@ Fpck_pack(ary, fmt)
case 'H': case 'h':
from = NEXTFROM;
if (from == Qnil) {
- ptr = Qnil;
+ ptr = 0;
plen = 0;
}
else {
@@ -110,7 +110,7 @@ Fpck_pack(ary, fmt)
str_cat(res, ptr, len);
else {
str_cat(res, ptr, plen);
- len == plen;
+ len = plen;
while (len >= 10) {
str_cat(res, nul10, 10);
len -= 10;
@@ -124,7 +124,7 @@ Fpck_pack(ary, fmt)
str_cat(res, ptr, len);
else {
str_cat(res, ptr, plen);
- len == plen;
+ len = plen;
while (len >= 10) {
str_cat(res, spc10, 10);
len -= 10;
@@ -479,7 +479,7 @@ encodes(str, s, len)
}
static VALUE
-Fpck_unpack(str, fmt)
+pack_unpack(str, fmt)
struct RString *str, *fmt;
{
static char *hexdigits = "0123456789abcdef0123456789ABCDEFx";
@@ -498,7 +498,6 @@ Fpck_unpack(str, fmt)
ary = ary_new();
while (p < pend) {
- retry:
type = *p++;
if (*p == '*') {
len = send - s;
@@ -840,8 +839,9 @@ Fpck_unpack(str, fmt)
return ary;
}
+void
Init_pack()
{
- rb_define_method(C_Array, "pack", Fpck_pack, 1);
- rb_define_method(C_String, "unpack", Fpck_unpack, 1);
+ rb_define_method(cArray, "pack", pack_pack, 1);
+ rb_define_method(cString, "unpack", pack_unpack, 1);
}
diff --git a/parse.y b/parse.y
index 9ea1fb1622..cdecb958bc 100644
--- a/parse.y
+++ b/parse.y
@@ -24,21 +24,27 @@
# undef const
#endif
-#include "ident.h"
+#define ID_SCOPE_SHIFT 3
+#define ID_SCOPE_MASK 0x07
+#define ID_LOCAL 0x00
+#define ID_INSTANCE 0x01
+#define ID_GLOBAL 0x02
+#define ID_ATTRSET 0x03
+#define ID_CONST 0x04
+
#define is_id_nonop(id) ((id)>LAST_TOKEN)
#define is_local_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
#define is_global_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
#define is_instance_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
#define is_attrset_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
#define is_const_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
-#define is_nthref_id(id) (((id)&ID_SCOPE_MASK)==ID_NTHREF)
struct op_tbl {
ID token;
char *name;
};
-NODE *eval_tree = Qnil;
+NODE *eval_tree = 0;
char *sourcefile; /* current source file */
int sourceline; /* current line no. */
@@ -49,16 +55,16 @@ static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_MID, /* newline significant, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */
+ EXPR_ARG, /* newline significant, +/- is a sign(meybe). */
EXPR_FNAME, /* ignore newline, +/- is a operator. */
} lex_state;
static int class_nest = 0;
static int in_single = 0;
-static ID cur_mid = Qnil;
+static ID cur_mid = 0;
static int value_expr();
static NODE *cond();
-static NODE *cond2();
static NODE *block_append();
static NODE *list_append();
@@ -66,11 +72,13 @@ static NODE *list_concat();
static NODE *list_copy();
static NODE *expand_op();
static NODE *call_op();
+static int in_defined = 0;
static NODE *gettable();
static NODE *asignable();
static NODE *aryset();
static NODE *attrset();
+static void backref_error();
static void local_push();
static void local_pop();
@@ -78,12 +86,17 @@ static int local_cnt();
static int local_id();
static ID *local_tbl();
+static struct RVarmap *dyna_push();
+static void dyna_pop();
+static int dyna_in_block();
+
+VALUE dyna_var_ref();
+#define dyna_id(id) dyna_var_ref(id)
+
#define cref_push() NEW_CREF(0)
static void cref_pop();
static NODE *cref_list;
-struct global_entry* rb_global_entry();
-
static void top_local_init();
static void top_local_setup();
%}
@@ -93,6 +106,7 @@ static void top_local_setup();
VALUE val;
ID id;
int num;
+ struct RVarmap *vars;
}
%token CLASS
@@ -100,7 +114,7 @@ static void top_local_setup();
DEF
UNDEF
BEGIN
- RESQUE
+ RESCUE
ENSURE
END
IF
@@ -124,24 +138,27 @@ static void top_local_setup();
NIL
AND
OR
+ NOT
_FILE_
_LINE_
IF_MOD
WHILE_MOD
ALIAS
+ DEFINED
-%token <id> IDENTIFIER GVAR IVAR CONSTANT NTH_REF
+%token <id> IDENTIFIER FID GVAR IVAR CONSTANT
%token <val> INTEGER FLOAT STRING XSTRING REGEXP
-%token <node> STRING2 XSTRING2 DREGEXP
+%token <node> STRING2 XSTRING2 DREGEXP NTH_REF BACK_REF
%type <node> singleton
%type <val> literal numeric
%type <node> compexpr exprs expr arg primary var_ref
-%type <node> if_tail opt_else case_body cases resque ensure
+%type <node> if_tail opt_else case_body cases rescue ensure
%type <node> call_args call_args0 args args2 opt_args
-%type <node> f_arglist f_args array assoc_list assocs assoc
-%type <node> mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var
-%type <id> superclass variable symbol
+%type <node> superclass f_arglist f_args f_optarg f_opt
+%type <node> array assoc_list assocs assoc undef_list
+%type <node> mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var backref
+%type <id> variable symbol operation
%type <id> cname fname op rest_arg
%type <num> f_arg
%token UPLUS /* unary+ */
@@ -160,7 +177,10 @@ static void top_local_setup();
%token COLON2 /* :: */
%token <id> OP_ASGN /* +=, -= etc. */
%token ASSOC /* => */
-%token LPAREN LBRACK LBRACE
+%token LPAREN /* ( */
+%token LBRACK /* [ */
+%token LBRACE /* { */
+%token STAR /* * */
%token SYMBEG
/*
@@ -168,10 +188,9 @@ static void top_local_setup();
*/
%left IF_MOD WHILE_MOD
+%right NOT
%left OR AND
-%left YIELD RETURN FAIL
%right '=' OP_ASGN
-%right COLON2
%nonassoc DOT2 DOT3
%left OROP
%left ANDOP
@@ -184,6 +203,7 @@ static void top_local_setup();
%left '*' '/' '%'
%right '!' '~' UPLUS UMINUS
%right POW
+%left COLON2
%token LAST_TOKEN
@@ -246,24 +266,29 @@ expr : mlhs '=' args2
value_expr($2);
$$ = NEW_YIELD($2);
}
- | IDENTIFIER call_args0
+ | DEFINED {in_defined = 1;} arg
+ {
+ in_defined = 0;
+ $$ = NEW_DEFINED($3);
+ }
+ | operation call_args0
{
$$ = NEW_FCALL($1, $2);
}
- | primary '.' IDENTIFIER call_args0
+ | primary '.' operation call_args0
{
value_expr($1);
$$ = NEW_CALL($1, $3, $4);
}
| SUPER call_args0
{
- if (!cur_mid && !in_single)
+ if (!cur_mid && !in_single && !in_defined)
Error("super called outside of method");
$$ = NEW_SUPER($2);
}
- | UNDEF fname
+ | UNDEF undef_list
{
- $$ = NEW_UNDEF($2);
+ $$ = $2;
}
| ALIAS fname {lex_state = EXPR_FNAME;} fname
{
@@ -271,27 +296,41 @@ expr : mlhs '=' args2
}
| expr IF_MOD expr
{
+ value_expr($3);
$$ = NEW_IF(cond($3), $1, Qnil);
}
| expr WHILE_MOD expr
{
- $$ = NEW_WHILE2(cond($3), $1);
+ value_expr($3);
+ if (nd_type($1) == NODE_BEGIN) {
+ $$ = NEW_WHILE2(cond($3), $1);
+ }
+ else {
+ $$ = NEW_WHILE(cond($3), $1);
+ }
}
| expr AND expr
{
+ value_expr($1);
$$ = NEW_AND(cond($1), cond($3));
}
| expr OR expr
{
+ value_expr($1);
$$ = NEW_OR(cond($1), cond($3));
}
+ | NOT expr
+ {
+ value_expr($2);
+ $$ = NEW_NOT(cond($2));
+ }
| arg
mlhs : mlhs_head
{
$$ = NEW_MASGN(NEW_LIST($1), Qnil);
}
- | mlhs_head '*' lhs
+ | mlhs_head STAR lhs
{
$$ = NEW_MASGN(NEW_LIST($1), $3);
}
@@ -299,7 +338,7 @@ mlhs : mlhs_head
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),Qnil);
}
- | mlhs_head mlhs_tail comma '*' lhs
+ | mlhs_head mlhs_tail comma STAR lhs
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),$5);
}
@@ -327,6 +366,11 @@ lhs : variable
{
$$ = attrset($1, $3, Qnil);
}
+ | backref
+ {
+ backref_error($1);
+ $$ = Qnil;
+ }
cname : IDENTIFIER
{
@@ -335,6 +379,7 @@ cname : IDENTIFIER
| CONSTANT
fname : IDENTIFIER
+ | FID
| CONSTANT
| op
{
@@ -342,8 +387,16 @@ fname : IDENTIFIER
$$ = $1;
}
-op : COLON2 { $$ = COLON2; }
- | DOT2 { $$ = DOT2; }
+undef_list : fname
+ {
+ $$ = NEW_UNDEF($1);
+ }
+ | undef_list ',' fname
+ {
+ $$ = block_append($1, NEW_UNDEF($3));
+ }
+
+op : DOT2 { $$ = DOT2; }
| '|' { $$ = '|'; }
| '^' { $$ = '^'; }
| '&' { $$ = '&'; }
@@ -359,6 +412,7 @@ op : COLON2 { $$ = COLON2; }
| '+' { $$ = '+'; }
| '-' { $$ = '-'; }
| '*' { $$ = '*'; }
+ | STAR { $$ = '*'; }
| '/' { $$ = '/'; }
| '%' { $$ = '%'; }
| POW { $$ = POW; }
@@ -381,13 +435,20 @@ arg : variable '=' arg
{
$$ = attrset($1, $3, $5);
}
+ | backref '=' arg
+ {
+ value_expr($3);
+ backref_error($1);
+ $$ = Qnil;
+ }
| variable OP_ASGN arg
{
NODE *val;
value_expr($3);
if (is_local_id($1)) {
- val = NEW_LVAR($1);
+ if (local_id($1)) val = NEW_LVAR($1);
+ else val = NEW_DVAR($1);
}
else if (is_global_id($1)) {
val = NEW_GVAR($1);
@@ -411,33 +472,22 @@ arg : variable '=' arg
{
$$ = NEW_OP_ASGN2($1, $4, $5);
}
+ | backref OP_ASGN arg
+ {
+ backref_error($1);
+ $$ = Qnil;
+ }
| arg DOT2 arg
{
- $$ = call_op($1, DOT2, 1, $3);
+ $$ = NEW_DOT2($1, $3);
}
| arg DOT3 arg
{
- $$ = NEW_DOT3(cond2($1), cond2($3));
+ $$ = NEW_DOT3($1, $3);
}
| arg '+' arg
{
- $$ = Qnil;
- if ($1 && $3
- && (nd_type($3) == NODE_LIT
- || nd_type($3) == NODE_STR)
- && nd_type($1) == NODE_CALL && $1->nd_mid == '+') {
- if ($1->nd_args->nd_head == Qnil)
- Bug("bad operand for `+'");
- if (nd_type($1->nd_args->nd_head) == NODE_LIT
- || nd_type($1->nd_args->nd_head) == NODE_STR) {
- $1->nd_args->nd_head =
- expand_op($1->nd_args->nd_head, '+', $3);
- $$ = $1;
- }
- }
- if ($$ == Qnil) {
- $$ = call_op($1, '+', 1, $3);
- }
+ $$ = call_op($1, '+', 1, $3);
}
| arg '-' arg
{
@@ -517,20 +567,12 @@ arg : variable '=' arg
}
| '!' arg
{
+ value_expr($2);
$$ = NEW_NOT(cond($2));
}
| '~' arg
{
- if ($2
- && (nd_type($2) == NODE_STR
- || (nd_type($2) == NODE_LIT
- && (TYPE($2->nd_lit) == T_REGEXP
- || TYPE($2->nd_lit) == T_STRING)))) {
- $$ = NEW_CALL($2, '~', Qnil);
- }
- else {
- $$ = call_op($2, '~', 0);
- }
+ $$ = call_op($2, '~', 0);
}
| arg LSHFT arg
{
@@ -540,16 +582,18 @@ arg : variable '=' arg
{
$$ = call_op($1, RSHFT, 1, $3);
}
- | arg COLON2 arg
+ | arg COLON2 cname
{
- $$ = call_op($1, COLON2, 1, $3);
+ $$ = NEW_COLON2($1, $3);
}
| arg ANDOP arg
{
+ value_expr($1);
$$ = NEW_AND(cond($1), cond($3));
}
| arg OROP arg
{
+ value_expr($1);
$$ = NEW_OR(cond($1), cond($3));
}
| primary
@@ -562,10 +606,6 @@ call_args : /* none */
$$ = Qnil;
}
| call_args0 opt_nl
- | '*' arg opt_nl
- {
- $$ = $2;
- }
call_args0 : args
| assocs
@@ -576,10 +616,19 @@ call_args0 : args
{
$$ = list_append($1, NEW_HASH($3));
}
- | args comma '*' arg
+ | args comma assocs comma STAR arg
+ {
+ $$ = list_append($1, NEW_HASH($3));
+ $$ = call_op($$, '+', 1, $6);
+ }
+ | args comma STAR arg
{
$$ = call_op($1, '+', 1, $4);
}
+ | STAR arg
+ {
+ $$ = $2;
+ }
opt_args : /* none */
{
@@ -630,15 +679,16 @@ primary : literal
| XSTRING2
| DREGEXP
| var_ref
+ | backref
| SUPER '(' call_args rparen
{
- if (!cur_mid && !in_single)
+ if (!cur_mid && !in_single && !in_defined)
Error("super called outside of method");
$$ = NEW_SUPER($3);
}
| SUPER
{
- if (!cur_mid && !in_single)
+ if (!cur_mid && !in_single && !in_defined)
Error("super called outside of method");
$$ = NEW_ZSUPER();
}
@@ -710,25 +760,39 @@ primary : literal
{
$$ = NEW_YIELD(Qnil);
}
- | primary '{' opt_iter_var compexpr rbrace
+ | DEFINED '(' {in_defined = 1;} arg ')'
+ {
+ in_defined = 0;
+ $$ = NEW_DEFINED($4);
+ }
+ | primary '{'
+ {
+ $<vars>$ = dyna_push();
+ }
+ opt_iter_var
+ compexpr rbrace
{
if (nd_type($1) == NODE_LVAR
- || nd_type($1) == NODE_LVAR2
|| nd_type($1) == NODE_CVAR) {
$1 = NEW_FCALL($1->nd_vid, Qnil);
}
- $$ = NEW_ITER($3, $1, $4);
+ $$ = NEW_ITER($4, $1, $5);
+ dyna_pop($<vars>3);
+ }
+ | FID
+ {
+ $$ = NEW_FCALL($1, Qnil);
}
- | IDENTIFIER '(' call_args rparen
+ | operation '(' call_args rparen
{
$$ = NEW_FCALL($1, $3);
}
- | primary '.' IDENTIFIER '(' call_args rparen
+ | primary '.' operation '(' call_args rparen
{
value_expr($1);
$$ = NEW_CALL($1, $3, $5);
}
- | primary '.' IDENTIFIER
+ | primary '.' operation
{
value_expr($1);
$$ = NEW_CALL($1, $3, Qnil);
@@ -738,10 +802,12 @@ primary : literal
if_tail
END
{
+ value_expr($2);
$$ = NEW_IF(cond($2), $4, $5);
}
| WHILE expr term compexpr END
{
+ value_expr($2);
$$ = NEW_WHILE(cond($2), $4);
}
| CASE compexpr
@@ -751,29 +817,20 @@ primary : literal
value_expr($2);
$$ = NEW_CASE($2, $3);
}
- | FOR iter_var IN expr term
- compexpr
- END
+ | FOR iter_var IN expr term compexpr END
{
- value_expr($4);
+ value_expr($2);
$$ = NEW_FOR($2, $4, $6);
}
| BEGIN
compexpr
- resque
+ rescue
ensure
END
{
- if ($3 == Qnil && $4 == Qnil) {
- $$ = $2;
- }
- else {
- $$ = NEW_BEGIN($2, $3, $4);
- }
+ $$ = NEW_BEGIN($2, $3, $4);
}
- | LPAREN expr
- opt_nl
- rparen
+ | LPAREN exprs opt_nl rparen
{
$$ = $2;
}
@@ -823,13 +880,14 @@ primary : literal
{
$$ = NEW_DEFN($2, $4, $5, class_nest?0:1);
local_pop();
- cur_mid = Qnil;
+ cur_mid = 0;
}
| DEF singleton '.' fname
{
value_expr($2);
in_single++;
local_push();
+ lex_state = EXPR_END; /* force for args */
}
f_arglist
compexpr
@@ -849,6 +907,7 @@ if_tail : opt_else
compexpr
if_tail
{
+ value_expr($2);
$$ = NEW_IF(cond($2), $4, $5);
}
@@ -864,7 +923,11 @@ opt_else : /* none */
iter_var : lhs
| mlhs
-opt_iter_var : '|' /* none */ '|'
+opt_iter_var : /* node */
+ {
+ $$ = Qnil;
+ }
+ | '|' /* none */ '|'
{
$$ = Qnil;
}
@@ -887,11 +950,11 @@ case_body : WHEN args then
cases : opt_else
| case_body
-resque : /* none */
+rescue : /* none */
{
$$ = Qnil;
}
- | RESQUE compexpr
+ | RESCUE compexpr
{
if ($2 == Qnil)
$$ = (NODE*)1;
@@ -926,7 +989,6 @@ variable : IDENTIFIER
| IVAR
| GVAR
| CONSTANT
- | NTH_REF
| NIL
{
$$ = NIL;
@@ -941,6 +1003,9 @@ var_ref : variable
$$ = gettable($1);
}
+backref : NTH_REF
+ | BACK_REF
+
superclass : term
{
$$ = Qnil;
@@ -949,7 +1014,7 @@ superclass : term
{
lex_state = EXPR_BEG;
}
- CONSTANT
+ expr term
{
$$ = $3;
}
@@ -958,36 +1023,47 @@ f_arglist : '(' f_args rparen
{
$$ = $2;
}
- | term
+ | f_args term
{
- $$ = NEW_ARGS(0, -1);
+ $$ = $1;
}
f_args : /* no arg */
{
- $$ = NEW_ARGS(0, -1);
+ $$ = NEW_ARGS(0, 0, -1);
}
| f_arg
{
- $$ = NEW_ARGS($1, -1);
+ $$ = NEW_ARGS($1, 0, -1);
}
| f_arg comma rest_arg
{
- $$ = NEW_ARGS($1, $3);
+ $$ = NEW_ARGS($1, 0, $3);
}
- | rest_arg
+ | f_arg comma f_optarg
{
- $$ = NEW_ARGS(Qnil, $1);
+ $$ = NEW_ARGS($1, $3, -1);
}
- | f_arg error
+ | f_arg comma f_optarg comma rest_arg
{
- lex_state = EXPR_BEG;
- $$ = NEW_ARGS($1, -1);
+ $$ = NEW_ARGS($1, $3, $5);
+ }
+ | f_optarg
+ {
+ $$ = NEW_ARGS(0, $1, -1);
+ }
+ | f_optarg comma rest_arg
+ {
+ $$ = NEW_ARGS(0, $1, $3);
+ }
+ | rest_arg
+ {
+ $$ = NEW_ARGS(0, 0, $1);
}
| error
{
lex_state = EXPR_BEG;
- $$ = NEW_ARGS(0, -1);
+ $$ = NEW_ARGS(0, 0, -1);
}
f_arg : IDENTIFIER
@@ -1005,7 +1081,23 @@ f_arg : IDENTIFIER
$$ += 1;
}
-rest_arg : '*' IDENTIFIER
+f_opt : IDENTIFIER '=' arg
+ {
+ if (!is_local_id($1))
+ Error("formal argument must be local variable");
+ $$ = asignable($1, $3);
+ }
+
+f_optarg : f_opt
+ {
+ $$ = NEW_BLOCK($1);
+ }
+ | f_optarg comma f_opt
+ {
+ $$ = block_append($1, $3);
+ }
+
+rest_arg : STAR IDENTIFIER
{
if (!is_local_id($2))
Error("rest argument must be local variable");
@@ -1025,7 +1117,7 @@ singleton : var_ref
$$ = $1;
}
}
- | LPAREN compexpr rparen
+ | LPAREN expr opt_nl rparen
{
switch (nd_type($2)) {
case NODE_STR:
@@ -1048,6 +1140,9 @@ assoc_list : /* none */
$$ = Qnil;
}
| assocs trailer
+ {
+ $$ = $1;
+ }
| args trailer
{
if ($1->nd_alen%2 != 0) {
@@ -1067,6 +1162,9 @@ assoc : arg ASSOC arg
$$ = list_append(NEW_LIST($1), $3);
}
+operation : IDENTIFIER
+ | FID
+
opt_term : /* none */
| term
@@ -1109,7 +1207,6 @@ VALUE newinteger();
char *strdup();
static NODE *var_extend();
-static void read_escape();
#define LEAVE_BS 1
@@ -1122,7 +1219,7 @@ lex_setsrc(src, ptr, len)
char *ptr;
int len;
{
- sourcefile = (char*)strdup(src);
+ sourcefile = strdup(src);
sourceline = 1;
lex_p = ptr;
@@ -1151,7 +1248,7 @@ do { \
#define tokfix() (tokenbuf[tokidx]='\0')
#define tok() tokenbuf
#define toklen() tokidx
-#define toknow() &toknbuf[tokidx]
+#define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
char *
newtok()
@@ -1179,6 +1276,88 @@ tokadd(c)
}
static int
+read_escape()
+{
+ int c;
+
+ switch (c = nextc()) {
+ case '\\': /* Backslash */
+ return c;
+
+ case 'n': /* newline */
+ return '\n';
+
+ case 't': /* horizontal tab */
+ return '\t';
+
+ case 'r': /* carriage-return */
+ return '\r';
+
+ case 'f': /* form-feed */
+ return '\f';
+
+ case 'v': /* vertical tab */
+ return '\13';
+
+ case 'a': /* alarm(bell) */
+ return '\007';
+
+ case 'e': /* escape */
+ return 033;
+
+ case '0': case '1': case '2': case '3': /* octal constant */
+ case '4': case '5': case '6': case '7':
+ pushback();
+ SCAN_OCT(c);
+ return c;
+
+ case 'x': /* hex constant */
+ SCAN_HEX(c);
+ return c;
+
+ case 'b': /* backspace */
+ return '\b';
+
+ case 'M':
+ if ((c = nextc()) != '-') {
+ Error("Invalid escape character syntax");
+ return '\0';
+ }
+ if ((c = nextc()) == '\\') {
+ return read_escape() | 0x80;
+ }
+ else if (c == -1) goto eof;
+ else {
+ return ((c & 0xff) | 0x80);
+ }
+
+ case 'C':
+ if ((c = nextc()) != '-') {
+ Error("Invalid escape character syntax");
+ return '\0';
+ }
+ case 'c':
+ case '^':
+ if ((c = nextc())== '\\') {
+ c = read_escape();
+ }
+ else if (c == '?')
+ return 0177;
+ else if (c == -1) goto eof;
+ return c & 0x9f;
+
+ eof:
+ case -1:
+ Error("Invalid escape character syntax");
+ pushback();
+ return '\0';
+
+ default:
+ return c;
+ }
+}
+
+static int
parse_regx()
{
register int c;
@@ -1188,7 +1367,7 @@ parse_regx()
NODE *list = Qnil;
newtok();
- while (c = nextc()) {
+ while ((c = nextc()) != -1) {
switch (c) {
case '[':
in_brack = 1;
@@ -1235,7 +1414,8 @@ parse_regx()
/* fall through */
default:
pushback();
- read_escape(LEAVE_BS);
+ tokadd('\\');
+ tokadd(read_escape());
}
continue;
@@ -1247,6 +1427,7 @@ parse_regx()
casefold = 1;
}
else {
+ casefold = 0;
pushback();
}
@@ -1263,7 +1444,7 @@ parse_regx()
return DREGEXP;
}
else {
- yylval.val = regexp_new(tok(), toklen(), casefold);
+ yylval.val = reg_new(tok(), toklen(), casefold);
return REGEXP;
}
case -1:
@@ -1279,6 +1460,8 @@ parse_regx()
}
tokadd(c);
}
+ Error("unterminated regexp");
+ return 0;
}
static int
@@ -1287,7 +1470,6 @@ parse_string(term)
{
int c;
NODE *list = Qnil;
- ID id;
int strstart;
strstart = sourceline;
@@ -1320,10 +1502,9 @@ parse_string(term)
tokadd(c);
}
else {
- int flags = 0;
- if (term != '"') flags = LEAVE_BS;
pushback();
- read_escape(flags);
+ if (term != '"') tokadd('\\');
+ tokadd(read_escape());
}
continue;
}
@@ -1369,6 +1550,7 @@ static struct kwtable {
"class", CLASS, EXPR_BEG,
"continue", CONTINUE, EXPR_END,
"def", DEF, EXPR_FNAME,
+ "defined?", DEFINED, EXPR_END,
"else", ELSE, EXPR_BEG,
"elsif", ELSIF, EXPR_BEG,
"end", END, EXPR_END,
@@ -1379,9 +1561,10 @@ static struct kwtable {
"in", IN, EXPR_BEG,
"module", MODULE, EXPR_BEG,
"nil", NIL, EXPR_END,
+ "not", NOT, EXPR_BEG,
"or", OR, EXPR_BEG,
"redo", REDO, EXPR_END,
- "resque", RESQUE, EXPR_BEG,
+ "rescue", RESCUE, EXPR_BEG,
"retry", RETRY, EXPR_END,
"return", RETURN, EXPR_MID,
"self", SELF, EXPR_END,
@@ -1393,10 +1576,17 @@ static struct kwtable {
"yield", YIELD, EXPR_END,
};
+static void
+arg_ambiguous()
+{
+ Warning("ambiguous first argument; make sure");
+}
+
static int
yylex()
{
register int c;
+ int space_seen = 0;
struct kwtable *low = kwtable, *mid, *high = LAST(kwtable);
retry:
@@ -1410,6 +1600,7 @@ retry:
/* white spaces */
case ' ': case '\t': case '\f': case '\r':
case '\13': /* '\v' */
+ space_seen = 1;
goto retry;
case '#': /* it's a comment */
@@ -1424,14 +1615,15 @@ retry:
/* fall through */
case '\n':
sourceline++;
- if (lex_state == EXPR_BEG || lex_state == EXPR_FNAME)
+ if (lex_state == EXPR_BEG
+ || lex_state == EXPR_FNAME)
goto retry;
lex_state = EXPR_BEG;
return '\n';
case '*':
- lex_state = EXPR_BEG;
if ((c = nextc()) == '*') {
+ lex_state = EXPR_BEG;
if (nextc() == '=') {
yylval.id = POW;
return OP_ASGN;
@@ -1439,11 +1631,21 @@ retry:
pushback();
return POW;
}
- else if (c == '=') {
+ if (c == '=') {
yylval.id = '*';
+ lex_state = EXPR_BEG;
return OP_ASGN;
}
pushback();
+ if (lex_state == EXPR_ARG && space_seen && !isspace(c)){
+ arg_ambiguous();
+ lex_state = EXPR_BEG;
+ return STAR;
+ }
+ if (lex_state == EXPR_BEG) {
+ return STAR;
+ }
+ lex_state = EXPR_BEG;
return '*';
case '!':
@@ -1558,9 +1760,7 @@ retry:
case '?':
if ((c = nextc()) == '\\') {
- newtok();
- read_escape(0);
- c = tok()[0];
+ c = read_escape();
}
c &= 0xff;
yylval.val = INT2FIX(c);
@@ -1592,21 +1792,27 @@ retry:
return '|';
case '+':
+ c = nextc();
if (lex_state == EXPR_FNAME) {
- if ((c = nextc()) == '@') {
+ if (c == '@') {
return UPLUS;
}
pushback();
return '+';
}
- c = nextc();
+ if (lex_state == EXPR_ARG) {
+ if (!space_seen || c == '=' || isspace(c)) {
+ arg_ambiguous();
+ lex_state = EXPR_END;
+ }
+ }
if (lex_state != EXPR_END) {
pushback();
if (isdigit(c)) {
goto start_num;
}
lex_state = EXPR_BEG;
- return UMINUS;
+ return UPLUS;
}
lex_state = EXPR_BEG;
if (c == '=') {
@@ -1617,21 +1823,28 @@ retry:
return '+';
case '-':
+ c = nextc();
if (lex_state == EXPR_FNAME) {
- if ((c = nextc()) == '@') {
+ if (c == '@') {
return UMINUS;
}
pushback();
return '-';
}
- c = nextc();
+ if (lex_state == EXPR_ARG) {
+ if (!space_seen || c == '=' || isspace(c)) {
+ arg_ambiguous();
+ lex_state = EXPR_END;
+ }
+ }
if (lex_state != EXPR_END) {
- pushback();
if (isdigit(c)) {
+ pushback();
c = '-';
goto start_num;
}
lex_state = EXPR_BEG;
+ pushback();
return UMINUS;
}
lex_state = EXPR_BEG;
@@ -1774,16 +1987,25 @@ retry:
return SYMBEG;
case '/':
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+ if (lex_state == EXPR_BEG
+ || lex_state == EXPR_MID) {
return parse_regx();
}
+ c = nextc();
+ if (lex_state == EXPR_ARG) {
+ if (space_seen && c != '=' && !isspace(c)) {
+ pushback();
+ arg_ambiguous();
+ return parse_regx();
+ }
+ }
lex_state = EXPR_BEG;
- if (nextc() == '=') {
+ if (c == '=') {
yylval.id = '/';
return OP_ASGN;
}
pushback();
- return c;
+ return '/';
case '^':
lex_state = EXPR_BEG;
@@ -1795,6 +2017,9 @@ retry:
return c;
case ',':
+ lex_state = EXPR_BEG;
+ return c;
+
case ';':
lex_state = EXPR_BEG;
return c;
@@ -1809,15 +2034,23 @@ retry:
return c;
case '(':
- if (lex_state != EXPR_END)
+ if (lex_state == EXPR_BEG
+ || lex_state == EXPR_MID) {
c = LPAREN;
- lex_state = EXPR_BEG;
+ lex_state = EXPR_BEG;
+ }
+ else if (lex_state == EXPR_ARG && space_seen) {
+ arg_ambiguous();
+ c = LPAREN;
+ lex_state = EXPR_BEG;
+ }
+ else {
+ lex_state = EXPR_BEG;
+ }
return c;
case '[':
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID)
- c = LBRACK;
- else if (lex_state == EXPR_FNAME) {
+ if (lex_state == EXPR_FNAME) {
if ((c = nextc()) == ']') {
if ((c = nextc()) == '=') {
return ASET;
@@ -1828,11 +2061,19 @@ retry:
pushback();
return '[';
}
+ else if (lex_state == EXPR_BEG
+ || lex_state == EXPR_MID) {
+ c = LBRACK;
+ }
+ else if (lex_state == EXPR_ARG && space_seen) {
+ arg_ambiguous();
+ c = LBRACK;
+ }
lex_state = EXPR_BEG;
return c;
case '{':
- if (lex_state != EXPR_END)
+ if (lex_state != EXPR_END && lex_state != EXPR_ARG)
c = LBRACE;
lex_state = EXPR_BEG;
return c;
@@ -1841,6 +2082,7 @@ retry:
c = nextc();
if (c == '\n') {
sourceline++;
+ space_seen = 1;
goto retry; /* skip \\n */
}
pushback();
@@ -1860,6 +2102,9 @@ retry:
newtok();
c = nextc();
switch (c) {
+ case '~': /* $~: match-data */
+ local_cnt('~');
+ /* fall through */
case '*': /* $*: argv */
case '$': /* $$: pid */
case '?': /* $?: last status */
@@ -1870,51 +2115,42 @@ retry:
case ',': /* $,: output field separator */
case '.': /* $.: last read line number */
case '_': /* $_: last read line string */
- case '&': /* $&: last match */
- case '`': /* $&: string before last match */
- case '\'': /* $&: string after last match */
- case '+': /* $&: string matches last paren. */
- case '~': /* $~: match-data */
case '=': /* $=: ignorecase */
case ':': /* $:: load path */
case '<': /* $<: reading filename */
case '>': /* $>: default output handle */
- case '"': /* $": already loaded files */
+ case '\"': /* $": already loaded files */
tokadd('$');
tokadd(c);
tokfix();
yylval.id = rb_intern(tok());
return GVAR;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
+ case '&': /* $&: last match */
+ case '`': /* $`: string before last match */
+ case '\'': /* $': string after last match */
+ case '+': /* $+: string matches last paren. */
+ yylval.node = NEW_BACK_REF(c);
+ return BACK_REF;
+
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
while (isdigit(c)) {
tokadd(c);
c = nextc();
}
pushback();
tokfix();
- {
- ID id = atoi(tok());
- id <<= ID_SCOPE_SHIFT;
- id |= ID_NTHREF;
- yylval.id = id;
- return NTH_REF;
- }
+ yylval.node = NEW_NTH_REF(atoi(tok()));
+ return NTH_REF;
- case '0':
default:
if (!is_identchar(c)) {
pushback();
return '$';
}
+ case '0':
tokadd('$');
}
break;
@@ -1947,7 +2183,12 @@ retry:
}
c = nextc();
}
- pushback();
+ if (c == '!' || c == '?') {
+ tokadd(c);
+ }
+ else {
+ pushback();
+ }
tokfix();
{
@@ -1955,9 +2196,11 @@ retry:
switch (tok()[0]) {
case '$':
+ lex_state = EXPR_END;
result = GVAR;
break;
case '@':
+ lex_state = EXPR_END;
result = IVAR;
break;
default:
@@ -1967,7 +2210,8 @@ retry:
if (( c = strcmp(mid->name, tok())) == 0) {
enum lex_state state = lex_state;
lex_state = mid->state;
- if (state != EXPR_BEG) {
+ if (state != EXPR_BEG
+ && state != EXPR_BEG) {
if (mid->id == IF) return IF_MOD;
if (mid->id == WHILE) return WHILE_MOD;
}
@@ -1982,6 +2226,7 @@ retry:
}
if (lex_state == EXPR_FNAME) {
+ lex_state = EXPR_END;
if ((c = nextc()) == '=') {
tokadd(c);
}
@@ -1989,14 +2234,21 @@ retry:
pushback();
}
}
+ else if (lex_state == EXPR_BEG){
+ lex_state = EXPR_ARG;
+ }
+ else {
+ lex_state = EXPR_END;
+ }
if (isupper(tok()[0])) {
result = CONSTANT;
}
- else {
+ else if (toklast() == '!' || toklast() == '?') {
+ result = FID;
+ } else {
result = IDENTIFIER;
}
}
- lex_state = EXPR_END;
yylval.id = rb_intern(tok());
return result;
}
@@ -2007,16 +2259,16 @@ var_extend(list, term)
NODE *list;
char term;
{
- int c, t;
+ int c, t, brace;
VALUE ss;
+ NODE *node;
ID id;
c = nextc();
switch (c) {
- default:
- tokadd('#');
- pushback();
- return list;
+ case '$':
+ case '{':
+ break;
case '@':
t = nextc();
pushback();
@@ -2025,9 +2277,10 @@ var_extend(list, term)
tokadd(c);
return list;
}
- case '$':
- case '{':
- break;
+ default:
+ tokadd('#');
+ pushback();
+ return list;
}
ss = str_new(tok(), toklen());
@@ -2038,49 +2291,64 @@ var_extend(list, term)
list_append(list, NEW_STR(ss));
}
newtok();
- if (c == '{') {
- while ((c = nextc()) != '}') {
- if (c == -1) {
- return (NODE*)-1;
- }
- if (isspace(c)) {
- Error("Invalid variable name in string");
- break;
- }
- if (c == term) {
- Error("Inmature variable name in string");
- pushback();
- return list;
- }
- tokadd(c);
- }
+ if (c == '{') {
+ brace = 1;
+ c = nextc();
}
else {
+ brace = 0;
+ }
+
+ switch (c) {
+ case '$':
+ c = nextc();
+ if (c == -1) return (NODE*)-1;
switch (c) {
- case '$':
- tokadd(c);
+ case '&':
+ case '`':
+ case '\'':
+ case '+':
+ node = NEW_BACK_REF(c);
c = nextc();
- if (c == -1) return (NODE*)-1;
- if (!is_identchar(c)) {
+ goto append_node;
+
+ case '~':
+ local_cnt('~');
+ id = '~';
+ goto id_node;
+
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ while (isdigit(c)) {
tokadd(c);
- goto fetch_id;
+ c = nextc();
}
- /* through */
- case '@':
- tokadd(c);
- c = nextc();
- break;
+ tokfix();
+ node = NEW_NTH_REF(atoi(tok()));
+ goto append_node;
}
- while (is_identchar(c)) {
+
+ tokadd('$');
+ if (!is_identchar(c)) {
tokadd(c);
- if (ismbchar(c)) {
- c = nextc();
- tokadd(c);
- }
+ goto fetch_id;
+ }
+ /* through */
+ case '@':
+ tokadd(c);
+ c = nextc();
+ break;
+ }
+ while (is_identchar(c)) {
+ tokadd(c);
+ if (ismbchar(c)) {
c = nextc();
+ tokadd(c);
}
- pushback();
+ c = nextc();
}
+
fetch_id:
tokfix();
if (strcmp("__LINE__", tok()) == 0)
@@ -2089,90 +2357,21 @@ var_extend(list, term)
id = _FILE_;
else
id = rb_intern(tok());
- list_append(list, gettable(id));
+ id_node:
+ node = gettable(id);
+
+ append_node:
+ if (brace) {
+ if (c != '}')
+ Error("Invalid variable name in string");
+ }
+ else pushback();
+
+ list_append(list, node);
newtok();
return list;
}
-static void
-read_escape(flag)
- int flag;
-{
- char c;
-
- switch (c = nextc()) {
- case '\\': /* Backslash */
- tokadd('\\');
- break;
-
- case 'n': /* newline */
- tokadd('\n');
- break;
-
- case 't': /* horizontal tab */
- tokadd('\t');
- break;
-
- case 'r': /* carriage-return */
- tokadd('\r');
- break;
-
- case 'f': /* form-feed */
- tokadd('\f');
- break;
-
- case 'v': /* vertical tab */
- tokadd('\13');
- break;
-
- case 'a': /* alarm(bell) */
- tokadd('\007');
- break;
-
- case 'e': /* escape */
- tokadd(033);
- break;
-
- case 'c':
- if ((c = nextc()) == '?')
- tokadd(0177);
- else {
- if (islower(c))
- c = toupper(c);
- c = c - '@';
- tokadd(c);
- }
- break;
-
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- { /* octal constant */
- pushback();
- SCAN_OCT(c);
- tokadd(c);
- }
- break;
-
- case 'x': /* hex constant */
- {
- SCAN_HEX(c);
- tokadd(c);
- }
- break;
-
- case 'b': /* backspace */
- tokadd('\b');
- return;
-
- default:
- if (flag & LEAVE_BS) {
- tokadd('\\');
- }
- case '#':
- tokadd(c);
- break;
- }
-}
NODE*
newnode(type, a0, a1, a2)
@@ -2282,72 +2481,6 @@ list_concat(head, tail)
return head;
}
-static NODE*
-list_copy(list)
- NODE *list;
-{
- NODE *tmp;
-
- if (list == Qnil) return Qnil;
-
- tmp = Qnil;
- while(list) {
- tmp = list_append(tmp, list->nd_head);
- list = list->nd_next;
- }
- return tmp;
-}
-
-struct call_arg {
- ID id;
- VALUE recv;
- int narg;
- VALUE arg;
-};
-
-static VALUE
-call_lit(arg)
- struct call_arg *arg;
-{
- return rb_funcall(arg->recv, arg->id, arg->narg, arg->arg);
-}
-
-static VALUE
-except_lit()
-{
- extern VALUE errstr;
-
- Error("%s", RSTRING(errstr)->ptr);
- return Qnil;
-}
-
-static NODE *
-expand_op(recv, id, arg)
- NODE *recv, *arg;
- ID id;
-{
- struct call_arg arg_data;
- VALUE val;
- NODE *result;
-
- arg_data.recv = recv->nd_lit;
- arg_data.id = id;
- arg_data.narg = arg?1:0;
- arg_data.arg = arg->nd_lit;
-
- val = rb_resque(call_lit, &arg_data, except_lit, Qnil);
- if (TYPE(val) == T_STRING) {
- result = NEW_STR(val);
- }
- else {
- result = NEW_LIT(val);
- }
-
- return result;
-}
-
-#define NODE_IS_CONST(n) (nd_type(n) == NODE_LIT || nd_type(n) == NODE_STR)
-
static NODE *
call_op(recv, id, narg, arg1)
NODE *recv;
@@ -2360,9 +2493,6 @@ call_op(recv, id, narg, arg1)
value_expr(arg1);
}
- if (NODE_IS_CONST(recv) && (narg == 0 || NODE_IS_CONST(arg1))) {
- return expand_op(recv, id, (narg == 1)?arg1:Qnil);
- }
return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):Qnil);
}
@@ -2385,10 +2515,10 @@ gettable(id)
return NEW_STR(s);
}
else if (is_local_id(id)) {
- if (local_id(id))
- return NEW_LVAR(id);
- else
- return NEW_LVAR2(id);
+ if (local_id(id)) return NEW_LVAR(id);
+ if (dyna_id(id)) return NEW_DVAR(id);
+ /* method call without arguments */
+ return NEW_FCALL(id, Qnil);
}
else if (is_global_id(id)) {
return NEW_GVAR(id);
@@ -2399,9 +2529,8 @@ gettable(id)
else if (is_const_id(id)) {
return NEW_CVAR(id);
}
- else if (is_nthref_id(id)) {
- return NEW_NTH_REF(id>>ID_SCOPE_SHIFT);
- }
+ Bug("invalid id for gettable");
+ return Qnil;
}
static NODE*
@@ -2409,6 +2538,7 @@ asignable(id, val)
ID id;
NODE *val;
{
+ extern VALUE dyna_var_asgn();
NODE *lhs = Qnil;
if (id == SELF) {
@@ -2421,7 +2551,12 @@ asignable(id, val)
Error("Can't asign to special identifier");
}
else if (is_local_id(id)) {
- lhs = NEW_LASGN(id, val);
+ if (local_id(id) || !dyna_in_block())
+ lhs = NEW_LASGN(id, val);
+ else{
+ dyna_var_asgn(id, TRUE);
+ lhs = NEW_DASGN(id, val);
+ }
}
else if (is_global_id(id)) {
lhs = NEW_GASGN(id, val);
@@ -2434,9 +2569,6 @@ asignable(id, val)
Error("class constant asigned in method body");
lhs = NEW_CASGN(id, val);
}
- else if (is_nthref_id(id)) {
- Error("Can't set variable $%d", id>>ID_SCOPE_SHIFT);
- }
else {
Bug("bad id for variable");
}
@@ -2452,6 +2584,15 @@ aryset(recv, idx, val)
return NEW_CALL(recv, ASET, list_append(idx, val));
}
+ID
+id_attrset(id)
+ ID id;
+{
+ id &= ~ID_SCOPE_MASK;
+ id |= ID_ATTRSET;
+ return id;
+}
+
static NODE *
attrset(recv, id, val)
NODE *recv, *val;
@@ -2460,12 +2601,26 @@ attrset(recv, id, val)
value_expr(recv);
value_expr(val);
- id &= ~ID_SCOPE_MASK;
+ id &= ~ID_SCOPE_MASK;
id |= ID_ATTRSET;
return NEW_CALL(recv, id, NEW_LIST(val));
}
+static void
+backref_error(node)
+ NODE *node;
+{
+ switch (nd_type(node)) {
+ case NODE_NTH_REF:
+ Error("Can't set variable $%d", node->nd_nth);
+ break;
+ case NODE_BACK_REF:
+ Error("Can't set variable $%c", node->nd_nth);
+ break;
+ }
+}
+
static int
value_expr(node)
NODE *node;
@@ -2503,6 +2658,8 @@ value_expr(node)
}
}
+static NODE *cond2();
+
static NODE*
cond0(node)
NODE *node;
@@ -2515,6 +2672,12 @@ cond0(node)
else if (type == NODE_LIT && TYPE(node->nd_lit) == T_REGEXP) {
return call_op(node,MATCH,1,NEW_GVAR(rb_intern("$_")));
}
+ else if (type == NODE_DOT2 || type == NODE_DOT3) {
+ node->nd_beg = cond2(node->nd_beg);
+ node->nd_end = cond2(node->nd_end);
+ if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
+ else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
+ }
return node;
}
@@ -2524,10 +2687,10 @@ cond(node)
{
enum node_type type = nd_type(node);
- value_expr(node);
switch (type) {
case NODE_MASGN:
case NODE_LASGN:
+ case NODE_DASGN:
case NODE_GASGN:
case NODE_IASGN:
case NODE_CASGN:
@@ -2561,6 +2724,7 @@ st_table *new_idhash();
static struct local_vars {
ID *tbl;
int cnt;
+ int dlev;
struct local_vars *prev;
} *lvtbl;
@@ -2572,7 +2736,8 @@ local_push()
local = ALLOC(struct local_vars);
local->prev = lvtbl;
local->cnt = 0;
- local->tbl = Qnil;
+ local->tbl = 0;
+ local->dlev = 0;
lvtbl = local;
}
@@ -2600,11 +2765,11 @@ local_cnt(id)
if (id == 0) return lvtbl->cnt;
- for (cnt=0, max=lvtbl->cnt; cnt<max ;cnt++) {
- if (lvtbl->tbl[cnt+1] == id) return cnt;
+ for (cnt=1, max=lvtbl->cnt+1; cnt<max ;cnt++) {
+ if (lvtbl->tbl[cnt] == id) return cnt-1;
}
- if (lvtbl->tbl == Qnil) {
+ if (lvtbl->tbl == 0) {
lvtbl->tbl = ALLOC_N(ID, 2);
lvtbl->tbl[0] = 0;
}
@@ -2622,7 +2787,7 @@ local_id(id)
{
int i, max;
- if (lvtbl == Qnil) return FALSE;
+ if (lvtbl == 0) return FALSE;
for (i=1, max=lvtbl->cnt+1; i<max; i++) {
if (lvtbl->tbl[i] == id) return TRUE;
}
@@ -2632,7 +2797,7 @@ local_id(id)
static void
top_local_init()
{
- if (lvtbl == Qnil) {
+ if (lvtbl == 0) {
local_push();
}
else if (the_scope->local_tbl) {
@@ -2643,12 +2808,13 @@ top_local_init()
}
if (lvtbl->cnt > 0) {
lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+1);
- MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt);
+ MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt+1);
}
else {
- lvtbl->tbl = Qnil;
+ lvtbl->tbl = 0;
}
NEW_CREF0(); /* initialize constant c-ref */
+ lvtbl->dlev = (the_dyna_vars?1:0);
}
static void
@@ -2661,14 +2827,7 @@ top_local_setup()
i = lvtbl->tbl[0];
if (i < len) {
- if (the_scope->flags & SCOPE_MALLOCED) {
- VALUE *vars = the_scope->local_vars;
-
- REALLOC_N(the_scope->local_vars, VALUE, len);
- MEMZERO(the_scope->local_vars+i, VALUE, len-i);
- free(the_scope->local_tbl);
- }
- else {
+ if (the_scope->flag == SCOPE_ALLOCA) {
VALUE *vars = the_scope->local_vars;
the_scope->local_vars = ALLOC_N(VALUE, len);
if (vars) {
@@ -2678,10 +2837,15 @@ top_local_setup()
else {
MEMZERO(the_scope->local_vars, VALUE, len);
}
+ the_scope->flag = SCOPE_MALLOC;
+ }
+ else {
+ REALLOC_N(the_scope->local_vars, VALUE, len);
+ MEMZERO(the_scope->local_vars+i, VALUE, len-i);
+ free(the_scope->local_tbl);
}
lvtbl->tbl[0] = len;
the_scope->local_tbl = lvtbl->tbl;
- the_scope->flags |= SCOPE_MALLOCED;
}
else if (lvtbl->tbl) {
free(lvtbl->tbl);
@@ -2690,6 +2854,27 @@ top_local_setup()
cref_list = Qnil;
}
+static struct RVarmap*
+dyna_push()
+{
+ lvtbl->dlev++;
+ return the_dyna_vars;
+}
+
+static void
+dyna_pop(vars)
+ struct RVarmap* vars;
+{
+ lvtbl->dlev--;
+ the_dyna_vars = vars;
+}
+
+static int
+dyna_in_block()
+{
+ return (lvtbl->dlev > 0);
+}
+
static void
cref_pop()
{
@@ -2721,7 +2906,7 @@ yywhole_loop(chop, split)
if (chop) {
eval_tree =
block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
- rb_intern("chop"), Qnil), eval_tree);
+ rb_intern("chop!"), Qnil), eval_tree);
}
eval_tree = NEW_WHILE(NEW_FCALL(rb_intern("gets"),0),eval_tree);
}
@@ -2808,14 +2993,14 @@ rb_intern(name)
/* operator */
int i;
- id = Qnil;
+ id = 0;
for (i=0; rb_op_tbl[i].token; i++) {
if (strcmp(rb_op_tbl[i].name, name) == 0) {
id = rb_op_tbl[i].token;
break;
}
}
- if (id == Qnil) Bug("Unknown operator `%s'", name);
+ if (id == 0) Bug("Unknown operator `%s'", name);
break;
}
@@ -2844,7 +3029,7 @@ rb_intern(name)
static char *find_ok;
-static
+static int
id_find(name, id1, id2)
char *name;
ID id1, id2;
@@ -2860,7 +3045,7 @@ char *
rb_id2name(id)
ID id;
{
- find_ok = Qnil;
+ find_ok = 0;
if (id < LAST_TOKEN) {
int i = 0;
@@ -2897,7 +3082,7 @@ const_check(id, val, class)
VALUE val;
struct RClass *class;
{
- if (is_const_id(id) && rb_const_bound(class, id)) {
+ if (is_const_id(id) && rb_const_defined(class, id)) {
Warning("constant redefined for %s", rb_class2name(class));
return ST_STOP;
}
diff --git a/process.c b/process.c
index ba6ba45f22..116a93f965 100644
--- a/process.c
+++ b/process.c
@@ -11,11 +11,20 @@
************************************************/
#include "ruby.h"
+#include "sig.h"
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
-#include <sys/time.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+struct timeval {
+ long tv_sec; /* seconds */
+ long tv_usec; /* and microseconds */
+};
+#endif
+
#include <sys/resource.h>
#ifdef HAVE_VFORK_H
#include <vfork.h>
@@ -31,9 +40,17 @@ get_pid()
static VALUE
get_ppid()
{
+#ifdef NT
+ return INT2FIX(0);
+#else
return INT2FIX(getppid());
+#endif
}
+#ifdef NT
+#define HAVE_WAITPID
+#endif
+
static VALUE status;
#if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
@@ -96,7 +113,7 @@ static wait_each(key, value)
#endif
static VALUE
-Fwait(obj)
+f_wait()
{
int pid, state;
@@ -118,12 +135,12 @@ Fwait(obj)
}
static VALUE
-Fwaitpid(obj, vpid, vflags)
+f_waitpid(obj, vpid, vflags)
VALUE obj, vpid, vflags;
{
int pid, flags;
- if (vflags == Qnil) flags = Qnil;
+ if (vflags == Qnil) flags = 0;
else flags = FIX2UINT(vflags);
if ((pid = rb_waitpid(FIX2UINT(vpid), flags)) < 0)
@@ -133,6 +150,7 @@ Fwaitpid(obj, vpid, vflags)
char *strtok();
+int
rb_proc_exec(str)
char *str;
{
@@ -161,7 +179,7 @@ rb_proc_exec(str)
}
static VALUE
-Fexec(obj, str)
+f_exec(obj, str)
VALUE obj;
struct RString *str;
{
@@ -171,18 +189,22 @@ Fexec(obj, str)
}
static VALUE
-Ffork(obj)
+f_fork(obj)
VALUE obj;
{
int pid;
switch (pid = fork()) {
case 0:
- return INT2FIX(0);
+ if (iterator_p()) {
+ rb_yield(Qnil);
+ _exit(0);
+ }
+ return Qnil;
case -1:
rb_sys_fail("fork(2)");
- break;
+ return Qnil;
default:
return INT2FIX(pid);
@@ -190,7 +212,7 @@ Ffork(obj)
}
static VALUE
-F_exit(obj, status)
+f_exit_bang(obj, status)
VALUE obj, status;
{
int code = -1;
@@ -223,11 +245,21 @@ rb_syswait(pid)
}
static VALUE
-Fsystem(obj, str)
+f_system(obj, str)
VALUE obj;
struct RString *str;
{
- int pid, w;
+#ifdef NT
+ int state;
+
+ Check_Type(str, T_STRING);
+ state = do_spawn(str->ptr);
+ status = INT2FIX(state);
+
+ if (state == 0) return TRUE;
+ return FALSE;
+#else
+ int pid;
Check_Type(str, T_STRING);
@@ -255,10 +287,13 @@ Fsystem(obj, str)
rb_syswait(pid);
}
- return status;
+ if (status == INT2FIX(0)) return TRUE;
+ return FALSE;
+#endif
}
-Fsleep(argc, argv)
+VALUE
+f_sleep(argc, argv)
int argc;
VALUE *argv;
{
@@ -269,7 +304,9 @@ Fsleep(argc, argv)
sleep((32767<<16)+32767);
}
else if (argc == 1) {
+ TRAP_BEG;
sleep(NUM2INT(argv[0]));
+ TRAP_END;
}
else {
Fail("wrong # of arguments");
@@ -280,8 +317,9 @@ Fsleep(argc, argv)
return int2inum(end);
}
+#ifndef NT
static VALUE
-Fproc_getpgrp(argc, argv, obj)
+proc_getpgrp(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -302,7 +340,7 @@ Fproc_getpgrp(argc, argv, obj)
}
static VALUE
-Fproc_setpgrp(obj, pid, pgrp)
+proc_setpgrp(obj, pid, pgrp)
VALUE obj, pid, pgrp;
{
int ipid, ipgrp;
@@ -316,7 +354,7 @@ Fproc_setpgrp(obj, pid, pgrp)
}
static VALUE
-Fproc_getpriority(obj, which, who)
+proc_getpriority(obj, which, who)
VALUE obj, which, who;
{
#ifdef HAVE_GETPRIORITY
@@ -334,7 +372,7 @@ Fproc_getpriority(obj, which, who)
}
static VALUE
-Fproc_setpriority(obj, which, who, prio)
+proc_setpriority(obj, which, who, prio)
VALUE obj, which, who, prio;
{
#ifdef HAVE_GETPRIORITY
@@ -351,9 +389,10 @@ Fproc_setpriority(obj, which, who, prio)
Fail("The setpriority() function is unimplemented on this machine");
#endif
}
+#endif
static VALUE
-Fproc_getuid(obj)
+proc_getuid(obj)
VALUE obj;
{
int uid = getuid();
@@ -361,7 +400,7 @@ Fproc_getuid(obj)
}
static VALUE
-Fproc_setuid(obj, id)
+proc_setuid(obj, id)
VALUE obj, id;
{
int uid;
@@ -385,7 +424,7 @@ Fproc_setuid(obj, id)
}
static VALUE
-Fproc_getgid(obj)
+proc_getgid(obj)
VALUE obj;
{
int gid = getgid();
@@ -393,7 +432,7 @@ Fproc_getgid(obj)
}
static VALUE
-Fproc_setgid(obj, id)
+proc_setgid(obj, id)
VALUE obj, id;
{
int gid;
@@ -417,7 +456,7 @@ Fproc_setgid(obj, id)
}
static VALUE
-Fproc_geteuid(obj)
+proc_geteuid(obj)
VALUE obj;
{
int euid = geteuid();
@@ -425,7 +464,7 @@ Fproc_geteuid(obj)
}
static VALUE
-Fproc_seteuid(obj, euid)
+proc_seteuid(obj, euid)
VALUE obj, euid;
{
#ifdef HAVE_SETEUID
@@ -445,7 +484,7 @@ Fproc_seteuid(obj, euid)
}
static VALUE
-Fproc_getegid(obj)
+proc_getegid(obj)
VALUE obj;
{
int egid = getegid();
@@ -453,7 +492,7 @@ Fproc_getegid(obj)
}
static VALUE
-Fproc_setegid(obj, egid)
+proc_setegid(obj, egid)
VALUE obj, egid;
{
#ifdef HAVE_SETEGID
@@ -472,53 +511,58 @@ Fproc_setegid(obj, egid)
return egid;
}
-VALUE rb_readonly_hook();
-VALUE M_Process;
+VALUE mProcess;
-extern VALUE Fkill();
+extern VALUE f_kill();
+void
Init_process()
{
- extern VALUE C_Kernel;
-
- rb_define_variable("$$", Qnil, get_pid, Qnil, 0);
- rb_define_variable("$?", &status, Qnil, rb_readonly_hook, 0);
- rb_define_private_method(C_Kernel, "exec", Fexec, 1);
- rb_define_private_method(C_Kernel, "fork", Ffork, 0);
- rb_define_private_method(C_Kernel, "_exit", Ffork, 1);
- rb_define_private_method(C_Kernel, "wait", Fwait, 0);
- rb_define_private_method(C_Kernel, "waitpid", Fwaitpid, 2);
- rb_define_private_method(C_Kernel, "system", Fsystem, 1);
- rb_define_private_method(C_Kernel, "sleep", Fsleep, -1);
-
- M_Process = rb_define_module("Process");
- rb_extend_object(M_Process, M_Process);
-
- rb_define_single_method(M_Process, "fork", Ffork, 0);
- rb_define_single_method(M_Process, "_exit", Ffork, 1);
- rb_define_single_method(M_Process, "wait", Fwait, 0);
- rb_define_single_method(M_Process, "waitpid", Fwaitpid, 2);
- rb_define_single_method(M_Process, "kill", Fkill, -1);
-
- rb_define_method(M_Process, "pid", get_pid, 0);
- rb_define_method(M_Process, "ppid", get_ppid, 0);
-
- rb_define_method(M_Process, "getpgrp", Fproc_getpgrp, -1);
- rb_define_method(M_Process, "setpgrp", Fproc_setpgrp, 2);
-
- rb_define_method(M_Process, "getpriority", Fproc_getpriority, 2);
- rb_define_method(M_Process, "setpriority", Fproc_setpriority, 3);
-
- rb_define_const(M_Process, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
- rb_define_const(M_Process, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
- rb_define_const(M_Process, "PRIO_USER", INT2FIX(PRIO_USER));
-
- rb_define_method(M_Process, "uid", Fproc_getuid, 0);
- rb_define_method(M_Process, "uid=", Fproc_setuid, 1);
- rb_define_method(M_Process, "gid", Fproc_getgid, 0);
- rb_define_method(M_Process, "gid=", Fproc_setgid, 1);
- rb_define_method(M_Process, "euid", Fproc_geteuid, 0);
- rb_define_method(M_Process, "euid=", Fproc_seteuid, 1);
- rb_define_method(M_Process, "egid", Fproc_getegid, 0);
- rb_define_method(M_Process, "egid=", Fproc_setegid, 1);
+ extern VALUE cKernel;
+
+ rb_define_virtual_variable("$$", get_pid, Qnil);
+ rb_define_readonly_variable("$?", &status);
+#ifndef NT
+ rb_define_private_method(cKernel, "exec", f_exec, 1);
+ rb_define_private_method(cKernel, "fork", f_fork, 0);
+ rb_define_private_method(cKernel, "exit!", f_exit_bang, 1);
+ rb_define_private_method(cKernel, "wait", f_wait, 0);
+ rb_define_private_method(cKernel, "waitpid", f_waitpid, 2);
+#endif
+ rb_define_private_method(cKernel, "system", f_system, 1);
+ rb_define_private_method(cKernel, "sleep", f_sleep, -1);
+
+ mProcess = rb_define_module("Process");
+
+#ifndef NT
+ rb_define_singleton_method(mProcess, "fork", f_fork, 0);
+ rb_define_singleton_method(mProcess, "exit!", f_exit_bang, 1);
+ rb_define_singleton_method(mProcess, "wait", f_wait, 0);
+ rb_define_singleton_method(mProcess, "waitpid", f_waitpid, 2);
+ rb_define_singleton_method(mProcess, "kill", f_kill, -1);
+#endif
+
+ rb_define_module_function(mProcess, "pid", get_pid, 0);
+ rb_define_module_function(mProcess, "ppid", get_ppid, 0);
+
+#ifndef NT
+ rb_define_module_function(mProcess, "getpgrp", proc_getpgrp, -1);
+ rb_define_module_function(mProcess, "setpgrp", proc_setpgrp, 2);
+
+ rb_define_module_function(mProcess, "getpriority", proc_getpriority, 2);
+ rb_define_module_function(mProcess, "setpriority", proc_setpriority, 3);
+
+ rb_define_const(mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
+ rb_define_const(mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
+ rb_define_const(mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
+
+ rb_define_module_function(mProcess, "uid", proc_getuid, 0);
+ rb_define_module_function(mProcess, "uid=", proc_setuid, 1);
+ rb_define_module_function(mProcess, "gid", proc_getgid, 0);
+ rb_define_module_function(mProcess, "gid=", proc_setgid, 1);
+ rb_define_module_function(mProcess, "euid", proc_geteuid, 0);
+ rb_define_module_function(mProcess, "euid=", proc_seteuid, 1);
+ rb_define_module_function(mProcess, "egid", proc_getegid, 0);
+ rb_define_module_function(mProcess, "egid=", proc_setegid, 1);
+#endif
}
diff --git a/random.c b/random.c
index 7fa9e03eff..f7bc59569b 100644
--- a/random.c
+++ b/random.c
@@ -16,7 +16,7 @@ static int first = 1;
static char state[256];
static VALUE
-Fsrand(argc, argv, obj)
+f_srand(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -54,7 +54,7 @@ Fsrand(argc, argv, obj)
}
static VALUE
-Frand(obj, max)
+f_rand(obj, max)
VALUE obj, max;
{
int val;
@@ -73,10 +73,11 @@ Frand(obj, max)
return int2inum(val);
}
+void
Init_Random()
{
- extern VALUE C_Kernel;
+ extern VALUE cKernel;
- rb_define_private_method(C_Kernel, "srand", Fsrand, -1);
- rb_define_private_method(C_Kernel, "rand", Frand, 1);
+ rb_define_private_method(cKernel, "srand", f_srand, -1);
+ rb_define_private_method(cKernel, "rand", f_rand, 1);
}
diff --git a/range.c b/range.c
index cfcc3b909b..147c28ae7c 100644
--- a/range.c
+++ b/range.c
@@ -12,18 +12,21 @@
#include "ruby.h"
-VALUE M_Comparable;
-VALUE C_Range;
+VALUE mComparable;
+static VALUE cRange;
-static ID next;
+static ID upto;
static VALUE
-Srng_new(class, start, end)
+range_s_new(class, start, end)
VALUE class, start, end;
{
VALUE obj;
- if (!obj_is_kind_of(start, M_Comparable) || TYPE(start) != TYPE(end)) {
+ if (!(FIXNUM_P(start) && FIXNUM_P(end))
+ && (TYPE(start) != TYPE(end)
+ || CLASS_OF(start) != CLASS_OF(end)
+ || !rb_responds_to(start, upto))) {
Fail("bad value for range");
}
@@ -39,11 +42,11 @@ VALUE
range_new(start, end)
VALUE start, end;
{
- return Srng_new(C_Range, start, end);
+ return range_s_new(cRange, start, end);
}
static VALUE
-Frng_match(rng, obj)
+range_match(rng, obj)
VALUE rng, obj;
{
VALUE beg, end;
@@ -71,13 +74,15 @@ struct upto_data {
VALUE end;
};
-static rng_upto(data)
+static VALUE
+range_upto(data)
struct upto_data *data;
{
- return rb_funcall(data->beg, rb_intern("upto"), 1, data->end);
+ return rb_funcall(data->beg, upto, 1, data->end);
}
-static rng_upto_yield(v)
+static VALUE
+range_upto_yield(v)
VALUE v;
{
rb_yield(v);
@@ -85,19 +90,19 @@ static rng_upto_yield(v)
}
static VALUE
-Frng_each(obj)
+range_each(obj)
VALUE obj;
{
- VALUE b, e, current;
+ VALUE b, e;
b = rb_iv_get(obj, "start");
e = rb_iv_get(obj, "end");
if (FIXNUM_P(b)) { /* fixnum is a special case(for performance) */
- Fnum_upto(b, e);
+ num_upto(b, e);
}
else if (TYPE(b) == T_STRING) {
- Fstr_upto(b, e);
+ str_upto(b, e);
}
else {
struct upto_data data;
@@ -105,14 +110,14 @@ Frng_each(obj)
data.beg = b;
data.end = e;
- rb_iterate(rng_upto, &data, rng_upto_yield, Qnil);
+ rb_iterate(range_upto, &data, range_upto_yield, Qnil);
}
return Qnil;
}
static VALUE
-Frng_start(obj)
+range_start(obj)
VALUE obj;
{
VALUE b;
@@ -122,7 +127,7 @@ Frng_start(obj)
}
static VALUE
-Frng_end(obj)
+range_end(obj)
VALUE obj;
{
VALUE e;
@@ -132,7 +137,7 @@ Frng_end(obj)
}
static VALUE
-Frng_to_s(obj)
+range_to_s(obj)
VALUE obj;
{
VALUE args[4];
@@ -140,21 +145,36 @@ Frng_to_s(obj)
args[0] = str_new2("%d..%d");
args[1] = rb_iv_get(obj, "start");
args[2] = rb_iv_get(obj, "end");
- return Fsprintf(3, args);
+ return f_sprintf(3, args);
+}
+
+VALUE
+range_beg_end(range, begp, endp)
+ VALUE range;
+ int *begp, *endp;
+{
+ int beg, end;
+
+ if (!obj_is_kind_of(range, cRange)) return FALSE;
+
+ beg = rb_iv_get(range, "start"); *begp = NUM2INT(beg);
+ end = rb_iv_get(range, "end"); *endp = NUM2INT(end);
+ return TRUE;
}
-extern VALUE M_Enumerable;
+extern VALUE mEnumerable;
+void
Init_Range()
{
- C_Range = rb_define_class("Range", C_Object);
- rb_include_module(C_Range, M_Enumerable);
- rb_define_single_method(C_Range, "new", Srng_new, 2);
- rb_define_method(C_Range, "=~", Frng_match, 1);
- rb_define_method(C_Range, "each", Frng_each, 0);
- rb_define_method(C_Range, "start", Frng_start, 0);
- rb_define_method(C_Range, "end", Frng_end, 0);
- rb_define_method(C_Range, "to_s", Frng_to_s, 0);
-
- next = rb_intern("next");
+ cRange = rb_define_class("Range", cObject);
+ rb_include_module(cRange, mEnumerable);
+ rb_define_singleton_method(cRange, "new", range_s_new, 2);
+ rb_define_method(cRange, "=~", range_match, 1);
+ rb_define_method(cRange, "each", range_each, 0);
+ rb_define_method(cRange, "start", range_start, 0);
+ rb_define_method(cRange, "end", range_end, 0);
+ rb_define_method(cRange, "to_s", range_to_s, 0);
+
+ upto = rb_intern("upto");
}
diff --git a/re.c b/re.c
index fd0288181b..f6dde5a4eb 100644
--- a/re.c
+++ b/re.c
@@ -13,6 +13,9 @@
#include "ruby.h"
#include "re.h"
+#define BEG(no) regs->beg[no]
+#define END(no) regs->end[no]
+
#if 'a' == 97 /* it's ascii */
static char casetable[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
@@ -77,20 +80,37 @@ str_cicmp(str1, str2)
p1 = str1->ptr; p2 = str2->ptr;
for (i = 0; i < len; i++, p1++, p2++) {
- if (casetable[*p1] != casetable[*p2])
- return casetable[*p1] - casetable[*p2];
+ if (casetable[(int)*p1] != casetable[(int)*p2])
+ return casetable[(int)*p1] - casetable[(int)*p2];
}
return str1->len - str2->len;
}
+#define REG_IGNORECASE FL_USER0
+
+#define KCODE_NONE 0
+#define KCODE_EUC FL_USER1
+#define KCODE_SJIS FL_USER2
+#define KCODE_MASK (KCODE_EUC|KCODE_SJIS)
+
+static int reg_kcode =
+#ifdef EUC
+ KCODE_EUC;
+#else
+# ifdef SJIS
+ KCODE_SJIS;
+# else
+ KCODE_NONE;
+# endif
+#endif
+
static Regexp*
make_regexp(s, len)
-char *s;
-int len;
+ char *s;
+ int len;
{
Regexp *rp;
char *err;
- register int c;
/* Handle escaped characters first. */
@@ -111,20 +131,36 @@ int len;
return rp;
}
-struct match last_match;
+static VALUE
+match_alloc()
+{
+ NEWOBJ(match, struct RMatch);
+ OBJSETUP(match, cData, T_MATCH);
+
+ match->ptr = 0;
+ match->len = 0;
+ match->regs = ALLOC(struct re_registers);
+ MEMZERO(match->regs, struct re_registers, 1);
+
+ return (VALUE)match;
+}
+
VALUE ignorecase;
int
-research(reg, str, start)
+reg_search(reg, str, start, regs)
struct RRegexp *reg;
struct RString *str;
int start;
+ struct re_registers *regs;
{
int result;
int casefold = ignorecase;
+ VALUE match = 0;
+ struct re_registers *regs0 = 0;
/* case-flag set for the object */
- if (FL_TEST(reg, FL_USER1)) {
+ if (FL_TEST(reg, REG_IGNORECASE)) {
casefold = TRUE;
}
if (casefold) {
@@ -139,142 +175,113 @@ research(reg, str, start)
}
if (start > str->len) return -1;
- result = re_search(reg->ptr, str->ptr, str->len,
- start, str->len - start, &last_match.regs);
- if (result >= 0) {
- last_match.len = str->len;
- if (last_match.ptr == Qnil) {
- last_match.ptr = ALLOC_N(char, str->len+1);
- }
- else {
- REALLOC_N(last_match.ptr, char, str->len+1);
+ if (regs == (struct re_registers *)-1) {
+ regs = 0;
+ }
+ else if (match = backref_get()) {
+ if (match == 1) {
+ match = match_alloc();
+ backref_set(match);
}
- memcpy(last_match.ptr, str->ptr, last_match.len);
- last_match.ptr[last_match.len] = '\0';
+ regs0 = RMATCH(match)->regs;
+ }
+
+ if (regs && !match) regs0 = regs;
+
+ if ((RBASIC(reg)->flags & KCODE_MASK) != reg_kcode) {
+ char *err;
+
+ if ((err = re_compile_pattern(reg->str, reg->len, reg->ptr)) != NULL)
+ Fail("%s: /%s/", err, reg->str);
+ RBASIC(reg)->flags = RBASIC(reg)->flags & ~KCODE_MASK;
+ RBASIC(reg)->flags |= reg_kcode;
+ }
+
+ result = re_search(reg->ptr, str->ptr, str->len,
+ start, str->len - start, regs0);
+
+ if (match && result >= 0) {
+ RMATCH(match)->len = str->len;
+ REALLOC_N(RMATCH(match)->ptr, char, str->len+1);
+ memcpy(RMATCH(match)->ptr, str->ptr, str->len);
+ RMATCH(match)->ptr[str->len] = '\0';
}
+ if (regs && regs0 && regs0 != regs) re_copy_registers(regs, regs0);
return result;
}
VALUE
-re_nth_match(nth)
+reg_nth_defined(nth, match)
int nth;
+ struct RMatch *match;
+{
+ if (!match) return FALSE;
+ if (nth >= match->regs->num_regs) {
+ return FALSE;
+ }
+ if (match->BEG(nth) == -1) return FALSE;
+ return TRUE;
+}
+
+VALUE
+reg_nth_match(nth, match)
+ int nth;
+ struct RMatch *match;
{
int start, end, len;
- if (nth >= last_match.regs.num_regs) {
+ if (!match) return Qnil;
+ if (nth >= match->regs->num_regs) {
return Qnil;
}
- start = BEG(nth);
+ start = match->BEG(nth);
if (start == -1) return Qnil;
- end = END(nth);
+ end = match->END(nth);
len = end - start;
- return str_new(last_match.ptr + start, len);
+ return str_new(match->ptr + start, len);
}
VALUE
-re_last_match(id)
- ID id;
+reg_last_match(match)
+ struct RMatch *match;
{
- return re_nth_match(0);
+ return reg_nth_match(0, match);
}
-static VALUE
-re_match_pre()
+VALUE
+reg_match_pre(match)
+ struct RMatch *match;
{
- struct match *match;
-
- if (BEG(0) == -1) return Qnil;
- return str_new(last_match.ptr, BEG(0));
+ if (!match) return Qnil;
+ if (match->BEG(0) == -1) return Qnil;
+ return str_new(match->ptr, match->BEG(0));
}
-static VALUE
-re_match_post()
+VALUE
+reg_match_post(match)
+ struct RMatch *match;
{
- struct match *match;
-
- if (BEG(0) == -1) return Qnil;
- return str_new(last_match.ptr+END(0),
- last_match.len-END(0));
+ if (!match) return Qnil;
+ if (match->BEG(0) == -1) return Qnil;
+ return str_new(match->ptr+match->END(0),
+ match->len-match->END(0));
}
-static VALUE
-re_match_last()
+VALUE
+reg_match_last(match)
+ struct RMatch *match;
{
- int i, len;
+ int i;
- if (BEG(0) == -1) return Qnil;
+ if (!match) return Qnil;
+ if (match->BEG(0) == -1) return Qnil;
- for (i=last_match.regs.num_regs-1; BEG(i) == -1 && i > 0; i--) {
- }
+ for (i=match->regs->num_regs-1; match->BEG(i) == -1 && i > 0; i--)
+ ;
if (i == 0) return Qnil;
- return re_nth_match(i);
-}
-
-static VALUE
-get_match_data(id, nth)
- ID id;
- int nth;
-{
- return re_nth_match(nth);
-}
-
-static void
-free_match(data)
- struct match *data;
-{
- free(data->ptr);
- if (data->regs.allocated > 0) {
- free(data->regs.beg);
- free(data->regs.end);
- }
-}
-
-static VALUE
-get_match()
-{
- struct match *data;
- int beg, i;
-
- data = ALLOC(struct match);
-
- data->len = last_match.len;
- data->ptr = ALLOC_N(char, last_match.len+1);
- memcpy(data->ptr, last_match.ptr, data->len+1);
- data->regs.allocated = 0;
- re_copy_registers(&data->regs, &last_match.regs);
-
- return data_new(data, free_match, Qnil);
-}
-
-static VALUE
-set_match(val)
- struct RArray *val;
-{
- struct match *match;
-
- Check_Type(val, T_DATA);
- match = (struct match*)DATA_PTR(val);
- last_match.len = match->len;
- if (last_match.len == 0) {
- if (last_match.ptr) {
- free(last_match.ptr);
- last_match.ptr = Qnil;
- }
- }
- else {
- if (last_match.ptr == Qnil) {
- last_match.ptr = ALLOC_N(char, match->len+1);
- }
- else {
- REALLOC_N(last_match.ptr, char, match->len+1);
- }
- }
- memcpy(last_match.ptr, match->ptr, last_match.len+1);
- last_match.regs = match->regs;
-
- return (VALUE)val;
+ return reg_nth_match(i, match);
}
void
@@ -293,10 +300,10 @@ const char *s;
Fail(s);
}
-VALUE C_Regexp;
+VALUE cRegexp;
static VALUE
-regexp_new_1(class, s, len, ci)
+reg_new_1(class, s, len, ci)
VALUE class;
char *s;
int len, ci;
@@ -310,41 +317,44 @@ regexp_new_1(class, s, len, ci)
re->str[len] = '\0';
re->len = len;
- if (ci) FL_SET(re, FL_USER1);
+ FL_SET(re, reg_kcode);
+ if (ci) FL_SET(re, REG_IGNORECASE);
+
return (VALUE)re;
}
VALUE
-regexp_new(s, len, ci)
+reg_new(s, len, ci)
char *s;
int len, ci;
{
- return regexp_new_1(C_Regexp, s, len, ci);
+ return reg_new_1(cRegexp, s, len, ci);
}
-static VALUE str_cache, reg_cache;
+static VALUE reg_cache, ign_cache;
VALUE
-re_regcomp(str)
+reg_regcomp(str)
struct RString *str;
{
- if (str_cache && RSTRING(str_cache)->len == str->len &&
- memcmp(RSTRING(str_cache)->ptr, str->ptr, str->len))
+ if (reg_cache && RREGEXP(reg_cache)->len == str->len
+ && ign_cache == ignorecase
+ && memcmp(RREGEXP(reg_cache)->str, str->ptr, str->len) == 0)
return reg_cache;
- str_cache = (VALUE)str;
- return reg_cache = regexp_new(str->ptr, str->len, ignorecase);
+ ign_cache = ignorecase;
+ return reg_cache = reg_new(str->ptr, str->len, ignorecase);
}
VALUE
-Freg_match(re, str)
+reg_match(re, str)
struct RRegexp *re;
struct RString *str;
{
int start;
- Check_Type(str, T_STRING);
- start = research(re, str, 0);
+ if (TYPE(str) != T_STRING) return FALSE;
+ start = reg_search(re, str, 0, 0);
if (start < 0) {
return Qnil;
}
@@ -352,7 +362,7 @@ Freg_match(re, str)
}
VALUE
-Freg_match2(re)
+reg_match2(re)
struct RRegexp *re;
{
extern VALUE rb_lastline;
@@ -361,7 +371,7 @@ Freg_match2(re)
if (TYPE(rb_lastline) != T_STRING)
Fail("$_ is not a string");
- start = research(re, rb_lastline, 0);
+ start = reg_search(re, rb_lastline, 0, 0);
if (start == -1) {
return Qnil;
}
@@ -369,7 +379,7 @@ Freg_match2(re)
}
static VALUE
-Sreg_new(argc, argv, self)
+reg_s_new(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
@@ -387,10 +397,10 @@ Sreg_new(argc, argv, self)
src = argv[0];
switch (TYPE(src)) {
case T_STRING:
- reg = regexp_new_1(self, RREGEXP(src)->ptr, RREGEXP(src)->len, ci);
+ reg = reg_new_1(self, RREGEXP(src)->ptr, RREGEXP(src)->len, ci);
case T_REGEXP:
- reg = regexp_new_1(self, RREGEXP(src)->str, RREGEXP(src)->len, ci);
+ reg = reg_new_1(self, RREGEXP(src)->str, RREGEXP(src)->len, ci);
default:
Check_Type(src, T_STRING);
@@ -400,7 +410,7 @@ Sreg_new(argc, argv, self)
}
static VALUE
-Sreg_quote(re, str)
+reg_s_quote(re, str)
VALUE re;
struct RString *str;
{
@@ -430,20 +440,22 @@ Sreg_quote(re, str)
}
static VALUE
-Freg_clone(re)
+reg_clone(re)
struct RRegexp *re;
{
- int ci = FL_TEST(re, FL_USER1);
- return regexp_new_1(CLASS_OF(re), re->str, re->len, ci);
+ int ci = FL_TEST(re, REG_IGNORECASE);
+ return reg_new_1(CLASS_OF(re), re->str, re->len, ci);
}
VALUE
-re_regsub(str)
+reg_regsub(str, src, regs)
struct RString *str;
+ struct RString *src;
+ struct re_registers *regs;
{
VALUE val = Qnil;
char *p, *s, *e, c;
- int no, len;
+ int no;
p = s = str->ptr;
e = s + str->len;
@@ -471,10 +483,10 @@ re_regsub(str)
if (no < 0) { /* Ordinary character. */
if (c == '\\' && (*s == '\\' || *s == '&'))
- p = ++s;
+ p = s++;
} else {
if (BEG(no) == -1) continue;
- str_cat(val, last_match.ptr+BEG(no), END(no)-BEG(no));
+ str_cat(val, src->ptr+BEG(no), END(no)-BEG(no));
}
}
@@ -489,12 +501,26 @@ re_regsub(str)
}
static VALUE
-kcode()
+reg_to_s(re)
+ struct RRegexp *re;
{
- switch (re_syntax_options & RE_MBCTYPE_MASK) {
- case RE_MBCTYPE_SJIS:
+ VALUE str = str_new2("/");
+
+ str_cat(str, re->str, re->len);
+ str_cat(str, "/", 1);
+ if (FL_TEST(re, REG_IGNORECASE)) {
+ str_cat(str, "i", 1);
+ }
+ return str;
+}
+
+static VALUE
+kcode_getter()
+{
+ switch (reg_kcode) {
+ case KCODE_SJIS:
return str_new2("SJIS");
- case RE_MBCTYPE_EUC:
+ case KCODE_EUC:
return str_new2("EUC");
default:
return str_new2("NONE");
@@ -502,19 +528,21 @@ kcode()
}
void
-rb_set_kanjicode(code)
+rb_set_kcode(code)
char *code;
{
- if (code == Qnil) goto set_no_conversion;
+ if (code == 0) goto set_no_conversion;
switch (code[0]) {
case 'E':
case 'e':
+ reg_kcode = KCODE_EUC;
re_syntax_options &= ~RE_MBCTYPE_MASK;
re_syntax_options |= RE_MBCTYPE_EUC;
break;
case 'S':
case 's':
+ reg_kcode = KCODE_SJIS;
re_syntax_options &= ~RE_MBCTYPE_MASK;
re_syntax_options |= RE_MBCTYPE_SJIS;
break;
@@ -522,25 +550,57 @@ rb_set_kanjicode(code)
case 'N':
case 'n':
set_no_conversion:
+ reg_kcode = KCODE_NONE;
re_syntax_options &= ~RE_MBCTYPE_MASK;
break;
}
re_set_syntax(re_syntax_options);
}
-void
-rb_setup_kcode()
+static VALUE
+kcode_setter(val)
+ struct RString *val;
{
- rb_define_const(C_Object, "KCODE", kcode());
+ Check_Type(val, T_STRING);
+ rb_set_kcode(val->ptr);
+ return (VALUE)val;
+}
+
+static VALUE
+match_getter()
+{
+ VALUE match = backref_get();
+
+ if (match && match != 1) {
+ NEWOBJ(m, struct RMatch);
+ OBJSETUP(m, cData, T_MATCH);
+
+ m->len = RMATCH(match)->len;
+ if (RMATCH(match)->ptr) {
+ m->ptr = ALLOC_N(char, m->len+1);
+ memcpy(m->ptr, RMATCH(match)->ptr, m->len);
+ m->ptr[m->len] = '\0';
+ }
+ else {
+ m->ptr = 0;
+ }
+ m->regs = ALLOC(struct re_registers);
+ re_copy_registers(m->regs, RMATCH(match)->regs);
+ return (VALUE)m;
+ }
+ return Qnil;
}
-VALUE rb_readonly_hook();
+static void
+match_setter(val)
+{
+ Check_Type(val, T_MATCH);
+ backref_set(val);
+}
void
Init_Regexp()
{
- int i;
-
re_set_syntax(RE_NO_BK_PARENS | RE_NO_BK_VBAR
| RE_AWK_CLASS_HACK
| RE_INTERVALS
@@ -551,23 +611,20 @@ Init_Regexp()
#endif
);
- rb_define_variable("$~", Qnil, get_match, set_match, 0);
-
- rb_define_variable("$&", Qnil, re_last_match, Qnil, 0);
- rb_define_variable("$`", Qnil, re_match_pre, Qnil, 0);
- rb_define_variable("$'", Qnil, re_match_post, Qnil, 0);
- rb_define_variable("$+", Qnil, re_match_last, Qnil, 0);
+ rb_define_virtual_variable("$~", match_getter, match_setter);
- rb_define_variable("$=", &ignorecase, Qnil, Qnil, 0);
+ rb_define_variable("$=", &ignorecase, 0);
+ rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter);
- C_Regexp = rb_define_class("Regexp", C_Object);
- rb_define_single_method(C_Regexp, "new", Sreg_new, -1);
- rb_define_single_method(C_Regexp, "compile", Sreg_new, -1);
- rb_define_single_method(C_Regexp, "quote", Sreg_quote, 1);
+ cRegexp = rb_define_class("Regexp", cObject);
+ rb_define_singleton_method(cRegexp, "new", reg_s_new, -1);
+ rb_define_singleton_method(cRegexp, "compile", reg_s_new, -1);
+ rb_define_singleton_method(cRegexp, "quote", reg_s_quote, 1);
- rb_define_method(C_Regexp, "=~", Freg_match, 1);
- rb_define_method(C_Regexp, "~", Freg_match2, 0);
+ rb_define_method(cRegexp, "clone", reg_clone, 0);
+ rb_define_method(cRegexp, "=~", reg_match, 1);
+ rb_define_method(cRegexp, "~", reg_match2, 0);
+ rb_define_method(cRegexp, "to_s", reg_to_s, 0);
- rb_global_variable(&str_cache);
rb_global_variable(&reg_cache);
}
diff --git a/re.h b/re.h
index 1db1ec34cc..babbe413e5 100644
--- a/re.h
+++ b/re.h
@@ -21,16 +21,14 @@
typedef struct re_pattern_buffer Regexp;
-struct match {
+struct RMatch {
+ struct RBasic basic;
UINT len;
char *ptr;
- struct re_registers regs;
+ struct re_registers *regs;
};
-extern struct match last_match;
-
-#define BEG(no) last_match.regs.beg[no]
-#define END(no) last_match.regs.end[no]
+#define RMATCH(obj) (R_CAST(RMatch)(obj))
VALUE re_regcomp();
VALUE re_regsub();
diff --git a/regex.c b/regex.c
index cef4543788..4b4ff8a193 100644
--- a/regex.c
+++ b/regex.c
@@ -1743,7 +1743,6 @@ re_search(pbufp, string, size, startpos, range, regs)
{
register char *fastmap = pbufp->fastmap;
register unsigned char *translate = (unsigned char *) pbufp->translate;
- int endpos = startpos + range;
int val;
/* Check for out-of-range starting position. */
@@ -1811,9 +1810,9 @@ re_search(pbufp, string, size, startpos, range, regs)
return -2;
#ifndef NO_ALLOCA
-#ifdef C_ALLOCA
+#ifdef cALLOCA
alloca(0);
-#endif /* C_ALLOCA */
+#endif /* cALLOCA */
#endif /* NO_ALLOCA */
advance:
@@ -1968,10 +1967,6 @@ struct register_info
} \
}
-/* Test if at very beginning or at very end of the virtual concatenation
- of string1 and string2. If there is only one string, we've put it in
- string2. */
-
#define AT_STRINGS_BEG (d == string)
#define AT_STRINGS_END (d == dend)
@@ -2667,6 +2662,7 @@ re_copy_registers(regs1, regs2)
{
int i;
+ if (regs1 == regs2) return;
if (regs1->allocated == 0) {
regs1->beg = TMALLOC(regs2->num_regs, int);
regs1->end = TMALLOC(regs2->num_regs, int);
@@ -2680,3 +2676,11 @@ re_copy_registers(regs1, regs2)
regs1->end[i] = regs2->end[i];
}
}
+
+void
+re_free_registers(regs)
+ struct re_registers *regs;
+{
+ if (regs->beg) free(regs->beg);
+ if (regs->end) free(regs->end);
+}
diff --git a/regex.h b/regex.h
index 8162d79119..971c4e5c74 100644
--- a/regex.h
+++ b/regex.h
@@ -275,6 +275,7 @@ extern int re_search ();
extern int re_match ();
extern long re_set_syntax();
extern void re_copy_registers ();
+extern void re_free_registers ();
#endif /* __STDC__ */
diff --git a/ruby.1 b/ruby.1
deleted file mode 100644
index b8c6162554..0000000000
--- a/ruby.1
+++ /dev/null
@@ -1,248 +0,0 @@
-.\"ruby.1 - -*- Nroff -*-
-.\" $Author: matz $
-.\" $Date: 1994/11/22 01:22:40 $
-.\" created at: Tue Apr 12 01:45:04 JST 1994
-.TH RUBY 1 "\*(RP"
-.UC
-.SH NAME
-ruby \- ֥Ȼظץȸ
-.SH SYNOPSIS
-.B ruby
-[
-.B options
-] filename args
-.SH DESCRIPTION
-.B Ruby
-, ڤʥ֥Ȼظץߥ󥰤¸뤿μ
-εǽĥ֥ȻظץȸǤ롥߷פ
-ܸ§, ʲ̤Ǥ.
-
-.IP ǽ
-֥Ȼظץߥ󥰤ȥץȥץߥ󥰤Τ
-ɬפʵǽʬ. ä˥ƥȽطεǽ˭
-٤˻ġޤ, ʥ֥ȻظǤʤ, ɬ
-Ǥм³ץߥ󥰤ǽǤ.
-.IP ĥ
-ɬפ˱ưפ˵ǽĥǤ. 饹ͳɲäǤ
-Ȥ, CץΥ󥯤ˤäƥ󥿥ץ꥿ˤ
-뵡ǽɲäǤ. ˥ץåȥեˤäƤ, ưŪ
-֥ȥɤ󥯤뵡ǽ󶡤.
-.IP
-θ§ΤŬѤ褦ʰΤͤ.
-ˤäơ֥ѥγڤפϸΤʤ. ,
-ΤȤ䤹ˤ뤳ȤϤʤ.
-.PP
-.B Ruby
-shperlΤäƤͤˤȤäƤξQˤǤ¤꽾äΤ,
-θ̤ƤͤˤȤäƤϽ(¿ʬ)ưפ.
-.SH OPTIONS
-.B ruby
-󥿥ץ꥿ϰʲΰդ.
-.TP 5
-.B \-0
-ϥ쥳ɥѥ졼(`$/')8ʿǻꤹ.
-
-ꤷʤϥ̥륭饯ѥ졼ˤʤ롣
-¾ΥåäƤ褤
-
-\-00, ѥ饰ե⡼, \-0777(Υɤʸ¸
-ߤʤΤ)ե٤ɤ߹⡼ɤǤ.
-.TP 5
-.B \-a
-`\-n'`\-p'ȤȤѤ, ȥץåȥ⡼ɤONˤ.
-ȥץåȥ⡼ɤǤϳƥ롼פƬ,
-.nf
-.ne 2
-
- $F = $_.split
-
-.fi
-¹Ԥ. `\-n'`\-p'ץƱ˻ꤵʤ¤,
-Υץϰ̣ʤ.
-.TP 5
-.B \-c
-ץȤؤΥѥΤߤԤ, ¹Ԥʤ.
-ѥ뽪λ, ʸˡ顼̵, "Syntax OK"ȽϤ.
-.TP 5
-.B \-K " c"
-.B ruby
-νɤꤹ.
-.B ruby
-ϻꤷʸ `E'ޤ`e'ξʸ䥢ե
-뤬EUCǵҤƤȲꤹ. Ʊͤ`S'ޤ`s'ξ
-SJISȤƽ. `N'ϴʤ. ǥեȤ
-EUC.
-.nf
-.ne 2
-
- ruby -CE -e 'print "ƥ"'
- ruby -Cs -e 'print "ƥ"'
- ruby -Cn -e 'print "ƥ"'
-
-.fi
-ΥץϾʸɤμưȽ̵ǽɲä줿
-ˤѹ.
-.TP 5
-.B \-d, \-\-debug
-ǥХå⡼ɤonˤ. Υե饰åȤȥƥ
-ѿ$DEBUGåȤ.
-.TP 5
-.B \-e " script"
-ޥɥ饤󤫤饹ץȤꤹ. \-eץդ
-ˤϰ饹ץȥե̾ʤ.
-.TP 5
-.B \-F" ʸ"
-ϥեɥѥ졼(`$;')ͤʸ˥åȤ. awk
-Ʊ̾ΥץƱƯ򤹤.
-.TP 5
-.B \-i" extension"
-ǻꤵ줿եƤ֤(in-place edit)
-Ȥꤹ. ΥեϳĥҤĤ¸.
-.nf
-:
-.ne 2
-
- % echo matz > /tmp/junk
- % cat /tmp/junk
- matz
- % ruby -p -i.bak -e '$_.upcase' /tmp/junk
- % cat /tmp/junk
- MATZ
- % cat /tmp/junk.bak
- matz
-
-.fi
-.TP 5
-.B \-I" directory"
-եɤѥ(ɲ). ꤵ줿ǥ쥯
-.B ruby
-ѿ$LOAD_PATHɲä.
-.TP 5
-.B \-l
-`$\\'`$/'Ʊͤꤷ, print()Ǥνϻ˲Ԥղä
-. ޤ, \-nޤ\-pȤȤѤ, Ϥ줿ƹԤ
-Ǹʸchop.
-.TP 5
-.B \-n
-Υե饰åȤȥץΤ
-.nf
-.ne 2
-
- while gets()
- \.\.\.
- end
-
-.fi
-ǰϤޤƤ褦ư.
-.TP 5
-.B \-p
-`\-n'ե饰Ʊ, ƥ롼פκǸѿ`$_'ͤϤ.
-.nf
-:
-.ne 2
-
- % echo matz | ruby \-p \-e '$_\.tr "a-z", "A-Z"'
- MATZ
-
-.fi
-.TP 5
-.B \-s
-ץ̾³, \-ǻϤޤᤷ, Ʊ̾ѿ
-ͤꤹ. `\-\-'ʤʹߤϲԤʤʤ.
-$ARGV.
-.nf
-:
-.ne 2
-
- #! /usr/local/bin/ruby \-s
- # \-xyzץͿ"true"ɽ.
- print "true\n" if $xyz
-
-.fi
-.TP 5
-.B \-S
-ץ̾`/'ǻϤޤäƤʤ, Ķѿ`PATH'ͤ
-ȤäƥץȤõ. ϡ#! 򥵥ݡȤƤʤޥ
-ǡ#! ˤ¹Ԥ򥨥ߥ졼Ȥ뤿ˡʲΤ褦ˤ
-ƻȤȤǤ:
-
- #! /usr/local/bin/ruby
- # This line makes the next one a comment in ruby \
- eval "exec /usr/local/bin/ruby -S $0 $*"
-
-ƥϺǽιԤ̵뤷ץȤ`/bin/sh'Ϥ
-`/bin/sh'rubyץȤ򥷥륹ץȤȤƼ¹Ԥ褦
-Ȥ롥2ܤ򥳥ȤǤȲᤷ3ܤ
-Υ륳ޥɤȤƼ¹Ԥruby󥿥ץ꥿ư롥
-
-ƥˤäƤ`$0'ɬեѥޤޤʤΤǡ`-S'
-Ѥrubyɬפ˱ƥץȤõ褦˻ؼ롥
-rubyץȤ򸫤ĤȡιԤβϤϤ뤬
-ruby2ܤιˤХååˤꡤ2ܤΥ
-Ȥ3ܤޤǷ³Ȥߤʤơ3ܤ̵뤹롥
-
-ե̾˴ޤޤ륹ڡʤɤˤϡ`$*'
-`${1+"$@"}'Τۤ褤csh᤹ˤư
-
-.TP 5
-.B \-v, \-\-verbose
-Ĺ⡼. ư˥СֹɽԤ, ƥѿ
-$VERBOSE򥻥åȤ. ѿåȤƤ, Ĥ
-Υ᥽åɤϼ¹Ի˾ĹʥåϤ. \-v ץ
-󤬻ꤵq, ץʳΰʤˤϥС
-ɽ, ¹Ԥλ(ɸϤΥץȤԤ
-ʤ).
-.TP 5
-.B \-\-version
-.B ruby
-ΥСɽ.
-.nf
-ɽ:
-.ne 2
-
- ruby - version 0.56 (94/11/19)
-
-.fi
-.TP 5
-.B \-x"directory"
-åΥץȤФƼ¹Ԥ. #!ǻϤޤ,
-"ruby"ȤʸޤԤޤǤɤФ. ץȤν
-EOF(եν), ^D(ȥD), ^Z(ȥZ)
-ޤͽ``__END__''ǻꤹ.
-
-ǥ쥯ȥ̾ꤹȡץȼ¹˻ꤵ줿ǥ
-쥯ȥ˰ܤ.
-.TP 5
-.B \-y, \-\-yydebug
-ѥǥХå⡼. ѥιʸϤβɽ
-. ɽ˾ĹʤΤ, ѥ餽ΤΤǥХ
-ͰʳɽʤɤȻפ.
-
-.SH BUGS
-.PP
-٤. ñʽξperlawkʤɤ2,3ܤμ¹Ի֤.
-θȰۤʤ, 󶡤뵡ǽΤۤȤɤ᥽åɸ
-ӽФ𤹤뤳Ȥ, ¾θǤؿƤӽФ¿
-ʤ褦ʽǤϥ᥽åɥåʬ
-.B ruby
-ͭˤʤ뤷, ǡ¤ʣˤʤ, ֥Ȼظ
-åȤ褫Τ, ޤ뤫Τʤ.
-.PP
-perl국̤¿.
-.B ruby
-ɵᤷ̤Ǥ. , η,
-.B ruby
-ץȤperlɤߤ䤹Ϥ, 㴳ε̤
-򤷤䤹ȲƤȻפäߤ.
-.PP
-ɥȤԽʬ. ɬפʾ뤿ˤϥɤ
-ߤ.
-.PP
-ƥȤԽʬ. ХˤĤä, Ǥмʬľ,
-ä˶ߤ. ̵ʤ, ƥХƸ
-ΤˤƥݡȤߤ.
-
-.SH AUTHOR
- Թ (matz@caelum.co.jp)
diff --git a/ruby.c b/ruby.c
index ee3a684369..9d437f8895 100644
--- a/ruby.c
+++ b/ruby.c
@@ -31,7 +31,7 @@ int debug = 0;
int verbose = 0;
static int sflag = FALSE;
-char *inplace = Qnil;
+char *inplace = 0;
char *strdup();
extern int yydebug;
@@ -39,10 +39,6 @@ extern int nerrs;
int xflag = FALSE;
-#ifdef USE_DL
-char *rb_dln_argv0;
-#endif
-
static void load_stdin();
static void load_file();
@@ -52,6 +48,37 @@ static int do_split = FALSE;
static char *script;
+#ifndef RUBY_LIB
+#define RUBY_LIB ".:/usr/local/lib/ruby"
+#endif
+
+#define RUBY_LIB_SEP ':'
+
+extern VALUE rb_load_path;
+VALUE Frequire();
+
+static void
+addpath(path)
+ char *path;
+{
+ char *p, *s;
+
+ if (path == 0) return;
+
+ p = s = path;
+ while (*p) {
+ while (*p == RUBY_LIB_SEP) p++;
+ if (s = strchr(p, RUBY_LIB_SEP)) {
+ ary_push(rb_load_path, str_new(p, (int)(s-p)));
+ p = s + 1;
+ }
+ else {
+ ary_push(rb_load_path, str_new2(p));
+ break;
+ }
+ }
+}
+
static void
proc_options(argcp, argvp)
int *argcp;
@@ -62,7 +89,6 @@ proc_options(argcp, argvp)
int script_given, do_search;
char *s;
- extern VALUE rb_load_path;
extern VALUE RS, ORS, FS;
if (argc == 0) return;
@@ -81,7 +107,7 @@ proc_options(argcp, argvp)
do_split = TRUE;
s++;
goto reswitch;
-
+
case 'p':
do_print = TRUE;
/* through */
@@ -121,7 +147,7 @@ proc_options(argcp, argvp)
ORS = RS;
s++;
goto reswitch;
-
+
case 'S':
do_search = TRUE;
s++;
@@ -140,6 +166,16 @@ proc_options(argcp, argvp)
yyparse();
break;
+ case 'r':
+ if (*++s) {
+ f_require(Qnil, str_new2(s));
+ }
+ else if (argv[1]) {
+ f_require(Qnil, str_new2(argv[1]));
+ argc--,argv++;
+ }
+ break;
+
case 'i':
inplace = strdup(s+1);
break;
@@ -152,18 +188,34 @@ proc_options(argcp, argvp)
}
break;
+ case 'X':
+ s++;
+ if (!*s) {
+ s = argv[1];
+ argc--,argv++;
+ }
+ if (*s && chdir(s) < 0) {
+ Fatal("Can't chdir to %s", s);
+ }
+ break;
+
case 'F':
FS = str_new2(s+1);
break;
case 'K':
s++;
- rb_set_kanjicode(s);
+ rb_set_kcode(s);
s++;
goto reswitch;
case 'I':
- ary_unshift(rb_load_path, str_new2(s+1));
+ if (*++s)
+ ary_push(rb_load_path, str_new2(s));
+ else if (argv[1]) {
+ ary_push(rb_load_path, str_new2(argv[1]));
+ argc--,argv++;
+ }
break;
case '0':
@@ -185,9 +237,6 @@ proc_options(argcp, argvp)
}
goto reswitch;
- case 'u':
- case 'U':
-
case '-':
if (!s[1]) {
argc--,argv++;
@@ -218,7 +267,7 @@ proc_options(argcp, argvp)
}
switch_end:
- if (*argvp[0] == Qnil) return;
+ if (*argvp[0] == 0) return;
if (version) {
show_version();
@@ -228,8 +277,6 @@ proc_options(argcp, argvp)
show_copyright();
}
- rb_setup_kcode();
-
if (script_given == 0) {
if (argc == 0) { /* no more args */
if (verbose) exit(0);
@@ -263,10 +310,10 @@ proc_options(argcp, argvp)
argv[0][0] = '$';
if (s = strchr(argv[0], '=')) {
*s++ = '\0';
- rb_gvar_set2((*argvp)[0], str_new2(s));
+ rb_gvar_set2(argv[0], str_new2(s));
}
else {
- rb_gvar_set2((*argvp)[0], TRUE);
+ rb_gvar_set2(argv[0], TRUE);
}
}
*argcp = argc; *argvp = argv;
@@ -281,7 +328,7 @@ readin(fd, fname, script)
int script;
{
struct stat st;
- char *ptr, *p, *pend, *s;
+ char *ptr, *p, *pend;
if (fstat(fd, &st) < 0) rb_sys_fail(fname);
if (!S_ISREG(st.st_mode))
@@ -351,7 +398,6 @@ load_file(fname, script)
int script;
{
int fd;
- char *ptr;
if (fname[0] == '\0') {
load_stdin();
@@ -391,7 +437,7 @@ load_stdin()
readin(fd, "-");
}
-static VALUE Progname;
+VALUE Progname;
VALUE Argv;
static int origargc;
@@ -454,13 +500,13 @@ ruby_options(argc, argv, envp)
origargc = argc; origargv = argv; origenvp = envp;
- rb_define_variable("$@", &errat, Qnil, Qnil, 0);
+ rb_define_variable("$@", &errat);
errat = str_new2(argv[0]);
- rb_define_variable("$VERBOSE", &verbose, Qnil, Qnil, 0);
- rb_define_variable("$DEBUG", &debug, Qnil, Qnil, 0);
+ rb_define_variable("$VERBOSE", &verbose);
+ rb_define_variable("$DEBUG", &debug);
-#ifdef USE_DL
- rb_dln_argv0 = argv[0];
+#if defined(USE_DLN_A_OUT)
+ dln_argv0 = argv[0];
#endif
proc_options(&argc, &argv);
@@ -475,11 +521,14 @@ ruby_options(argc, argv, envp)
yywhole_loop(do_line, do_split);
}
- rb_define_variable("$0", &Progname, Qnil, set_arg0, 0);
+ rb_define_hooked_variable("$0", &Progname, 0, set_arg0);
ruby_script(script);
- rb_define_variable("$ARGV", &Argv, Qnil, Qnil, 0);
- rb_define_variable("$*", &Argv, Qnil, Qnil, 0);
+ addpath(getenv("RUBYLIB"));
+ addpath(RUBY_LIB);
+
+ rb_define_readonly_variable("$ARGV", &Argv);
+ rb_define_readonly_variable("$*", &Argv);
Argv = ary_new2(argc);
for (i=0; i < argc; i++) {
ary_push(Argv, str_new2(argv[i]));
diff --git a/ruby.h b/ruby.h
index b00b9fa214..5ea5a237af 100644
--- a/ruby.h
+++ b/ruby.h
@@ -13,16 +13,19 @@
#ifndef RUBY_H
#define RUBY_H
-#include "config.h"
+#ifndef NT
+# include "config.h"
+#endif
+
#include "defines.h"
#ifndef __STDC__
-#define volatile
-#ifdef __GNUC__
-#define const __const__
-#else
-#define const
-#endif
+# define volatile
+# ifdef __GNUC__
+# define const __const__
+# else
+# define const
+# endif
#endif
#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
@@ -39,9 +42,11 @@ typedef unsigned short USHORT;
# include <limits.h>
#else
# ifndef LONG_MAX
-# if !defined(LONG_MAX) || !defined(CHAR_BIT)
-# include <limits.h>
-# endif
+# ifdef HAVE_LIMITS_H
+# include <limits.h>
+# else
+# define LONG_MAX 2147483647 /* assuming 32bit(2's compliment) LONG */
+# endif
# endif
# ifndef LONG_MIN
# if (0 != ~0)
@@ -50,17 +55,17 @@ typedef unsigned short USHORT;
# define LONG_MIN (-LONG_MAX)
# endif
# endif
+# ifndef CHAR_BIT
+# define CHAR_BIT 8
+# endif
#endif
-#ifndef CHAR_BIT
-# define CHAR_BIT 8
-#endif
-
-# define FIXNUM_MAX (LONG_MAX>>1)
-# define FIXNUM_MIN RSHIFT((long)LONG_MIN,1)
+#define FIXNUM_MAX (LONG_MAX>>1)
+#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1)
#define FIXNUM_FLAG 0x01
#define INT2FIX(i) (VALUE)(((int)(i))<<1 | FIXNUM_FLAG)
+VALUE int2inum();
#if (-1==(((-1)<<1)&FIXNUM_FLAG)>>1)
# define RSHIFT(x,y) ((x)>>y)
@@ -69,25 +74,24 @@ typedef unsigned short USHORT;
#endif
#define FIX2INT(x) RSHIFT((int)x,1)
-#define FIX2UINT(f) ((unsigned int)(f)>>1)
+#define FIX2UINT(f) ((UINT)(f)>>1)
#define FIXNUM_P(f) (((int)(f))&FIXNUM_FLAG)
#define POSFIXABLE(f) ((f) <= FIXNUM_MAX)
#define NEGFIXABLE(f) ((f) >= FIXNUM_MIN)
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
-#define POINTER(p) (p)
#define NIL_P(p) ((p) == Qnil)
#undef TRUE
extern VALUE TRUE;
#define FALSE Qnil
-extern VALUE C_Object;
-extern VALUE C_Nil;
-extern VALUE C_Fixnum;
-extern VALUE C_Data;
+extern VALUE cObject;
+extern VALUE cNil;
+extern VALUE cFixnum;
+extern VALUE cData;
-#define CLASS_OF(obj) (FIXNUM_P(obj)?C_Fixnum: NIL_P(obj)?C_Nil:\
+#define CLASS_OF(obj) (FIXNUM_P(obj)?cFixnum: NIL_P(obj)?cNil:\
RBASIC(obj)->class)
#define T_NIL 0x00
@@ -103,9 +107,11 @@ extern VALUE C_Data;
#define T_HASH 0x0a
#define T_STRUCT 0x0b
#define T_BIGNUM 0x0c
-#define T_ASSOC 0x0f
+
#define T_DATA 0x10
+#define T_MATCH 0x11
+#define T_VARMAP 0xfd
#define T_SCOPE 0xfe
#define T_NODE 0xff
@@ -122,10 +128,10 @@ int num2int();
#define NEWOBJ(obj,type) type *obj = (type*)newobj()
#define OBJSETUP(obj,c,t) {\
RBASIC(obj)->class = (c);\
- RBASIC(obj)->flags |= (t);\
+ RBASIC(obj)->flags = (t);\
}
#define CLONESETUP(obj1,obj2) \
- OBJSETUP(obj1,RBASIC(obj2)->class,RBASIC(obj2)->flags&T_MASK);
+ OBJSETUP(obj1,RBASIC(obj2)->class,RBASIC(obj2)->flags);
struct RBasic {
UINT flags;
@@ -178,18 +184,18 @@ struct RData {
struct RBasic basic;
void (*dmark)();
void (*dfree)();
- VALUE *data;
+ void *data;
};
#define DATA_PTR(dta) (RDATA(dta)->data)
VALUE data_new();
-VALUE rb_ivar_get_1();
-VALUE rb_ivar_set_1();
+VALUE rb_ivar_get();
+VALUE rb_ivar_set();
#define Get_Data_Struct(obj, iv, type, sval) {\
VALUE _data_;\
- _data_ = rb_ivar_get_1(obj, iv);\
+ _data_ = rb_ivar_get(obj, iv);\
Check_Type(_data_, T_DATA);\
sval = (type*)DATA_PTR(_data_);\
}
@@ -197,19 +203,15 @@ VALUE rb_ivar_set_1();
#define Make_Data_Struct(obj, iv, type, mark, free, sval) {\
VALUE _new_;\
sval = ALLOC(type);\
- _new_ = data_new(sval,free,mark);\
+ _new_ = data_new(sval,mark,free);\
memset(sval, 0, sizeof(type));\
- rb_ivar_set_1(obj, iv, _new_);\
+ rb_ivar_set(obj, iv, _new_);\
}
struct RStruct {
struct RBasic basic;
UINT len;
- struct kv_pair {
- ID key;
- VALUE value;
- } *tbl;
- char *name;
+ VALUE *ptr;
};
struct RBignum {
@@ -219,14 +221,6 @@ struct RBignum {
USHORT *digits;
};
-struct RAssoc {
- struct RBasic basic;
- VALUE car, cdr;
-};
-
-#define CAR(c) (RASSOC(c)->car)
-#define CDR(c) (RASSOC(c)->cdr)
-
#define R_CAST(st) (struct st*)
#define RBASIC(obj) (R_CAST(RBasic)(obj))
#define ROBJECT(obj) (R_CAST(RObject)(obj))
@@ -239,7 +233,6 @@ struct RAssoc {
#define RDATA(obj) (R_CAST(RData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
-#define RASSOC(obj) (R_CAST(RAssoc)(obj))
#define FL_SINGLE (1<<8)
#define FL_MARK (1<<9)
@@ -271,38 +264,75 @@ extern VALUE Qself;
#define MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(n))
#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(n))
+#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n))
-#ifdef SAFE_SIGHANDLE
-extern int trap_immediate;
-# define TRAP_BEG (trap_immediate=1)
-# define TRAP_END (trap_immediate=0)
-#else
-# define TRAP_BEG
-# define TRAP_END
-#endif
+void *xmalloc();
+void *xcalloc();
+void *xrealloc();
VALUE rb_define_class();
VALUE rb_define_module();
+void rb_include_module();
+void rb_extend_object();
void rb_define_variable();
void rb_define_const();
void rb_define_method();
-void rb_define_single_method();
+void rb_define_singleton_method();
void rb_undef_method();
void rb_define_alias();
void rb_define_attr();
ID rb_intern();
char *rb_id2name();
+ID rb_to_id();
+
+char *rb_class2name();
+VALUE rb_method_boundp();
VALUE rb_eval_string();
VALUE rb_funcall();
VALUE rb_funcall2();
int rb_scan_args();
+VALUE rb_iv_get();
+VALUE rb_iv_set();
+void rb_const_set();
+
VALUE rb_yield();
+VALUE iterator_p();
+
+VALUE rb_equal();
extern int verbose, debug;
+#ifdef __GNUC__
+typedef void voidfn ();
+volatile voidfn Fail;
+volatile voidfn Fatal;
+volatile voidfn Bug;
+volatile voidfn WrongType;
+volatile voidfn rb_sys_fail;
+volatile voidfn rb_break;
+volatile voidfn rb_exit;
+volatile voidfn rb_fail;
+#else
+void Fail();
+void Fatal();
+void Bug();
+void WrongType();
+void rb_sys_fail();
+void rb_break();
+void rb_exit();
+void rb_fail();
+#endif
+
+void Warning();
+
+#if defined(EXTLIB) && defined(USE_DLN_A_OUT)
+/* hook for external modules */
+static char *libs_to_be_linked[] = { EXTLIB, 0 };
+#endif
+
#endif
diff --git a/ruby.texi b/ruby.texi
new file mode 100644
index 0000000000..50ffb63a16
--- /dev/null
+++ b/ruby.texi
@@ -0,0 +1,5044 @@
+\input texinfo @c -*-texinfo-*- created at: Tue Jun 20 16:58:39 JST 1995
+@setfilename ruby.info
+@settitle Ruby Reference Manual
+
+@titlepage
+@title Ruby Reference Manual
+@subtitle The Object-Oriented Scripting Language
+@author Yukihiro Matsumoto
+@author matz@@caelum.co.jp
+@end titlepage
+
+@node Top, Ϥ, (dir), (dir)
+
+Ruby Reference Manual
+
+@menu
+* Ϥ::
+* ޥɥ饤󥪥ץ::
+* rubyʸˡ::
+* Ȥ߹ߴؿ::
+* Ȥ߹ѿ::
+* Ȥ߹ߥ饹ȥ⥸塼::
+* CȤΥ󥿥ե::
+* ռ::
+* ʸˡ::
+* Variables Index::
+* Concept Index::
+* Function Index::
+@end menu
+
+@node Ϥ, ޥɥ饤󥪥ץ, Top, Top
+@comment node-name, next, previous, up
+@chapter Ϥ
+
+Ruby, ڤʥ֥Ȼظץߥ󥰤¸뤿μεǽ
+ĥ֥ȻظץȸǤ롥ܳŪʥ֥Ȼظ
+ǤSmalltalk, EiffelC++ʤɤǤ礲˻פ褦ΰǤΥ
+֥Ȼظץߥ󥰤ٱ礹뤳ȤŪȤ롥߷פδ
+§, ʲ̤Ǥ.
+
+@itemize @bullet
+@item
+
+
+ñ㳰ξʤʸˡǡ֥Ȼظץߥ󥰤ȥץȥ
+ߥ󥰤Τɬפʵǽʬ.
+
+@item
+
+
+ɬפ˱ưפ˵ǽĥǤ롥饹ͳɲäǤ뤳Ȥ,
+CץΥ󥯤ˤäƥ󥿥ץ꥿ˤ뵡ǽɲäǤ롥
+˥ץåȥեˤäƤ, ưŪ˥֥ȥɤ󥯤뵡
+ǽ󶡤.
+
+@item
+
+
+
+θ§ΤŬѤ褦ʰΤͤġ
+äơ֥ѥγڤפϸΤʤ,Τ
+䤹ˤ뤳ȤϤʤ.
+@end itemize
+
+RubyϡּڡפǤϤ뤬ܳŪʥ֥ȻظǽĤΤǡperl,
+tcl, pythonʤɥץȸ˥֥Ȼظǽɲä褦ʽ
+Ϥ⼫˥֥ȻظǤ롥˥١쥯㳰
+ǽϤŬʥץߥ󥰤ٱ礹롥
+
+RubyϥƥȽطεǽ˭٤(perlƱ餤)OSľ
+褦ʽ⵭ҤǤ롥ޤ, ʥ֥ȻظǤ
+, ɬפǤм³ץߥ󥰤ǽǤ.
+
+RubyshperlΤäƤͤˤȤäƤξQˤǤ¤꽾äΤ,
+θ̤ƤͤˤȤäƤϽ(¿ʬ)ưפץޤ
+RubyΥ֥ȻظǽˤĤƳؤ٤С궯ϤʤȤǤ褦
+
+@node ޥɥ饤󥪥ץ, rubyʸˡ, Ϥ, Top
+@comment node-name, next, previous, up
+@chapter ޥɥ饤󥪥ץ
+
+ruby󥿥ץ꥿ϰʲΰդ.
+
+@table @samp
+
+@item -0
+
+ϥ쥳ɥѥ졼(@code{$/})8ʿǻꤹ롥
+
+ꤷʤϥ̥륭饯ѥ졼ˤʤ롣θ¾Υ
+åäƤ褤
+
+-00, ѥ饰ե⡼, -0777(Υɤʸ¸ߤʤΤ)
+ե٤ɤ߹⡼ɤǤ.
+
+@item -a
+@cindex{ȥץåȥ⡼}
+
+@code{-n}@code{-p}ȤȤѤ, ȥץåȥ⡼ɤONˤ롥
+ȥץåȥ⡼ɤǤϳƥ롼פƬ,
+
+@example
+$F = $_.split
+@end example
+
+¹Ԥ롥@code{-n}@code{-p}ץƱ˻ꤵʤ¤,
+Υץϰ̣ʤ.
+
+@item -c
+
+ץȤؤΥѥΤߤԤ, ¹Ԥʤѥ뽪
+λ, ʸˡ顼̵, @samp{"Syntax OK"}ȽϤ.
+
+@item -K c
+
+rubyνɤꤹ롥 rubyϻꤵ줿ʸ @code{E}
+@code{e}ξʸ䥢եƤΥɤEUC
+Ȳꤹ롥Ʊͤ@code{S}ޤ@code{s}ξSJISȤƽ롥
+@code{N}ϴʤǥեȤEUC.
+
+@example
+ruby -CE -e 'print "ƥ"'
+ruby -Cs -e 'print "ƥ"'
+ruby -Cn -e 'print "ƥ"'
+@end example
+
+ΥץϾʸɤμưȽ̵ǽɲä줿ˤѹ
+.
+
+@item -d
+@itemx --debug
+
+ǥХå⡼ɤonˤ롥Υե饰åȤȥƥѿ
+@code{$DEBUG}åȤ.
+
+@item -e @var{script}
+
+ޥɥ饤󤫤饹ץȤꤹ롥-eץդˤϰ
+饹ץȥե̾ʤ.
+
+@item -F @var{ʸ}
+
+ϥեɥѥ졼(@code{$;})ͤʸ˥åȤ롥awkƱ̾
+ΥץƱƯ򤹤.
+
+@item -i @var{extension}
+
+ǻꤵ줿եƤ֤(in-place edit)Ȥꤹ
+롥ΥեϳĥҤĤ¸.
+
+:
+
+@example
+% echo matz > /tmp/junk
+% cat /tmp/junk
+matz
+% ruby -p -i.bak -e '$_.upcase' /tmp/junk
+% cat /tmp/junk
+MATZ
+% cat /tmp/junk.bak
+matz
+@end example
+
+ĥҤʤСХååפϤ줺ѹ줿եĤ롥
+
+@item -I @var{directory}
+
+եɤѥ(ɲ)롥ꤵ줿ǥ쥯ȥruby
+ѿ@code{$:}ɲä.
+
+@item -l
+
+@code{$\}@code{$/}Ʊͤꤷ, @code{print}Ǥνϻ˲Ԥ
+ä롥ޤ, @samp{-n}ޤ@samp{-p}ȤȤѤ, Ϥ줿
+ƹԤκǸʸ@code{chop!}.
+
+@item -n
+
+Υե饰åȤȥץΤ
+
+@example
+while gets
+ @dots{}
+end
+@end example
+
+ǰϤޤƤ褦ư.
+@item -p
+
+@code{-n}ե饰Ʊ, ƥ롼פκǸѿ@code{$_}ͤϤ.
+
+:
+
+@example
+% echo matz | ruby -p -e '$_.tr! "a-z", "A-Z"'
+MATZ
+@end example
+
+@item -r ե̾
+
+ץȼ¹˥ե̾ǻꤵե@code{require}롥
+@samp{-n}ץ@samp{-p}ץȤȤ˻ȤäͭǤ롥
+
+@xref{Ȥ߹ߴؿ}
+
+@item -s
+
+ץ̾³, @code{-}ǻϤޤᤷ, Ʊ̾ѿ
+ꤹ롥@code{--}ʤʹߤϲԤʤʤ
+@code{$ARGV}.
+
+:
+@example
+#! /usr/local/bin/ruby -s
+# -xyzץͿ"true"ɽ.
+print "true\n" if $xyz
+@end example
+
+@item -S
+
+ץ̾@code{/}ǻϤޤäƤʤ, Ķѿ@code{PATH}ͤ
+ȤäƥץȤõ ϡ@samp{#!} 򥵥ݡȤƤʤޥ
+ǡ@samp{#!} ˤ¹Ԥ򥨥ߥ졼Ȥ뤿ˡʲΤ褦ˤƻȤ
+ȤǤ:
+
+:
+@example
+#! /usr/local/bin/ruby
+# This line makes the next one a comment in ruby \
+ exec /usr/local/bin/ruby -S $0 $*
+@end example
+
+ƥϺǽιԤ̵뤷ץȤ@code{/bin/sh}Ϥ
+@code{/bin/sh}rubyץȤ򥷥륹ץȤȤƼ¹Ԥ褦Ȥ롥
+2ܤ򥳥ȤǤȲᤷ3ܤ̾Υ륳ޥ
+ȤƼ¹Ԥruby󥿥ץ꥿ư롥
+
+ƥˤäƤ@code{$0}ɬեѥޤޤʤΤǡ@code{-S}
+Ѥrubyɬפ˱ƥץȤõ褦˻ؼ롥ruby
+ץȤ򸫤ĤȡιԤβϤϤ뤬ruby2ܤιˤ
+Хååˤꡤ2ܤΥȤ3ܤޤǷ³Ȥߤʤơ
+3ܤ̵뤹롥
+
+ե̾˴ޤޤ륹ڡʤɤˤϡ@code{$*}
+@code{$@{1+"$@@"@}}Τۤ褤csh᤹ˤư
+@cindex{OS#!ᤷʤк}
+
+@item -v
+@itemx --verbose
+
+Ĺ⡼ɡư˥СֹɽԤ, ƥѿ
+@code{$VERBOSE}򥻥åȤ롥ѿåȤƤ, Ĥ
+᥽åɤϼ¹Ի˾ĹʥåϤ롥@samp{-v}ץ󤬻
+ꤵ, ʳΰʤˤϥСɽ, ¹Ԥλ
+(ɸϤΥץȤԤʤ).
+
+@item --version
+
+rubyΥСɽ.
+
+ɽ:
+
+@example
+ruby - version 0.87 (95/09/23)
+@end example
+
+@item -x[directory]
+
+åΥץȤФƼ¹Ԥ롥ץȤɤ߹ˡ
+@code{#!}ǻϤޤ, @code{ruby}ȤʸޤԤޤǤɤФ
+ץȤν@samp{EOF}(եν), @samp{^D}(ȥD),
+@samp{^Z}(ȥZ)ޤͽ@code{__END__}ǻꤹ.
+
+ǥ쥯ȥ̾ꤹȡץȼ¹˻ꤵ줿ǥ쥯ȥ
+ܤ.
+
+@item -X directory
+
+ץȼ¹˻ꤵ줿ǥ쥯ȥ˰ܤ.
+
+@item -y
+@itemx --yydebug
+
+ѥǥХå⡼ɡץȤɽ˥ѥ뤹ιʸ
+Ϥβɽ롥ɽ˾ĹʤΤ, ѥ餽ΤΤ
+ǥХåͰʳɽʤɤȻפ.
+@end table
+
+@node rubyʸˡ, Ȥ߹ߴؿ, ޥɥ饤󥪥ץ, Top
+@comment node-name, next, previous, up
+@chapter rubyʸˡ
+
+@menu
+* Lexical structure::
+* ץ::
+* ::
+@end menu
+
+@node Lexical structure, ץ, rubyʸˡ, rubyʸˡ
+@comment node-name, next, previous, up
+@section Lexical structure
+
+ߤrubyμϥ饯åȤȤASCIIѤ롥rubyʸ
+ʸ̤롥̻ҤǤʤǤդΤȤ˶ʸ򤪤
+Ȥ롥ʸϥڡ(space)(tab)ľ(vertical
+tab) CR(carriage return)(form feed)Ǥ롥(newline)
+˼³ˤ϶ʸȤơʳǤʸζڤȤƲ
+ᤵ롥
+
+̻Ҥϱʸ(@samp{"_"}ޤ)Ϥޤꡤѿ³ΤǤ롥
+rubyμ̻ҤŤϤʤߤμϼ̻ҤȤƥޥХȥ
+(EUC,SJIS)̤ʤ
+
+̻Ҥ
+
+@example
+foobar
+ruby_is_simple
+@end example
+
+@menu
+* ::
+* ͽ::
+* ڤʸ::
+@end menu
+
+@node , ͽ, Lexical structure, Lexical structure
+@comment node-name, next, previous, up
+@subsection
+
+
+
+@example
+# this is a comment line
+@end example
+
+ץȸνˤʤ餤ʸʸɽ(@code{?#})ʳ
+@code{#}ޤǤϥȤȸʤȹΥХåå
+ϼιԤؤΥȤη³̣롥
+
+@node ͽ, ڤʸ, , Lexical structure
+@comment node-name, next, previous, up
+@subsection ͽ
+
+ͽϰʲ̤Ǥ
+
+@display
+alias def for redo undef
+and defined? if rescue when
+begin else in retry while
+break elsif module return yield
+case end nil self __END__
+class ensure not super __FILE__
+continue fail or then __LINE__
+@end display
+
+ͽϥ饹̾᥽å̾ѿ̾ʤɤѤ뤳ȤϤǤʤ
+@samp{$}, @samp{@@}ƬˤĤΤͽȸʤʤΤǡ
+Хѿ󥹥ѿˤĤƤʤ
+
+@node ڤʸ, , ͽ, Lexical structure
+@comment node-name, next, previous, up
+@subsection ڤʸ
+
+ʸʤɤΥƥʳξζʸ(֤ȥڡ)Ӳ
+(@samp{\n})ڤ국Ȥʤ롥˲Ԥ
+
+@example
+a +
+b
+@end example
+
+Τ褦˹ԤǽꡤιԤ³Ȥ(Ǹʸ
+黻Ҥ뤤@code{,}Ǥ)ζڤȤǧ롥
+
+@node ץ, , Lexical structure, rubyʸˡ
+@comment node-name, next, previous, up
+@section ץ
+
+
+
+@example
+print "hello world!\n"
+@end example
+
+ץϼ¤٤ΤǤ롥ȼδ֤ϥߥ(@code{;})ޤ
+ϲԤǶڤ롥
+
+@node , , ץ, rubyʸˡ
+@comment node-name, next, previous, up
+@section
+
+
+
+@example
+TRUE
+(1+2)*3
+foo()
+if test then ok else ng end
+@end example
+
+RubyǤ@code{nil}ʳɾ롥CPerlʤɤȤϰۤ
+ꡤ0@code{""}(ʸ)ϵȤɾʤΤǵĤ뤳ȡ
+
+ϳ̤ˤäƥ롼ԥ󥰤뤳ȤǤ롥
+
+@menu
+* ʸ::
+* ޥɽ::
+* ɽ::
+* ѿŸ::
+* ͥƥ::
+* ѿ::
+* Хѿ::
+* 󥹥ѿ::
+* 饹::
+* ѿ::
+* ѿ::
+* ::
+* Ϣ::
+* ᥽åɸƽм::
+* SUPER::
+* ::
+* 黻Ҽ::
+* 湽¤::
+* 饹::
+* ⥸塼::
+* ᥽å::
+* ðۥ᥽å::
+* ALIAS::
+* UNDEF::
+* DEFINED?::
+@end menu
+
+@node ʸ, ޥɽ, ,
+@comment node-name, next, previous, up
+@subsection ʸ
+@cindex ʸ
+
+
+
+@example
+"this is a string expression\n"
+'ʸ'
+@end example
+
+֥륯(@code{"})dz줿ʸϥХåå³ʸ
+ʲΤ褦˲ᤵ롥
+
+Хåå嵭ˡ
+
+@table @samp
+@item \t
+(0x09)
+@item \n
+ʸ(0x0a)
+@item \r
+ʸ(0x0d)
+@item \f
+ڡʸ(0x0c)
+@item \b
+Хåڡ(0x08)
+@item \a
+٥(0x07)
+@item \e
+(0x1b)
+@item \nnn
+8ʿɽ(n0-7)
+@item \xnn
+16ʿɽ(n0-9,a-f)
+@item \cx
+ȥʸ(xASCIIʸ)
+@item \x
+ʸxΤ
+@end table
+
+ޤ@code{#}ˤѿŸԤ롥
+
+@xref{ѿŸ}
+
+󥰥륯(@code{'})dz줿ʸϡ@code{\\}(Хå
+å夽Τ)@code{\'}(󥰥륯)ơʸȤ
+Ԥʤ
+
+ʸ󼰤󿷤ʸ󥪥֥ȤΤǡʸƤ
+Ƥ⡤ȤȤʸѤʤ
+
+@node ޥɽ, ɽ, ʸ,
+@comment node-name, next, previous, up
+@subsection ޥɽ
+@cindex ޥɽ
+
+
+
+@example
+`date`
+@end example
+
+RubyǤshΤ褦˥ޥɤμ¹Է̤ʸƥΤ褦˻ȤȤ
+Ǥ롥@code{``}ǰϤޤ줿ʸϡ֥륯ȤǰϤޤ줿ʸ
+Ʊͤ˥Хåå嵭ˡβѿŸԤʤ줿塤ޥɤȤ
+Ƽ¹Ԥ졤μ¹Է̤ʸȤͿ롥ޥɤɾ
+Ӥ˼¹Ԥ롥
+
+@node ɽ, ѿŸ, ޥɽ,
+@comment node-name, next, previous, up
+@subsection ɽ
+@cindex ɽ
+
+
+
+@example
+/^ruby the OOPL/
+/ruby/i
+@end example
+
+@code{/}ǰϤޤ줿ʸɽɽ@code{/}θʸ
+@code{i}Ϳ줿ˤϡɽϥޥåʸʸζ
+̤򤷤ʤ
+
+@table @code
+@item ^
+@item $
+
+@item .
+Ǥդ1ʸ
+@item \w
+ѿ[0-9A-Za-z_]Ʊ
+@item \W
+ѿ
+@item \s
+ʸ[ \t\n\r\f]Ʊ
+@item \S
+@item \d
+[0-9] Ʊ
+@item \D
+
+@item \b
+춭ʸ(ʸ饹)
+@item \B
+춭ʸ
+@item \b
+(0x08)(ʸ饹)
+@item [ ]
+ʸ饹
+@item *
+ľɽ0ʾη֤
+@item +
+ľɽ1ʾη֤
+@item {m,n}
+m󤫤nη֤
+@item ?
+0ޤ1
+@item |
+
+@item ( )
+ɽޤȤ
+@end table
+
+¾ʸƱХåå嵭ˡѿŸͭǤ롥
+
+@node ѿŸ, ͥƥ, ɽ,
+@comment node-name, next, previous, up
+@subsection ѿŸ
+@cindex ѿŸ
+
+
+
+@example
+"my name is #@{$ruby@}"
+@end example
+
+֥륯(@code{"})ǰϤޤ줿ʸ󼰡ޥʸɽ
+ӥ磻ɥɼǤ@code{#{ѿ̾}}ȤѿƤ
+Ÿ뤳ȤǤ롥ѿѿ(@code{$},@code{@@})ǻϤޤ
+@code{#ѿ̾}ȤǤŸǤ롥ʸ@code{#}³ʸ
+@code{@{},@code{$},@code{@@}ǤʤСΤޤʸ@code{#}ȤƲ
+롥
+
+@node ͥƥ, ѿ, ѿŸ,
+@comment node-name, next, previous, up
+@subsection ͥƥ
+
+@table @samp
+@item 123
+
+@item -123
+(Ĥ)
+@item 1_234
+(10ʿ@code{_}ޤळȤǤ)
+@item 123.45
+@item 1.2e-3
+@item 0xffff
+16
+@item 0377
+8
+@item ?a
+ʸ@code{a}Υ(97)
+@item ?\C-a
+ȥaΥ(1)
+@item ?\M-a
+᥿aΥ(225)
+@item ?\M-\C-a
+᥿-ȥaΥ(129)
+@item :ܥ
+̻/ѿ̾/黻ҤȰабsendʤɤǥ᥽åɤꤹ
+ʤɤ˻Ȥ
+@end table
+
+?ɽǤƤΥХåå嵭ˡͭǤ롥
+
+@node ѿ, , ͥƥ,
+@comment node-name, next, previous, up
+@subsection ѿ
+
+Rubyѿϥ(ͭϰ)ȼ̿(ͭ)ˤä4ʬव졤
+μѿ̾κǽΰʸǷꤵ롥̾ѿ2ʸܰʹߤ
+ѿޤ@code{_}Ǥ뤬ƥѿΰϡ@code{$}+1ʸε
+פȤѿ롥ѿ̾Ĺ˴ؤ̤¤Ϥʤ
+
+@menu
+* Хѿ::
+* 󥹥ѿ::
+* 饹::
+* ѿ::
+* ѿ::
+@end menu
+
+@node Хѿ, 󥹥ѿ, ѿ, ѿ
+@comment node-name, next, previous, up
+@subsection Хѿ
+
+
+
+@example
+$foobar
+$/
+@end example
+
+@code{$}ǻϤޤѿΥפϥХǤꡤץΤɤ
+Ǥ⻲ȤǤ롥μ̿ϥץμ̿Хѿˤ
+ɬפʤƤʤХѿ򻲾Ȥͤ
+@code{nil}Ǥ롥
+
+@node 󥹥ѿ, 饹, Хѿ, ѿ
+@comment node-name, next, previous, up
+@subsection 󥹥ѿ
+
+
+
+@example
+@@foobar
+@end example
+
+@code{@@}ǻϤޤѿϥ󥹥ѿǤꡤΥ饹ޤϥ֥
+饹Υ᥽åɤ黲ȤǤ롥פϥ᥽åǤꡤμ̿ϥ
+֥Ȥμ̿󥹥ѿˤɬפʤ
+Ƥʤ󥹥ѿ򻲾Ȥͤ@code{nil}Ǥ롥
+
+@node 饹, ѿ, 󥹥ѿ, ѿ
+@comment node-name, next, previous, up
+@subsection 饹
+
+
+
+@example
+FOOBAR
+@end example
+
+ʸǻϤޤ뼱̻ҤؤΥǤꡤǽ줿饹
+ƤΥ֥饹ΥǻȤǤ롥
+Ƥ⥸塼򥤥󥯥롼ɤ뤳ȤˤäƹԤʤ롥ؤ
+ϥȥåץ٥롤ʤ᥽åɤǤ٥ǤΤ߲ǽǤ롥
+ϥ饹֤ͤͭ졤ͤѹ뤳ȤǤʤ
+(㳰ȯ)饹μ̿ϥ饹μ̿
+Ƥʤ饹򻲾Ȥͤ@code{nil}Ǥ롥
+
+饹ϼưŪΤǡ饹̾Ǥ롥
+
+륯饹ޤϥ⥸塼°黲Ȥ뤿ˤ
+@code{::}黻ҤѤ롥
+
+
+@example
+Foo::Bar
+@end example
+
+@code{::}黻ҤѤϤǤʤ
+
+@node ѿ, ѿ, 饹, ѿ
+@comment node-name, next, previous, up
+@subsection ѿ
+
+
+
+@example
+foobar
+@end example
+
+ʸޤ@code{_}ǻϤޤ뼱̻Ҥϥѿޤϥ᥽åɸƽФ
+롥ѿפˤ뾮ʸǻϤޤ뼱̻Ҥؤκǽ
+Υפ°ѿˤʤ롥Ƥʤ̻Ҥ
+Ȥϰ̵᥽åɸƤӽФȤߤʤ롥
+
+ѿΥפϡѿ줿ƥ졼֥å᥽
+ޤϥ饹/⥸塼֥åνޤǤǤ롥̿⤽
+Υ֥åνޤ(ȥåץ٥Υѿϥץνλޤ)
+Ǥ뤬㳰Ȥƥƥ졼֥å³֥Ȳ줿
+ϡΥ֥ȤǤޤ¸ߤ롥Ʊפ򻲾Ȥ³
+֥ȴ֤Ǥϥѿ϶ͭ롥
+
+@node ѿ, ѿ, ѿ, ѿ
+@comment node-name, next, previous, up
+@subsection ѿ
+
+̾ѿʳ˵ѿȸƤФüѿ4Ĥ롥
+
+@table @code
+@item self
+ߤΥ᥽åɤμ¹Լ
+@item nil
+Nil饹ͣΥ󥹥(ɽ)
+@item __FILE__
+ץȤΥե̾(ʸ)
+@item __LINE__
+ߤιֹ()
+@end table
+
+εѿˤäƤͤѹ뤳ȤϤǤʤ
+ѿؤ㳰ȯ롥
+
+@node , Ϣ, ѿ,
+@comment node-name, next, previous, up
+@subsection
+
+
+
+@example
+[1, 2, 3]
+@end example
+
+Array饹Υ󥹥󥹤Ǥ롥뼰ϰʲη
+롥
+
+@example
+@code{[} ,@dots{}@code{]}
+@end example
+
+줾μɾ̤ޤ֤ǿ0ζ
+뤿ˤ϶
+
+@example
+@code{[} @code{]}
+@end example
+
+Ѥ롥
+
+@node Ϣ, ᥽åɸƽм, ,
+@comment node-name, next, previous, up
+@subsection Ϣ
+
+
+
+@example
+@{1=>2, 2=>4, 3=>6@}
+@end example
+
+ϢȤǤդΥ֥Ȥ򥭡(ź)ȤƻǤ롥Ruby
+ϢHash(Ϣ)饹Υ󥹥󥹤Ǥ롥ܺ٤ϥ饹
+@code{Hash}ι򻲾Ȥ줿@xref{Hash}
+
+ϢϢ󼰤ϰʲηǤ롥
+
+@example
+@code{@{} @code{=>} @dots{}@code{@}}
+@end example
+
+줾μɾ̤򥭡ͤȤϢ󥪥֥Ȥ֤
+ǿ0Ϣ뤿ˤ϶Ϣ
+
+@example
+@code{@{} @code{@}}
+@end example
+
+Ѥ롥Ǥ1İʾ夢硤ۣǤʤ@code{@{}, @code{@}}
+άǤ롥
+
+@node ᥽åɸƽм, SUPER, Ϣ,
+@comment node-name, next, previous, up
+@subsection ᥽åɸƽм
+
+
+
+@example
+foo.bar()
+foo.bar
+bar()
+print "hello world\n"
+print
+@end example
+
+֥Ȥ˥åŪʹʸåǤꡤδ
+ܷϰʲ̤Ǥ롥
+
+@display
+1 `.' ᥽å̾ [`(' @dots{}[`*' ] `)']
+@end display
+
+1ɾ륪֥ȤΡ̻Ҥǻꤵ᥽åɤƤ
+
+᥽å̾ˤ̾μ̻Ҥ¾̻Ҥ@code{?}ޤ@code{!}³
+Τ롥ȤơҸ(֤ͤ᥽å)ˤ@code{?}
+Ʊ̾Υ᥽åɤ٤Ƥ˲ŪʺѤĥ᥽å(:@code{tr}
+@code{tr!})ˤ@code{!}Ĥ롥
+
+åǡ쥷Ф@code{self}ξ硤쥷Фά̾
+ץߥ󥰸ˤؿΤ褦ʷǥ᥽åɤƤӽФȤ
+롥
+
+@display
+᥽å̾ `(' @dots{}[`*' ]`)'
+@end display
+
+᥽åɸƤӽФΰμγ̤άǤ뤬Ȥʤ뼰
+ʸޤͽǻϤޤϡۣ롥
+
+@example
+(, [, @{, /, +, -, if, while, *
+@end example
+
+ruby1Τ褦˸ʬ򡤿ʹ֤ˤȤäƼȻפ褦
+黻Ҥζ򸫤ʤ顤㴳ʣʥ롼Dz᤹롥ͽ̤η
+̤ʤäꡤɤΤ褦ɾ뤫ʬʤϾά
+̤Ĥ
+
+
+
+@example
+foo bar+baz # ᥽åɸƤӽФfoo(bar+baz)
+foo(1+2)*5 # ᥽åɸƤӽФ(foo(1+2)) * 5
+foo (1+2)*5 # ᥽åɸƤӽФfoo((1+2) * 5)
+foo 1 # ᥽åɸƤӽФfoo(1)
+foo -1 # ᥽åɸƤӽФfoo(-1)
+foo - 1 # ѿfoo - 1
+@end example
+
+᥽åɸƤӽФǤϰ1Ĥʤˤ̤άǤ롥
+Фꤷʤ᥽åɸƤӽФξϥѿλȤȲᤵ
+롥
+
+᥽å̾ȤƤǤդμ̻ҤѤ뤳ȤǤ롥ǽʸʸ
+Ǥ⾮ʸǤ⹽ʤѿ̾Ȥϼ̻Ҥ֤̾㤦ΤǽʣƤ
+
+饹ModuleƤ᥽å(@code{public},@code{private})ǥ
+åɤθƤӽФ椹뤳Ȥ롥@code{private}ǻꤵ줿
+¤줿᥽åɤϴؿǤƤӽФȤʤ
+
+@node SUPER, ,᥽åɸƽм, Ϣ,
+@comment node-name, next, previous, up
+@subsection SUPER
+
+
+
+@example
+super
+super(1,2,3)
+@end example
+
+åüʥȤƥѡ饹Υ᥽åɤθƤӽФ
+롥ηϥ᥽åɤ˥ѡ饹Ѥ뤿
+˻Ȥ
+
+@display
+super
+@end display
+
+
+ߤΥ᥽åɤͿ줿Τޤޥѥ饹Ʊ̾Υ᥽åɤƤ
+ФȤͿ줿ѿͤѹƤ⡤ϤΤϸΰ
+ͤǤ롥
+
+@display
+super`(' @dots{}`)'
+@end display
+
+ȤȤ˥ѡ饹Ʊ̾Υ᥽åɤƤӽФֺǸΰ
+@code{*}³̾Υ᥽åɸƤӽФƱͤŸϤ롥
+
+@node , 黻Ҽ, SUPER,
+@comment node-name, next, previous, up
+@subsection
+
+
+
+@example
+foo = bar
+foo[0] = bar
+foo.bar = baz
+@end example
+
+ѿʤɤͤꤹ뤿Ѥ롥ϱ黻ҷȤ
+Ƥ뤬᥽åɤǤϤʤΤǺ뤳ȤϤǤʤդˤʤ뤳
+Τϰʲ3μǤ롥
+
+ѿ(`$'̻ | `@@'̻ | ̻)
+
+@display
+ѿ `='
+@end display
+
+ѿؤϱդμɾ줿ͤդǻꤵ줿ѿ
+롥
+
+󻲾([@dots{}])
+
+@display
+1`[' 2@dots{}`]' `=' n
+@end display
+
+󻲾ȼؤϡ1ɾ륪֥Ȥˡ2鼰n
+ޤǤȤơ@code{[]=} Ȥ᥽åɤƤӽФ
+
+°(`.'̻)
+
+@display
+1 `.' ̻ `=' 2
+@end display
+
+°(ʤΥ᥽åɸƤӽФ)ؤϡ1ɾ
+֥(쥷Фά줿@code{self})Фơ
+@code{̻=}Ȥ᥽åɤ򡤼2ȤƸƤӽФ
+
+@menu
+* ::
+* ¿::
+@end menu
+
+@node , ¿, ,
+@comment node-name, next, previous, up
+@subsubsection
+
+
+
+@example
+foo += 12
+@end example
+
+ͤΤΤ˱黻ä뤿˼롥
+
+@display
+1 op= 2 # 1ǽǤʤФʤʤ
+@end display
+
+ηŪ@code{1 = 1 op 2}Ʊͤɾ롥
+11󤷤ɾʤΤǡ1Ѥϡ
+@code{1 = 1 op 2}Ȥưۤʤ̤Ȥʤ롥
+opȤƻȤ黻Ҥ
+
+@display
+ +, -, *, /, %, **, &, |, ^, <<, >>
+@end display
+
+11Ǥ롥黻Ҥ@code{=}δ֤˥ڡƤϤʤ
+
+@node ¿, , ,
+@comment node-name, next, previous, up
+@subsubsection ¿
+
+
+
+@example
+foo, bar, baz = 1, 2, 3
+foo, = list()
+foo, *rest = list2()
+@end example
+
+ƱʣѿԤʤȤǤ롥ηϰʲ̤Ǥ롥
+
+@display
+ `,' [ `,'@dots{}] [`*' ]= [, @dots{}]
+@end display
+
+դˤ3μ롥դμĤʤϡ
+Ȥ(ɬפʤ@code{to_a}᥽åɤѴ)Ǥ
+줾캸դ롥ʳξˤϡ줾μͤդ
+롥դοȱդǤοʤˤ­ʤѿˤ
+@code{nil}졤;äǤ̵뤵롥¿κǸǤ
+@code{*}硤ĤưȤ롥
+
+
+
+@example
+foo, bar = [1, 2] # foo = 1; bar = 2
+foo, bar = 1, 2 # foo = 1; bar = 2
+foo, bar = 1 # foo = 1; bar = nil
+
+foo, bar, baz = 1, 2 # foo = 1; bar = 2; baz = nil
+foo, bar = 1, 2, 3 # foo = 1; bar = 2
+foo,*bar = 1, 2, 3 # foo = 1; bar = [2, 3]
+@end example
+
+¿ͤ(Ѵ줿)դǤ롥
+
+@node 黻Ҽ, 湽¤, ,
+@comment node-name, next, previous, up
+@subsection 黻Ҽ
+
+
+
+@example
+1+2*3/4
+@end example
+
+ץߥ󥰤ؤΤ˰Υ᥽åɸƤӽФ湽¤ϱ黻ҷ
+Ȥ롥Rubyˤϰʲˤ黻Ҥ롥ΤΤۤɷ̤
+Ʊα黻Ҥη̤ƱǤ롥
+@cindex{絬§}
+
+@display
+ ::
+ [](󻲾), []=()
+ **
+ -(unary) +(unary) ! ~
+ * / %
+ + -
+ << >>
+ &
+ | ^
+ > >= < <=
+ <=> == != =~ !~
+ &&
+ ||
+ .. ...
+ =() (+=, -=@dots{})
+ and or
+ not
+ if while
+@end display
+
+ۤȤɤα黻ˤϥ᥽åɸƤӽФȤƲᤵ(饹˺
+Ǥ)ǤʤüʤΤ롥Ǥʤü黻
+
+@display
+ =, .., ..., !, not, &&, and, |, or, if, while
+@end display
+
+γƱ黻ҤȡȤȤ߹碌ˤʤ !=, !~ Ӽ黻Ҥ
+롥
+
+Ǥü黻Ұʳα黻ҷϰʲΤ褦ʥ᥽åɸƤӽФȸ
+ʤ롥
+
+ñ黻(+, -, ~)
+
+@display
+1. 黻 ()
+@end display
+
+(Ϣޤ)Ǥλ(1 `[' 2@dots{}`]')
+
+@display
+1. `[]' (2@dots{})
+@end display
+
+Ǥ( 1 `[' 2@dots{}`]' `=' n)
+
+@display
+1. `[]=' (2@dots{}, n)
+@end display
+
+ʳ2黻(1 黻 2)
+
+@display
+1. 黻 (2)
+@end display
+
+ϤޤǤ⤽Υ᥽åɸƤӽФȤƲᤵȤ
+ǡrubyץǤҤȤ櫓ǤϤʤ
+
+@node 湽¤, 饹, 黻Ҽ,
+@comment node-name, next, previous, up
+@subsection 湽¤
+
+RubyǤ(CʤɤȤϰۤʤ)湽¤ϼǤꡤ餫ͤġ
+lispʤɤ˻ƤȤ롥RubyCPerlѤ湽¤
+ĤħŪ湽¤Ȥƥƥ졼ġƥ졼Ϸ֤Ϥ
+Ȥ桼ΤǤ.
+@xref{ƥ졼(֤)}
+
+@menu
+* IF::
+* IF::
+* CASE::
+* AND::
+* OR::
+* ϰϻ꼰::
+* NOT::
+* WHILE::
+* WHILE::
+* ƥ졼(֤)::
+* FOR::
+* YIELD::
+* FAIL::
+* BEGIN::
+* RETRY::
+* RETURN::
+* BREAK::
+* CONTINUE::
+* REDO::
+@end menu
+
+@node IF, IF, 湽¤, 湽¤
+@comment node-name, next, previous, up
+@subsubsection IF
+
+
+
+@example
+if age >= 12 then print "adult fee\n" else print "child fee\n" end
+gender = if foo.gender == "male" then "male" else "female" end
+@end example
+
+
+@display
+if 1 [then]
+ @dots{}
+[elsif 2 [then]
+ @dots{}]@dots{}
+[else
+ @dots{}]
+end
+@end display
+
+ȽǼRuby@code{if}@code{else if}Ǥ@code{elif}Ǥʤ
+@code{elsif}@code{if}Ϣ³ԤʤȤդ뤳ȡ郎Ω
+Ƽ¹Ԥ֤ͤ¹Ԥʤäͤ@code{nil}
+
+@code{if}ξȽμǤʸɽƥϼ
+@example
+$_=~ ƥ
+@end example
+ξάǤȤߤʤ롥
+
+@node IF, CASE, IF, 湽¤
+@comment node-name, next, previous, up
+@subsubsection IF
+
+
+
+@example
+print "debug\n" if $debug
+@end example
+
+
+@display
+ if
+@end display
+
+、(@code{if})μԤ뼰äɾ롥ưб
+@code{if}ƱͤǤ롥@code{if}ҤΤĤͤϾ郎Ω
+ˤϼ͡Ωξˤ@code{nil}Ǥ롥
+
+@node CASE, AND, IF, 湽¤
+@comment node-name, next, previous, up
+@subsubsection CASE
+
+
+
+@example
+case $age
+when 0 .. 2
+ "baby"
+when 3 .. 6
+ "little child"
+when 7 .. 12
+ "child"
+when 12 .. 18
+ "youth"
+else
+ "adult"
+end
+@end example
+
+
+@display
+case 0
+[when 1 [, 2]@dots{}[then]
+ @dots{}]@dots{}
+[else
+ @dots{}]
+end
+@end display
+
+ʬC@code{switch}Pascal@code{case}˻Ƥ롥
+@code{break}æФ뤳Ȥμ˷³뤳ȤʤΤա
+
+ΰפ@code{n =~ 0}ǹԤʤ롥Ĥޤꡤ
+
+@example
+case expr0
+when expr1, expr2
+ stmt1
+when expr3, expr4
+ stmt2
+else
+ stmt3
+end
+@end example
+
+ϰʲ@code{if}ȤۤǤ롥
+
+@example
+_tmp = expr0
+if expr1 =~ _tmp || expr2 =~ _tmp
+ stmt1
+elsif expr3 =~ _tmp || expr4 =~ _tmp
+ stmt2
+else
+ stmt3
+end
+@end example
+
+@node AND, OR, CASE, 湽¤
+@comment node-name, next, previous, up
+@subsubsection AND
+
+
+
+@example
+test && set
+test and set
+@end example
+
+
+@display
+1 `&&' 2
+1 `and' 2
+@end display
+
+1ɾͤ(@code{nil}ʳ)ǤС2ɾ롥
+@code{and}̤ͥ㤤̾Ǥ롥
+
+@code{and}ξդμǤʸɽƥϼ
+@code{$_ =~ ƥ} ξάǤȤߤʤ롥
+
+@node OR, ϰϻ꼰, AND, 湽¤
+@comment node-name, next, previous, up
+@subsubsection OR
+
+
+
+@example
+demo || die
+demo or die
+@end example
+
+
+@display
+1 `||' 2
+1 'or 2
+@end display
+
+1ɾͤǤС2ɾ롥@code{or}̤ͥ
+㤤̾Ǥ롥
+
+@code{or}ξդμǤʸɽƥϼ
+@code{$_ =~ ƥ}ξά
+ǤȤߤʤ롥
+
+@node ϰϻ꼰, NOT, OR, 湽¤
+@comment node-name, next, previous, up
+@subsubsection ϰϻ꼰
+
+
+
+@example
+1 .. 20
+/first/ ... /second/
+@end example
+
+
+@display
+1 `..' 2
+1 `...' 2
+@end display
+
+PʳξǤϼ1鼰2ޤǤϰϥ֥Ȥ֤
+
+PȤϰϻ꼰Ѥ줿ϡ1ˤʤޤǤϵ֤
+θϼ2֤ޤǤϿ֤2ˤʤо֤ϵ롥
+@code{..}ϼ1ˤʤä˼2ɾ(awkΤ褦)@code{...}ϼ
+ɾޤǼ2ɾʤ(sedΤ褦)
+
+Pϰϻ꼰ξդȤʤ뼰Ǥϡʸɽƥϼ
+@code{$_ =~ ƥ}ξά@code{$. == }ξάȲᤵ
+롥
+
+@node NOT, WHILE, ϰϻ꼰, 湽¤
+@comment node-name, next, previous, up
+@subsubsection NOT
+
+
+
+@example
+! me
+not me
+i != you
+@end example
+
+
+@display
+`!'
+not
+@end display
+
+ǤеǤп֤
+
+@code{!}Ǥʸɽƥϼ@code{$_ =~ ƥ}ξά
+ǤȤߤʤ롥
+
+@display
+1 `!=' 2
+@end display
+
+@code{!(1 == 2)}ξά
+
+@display
+1 `!~' 2
+@end display
+
+@code{!(1 ~= 2)}ξά
+
+@node WHILE, WHILE, NOT, 湽¤
+@comment node-name, next, previous, up
+@subsubsection WHILE
+
+
+
+@example
+while sunshine()
+ work()
+end
+@end example
+
+
+@display
+while
+ @dots{}
+end
+@end display
+
+ɾͤδ֡Τ򷫤֤¹Ԥ롥@code{while}ͤ
+@code{nil}Ǥ롥
+
+whileξȽμǤʸɽƥϼ
+@code{$_ =~ ƥ} ξάǤȤߤʤ롥
+
+@node WHILE, ƥ졼(֤), WHILE, 湽¤
+@comment node-name, next, previous, up
+@subsubsection WHILE
+
+
+
+@example
+sleep while idle
+@end example
+
+
+@display
+ñ㼰 while
+@end display
+
+μɾͤδ֡ñ㼰򷫤֤¹Ԥ롥ñ㼰
+@code{begin}ǤϤޤ@code{begin}ɾƤPɾ
+(٤begin¹Ԥ)@code{while}ҤΤĤͤ
+@code{nil}Ǥ롥
+
+@node ƥ졼(֤), FOR, WHILE, 湽¤
+@comment node-name, next, previous, up
+@subsubsection ƥ졼(֤)
+
+
+
+@example
+[1,2,3].each@{|i| print i*2, "\n"@}
+@end example
+
+ƥ졼Ȥ湽¤(ä˥롼)ݲΤѤ᥽åɤ
+Ǥ롥ɤ(֥åȸƤФ)ꤷƥƥ졼Ƥ
+Фȡƥ졼Ŭͤ򥻥åȤƥ֥åɾ(餯
+ʣ)ƥ졼Υ֥åθƤӽФ@code{yield}Ѥ(
+)
+
+ƥ졼θƤӽФϰʲιʸǹԤʤ롥
+
+@display
+ `@{' [`|' ռ@dots{}`|'] @dots{}`@}'
+@end display
+
+ּפ֥åȤꤷּפΥ᥽åɤ򥤥ƥ졼Ȥɾ
+롥ּפΥȥåץ٥Υ᥽åɤƥ졼ȤƸƤӽФ졤
+쥷Фɽ䡤μϥƥ졼ȤƤϸƤӽФʤּ
+ʣμޤơƥ졼Ȥƽ˸ƤФ롥
+
+ƥ졼@code{yield}¹Ԥȡǻꤵ줿ͤռ
+ǻꤵ줿ѿ졤֥å¹Ԥ롥֥åμ¹Ԥλ
+Ȥͤ @code{yield}ͤȤ֤롥᥽åɤƥ졼
+ȤƸƤӽФ줿ɤϥ᥽å@code{iterator?}ͤΤ뤳
+ȤǤ롥ˤ@code{Enumerable:grep}᥽åɤΤ褦˥ƥ졼Ȥ
+ƸƤФ줿̤Υ᥽åɤȤƸƤФ줿Ȥưۤʤ᥽åɤ
+롥
+
+@node FOR, YIELD, ƥ졼(֤), 湽¤
+@comment node-name, next, previous, up
+@subsubsection FOR
+
+
+
+@example
+for i in [1, 2, 3]
+ print i*2, "\n"
+end
+@end example
+
+֥ȤγǤФԤʤη󶡤Ƥ롥
+ϰʲ̤ꡥ
+
+@display
+for ռ@dots{} in
+
+end
+@end display
+
+γǤФ¹Ԥ롥ϰʲμȤۤǤ롥֤ۤܡ
+ȤΤϡƥ졼֥åϿѿͭϰϤƳ
+ΤФ@code{for}ʸϥѿΥפ˱ƶڤܤʤ
+ʤ뤫Ǥ
+
+@display
+().each `@{' `|' ռ@dots{}`|' `@}'
+@end display
+
+äƼͤΥ֥Ȥ᥽å@code{each}ʤ硤
+@code{for}¹Ԥ㳰ȯ롥
+
+@node YIELD, FAIL, FOR, 湽¤
+@comment node-name, next, previous, up
+@subsubsection YIELD
+
+
+
+@example
+yield data
+@end example
+
+
+@display
+yield `(' [ [`,' @dots{}]])
+@end display
+
+ƥ졼ǥ֥åθƤӽФԤʤ@code{yield}¹Ԥ᥽
+ɤƥ졼ȤƸƤӽФƤʤˤ㳰ȯ롥
+@code{yield} ͤϥ֥åͤǤ롥
+
+@code{yield}ΰγ̤ۣǤʤ¤άǤ롥
+
+@node FAIL, BEGIN, YIELD, 湽¤
+@comment node-name, next, previous, up
+@subsubsection FAIL
+
+
+
+@example
+fail
+fail "you lose"
+@end example
+
+
+@display
+fail `(' [å] `)'
+@end display
+
+㳰ȯ롥åͿ줿ˤȯե
+ֹ̾򥷥ƥѿ@code{$@@}ˡå@code{$!}˥åȤ롥
+
+@code{fail}ΰγ̤ϾάǤ롥
+
+@node BEGIN, RETRY, FAIL, 湽¤
+@comment node-name, next, previous, up
+@subsubsection BEGIN
+
+
+
+@example
+begin
+ do_something()
+rescue
+ recover()
+ensure
+ must_to_do()
+end
+@end example
+
+ʣμޤȤ뤿㳰Τ@code{begin}롥
+@code{begin}ηϰʲ̤Ǥ롥
+
+@display
+begin
+ @dots{}
+[rescue
+ @dots{}]
+[ensure
+ @dots{}]
+end
+@end display
+
+@code{begin}ͤϰֺǸɾ줿ͤǤ롥@code{begin}
+ȯ㳰@code{rescue}ͤ뤳Ȥ롥
+@code{begin}ͤϤ@code{rescue}ǺǸɾͤ
+롥@code{ensure}᤬¸ߤ@code{begin}λɬ
+(ェλǤʤ㳰, @code{return}, @code{break},
+@code{continue}, @code{redo}ʤɤˤæФǤ)@code{ensure}μɾ
+롥
+
+@node RETRY, RETURN, BEGIN, 湽¤
+@comment node-name, next, previous, up
+@subsubsection RETRY
+
+
+
+@example
+retry
+@end example
+
+
+@display
+retry
+@end display
+
+Ƽ¹ԡ@code{begin}@code{rescue}ǻȤ줿硤@code{begin}
+Ϥᤫ⤦ټ¹Ԥ롥㳰ԤʤäƤƻԤΤ˻Ȥ
+
+@example
+begin
+ 餫ν(㳰ȯ)
+rescue
+ 㳰
+ retry # 㳰бƺƼ¹
+end
+@end example
+
+ƥ졼ƥ졼֥åޤforʸǻȤ줿ˤϡ
+ƥ졼ɾΤǽ餫¹Ԥ롥ƥ졼ΰɾ롥
+
+@example
+for i in 1..5
+ retry if some_condition # i == 1 ľ
+end
+@end example
+
+@example
+# 桼until loop
+def until(cond)
+ yield
+ retry if not cond
+end
+@end example
+
+@code{rescue}䥤ƥ졼ʳretryѤ줿㳰ȯ롥
+
+@node RETURN, BREAK, RETRY, 湽¤
+@comment node-name, next, previous, up
+@subsubsection RETURN
+
+
+
+@example
+return
+return 12
+return 1,2,3
+@end example
+
+
+@display
+return [[`,' @dots{}]]
+@end display
+
+ͤͤȤƥ᥽åɤμ¹Ԥλ롥2İʾͿ줿
+ˤϡǤȤ᥽åɤͤȤ롥Ĥʤ
+ˤ @code{nil} ͤȤʤ롥
+
+@node BREAK, CONTINUE, RETURN, 湽¤
+@comment node-name, next, previous, up
+@subsubsection BREAK
+
+
+
+@example
+break
+@end example
+
+
+@display
+break
+@end display
+
+@code{break} ϥ롼פæФ롥CȰ㤤@code{break}ϤäȤ¦
+롼פæФѤ@code{case} ȴѤϻʤ
+
+@node CONTINUE, REDO, BREAK, 湽¤
+@comment node-name, next, previous, up
+@subsubsection CONTINUE
+
+
+
+@example
+continue
+@end example
+
+
+@display
+continue
+@end display
+
+@code{continue}ϤäȤ¦Υ롼פμη֤Ϥ롥
+
+@node REDO, 湽¤, CONTINUE, 湽¤
+@comment node-name, next, previous, up
+@subsubsection REDO
+
+
+
+@example
+redo
+@end example
+
+
+@display
+redo
+@end display
+
+@findex redo
+@code{redo}ϥ롼׾ΥåԤʤ鷺ߤη֤ľ
+
+@node 饹, ⥸塼, 湽¤,
+@comment node-name, next, previous, up
+@subsection 饹
+@cindex 饹
+
+
+
+@example
+class Foo:Super
+ def test
+ :
+ end
+ :
+end
+@end example
+
+
+@display
+class 饹̾ [`:' ѡ饹̾ ]
+
+end
+@end display
+
+@findex class
+饹̾ʸǻϤޤ뼱̻ҤǤ롥
+
+@node ⥸塼, ᥽å, 饹,
+@comment node-name, next, previous, up
+@subsection ⥸塼
+@cindex ⥸塼
+
+
+
+@example
+module Foo
+ def test
+ :
+ end
+ :
+end
+@end example
+
+
+@display
+module 饹̾
+
+end
+@end display
+
+@findex module
+⥸塼̾ʸǻϤޤ뼱̻ҤǤ롥
+
+@node ᥽å, ðۥ᥽å, ⥸塼,
+@comment node-name, next, previous, up
+@subsection ᥽å
+@cindex ᥽åɤ
+
+
+
+@example
+def fact(n)
+ if n == 1 then
+ 1
+ else
+ n * fact(n-1)
+ end
+end
+@end example
+
+
+@display
+def ᥽å̾ [`(' [ [= ǥե]]@dots{}[`,' `*' ]`)']
+
+end
+@end display
+@findex def
+
+˥ǥեȼͿ줿硤᥽åɸƤӽФ˰Ϳ
+ʤäˤϥǥեȼɾ̤ǽ(ǥեȼ
+ɾϸƤӽФ˹Ԥ)ֺǸΰ@code{*}³(ñ)
+Ǥ硤μɾ(ǤʤѴ)Ÿơ
+Ȥɲä롥
+
+̾᥽åϥͥȤǤʤΤǡ᥽åǤϥ᥽å
+ƤӸƤӽФʤ
+
+᥽å̾ϼ̻ҤޤʸǤ롥黻Ҥκ򤹤ˤʸ
+ǻꤹ롥¤ӤκǸ@code{*}硤¿Ϳ
+줿°ϡǸΰȤͿ(­ʤˤϥ顼)
+
+᥽åɤˤϸƤӽФ¤ä뤳ȤǤ¤ä줿᥽åɤϡ
+ؿǤƤӽФʤ(private᥽å)
+
+˥᥽åɤ硤饹γˤdefϥǥե
+Ǥprivate᥽åɤ饹ˤdefpublic᥽
+ɤ롥ѡ饹Υ᥽åɤˤ
+åɤβĻϥѡ饹Υ᥽åɤΤΤѤ
+
+᥽åɤβĻѹˤ@code{Module}饹Ƥ
+@code{public}, @code{private}γƥ᥽åɤѤ롥
+
+@node ðۥ᥽å, ALIAS, ᥽å,
+@comment node-name, next, previous, up
+@subsection ðۥ᥽å
+
+
+
+@example
+def foo.test()
+ print "this is foo\n"
+end
+@end example
+
+
+@display
+def `.' ᥽å̾ [`(' [ [= ǥե]]@dots{}[`,' `*' ]`)']
+
+end
+@end display
+
+ðۥ᥽åɤȤϤΥ֥Ȥ˸ͭΥ᥽åɤǤ롥
+
+ηϼͤǤ륪֥Ȥðۥ᥽åɤ롥ͤ
+(ӥȥ󥯥饹Ǥʤ)̾索֥Ȥ饹ޤϥ⥸塼Ǥ
+ɬפ롥̾᥽åȤϰۤʤꡤðۥ᥽åɤϥ᥽å
+ǤͥȤ뤳ȤǤ롥
+
+ðۥ᥽åɤ̾ϷѾʤ㳰Ȥƥ饹ðۥ᥽åɤϤ
+֥饹ˤѾ롥ؤХ饹ðۥ᥽åɤ¾Υ֥
+Ȼظƥˤ륯饹᥽åɤƯ򤹤롥
+
+: 󥯥롼ɤ⥸塼ðۥ᥽åɤϷѾʤ
+
+@node ALIAS, UNDEF, ðۥ᥽å,
+@comment node-name, next, previous, up
+@subsection ALIAS
+@cindex ᥽åɤ̾Ĥ
+
+
+
+@example
+alias foo bar
+@end example
+
+
+@display
+alias ᥽å̾1 ᥽å̾2
+@end display
+
+@findex alias
+@code{alias}ʸǥ᥽åɤ̾Ĥ뤳ȤǤ롥̾դ줿
+åɤϡλǤΥ᥽åѤΥ᥽åɤ
+Ƥ⡤θŤ᥽åɤƤӽФ줿ΤƱƯ򤹤롥
+
+@node UNDEF, DEFINED?, ALIAS,
+@comment node-name, next, previous, up
+@subsection UNDEF
+@cindex ᥽åɤä
+
+
+
+@example
+undef bar
+@end example
+
+
+@display
+undef ᥽å̾
+@end display
+
+@findex undef
+᥽åɤäˤundefѤ롥
+
+defˤ̾@code{undef}ˤäˤäƥ饹Υ
+ե򥹡ѡ饹Ωѹ뤳ȤǤ롥᥽
+ɤself˥åäƤ⤢Τǡ褯դʤȴ¸
+᥽åɤưʤʤǽ롥
+
+@node DEFINED?, , UNDEF,
+@comment node-name, next, previous, up
+@subsection DEFINED?
+@cindex ᥽åɤƤ뤫ɤ
+@cindex ѿƤ뤫ɤ
+@cindex Ƥ뤫ɤ
+
+
+
+@example
+defined? print
+defined? File.print
+defined?(foobar)
+defined?($foobar)
+defined?(@@foobar)
+defined?(Foobar)
+@end example
+
+
+@display
+defined?
+@end display
+
+@findex defined?
+᥽åɸƤӽФξ硤Υ᥽åɤƤ˿֤
+ѿλȤǤϡѿƤ
+˿֤ʳμξϼɾơ㳰ȯʤп
+
+@node Ȥ߹ߴؿ, Ȥ߹ѿ, rubyʸˡ, Top
+@comment node-name, next, previous, up
+@chapter Ȥ߹ߴؿ
+
+Rubyˤϸ̩ʰ̣ǤϴؿϤʤ@code{Kernel}饹δؿ᥽åɤ
+(Ƥ̾說饹ؿǸƤӽФΤ)ؿŪѤ롥
+ŪѤ᥽åɤʲˤ롥Υ᥽åɤ
+ˤϸߴͤƹԤʤ٤Ǥ롥
+
+@ftable @code
+@item autoload(@var{module}, @var{file})
+
+@var{module}˺ǽ˥@var{file}@code{require}褦
+ꤹ롥@var{module}ʸޤϥܥǻꤹ롥
+
+@item caller([@var{level}])
+
+@var{level}ʾθƽФξ@code{$@@}η롥ȥåץ٥
+Ǥ@code{nil}֤callerͤ@code{$@@}뤳Ȥ㳰
+ȯ֤Ǥ롥ޤʲΤ褦ʥɤǸƽФطΥХåȥ졼
+ɽǤ롥
+
+@example
+n = 0
+while c = caller(n)
+ print c, "\n"
+end
+@end example
+
+@item eof
+@itemx eof?
+
+ޥɥ饤󤫤Ϥ@code{EOF}ãƤ硤֤
+
+@item eval(@var{expr})
+
+@var{expr}ȤͿ줿ʸrubyץȤƲᡤ¹Ԥ롥
+
+@item exec(@var{command})
+
+ץμ¹Ԥλ롥@var{status}ȤͿ줿硤
+ͤrubyޥɤνλơȤ롥ǥեȤ0
+
+@item exit!(@var{status})
+
+ץμ¹Ԥλ롥@var{status}λơȤ롥
+@code{exit}Ȥϰäơ㳰ʤɤϰڹԤʤʤ@code{fork}θ塤
+ҥץλʤɤѤ롥
+
+@item fork
+
+@samp{fork}ƥॳ¹Ԥҥץ롥ܺ٤
+@samp{fork(2)}򻲾ȤΤȡƥץ¦ǤϻҥץΥץid
+ҥץ¦Ǥ@code{nil}֤餫θǻҥץ
+Ԥˤ㳰ȯ롥ƥ졼ȤƸƤФ줿ϡ
+ץͿ줿֥åɾ֥åɾλǻ
+ץェλ롥
+
+@item format(@var{format}@dots{})
+
+եޥåȤȤͿ줿ʸC@samp{sprintf}Ʊ褦
+ᤷŸʸ֤᥽å@code{sprintf}̾
+
+Rubyˤ@samp{format}ҤγĥˤĤƤ@code{sprintf}ι
+ȤΤȡ
+
+@item getc
+
+ɸϤʸФͤɤ߹ʸʸ(ASCII)
+ɽ@code{Fixnum}Ǥ롥
+
+@item gets
+
+ȤͿ줿ե(ʤɸ)ǹ벾
+Ūʥե(ƥѿ@code{$<}ǥǤ)ɤ߹
+ǡɤ߹ߤˤϤʸ֤եν
+ãˤ@code{nil}֤Ԥζڤϥƥѿ@code{$/}ˤä
+ѹǤ롥ɤ߹ʸϥƥѿ@code{$_}ˤ⥻åȤ롥
+
+@item gsub(@var{pattern}[, @var{replace}])
+@itemx gsub!(@var{pattern}[, @var{replace}])
+
+ƥѿ@code{$_}λؤʸ @var{pattern}˥ޥåʬ
+@var{replace}֤롥@code{String}饹@code{gsub}᥽
+ɤβ򻲾ȤΤȡ@var{replace}ά줿ˤϥƥ졼
+ư֥åɾִ̤롥@code{gsub}᥽åɤ
+@code{$_}ͤ򥳥ԡơԡ򹹿@code{$_}롥
+
+@code{gsub!}@code{$_}λؤƤʸ󤽤ΤΤ񤭴롥
+
+@item iterator?
+
+᥽åɤƥ졼ȤƸƤӽФ줿ˤϿǤʤ˵֤
+Ҹ졥
+
+@item kill(@var{signal}, @var{pid}@dots{})
+
+@var{pid}ǻꤵ줿ץ˥ʥ롥@var{signal}ϥʥ
+ֹ椫̾ǻꤹ롥ͤĥʥ(뤤ϥʥ̾
+@code{-})ͿȥץǤϤʤץ롼פ˥ʥ롥
+
+@item load(@var{file})
+
+@var{file}ɤ롥@var{file}ɤѥϥƥѿ
+@code{$:}Ƿꤵ롥
+
+@item loop
+
+̵¥롼פ륤ƥ졼(Ǥʤ¤)ʵפ˥ƥ졼֥å
+ɾ³롥
+
+@item open(@var{file}[, @var{mode}])
+
+@var{file}򥪡ץ󤷤ơ@code{File}֥Ȥ֤ե̾
+ץ󤹤ե򼨤ե̾@code{|}ǻϤޤˤ³ʸ
+򥳥ޥɤȤƵưѥץ饤롥
+
+ޥ̾@samp{"-"}Ǥ@code{open}rubyλҥץ
+λҥץȤΥѥפ֤
+
+@var{mode}ϥեΥ⡼ɤꤹ롥ϰʲΤΤ
+줫ʸǤ롥
+
+@table @samp
+@item r
+ɤ߹ѡ@code{open}եϤ餫¸ߤƤɬפ
+롥
+
+@item r+
+ɤ߽ξѡ@code{open}եϤ餫¸ߤƤɬפ
+롥
+
+@item w
+񤭹ѡե뤬¸ߤƤ硤Ĺ0ˤ롥¸ߤƤ
+п˥ե롥
+
+@item w+
+ɤ߽ξѡɤ߹ߤԤʤ뤳Ȱʳ@samp{"w"}ƱƯ򤹤롥
+
+@item a
+ɲý񤭹ѡեϤ餫¸ߤƤɬפ롥񤭹
+ϥեκǸɲä롥
+
+@item a+
+ɤ߽ξѡե뤬¸ߤƤʤп˺롥
+ϥեκǸ˽롥
+@end table
+
+⡼ɤά줿ΥǥեȤ@samp{"r"}Ǥ롥
+
+@item print(@var{arg}1@dots{})
+
+˽Ϥ롥Ϳʤˤ@code{$_}ͤϤ롥
+ʸʳΥ֥ȤȤͿ줿ˤϡ֥
+Ȥ@code{to_s}᥽åɤˤäʸѴƤϤ롥
+ѿ@code{$;}(ϥեɥѥ졼)@code{nil}Ǥʤͤå
+Ƥˤϡưδ֤ˤʸϤ롥ƥѿ
+@code{$\}(ϥեɥѥ졼)@code{nil}ǤʤͤåȤƤ
+ˤϡǸˤϤ롥
+
+@item printf([@var{port}, ]@var{format}, @var{arg}@dots{})
+
+CprintfƱ褦@var{format}˽ʸѴ
+롥1IOΥ֥饹Υ󥹥󥹤ǤäϤΥ֥
+ȤФƽϤԤʤǥեȤ@code{$stdout}˽Ϥ롥
+
+RubyˤformatҤγĥˤĤƤsprintfι򻲾ȤΤȡ
+
+@item proc
+@itemx lambda
+
+Ϳ줿ƥ졼֥å³֥(饹@code{Proc}Υ
+󥹥)Ȥ֤
+
+@item rand(@var{max})
+
+0@var{max}ۤʤϰϤȯ롥ͤ
+@code{Fixnum}
+
+@item require(@var{feature})
+
+@var{feature}ǻꤵfileɤ롥@var{feature}ϥɤե
+ꤹʸǡĥ@code{.rb}ꤵƤruby
+ץȡĥ@code{.o}ꤵƤϡХʥ⥸塼
+롥ĤΥƥǤϥХʥ⥸塼Υɤ
+󶡤ʤХʥ⥸塼μºݤΥեγĥҤϥƥ
+˰ۤʤ뤬@var{feature}̾γĥҤϤĤ@code{.o}Ѥ롥
+
+ĥҤꤵʤϡޤ@code{.rb}@code{.o}äơե
+򸡺롥
+
+requireϼºݤ˥ɤˤ @code{TRUE}˥ɤƤ
+@code{FALSE}֤ޤɤ@var{feature}̾(ĥҤޤ
+)ѿ@code{$"}ɲä롥
+
+@item select(@var{reads}[, @var{writes}[, @var{execpts}[, @var{timeout}]]])
+
+@samp{select(2)}¹Ԥ롥@var{reads}/@var{writes}/@var{execpts}ˤ
+IO(ޤϤΥ֥饹)Υ󥹥󥹤Ϳ롥@var{timeout}
+Fixnum/Float/TimeΤ줫ǻꤹ롥ͤ@var{timeout}Ω
+ˤ@code{nil}ǤʤȤ3Ǥ֤γǤ
+//㳰ԤΥ֥ȤǤ(ꤷΥ֥åȡ
+Ԥ֥Ȥꤷʤä@code{nil})ƥॳ
+¹˳ߤäˤϳ϶ˤʤ롥
+
+@item sleep([@var{sec}])
+
+@var{sec}äץμ¹Ԥߤ롥@var{sec}ά줿硤
+ץ@code{SIGALRM}ʤ¤ꡤʵפ˥꡼פ롥ºݤ˥
+꡼פÿ֤
+
+@item sprintf(@var{format}@dots{})
+
+@var{format}ʸC@samp{sprintf}Ʊ褦˲ᤷŸ
+ʸ֤᥽å@code{format}̾
+
+@var{format}ҤC@samp{sprintf}()դ(
+Rubyˤ unsignedʤΤǡ%uϽ)˲ä, %b, %B, %O, %XȤ
+ȤǤ롥%bϿͤ2ɽ%B, %O, %XϤ줾2ʡ8ʡ16ʿ
+ɽԤʤονκݤ2ɽǤϤʤɽ
+Ƭ@code{-}ĤΤɽ롥
+
+@item srand([@var{seed}])
+
+@var{seed}ꤷŤ֤ͤͤά줿ˤ
+@samp{time(3)}֤ͤǥեȤȤ롥
+
+@item sub(@var{pattern}[, @var{replace}])
+@itemx sub!(@var{pattern}[, @var{replace}])
+
+ƥѿ@code{$_}λؤʸǺǽ@var{pattern}˥ޥåʬ
+@var{replace}֤롥@var{replace} ά줿ˤϥ
+졼Ȥư֥åɾִ̤롥sub᥽åɤ
+@code{$_}ͤ򥳥ԡơԡ򹹿@code{$_}롥
+¾ξܺ٤˴ؤƤ@code{String}饹@code{sub}᥽åɤβ
+ȤΤȡ
+
+@code{sub!}@code{$_}λؤƤʸ󤽤ΤΤ񤭴롥
+
+@item syscall(@var{num}, @var{arg}@dots{})
+
+@var{num}ǻꤵ줿ֹΥƥॳ¹Ԥ롥2ʹߤ򥷥
+ƥॳΰȤϤʸޤǤʤФʤʤ
+
+@item system(@var{command})
+
+@var{command}¹Ԥ(֥ץstatus 0ǽλ)
+ˤϿ򡤼Ԥˤϵ֤λơѿ@code{$?} ǻ
+ȤǤ롥
+
+@item test(@var{cmd}, @var{file} [, @var{file}])
+
+եƥȤԤ@var{cmd}ϰʲ˼ʸƥǤ롥ե
+̾Ȥ@code{"&"}ꤹȡľΥեؤ@samp{stat(2)}η
+̤Ѥ롥
+
+
+1Ĥΰ
+
+@display
+?r ե¸ uid ɤळȤǤ
+?w ե˼¸ uid ǽ񤯤ȤǤ
+?x ե¸ uid Ǽ¹Ԥ뤳ȤǤ
+?o եνͭԤ¸ uid Ǥ
+
+?R ե uid ɤळȤǤ
+?W ե˼ uid ǽ񤯤ȤǤ
+?X ե uid Ǽ¹Ԥ뤳ȤǤ
+?O եνͭԤ uid Ǥ
+
+?e ե뤬¸ߤ
+
+?z ե륵 0 Ǥ
+?s ե륵 0 Ǥʤ(ե륵֤)
+
+?f եϥץ졼եǤ
+?d եϥǥ쥯ȥǤ
+?l եϥܥå󥯤Ǥ
+?p ե̾Ĥѥ(FIFO)Ǥ
+?S եϥåȤǤ
+?b եϥ֥åüեǤ
+?c եϥ饯üեǤ
+
+?u ե setuid ӥåȤåȤƤ
+?g ե setgid ӥåȤåȤƤ
+?k ե sticky ӥåȤåȤƤ
+
+?M ץȤμ¹Ԥ򳫻ϤǤΥեθŤ
+?A ץȤμ¹Ԥ򳫻ϤǤΥեΥ
+?C ץȤμ¹Ԥ򳫻ϤǤΥե inode ѹ
+@end display
+
+2Ĥΰ
+
+@display
+?= ե1ȥե2Υॹפ
+?> ե1ե2깹֤
+?< ե1ե2깹֤Ť
+?- ե1ե2˥ϡɥ󥯤Ƥ
+@end display
+
+@item trace_var(@var{var}, @var{command})
+
+@var{var}ǻꤵ줿ѿͤѹ줿ɾ
+@var{command}ꤹ롥@var{command}ʸ󡤤ޤϥ֥åǻꤹ
+롥trace뤿ˤ@code{untrace_var}Ѥ롥
+
+@item trap(@var{signal}, @var{command})
+@itemx trap(@var{signal}) @{@dots{}@}
+
+@var{signal}γߤä@var{command}¹Ԥ롥
+@var{signal}ϥʥ̾ʥֹ桥@var{command}ʸ󡤤ޤ
+ϥ֥åǻꤹ롥commandȤ@samp{"SIG_IGN"}ޤ
+@samp{"IGNORE"}ꤷˤϤΥʥ̵뤹(ǽʤ)
+@samp{"SIG_DFL"}ޤ@samp{"DEFAULT"}ꤷϥǥեȤư
+Ԥʤ@samp{"EXIT"}ꤷϥʥ(λԤ
+)exit status 1ǽλ롥
+
+@item untrace_var(@var{var})
+
+@var{var}ФƤtrace롥traceȤƻꤵƤ륪
+Ȥˤ֤
+
+@item wait
+
+ҥץλΤԤλҥץpid֤ҥץ
+Ĥʤ@code{nil}֤
+
+@item waitpid(@var{pid}, @var{flags})
+
+@var{pid}ǻꤵλҥץνλԤΥץλ
+˿֤ҥץ¸ߤʤΥ֥å󥰥⡼ɤǻ
+ץޤλƤʤˤ@code{nil}֤@samp{waitpid(2)}
+@samp{wait4(2)}μƤʤޥǤ@var{flags}ϤĤ@code{nil}ޤ
+0ǤʤФʤʤ
+@end ftable
+
+@node Ȥ߹ѿ, Ȥ߹ߥ饹ȥ⥸塼, Ȥ߹ߴؿ, Top
+@comment node-name, next, previous, up
+@chapter Ȥ߹ѿ
+@cindex{ȹѿ}
+
+@table @samp
+
+@item $!
+顼åfailꤹ롥
+
+@item $@@
+顼ȯΥե̾ȹֹ椬
+@example
+"ե:ֹ[:᥽å̾()]"
+@end display
+ηdzǼ롥
+
+@item $&
+Ǹѥޥå
+
+@item $`
+ǸΥѥޥåǥޥåʸʸ
+
+@item $'
+ǸΥѥޥåǥޥåʸθ³ʸ
+
+@item $+
+ǸθѥǥޥåǸγ
+
+@item $1@dots{}$9
+Ǹѥޥånܤγ̤˥ޥåͤǼ롥
+̤ʤ@code{nil}äƤ롥
+
+@item $~
+ǸΥޥå˴ؤ󡥤򥻥åȤ@code{$&}
+@samp{$1@dots{}$9}ͤѲ롥
+
+@item $=
+ѿͤ@code{nil}ǤʤѥޥåʸӤǥե٥
+Ȥʸʸ̤ʤǥեȤ@code{nil}(̤)
+
+@item $/
+ϥ쥳ɥѥ졼եʸФ@code{each}Ԥʤ
+ʬʸꤹ롥$/˶ʸ(@code{""})ꤹñ̤
+ϤԤʤ@code{nil}ꤹΤ٤ɤ߹ࡥ@code{$/}ˤ
+ɽϻȤʤǥեȤ@samp{"\n"}
+
+@item $\
+ϥ쥳ɥѥ졼ѿʸꤹ@code{write}
+@code{print}٤˺ǸˤʸղäƽϤ롥ǥեȤ
+@code{nil} (ʤˤɲäʤ)
+
+@item $,
+@code{Array:join}ΥǥեȤζڤʸ@code{print}γưδ
+˽Ϥʸ
+
+@item $;
+@code{String:split}ΥǥեȤζڤʸ
+
+@item $.
+Ǹɤϥեιֹ桥
+
+@item $<
+(ʤɸ)ǹ벾ۥե롥Ĥޤ@code{gets}
+@code{$<.gets}Ʊ̣Ǥ롥@code{$<.file}Ǹɤ߹Υե
+륪֥Ȥ@code{$<.filename}ǤΥե̾롥(Ф
+: @code{<}ϥϸ)
+
+@item $>
+@code{print}@code{printf}ΥǥեȤν补ͤ
+@code{$stdout}@samp{-i}ץꤷˤɤ߹߸Ʊ
+̾Υե롥(Ф: @code{>}ϥν)
+
+@item $_
+Ǹ@code{gets}ʤɤɤ߹ʸ
+
+@item $0
+rubyץȤ̾ѿ@samp{ps(1)}νϤѲ롥
+
+@item $*
+rubyץȤͿ줿rubyȤФϼƤ롥
+
+@item $$
+߼¹rubyץpid
+
+@item $?
+Ǹ˼¹Ԥҥץstatus
+
+@item $:
+եɤ˸ǥ쥯ȥؤΥѥޤ󡥵ư
+ˤϥǥե(ѥ˻ꤹ)˲äơĶѿ
+@var{RUBYLIB}ͤrubyư@samp{-I}ץǻꤵ줿ͤɲ
+롥(Ф: ϴĶѿ@var{PATH}ζڤʸǤ)
+
+@item $"
+@code{require}ǥɤ줿ե̾ޤ@code{require}Ʊ
+ե2ɤʤѤ롥(Ф: prevent files to
+be doubly quoted(loaded))
+
+@item $ARGF
+@code{$<}̾
+
+@item $ARGV
+@code{$*}̾
+
+@item $DEBUG
+@code{-d}ե饰ξ()
+
+@item $FILENAME
+ۥե@code{$<}Ǹɤ߹(᥽ågetsɤǤ)ե
+̾@code{$<.filename}Ʊ
+
+@item $KCODE
+߽оݤȤƤɤɽʸ@samp{"EUC"}
+@samp{"SJIS"}ޤ@samp{"NONE"}ѿͤѹɽΥޥ
+ľɽκƥѥ뤬Ԥ롥
+
+@item $LOAD_PATH
+@code{$:}̾
+
+@item $stdin
+
+@item $stdout
+
+@item $stderr
+ɸ२顼
+
+@item $VERBOSE
+@code{-v}ե饰ξ()
+
+@item TRUE
+@itemx FALSE
+줾쿿ͤɽ(@code{TRUE}ͤt@code{FALSE}ͤ@code{nil})
+ȽǤ@code{nil}򵶡ʳƤͤ򿿤ȤȽǤ뤿ᡤ
+@code{TRUE}ͤɽŪʿͤȤʾΰ̣ʤäơ
+᥽åɤͤǤȤȤȡ줬@code{TRUE}֤Ȥ
+Ȥϸ̩ˤƱǤϤʤ(ҸŪѤ᥽åɤ񿿤ͤȤ
+@code{TRUE}֤褦ˤϤʤäƤ뤬)Ĥޤ
+
+@example
+if some.method() then @dots{} else @dots{} end
+@end example
+
+
+
+@example
+if some.method() == TRUE then @dots{} else @dots{} end
+@end example
+
+ϴˤƱǤϤʤ@code{FALSE}˴ؤƤϡΤ褦
+
+@item STDIN
+ɸ($stdinν)
+@item STDOUT
+ɸ($stdoutν)
+@item STDERR
+ɸ२顼($stderrν)
+
+@item ENV
+Ķѿ˥Ϣʸ򥭡ȤͿбĶ
+ѿͤ롥Ķѿ¸ߤʤ@code{nil}֤롥
+
+@item VERSION
+rubyΥС򼨤ʸ
+@end table
+
+@node Ȥ߹ߥ饹ȥ⥸塼, CȤΥ󥿥ե, Ȥ߹ѿ, Top
+@comment node-name, next, previous, up
+@chapter Ȥ߹ߥ饹ȥ⥸塼
+
+@menu
+饹
+* Array::
+* Bignum::
+* Class::
+* Dir::
+* File::
+* Fixnum::
+* Float::
+* Hash::
+* Integer::
+* IO::
+* Kernel::
+* Module::
+* Nil::
+* Numeric::
+* Object::
+* Proc::
+* Range::
+* Regexp::
+* String::
+* Struct::
+* Time::
+
+⥸塼
+
+* Comparable::
+* Enumerable::
+* Etc::
+* FileTest::
+* GC::
+* Math::
+* Process::
+@end menu
+
+@node Array, Bignum, Ȥ߹ߥ饹ȥ⥸塼, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Array
+
+źȤΥ饹Ǥ롥ϰŪˤ``[@dots{}]''
+Ԥʤ롥
+
+SuperClass: Object
+
+Included Modules: Enumerable
+
+Methods:
+
+@ftable @code
+@item self[@var{nth}]
+@itemx self[@var{start}..@var{end}]
+@itemx self[@var{start}, @var{length}]
+
+Ǥ˥롥ǽηǤ@var{nth}ܤǤ
+2ܤηǤ@var{start}ܤǤ@var{end}ܤǤޤ
+ʬ֤3ܤηǤ@var{start}ܤ@var{length}Ĥ
+ޤʬ֤
+
+@item self[@var{nth}] = @var{val}
+@itemx self[@var{start}..@var{end}] = @var{val}
+@itemx self[@var{start}, @var{length}] = @var{val}
+
+Ǥѹ롥ǽηǤ@var{nth}ܤǤ
+@var{val}ѹ롥2ܤη@var{start}ܤǤ@var{end}
+ܤǤޤǤ@var{val}ѹ롥3ܤηǤ@var{start}ܤ
+@var{length}ĤǤ@var{val}ѹ롥
+
+2ܡ3ܤηǤ@var{val}ǤʤФʤʤ
+
+
+
+@example
+ary = [1, 2, 3, 4, 5]
+ary[0..2] = [0, 0] # Ƥ [0, 0, 4, 5]
+ary[1, 0] = [7] # Ƥ [0, 7, 0, 6, 5]
+@end example
+
+@item self + @var{other}
+
+Ϣ롥@code{self}@var{other}ξƤҤ
+
+@item self * @var{times}
+
+η֤
+
+@item self - @var{other}
+
+κ黻@code{self}@var{other}ǤƤο
+֤ʣǤ1٤롥
+
+@item self * @var{other}
+
+ѱ黻ξ˴ޤޤǤʤ뿷֤
+ʣǤ1٤롥
+
+@item self | @var{other}
+
+±黻ξˤ줫˴ޤޤǤƴޤ࿷
+֤ʣǤ1٤롥
+
+@item self << @var{obj}
+
+objɲä롥@code{self}֤Τ@code{C++}ŪϢǤ
+롥
+
+@item assoc(@var{key})
+
+Ϣۥꥹ(2ǤǤȤ)򸡺1Ǥ@var{key}
+ (@code{==}Ӥ)֤
+
+@item clear
+
+礭0ˤ롥
+
+@item delete(@var{val})
+
+@var{val}ȰפǤ롥
+
+@item delete_if @{@dots{}@}
+
+Ǥ륤ƥ졼֥åɾͤλбǤ
+󤫤롥
+
+@item each @{@dots{}@}
+
+γǤͿ륤ƥ졼
+
+@item fill(@var{val})
+@itemx fill(@var{val}, @var{start}[, @var{length}])
+@itemx fill(@var{val}, @var{start}..@var{end})
+
+(λꤵ줿ʬ)Ǥͤ@var{val}ꤹ롥2֤η
+@var{length}ά줿νޤǤĹȤ롥ꤵ줿ʬ
+󤬸ϰϤۤϼưŪ˳ĥ롥
+
+@item index(@var{val})
+
+@var{val}ǽǤΥǥå֤Ǥ¸ߤ
+ʤ@code{nil}֤
+
+@item indexes(@var{ary})
+@itemx indexes(@var{index_}1,@dots{}, @var{index_n})
+
+1ܤηǤȤƼơǤ򥤥ǥå
+Ǥޤ֤2ܤηǤϳưͤ򥤥ǥåȤ
+Ǥޤ֤
+
+@item join([@var{sep}])
+
+ǤϢ뤷ʸ֤ǤʸѴ졤֤
+@var{sep}򶴤Ϣ뤵롥@var{sep}ά줿ˤϥƥѿ
+@code{$,}ͤѤ롥
+
+@item length
+@itemx size
+
+Ĺ(ǿ)֤
+
+@item pack(@var{template})
+
+Ƥ@var{template}ʸˤäơ1Ĥʸ˥ѥå롥
+ѥåʸ֤ƥץ졼ȤϷʸȤĹ(ά
+1)¤٤ΤǤ롥ĹȤ@code{*}ꤵ줿ϡֻĤΥǡ
+ơפĹɽ
+
+ʸϰʲΤΤ롥
+
+@display
+a ASCIIʸ(nullʸͤ)
+A ASCIIʸ(ڡͤ)
+b ӥåȥȥ(̥ӥåȤ̥ӥå)
+B ӥåȥȥ(̥ӥåȤ鲼̥ӥå)
+h 16ʸ(̥˥֥뤬)
+H 16ʸ(̥˥֥뤬)
+c char
+C unsigned char
+s sort
+S unsigned sort
+i int
+I unsigned int
+l long
+L unsigned int
+n ͥåȥХȥshort
+N ͥåȥХȥlong
+f ñư(¸)
+d ư(¸)
+x ʥХ
+X 1Хȸ
+@@ а֤ؤΰư
+@end display
+
+@item pop
+
+Ǥơ֤
+
+@item push(@var{obj})
+
+@var{obj}ɲä롥
+
+@item rassoc(@var{value})
+
+Ϣۥꥹ(2ǤǤȤ)򸡺2Ǥ@var{value}
+(@code{==}Ӥ)֤
+
+@item shift
+
+ƬǤơ֤
+
+@item sort
+@itemx sort @{|@var{a}, @var{b}|@dots{}@}
+
+Ƥ򥽡Ȥ롥ƥ졼ȤƸƤӽФ줿ϥ֥åɾ
+ͤǤ羮ꤹ롥礭0
+顥̾Υ᥽åɤȤƸƤӽФ줿ϳǤ@code{<=>}Ӥ롥
+
+@item to_a
+
+ʬȤ֤оΤѰդƤ᥽åɤǤޤ򤯤ʤ
+
+@item unshift(@var{obj})
+
+@var{obj}Ƭɲä롥
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item Array[@var{item}@dots{}]
+
+ǤȤ롥
+@end ftable
+
+@xref{Object}
+@xref{Enumerable}
+
+@node Bignum, Class, Array, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Bignum
+
+̵¿ĹΥ饹黻η̤@code{Fixnum}ϰǤ
+ˤϼưŪ˥饹@code{Fixnum}Ѵ롥Ūrubyץ
+Ǥ@code{Fixnum}@code{Bignum}ѴϰۤΤ˹ԤΤǡ
+ɬפ̵@code{Float}Ȥκ˴ؤƤϡ@code{Bignum}
+@code{Float}genericity⤤Τˤؤ餺@code{Bignum}
+礭ͤɽǤΤǡѴ˷ǽ롥
+
+SuperClass: Integer
+
+Methods:
+
+@ftable @code
+@item self + @var{other}
+@itemx self - @var{other}
+@itemx self * @var{other}
+@itemx self / @var{other}
+@itemx self % @var{other}
+@itemx self ** @var{other}
+
+ѱ黻줾¡ѡ;Ѿ֤
+
+@item ~ self
+@itemx self | @var{other}
+@itemx self & @var{other}
+@itemx self ^ @var{other}
+
+ӥåȱ黻줾ӥåȿž¡ѡ¾Ū¤֤
+
+@item self << @var{bits}
+@itemx self >> @var{bits}
+
+եȱ黻줾@var{bits}ӥåȤ˥ӥåȥեȤԤʤ
+
+@item divmod(@var{other})
+
+Ⱦ;ʤ֤
+@end ftable
+
+@xref{Integer}
+
+@node Class, Comparable, Bignum, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Class
+
+饹Υ饹긷̩ȥ饹ðۥ᥽åɤѾ뤿
+ˡ줾᥿饹ȸƤФ̾Τʤ饹򥯥饹Ȥƻ
+@code{Class}ϤΥ᥿饹Υ饹Ǥ(ʬä?)β
+⤬ǤʤƤ⡤rubyȤȤ˲λپʤ饹ˤðۥ
+åɤǤȡѡ饹줿ðۥ᥽åɤϤΥ
+֥饹ǤͭǤΤнʬǤ롥
+
+SuperClass: Module
+
+Private Methods:
+
+@ftable @code
+@item attr(@var{name}[, @var{public}])
+
+Υ饹Υ󥹥󥹤Ф@var{name}ǻꤵ°롥
+ܤ@code{Module}@code{attr}᥽åɤι򻲾ȤΤȡ
+@end ftable
+
+Methods:
+
+@ftable @code
+@item new(@dots{})
+
+饹Υ󥹥󥹤롥¿ξ礳Υ᥽åɤϥ֥饹
+ۥ᥽åɤˤäƥС饤ɤ졤饹ˤäưۤʤ롥
+@end ftable
+
+@xref{Module}
+
+@node Comparable, Dir, Class, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Comparable
+
+ӱ黻饹Τ@code{Mixin}Υ⥸塼򥤥󥯥롼
+뤳Ȥˤäơ@code{<=>}黻Ҥ¾α黻ҤϤ
+ѤǤ롥
+
+Methods:
+
+@ftable @code
+@item self == @var{other}
+
+@code{self}@var{other}֤
+
+@item self > other
+
+@code{self}@var{other}礭֤
+
+@item self >= @var{other}
+
+@code{self}@var{other}礭֤
+
+@item self < @var{other}
+
+@code{self}@var{other}꾮֤
+
+@item self <= @var{other}
+
+@code{self}@var{other}꾮֤
+
+@item between?(min, max)
+
+@code{self}@var{min}@var{max}ϰˤ֤
+@end ftable
+
+@node Dir, Enumerable, Comparable, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Dir
+
+ǥ쥯ȥǤ֤ǥ쥯ȥꥹȥ꡼ΤΥ饹
+
+SuperClass: Object
+
+Included Modules: Enumerable
+
+Methods:
+
+@ftable @code
+
+@item close
+
+ǥ쥯ȥꥹȥ꡼򥯥롥ʸ㳰ȯ롥
+
+@item each @{|@var{item}|@dots{}@}
+
+ǥ쥯ȥγǤͿ륤ƥ졼
+
+@item getwd
+@itemx pwd
+
+ȥǥ쥯ȥ֤
+
+@item rewind
+
+ǥ쥯ȥꥹȥ꡼Ƭ˥ꥻåȤ롥
+
+@item seek(@var{pos})
+
+ǥ쥯ȥꥹȥ꡼ΰ֤@var{pos}ꤹ롥
+
+@item tell
+
+ǥ쥯ȥꥹȥ꡼θߤΰ֤֤
+
+Single Methods:
+
+@item self[@var{pat}]
+@itemx glob(@var{pat})
+
+ʸ@var{pat}@samp{sh}Υ磻ɥɤȤŸ̤ʸ
+Ȥ֤񼰤ϰʲ̤Ǥ롥
+
+@ftable @samp
+@item *
+Ǥդʸ(ʸޤ)Ȱ
+@item ?
+Ǥդ1ʸȰ
+@item [ ]
+[]Τ줫1ʸȰ
+@item {@dots{}}
+{}(ޤǶڤ줿)줫ʸȰ
+@end ftable
+
+@item chdir(@var{path})
+
+ȥǥ쥯ȥ@var{path}ѹ롥
+
+@item chroot(@var{path})
+
+ץΥ롼ȥǥ쥯ȥѹ롤Ʊ̾ΥƥॳƱƯ
+򤹤롥ϼ¸uidѥ桼Ǥ¤Ƥ롥
+롼ȥǥ쥯ȥ򸵤᤹(롼ȥǥ쥯ȥѹ)ˡ
+󶡤Ƥʤ
+
+@item mkdir(@var{path}[, @var{mode}])
+
+@var{mode}ǻꤵ줿⡼ɤĥǥ쥯ȥ@var{path}롥⡼
+ɤ@code{umask}ˤäƽ롥@var{mode}Υǥեͤ0777
+
+@item open(@var{path})
+
+@var{path}Фǥ쥯ȥꥹȥ꡼򥪡ץ󤹤롥
+
+@item rmdir(@var{path})
+
+@var{path}ǻꤵ줿ǥ쥯ȥ롥ǥ쥯ȥ϶Ǥɬ
+פ롥
+@end ftable
+
+@xref{Object}
+@xref{Enumerable}
+
+@node Enumerable, File, Dir, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Enumerable
+
+ǤФ뷫֤Ԥʤ饹Τ@code{Mixin}Υ⥸塼
+򥤥󥯥롼ɤ뤿ˤϡ᥽å@code{each}ɬפ롥
+
+Methods:
+
+@ftable @code
+
+@item collect @{|@var{item}|@dots{}@}
+
+ǤФƥ֥åɾ̤ƴޤ֤
+
+@item find @{|@var{item}|@dots{}@}
+
+ǤФƥ֥åɾͤˤʤäǽǤ֤
+
+@item find_all @{|@var{item}|@dots{}@}
+
+ǤФƥ֥åɾͤǤäǤƴޤ֤
+
+@item grep(pattern)
+@itemx grep(pattern) @{|@var{item}|@dots{}@}
+
+@code{ =~ @var{pattern}}ΩƤǤޤ֤
+졼ȤѤ줿Ͼ嵭ξΩǤФƥ֥å
+Ԥ롥
+
+@item member?(@var{val})
+
+@var{val}@code{==}δطˤǤĻ֤
+
+@item index(@var{val})
+
+@var{val}@code{==}δطˤ륪֥Ȥܤ˸줿֤
+ֺǽǤ0ˤʤ롥Ǥ¸ߤʤˤ@code{nil}֤
+Τʤ饹ФƤϤޤ̣ʤ
+
+@item length
+
+Ǥο֤
+
+@item min
+
+ǾǤ֤ƤǤߤ@code{<=>}᥽åɤӤǤ뤳
+ȤꤷƤ롥
+
+@item max
+
+Ǥ֤Ǥ@code{<=>}᥽åɤӤǤ뤳Ȥꤷ
+롥
+
+@item reverse
+
+ƤǤս¤٤֤
+
+@item sort
+@itemx sort @{|@var{a}, @var{b}|@dots{}@}
+
+ƤǤ򥽡Ȥ֤
+@end ftable
+
+@node File, FileTest, Enumerable, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section File
+
+ե륢ΤΥ饹᥽å@code{open}롥ޤ
+Υ饹ðۥ᥽åɤȤ@code{test}Υեƥȱ黻
+᥽åɤƤ(@code{FileTest}⥸塼Υ᥽åɷ)
+
+SuperClass: IO
+
+Methods:
+
+@ftable @code
+
+@item atime
+
+եκǽ֤
+
+@item ctime
+
+եκǽơѹ֤
+
+@item chmod(@var{mode})
+
+եΥѡߥåѹ(cf @samp{chmod(2)})
+
+@item chown(@var{owner}, @var{group})
+
+եνͭԤȥ롼פѹ(cf @samp{chown(2)})@code{nil}
+@code{-1}ꤹ뤳ȤˤäƽͭԤ䥰롼פ򸽺ߤΤޤѤʤ
+ȤǤ롥
+
+@item eof
+@itemx eof?
+
+եνüã˿֤
+
+@item lstat
+
+ե˴ؤ@code{Stat}¤Τ֤@code{lstat}ϥե뤬
+ܥå󥯤ǤХ󥯤ΤΤ˴ؤ@code{Stat}¤Τ֤
+¤ΤƤˤĤƤ@code{stat}򻲾ȤΤȡ
+
+@item mtime
+
+եκǽ֤
+
+@item rewind
+
+եΥեݥ󥿤ΰ֤Ƭ˰ư롥
+
+@item path
+
+եΥѥ֤̾
+
+@item seek(@var{offset}, @var{ptrname})
+
+եΥեݥ󥿤ΰ֤@var{offset}˰ư롥
+@var{ptrname}012Τ줫Ǥäơ줾եƬ
+֡եνüФ򼨤
+
+@item stat
+
+ե˴ؤ@code{Stat}¤Τ֤(@xref{Struct})
+
+@display
+struct stat
+ dev # ե¸ߤǥХ
+ ino # եi-nodeֹ
+ mode # ⡼
+ nlink # ϡɥ󥯤ο
+ uid # ͭԤΥ桼ID
+ gid # ͭԤΥ롼ID
+ rdev # ǥХID(ڥեΤ)
+ size # ե륵(byte)
+ blksize # ե륷ƥˤŬڤʥ֥å
+ blocks # ֥å
+ atime # ǽ
+ mtime # ǽ
+ ctime # ǽѹ
+end
+@end display
+
+ܺ٤@samp{stat(2)}򻲾ȤΤȡƥƤ
+@code{Stat}¤Τ˳Фʤ0ꤵƤ롥
+
+@item tell
+
+եθߤΥեݥ󥿤ΰ֤֤
+
+@item truncate(@var{length})
+
+եڤΤƤƺ@var{length}ХȤˤ롥ե
+@code{write}⡼ɤǥץ󤵤ƤʤФʤʤ
+
+Single Methods:
+
+@item atime(@var{filename})
+
+@var{filename}κǽ֤
+
+@item basename(@var{filename}[, @var{suffix}])
+
+@var{filename}κǸǤ֤@var{suffix}Ϳ줿ϡ
+ĥҤ
+
+@example
+basename("ruby/ruby.c")
+ @result{} "ruby.c"
+basename("ruby/ruby.c", ".c")
+ @result{} "ruby"
+@end example
+
+@item ctime(@var{filename})
+
+@var{filename}κǽơѹ֤
+
+@item chmod(@var{mode}, @var{path}, @var{file}@dots{})
+
+եΥѡߥåѹ(cf @samp{chmod(2)})ѹե
+
+@item chown(@var{owner}, @var{group}, @var{file}@dots{})
+
+եνͭԤȥ롼פѹ(cf @samp{chown(2)})@code{nil}
+@code{-1}ꤹ뤳ȤˤäƽͭԤ䥰롼פ򸽺ߤΤޤѤʤ
+ȤǤ롥ѹե֤
+
+@item dirname(@var{fname})
+
+ե̾κǸǰʳ֤
+
+@item expand_path(@var{path})
+
+ե̾ХѥŸ롥@samp{~}ϥۡǥ쥯ȥŸ
+롥
+
+@example
+expand_file_name("..")
+ @result{} "/home/matz/work"
+expand_file_name("~")
+ @result{} "/home/matz"
+expand_file_name("~matz")
+ @result{} "/home/matz"
+@end example
+
+@item link(@var{old}, @var{new})
+
+@var{old}ؤΥϡɥ@var{new}롥@samp{link(2)}Ʊ
+롥
+
+@item mtime(@var{filename})
+
+@var{filename}κǽ֤
+
+@item readlink(@var{path})
+
+ܥå@var{path}ƤʸȤ֤
+
+@item rename(@var{from}, @var{to})
+
+ե̾@var{from}@var{to}ѹ롥@samp{rename(2)}ȡ
+@var{to}Ȥ̾Υե뤬¸ߤˤϤޤΥե뤬
+롥
+
+@item stat(@var{filename})
+
+@var{filename}Υե@code{Stat}¤Τ֤
+
+@item symlink(@var{old}, @var{new})
+
+@var{old}ؤΥܥå@var{new}롥
+
+@item truncate(@var{path}, @var{length})
+
+@var{path}ǻꤵ줿եڤΤƤƺ@var{length}ХȤˤ롥
+
+@item type(@var{filename})
+
+@var{filename}ΥեΥפɽʸ֤ʸ
+@code{"file"}@code{"directory"}@code{"characterSpecial"}
+@code{"blockSpecial"}@code{"fifo"}@code{"link"}@code{"socket"}
+Τ줫ĤǤ롥
+
+@item unlink(@var{file}@dots{})
+
+ե롥ǥ쥯ȥκˤ@code{Dir.rmdir}Ȥȡ
+
+@item utime(@var{atime}, @var{mtime}, @var{file}@dots{})
+
+եΥ@var{atime}ˡ@var{mtime}ꤹ롥
+@var{atime}@var{mtime}Ͽޤ@code{Time}饹Υ󥹥󥹤Ǥ
+Фʤʤ
+@end ftable
+
+ʳ@code{FileTest}⥸塼Υ᥽åɤðۥ᥽åɤȤƻġ
+
+@xref{IO}
+
+@node FileTest, Fixnum, File, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section FileTest
+
+եƥѥ᥽åɤ򽸤᤿⥸塼롥󥯥롼ɤѤ뤳
+Ǥ롥Υ⥸塼Υ᥽åɤ˥ե̾Ȥ@code{"&"}ꤹ
+ȡľΥեؤ@samp{stat(2)}η̤Ѥ롥
+
+Methods:
+Single Methods:
+
+@ftable @code
+@item blockdev?(@var{filename})
+
+@var{filename}Υե뤬֥åڥեǤ֤
+
+@item chardev?(@var{filename})
+
+@var{filename}Υե뤬饯ڥեǤ
+
+
+@item executable?(@var{filename})
+
+@var{filename}Υե뤬¹Բǽλ֤
+
+@item executable_real?(@var{filename})
+
+@var{filename}Υե뤬uid/gidǼ¹Բǽλ֤
+
+@item exists?(@var{filename})
+
+@var{filename}Υե뤬¸ߤ֤
+
+@item grpowned?(@var{filename})
+
+@var{filename}Υեgid¸롼פgidƱ֤
+
+@item directory?(@var{filename})
+
+@var{filename}ǥ쥯ȥλ֤
+
+@item file?(@var{filename})
+
+@var{filename}Υե뤬̾եλ֤
+
+@item link?(@var{filename})
+
+@var{filename}Υե뤬ܥå󥯤Ǥ֤
+
+@item pipe?(@var{filename})
+
+@var{filename}Υե뤬̾Ĥѥ(@code{FIFO})Ǥ
+
+
+@item socket?(@var{filename})
+
+@var{filename}Υե뤬åȤǤ֤
+
+@item owned?(@var{filename})
+
+@var{filename}Υե¸桼ͭƤ֤
+
+@item readable?(@var{filename})
+
+@var{filename}ΥեɤߤȤǽλ֤
+
+@item readable_real?(@var{filename})
+
+@var{filename}Υեuid/gidɤߤȤǽλ֤
+
+@item setuid?(@var{filename})
+
+@var{filename}ΥեsetuidӥåȤåȤƤ֤
+
+@item setgid?(@var{filename})
+
+@var{filename}ΥեsetgidӥåȤåȤƤ֤
+
+@item size(@var{filename})
+
+@var{filename}Υե뤬¸ߤե礭֤¸ߤ
+@code{nil}֤
+
+@item sticky?(@var{filename})
+
+@var{filename}ΥեstickyӥåȤåȤƤ֤
+
+@item symlink?(@var{filename})
+
+@var{filename}ܥå󥯤Ǥ֤
+
+@item writable?(@var{filename})
+
+@var{filename}Υե뤬uid/gidǽ񤭹߲ǽλ֤
+
+@item writable_real?(@var{filename})
+
+@var{filename}Υե뤬񤭹߲ǽλ֤
+
+@item zero?(@var{filename})
+
+@var{filename}Υե뤬¸ߤ礭0Ǥ֤
+@end ftable
+
+@node Fixnum, Float, FileTest, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Fixnum
+
+31bit(ޥlongĹ-1 bit)Υ饹builtin classǤ롥
+饹pointer¨ͤǤ뤿call by valueǸƤӽФħŪ
+Ǥ(¾Υ饹call by reference)黻η̤31bitۤ
+ϼưŪ@code{Bignum}(̵¿Ĺ)˳ĥ롥
+
+ƥ졼@code{upto}@code{downto}@code{step}Ϸ֤Τ
+졤̤@code{Range}饹Ѥ®Ǥ롥
+
+SuperClass: Integer
+
+Methods:
+
+@ftable @code
+@item self + @var{other}
+@itemx self - @var{other}
+@itemx self * @var{other}
+@itemx self / @var{other}
+@itemx self % @var{other}
+@itemx self ** @var{other}
+
+ѱ黻줾¡ѡ;Ѿ֤
+
+@item ~ self
+@itemx self | @var{other}
+@itemx self & @var{other}
+@itemx self ^ @var{other}
+
+ӥåȱ黻줾ӥåȿž¡ѡ¾Ū¤֤
+
+@item self << @var{bits}
+@itemx self >> @var{bits}
+
+եȱ黻줾@var{bits}ӥåȤ˥ӥåȥեȤԤʤ
+
+@item downto(@var{min}) @{@dots{}@}
+
+ƥ졼@code{self}@var{min}ޤDz˷֤
+
+@item id2name
+
+ͤIDȤߤʤơʸ֤ʸ¸ߤ
+@code{nil}֤
+
+@item step(@var{max}, @var{step}) @{@dots{}@}
+
+ƥ졼@code{self}@var{max}ޤ@var{step}Ѳʤ顤
+
+@item to_f
+
+@code{self}@code{Float}ѴΤ֤
+
+@item to_i
+
+@code{self}򤽤Τޤ֤
+
+@item upto(@var{max}) @{@dots{}@}
+
+ƥ졼@code{self}@var{max}ޤǷ֤
+@end ftable
+
+@xref{Integer}
+
+@node Float, GC, Fixnum, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Float
+
+ưΥ饹
+
+SuperClass: Numeric
+
+Methods:
+
+@ftable @code
+@item self + @var{other}
+@itemx self - @var{other}
+@itemx self * @var{other}
+@itemx self / @var{other}
+@itemx self % @var{other}
+@itemx self ** @var{other}
+
+ѱ黻줾¡ѡ;Ѿ֤
+
+@item self == @var{other}
+@itemx self > @var{other}
+
+ӱ黻
+
+@item coerce(@var{num})
+
+@var{num}@code{Float}Ѵ롥@code{Float}
+¾ο@code{Fixnum}@code{Bignum}Ǥ롥
+
+@item to_f
+
+@code{self}򤽤Τޤ֤
+
+@item to_i
+
+@code{self}Ѵ̤֤
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item new(@var{float})
+
+@var{float}ƱͤĿ@code{Float}֥Ȥ֤
+@end ftable
+
+@xref{Numeric}
+
+@node GC, Hash, Float, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section GC
+
+RubyȤ߹ߤgarbage collectorԤʤΥ⥸塼롥Υ
+塼Υ᥽åɤѤ뤳ȤˤäơŪGCߤ᤿ꡤGCε
+륿ߥ󥰤椷Ǥ롥
+
+Methods:
+
+@ftable @code
+@item garbage_collect
+
+GC򳫻Ϥ롥@code{GC.start}Ʊ
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item disable
+
+GCػߤ롥
+
+@item enable
+
+GCĤ롥
+
+@item start
+
+GC򳫻Ϥ롥
+@end ftable
+
+@node Hash, Integer, GC, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Hash
+
+Ϣ󤢤뤤ϥϥåɽǤդΥ֥ȤźȤǤΥ
+Ǥ롥Ϣ󥪥֥ȤϰŪˤϢ
+
+@display
+{a=>b,@dots{}}
+@end display
+
+ǹԤʤ롥
+
+ȤͿ֥ȤƤѲ᥽å@code{hash}֤
+ͤѤ@code{Hash}ưʤ(ͤФʤʤ)
+ˤä@code{hash}ͤѲ륯饹(Ȥ@code{Array},
+@code{Hash}ʤ)Υ󥹥󥹤ϥ˸ʤƤ
+@code{hash}ͤ˱ƶ륪֥ȤΤʸ̤˰
+롥ʸ򥭡ȤͿȡʸ򥳥ԡԡ򹹿ԲĤ
+ꤷǡȤƻѤ롥äơʸ򹹿Ƥ⥭ʸ
+Ѳʤ@code{each}, @code{each_key}, @code{keys}ʤɤΥ᥽
+ɤȤʸ֤ʸϹǤʤ(㳰ȯ)
+
+SuperClass: Object
+
+Included Modules: Enumerable
+
+Methods:
+
+@ftable @code
+@item self [@var{key}]
+
+@var{key}򥭡Ȥ֤ͤ
+
+@item self [@var{key}]= @var{value}
+
+@var{key}򥭡Ȥơ@var{value}Ǽ롥@var{value}Ȥ
+@code{nil}ꤹȤ@var{key}ФܤκȤʤ롥Ĥޤꡤ
+@code{Hash}ͤȤ@code{nil}ĤȤϤǤʤ
+
+@item clear
+
+Ϣˤ롥
+
+@item delete(@var{key})
+
+@var{key}򥭡ȤȤ롥
+
+@item delete_if @{|@var{item}|@dots{}@}
+
+Ǥ륤ƥ졼@code{[key,value]}ȤͿơ֥
+ɾͤλܤ롥
+
+@item each @{|@var{key}, @var{value}|@dots{}@}
+@itemx each_pair @{|@var{key}, @var{value}|@dots{}@}
+
+@code{[key,value]}ʤ2ǤͿ륤ƥ졼
+
+@item each_key @{|@var{key}|@dots{}@}
+
+ƤkeyФƷ֤ƥ졼
+
+@item each_value @{|@var{value}|@dots{}@}
+
+ƤvalueФƷ֤ƥ졼
+
+@item has_key?(@var{key})
+
+@var{key}򥭡ȤȤϢ¸ߤ֤
+
+@item has_value?(@var{value})
+
+@var{value}ͤȤȤϢ¸ߤ֤
+
+@item indexes(@var{ary})
+@itemx indexes(@var{key_}1,@dots{}, @var{key_n})
+
+1ܤηǤȤƼơǤ򥭡ȤǤޤ
+֤2ܤηǤϳưͤ򥭡ȤǤޤ֤
+
+@item keys
+
+Ϣ¸ߤ륭Ƥޤ֤
+@item length
+@itemx size
+
+ϢǤο֤
+
+@item shift
+
+ϢǤļФ()@code{[key,value]}ʤ2
+
+@item to_a
+
+Ϣ@code{key-value}2ǤǤȤ֤
+
+@item values
+
+Ϣ¸ߤƤޤ֤
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item Hash[@var{key}, @var{value}@dots{}]
+
+ܤΰ@var{key}ܤΰ@var{value}ȤϢ
+롥
+
+@item new
+
+()Ϣ󥪥֥Ȥ֤
+@end ftable
+
+@xref{Object}
+@xref{Enumerable}
+
+@node Integer, IO, Hash, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Integer
+
+饹ºݤϤ礭ˤä@code{Fixnum}@code{Bignum}
+ĤΥ֥饹Ǽ¸Ƥ롥@code{Integer}ϤΥѡ饹
+Ȥʤݥ饹Ǥ롥RubyǤϤۤȤɤξ硤@code{Fixnum}
+@code{Bignum}ζ̤ɬפʤߤѴϼưŪ˹Ԥʤ롥
+ӥåȤߤʤˤϡ̵¤Ĺĥӥåȹͤƹʤ
+
+SuperClass: Numeric
+
+Methods:
+
+@ftable @code
+@item self[@var{idx}]
+
+@var{idx}ӥåܤåȤƤ1åȤƤʤ0
+
+@item chr
+
+ο򥳡ɤȤʸޤ1ʸʸ֤̤Ĺ1ʾ
+ʸˤĤơδطΩ롥
+
+@example
+str[0].chr == str[0,1]
+@end example
+
+ʸϰ(0@dots{}255)ˤʤ㳰ȯ롥
+
+@item integer?
+
+Ĥ⿿֤
+@end ftable
+
+@xref{Numeric}
+
+@node IO, Kernel, Integer, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section IO
+
+ϤΤδܥ饹
+
+SuperClass: Object
+
+Included Modules: Enumerable
+
+Methods:
+
+@ftable @code
+@item self << @var{object}
+
+@var{object}Ϥ롥@var{object}ʸǤʤˤϥ᥽å
+@code{to_s}ѤʸѴ롥@code{self}ͤȤΤǡ
+@code{C++}Τ褦@code{<<}ϢȤ롥
+
+
+
+@example
+$stdout << 1 << " is a " << Fixnum << "\n"
+@end example
+
+@item close
+
+ϥݡȤ򥯥롥ʸΤΥ֥ȤФ
+顼ˤʤ롥
+
+@item closed?
+
+ݡȤƤ֤
+
+@item each @{|@var{line}|@dots{}@}
+@item each_line @{|@var{line}|@dots{}@}
+
+Ԥɤ߹Ǥ뤿Υƥ졼Ԥζڤϥƥѿ
+@code{$/}ˤäѹǤ롥ɤ߹ʸϥƥѿ@code{$_}
+⥻åȤ롥
+
+@itemx each_byte @{|@var{ch}|@dots{}@}
+
+ʸɤ߹Ǥ뤿Υƥ졼ʸʸɤɽ
+@code{Fixnum}Ǥ롥
+
+@item fileno
+@itemx to_i
+
+@code{IO}֥ȤȤäƤեǥץ(@code{Fixnum})
+
+@item flush
+
+Хåեեå夹롥
+
+@item getc
+
+ɤ߹ǡɤ߹ߤˤϤʸ֤եν
+ãˤ@code{nil}֤ͥ᥽å@code{getc}
+@code{$stdin.getc}Ʊ̣Ǥ롥
+
+@item gets
+
+ɤ߹ǡɤ߹ߤˤϤʸ֤եν
+ãˤ@code{nil}֤
+
+@item isatty
+@itemx tty?
+
+ϥݡȤttyǤ֤
+
+@item print(@var{arg}@dots{})
+
+˽Ϥ롥褬@code{$>}Ǥʤ쥷ФǤʳ
+@code{Kernel}饹@code{print}᥽åɤƱư򤹤롥
+
+@item printf(@var{format}, @var{arg}@dots{})
+
+@code{C}@code{printf()}Ʊ@var{format}˽ʸ
+쥷Ф˽Ϥ롥
+
+@item puts(@var{obj})
+
+@var{obj}Ϥ롥@code{self << obj}Ʊ̣Ǥ롥
+
+@item read([@var{length}])
+
+@var{length}Хɤ߹ǡʸ֤@var{length}ά
+ˤϡ@code{EOF}ޤǤƤΥǡɤ߹ࡥ
+
+@item readlines
+
+եɤ߹dzƹԤǤȤƤ֤
+
+@item sync
+
+ߤνƱ⡼ɤ򿿵֤ͤƱ⡼ɤλϽϴؿθƽ
+˥Хåեեå夵롥
+
+@item sync= @var{newstate}
+
+Ʊ⡼ɤꤹ롥
+
+@item sysread(@var{length})
+
+@samp{stdio}ͳ@samp{read(2)}ѤϤԤʤϤ줿
+ǡޤʸ֤եνãˤ@code{nil}
+@samp{read(2)}ˤɬ@var{length}ХȤʸɤ߹
+櫓ǤϤʤ@code{gets}@code{getc}ʤ@samp{stdio}ͳ
+åɤȺѤ뤳ȤϥХåե󥰤ʤɤǻפư򤹤뤳
+롥
+
+@item syswrite(@var{str})
+
+@samp{stdio}ͳˡ@samp{write(2)}ѤƽϤԤʤΥ
+åɤϥХåե󥰤ʤ@samp{stdio}Ƥ뤳ȤϰڹԤʤʤ
+@code{syswrite}ϼºݤ˽񤭹Хȿ֤@code{print}
+@code{printf}@code{syswrite}ѤΤϿ侩Ǥʤ
+
+@item write(@var{str})
+
+@var{str}Ϥ롥ϤХȿ֤
+@end ftable
+
+@xref{Object}
+@xref{Enumerable}
+
+@node Kernel, Math, IO, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Kernel
+
+ƤΥ饹δ쥯饹RubyȤ߹ߤƤδؿ᥽åɤϤΥ饹
+Ƥ롥ؿ᥽åɤˤĤƤϡִؿפιܤ򻲾ȤΤȡ
+
+SuperClass: ʤ
+
+Methods:
+
+@ftable @code
+@item self == @var{other}
+@itemx equal?(@var{other})
+
+֥ȤΰȽꡥ쥷ФȰΰפ֤
+@code{Kernel}饹ǤΥ֥ȤƱλ֤
+@code{==}᥽åɤϳƥ֥Ȥ˱ƺɬפ롥
+@code{==}᥽åɤˤϡ@code{hash}᥽åɤ⤽˹碌
+ƺɬפ롥
+
+equal?᥽åɤ@code{==}᥽åɤ̾ǡ@code{==}Ǥ
+֥ȤƱȽԤʤѤ롥ä@code{equal?}
+᥽åɤϥ֥饹Ǻ٤ǤϤʤ
+
+@item self =~ @var{other}
+
+ޥåǥեȤư@code{==}ƱǤ롥@code{=~}
+@code{case}ʸǤӤˤѤ롥
+
+@item hash
+
+֥ȤΥϥå(@code{Fixnum})֤@code{Hash}饹ǥ
+Ȥʤ륪֥ȤǼΤѤƤ.@code{A == B}Ω
+ɬ@code{A.hash == B.hash}ΩɬפΤǡ@code{==}
+ˤɬ⤽˹碌ƺ뤳ȡ
+
+@item id
+
+ƥ֥ȤФưդ@code{Fixnum}֤@code{Fixnum}ϼ
+ʬȤ֤Τǡ@code{id}פƤƱ֥ȤǤ뤳Ȥ
+ڤʤĤޤꡤ@code{obj1.id == obj2.id}ΩƤ⡤ɤ餫
+@code{Fixnum}ǤС@code{obj1}@code{obj2}ƱǤȤϸ¤
+ξ@code{Fixnum}ǤʤȤݾڤǤС2ĤΥ֥
+ȤƱǤ뤳Ȥϳμ¤Ǥ롥
+
+@item inspect
+
+֥Ȥʹ֤ɤʸѴ롥
+
+@item nil?
+
+֥Ȥ@code{nil}Ǥ뤫ɤ@code{Kernel}饹Ǥ
+֤@code{Nil}饹ǵ֤褦Ƥ롥
+
+
+@item type
+
+֥ȤưŪʷ(饹)֤
+
+@example
+obj.is_kind_of?(obj.type)
+@end example
+
+ϾΩ롥
+
+@item send(@var{symbol}[, @var{args}@dots{}])
+
+@var{symbol}ǻꤵ᥽åɤ@var{args}ȤȤ˸ƤӽФ
+
+@end ftable
+
+@node Math, Module, Kernel, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Math
+
+ư黻򥵥ݡȤ륯饹Math⥸塼ƱΥ᥽å
+ðۥ᥽åɤȤξƤΤǡðۥ᥽åɤƤӽФƻ
+Ȥȡ饹˥󥯥롼ɤƻȤȤȤξǤ롥
+
+
+
+@example
+pi = Math.atan2(1, 1) * 4;
+include Math
+pi2 = atan2(1, 1)
+@end example
+
+Methods:
+Single Methods:
+
+@ftable @code
+@item atan2(@var{x}, @var{y})
+
+С-ФϰϤ@var{x}/@var{y}Υ󥸥Ȥ֤
+
+@item cos(@var{x})
+@itemx sin(@var{x})
+@itemx tan(@var{x})
+
+饸ɽ줿@var{x}λѴؿ֤ͤ
+
+@item exp(@var{x})
+
+@var{x}λؿؿ֤ͤ
+
+@item log(@var{x})
+
+@var{x}μп֤
+
+@item log10(@var{x})
+
+@var{x}ξп֤
+
+@item sqrt(@var{x})
+
+@var{x}ʿ֤@var{x}ͤǤˤ㳰ȯ롥
+
+@item cbrt(@var{x})
+
+@var{x}Ω֤
+@end ftable
+
+@node Module, Nil, Math, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Module
+
+⥸塼Υ饹
+
+SuperClass: Object
+
+Private Methods:
+
+@ftable @code
+@item attr(@var{name}[, @var{public}])
+
+Υ⥸塼򥤥󥯥롼ɤ饹Υ󥹥󥹤Ф@var{name}
+ǻꤵ°ղä°Ф륢᥽åɤ롥
+@code{attr("attr")}ϥ饹˰ʲ˼ɤɲäΤȤۤƱ
+Ǥ롥
+
+@example
+def attr; @@attr; end
+@end example
+
+άǽ2@var{public}ͿơĤͤ@code{nil}Ǥ
+ˤϤ°ˤ°᥽åɤѰդ졤ǽˤʤ롥
+
+@code{attr("attr", TRUE)}ϥ饹˰ʲΥɤɲäΤȤۤ
+ƱǤ롥
+
+@example
+def attr; @@attr; end
+def attr=(val); @@attr = val; end
+@end example
+
+°᥽åɤ뤳Ȥˤäơưѹ
+Ǥ롥㤨
+
+@example
+attr("test", TRUE)
+def test=(val)
+ print("test was ", @@test, "\n")
+ print("and now is ", @@test = val, "\n")
+end
+@end example
+
+Τ褦°ͤɽ褦ʤȤǽǤ롥@var{attr}
+᥽åɤǤƤϡǥեȤΥ᥽
+ɤʤ
+@end ftable
+
+Methods:
+
+@ftable @code
+@item include(@var{module}@dots{})
+
+ǻꤷ⥸塼򥤥󥯥롼ɤơ᥽åɡɲä롥
+饹⥸塼̤Υ⥸塼򥤥󥯥롼ɤ뤳Ȥˤäơ
+줿¿ŷѾ(@code{Mixin})¸Ǥ롥
+
+@item module_function(@var{name}@dots{})
+
+@var{name}ǻꤵ줿᥽åɤ@samp{module function}˻ꤹ롥
+@samp{Module function}Ȥϥ⥸塼ðۥ᥽åɤǤꡤĤΥ⥸塼
+򥤥󥯥롼ɤ饹private᥽åɤˤʤ褦ʥ᥽åɤλ
+Ǥ롥㤨СMath⥸塼δؿ@samp{module function}Ǥ롥
+
+@item private(@var{name}@dots{})
+
+@var{name}ǻꤵ줿᥽åɤؿǤƤӽФǽˤ롥
+private᥽åɤǤˤϲ⤷ʤ
+
+@item public(@var{name}@dots{})
+
+@var{name}ǻꤵ줿᥽åɤ̾ǸƤӽФǽˤ롥Ǥ
+public᥽åɤǤˤϲ⤷ʤ
+
+@example
+def foo() 1 end
+foo
+ @result{} 1
+self.foo
+ @result{} 1
+
+def bar() 2 end
+private :bar
+bar
+ @result{} 2
+self.bar
+ @error{} method `bar' not available for "main"(Object)
+
+Module Baz
+ def baz() 3 end
+ module_function :baz
+end
+Baz.baz
+ @result{} 3
+include Baz
+baz
+ @result{} 3
+self.baz
+ @error{} method `baz' not available for "main"(Object)
+@end example
+
+@item to_s
+
+⥸塼ʸɽǤ⥸塼֤̾
+@end ftable
+
+@xref{Object}
+
+@node Nil, Numeric, Module, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Nil
+
+ɽ֥@code{nil}Υ饹ѿ()@code{nil}
+@code{Nil}饹ͣΥ󥹥󥹤Ǥ롥
+
+SuperClass: Kernel
+
+Methods:
+
+@ftable @code
+@item self + @var{other}
+
+@var{other}ưʸǤ@var{other}
+
+
+@item nil?
+
+˿֤
+@end ftable
+
+@xref{Kernel}
+
+@node Numeric, Object, Nil, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Numeric
+
+̤ɽݥ饹
+
+SuperClass: Object
+
+Included Modules: Comparable
+
+Methods:
+
+@ftable @code
+@item + self
+
+֥@code{self}ΤΤ֤
+
+@item - self
+
+@code{0 - self}֤֥ͤ饹ǤΨŪ˺뤳Ȥ
+Ԥ롥
+
+@item abs
+
+֤ͤ
+
+@item divmod(@var{other})
+
+Ⱦ;2Ǥ֤
+
+@item next
+
+ο֤οȤϤοۤǾǤ롥
+@end ftable
+
+@xref{Object}
+@xref{Comparable}
+
+@node Object, Proc, Numeric, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Object
+
+Ƥ̾說饹Υѥ饹̾說饹Υ󥹥󥹤ΰŪʿ
+Ƥ롥Υ饹Υ֥饹Ǥʤ饹@code{Kernel}
+@code{Nil}Ǥ롥
+
+SuperClass: Kernel
+
+Methods:
+
+@ftable @code
+@item extened(module@dots{})
+
+ǻꤷ⥸塼@code{self}˥󥯥롼ɤ롥⥸塼
+Ƥ᥽åɤðۥ᥽åɤȤɲä롥
+
+@item initialize(@dots{})
+
+@code{Class:new}饪֥Ȥ˼ưŪ˸ƤӽФ롥ǥե
+Ȥϲ⤷ʤ֥饹ɬפ˱ƺ뤳Ȥ
+Ƥ롥@code{Class:new}Ϳ줿ΤޤϤ롥
+
+@item is_instance_of?(@var{class})
+
+֥@code{self}饹@var{class}Υ󥹥󥹤Ǥ
+֤@code{obj.is_instance_of?(c)}ΩĤ
+@code{obj.is_kind_of?(c)}Ω롥
+
+@item is_kind_of?(@var{class})
+
+֥@code{self}饹@var{class}Υ֥饹Υ󥹥
+Ǥ֤
+
+@item clone
+@item dup
+
+֥Ȥʣ롥󥹥󥹤¨ͤǤFixnum饹ʳΥ
+饹ξ硤@code{obj.equal?(obj.clone)}ϵǤ뤬¿ξ
+@code{obj == obj.clone}ϿǤ롥
+
+String饹ʳǤ(ä˺ʤ¤)dupclone̾Ǥ롥
+
+@item to_s
+
+֥Ȥʸɽ֤Υ᥽åɤŪprintformat
+åɤѤƤ롥
+
+@item to_a
+
+֥ȤѴ롥@code{Kernel}饹Ƥǥե
+ȤϡΥ֥ȼȤޤ1Ǥ֤
+@end ftable
+
+@xref{Kernel}
+
+@node Proc, Process, Object, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Proc
+
+ƥ졼Ϥ줿ƥ졼֥å³Ȥƥ֥Ȳ
+Ρ¹Ԥ륳ɤǤʤƥ(ѿ)ʤɤ¸롥
+֥å֥Ȥϡ@code{call}᥽åɤˤäơ줿ΤƱ
+Ķɾ뤳ȤǤ롥æ(@code{return},
+@code{break}, @code{continue}, @code{redo}, @code{retry})δĶ¸
+ʤΤǡ֥å֥ȤæФμ¹Ԥ㳰ȯ
+뤳Ȥˤʤ롥
+
+SuperClass: Object
+
+Methods:
+
+@ftable @code
+@item call(@var{arg}[,@dots{}])
+
+֥å¹Ԥ롥
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item new
+
+֥å롥@code{yield}¹ԤǤǤΥ᥽åɤ
+ƤФȡλǼ¹Ԥ٤ɤ򥳥ƥȤȤȤ߹
+֥(@code{Proc})롥
+@end ftable
+
+@xref{Object}
+
+@node Process, Range, Proc, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Process
+
+ץ˴ؤԤʤΥ⥸塼롥@code{Math}⥸塼
+ƱͤƤΥ᥽åɤðۥ᥽åɤȤƤ̾Υ᥽åɤȤƤȤ롥
+@code{Process}ϥץ֥ȤΥ饹ǤϤʤơץ
+᥽åɤޤȤ᤿ΤǤ뤳Ȥդ뤳ȡ
+
+Methods:
+Single Methods:
+
+@ftable @code
+@item egid
+
+ץθߤμ¸GID֤
+
+@item egid= @var{gid}
+
+ץθߤμ¸GID@var{gid}˥åȤ롥
+
+@item euid
+
+ץθߤμ¸UID֤
+
+@item euid= @var{uid}
+
+ץθߤμ¸UID@var{uid}˥åȤ롥
+
+@item getpgrp([@var{pid}])
+
+@var{pid}ǻꤵ줿ץ߽°Ƥץ롼פid
+֤@var{pid}ά@var{pid}0Ϳϸ߼¹ԤƤ
+ץоݤˤ롥
+
+@item getpriority(@var{which}, @var{who})
+
+@var{which}@var{who}ǻꤵץץ롼ס桼
+ߤ̤֤ͥܺ٤@samp{getpriority(2)}򻲾ȡProcess⥸塼
+ǤwhichȤƻǤ@var{PRIO_PROCESS}@var{PRIO_PGRP}
+@var{PRIO_USER}Ƥ롥
+
+@item gid
+
+ץθߤμGID֤
+
+@item gid= @var{gid}
+
+ץθߤμGIDgid˥åȤ.
+
+@item pid
+
+ץΥץID֤ϥƥѿ@code{$$}ͤƱǤ
+롥
+
+@item ppid
+
+ƥץΥץΥץID֤UNIXǤľܤοƥץλ
+硤ƥץpid1(initpid)ˤʤ롥
+
+@item setpgrp(@var{pid}, @var{pgrp})
+
+@var{pid}ǻꤵ줿ץΥץ롼פ@var{pgrp}ˤ롥
+@var{pid}0Ϳȸ߼¹Υץоݤˤ롥
+
+@item setpriority(@var{which}, @var{who}, @var{prio})
+
+@var{which}@var{who}ǻꤵץץ롼ס桼
+ߤ̤ͥ@var{prio}ꤹ롥ܺ٤@samp{setpriority(2)}
+ȤΤȡ
+
+@item uid
+
+ץθߤμUID֤
+
+@item uid= @var{uid}
+
+ץθߤμUID@var{uid}˥åȤ.
+@end ftable
+
+@node Range, Regexp, Process, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Range
+
+ϰϥ֥ȤΥ饹ϰϥ֥Ȥ@code{..}黻Ҥˤä
+졤ŪˤϰʲΤ褦ʻȤ򤹤
+
+@example
+for i in 1..5
+ @dots{}
+end
+@end example
+
+ξϰʲ®.
+
+@example
+1.upto(5) {
+ @dots{}
+}
+@end example
+
+ϰϥ֥Ȥ@code{..}黻Ҥξդ@code{Comparable}
+९饹Υ󥹥󥹤ǤвǤ⹽ʤϰϤϻȽޤळ
+Ȥդ뤳.
+
+SuperClass: Object
+
+Included Modules: Enumerable
+
+Methods:
+
+@ftable @code
+@item self =~ @var{other}
+
+@code{self}@var{other}Ʊ饹Фϰϥ֥Ȥǡ
+@var{other}(@code{start <= @var{other} <= end})
+@code{case}ϰϻꤹǤ롥㤨
+
+@example
+case i
+when 1, 3..5
+ @dots{}
+end case
+@end example
+
+Τ褦ʥɤ񤯤ȤǤ롥
+
+@item each
+
+ϰ¸ߤ륪֥ȤͿ륤ƥ졼@code{for}Τ
+Ѥ롥
+
+@item end
+
+ϰϤν֤
+
+@item start
+
+ϰϤλ֤
+@end ftable
+
+@xref{Object}
+@xref{Enumerable}
+
+@node Regexp, String, Range, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Regexp
+
+ɽΥ饹ɽΥƥ@code{/@dots{}/}Ȥɽ
+ưŪ뤿ˤ
+
+@example
+Regexp.new(ʸ)
+@end example
+
+Ȥ롥String饹@code{=~}ϤȤ¿Υ᥽åɤ
+ɽؤʸͿ줿ˤŪɽΤǡ
+Ȥ󤷤Ȼפ䡤ɽʸʸζ̤Ū
+˻ꤷʤɰʳŪȻפȤϾʤϤ
+
+SuperClass: Object
+
+Methods:
+
+@ftable @code
+@item self =~ @var{string}
+
+ɽʸ˥ޥå硤ޥå֤֤ޥåʤ
+@code{nil}֤
+
+@item ~ self
+
+@code{$_ =~ self}Ʊ
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item compile(@var{string}[, @var{casefold}])
+@itemx new(@var{string}[, @var{casefold}])
+
+ʸɽѴ֥Ȥ֤άǽ2Ϳ
+졤ͤ@code{nil}Ǥʤˤϡ줿ɽ֥Ȥ
+ƥѿ@code{$=}ͤ˴ؤ餺ޥåʸʸΰ㤤
+̵뤹롥
+
+@item quote(@var{str})
+
+ʸɽǰ̣ʸ򥨥פ롥ʸ
+
+@end ftable
+
+@xref{Object}
+
+@node String, Struct, Regexp, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section String
+
+ʸ󥯥饹Rubyʸϥ̥륿ߥ͡ȤǤϤʤΤǡХʥǡ
+ⰷ롥äƤɤ餫ȤñʤʸȤХǤ롥
+λۤ˴Ťơɽ˴ؤ᥽åɰʳ2byteϤʸռ
+ƤʤϺԤμȴǤϤʤտŪˤƤΤǤ(
+Ƥ)
+
+String饹Υ᥽åɤΤ@code{!}ǽΤϥ쥷Ф񤭴롥
+Ʊ̾@code{!}̵Τϥ쥷ФΥԡäƤ顤
+롥@code{!}ΤΤ®ͽ̷̤򾷤䤹
+ǡ̵ΤǤ롥
+
+@example
+f = "string"
+print f, sub("str", "ski"), f
+ @result{} string, skiing, string
+print f, sub!("str", "ski"), f
+ @result{} skiing, skiing, skiing
+@end example
+
+SuperClass: Object
+
+Included Modules: Comparable, Enumerable
+
+Methods:
+
+@ftable @code
+@item self + @var{other}
+
+ʸϢ롥Ϣ뤵줿ʸ֤
+
+@item self * @var{times}
+
+ʸη֤㤨@code{x" * 4 == "xxxx"}Ǥ롥
+
+@item self == @var{other}
+@item self > @var{other}
+
+ʸӡƥѿ@code{$=}@code{nil}Ǥʤˤʸʸ
+̤ӤԤʤ
+
+@item self =~ @var{other}
+
+ʸΥޥå@var{other}ɽʸ@var{other}ʸξ
+ˤưŪɽѴ롥ޥåϥޥå֡
+ä@code{nil}֤롥
+
+@item ~ self
+
+@code{$_ =~ self}Ʊ
+
+@item self[@var{nth}]
+@item self[@var{beg}..@var{end}]
+@item self[@var{beg}, @var{len}]
+
+ƤμФ1ܤηǤ@var{nth}ХܤΥǡFixnumȤ
+֤2ܤηǤ@var{beg}Хܤ@var{end}ХܤޤǤʬ
+ʸ֤(ξüޤ)3ܤηǤ@var{beg}Хܤ
+@var{len}Хʬʬʸ֤
+
+@item self[@var{nth}] = @var{val}
+@item self[@var{beg}..@var{end}] = @var{val}
+@item self[@var{beg}, @var{len}] = @var{val}
+
+Ƥι1ܤηǤ@var{nth}ХܤΥǡ@var{val}()
+ѹ롥2ܤη@var{beg}Хܤ@var{end}ХܤޤǤ
+ʬʸ@var{val}ȤͿ줿ʸ֤롥3ܤη
+@var{beg}Хܤ@var{len}Хʬʬʸ@var{val}ȤͿ
+줿ʸ֤롥
+
+@item capitalize
+@itemx capitalize!
+
+ʸκǽʸ(줬ե٥åȤǤ)ʸѴ
+ĤʸΥե٥åȤʸ֤롥
+
+@item chop
+@itemx chop!
+
+ʸκǸΥХȤڤȤʸѹ뤳Ȥդ뤳
+ȡ@code{chop!}ϸʸ򹹿롥
+
+@item crypt(@var{salt})
+
+@samp{crypt(3)}ѤưŹ沽ʸ֤@var{salt}2ХȰʾ
+ĹǤդʸǤ롥
+
+@item delete(@var{str})
+@itemx delete!(@var{str})
+
+ʸΤ@var{str}˴ޤޤʸ롥ʸλ
+@code{tr}ƱͤǤꡤ@code{a-b}@code{a}@code{b}ޤǤϰϤ
+Ƭ@code{^}ʸ(ޤޤƤʤΤ)̣롥
+
+@item dup
+
+@code{self}ƱƤʸ롥@code{clone}
+@code{freeze}֤⥳ԡ뤬@code{dup}Ƥʸ
+롥
+
+@item downcase
+@itemx downcase!
+
+ʸΥե٥åȤƾʸ֤ʸ֤
+@code{tr("A-Z", "a-z")}꾯®
+
+@item each @{|@var{char}|@dots{}@}
+@itemx each_byte @{|@var{char}|@dots{}@}
+
+ʸΤ줾ΥХȤˤĤƷ֤ƥ졼
+
+@item each_line @{|@var{line}|@dots{}@}
+
+ʸ󤫤1Ԥɤ߹Ǥ륤ƥ졼
+
+@item freeze
+
+ʸ򹹿ԲĤˤ롥ٹԲĤꤵ줿ʸƤѹ
+Ȥ㳰ȯ롥
+
+@item gsub(@var{pattern}, @var{replace})
+@itemx gsub(@var{pattern}) @{@dots{}@}
+@itemx gsub!(@var{pattern}, @var{replace})
+@itemx gsub!(@var{pattern}) @{@dots{}@}
+
+ʸ@var{pattern}˥ޥåʬ@var{replace}֤롥
+ִʸ@var{replace}@samp{&}@samp{\0}ϥޥåʸˡ
+@samp{\1@dots{}\9}nܤγ̤Ƥ֤롥
+@var{replace}ά줿ˤϥƥ졼Ȥư֥åɾ
+ִ̤롥
+
+@code{gsub}ִ줿ʸ֤(ִԤʤʤäϸʸ
+֤)@code{gsub!}ִԤʤ줿ˤоݤȤʤʸ
+Ԥʤʤäˤ@code{nil}֤
+
+@item hex
+
+ʸ16ʿɽʸȲᤷơѴ롥
+
+@item index(@var{substr}[, @var{pos}])
+
+@var{substr}ǽ˽и֤֤@var{pos}ͿȤΰ֤
+鸡򳫻Ϥ롥Ĥʤˤ@code{nil}֤
+
+@item intern
+
+ʸ˰դб֤ʸϥʥʸޤǤϤʤʤ
+
+@item length
+@itemx size
+
+ʸĹ(Хȿ)֤
+
+@item ljust(@var{width})
+@itemx rjust(@var{width})
+@itemx center(@var{width})
+
+ʸ򤽤줾졤ͤᡤͤᡤ󤻤@var{width}ʸ
+֤ʸĹ@var{width}Ĺϸʸ֤ڤͤ
+
+
+@item next
+
+@code{self}ΡּΡʸ֤ʸȤϿϿȤơ
+ʸϱʸȤä夬νԤʤ줿ΤǤ롥
+
+@example
+"aa".next @result{} "ab"
+"99".next @result{} "100"
+"a9".next @result{} "b0"
+@end example
+
+@item oct
+
+ʸ8ʿɽʸȲᤷơѴ롥8ʿ
+@code{/[0-7]+/}ǤꡤʸƬ餳Υѥ˥ޥåʬ
+Ѵ롥ƤϤޤʤʸФƤ0֤
+perlȤϰäʸ0xϤޤäƤ뤫Ȥä 16ʿȸʤ
+Ƥ줿ϤʤƬ08ʿǧ졤0֤
+
+@item reverse
+@itemx reverse!
+
+ʸγƥХȤս¤٤ʸ֤ʸ2ХȤǹ
+ʸޤǤƤ⤪ʤ˥Хñ̤ȿž롥@code{split}2
+Хʸ򤹤Τǡ2Хʸޤʸʸñ̤ȿž
+
+@example
+"ʸ".split(//).reverse.join("")
+@end example
+
+ȤФ褤
+
+@item rindex(@var{substr}[, @var{pos}])
+
+ʸ@var{substr}Ǹ˽и֤֤@var{pos}ͿȤ
+֤Ǹλ롥Ĥʤˤ@code{nil}֤@code{index}
+
+@itemize
+@item
+ʸ鸡롥
+@item
+substrȤɽդʤ
+@end itemize
+
+2Ǥ롥
+
+@item split([@var{sep}[, @var{limit}]])
+
+ʸ@var{sep}ǻꤵ줿ѥˤäơեɤʬ䤹롥
+@var{sep}ά줿ΥǥեȤϥƥѿ@code{$;}ͤѤ
+롥@var{limit}ꤵ줿ˤϺ@var{limit}ĤΥեɤʬ
+롥s@code{plit}ʬ䤵줿ʸޤ֤@var{sep}ǻ
+줿ѥ󤬶ʸȥޥåʸ1ʸĤʬ䤵
+롥
+
+@item squeeze([@var{str}])
+@itemx squeeze!([@var{str}])
+
+ʸΤ@var{str}˴ޤޤʸϢ³Ƥ硤ʸ˰
+롥@var{str}ά줿硤٤ƤʸоݤȤ롥ʸλ
+trƱͤǤꡤ@code{a-b}@code{a}@code{b}ޤǤϰϤƬ
+@code{^}ʸ(ޤޤƤʤΤ)̣롥
+
+@item strip
+@itemx strip!
+
+ʸζ
+
+@item sub(@var{pattern}, @var{replace})
+@itemx sub(@var{pattern}) @{@dots{}@}
+@itemx sub!(@var{pattern}, @var{replace})
+@itemx sub!(@var{pattern}) @{@dots{}@}
+
+ʸ@var{pattern}˥ޥåǽʬ@var{replace}֤롥
+ִʸ@var{replace}@samp{&}@samp{\0}ϥޥåʸˡ
+@samp{\1@dots{}\9} nܤγ̤Ƥ֤롥
+@var{replace}Τʤλˤϥƥ졼Ȥư֥åɾ
+ִ̤롥
+
+@code{sub}ִ줿ʸ֤(ִԤʤʤäϸʸ
+֤)@code{sub!}ִԤʤ줿ˤоݤȤʤʸ򡤹
+ʤʤäˤ@code{nil}֤
+
+@item sum([@var{bits}])
+
+ʸ@var{bits}ӥåȤΥå롥άͤ16Ǥ롥ruby
+ϰʲΥɤSystem V@code{sum}ץƱͤ롥
+
+@example
+while gets()
+ sum += $_.sum
+end
+sum %= 65536
+@end example
+
+@item swapcase
+@itemx swapcase!
+
+ʸΥե٥åȤΤʸʸˡʸʸ֤
+롥
+
+@item to_f
+
+ʸFloatѴ롥
+
+@item to_i
+
+ʸ10ʿɽʸȲᤷơѴ롥
+
+@item tr(@var{search}, @var{replace})
+@itemx tr!(@var{search}, @var{replace})
+
+ʸ@var{search}ʸ˴ޤޤʸ¸ߤС
+@var{replace}ʸбʸ֤롥@var{replace}ʸ󤬾
+ά줿϶ʸͿ줿ȸʤ@var{replace}ʸ
+@var{search}ʸû@var{replace}ʸκǸʸ
+֤Ƥȸʤ@var{search}ʸûˤбʸ
+ʤ@var{replace}ñ̵뤵(BSD@samp{tr}ư)
+
+@var{search}ʸ@var{replace}ʸ@code{a-b}Ȥ
+硤@code{a}@code{b}ޤǤϰϤʸASCIIξǻꤷ
+Ȥˤʤ롥ޤ@var{search}ʸκǽʸ@code{^}Ǥ硤
+³ʸ*ޤޤʤ*ʸִоݤˤʤ롥
+
+@samp{tr(1)}εǽΤʸ뵡ǽϢ³ʸ򰵽̤뵡
+ǽ̤Υ᥽åɤʬ䤵Ƥ롥εǽˤĤƤ@code{delete}
+@code{squeeze}򻲾ȤΤȡ
+
+ؤΤᡤ@code{str.tr(src,repl).squeeze(repl)}᥽å
+@code{tr_s(src,repl)}󶡤Ƥ롥
+
+@item unpack(@var{template})
+
+ʸ@var{template}ʸˤäƥѥåǤ
+֤@var{template}ʸArray饹pack᥽åɤȤۤƱ
+ͤǤ롥
+
+@display
+a ASCIIʸ(³nullʸ䥹ڡĤ)
+A ASCIIʸ(³nullʸ䥹ڡ)
+b ӥåȥȥ(̥ӥåȤ̥ӥå)
+B ӥåȥȥ(̥ӥåȤ鲼̥ӥå)
+h 16ʸ(̥˥֥뤬)
+H 16ʸ(̥˥֥뤬)
+c char
+C unsigned char
+s sort
+S unsigned sort
+i int
+I unsigned int
+l long
+L unsigned int
+n ͥåȥХȥshort
+N ͥåȥХȥlong
+f ñư(¸)
+d ư(¸)
+x 1ХɤФ
+X 1Хȸ
+@@ а֤ؤΰư
+@end display
+
+ruby@code{unpack}perlȰäƥåη׻ǽʤȤ
+դ뤳ȡ
+
+
+@item upcase
+@itemx upcase!
+
+ʸΥե٥åȤʸ֤ʸ֤
+@code{tr("a-z", "A-Z")}꾯®
+
+@item upto(@var{end}) @{@dots{}@}
+
+@code{self}Ϥޤäơ@var{end}ޤǡּΡʸͿ륤ƥ졼
+ʸȤ@code{str.next}ͿʸǤ롥
+
+Υ᥽åɤ@code{Range:each}ѤƤΤǡʲΤ褦ʽ
+ǽǤ롥
+
+@example
+for i in "a" .. "ba"
+ print(i, "\n");
+end
+@end example
+
+@samp{a, b, c,@dots{}aa,@dots{}az, ba}ޤǤƹԤ˽Ϥ롥
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item new(@var{string})
+
+@var{string}ƱƤĿʸ֤
+@end ftable
+
+@xref{Object}
+@xref{Enumerable}
+@xref{Comparable}
+
+@node Struct, Time, String, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Struct
+
+¤Υ饹Υ饹Υ֥饹ʣΥǡޤȤѤ
+(: @code{Time:times})ǡޤȤˤ󥯥饹Ѥ
+뤳Ȥ⤢뤬(: @code{select})¤ΤȤ٤ϰʲΤ褦
+Ǥ롥@code{Struct:new}@code{Struct}Υ֥饹򿷤
+ơ֤¤ΤϤΥ֥饹Υ󥹥󥹤Ȥʤ롥
+
+@enumerate
+@item
+Ǥο
+
+ǤοưΤϹ¤ΤȤΤˤϸʤ
+
+@item
+Ǥο¿
+
+ʹ֤٤ưפ˰복ǰο7ĤޤǤǤȤ⤬롥
+˽СǤ4İʾ夢ǡξѤ硤ǿ
+2(ĤޤꥪեåȤȤΰ̣)7ۤ롥äơΤ褦
+ˤϹ¤ΤȤä򤷤䤹Ȼפ롥
+
+@item
+Ʊ̤ʤ
+
+¤Τ㴳Ȥ⤤Τǡ®٤ˤʤ (㤨
+Ʊ̤ʤ)Ϲ¤ΤλѤŬڤǤʤǽ
+롥
+@end enumerate
+
+ƹ¤Τˤϥ̾Ʊ̾ΰΤʤ᥽åɤ롥
+
+ܥɥǡ¤Τɽ뤿ˤϰʲηȤ
+
+@display
+struct ¤̾
+ @dots{}
+end
+@end display
+
+ץǤηǹ¤Τ櫓ǤϤʤ
+
+SuperClass: Object
+
+Included Modules: Enumerable
+
+Methods:
+
+@ftable @code
+@item self[@var{idx}]
+
+@var{idx}λ@var{idx}ܤǤ֤
+
+@item values
+@itemx to_a
+
+¤ΤΥФͤǤ˻֤㤨аʲΥɤǼʬ
+passwdȥϤ뤳ȤǤ롥
+
+@example
+print(Etc.getpwuid().values.join(":"), "\n")
+@end example
+
+νϤ@samp{grep "$USER" /etc/passwd}νϤ;ʬʥեɤ
+Ĥ(ƥˤäưۤʤ)ʳƱǤ롥
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item new(@var{name}, @var{member}@dots{})
+
+@var{name}Ȥ̾ŤΤΥ饹롥@var{member_value}
+Ϲ¤ΤΥФɽʸǤ롥줿¤Υ饹ˤϥФ
+ꤵ줿̾Υ᥽åɤƤơΥ᥽åɤˤäƥФ
+Ƥ뤳ȤǤ롥
+@end ftable
+
+Single Methods for subclasses:
+
+@ftable @code
+@item new(@var{value}@dots{})
+
+¤Υ饹Υ󥹥󥹤롥@var{value}Ϲ¤ΤΥФ
+Ǥ롥Фο¤Υ饹줿Ȱۤʤˤ㳰ȯ
+롥
+@end ftable
+
+@xref{Object}
+@xref{Enumerable}
+
+@node Time, , Struct, Ȥ߹ߥ饹ȥ⥸塼
+@comment node-name, next, previous, up
+@section Time
+
+֤ɽ饹羮ӤʤɤǤ롥@code{Time.now}Ǹߤλ֤
+뤳ȤǤ롥ޤեΥॹפ᥽åɤͤ
+Υ饹Υ󥹥󥹤Ǥ롥
+
+SuperClass: Object
+
+Included Modules: Comparable
+
+Methods:
+
+@ftable @code
+@item self <=> @var{other}
+
+@var{other}TimeΥ󥹥󥹤Ϳ줿ˤ
+@samp{1970ǯ1 1 00:00:00 GMT}ÿǤȤƻȤӤ
+Ԥʤ
+
+@item asctime
+@itemx ctime
+@itemx to_s
+
+@samp{date(1)}ʸѴ롥
+
+@item gmtime
+
+ॾνԤʤʤGMTǤλ롥Υ᥽åɤȤ
+Time饹Υ󥹥󥹤ϡʸλѴGMTǹԤʤ
+@code{gmtime}ϼʬȤ֤
+
+ɥλɽˤ@code{print(Time.now.gmtime, "\n")}Ȥ
+Ф褤
+
+@item localtime
+
+ॾνԤʤä(ǥե)@code{localtime}
+ʬȤ֤
+
+@item to_i
+@itemx tv_sec
+
+@samp{1970ǯ 1 1 00:00:00 GMT}ޤǤÿ֤
+secondʬǤ⤢롥
+
+@item sec
+@itemx min
+@itemx hour
+@itemx mday
+@itemx year
+@itemx wday
+@itemx yday
+@itemx zone
+@itemx isdst
+
+ŪݻƤ@code{tm}¤ΤƤ֤@code{zone}ʳ
+֤@code{zone}ϥॾɽʸ֤(cf
+@samp{localtime(3)})
+
+@item strftime(@var{format})
+
+@var{format}ʸ˽äʸѴ̤֤
+@var{format}ʸȤƻǤΤ ʲ̤Ǥ롥
+
+@display
+%A ̾(Sunday, Monday@dots{})
+%a ξά̾(Sun, Mon@dots{})
+%B ̾(January, February@dots{})
+%b ξά̾(Jan, Feb@dots{})
+%c ɽ(cf @samp{ctime(3)})
+%d ʿǤ(01-31)
+%H 24λ(00-23)
+%I 12λ(01-12)
+%j ǯ̻(001-366)
+%M ʬ(00-59)
+%m ɽ(01-12)
+%p ޤϸ(AM,PM)
+%S (00-61)
+%U ɽǽ1
+ Ϥޤ(00-53)
+%W ɽǽη1
+ Ϥޤ(00-53)
+%w ɽ0(0-6)
+%X (: 15:01:06)
+%x (: Fri Jan 14 1994)
+%Y ɽ
+%y β2(00-99)
+%Z ॾ
+%% %
+@end display
+
+@item usec
+@itemx tv_usec
+
+micro secondʬ֤
+@end ftable
+
+Single Methods:
+
+@ftable @code
+@item now
+
+ߤλɽ@code{Time}饹Υ󥹥󥹤롥
+
+@item at(@var{time})
+
+@var{time}Ʊɽ@code{Time}饹Υ󥹥󥹤롥
+@var{time}@code{Time}饹Υ󥹥󥹤뤤Ͽ(/ư
+)Ǥꡤξ@samp{1970ǯ 1 1 00:00:00 GMT}ÿ
+Ȥƻ׻롥
+
+@item times
+
+ߤΥץȤλҥץ񤷤桼/ƥCPUѻ
+¤ΤȤ֤(@xref{Struct})
+
+@display
+struct tms
+ utime # ץΥ桼
+ stime # ץΥƥ
+ cutime # ҥץΥ桼
+ cstime # ҥץΥƥ
+end
+@end display
+
+֤ñ̤äǤꡤưͿ롥ܺ٤@samp{times(3)}
+򻲾ȤΤȡ
+@end ftable
+
+@xref{Object}
+@xref{Comparable}
+
+@node CȤΥ󥿥ե, ռ, Ȥ߹ߥ饹ȥ⥸塼, Top
+@comment node-name, next, previous, up
+@chapter CȤΥ󥿥ե
+
+rubyCȤΥ󥿡ե󶡤C줫Υ饹⥸塼
+CǵҤ᥽åɤrubyΥ᥽åɤθƤӽФ
+졼θƤӽФ㳰ʤɤԤʤȤ롥ޤOSм
+ԻCǽ񤫤줿⥸塼ɤ뤳Ȥ롥
+
+Ūʥ󥿥ե˴ؤƤϡ̥ɥ(źեե C-IF)
+ȤΤȡ
+
+@node ռ, ʸˡ, CȤΥ󥿥ե, Top
+@comment node-name, next, previous, up
+@chapter ռ
+
+RubyθͤϿ¿θαƶƤ롥ʲˤΤϤμ
+ʸǤ롥
+
+ C, Perl, CLU, Sather, CLOS, Eiffel, Icon, tcl, AWK, bourne shell,
+ Smalltalk, Emacs Lisp.
+
+ޤrubyθͤꤹ뤿˶ϤƲäʲˤ롥
+
+ ͷƣϺ¼Σţáغܣģţá
+ ʤֺ.ٻ(ɾά)
+
+@node ʸˡ, Variables Index, ռ, Top
+@comment node-name, next, previous, up
+@chapter ʸˡ
+
+ʲϵBNFǵҤrubyʸˡǤ롥ΤʵҤparse.y򻲾
+줿
+
+@example
+PROGRAM : COMPEXPR
+
+COMPEXPR : EXPR (TERM EXPR)* [TERM]
+
+EXPR : MLHS `=' ARGS
+ | return ARGS
+ | fail ARGS
+ | yield ARGS
+ | defined? ARG
+ | identifier CALL_ARGS0
+ | PRIMARY `.' identifier CALL_ARGS0
+ | super CALL_ARGS
+ | undef FNAME
+ | alias FNAME FNAME
+ | include identifier (`,' identifier)*
+ | EXPR if EXPR
+ | EXPR while EXPR
+ | EXPR and EXPR
+ | EXPR or EXPR
+ | ASSOCS
+ | ARG
+
+ARG : LHS `=' ARG
+ | LHS OP_ASGN ARG
+ | ARG `..' ARG
+ | ARG `...' ARG
+ | ARG `+' ARG
+ | ARG `-' ARG
+ | ARG `*' ARG
+ | ARG `/' ARG
+ | ARG `%' ARG
+ | ARG `**' ARG
+ | `+' ARG
+ | `-' ARG
+ | ARG `|' ARG
+ | ARG `^' ARG
+ | ARG `&' ARG
+ | ARG `<=>' ARG
+ | ARG `>' ARG
+ | ARG `>=' ARG
+ | ARG `<' ARG
+ | ARG `<=' ARG
+ | ARG `==' ARG
+ | ARG `!=' ARG
+ | ARG `=~' ARG
+ | ARG `!~' ARG
+ | `!' ARG
+ | `~' ARG
+ | ARG `<<' ARG
+ | ARG `>>' ARG
+ | ARG `&&' ARG
+ | ARG `||' ARG
+ | ARG `::' identifier
+ | PRIMARY
+
+PRIMARY : `(' COMPEXPR `)'
+ | LITERAL
+ | VARIABLE
+ | super `(' [CALL_ARGS] `)'
+ | super
+ | PRIMARY `[' [ARGS] `]'
+ | `[' [ARGS [`,']] `]'
+ | `@{' [ (ARGS|ASSOCS) [`,'] ] `@}'
+ | redo
+ | break
+ | continue
+ | retry
+ | return
+ | fail [`(' [ARGS] `)']
+ | yield [`(' [ARGS] `)']
+ | defined? `(' ARG `)'
+ | PRIMARY `@{' [`|' [ITER_VAR] `|'] COMPEXPR `@}'
+ | OPERATION `(' [CALL_ARGS] `)'
+ | PRIMARY `.' OPERATION `(' [CALL_ARGS] `)'
+ | PRIMARY `.' OPERATION
+ | if EXPR THEN
+ COMPEXPR
+ (elsif EXPR THEN COMPEXPR)*
+ [else COMPEXPR]
+ end
+ | while EXPR TERM COMPEXPR end
+ | case COMPEXPR
+ (when ARGS THEN)+
+ [else COMPEXPR]
+ end
+ | for ITER_VAR in EXPR TERM
+ COMPEXPR
+ end
+ | begin
+ COMPEXPR
+ [rescue COMPEXPR]
+ [ensure COMPEXPR]
+ end
+ | class identifier `:' identifier
+ COMPEXPR
+ end
+ | module identifier
+ COMPEXPR
+ end
+ | def FNAME ARGLIST
+ COMPEXPR
+ end
+ | def SINGLETON `.' FNAME ARGLIST
+ COMPEXPR
+ end
+
+THEN : TERM
+ | then
+ | TERM then
+
+ITER_VAR : LHS
+ | MLHS
+
+MLHS : LHS `,' [LHS (`,' LHS)*] [`*' LHS]
+
+LHS : VARIABLE
+ | PRIMARY `[' [ARGS] `]'
+ | PRIMARY `.' identifier
+
+CALL_ARGS : ARGS
+ | ASSOCS
+ | ARGS [`,' ASSOCS] [`,' `*' ARG]
+ | `*' ARG
+
+ARGS : ARG (`,' ARG)*
+
+ARGLIST : `('[identifier(`,'identifier)*][`*'identifier]`)'
+ | TERM
+
+SINGLETON : VARIABLE
+ | `(' EXPR `)'
+
+ASSOCS : ASSOC (`,' ASSOC)*
+
+ASSOC : ARG `=>' ARG
+
+VARIABLE : VARNAME
+ | nil
+ | self
+ | `__FILE__'
+ | `__LINE__'
+
+LITERAL : numeric
+ | SYMBOL
+ | STRING
+ | REGEXP
+
+TERM : `;'
+ | `\n'
+
+@end example
+
+겼ϻǧ롥
+
+@example
+
+SYMBOL : `:'FNAME
+ | `:'VARNAME
+
+FNAME : identifier | `..' | `|' | `^' | `&'
+ | `<=>' | `==' | `=~' | `>' | `>=' | `<' | `<='
+ | `<<' | `>>' | `+' | `-' | `*' | `/' | `%' | `**'
+ | `~' | `+@@' | `-@@' | `[]' | `[]='
+
+OPERATION : identifier
+ | identifier'!'
+ | identifier'?'
+
+VARNAME : GLOBAL
+ | `@@'identifier
+ | identifier
+
+GLOBAL : `$'identifier
+ | `$'any_char
+
+STRING : `"' any_char* `"'
+ | `'' any_char* `''
+ | ``' any_char* ``'
+
+REGEXP : `/' any_char* `/'[i]
+
+@end example
+
+@node Variables Index, Concept Index, Function Index, Top
+@comment node-name, next, previous, up
+@unnumbered Variable Index
+
+@printindex vr
+
+@node Concept Index, Function Index , Variables Index, Top
+@comment node-name, next, previous, up
+@unnumbered Concept Index
+
+@printindex cp
+
+@node Function Index, Top , Concept Index, Top
+@comment node-name, next, previous, up
+@unnumbered Function Index
+
+@printindex fn
+
+@summarycontents
+@contents
+@bye
+
+Local variables:
+fill-column: 70
+end:
diff --git a/sample/MANIFEST b/sample/MANIFEST
deleted file mode 100644
index 93c971b114..0000000000
--- a/sample/MANIFEST
+++ /dev/null
@@ -1,63 +0,0 @@
-MANIFEST
-aset.rb
-attr.rb
-biorhythm.rb
-blk.rb
-case.rb
-cat.rb
-cat2.rb
-cbreak.rb
-clnt.rb
-clone.rb
-const.rb
-dbm.rb
-dir.rb
-evaldef.rb
-export.rb
-exyacc.rb
-fib.awk
-fib.pl
-fib.rb
-fib.scm
-freq.rb
-from.rb
-fullpath.pl
-fullpath.rb
-gctest.rb
-gctest2.rb
-getopts.rb
-getopts.test
-hash.rb
-io.rb
-less.rb
-list.rb
-list2.rb
-list3.rb
-math.rb
-mpart.rb
-occur.pl
-occur.rb
-occur2.rb
-opt_s.rb
-opt_x.test
-parsearg.rb
-rcs.awk
-rcs.dat
-rcs.rb
-ruby-mode.el
-samp.rb
-sieve.rb
-split.rb
-struct.rb
-svr.rb
-system.rb
-t1.rb
-t2.rb
-test.rb
-time.rb
-trap.pl
-trap.rb
-trojan.pl
-trojan.rb
-tt.rb
-uumerge.rb
diff --git a/sample/aset.rb b/sample/aset.rb
deleted file mode 100644
index 414c13ba70..0000000000
--- a/sample/aset.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# array set example
-# output:
-# 07045
-
-ary = [0, 0, 4, 5]
-ary[1, 0] = [7]
-print ary, "\n"
diff --git a/sample/attr.rb b/sample/attr.rb
deleted file mode 100644
index 1d329ea06a..0000000000
--- a/sample/attr.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# attribute access example
-# output:
-# 10
-# #<Foo: @test=10>
-
-class Foo
- attr "test", TRUE
-end
-
-foo = Foo.new
-foo.test = 10
-print foo.test, "\n"
-foo._inspect.print
-print "\n"
diff --git a/sample/blk.rb b/sample/blk.rb
deleted file mode 100644
index e11cc026ea..0000000000
--- a/sample/blk.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-def foo()
- $block = Block.new
-end
-
-foo(){|i| print "i = ", i, "\n"}
-$block.call(2)
-
-foo(){|i| print "i*2 = ", i*2, "\n"}
-$block.call(2)
diff --git a/sample/case.rb b/sample/case.rb
deleted file mode 100644
index e844cddfd6..0000000000
--- a/sample/case.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# case statement example
-# output:
-# 3..5
-
-case "t"
-when /1/
- print 1, "\n"
-when /t/
- print 3..5, "\n"
-when /./
- print 2, "\n"
-else
- print "else\n"
-end
diff --git a/sample/cat.rb b/sample/cat.rb
deleted file mode 100644
index a3243d308d..0000000000
--- a/sample/cat.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# cat -n & `...' operator test
-while gets()
- if $. == 1 ... ~ /^\*/; print("--") end
- printf("%5d: %s", $., $_)
-end
diff --git a/sample/cat2.rb b/sample/cat2.rb
deleted file mode 100644
index bbc1ebb0ff..0000000000
--- a/sample/cat2.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# cat -n & `...' operator test
-while gets()
- if 1 ... /^\*/; print("--") end
- printf("%5d: %s", $., $_)
-end
diff --git a/sample/clnt.rb b/sample/clnt.rb
index d2c71ec563..c8c4b2db9f 100644
--- a/sample/clnt.rb
+++ b/sample/clnt.rb
@@ -1,5 +1,8 @@
# socket example - client side
# usage: ruby clnt.rb [host] port
+
+require "socket"
+
host=(if $ARGV.length == 2; $ARGV.shift; else "localhost"; end)
print("Trying ", host, " ...")
STDOUT.flush
diff --git a/sample/clone.rb b/sample/clone.rb
deleted file mode 100644
index e7d6b00a31..0000000000
--- a/sample/clone.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# object cloning & single method test
-# output:
-# test2
-# test
-# test
-# clone.rb:18: undefined method `test2' for "#<Object: 0xbfca4>"(Object)
-foo = Object.new
-def foo.test
- print("test\n")
-end
-bar = foo.clone
-def bar.test2
- print("test2\n")
-end
-bar.test2
-bar.test
-foo.test
-foo.test2
diff --git a/sample/const.rb b/sample/const.rb
deleted file mode 100644
index 50780407b8..0000000000
--- a/sample/const.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# constant access test
-# output:
-# 1234
-# 1268
-TEST1 = 1
-TEST2 = 2
-
-module Const
- TEST3 = 3
- TEST4 = 4
-end
-
-module Const2
- TEST3 = 6
- TEST4 = 8
-end
-
-include Const
-
-print(TEST1,TEST2,TEST3,TEST4,"\n")
-
-include Const2
-
-print(TEST1,TEST2,TEST3,TEST4,"\n")
diff --git a/sample/dbm.rb b/sample/dbm.rb
index a2e0659bf5..c77cc2065b 100644
--- a/sample/dbm.rb
+++ b/sample/dbm.rb
@@ -1,4 +1,6 @@
# ruby dbm acess
+require "dbm"
+
d = DBM.open("test")
keys = d.keys
if keys.length > 0 then
diff --git a/sample/exyacc.rb b/sample/exyacc.rb
index cd1170feb4..dafcb037cc 100644
--- a/sample/exyacc.rb
+++ b/sample/exyacc.rb
@@ -8,15 +8,15 @@ while gets()
sbeg = $_.index("\n%%") + 1
send = $_.rindex("\n%%") + 1
$_ = $_[sbeg, send-sbeg]
- sub(/.*\n/, "")
- gsub(/'{'/, "'\001'")
- gsub(/'}'/, "'\002'")
- gsub('\*/', "\003\003")
- gsub("/\\*[^\003]*\003\003", '')
- while gsub(/{[^}{]*}/, ''); end
- gsub(/'\001'/, "'{'")
- gsub(/'\002'/, "'}'")
- while gsub(/^[ \t]*\n(\s)/, '\1'); end
- gsub(/([:|])[ \t\n]+(\w)/, '\1 \2')
+ sub!(/.*\n/, "")
+ gsub!(/'{'/, "'\001'")
+ gsub!(/'}'/, "'\002'")
+ gsub!('\*/', "\003\003")
+ gsub!("/\\*[^\003]*\003\003", '')
+ while gsub!(/{[^}{]*}/, ''); end
+ gsub!(/'\001'/, "'{'")
+ gsub!(/'\002'/, "'}'")
+ while gsub!(/^[ \t]*\n(\s)/, '\1'); end
+ gsub!(/([:|])[ \t\n]+(\w)/, '\1 \2')
print $_
end
diff --git a/sample/from.rb b/sample/from.rb
index f21b1d10f5..2f5fcebe12 100755
--- a/sample/from.rb
+++ b/sample/from.rb
@@ -1,97 +1,10 @@
#! /usr/local/bin/ruby
-module ParseDate
- MONTHS = {
- 'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4,
- 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8,
- 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12 }
- MONTHPAT = MONTHS.keys.join('|')
- DAYPAT = 'mon|tue|wed|thu|fri|sat|sun'
-
- def parsedate(date)
- if date.sub(/(#{DAYPAT})/i, ' ')
- dayofweek = $1
- end
- if date.sub(/\s+(\d+:\d+(:\d+)?)/, ' ')
- time = $1
- end
- if date =~ /19(\d\d)/
- year = $1
- end
- if date.sub(/\s*(\d+)\s+(#{MONTHPAT})\S*\s+/i, ' ')
- dayofmonth = $1
- monthname = $2
- elsif date.sub(/\s*(#{MONTHPAT})\S*\s+(\d+)\s+/i, ' ')
- monthname = $1
- dayofmonth = $2
- elsif date.sub(/\s*(#{MONTHPAT})\S*\s+(\d+)\D+/i, ' ')
- monthname = $1
- dayofmonth = $2
- elsif date.sub(/\s*(\d\d?)\/(\d\d?)/, ' ')
- month = $1
- dayofmonth = $2
- end
- if monthname
- month = MONTHS[monthname.tolower]
- end
- if ! year && date =~ /\d\d/
- year = $&
- end
- return year, month, dayofmonth
- end
-
-end
+require "parsedate"
+require "base64"
include ParseDate
-def decode64(str)
- e = -1;
- c = ","
- for line in str.split("\n")
- line.tr 'A-Za-z0-9+/', "\000-\377"
- line.each_byte { |ch|
- e+=1
- if e==0
- c = ch << 2
- elsif e==1
- c |= ch >>4
- string += [c].pack('c')
- c = ch << 4
- elsif e == 2
- c |= ch >> 2
- string += [c].pack('c');
- c = ch << 6
- elsif e==3
- c |= ch
- string += [c].pack('c')
- e = -1;
- end
- }
- end
- return string;
-end
-
-def j2e(str)
- while str =~ /\033\$B([^\033]*)\033\(B/
- s = $1
- pre, post = $`, $'
- s.gsub(/./) { |ch|
- (ch[0]|0x80).chr
- }
- str = pre + s + post
- end
- str
-end
-
-def decode_b(str)
- while str =~ /=\?ISO-2022-JP\?B\?(.*)=\?=/
- pre, post = $`, $'
- s = decode64($1)
- str = pre + s + post
- end
- j2e(str)
-end
-
if $ARGV[0] == '-w'
wait = TRUE
$ARGV.shift
@@ -100,7 +13,7 @@ end
class Mail
def Mail.new(f)
- if !f.is_kind_of(IO)
+ if !f.is_kind_of?(IO)
f = open(f, "r")
me = super
f.close
@@ -114,9 +27,9 @@ class Mail
@header = {}
@body = []
while f.gets()
- $_.chop
+ $_.chop!
continue if /^From / # skip From-line
- break if /^[ \t]*$/ # end of header
+ break if /^$/ # end of header
if /^(\S+):\s*(.*)/
@header[attr = $1.capitalize] = $2
elsif attr
@@ -149,17 +62,18 @@ $outcount = 0;
def fromout(date, from, subj)
return if !date
y = m = d = 0
+ esc = "\033\(B"
y, m, d = parsedate(date) if date
from = "sombody@somewhere" if ! from
subj = "(nil)" if ! subj
from = decode_b(from)
subj = decode_b(subj)
- printf "%-02d/%02d/%02d [%-28.28s] %-40.40s\n", y, m, d, from, subj
+ printf "%-02d/%02d/%02d [%-28.28s%s] %-40.40s%s\n",y,m,d,from,esc,subj,esc
$outcount += 1
end
for file in $ARGV
- continue if !File.exists(file)
+ continue if !File.exists?(file)
f = open(file, "r")
while !f.eof
mail = Mail.new(f)
diff --git a/sample/gctest.rb b/sample/gctest.rb
deleted file mode 100644
index 6810b95481..0000000000
--- a/sample/gctest.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# GC stress test
-def cons(car, cdr)
- [car, cdr]
-end
-
-def car(x)
- if x == nil ; nil else x[0] end
-end
-
-def cdr(x)
- if x == nil ; nil else x[1] end
-end
-
-def reverse1(x, y)
- if x == nil ; y else reverse1(cdr(x), cons(car(x), y)) end
-end
-
-def reverse(x)
- reverse1(x, nil)
-end
-
-def ints(low, up)
- if low > up
- nil
- else
- cons(low, ints(low+1, up))
- end
-end
-
-def print_int_list(x)
- if x == nil
- print("NIL\n")
- else
- print(car(x))
- if nil != cdr(x)
- print(", ")
- print_int_list(cdr(x))
- else
- print("\n")
- end
- end
-end
-
-print("start\n")
-
-a = ints(1, 100)
-print_int_list(a)
-b = ints(1, 50)
-print_int_list(b)
-print_int_list(reverse(a))
-print_int_list(reverse(b))
-for i in 1 .. 100
- b = reverse(reverse(b))
-# print(i, ": ")
-# print_int_list(b)
-end
-print("a: ")
-print_int_list(a)
-print("b: ")
-print_int_list(b)
-print("reverse(a): ")
-print_int_list(reverse(a))
-print("reverse(b): ")
-print_int_list(reverse(b))
-a = b = nil
-print("finish\n")
-GC.start()
diff --git a/sample/gctest2.rb b/sample/gctest2.rb
deleted file mode 100644
index 851d14f217..0000000000
--- a/sample/gctest2.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# GC stress test
-def cons(car, cdr)
- car::cdr
-end
-
-def car(x)
- x.car
-end
-
-def cdr(x)
- x.cdr
-end
-
-def reverse1(x, y)
- if x == nil then
- y
- else
- reverse1(cdr(x), cons(car(x), y))
- end
-end
-
-def reverse(x)
- reverse1(x, nil)
-end
-
-def ints(low, up)
- if low > up
- nil
- else
- cons(low, ints(low+1, up))
- end
-end
-
-def print_int_list(x)
- if x == nil
- print("NIL\n")
- else
- print(car(x))
- if cdr(x)
- print(", ")
- print_int_list(cdr(x))
- else
- print("\n")
- end
- end
-end
-
-print("start\n")
-
-a = ints(1, 100)
-print_int_list(a)
-b = ints(1, 50)
-print_int_list(b)
-print_int_list(reverse(a))
-print_int_list(reverse(b))
-for i in 1 .. 100
- b = reverse(reverse(b))
-# print(i, ": ")
-# print_int_list(b)
-end
-print("a: ")
-print_int_list(a)
-print("b: ")
-print_int_list(b)
-print("reverse(a): ")
-print_int_list(reverse(a))
-print("reverse(b): ")
-print_int_list(reverse(b))
-a = b = nil
-print("finish\n")
-GC.start()
diff --git a/sample/hash.rb b/sample/hash.rb
deleted file mode 100644
index 85f719e7eb..0000000000
--- a/sample/hash.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# hash value
-# output:
-# 78651
-# 78651
-# 78651
-# -45637
-
-print(+-1.0.hash,"\n")
-print(-1.0.hash,"\n")
-print((-1.0).hash,"\n")
-print(-(1.0.hash),"\n")
diff --git a/sample/list3.rb b/sample/list3.rb
index 2c1beb6fa2..1d756fdff0 100644
--- a/sample/list3.rb
+++ b/sample/list3.rb
@@ -1,5 +1,5 @@
# Linked list example -- short version
-# using _inspect
+# using inspect
class Point
def initialize(x, y)
@@ -14,5 +14,5 @@ end
list1 = [10, 20, Point.new(2, 3), Point.new(4, 5)]
list2 = [20, Point.new(4, 5), list1]
-print("list1: ", list1._inspect, "\n")
-print("list2: ", list2._inspect, "\n")
+print("list1: ", list1.inspect, "\n")
+print("list2: ", list2.inspect, "\n")
diff --git a/sample/marshal.rb b/sample/marshal.rb
new file mode 100644
index 0000000000..3d399ffe68
--- /dev/null
+++ b/sample/marshal.rb
@@ -0,0 +1,13 @@
+require "marshal"
+include Marshal
+a = 25.6;
+pt = Struct.new('point', :x,:y);
+x = pt.new(10, 10)
+y = pt.new(20, 20)
+rt = Struct.new('rectangle', :origin,:corner);
+z = rt.new(x, y)
+c = Object.new
+s = [a, x, z, c, c, "fff"];
+print s.inspect;
+d = dumps(s);
+print load(d).inspect
diff --git a/sample/math.rb b/sample/math.rb
deleted file mode 100644
index c0b5225080..0000000000
--- a/sample/math.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# math example
-include Math
-sqrt(4)
-print(Math.sqrt(257), "\n")
diff --git a/sample/mkproto.rb b/sample/mkproto.rb
new file mode 100644
index 0000000000..1d9c9faccb
--- /dev/null
+++ b/sample/mkproto.rb
@@ -0,0 +1,27 @@
+$/ = nil
+while gets()
+ if /^((void|VALUE|int|char *\*|ID|struct [\w_]+ *\*|st_table *\*) *)?\n([\w\d_]+)\(.*\)\n\s*((.+;\n)*){/
+ $_ = $'
+ printf "%s %s(", $2, $3
+ args = []
+ for arg in $4.split(/;\n\s*/)
+ arg.gsub! ' +', ' '
+ if arg =~ /,/
+ if arg =~ /(([^*]+) *\** *[\w\d_]+),/
+ type = $2.strip!
+ args.push $1.strip!
+ arg = $'
+ else
+ type = ""
+ end
+ while arg.sub!(/(\** *[\w\d_]+)(,|$)/, "")
+ args.push type + " " + $1.strip!
+ end
+ else
+ args.push arg.strip!
+ end
+ end
+ printf "%s);\n", args.join(', ')
+ redo
+ end
+end
diff --git a/sample/occur2.rb b/sample/occur2.rb
index 8cd5acbe5e..c450c30b0f 100644
--- a/sample/occur2.rb
+++ b/sample/occur2.rb
@@ -5,7 +5,7 @@ while gets()
for word in $_.split(/\W+/)
begin
freq[word] = freq[word] + 1
- resque
+ rescue
freq[word] = 1
end
end
diff --git a/sample/opt_s.rb b/sample/opt_s.rb
deleted file mode 100644
index 56ff0eea15..0000000000
--- a/sample/opt_s.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-#! ./ruby -s
-# test for option `-s'
-
-if ($xyz)
- print("xyz = TRUE\n")
-end
-if ($zzz)
- print("zzz = ", $zzz, "\n")
-end
-if ($ARGV.length > 0)
- print($ARGV.join(", "), "\n")
-end
diff --git a/sample/opt_x.test b/sample/opt_x.test
deleted file mode 100644
index 47a67f6cfa..0000000000
--- a/sample/opt_x.test
+++ /dev/null
@@ -1,10 +0,0 @@
-test for option `-x'
-
-this is a forwarding header
-this is a header too.
-
-from here script starts
-#! ./ruby -v
-print("tt\n")
-__END__
-this is a trailer
diff --git a/sample/rcs.rb b/sample/rcs.rb
index faa4606788..13476267b2 100644
--- a/sample/rcs.rb
+++ b/sample/rcs.rb
@@ -16,7 +16,7 @@ while gets()
s = "";
while xr < hdw
x = xr * (1 + y) - y * w / 2
- i = (x / (1 + h) + sw /2)
+ i = (x / (1 + h) + sw / 2)
if (1 < i && i < $_.length);
c = $_[i, 1].to_i
else
diff --git a/sample/ruby-mode.el b/sample/ruby-mode.el
index bcbbdc35f3..b555994fea 100644
--- a/sample/ruby-mode.el
+++ b/sample/ruby-mode.el
@@ -12,21 +12,24 @@
)
(defconst ruby-block-mid-re
- "else\\|elsif\\|when\\|resque\\|ensure"
+ "then\\|else\\|elsif\\|when\\|rescue\\|ensure"
)
(defconst ruby-block-end-re "end")
(defconst ruby-delimiter
- (concat "[$/<(){}#\"'`]\\|\\[\\|\\]\\|\\b\\("
- ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\b")
+ (concat "[?$/(){}#\"'`]\\|\\[\\|\\]\\|\\<\\("
+ ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\>")
)
(defconst ruby-negative
(concat "^[ \t]*\\(\\b\\(" ruby-block-mid-re "\\)\\|\\("
- ruby-block-end-re "\\)\\b\\|\\}\\|\\]\\)")
+ ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)")
)
+(defconst ruby-operator-chars "[,.+*/%-&|^~=<>:]")
+(defconst ruby-symbol-chars "[a-zA-Z0-9_]")
+
(defvar ruby-mode-abbrev-table nil
"Abbrev table in use in ruby-mode buffers.")
@@ -53,17 +56,16 @@
(setq ruby-mode-syntax-table (make-syntax-table))
(modify-syntax-entry ?\' "\"" ruby-mode-syntax-table)
(modify-syntax-entry ?\" "\"" ruby-mode-syntax-table)
-;;(modify-syntax-entry ?\n ">" ruby-mode-syntax-table)
-;;(modify-syntax-entry ?\f ">" ruby-mode-syntax-table)
(modify-syntax-entry ?# "<" ruby-mode-syntax-table)
- (modify-syntax-entry ?$ "/" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\n ">" ruby-mode-syntax-table)
(modify-syntax-entry ?\\ "'" ruby-mode-syntax-table)
- (modify-syntax-entry ?_ "w" ruby-mode-syntax-table)
+ (modify-syntax-entry ?$ "/" ruby-mode-syntax-table)
+ (modify-syntax-entry ?? "/" ruby-mode-syntax-table)
+ (modify-syntax-entry ?_ "_" ruby-mode-syntax-table)
(modify-syntax-entry ?< "." ruby-mode-syntax-table)
(modify-syntax-entry ?> "." ruby-mode-syntax-table)
(modify-syntax-entry ?& "." ruby-mode-syntax-table)
(modify-syntax-entry ?| "." ruby-mode-syntax-table)
- (modify-syntax-entry ?$ "." ruby-mode-syntax-table)
(modify-syntax-entry ?% "." ruby-mode-syntax-table)
(modify-syntax-entry ?= "." ruby-mode-syntax-table)
(modify-syntax-entry ?/ "." ruby-mode-syntax-table)
@@ -152,6 +154,19 @@ The variable ruby-indent-level controls the amount of indentation.
(indent-to x)
(if (> p 0) (forward-char p)))))
+(defun ruby-expr-beg ()
+ (save-excursion
+ (skip-chars-backward " \t")
+ (or (bolp) (forward-char -1))
+ (or (looking-at ruby-operator-chars)
+ (looking-at "[\\[({]")
+ (bolp)
+ (and (looking-at ruby-symbol-chars)
+ (forward-word -1)
+ (or
+ (looking-at ruby-block-beg-re)
+ (looking-at ruby-block-mid-re))))))
+
(defun ruby-parse-region (start end)
(let ((indent-point end)
(indent 0)
@@ -163,113 +178,97 @@ The variable ruby-indent-level controls the amount of indentation.
(if start
(goto-char start)
(ruby-beginning-of-defun))
- (while (and (> indent-point (point))
- (re-search-forward ruby-delimiter indent-point t))
- (let ((w (buffer-substring (match-beginning 0) (match-end 0)))
- (pnt (match-beginning 0)))
- (cond
- ((or (string= "\"" w) ;skip string
- (string= "'" w)
- (string= "`" w))
- (cond
- ((string= w (char-to-string (char-after (point))))
- (forward-char 1))
- ((re-search-forward (format "[^\\]%s" w) indent-point t)
+ (save-restriction
+ (narrow-to-region (point) end)
+ (while (and (> indent-point (point))
+ (re-search-forward ruby-delimiter indent-point t))
+ (let ((pnt (point)) w)
+ (goto-char (match-beginning 0))
+ (cond
+
+ ((or (looking-at "\"") ;skip string
+ (looking-at "'")
+ (looking-at "`"))
+ (setq w (char-after (point)))
+ (cond
+ ((and (not (eobp))
+ (equal w (char-after (point)))
+ (re-search-forward (format "[^\\]%c" w) indent-point t))
nil)
- (t
- (goto-char indent-point)
- (setq in-string t))))
- ((or (string= "/" w)
- (string= "<" w))
- (if (string= "<" w) (setq w ">"))
- (let (c)
- (save-excursion
- (goto-char pnt)
- (skip-chars-backward " \t")
- (setq c (char-after (1- (point))))
- (if c
- (setq c (char-syntax c))))
+ (t
+ (goto-char indent-point)
+ (setq in-string t))))
+ ((looking-at "/")
+ (if (and (ruby-expr-beg)
+ (goto-char pnt)
+ (looking-at "\\([^/\n]\\|\\\\/\\)*")
+ (eq ?/ (char-after (match-end 0))))
+ (goto-char (1+ (match-end 0)))
+ (goto-char indent-point)
+ (setq in-string t)))
+ ((looking-at "\\?") ;skip ?char
(cond
- ((or (eq c ?.)
- (and (eq c ?w)
- (save-excursion
- (forward-word -1)
- (or
- (looking-at ruby-block-beg-re)
- (looking-at ruby-block-mid-re)))))
- (if (search-forward w indent-point t)
- nil
- (goto-char indent-point)
- (setq in-string t))))))
- ((string= "$" w) ;skip $char
- (forward-char 1))
- ((string= "#" w) ;skip comment
- (forward-line 1))
- ((string= "(" w) ;skip to matching paren
- (let ((orig depth))
- (setq nest (cons (point) nest))
- (setq depth (1+ depth))
- (while (and (/= depth orig)
- (re-search-forward "[()]" indent-point t))
- (cond
- ((= (char-after (match-beginning 0)) ?\( )
- (setq nest (cons (point) nest))
- (setq depth (1+ depth)))
- (t
- (setq nest (cdr nest))
- (setq depth (1- depth)))))
- (if (> depth orig) (setq in-paren ?\())))
- ((string= "[" w) ;skip to matching paren
- (let ((orig depth))
- (setq nest (cons (point) nest))
- (setq depth (1+ depth))
- (while (and (/= depth orig)
- (re-search-forward "\\[\\|\\]" indent-point t))
- (cond
- ((= (char-after (match-beginning 0)) ?\[ )
- (setq nest (cons (point) nest))
- (setq depth (1+ depth)))
- (t
- (setq nest (cdr nest))
- (setq depth (1- depth)))))
- (if (> depth orig) (setq in-paren ?\[))))
- ((string= "{" w) ;skip to matching paren
- (let ((orig depth))
- (setq nest (cons (point) nest))
+ ((ruby-expr-beg)
+ (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.")
+ (goto-char (match-end 0)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "\\$") ;skip $char
+ (goto-char pnt)
+ (forward-char 1))
+ ((looking-at "#") ;skip comment
+ (forward-line 1)
+ (goto-char pnt))
+ ((looking-at "[\\[({]")
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
(setq depth (1+ depth))
- (while (and (/= depth orig)
- (re-search-forward "[{}]" indent-point t))
- (cond
- ((= (char-after (match-beginning 0)) ?{ )
- (setq nest (cons (point) nest))
- (setq depth (1+ depth)))
- (t
- (setq nest (cdr nest))
- (setq depth (1- depth)))))
- (if (> depth orig) (setq in-paren ?{))))
- ((string-match ruby-block-end-re w)
- (setq nest (cdr nest))
- (setq depth (1- depth)))
- ((string-match ruby-block-beg-re w)
- (let (c)
- (save-excursion
- (goto-char pnt)
- (skip-chars-backward " \t")
- (setq c (char-after (1- (point)))))
- (if (or (null c) (= c ?\n) (= c ?\;))
- (progn
- (setq nest (cons (point) nest))
- (setq depth (1+ depth))))))
- (t
- (error (format "bad string %s" w)))))))
- (list in-string in-paren (car nest) depth)))
+ (goto-char pnt))
+ ((looking-at "[])}]")
+ (setq nest (cdr nest))
+ (setq depth (1- depth))
+ (goto-char pnt))
+ ((looking-at ruby-block-end-re)
+ (if (and (not (bolp))
+ (progn
+ (forward-char -1)
+ (eq ?_ (char-after (point))))
+ (progn
+ (goto-char pnt)
+ (eq ?_ (char-after (point)))))
+ nil
+ (setq nest (cdr nest))
+ (setq depth (1- depth)))
+ (goto-char pnt))
+ ((looking-at ruby-block-beg-re)
+ (and
+ (or (bolp)
+ (progn
+ (forward-char -1)
+ (not (eq ?_ (char-after (point))))))
+ (save-excursion
+ (goto-char pnt)
+ (not (eq ?_ (char-after (point)))))
+ (skip-chars-backward " \t")
+ (or (bolp)
+ (save-excursion
+ (forward-char -1)
+ (looking-at ruby-operator-chars)))
+ (progn
+ (setq nest (cons (cons nil pnt) nest))
+ (setq depth (1+ depth))))
+ (goto-char pnt))
+ (t
+ (error (format "bad string %s"
+ (buffer-substring (point) pnt)
+ )))))))
+ (list in-string (car nest) depth))))
(defun ruby-calculate-indent (&optional parse-start)
(save-excursion
(beginning-of-line)
(let ((indent-point (point))
(case-fold-search nil)
- state eol
+ state bol eol
(indent 0))
(if parse-start
(goto-char parse-start)
@@ -281,25 +280,74 @@ The variable ruby-indent-level controls the amount of indentation.
(setq indent nil)) ; do nothing
((nth 1 state) ; in paren
- (goto-char (nth 2 state))
+ (goto-char (cdr (nth 1 state)))
(setq indent
- (if (and (eq (nth 1 state) ?\( ) (not (looking-at "$")))
+ (if (and (eq (car (nth 1 state)) ?\( )
+ (not (looking-at "(\\s *$")))
(current-column)
(+ (current-indentation) ruby-indent-level))))
- ((> (nth 3 state) 0) ; in nest
- (goto-char (nth 2 state))
+ ((> (nth 2 state) 0) ; in nest
+ (goto-char (cdr (nth 1 state)))
(forward-word -1) ; skip back a keyword
(setq indent (+ (current-column) ruby-indent-level)))
(t ; toplevel
(setq indent 0)))
- (goto-char indent-point)
- (end-of-line)
- (setq eol (point))
- (beginning-of-line)
- (if (re-search-forward ruby-negative eol t)
+
+ (cond
+ (indent
+ (goto-char indent-point)
+ (end-of-line)
+ (setq eol (point))
+ (beginning-of-line)
+ (cond
+ ((re-search-forward ruby-negative eol t)
(setq indent (- indent ruby-indent-level)))
+ ;;operator terminated lines
+ ((and
+ (save-excursion
+ (beginning-of-line)
+ (not (bobp)))
+ (or (null (car (nth 1 state))) ;not in parens
+ (and (eq (car (nth 1 state)) ?\{)
+ (save-excursion ;except non-block braces
+ (goto-char (cdr (nth 1 state)))
+ (or (bobp) (forward-char -1))
+ (not (ruby-expr-beg))))))
+ (beginning-of-line)
+ (skip-chars-backward " \t\n")
+ (beginning-of-line) ; goto beginning of non-empty line
+ (setq bol (point))
+ (end-of-line)
+ (setq eol (point))
+ (and (search-backward "#" bol t) ; check for comment line
+ (not (eq ?? (char-after (1- (point)))))
+ (not (nth 0 (ruby-parse-region parse-start (point))))
+ (setq eol (point)))
+ (goto-char eol)
+ (skip-chars-backward " \t")
+ (or (bobp) (forward-char -1))
+ (and (looking-at ruby-operator-chars)
+;; (or (not (eq ?/ (char-after (point))))
+;; (progn
+;; (not (nth 0 (ruby-parse-region parse-start (point))))))
+ (or (not (eq ?/ (char-after (point))))
+ (null (nth 0 (ruby-parse-region parse-start (point)))))
+ (save-excursion
+ (goto-char parse-start)
+ (sit-for 1))
+ (not (eq (char-after (1- (point))) ?$))
+ (or (not (eq ?| (char-after (point))))
+ (save-excursion
+ (or (eolp) (forward-char -1))
+ (and (search-backward "|" bol t)
+ (skip-chars-backward " \t\n")
+ (and (not (eolp))
+ (progn
+ (forward-char -1)
+ (not (looking-at "\\{")))))))
+ (setq indent (+ indent ruby-indent-level)))))))
indent)))
(defun ruby-electric-brace (arg)
@@ -329,7 +377,7 @@ An end of a defun is found by moving forward from the beginning of one."
(interactive "*")
(save-excursion
(delete-region (point) (progn (skip-chars-backward " \t") (point))))
- (insert ?\n)
+ (newline)
(save-excursion
(forward-line -1)
(indent-according-to-mode))
@@ -348,3 +396,26 @@ An end of a defun is found by moving forward from the beginning of one."
(goto-char beg)
(while (re-search-forward "^\\([ \t]*\\)#" end t)
(replace-match "\\1" nil nil))))
+
+(if (featurep 'hilit19)
+ (hilit-set-mode-patterns
+ 'ruby-mode
+ '(("\\s #.*$" nil comment)
+ ("^#.*$" nil comment)
+ ("\\$\\(.\\|\\sw+\\)" nil type)
+ ("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string)
+ ("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string)
+ ("^/\\([^/\n]\\|\\\\/\\)*/" nil string)
+ ("[^a-zA-Z_]\\s *\\(/\\([^/\n]\\|\\\\/\\)*/\\)" 1 string)
+ ("\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|rescue\\|then\\|when\\|while\\)\\s *\\(/\\([^/\n]\\|\\\\/\\)*/\\)" 2 string)
+ ("^\\s *require.*$" nil include)
+ ("^\\s *load.*$" nil include)
+ ("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl)
+ ("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun)
+ ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|rescue\\|then\\|when\\|while\\)\\>[^_]" 1 defun)
+ ("[^_]\\<\\(and\\|break\\|continue\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\)\\>[^_]" 1 keyword)
+ ("[^_]\\<\\(self\\|nil\\|TRUE\\|FALSE\\|__LINE__\\|__FILE__\\)\\>[^_]" 1 define)
+ ("$.[a-zA-Z_0-9]*" nil struct)
+ ("@[a-zA-Z_0-9]+" nil struct)
+ ("[^_]\\<[A-Z].[a-zA-Z_0-9]*" nil define)
+ ("^__END__" nil label))))
diff --git a/sample/samp.rb b/sample/samp.rb
deleted file mode 100644
index 4052a308c1..0000000000
--- a/sample/samp.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# Sp܂ރXNvg
-# g: samp.rb file..
-
-P = 0
-while gets()
- printf("%3d: %s", $., $_)
- while sub(/\w+/, '')
- if $& != "";
- P += 1
- end
- end
- if ($. >= 10); break; end
-end
-printf("line: %d\n", $.)
-printf("word: %d\n", P)
diff --git a/sample/sieve.rb b/sample/sieve.rb
index 640cc32b08..a953784284 100644
--- a/sample/sieve.rb
+++ b/sample/sieve.rb
@@ -12,7 +12,7 @@ for i in 2 .. max
print ", "
print i
sieve.push(i)
- resque
+ rescue
end
end
print "\n"
diff --git a/sample/split.rb b/sample/split.rb
deleted file mode 100644
index 2b6f3921ce..0000000000
--- a/sample/split.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# split test
-print("1 byte string", "\n")
-print("1 byte string".reverse, "\n")
-
-print("ʸ", "\n")
-print("ʸ".reverse, "\n")
-
-print("1 byte string", "\n")
-print("1 byte string".split(//).reverse.join(":"), "\n")
-print("ʸ", "\n")
-print("ʸ".split(//).reverse.join(":"), "\n")
-print("Ѥ1byteκ", "\n")
-print("Ѥ1byteκ".split(//).reverse.join(":"), "\n")
diff --git a/sample/struct.rb b/sample/struct.rb
deleted file mode 100644
index 322764d02f..0000000000
--- a/sample/struct.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-#output:
-# struct test
-# 1
-
-foo = Struct.new("test", "a1"::1, "a2"::2)
-print(foo, "\n")
-bar = foo.clone
-print(bar.a1, "\n")
diff --git a/sample/svr.rb b/sample/svr.rb
index 23b2bf71f6..460c16bedf 100644
--- a/sample/svr.rb
+++ b/sample/svr.rb
@@ -1,6 +1,8 @@
# socket example - server side
# usage: ruby svr.rb
+require "socket"
+
gs = TCPserver.open(0)
addr = gs.addr
addr.shift
diff --git a/sample/system.rb b/sample/system.rb
deleted file mode 100644
index 02f3782b39..0000000000
--- a/sample/system.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-# command string
-print(`echo foobar`)
diff --git a/sample/t1.rb b/sample/t1.rb
deleted file mode 100644
index 701a1cd389..0000000000
--- a/sample/t1.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-def test(a1, *a2)
- while 1
- case gets()
- when nil
- break
- when /^-$/
- print("-\n")
- return
- when /^-help/
- print("-help\n")
- break
- end
- end
- print(a1, a2, "\n")
-end
-
-print($ARGV, "\n")
-print("in: ")
-test(1)
-print("end\n")
diff --git a/sample/t2.rb b/sample/t2.rb
deleted file mode 100644
index 2e3741e8f1..0000000000
--- a/sample/t2.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-#print("in Print\n")
-def t2() end
-
-def println(*args)
- for a in args
- t2()
- print(a)
- end
- print("\n")
-end
-
-def tt
- for i in 1..10
- println("i:", i);
- yield(i);
- end
-end
-
-test = tt{|i|
- if i == 3; break end
- println("ttt: ", i);
-}
-#exit()
diff --git a/sample/test.rb b/sample/test.rb
index 9c422cc94a..7f26433181 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -1,5 +1,1040 @@
-index = 1
-for argument in $ARGV
- printf("%d:%s\n", index, argument)
- index = index + 1
+#! /usr/local/bin/ruby
+
+$testnum=0
+
+def check(what)
+ printf "%s\n", what
+ $what = what
+ $testnum = 0
end
+
+def ok
+ $testnum+=1
+ printf "ok %d\n", $testnum
+end
+
+def notok
+ $testnum+=1
+ printf "not ok %s %d\n", $what, $testnum
+ $failed = TRUE
+end
+
+# make sure conditional operators work
+
+check "condition"
+
+$x = '0';
+
+$x == $x && ok
+$x != $x && notok
+$x == $x || notok
+$x != $x || ok
+
+# first test to see if we can run the tests.
+
+check "if";
+
+$x = 'test';
+if $x == $x then ok else notok end
+if $x != $x then notok else ok end
+
+check "case"
+
+case 5
+when 1, 2, 3, 4, 6, 7, 8
+ notok
+when 5
+ ok
+end
+
+case 5
+when 5
+ ok
+when 1..10
+ notok
+end
+
+case 5
+when 5
+ ok
+else
+ notok
+end
+
+case "foobar"
+when /^f.*r$/
+ ok
+else
+ notok
+end
+
+check "while";
+
+tmp = open("while_tmp", "w")
+tmp.print "tvi925\n";
+tmp.print "tvi920\n";
+tmp.print "vt100\n";
+tmp.print "Amiga\n";
+tmp.print "paper\n";
+tmp.close
+
+# test break
+
+tmp = open("while_tmp", "r")
+
+while tmp.gets()
+ break if /vt100/
+end
+
+if !tmp.eof && /vt100/ then
+ ok
+else
+ notok
+end
+tmp.close
+
+# test continue
+$bad = FALSE
+tmp = open("while_tmp", "r")
+while tmp.gets()
+ continue if /vt100/;
+ $bad = 1 if /vt100/;
+end
+if !tmp.eof || /vt100/ || $bad
+ notok
+else
+ ok
+end
+tmp.close
+
+# test redo
+$bad = FALSE
+tmp = open("while_tmp", "r")
+while tmp.gets()
+ if gsub!('vt100', 'VT100')
+ gsub!('VT100', 'Vt100')
+ redo;
+ end
+ $bad = 1 if /vt100/;
+ $bad = 1 if /VT100/;
+end
+if !tmp.eof || $bad
+ notok
+else
+ ok
+end
+tmp.close
+
+# test interval
+$bad = FALSE
+tmp = open("while_tmp", "r")
+while tmp.gets()
+ break if not 1..2
+ if /vt100/ || /Amiga/ || /paper/
+ $bad = TRUE
+ notok
+ break
+ end
+end
+ok if not $bad
+tmp.close
+
+File.unlink "while_tmp" or `/bin/rm -f "while_tmp"`
+
+# exception handling
+check "exception";
+
+begin
+ fail "this must be handled"
+ notok
+rescue
+ ok
+end
+
+$bad = TRUE
+begin
+ fail "this must be handled no.2"
+rescue
+ if $bad
+ $bad = FALSE
+ retry
+ notok
+ end
+end
+ok
+
+$bad = TRUE
+$string = "this must be handled no.3"
+begin
+ fail $string
+rescue
+ensure
+ $bad = FALSE
+ ok
+end
+notok if $bad || $! != $string
+
+# exception in rescue clause
+begin
+ begin
+ fail "this must be handled no.4"
+ rescue
+ fail "exception in rescue clause"
+ end
+ notok
+rescue
+ ok
+end
+
+check "array"
+$x = [0, 1, 2, 3, 4, 5]
+if $x[2] == 2
+ ok
+else
+ notok
+end
+
+if $x[1..3] == [1, 2, 3]
+ ok
+else
+ notok
+end
+
+if $x[1,3] == [1, 2, 3]
+ ok
+else
+ notok
+end
+
+if [1, 2] + [3, 4] == [1, 2, 3, 4]
+ ok
+else
+ notok
+end
+
+$x[0, 2] = 10
+if $x[0] == 10 && $x[1] == 2
+ ok
+else
+ notok
+end
+
+$x[0, 0] = -1
+if $x[0] == -1 && $x[1] == 10
+ ok
+else
+ notok
+end
+
+$x[-1, 1] = 20
+if $x[-1] == 20 && $x.pop == 20
+ ok
+else
+ notok
+end
+
+$x = ["it", "came", "to", "pass", "that", "..."]
+$x = $x.sort.join(" ")
+if $x == "... came it pass that to"
+ ok
+else
+ notok
+end
+
+# split test
+if "1 byte string".split(//).reverse.join(":") == "g:n:i:r:t:s: :e:t:y:b: :1"
+ ok
+else
+ notok
+end
+
+$x = [1]
+if ($x * 5).join(":") == '1:1:1:1:1' then ok else notok end
+if ($x * 1).join(":") == '1' then ok else notok end
+if ($x * 0).join(":") == '' then ok else notok end
+
+check "hash"
+$x = {1=>2, 2=>4, 3=>6}
+$y = {1, 2, 2, 4, 3, 6}
+
+if $x[1] == 2
+ ok
+else
+ notok
+end
+
+begin
+ for k,v in $y
+ fail if k*2 != v
+ end
+ ok
+rescue
+ notok
+end
+
+if $x.length == 3
+ ok
+else
+ notok
+end
+
+if $x.has_key?(1)
+ ok
+else
+ notok
+end
+
+if $x.has_value?(4)
+ ok
+else
+ notok
+end
+
+if $x.indexes(2,3) == [4,6]
+ ok
+else
+ notok
+end
+
+$z = $y.keys.join(":")
+if $z == "1:2:3"
+ ok
+else
+ notok
+end
+
+$z = $y.values.join(":")
+if $z == "2:4:6"
+ ok
+else
+ notok
+end
+
+if $x == $y
+ ok
+else
+ notok
+end
+
+$y.shift
+if $y.length == 2
+ ok
+else
+ notok
+end
+
+check "iterator"
+
+if iterator? then notok else ok end
+
+def ttt
+ if iterator? then ok else notok end
+end
+ttt{}
+
+# yield at top level
+begin
+ yield
+ notok
+rescue
+ ok
+end
+
+$x = [1, 2, 3, 4]
+$y = []
+
+# iterator over array
+for i in $x
+ $y.push i
+end
+if $x == $y
+ ok
+else
+ notok
+end
+
+# nested iterator
+def tt
+ 1.upto(10) {|i|
+ yield i
+ }
+end
+
+tt{|i| break if i == 5}
+if i == 5
+ ok
+else
+ notok
+end
+
+# iterator break/redo/continue/retry
+done = TRUE
+loop{
+ break
+ done = FALSE
+ notok
+}
+ok if done
+
+done = TRUE
+$bad = FALSE
+loop {
+ break if not done
+ done = FALSE
+ continue
+ $bad = TRUE
+}
+if $bad
+ notok
+else
+ ok
+end
+
+done = TRUE
+$bad = FALSE
+loop {
+ break if not done
+ done = FALSE
+ redo
+ $bad = TRUE
+}
+if $bad
+ notok
+else
+ ok
+end
+
+$x = []
+for i in 1 .. 7
+ $x.push(i)
+end
+if $x.size == 7
+ ok
+else
+ notok
+end
+# $x == [1, 2, 3, 4, 5, 6, 7]
+$done = FALSE
+$x = []
+for i in 1 .. 7 # see how retry works in iterator loop
+ if i == 4 and not $done
+ $done = TRUE
+ retry
+ end
+ $x.push(i)
+end
+# $x == [1, 2, 3, 1, 2, 3, 4, 5, 6, 7]
+if $x.size == 10
+ ok
+else
+ notok
+end
+
+check "bignum"
+def fact(n)
+ return 1 if n == 0
+ return n*fact(n-1)
+end
+if fact(40) == 815915283247897734345611269596115894272000000000
+ ok
+else
+ notok
+end
+if fact(40) == 815915283247897734345611269596115894272000000001
+ notok
+else
+ ok
+end
+
+check "string & char"
+
+if "abcd" == "abcd"
+ ok
+else
+ notok
+end
+
+if "abcd" =~ "abcd"
+ ok
+else
+ notok
+end
+
+$foo = "abc"
+if "#$foo = abc" == "abc = abc"
+ ok
+else
+ notok
+end
+
+if "#{$foo} = abc" == "abc = abc"
+ ok
+else
+ notok
+end
+
+foo = "abc"
+if "#{foo} = abc" == "abc = abc"
+ ok
+else
+ notok
+end
+
+if '-' * 5 == '-----' then ok else notok end
+if '-' * 1 == '-' then ok else notok end
+if '-' * 0 == '' then ok else notok end
+
+foo = '-'
+if foo * 5 == '-----' then ok else notok end
+if foo * 1 == '-' then ok else notok end
+if foo * 0 == '' then ok else notok end
+
+# character constants(assumes ASCII)
+if "a"[0] == ?a
+ ok
+else
+ notok
+end
+
+if ?a == ?a
+ ok
+else
+ notok
+end
+
+if ?\C-a == 1
+ ok
+else
+ notok
+end
+
+if ?\M-a == 225
+ ok
+else
+ notok
+end
+
+if ?\M-\C-a == 129
+ ok
+else
+ notok
+end
+
+$x = "abcdef"
+$y = [ ?a, ?b, ?c, ?d, ?e, ?f ]
+$bad = FALSE
+$x.each_byte {|i|
+ if i != $y.shift
+ $bad = TRUE
+ break
+ end
+}
+if not $bad
+ ok
+else
+ notok
+end
+
+check "asignment"
+a = nil
+if a == nil
+ ok
+else
+ notok
+end
+
+a, b = 1, 2
+if a == 1 and b == 2 then
+ ok
+else
+ notok
+end
+
+a, *b = 1, 2, 3
+if a == 1 and b == [2, 3] then
+ ok
+else
+ notok
+end
+
+check "call"
+def aaa(a, b=100, *rest)
+ res = [a, b]
+ res += rest if rest
+ return res
+end
+
+begin
+ aaa()
+ notok
+rescue
+ ok
+end
+
+begin
+ aaa
+ notok
+rescue
+ ok
+end
+
+begin
+ if aaa(1) == [1, 100]
+ ok
+ else
+ fail
+ end
+rescue
+ notok
+end
+
+begin
+ if aaa(1, 2) == [1, 2]
+ ok
+ else
+ fail
+ end
+rescue
+ notok
+end
+
+begin
+ if aaa(1, 2, 3, 4) == [1, 2, 3, 4]
+ ok
+ else
+ fail
+ end
+rescue
+ notok
+end
+
+begin
+ if aaa(1, *[2, 3, 4]) == [1, 2, 3, 4]
+ ok
+ else
+ fail
+ end
+rescue
+ notok
+end
+
+check "proc"
+$proc = proc{|i| i}
+if $proc.call(2) == 2
+ ok
+else
+ notok
+end
+
+$proc = proc{|i| i*2}
+if $proc.call(2) == 4
+ ok
+else
+ notok
+end
+
+proc{
+ iii=5 # dynamic local variable
+ $proc = proc{ |i|
+ iii = i
+ }
+ $proc2 = proc {
+ $x = iii # dynamic variables shared by procs
+ }
+ if defined?(iii) # dynamic variables' scope
+ ok
+ else
+ notok
+ end
+}.call
+if defined?(iii) # out of scope
+ notok
+else
+ ok
+end
+$x=0
+$proc.call(5)
+$proc2.call
+if $x == 5
+ ok
+else
+ notok
+end
+
+check "signal"
+begin
+ kill "SIGINT", $$
+ sleep 1
+ notok
+rescue
+ ok
+end
+
+$x = 0
+trap "SIGINT", proc{|sig| $x = sig;fail}
+begin
+ kill "SIGINT", $$
+ sleep 1
+ notok
+rescue
+ if $x == 2
+ ok
+ else
+ notok
+ end
+end
+
+$x = FALSE
+trap "SIGINT", "$x = TRUE;fail"
+begin
+ kill "SIGINT", $$
+ sleep 1
+ notok
+rescue
+ if $x
+ ok
+ else
+ notok
+ end
+end
+
+check "eval"
+$bad=FALSE
+eval 'while FALSE; $bad = TRUE; print "foo\n" end
+if not $bad then ok else notok end'
+
+$foo = 'ok'
+begin
+ eval $foo
+rescue
+ notok
+end
+
+check "system"
+if `echo foobar` == "foobar\n"
+ ok
+else
+ notok
+end
+
+if `./ruby -e 'print "foobar"'` == 'foobar'
+ ok
+else
+ notok
+end
+
+tmp = open("script_tmp", "w")
+tmp.print "print $zzz\n";
+tmp.close
+
+if `./ruby -s script_tmp -zzz` == 't'
+ ok
+else
+ notok
+end
+
+if `./ruby -s script_tmp -zzz=555` == '555'
+ ok
+else
+ notok
+end
+
+tmp = open("script_tmp", "w")
+tmp.print "#! /usr/local/bin/ruby -s\n";
+tmp.print "print $zzz\n";
+tmp.close
+
+if `./ruby script_tmp -zzz=678` == '678'
+ ok
+else
+ notok
+end
+
+tmp = open("script_tmp", "w")
+tmp.print "this is a leading junk\n";
+tmp.print "#! /usr/local/bin/ruby -s\n";
+tmp.print "print $zzz\n";
+tmp.print "__END__\n";
+tmp.print "this is a trailing junk\n";
+tmp.close
+
+if `./ruby -x script_tmp` == 'nil'
+ ok
+else
+ notok
+end
+
+if `./ruby -x script_tmp -zzz=555` == '555'
+ ok
+else
+ notok
+end
+
+tmp = open("script_tmp", "w")
+for i in 1..5
+ tmp.print i, "\n"
+end
+tmp.close
+
+`./ruby -i.bak -pe 'sub(/^[0-9]+$/){$&.to_i * 5}' script_tmp`
+done = TRUE
+tmp = open("script_tmp", "r")
+while tmp.gets
+ if $_.to_i % 5 != 0
+ done = FALSE
+ notok
+ break
+ end
+end
+ok if done
+
+File.unlink "script_tmp" or `/bin/rm -f "script_tmp"`
+File.unlink "script_tmp.bak" or `/bin/rm -f "script_tmp.bak"`
+
+check "const"
+TEST1 = 1
+TEST2 = 2
+
+module Const
+ TEST3 = 3
+ TEST4 = 4
+end
+
+module Const2
+ TEST3 = 6
+ TEST4 = 8
+end
+
+include Const
+
+if [TEST1,TEST2,TEST3,TEST4] == [1,2,3,4]
+ ok
+else
+ notok
+end
+
+include Const2
+
+if [TEST1,TEST2,TEST3,TEST4] == [1,2,6,8]
+ ok
+else
+ notok
+end
+
+check "clone"
+foo = Object.new
+def foo.test
+ "test"
+end
+bar = foo.clone
+def bar.test2
+ "test2"
+end
+
+if bar.test2 == "test2"
+ ok
+else
+ notok
+end
+
+if bar.test == "test"
+ ok
+else
+ notok
+end
+
+if foo.test == "test"
+ ok
+else
+ notok
+end
+
+begin
+ foo.test2
+ notok
+rescue
+ ok
+end
+
+check "pack"
+
+$format = "c2x5CCxsdila6";
+# Need the expression in here to force ary[5] to be numeric. This avoids
+# test2 failing because ary2 goes str->numeric->str and ary doesn't.
+ary = [1,-100,127,128,32767,987.654321098 / 100.0,12345,123456,"abcdef"]
+$x = ary.pack($format)
+ary2 = $x.unpack($format)
+
+if ary.length == ary2.length then ok else notok end
+
+if ary.join(':') == ary2.join(':') then ok else notok end
+
+if $x =~ /def/ then ok else notok end
+
+check "math"
+if Math.sqrt(4) == 2
+ ok
+else
+ notok
+end
+
+include Math
+if sqrt(4) == 2
+ ok
+else
+ notok
+end
+
+check "struct"
+struct_test = Struct.new("Test", :foo, :bar)
+if struct_test == Struct::Test
+ ok
+else
+ notok
+end
+test = struct_test.new(1, 2)
+if test.foo == 1 && test.bar == 2
+ ok
+else
+ notok
+end
+if test[0] == 1 && test[1] == 2
+ ok
+else
+ notok
+end
+a, b = test
+if a == 1 && b == 2
+ ok
+else
+ notok
+end
+test[0] = 22
+if test.foo == 22
+ ok
+else
+ notok
+end
+test.bar = 47
+if test.bar == 47
+ ok
+else
+ notok
+end
+
+check "variable"
+if $$.is_instance_of? Fixnum
+ ok
+else
+ notok
+end
+
+begin
+ $$ = 5
+ notok
+rescue
+ ok
+end
+
+foobar = "foobar"
+$_ = foobar
+if $_ == foobar
+ ok
+else
+ notok
+end
+
+check "trace"
+$x = 1234
+$y = 0
+trace_var :$x, proc{$y = $x}
+$x = 40414
+if $y == $x
+ ok
+else
+ notok
+end
+
+untrace_var :$x
+$x = 19660208
+if $y != $x
+ ok
+else
+ notok
+end
+
+trace_var :$x, proc{$x *= 2}
+$x = 5
+if $x == 10
+ ok
+else
+ notok
+end
+untrace_var :$x
+
+check "defined?"
+if defined? $x
+ ok
+else
+ notok
+end
+
+foo=5
+if defined? foo
+ ok
+else
+ notok
+end
+
+if defined? Array
+ ok
+else
+ notok
+end
+
+if defined? Object.new
+ ok
+else
+ notok
+end
+
+if defined? 1 == 2
+ ok
+else
+ notok
+end
+
+if defined? fail
+ ok
+else
+ notok
+end
+
+def defined_test
+ return defined?(yield)
+end
+
+if defined_test
+ notok
+else
+ ok
+end
+
+if defined_test{}
+ ok
+else
+ notok
+end
+
+check "gc"
+begin
+ 1.upto(10000) {
+ tmp = [0,1,2,3,4,5,6,7,8,9]
+ }
+ tmp = nil
+ ok
+rescue
+ notok
+end
+
+print "end of test\n" if not $failed
diff --git a/sample/tkbiff.rb b/sample/tkbiff.rb
new file mode 100644
index 0000000000..9b406010cb
--- /dev/null
+++ b/sample/tkbiff.rb
@@ -0,0 +1,121 @@
+#! /usr/local/bin/ruby
+
+if $ARGV.length == 0
+ if ENV['MAIL']
+ $spool = ENV['MAIL']
+ else
+ $spool = '/usr/spool/mail/' + ENV['USER']
+ end
+else
+ $spool = $ARGV[0]
+end
+
+exit if fork
+
+require "parsedate"
+require "base64"
+
+include ParseDate
+
+class Mail
+ def Mail.new(f)
+ if !f.is_kind_of?(IO)
+ f = open(f, "r")
+ me = super
+ f.close
+ else
+ me = super
+ end
+ return me
+ end
+
+ def initialize(f)
+ @header = {}
+ @body = []
+ while f.gets()
+ $_.chop!
+ continue if /^From / # skip From-line
+ break if /^$/ # end of header
+ if /^(\S+):\s*(.*)/
+ @header[attr = $1.capitalize] = $2
+ elsif attr
+ sub(/^\s*/, '')
+ @header[attr] += "\n" + $_
+ end
+ end
+
+ return if ! $_
+
+ while f.gets()
+ break if /^From /
+ @body.push($_)
+ end
+ end
+
+ def header
+ return @header
+ end
+
+ def body
+ return @body
+ end
+
+end
+
+require "tkscrollbox"
+
+$top = TkRoot.new
+$top.withdraw
+$list = TkScrollbox.new($top) {
+ relief 'raised'
+ width 80
+ height 8
+ setgrid 'yes'
+ pack
+}
+TkButton.new($top) {
+ text 'Dismiss'
+ command proc {$top.withdraw}
+ pack('fill'=>'both','expand'=>'yes')
+}
+$top.bind "Control-c", proc{exit}
+$top.bind "Control-q", proc{exit}
+$top.bind "space", proc{exit}
+
+$spool_size = 0
+def check
+ size = File.size($spool)
+ if size and size != $spool_size
+ pop_up if size > 0
+ end
+ Tk.after 5000, proc{check}
+end
+
+def pop_up
+ outcount = 0;
+ $spool_size = File.size($spool)
+ $list.delete 0, 'end'
+ f = open($spool, "r")
+ while !f.eof
+ mail = Mail.new(f)
+ date, from, subj = mail.header['Date'], mail.header['From'], mail.header['Subject']
+ continue if !date
+ y = m = d = 0
+ y, m, d = parsedate(date) if date
+ from = "sombody@somewhere" if ! from
+ subj = "(nil)" if ! subj
+ from = decode_b(from)
+ subj = decode_b(subj)
+ $list.insert 'end', format('%-02d/%02d/%02d [%-28.28s] %s',y,m,d,from,subj)
+ outcount += 1
+ end
+ f.close
+ if outcount == 0
+ $list.insert 'end', "You have no mail."
+ end
+ $top.deiconify
+ Tk.after 2000, proc{$top.withdraw}
+end
+
+check
+Tk.mainloop
diff --git a/sample/tkbrowse.rb b/sample/tkbrowse.rb
new file mode 100644
index 0000000000..dbaa132d1f
--- /dev/null
+++ b/sample/tkbrowse.rb
@@ -0,0 +1,69 @@
+#!/usr/local/bin/ruby
+#
+# This script generates a directory browser, which lists the working
+# directory and allows you to open files or subdirectories by
+# double-clicking.
+
+# Create a scrollbar on the right side of the main window and a listbox
+# on the left side.
+
+require "tkscrollbox"
+
+list = TkScrollbox.new {
+ relief 'raised'
+ width 20
+ height 20
+ setgrid 'yes'
+ pack
+}
+
+# The procedure below is invoked to open a browser on a given file; if the
+# file is a directory then another instance of this program is invoked; if
+# the file is a regular file then the Mx editor is invoked to display
+# the file.
+
+def browse (dir, file)
+ if dir != "."
+ file="#{dir}/#{file}"
+ if File.isdirectory? file
+ system "browse #{file} &"
+ else
+ if File.isfile? file
+ if ENV['EDITOR']
+ system format("%s %s&", ENV['EDITOR'], file)
+ else
+ sysmte "xedit #{file}&"
+ end
+ else
+ STDERR.print "\"#{file}\" isn't a directory or regular file"
+ end
+ end
+ end
+end
+
+# Fill the listbox with a list of all the files in the directory (run
+# the "ls" command to get that information).
+
+if $ARGV.length>0
+ dir = $ARGV[0]
+else
+ dir="."
+end
+list.insert 'end', *`ls #{dir}`.split
+
+# Set up bindings for the browser.
+
+list.focus
+list.bind "Control-q", proc{exit}
+list.bind "Control-c", proc{exit}
+list.bind "Control-p", proc{
+ print "selection <", TkSelection.get, ">\n"
+}
+
+list.bind "Double-Button-1", proc{
+ for i in TkSelection.get.split
+ print "clicked ", i, "\n"
+ browse dir, i
+ end
+}
+Tk.mainloop
diff --git a/sample/tkdialog.rb b/sample/tkdialog.rb
new file mode 100644
index 0000000000..e83e16d0a8
--- /dev/null
+++ b/sample/tkdialog.rb
@@ -0,0 +1,62 @@
+#! /usr/local/bin/ruby
+require "tk"
+
+root = TkFrame.new
+top = TkFrame.new(root) {
+ relief 'raised'
+ border 1
+}
+msg = TkMessage.new(top) {
+ text "File main.c hasn't been saved to disk since \
+it was last modified. What should I do?"
+ justify 'center'
+ aspect 200
+ font '-Adobe-helvetica-medium-r-normal--*-240*'
+ pack('padx'=>5, 'pady'=>5, 'expand'=>'yes')
+}
+top.pack('fill'=>'both')
+root.pack
+
+bot = TkFrame.new(root) {
+ relief 'raised'
+ border 1
+}
+
+TkFrame.new(bot) { |left|
+ relief 'sunken'
+ border 1
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10, 'pady'=> 10)
+ TkButton.new(left) {
+ text "Save File"
+ command "quit 'save'"
+ pack('expand'=>'yes','padx'=>6,'pady'=> 6)
+ top.bind "Enter", proc{state 'active'}
+ msg.bind "Enter", proc{state 'active'}
+ bot.bind "Enter", proc{state 'active'}
+ top.bind "Leave", proc{state 'normal'}
+ msg.bind "Leave", proc{state 'normal'}
+ bot.bind "Leave", proc{state 'normal'}
+ Tk.root.bind "ButtonRelease-1", proc{quit 'save'}
+ Tk.root.bind "Return", proc{quit 'save'}
+ }
+}
+TkButton.new(bot) {
+ text "Quit Anyway"
+ command "quit 'quit'"
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10)
+}
+TkButton.new(bot) {
+ text "Return To Editor"
+ command "quit 'return'"
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10)
+}
+bot.pack
+root.pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
+
+def quit(button)
+ print "aaa\n"
+ print "You pressed the \"#{button}\" button; bye-bye!\n"
+ exit
+end
+
+Tk.mainloop
diff --git a/sample/tkfrom.rb b/sample/tkfrom.rb
new file mode 100644
index 0000000000..4a0d8c2b5d
--- /dev/null
+++ b/sample/tkfrom.rb
@@ -0,0 +1,115 @@
+#! /usr/local/bin/ruby
+
+require "parsedate"
+require "base64"
+
+include ParseDate
+
+class Mail
+ def Mail.new(f)
+ if !f.is_kind_of?(IO)
+ f = open(f, "r")
+ me = super
+ f.close
+ else
+ me = super
+ end
+ return me
+ end
+
+ def initialize(f)
+ @header = {}
+ @body = []
+ while f.gets()
+ $_.chop!
+ continue if /^From / # skip From-line
+ break if /^$/ # end of header
+ if /^(\S+):\s*(.*)/
+ @header[attr = $1.capitalize] = $2
+ elsif attr
+ sub(/^\s*/, '')
+ @header[attr] += "\n" + $_
+ end
+ end
+
+ return if ! $_
+
+ while f.gets()
+ break if /^From /
+ @body.push($_)
+ end
+ end
+
+ def header
+ return @header
+ end
+
+ def body
+ return @body
+ end
+
+end
+
+$ARGV[0] = '/usr/spool/mail/' + ENV['USER'] if $ARGV.length == 0
+
+require "tk"
+list = scroll = nil
+TkFrame.new{|f|
+ list = TkListbox.new(f) {
+ yscroll proc{|idx|
+ scroll.set *idx
+ }
+ relief 'raised'
+# geometry "80x5"
+ width 80
+ height 5
+ setgrid 'yes'
+ pack('side'=>'left','fill'=>'both','expand'=>'yes')
+ }
+ scroll = TkScrollbar.new(f) {
+ command proc{|idx|
+ list.yview *idx
+ }
+ pack('side'=>'right','fill'=>'y')
+ }
+ pack
+}
+root = Tk.root
+TkButton.new(root) {
+ text 'Dismiss'
+ command proc {exit}
+ pack('fill'=>'both','expand'=>'yes')
+}
+root.bind "Control-c", proc{exit}
+root.bind "Control-q", proc{exit}
+root.bind "space", proc{exit}
+
+$outcount = 0;
+for file in $ARGV
+ continue if !File.exists?(file)
+ f = open(file, "r")
+ while !f.eof
+ mail = Mail.new(f)
+ date, from, subj = mail.header['Date'], mail.header['From'], mail.header['Subject']
+ continue if !date
+ y = m = d = 0
+ y, m, d = parsedate(date) if date
+ from = "sombody@somewhere" if ! from
+ subj = "(nil)" if ! subj
+ from = decode_b(from)
+ subj = decode_b(subj)
+ list.insert 'end', format('%-02d/%02d/%02d [%-28.28s] %s',y,m,d,from,subj)
+ $outcount += 1
+ end
+ f.close
+end
+
+limit = 10000
+if $outcount == 0
+ list.insert 'end', "You have no mail."
+ limit = 2000
+end
+Tk.after limit, proc{
+ exit
+}
+Tk.mainloop
diff --git a/sample/tkhello.rb b/sample/tkhello.rb
new file mode 100644
index 0000000000..1ff1403e71
--- /dev/null
+++ b/sample/tkhello.rb
@@ -0,0 +1,13 @@
+require "tk"
+
+TkButton.new {
+ text 'hello'
+ command proc{print "hello\n"}
+ pack('fill'=>'x')
+}
+TkButton.new {
+ text 'quit'
+ command 'exit'
+ pack('fill'=>'x')
+}
+Tk.mainloop
diff --git a/sample/tkline.rb b/sample/tkline.rb
new file mode 100644
index 0000000000..843893b5d9
--- /dev/null
+++ b/sample/tkline.rb
@@ -0,0 +1,29 @@
+require "tkclass"
+
+$c = Canvas.new
+$c.pack
+$start_x = start_y = 0
+
+def do_press(x, y)
+ $start_x = x
+ $start_y = y
+ $current_line = Line.new($c, x, y, x, y, 'fill' => 'gray')
+end
+def do_motion(x, y)
+ if $current_line
+ $current_line.coords $start_x, $start_y, x, y
+ end
+end
+
+def do_release(x, y)
+ if $current_line
+ $current_line.coords $start_x, $start_y, x, y
+ $current_line.fill 'black'
+ $current_line = nil
+ end
+end
+
+$c.bind("1", proc{|e| do_press e.x,e.y})
+$c.bind("B1-Motion", proc{|e| do_motion e.x,e.y})
+$c.bind("ButtonRelease-1", proc{|e| do_release e.x,e.y})
+Tk.mainloop
diff --git a/sample/tktimer.rb b/sample/tktimer.rb
new file mode 100644
index 0000000000..b8b3617646
--- /dev/null
+++ b/sample/tktimer.rb
@@ -0,0 +1,49 @@
+#!/usr/local/bin/ruby
+# This script generates a counter with start and stop buttons.
+
+require "tk"
+$label = TkLabel.new {
+ text '0.00'
+ relief 'raised'
+ width 10
+ pack('side'=>'bottom', 'fill'=>'both')
+}
+
+TkButton.new {
+ text 'Start'
+ command proc {
+ if $stopped
+ $stopped = FALSE
+ tick
+ end
+ }
+ pack('side'=>'left','fill'=>'both','expand'=>'yes')
+}
+TkButton.new {
+ text 'Stop'
+ command proc{
+ $stopped = TRUE
+ }
+ pack('side'=>'right','fill'=>'both','expand'=>'yes')
+}
+
+$seconds=0
+$hundredths=0
+$stopped=TRUE
+
+def tick
+ if $stopped then return end
+ Tk.after 50, proc{tick}
+ $hundredths+=5
+ if $hundredths >= 100
+ $hundredths=0
+ $seconds+=1
+ end
+ $label.text format("%d.%02d", $seconds, $hundredths)
+end
+
+root = Tk.root
+root.bind "Control-c", proc{root.destroy}
+root.bind "Control-q", proc{root.destroy}
+Tk.root.focus
+Tk.mainloop
diff --git a/sample/trap.pl b/sample/trap.pl
deleted file mode 100644
index ce022d4062..0000000000
--- a/sample/trap.pl
+++ /dev/null
@@ -1,6 +0,0 @@
-$SIG{'INT'} = 'test';
-
-while (<>) {
- print;
-}
-sub test { print "C-c handled\n"; }
diff --git a/sample/trap.rb b/sample/trap.rb
deleted file mode 100644
index e552a0fddc..0000000000
--- a/sample/trap.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-trap('print("C-c handled\n")', 'INT', 'HUP')
-print("---\n")
-while gets(); print($_) end
diff --git a/sample/tt.rb b/sample/tt.rb
deleted file mode 100644
index f4960feaea..0000000000
--- a/sample/tt.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-module Print
- print("in Print\n")
- def println(*args)
- for a in args
- print(a)
- end
- print("\n")
- end
-
- def println2(*args)
- print(*args)
- print("\n")
- end
-end
-
-module Print2
- def println(*args)
- print("pr2: ");
- super
- end
-end
-
-module Print3
- include Print2
- def println(*args)
- print("pr3: ");
- super
- end
-end
-
-include Print, Print2, Print3
-
-println2("in TopLevel")
-
-print("a: ", $OPT_test, "\n")
-printf("%10.5g: %*s -> 0x%x\n", 123345, -10, Print, Print.id);
-
-println("a+ matches aaa at ", "bccAAaaa" =~ /a+/)
-ttt = "this is a "
-if offset = (ttt =~ /this ([^ ]*) (.*)/)
- println("0 = ", $&);
- println("1 = ", $1);
- println("2 = ", $2);
-end
-
-class Fib : Object
- print("in Fib:Object\n")
-
- def Fib.test(*args)
- println("in Fib.test")
-
- if args; println(*args) end
- args = args.grep(/^c/)
- super(*args)
- end
-
- def init
- println("in Fib.init");
- end
-
- def fib(n)
- a =0; b = 1
-
- while b <= n
- c = a; a = b; b = c+b
- end
- return b
- end
-end
-
-def Object.test(*args)
- println("in Object.test")
- if args; println(*args) end
-end
-
-Fib.test("abc", "def", "aaa", "ccc")
-println("1:", 0x3fffffffa)
-println("2:", 0x3ffffffa)
-#println("3:", 0x40000000+0x40000000)
-
-fib = Fib.new
-
-fib.init
-print(Fib, ":")
-
-#for i in 1 .. 100
-# fib.fib(90000)
-#end
-
-println(fib.fib(9000))
-
-def tt
- for i in 1..10
- println("i:", i);
- yield(i);
- end
-end
-
-test = tt() {|i|break if i == 2}
-println([1,2,3,4].join(":"))
diff --git a/sig.h b/sig.h
new file mode 100644
index 0000000000..da30956e12
--- /dev/null
+++ b/sig.h
@@ -0,0 +1,28 @@
+/************************************************
+
+ sig.h -
+
+ $Author$
+ $Date$
+ created at: Wed Aug 16 01:15:38 JST 1995
+
+************************************************/
+#ifndef SIG_H
+#define SIG_H
+
+#ifdef SAFE_SIGHANDLE
+extern int trap_immediate;
+# define TRAP_BEG (trap_immediate=1)
+# define TRAP_END (trap_immediate=0)
+#else
+# define TRAP_BEG
+# define TRAP_END
+#endif
+
+typedef RETSIGTYPE(*SIGHANDLE)();
+SIGHANDLE sig_beg();
+void sig_end();
+
+extern int trap_pending;
+
+#endif
diff --git a/signal.c b/signal.c
index dd8f3c2499..a91facc831 100644
--- a/signal.c
+++ b/signal.c
@@ -9,6 +9,7 @@
************************************************/
#include "ruby.h"
+#include "sig.h"
#include <signal.h>
#include <stdio.h>
@@ -162,7 +163,7 @@ signm2signo(nm)
}
VALUE
-Fkill(argc, argv)
+f_kill(argc, argv)
int argc;
VALUE *argv;
{
@@ -251,7 +252,7 @@ static RETSIGTYPE
sighandle(sig)
int sig;
{
- if (sig >= NSIG || trap_list[sig] == Qnil)
+ if (sig >= NSIG ||(sig != SIGINT && trap_list[sig] == Qnil))
Fail("trap_handler: Bad signal %d", sig);
#ifndef HAVE_BSD_SIGNALS
@@ -260,14 +261,16 @@ sighandle(sig)
#ifdef SAFE_SIGHANDLE
if (trap_immediate) {
- rb_trap_eval(trap_list[sig]);
+ if (sig == SIGINT && !trap_list[sig]) Fail("Interrupt");
+ rb_trap_eval(trap_list[sig], sig);
}
else {
trap_pending++;
trap_pending_list[sig]++;
}
#else
- rb_trap_eval(trap_list[sig]);
+ if (sig == SIGINT && !trap_list[sig]) Fail("Interrupt");
+ rb_trap_eval(trap_list[sig], sig);
#endif
}
@@ -275,119 +278,184 @@ void
rb_trap_exit()
{
if (trap_list[0])
- rb_trap_eval(trap_list[0]);
+ rb_trap_eval(trap_list[0], 0);
}
#ifdef SAFE_SIGHANDLE
+void
rb_trap_exec()
{
int i;
- trap_pending = 0;
for (i=0; i<NSIG; i++) {
if (trap_pending_list[i]) {
trap_pending_list[i] = 0;
- rb_trap_eval(trap_list[i]);
+ if (i == SIGINT && trap_list[SIGINT] == 0)
+ Fail("Interrupt");
+ rb_trap_eval(trap_list[i], i);
}
}
+ trap_pending = 0;
}
#endif
-static VALUE
-Ftrap(argc, argv)
- int argc;
- VALUE *argv;
-{
- RETSIGTYPE (*func)();
- VALUE command;
- int i, sig;
-#ifdef HAVE_SIGPROCMASK
+struct trap_arg {
+#ifndef NT
+# ifdef HAVE_SIGPROCMASK
sigset_t mask;
-#else
+# else
int mask;
+# endif
#endif
+ VALUE sig, cmd;
+};
- if (argc < 2)
- Fail("wrong # of arguments -- kill(cmd, sig...)");
+static RETSIGTYPE
+sigexit()
+{
+ rb_exit(1);
+}
- /* disable interrupt */
-#ifdef HAVE_SIGPROCMASK
- sigfillset(&mask);
- sigprocmask(SIG_BLOCK, &mask, &mask);
-#else
- mask = sigblock(~0);
-#endif
+static VALUE
+trap(arg)
+ struct trap_arg *arg;
+{
+ RETSIGTYPE (*func)();
+ VALUE command;
+ int i, sig;
func = sighandle;
-
- if (argv[0] == Qnil) {
+ command = arg->cmd;
+ if (command == Qnil) {
func = SIG_IGN;
- command = Qnil;
}
- else {
- Check_Type(argv[0], T_STRING);
- command = argv[0];
- if (RSTRING(argv[0])->len == 0) {
+ else if (TYPE(command) == T_STRING) {
+ if (RSTRING(command)->len == 0) {
func = SIG_IGN;
}
- else if (RSTRING(argv[0])->len == 7) {
- if (strncmp(RSTRING(argv[0])->ptr, "SIG_IGN", 7) == 0) {
+ else if (RSTRING(command)->len == 7) {
+ if (strncmp(RSTRING(command)->ptr, "SIG_IGN", 7) == 0) {
func = SIG_IGN;
}
- else if (strncmp(RSTRING(argv[0])->ptr, "SIG_DFL", 7) == 0) {
+ else if (strncmp(RSTRING(command)->ptr, "SIG_DFL", 7) == 0) {
func = SIG_DFL;
}
- else if (strncmp(RSTRING(argv[0])->ptr, "DEFAULT", 7) == 0) {
+ else if (strncmp(RSTRING(command)->ptr, "DEFAULT", 7) == 0) {
func = SIG_DFL;
}
}
- else if (RSTRING(argv[0])->len == 6) {
- if (strncmp(RSTRING(argv[0])->ptr, "IGNORE", 6) == 0) {
+ else if (RSTRING(command)->len == 6) {
+ if (strncmp(RSTRING(command)->ptr, "IGNORE", 6) == 0) {
func = SIG_IGN;
}
}
+ else if (RSTRING(command)->len == 4) {
+ if (strncmp(RSTRING(command)->ptr, "EXIT", 4) == 0) {
+ func = sigexit;
+ }
+ }
}
- if (func == SIG_IGN || func == SIG_DFL)
+ if (func == SIG_IGN || func == SIG_DFL) {
command = Qnil;
+ }
- for (i=1; i<argc; i++) {
- if (TYPE(argv[i]) == T_STRING) {
- char *s = RSTRING(argv[i])->ptr;
+ if (TYPE(arg->sig) == T_STRING) {
+ char *s = RSTRING(arg->sig)->ptr;
- if (strncmp("SIG", s, 3) == 0)
- s += 3;
- sig = signm2signo(s);
- if (sig == 0 && strcmp(s, "EXIT") != 0)
- Fail("Invalid signal SIG%s", s);
- }
- else {
- sig = NUM2INT(argv[i]);
- }
- if (sig < 0 || sig > NSIG)
- Fail("Invalid signal no %d", sig);
+ if (strncmp("SIG", s, 3) == 0)
+ s += 3;
+ sig = signm2signo(s);
+ if (sig == 0 && strcmp(s, "EXIT") != 0)
+ Fail("Invalid signal SIG%s", s);
+ }
+ else {
+ sig = NUM2INT(arg->sig);
+ }
+ if (sig < 0 || sig > NSIG) {
+ Fail("Invalid signal no %d", sig);
+ }
+ signal(sig, func);
+ trap_list[sig] = command;
+ /* enable at least specified signal. */
+#ifdef HAVE_SIGPROCMASK
+ sigdelset(&arg->mask, sig);
+#else
+ arg->mask &= ~sigmask(sig);
+#endif
+ return Qnil;
+}
- signal(sig, sighandle);
- trap_list[sig] = command;
- /* enable at least specified signal. */
+#ifndef NT
+static void
+trap_ensure(arg)
+ struct trap_arg *arg;
+{
+ /* enable interrupt */
#ifdef HAVE_SIGPROCMASK
- sigdelset(&mask, sig);
+ sigprocmask(SIG_SETMASK, &arg->mask, NULL);
#else
- mask &= ~sigmask(sig);
+ sigsetmask(arg->mask);
#endif
+}
+#endif
+
+static VALUE
+f_trap(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ struct trap_arg arg;
+
+ if (argc == 0 || argc > 2) {
+ Fail("wrong # of arguments -- trap(sig, cmd)/trap(sig){...}");
}
+
+ arg.sig = argv[0];
+ if (argc == 1) {
+ arg.cmd = f_lambda();
+ }
+ else if (argc == 2) {
+ arg.cmd = argv[1];
+ }
+
+#ifndef NT
/* disable interrupt */
-#ifdef HAVE_SIGPROCMASK
- sigprocmask(SIG_SETMASK, &mask, NULL);
+# ifdef HAVE_SIGPROCMASK
+ sigfillset(&arg.mask);
+ sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask);
+# else
+ arg.mask = sigblock(~0);
+# endif
+
+ return rb_ensure(trap, &arg, trap_ensure, &arg);
#else
- sigsetmask(mask);
+ return trap(&arg);
#endif
- return Qnil;
}
+SIGHANDLE
+sig_beg()
+{
+ if (!trap_list[SIGINT]) {
+ return signal(SIGINT, sighandle);
+ }
+ return 0;
+}
+
+void
+sig_end(handle)
+ SIGHANDLE handle;
+{
+ if (!trap_list[SIGINT]) {
+ signal(SIGINT, handle);
+ }
+}
+
+void
Init_signal()
{
- extern VALUE C_Kernel;
+ extern VALUE cKernel;
- rb_define_method(C_Kernel, "kill", Fkill, -1);
- rb_define_method(C_Kernel, "trap", Ftrap, -1);
+ rb_define_method(cKernel, "kill", f_kill, -1);
+ rb_define_method(cKernel, "trap", f_trap, -1);
}
diff --git a/spec b/spec
deleted file mode 100644
index 77d6e8fd5a..0000000000
--- a/spec
+++ /dev/null
@@ -1,3538 +0,0 @@
-.\" spec - -*- Indented-Text -*- created at: Tue May 25 15:18:26 JST 1993
-
-* Ϥ
-
-RubyϡUNIXǼڤ˥֥Ȼظץߥ󥰡פ򤷤Ȥ˾
-¸뤿ޤ줿ΤɬפȻפ줿:
-
- * ʸˡ䵡ǽñǤ롥
- * ֥Ȼظץߥ󥰤򥵥ݡȤ뵡ǽ
- ĸȤ߷פƤ롥
- * 󥢥饦ɥबû(󥿥ץ꥿Ǥ)
- * OS(UNIX)εǽñѤǤ롥
- * ץȸȤƻȤ롥
- * ϤfreeǤ롥
-
-ʤɤǤ롥֥ȻظȤưŪǤSmalltalkC++ʤɤ
-ξΰƤϤ뤬ä˼ڤʥץߥ󥰤Ȥ˷
-ƤꡤʾξƤΤǤϤʤäץȸ
-ǤPerl Tcl˥֥Ȼظǽɲäƥ¸ߤ뤬
-ϡּڤ˥ץߥ󥰡פȤƤϤƤ⡤դ˥
-Ȼظǽääơξ
-߷פ줿Rubyħ:
-
- * 󥿥ץ꥿Ǥ롥
- * ñ㳰ξʤʸˡ
- * ʬʥ֥Ȼظǽġ
- * Ǥ񤭤䤹(黻ҷʤ)
- * ١쥯롥
- * 㳰ǽ롥
- * ʬ˶Ϥʥ饹Ȥ߹ޤƤ롥
- * OS򥢥뵡ǽ󶡤롥
- * ĥ䤹
-
-ʤɤǤ롥RubyshPerlΤäƤͤˤȤäƤξQˤʤ뤿ä
-Τǡθ줫μʰܹԤǽǤȻפ롥ץޤ
-RubyΥ֥ȻظǽˤĤƳؤ٤С궯ϤʤȤǤ褦
-
-Cǥ饹᥽åɤ򵭽Ҥɲä뤳ȤRuby򹹤˶Ϥˤ
-뤳ȤǤ롥ΥץåȥեǤRubyưŪ˥֥ȥե
-󥯤Ǥ뤷ǤʤƤRubyƥѥ뤷Ȥ߹ߥ
-ɲäΤưפǤ(PerlʤɤϤ뤫ưפǤ)
-
-* Lexical structure
-
-ߤrubyμϥ饯åȤȤASCIIѤ롥rubyʸ
-ʸ̤롥̻ҤǤʤǤդΤȤ˶ʸ򤪤
-Ȥ롥ʸϥڡ(space)(tab)ľ(vertical
-tab) CR(carriage return)(form feed)Ǥ롥(newline)
-˼³ˤ϶ʸȤơʳǤʸζڤȤƲ
-ᤵ롥
-
-̻Ҥϱʸ("_"ޤ)Ϥޤꡤѿ³ΤǤ롥ruby
-̻ҤŤϤʤߤμϼ̻ҤȤƥޥХȥ
-(EUC,SJIS)̤ʤ
-
-Хѿ̾"$"³̻Ҥޤϵ1ʸ󥹥ѿ
-"@"³̻ҡˤʸǻϤޤ뼱̻ҡѿ̾Ͼʸ
-ǻϤޤ뼱̻ҤǤ롥᥽å̾ˤñʤ뼱̻ҤѤ(᥽å̾
-ʸǤ⾮ʸǤϤ)
-
-**
-
-ץȸνˤʤ餤ʸʸɽ(?#)ʳ`#'
-ޤǤϥȤȸʤ
-
-** ͽ
-
-ͽϰʲ̤Ǥ
-
- alias def if retry while
- and else in return yield
- begin elsif module self __END__
- break end nil super __FILE__
- case ensure or then __LINE__
- class fail redo undef
- continue for resque when
-
-ͽϥ饹̾᥽å̾ѿ̾ʤɤѤ뤳ȤϤǤʤ
-
-** ڤʸ
-
-ʸʤɤΥƥʳξζʸ(֤ȥڡ)Ӳ
-(\n)ڤ국Ȥʤ롥˲Ԥ
-
- a +
- b
-
-Τ褦˹ԤǽꡤιԤ³Ȥ(Ǹʸ
-黻Ҥ뤤`,'Ǥ)ζڤȤǧ롥
-
-* ץ
-
-:
-
- print "hello world!\n"
-
-ץϼ¤٤ΤǤ롥ȼδ֤ϥߥ(`;')ޤϲ
-ԤǶڤ롥
-
-*
-
-RubyǤnilʳɾ롥CPerlʤɤȤϰۤʤꡤ0
-""(ʸ)ϵȤɾʤΤǵĤ뤳ȡ
-
-** ʸ
-
-֥륯(`"')dz줿ʸϥХåå³ʸʲ
-Τ褦˲ᤵ롥
-
-Хåå嵭ˡ
-
- \t (0x09)
- \n ʸ(0x0a)
- \r ʸ(0x0d)
- \f ڡʸ(0x0c)
- \b Хåڡ(0x08)
- \a ٥(0x07)
- \e (0x1b)
- \# ʸ`#'Τ
- \nnn 8ʿɽ(n0-7)
- \xnn 16ʿɽ(n0-9,a-f)
- \cx ȥʸ(xASCIIʸ)
- \x ʸxΤ
-
-ޤ`#'ˤѿŸԤ롥󥰥륯(`'')dz
-ʸϡ`\\'(Хåå夽Τ)`\''(󥰥륯)
-ơʸȤβԤʤ
-
-ʸ󼰤󿷤ʸ󥪥֥ȤΤǡʸƤ
-Ƥ⡤ȤȤʸѤʤ
-
-** ޥɽ
-
-RubyǤshΤ褦˥ޥɤμ¹Է̤ʸƥΤ褦˻ȤȤ
-Ǥ롥``ǰϤޤ줿ʸϡ֥륯ȤƱͤ˥Хåå嵭
-ˡβѿŸԤʤ줿塤ޥɤȤƼ¹Ԥ졤μ¹Է
-ʸȤͿ롥ޥɤɾ뤿Ӥ˼¹Ԥ롥
-
-** ɽ
-
-`/'ǰϤޤ줿ʸɽɽ`/'θʸ`i'Ϳ
-줿ˤϡɽϥޥåʸʸζ̤򤷤ʤ
-
- ^ Ƭ
- $
- . Ǥդ1ʸ
- \w ѿ[0-9A-Za-z_]Ʊ
- \W ѿ
- \s ʸ[ \t\n\r\f]Ʊ
- \S ʸ
- \d [0-9] Ʊ
- \D
- \b 춭ʸ(ʸ饹)
- \B 춭ʸ
- \b (0x08)(ʸ饹)
- [ ] ʸ饹
- * ľɽ0ʾη֤
- + ľɽ1ʾη֤
- {m,n} m󤫤nη֤
- ? 0ޤ1
- |
- ( ) ɽޤȤ
-
-¾ʸƱХåå嵭ˡѿŸͭǤ롥
-
-** ѿŸ
-
-֥륯(`"')ǰϤޤ줿ʸ󼰡ޥʸɽ
-ӥ磻ɥɼǤ`#{ѿ̾}'ȤѿƤŸ
-ȤǤ롥ѿѿ(`$',`@')ǻϤޤˤ`#ѿ̾'Ȥ
-ǤŸǤ롥ʸ`#'³ʸ `{',`$',`@'ǤʤСΤޤ
-ʸ`#'ȤƲᤵ롥
-
-** ͥƥ
-
- 123
- -123 (Ĥ)
- 1_234 (10ʿ`_'ޤळȤǤ)
- 123.45 ư
- 1.2e-3 ư
- 0xffff 16
- 0377 8
- ?a ʸ`a'Υ(97)
- ?\C-a ȥaΥ(1)
- ?\M-a ᥿aΥ(225)
- ?\M-\C-a ᥿-ȥaΥ(129)
-
- :ܥ ̻/ѿ̾/黻ҤȰабapplyʤ
- ǥ᥽åɤꤹʤɤ˻Ȥ
-
-?ɽǤƤΥХåå嵭ˡͭǤ롥
-
-** ѿ
-
-Rubyѿϥ(ͭϰ)ȼ̿(ͭ)ˤä4ʬव졤
-μѿ̾κǽΰʸǷꤵ롥̾ѿ2ʸܰʹߤ
-ѿޤ`_'Ǥ뤬ƥѿΰϡ`$'+1ʸεפȤ
-ѿ롥ѿ̾Ĺ˴ؤ̤¤Ϥʤ
-
-ѿΥפ˴ؤ餺Ƥʤѿ򻲾Ȥͤnil
-Ǥ롥μѿɬפʤ
-
-*** Хѿ
-
-:
-
- $foobar
- $/
-
-`$'ǻϤޤѿΥפϥХǤꡤץΤɤǤ
-ȤǤ롥μ̿ϥץμ̿
-
-*** 󥹥ѿ
-
-:
-
- @foobar
-
-`@'ǻϤޤѿϥ󥹥ѿǤꡤΥ饹ޤϥ֥饹
-᥽åɤ黲ȤǤ롥פϥ᥽åǤꡤμ̿ϥ֥
-Ȥμ̿
-
-*** 饹
-
-:
-
- FOOBAR
-
-ʸǻϤޤ뼱̻ҤؤΥǤꡤǽ줿饹
-ƤΥ֥饹ΥǻȤǤ롥
-Ƥ⥸塼򥤥󥯥롼ɤ뤳ȤˤäƹԤʤ롥ؤ
-ϥȥåץ٥롤ʤ᥽åɤǤ٥ǤΤ߲ǽǤ롥
-ϥ饹֤ͤͭ졤ͤѹ뤳ȤǤʤ
-(㳰ȯ)饹μ̿ϥ饹μ̿
-
-饹ϼưŪΤǡ饹̾Ǥ롥
-
-*** ѿ
-
-:
-
- foobar
-
-ʸޤ`_'ǻϤޤ뼱̻ҤϥѿؤΥǤ롥
-ʤѿͤnilǤ
-
-ѿΥפϥ֥åϰ(᥽åǤϥ᥽åɤν
-ޤǡ饹/⥸塼ǤϤνޤ)Ǥ롥̿⤽
-֥åνޤ(ȥåץ٥Υѿϥץνλޤ)
-롥
-
-*** ѿ
-
-̾ѿʳ˵ѿȸƤФüѿ4Ĥ롥
-
- self | ߤΥ᥽åɤμ¹Լ
- nil | Nil饹ͣΥ󥹥(ɽ)
- __FILE__ | ץȤΥե̾(ʸ)
- __LINE__ | ߤιֹ()
-
-εѿˤäƤͤѹ뤳ȤϤǤʤ
-ѿؤ㳰ȯ롥
-
-**
-
-:
-
- [1, 2, 3]
-
-Array饹Υ󥹥󥹤Ǥ롥뼰ϰʲη
-롥
-
- `[' , .. `]'
-
-줾μɾ̤ޤ֤ǿ0ζ
-뤿ˤ϶
-
- `[' `]'
-
-Ѥ롥
-
-** Ϣ
-
-:
-
- {1=>2, 2=>4, 3=>6}
-
-ϢȤǤդΥ֥Ȥ򥭡(ź)ȤƻǤ롥Ruby
-ϢHash(Ϣ)饹Υ󥹥󥹤Ǥ롥ܺ٤ϥ饹
-Hashι򻲾Ȥ줿ϢϢ󼰤ϰʲηǤ롥
-
- `{' `=>' .. `}'
-
-줾μɾ̤򥭡ͤȤϢ󥪥֥Ȥ֤
-ǿ0Ϣ뤿ˤ϶Ϣ
-
- `{' `}'
-
-Ѥ롥Ǥ1İʾ夢硤ۣǤʤ`{', `}'ϾάǤ롥
-
-** ᥽åɸƽм
-
-:
-
- foo.bar()
- foo.bar
- bar()
-
-֥Ȥ˥åŪʹʸåǤꡤδ
-ܷϰʲ̤Ǥ롥
-
- 1 `.' ᥽å̾ `(' 1.. [`,' `*' n ]`)'
-
-1ɾ륪֥ȤΡ̻Ҥǻꤵ᥽åɤƤ
-ФֺǸΰ`*'³(ñ)Ǥ硤μɾ
-(ǤʤѴ)ŸơȤɲä롥
-
-åǡ쥷Фselfξ硤쥷Фά̾Υץ
-ߥ󥰸ˤؿΤ褦ʷǥ᥽åɤƤӽФȤǤ롥
-
-᥽åɸƤӽФΰμγ̤άǤ뤬Ȥʤ뼰
-ʸޤͽǻϤޤϡ̤ͥδطͽ̤η̤
-ʤ礬롥
-
- (, [, {, /, +, -, if, while
-
-ɤΤ褦ɾ뤫ۣʾˤϳ̤Ĥ
-
-㡧
- foo bar+baz # ᥽åɸƤӽФfoo(bar+baz)
- foo (1+2)*5 # ᥽åɸƤӽФ(foo(1+2)) * 5
- foo 1 # ᥽åɸƤӽФfoo(1)
- foo -1 # ѿfoo - 1
-
-쥷Фꤷ᥽åɸƤӽФǤϤξ1Ĥʤˤ
-άǤ(쥷Фꤷʤ硤̤Ĥʤȥѿ
-ȤȤƲᤵ)
-
-᥽å̾ȤƤǤդμ̻ҤѤ뤳ȤǤ롥ǽʸʸ
-Ǥ⾮ʸǤ⹽ʤѿ̾Ȥϼ̻Ҥ֤̾㤦ΤǽʣƤ
-
-饹ModuleƤ᥽å(public,private)ǥ᥽åɤθƤӽ
-椹뤳Ȥ롥privateǻꤵ줿¤줿᥽åɤϴ
-ǤƤӽФȤʤ
-
-** SUPER
-
-:
-
- super
- super(1,2,3)
-
-åüʥȤƥѡ饹Υ᥽åɤθƤӽФ
-롥ηϥ᥽åɤ˥ѡ饹Ѥ뤿
-˻Ȥ
-
- super
-
-ߤΥ᥽åɤͿ줿Τޤޥѥ饹Ʊ̾Υ᥽åɤƤ
-ФȤͿ줿ѿͤѹƤ⡤ϤΤϸΰ
-ͤǤ롥
-
- super`(' .. `)'
-
-ȤȤ˥ѡ饹Ʊ̾Υ᥽åɤƤӽФֺǸΰ
-`*'³̾Υ᥽åɸƤӽФƱͤŸϤ롥
-
-**
-
-:
-
- foo = bar
- foo[0] = bar
- foo.bar = baz
-
-ѿʤɤͤꤹ뤿Ѥ롥ϱ黻ҷȤ
-Ƥ뤬᥽åɤǤϤʤΤǺ뤳ȤϤǤʤդˤʤ뤳
-Τϰʲ3μǤ롥
-
-ѿ(`$'̻ | `@'̻ | ̻)
-
- ѿ `='
-
-ѿؤϱդμɾ줿ͤդǻꤵ줿ѿ
-롥
-
-󻲾([..])
-
- 1`[' 2.. `]' `=' n
-
-󻲾ȼؤϡ1ɾ륪֥Ȥˡ2鼰n
-ޤǤȤơ"[]=" Ȥ᥽åɤƤӽФ
-
-°(`.'̻)
-
- 1 `.' ̻ `=' 2
-
-°(ʤΥ᥽åɸƤӽФ)ؤϡ1ɾ
-֥(쥷Фά줿`self')Фơ"̻="Ȥ
-᥽åɤ 2ȤƸƤӽФ
-
-**
-
-:
-
- foo += 12
-
-ͤΤΤ˱黻ä뤿˼롥
-
- 1 op= 2 # 1ǽǤʤФʤʤ
-
-ηŪˡּ1 = 1 op 2פƱͤɾ롥1
-1󤷤ɾʤΤǡ1Ѥϡּ1 = 1 op 2
-Ȥưۤʤ̤Ȥʤ롥opȤƻȤ黻Ҥ
-
- +, -, *, /, %, **, &, |, ^, <<, >>
-
-11Ǥ롥黻Ҥ`='δ֤˥ڡƤϤʤ
-
-** ¿
-
-:
-
- foo, bar, baz = 1, 2, 3
- foo, = list()
- foo, *rest = list2()
-
-ƱʣѿԤʤȤǤ롥ηϰʲ̤Ǥ롥
-
- `,' [ `,'..] [`*' ]= [, ..]
-
-դˤ3μ롥դμĤʤϡ
-Ȥ(ɬפʤto_a᥽åɤѴ)Ǥ򤽤줾캸
-դ롥ʳξˤϡ줾μͤդ롥
-դοȱդǤοʤˤ­ʤѿˤ nil졤
-;äǤ̵뤵롥¿κǸǤ`*'硤Ĥ
-ưȤ롥
-
- foo, bar = [1, 2] # foo = 1; bar = 2
- foo, bar = 1, 2 # foo = 1; bar = 2
- foo, bar = 1 # foo = 1; bar = nil
-
- foo, bar, baz = 1, 2 # foo = 1; bar = 2; baz = nil
- foo, bar = 1, 2, 3 # foo = 1; bar = 2
- foo,*bar = 1, 2, 3 # foo = 1; bar = [2, 3]
-
-¿ͤ(Ѵ줿)դǤ롥
-
-** 黻Ҽ
-
-:
-
- 1+2*3/4
-
-ץߥ󥰤ؤΤ˰Υ᥽åɸƤӽФ湽¤ϱ黻ҷ
-Ȥ롥Rubyˤϰʲˤ黻Ҥ롥ΤΤۤɷ̤
-Ʊα黻Ҥη̤ƱǤ롥
-
- [](󻲾), []=()
- -(unary) +(unary) ! ~
- **
- * / %
- + -
- << >>
- &
- | ^
- > >= < <=
- <=> == != =~ !~
- &&
- ||
- .. ...
- ::
- =() (+=, -=,..)
- and
- or
- if while
-
-ۤȤɤα黻ˤϥ᥽åɸƤӽФȤƲᤵ(饹˺
-Ǥ)ǤʤüʤΤ롥Ǥʤü黻
-
- =(), ...(ϰ), !(), &&(), and, |(), or,
- if, while
-
-9Ĥα黻ҤȤȤȤ߹碌ˤʤ !=, !~ Ӽ黻
-Ǥ롥
-
-Ǥü黻Ұʳα黻ҷϰʲΤ褦ʥ᥽åɸƤӽФȸ
-ʤ롥
-
-ñ黻(+, -, ~)
-
- 1. 黻 ()
-
-(Ϣޤ)Ǥλ(1 `[' 2.. `]')
-
- 1. `[]' (2..)
-
-Ǥ( 1 `[' 2.. `]' `=' n)
-
- 1. `[]=' (2.., n)
-
-ʳ2黻(1 黻 2)
-
- 1. 黻 (2)
-
-ϤޤǤ⤽Υ᥽åɸƤӽФȤƲᤵȤ
-ǡrubyץǤҤȤ櫓ǤϤʤ
-
-** ̤ˤ륰롼ԥ
-
-:
-
- (1+2)*3
-
-ϳ̤ˤäƥ롼ԥ󥰤뤳ȤǤ롥
-
- `(' `)'
-
-** IF
-
- if 1 [then]
- ..
- [elsif 2 [then]
- .. ]..
- [else
- .. ]
- end
-
-ȽǼRubyifelse ifǤelifǤʤelsififϢ³Ԥʤ
-Ȥդ뤳ȡ郎ΩƼ¹Ԥ֤ͤ¹Ԥʤä
-ͤnil
-
-ifξȽμǤʸɽƥϼ$_=~ ƥפ
-άǤȤߤʤ롥
-
-** IF
-
- if
-
-、(if)μԤ뼰äɾ롥ưбif
-ƱͤǤ롥ifҤΤĤͤϾ郎Ωˤϼ͡
-ΩξˤnilǤ롥
-
-** CASE
-
- case 0
- [when 1 [, 2].. [then]
- .. ]..
- [else
- .. ]
- end
-
-ʬCswitchPascalcase˻Ƥ롥breakæФ뤳Ȥ
-μ˷³뤳ȤʤΤա
-
-ΰפϡּn =~ 0]ǹԤʤ롥Ĥޤꡤ
-
- case expr0
- when expr1, expr2
- stmt1
- when expr3, expr4
- stmt2
- else
- stmt3
- end
-
-ϰʲifȤۤǤ롥
-
- _tmp = expr0
- if expr1 =~ _tmp || expr2 =~ _tmp
- stmt1
- elsif expr3 =~ _tmp || expr4 =~ _tmp
- stmt2
- else
- stmt3
- end
-
-** AND
-
- 1 `&&' 2
- 1 `and' 2
-
-1ɾͤ(nilʳ)ǤС2ɾ롥`and'ͥ
-̤㤤̾Ǥ롥
-
-andξդμǤʸɽƥϼ$_=~ ƥפξά
-Ȥߤʤ롥
-
-** OR
-
- 1 `||' 2
- 1 'or 2
-
-1ɾͤǤС2ɾ롥`or'̤ͥ㤤
-̾Ǥ롥
-
-orξդμǤʸɽƥϼ$_=~ ƥפξά
-Ȥߤʤ롥
-
-** ϰϻ꼰
-
- 1 `...' 2
-
-1ˤʤޤǤϵ֤θϼ2֤ޤǤϿ֤2
-ˤʤо֤ϵ롥
-
-`...'ξդμǤʸɽƥϼ$_=~ ƥפξά
-ϡ$.==פξάȲᤵ롥
-
-** NOT
-
- `!'
-
-ǤеǤп֤
-
-`!'Ǥʸɽƥϼ$_=~ ƥפξάǤȤ
-ʤ롥
-
- 1 `!=' 2
-
-!(1 == 2)פξά
-
- 1 `!~' 2
-
-!(1 ~= 2)פξά
-
-** WHILE
-
- while
- ..
- end
-
-ɾͤδ֡򷫤֤¹Ԥ롥whileͤnilǤ롥
-
-whileξȽμǤʸɽƥϼ$_=~ ƥ
-ξάǤȤߤʤ롥
-
-** WHILE
-
- ñ㼰 while
-
-֤(while)ϤޤԤ뼰ɾƤPɾ
-ǡ٤ϼ¹Ԥ뤳Ȥˤʤ롥whileҤΤĤͤnil
-롥
-
-** ƥ졼(֤)
-
-ƥ졼Ȥ湽¤(ä˥롼)ݲΤѤ᥽åɤ
-Ǥ롥ɤ(֥åȸƤФ)ꤷƥƥ졼Ƥ
-Фȡƥ졼Ŭͤ򥻥åȤƥ֥åɾ(餯
-ʣ)ƥ졼Υ֥åθƤӽФyieldѤ()
-
-ƥ졼θƤӽФϰʲιʸǹԤʤ롥
-
- `{' ռ.. `|' .. `}'
-
-ּפ֥åȤꤷּפΥ᥽åɤ򥤥ƥ졼Ȥɾ
-롥ּפΥȥåץ٥Υ᥽åɤƥ졼ȤƸƤӽФ졤
-쥷Фɽ䡤μϥƥ졼ȤƤϸƤӽФʤּ
-ʣμޤơƥ졼Ȥƽ˸ƤФ롥
-
-ƥ졼yield¹Ԥȡǻꤵ줿ͤռǻꤵ
-줿ѿ졤֥å¹Ԥ롥֥åμ¹ԤλȤ
-ͤ yieldͤȤ֤롥᥽åɤƥ졼ȤƸƤӽ
-줿ɤϥ᥽åiterator_p()ͤΤ뤳ȤǤ롥ˤ
-Enumerable⥸塼grep᥽åɤΤ褦˥ƥ졼ȤƸƤФ줿
-̤Υ᥽åɤȤƸƤФ줿Ȥưۤʤ᥽åɤ⤢롥
-
-** FOR
-
-֥ȤγǤФԤʤη󶡤Ƥ롥
-ϰʲ̤ꡥ
-
- for ռ.. in
-
- end
-
-γǤФ¹Ԥ롥ϰʲμǤ롥
-
- ().each `{' ռ.. `|' `}'
-
-äƼͤΥ֥Ȥ᥽åeachʤ硤for¹Ԥ
-㳰ȯ롥
-
-** YIELD
-
- yield `(' [ [`,' ..]])
- yield
-
-ƥ졼ǥ֥åθƤӽФԤʤyield¹Ԥ᥽åɤ
-ƥ졼ȤƸƤӽФƤʤˤ㳰ȯ롥yield ͤϥ
-åͤǤ롥
-
-yieldΰγ̤ۣǤʤ¤άǤ롥
-
-** FAIL
-
- fail `(' [å] `)'
-
-㳰ȯ롥åͿ줿ˤȯե
-ֹ̾򥷥ƥѿ`$@'ˡå`$!'˥åȤ롥
-
-failΰγ̤ϾάǤ롥
-
-** BEGIN
-
-ʣμޤȤ뤿㳰Τbegin롥beginη
-ʲ̤Ǥ롥
-
- begin
- ..
- [resque
- .. ]
- [ensure
- ..]
- end
-
-beginͤϰֺǸɾ줿ͤǤ롥beginνȯ
-㳰resqueͤ뤳Ȥ롥ξbeginͤ
-resqueǺǸɾͤǤ롥ensure᤬¸ߤ
-beginλɬ(ェλǤʤ㳰, return, break,
-continue, redoʤɤˤæФǤ)ensureμɾ롥
-
-** RETRY
-
- retry
-
-beginresqueǻȤbeginϤᤫ⤦ټ¹Ԥ롥㳰
-ԤʤäƤƻԤΤ˻ȤresqueʳretryѤ줿
-ȯ롥
-
-** RETURN
-
- return [[`,' ..]]
-
-ͤͤȤƥ᥽åɤμ¹Ԥλ롥2İʾͿ줿
-ˤϡǤȤ᥽åɤͤȤ롥Ĥʤ
-ˤ nil ͤȤʤ롥
-
-** BREAK
-
- break
-
-break ϥ롼פæФ롥CȰ㤤breakϤäȤ¦Υ롼פæФ
-Ѥcase ȴѤϻʤ
-
-** CONTINUE
-
- continue
-
-continueϤäȤ¦Υ롼פμη֤Ϥ롥
-
-** REDO
-
- redo
-
-redoϥ롼׾ΥåԤʤ鷺ߤη֤ľ
-
-** 饹
-
-饹빽ϰʲ̤Ǥ롥
-
- class 饹̾ [`:' ѡ饹̾ ]
-
- end
-
-饹̾ʸǻϤޤ뼱̻ҤǤ롥
-
-** ⥸塼
-
-⥸塼빽ϰʲ̤Ǥ롥
-
- module 饹̾
-
- end
-
-⥸塼̾ʸǻϤޤ뼱̻ҤǤ롥
-
-** ᥽å
-
-̾(ðۥ᥽åɤǤʤ)᥽åηϰʲ̤Ǥ롥̾᥽
-ϥͥȤǤʤΤǡ᥽åǤϥ᥽åƤӸ
-ӽФʤ
-
- def ᥽å̾ [`(' [`,' ..][`,' `*' ] `)']
-
- end
-
-᥽å̾ϼ̻ҤޤʸǤ롥黻Ҥκ򤹤ˤʸ
-ǻꤹ롥¤ӤκǸ`*'硤¿Ϳ줿
-°ϡǸΰȤͿ(­ʤˤϥ顼)
-
-
-᥽åɤˤϸƤӽФ¤ä뤳ȤǤ¤ä줿᥽åɤϡ
-ؿǤƤӽФʤ(private᥽å)
-
-˥᥽åɤ硤饹γˤdefϥǥե
-Ǥprivate᥽åɤ饹ˤdefpublic᥽
-ɤ롥ѡ饹Υ᥽åɤˤ
-åɤβĻϥѡ饹Υ᥽åɤΤΤѤ
-
-᥽åɤβĻѹˤModule饹Ƥpublic,
-privateγƥ᥽åɤѤ롥
-
-** ðۥ᥽å
-
-᥽åˤϤ⤦ðۥ᥽åɤ롥ðۥ᥽åɤȤϤ
-Υ֥Ȥ˸ͭΥ᥽åɤǤ롥ϰʲ̤Ǥ롥
-
- def `.' ᥽å̾ [`(' [`,' ..][`,' `*' ] `)']
-
- end
-
-ηϼͤǤ륪֥Ȥðۥ᥽åɤ롥ͤ
-(ӥȥ󥯥饹Ǥʤ)̾索֥Ȥ饹ޤϥ⥸塼Ǥ
-ɬפ롥̾᥽åȤϰۤʤꡤðۥ᥽åɤϥ᥽å
-ǤͥȤ뤳ȤǤ롥
-
-ðۥ᥽åɤ̾ϷѾʤ㳰Ȥƥ饹ðۥ᥽åɤϤ
-֥饹ˤѾ롥ؤХ饹ðۥ᥽åɤ¾Υ֥
-Ȼظƥˤ륯饹᥽åɤƯ򤹤롥
-
-: 󥯥롼ɤ⥸塼ðۥ᥽åɤϷѾʤ
-
-** ALIAS
-
-ʲηǥ᥽åɤ̾Ĥ뤳ȤǤ롥
-
- alias ᥽å̾1 ᥽å̾2
-
-̾դ줿᥽åɤϡλǤΥ᥽åѤΥ
-åɤƤ⡤θŤ᥽åɤƤӽФ줿ΤƱ
-Ư򤹤롥
-
-** UNDEF
-
-᥽åɤäˤundefѤ롥
-
- undef ᥽å̾
-
-ꤷ᥽åɤä
-
-defˤ̾undefˤäˤäƥ饹Υ󥿥ե
-򥹡ѡ饹Ωѹ뤳ȤǤ롥᥽åɤself
- ˥åäƤ⤢Τǡ褯դʤȴ¸Υ᥽
-ɤưʤʤǽ롥
-
-* Ȥ߹ߴؿ
-
-Rubyˤϸ̩ʰ̣ǤϴؿϤʤKernel饹δؿ᥽åɤ(Ƥ
-̾說饹ؿǸƤӽФΤ)ؿŪѤ롥ؿŪ
-Ѥ᥽åɤʲˤ롥Υ᥽åɤݤˤϸ
-ͤƹԤʤ٤Ǥ롥
-
- _exit(status)
-
- ץμ¹Ԥλ롥statusλơȤ롥
- exit()Ȥϰäơ㳰ʤɤϰڹԤʤʤfork()θ塤
- ץλʤɤѤ롥
-
- eof()
-
- ޥɥ饤󤫤ϤEOFãƤ硤֤
-
- eval(expr)
-
- exprȤͿ줿ʸrubyץȤƲᡤ¹Ԥ롥
-
- exec(command)
-
- ߼¹ԤƤץλơcommandʸǻꤵ
- ̥ץư롥
-
- exit([status])
-
- ץμ¹Ԥλ롥statusȤͿ줿硤
- ͤRubyޥɤνλơȤ롥ǥեȤ0
-
- fork()
-
- forkƥॳ¹Ԥҥץ롥ܺ٤
- fork(2)򻲾ȤΤȡƥץ¦ǤϻҥץΥץid
- ֤ҥץ¦Ǥnil֤餫θǻҥץ
- ˼Ԥˤ㳰ȯ롥
-
- format(format, ...)
-
- եޥåȤȤͿ줿ʸCsprintfƱ褦
- ᤷŸʸ֤᥽åsprintf()̾
-
- RubyˤformatҤγĥˤĤƤsprintf()ι򻲾Ȥ
- ȡ
-
- getc()
-
- ɸϤʸФͤɤ߹ʸʸ
- (ASCII)ɽFixnumǤ롥
-
- gets()
-
- ȤͿ줿ե(ʤɸ)ǹ벾
- Ūʥե(ƥѿ`$<'ǥǤ)ɤ߹
- ǡɤ߹ߤˤϤʸ֤եν
- ãˤnil֤Ԥζڤϥƥѿ`$/'ˤä
- ѹǤ롥ɤ߹ʸϥƥѿ`$_'ˤ⥻åȤ롥
-
- gsub(pattern[, replace])
-
- ƥѿ`$_'λؤʸ pattern˥ޥåʬ
- replace֤롥String饹gsub᥽åɤβ򻲾Ȥ
- ȡreplaceά줿ˤϥƥ졼Ȥư
- åɾִ̤롥 gsub᥽åɤ`$_'ͤ򹹿
- 롥
-
- iterator_p()
-
- ᥽åɤƥ졼ȤƸƤӽФ줿˿Ǥʤ˵
- ֤Ҹ졥
-
- kill(signal, pid..)
-
- pidǻꤵ줿ץ˥ʥ롥ʥϥʥ
- 椫̾ǻꤹ롥ͤĥʥ(뤤ϥʥ̾
- `-')ͿȥץǤϤʤץ롼פ˥ʥ
- 롥
-
- load(file)
-
- fileɤ롥fileɤѥϥƥѿ$LOAD_PATH
- Ƿꤵ롥
-
- open(file[, mode])
-
- file򥪡ץ󤷤ơFile֥Ȥ֤ե̾ϥ
- 󤹤ե򼨤ե̾`|'ǻϤޤˤ³ʸ
- 򥳥ޥɤȤƵưѥץ饤롥
-
- ޥ̾"-"Ǥopen()Rubyλҥץ
- λҥץȤΥѥפ֤
-
- modeϥեΥ⡼ɤꤹ롥ϰʲΤΤ
- 줫ʸǤ롥
-
- r ɤ߹ѡopenեϤ餫¸ߤƤ
- ɬפ롥
-
- r+ ɤ߽ξѡopenեϤ餫¸ߤƤ
- ɬפ롥
-
- w 񤭹ѡե뤬¸ߤƤ硤Ĺ0ˤ
- 롥¸ߤƤʤп˥ե롥
-
- w+ ɤ߽ξѡɤ߹ߤԤʤ뤳Ȱʳ"w"ƱƯ
- 򤹤롥
-
- a ɲý񤭹ѡեϤ餫¸ߤƤɬ
- 롥񤭹ߤϥեκǸɲä롥
-
- a+ ɤ߽ξѡե뤬¸ߤƤʤп˺
- 롥֤ϥեκǸ˽롥
-
- ⡼ɤά줿ΥǥեȤ"r"Ǥ롥
-
- print(arg1, ..., argn)
-
- ˽Ϥ롥Ϳʤˤϥ쥷ФϤ롥
- ʸʳΥ֥ȤȤͿ줿ˤϡ
- ֥Ȥto_s᥽åɤˤäʸѴƤϤ롥
- ƥѿ`$;'(ϥեɥѥ졼)nilǤʤͤ
- ȤƤˤϡưδ֤ˤʸϤ롥ƥ
- ѿ`$\'(ϥեɥѥ졼)nil ǤʤͤåȤ
- ˤϡǸˤϤ롥
-
- printf([port, ]format, arg1, ..., argn)
-
- Cprintf()Ʊformat˽ʸѴϤ
- 롥1IOΥ֥饹Υ󥹥󥹤ǤäϤΥ
- ֥ȤФƽϤԤʤǥեȤ$stdout˽Ϥ롥
-
- RubyˤformatҤγĥˤĤƤsprintf()ι򻲾Ȥ
- ȡ
-
- rand(max)
-
- 0maxۤʤϰϤȯ롥ͤFixnum
-
- require(file)
-
- fileɤ롥loadȤưΰ㤤ϳĥҤäƤ
- ɤեΥեѥѿ`$"'˳ФƤƴ˥ɤ
- եϺƥɤʤȥʥߥåǥ󥰤б
- Ƥ(OS ˤ)Ǥ롥ºݤ˥ɤˤ TRUE˥
- ɤƤˤFALSE֤
-
- select(reads[, writes[, execpts[, timeout]]])
-
- select(2)¹Ԥ롥reads/writes/execptsˤIO(ޤϤΥ
- 饹)Υ󥹥󥹤Ϳ롥timeoutFixnum / Float
- / TimeΤ줫ǻꤹ롥ͤtimeoutΩˤ
- nilǤʤȤ3Ǥ֤γǤ//
- 㳰ԤΥ֥ȤǤȤƻġ
-
- sleep([sec])
-
- secäץμ¹Ԥߤ롥secά줿硤ץ
- SIGALRMʤ¤ꡤʵפ˥꡼פ롥ºݤ˥꡼
- פÿ֤
-
- sprintf(format, ...)
-
- formatʸCsprintfƱ褦˲ᤷŸ
- ʸ֤᥽åformat()̾
-
-
- formatҤCsprintf()դ(Ruby
- unsignedʤΤǡ%uϽ)˲ä, %b, %B, %O, %XȤ
- ȤǤ롥%bϿͤ2ɽ%B, %O, %XϤ줾2ʡ8ʡ
- 16ʿɽԤʤονκݤ2ɽǤϤʤ
- ɽƬ`-'ĤΤɽ롥
-
- srand([])
-
- νͤꤷŤ֤ͤͤά줿
- time(3)֤ͤǥեȤȤ롥
-
- sub(pattern[, replace])
-
- ƥѿ`$_'λؤʸǺǽpattern˥ޥåʬ
- replace֤롥replace ά줿ˤϥƥ졼
- Ȥư֥åɾִ̤롥sub᥽åɤ
- `$_'ͤ򹹿롥¾ξܺ٤˴ؤƤString饹sub
- åɤβ򻲾ȤΤȡ
-
- syscall(num, arg..)
-
- numǻꤵ줿ֹΥƥॳ¹Ԥ롥2ʹߤ
- ƥॳΰȤϤʸޤǤʤ
- ʤʤ
-
- system(command)
-
- ޥɤ¹Ԥνλơ֤
-
- trap(command, signal..)
-
- signalγߤäcommand¹Ԥ롥signalϥ
- ʥ̾ʥֹ桥commandȤ"SIG_IGN"ޤ"IGNORE"
- ꤷˤϤΥʥ̵뤹(ǽʤ)"SIG_DFL"
- "DEFAULT"ꤷϥǥեȤưԤʤ
-
- wait()
-
- ҥץλΤԤλҥץpid֤
- ҥץĤʤnil֤
-
- waitpid(pid, flags)
-
- λҥץνλԤΥץλ˿
- ҥץ¸ߤʤΥ֥å󥰥⡼ɤǻҥץ
- ޤλƤʤˤnil֤waitpid(2)wait4(2)
- ƤʤޥǤflagsϤĤnilޤ0ǤʤФ
- ʤ
-
-* Ȥ߹ѿ
-
- $! 顼åfailꤹ롥
-
- $@ 顼ȯΥե̾ȹֹ椬
-
- "ե:ֹ[:᥽å̾()]"
-
- ηdzǼ롥
-
- $& Ǹѥޥå
-
- $` ǸΥѥޥåǥޥåʸʸ
-
- $' ǸΥѥޥåǥޥåʸθ³ʸ
-
- $+ ǸθѥǥޥåǸγ
-
- $1..$9 Ǹѥޥånܤγ̤˥ޥå
- ͤǼ롥̤ʤniläƤ롥
-
- $~ ǸΥޥå˴ؤ󡥤򥻥åȤ$&$1..$9
- ͤѲ롥
-
- $= ѿͤnilǤʤѥޥåʸ
- Ӥǥե٥åȤʸʸ̤ʤǥե
- Ȥnil(̤)
-
- $/ ϥ쥳ɥѥ졼եʸФeach
- Ԥʤʬʸꤹ롥$/˶ʸ("")ꤹ
- ñ̤ϤԤʤnilꤹΤ
- ɤ߹ࡥ$/ˤɽϻȤʤǥեȤ
- "\n"
-
- $\ ϥ쥳ɥѥ졼ѿʸꤹ
- write()print()٤˺ǸˤʸղäƽϤ
- 롥ǥեȤnil(ʤˤɲäʤ)
-
- $, Array:join()ΥǥեȤζڤʸprint()γư
- δ֤˽Ϥʸ
-
- $; String:split()ΥǥեȤζڤʸ
-
- $. Ǹɤϥեιֹ桥
-
- $< (ʤɸ)ǹ벾ۥե롥Ĥޤ
- gets()$<.gets()Ʊ̣Ǥ롥$<.fileǸɤ߹
- Υե륪֥Ȥ$<.filenameǤΥե
- ̾롥(Ф: `<'ϥϸ)
-
- $> printprintfΥǥեȤν补ͤ$stdout-i
- ץꤷˤɤ߹߸Ʊ̾Υե
- 롥(Ф: `>'ϥν)
-
- $_ Ǹgets()ʤɤɤ߹ʸ
-
- $0 rubyץȤ̾ѿps(1)ν
- Ѳ롥
-
- $* rubyץȤͿ줿rubyȤФ
- Ƥ롥
-
- $$ ߼¹rubyץpid
-
- $? Ǹ˼¹Ԥҥץstatus
-
- $: եɤ˸ǥ쥯ȥؤΥѥ
- ޤ󡥵ưˤϥǥե(ѥ˻ꤹ
- )˲äơĶѿRUBYLIBͤrubyư-Iץ
- ǻꤵ줿ͤɲä롥(Ф: ϴĶ
- PATHζڤʸǤ)
-
- $" ˥ɤ줿ե̾ޤrequire()Ʊ
- ե2ɤʤѤ롥(Ф:
- prevent files to be doubly quoted(loaded))
-
- $ARGF $<̾
-
- $ARGV $*̾
-
- $DEBUG `-d'ե饰ξ()
-
- $FILENAME ۥե`$<'Ǹɤ߹(᥽ågets()
- ɤǤ)ե̾$<.filenameƱ
-
- $LOAD_PATH $:̾
-
- $stdin ɸ
- $stdout ɸ
- $stderr ɸ२顼
-
- $VERBOSE `-v'ե饰ξ()
-
- TRUE t
- FALSE nil
-
- 줾쿿ͤɽȽǤnil򵶡ʳƤͤ
- ȤȽǤ뤿ᡤTRUEͤɽŪʿͤȤʾΰ̣
- ʤäơ᥽åɤͤǤȤȤȡ
- 줬TRUE֤ȤȤϸ̩ˤƱǤϤʤ(ҸŪѤ
- ᥽åɤ񿿤ͤȤTRUE֤褦ˤϤʤäƤ뤬)
- Ĥޤ
-
- if some.method() then ... else ... end
-
-
-
- if some.method() == TRUE then ... else ... end
-
- ϴˤƱǤϤʤFALSE˴ؤƤϡΤ褦
- ʤ
-
- STDIN ɸ
- STDOUT ɸ
- STDERR ɸ२顼
-
- ENV Ķѿ˥Ϣʸ򥭡ȤͿ
- бĶѿͤ롥Ķѿ¸ߤ
- nil֤롥
-
- KCODE бƤɤɽʸ"EUC","SJIS"ޤ
- "NONE"
-
- VERSION rubyΥС򼨤ʸ
-
-* Ȥ߹ߥ饹ȥ⥸塼
-
-** Array(饹)
-
-źȤΥ饹Ǥ롥ϰŪˤ``[..]''
-Ԥʤ롥
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- self[nth]
- self[start..end]
- self[start, length]
-
- Ǥ˥롥ǽηǤnthܤǤ
- ֤2ܤηǤstartܤǤendܤǤޤ
- ʬ֤3ܤηǤstartܤlengthĤǤޤ
- ʬ֤
-
- self[nth] = val
- self[start..end] = val
- self[start, length] = val
-
- Ǥѹ롥ǽηǤnthܤǤval
- ѹ롥2ܤηstartܤǤendܤǤޤǤ
- valѹ롥3ܤηǤstartܤlengthĤǤval
- ѹ롥
-
- 2ܡ3ܤηǤvalǤʤФʤʤ
-
- :
-
- ary = [1, 2, 3, 4, 5]
- ary[0..2] = [0, 0] # Ƥ [0, 0, 4, 5]
- ary[1, 0] = [7] # Ƥ [0, 7, 0, 6, 5]
-
- self + other
-
- Ϣ롥selfotherξƤҤ
- ֤
-
- self * times
-
- η֤
-
- self - other
-
- κ黻selfotherǤƤο
- ֤ʣǤ1٤롥
-
- self * other
-
- ѱ黻ξ˴ޤޤǤʤ뿷֤
- ʣǤ1٤롥
-
- self | other
-
- ±黻ξˤ줫˴ޤޤǤƴޤ࿷
- ֤ʣǤ1٤롥
-
- self << obj
-
- objɲä롥self֤ΤC++ŪϢǤ롥
-
- assoc(key)
-
- Ϣۥꥹ(assocڥǤȤ)򸡺1Ǥkey
- ("=="Ӥ)֤
-
- clear
-
- 礭0ˤ롥
-
- delete(val)
-
- valȰפǤ롥
-
- delete_if
-
- Ǥ륤ƥ졼֥åɾͤλб
- Ǥ󤫤롥
-
- each
-
- γǤͿ륤ƥ졼
-
- fill(val)
- fill(val, start[, length])
- fill(val, start..end)
-
- (λꤵ줿ʬ)Ǥͤvalꤹ롥2֤η
- lengthά줿νޤǤĹȤ롥ꤵ줿
- ʬ󤬸ϰϤۤϼưŪ˳ĥ롥
-
- index(val)
-
- valǽǤΥǥå֤Ǥ¸
- ʤnil֤
-
- indexes(ary)
- indexes(index-1, ..., index-n)
-
- 1ܤηǤȤƼơǤ򥤥ǥ
- ȤǤޤ֤2ܤηǤϳưͤ
- ǥåȤǤޤ֤
-
- join([sep])
-
- ǤϢ뤷ʸ֤ǤʸѴ졤
- sep򶴤Ϣ뤵롥sepά줿ˤϥƥѿ`$,'
- ͤѤ롥
-
- length
- size
-
- Ĺ(ǿ)֤
-
- push(obj)
-
- objɲä롥
-
- pack(template)
-
- Ƥtemplateʸˤäơ1Ĥʸ˥ѥå
- 롥ѥåʸ֤ƥץ졼ȤϷʸȤĹ
- (ά1)¤٤ΤǤ롥ĹȤ`*'ꤵ줿
- ֻĤΥǡơפĹɽ
-
- ʸϰʲΤΤ롥
-
- a ASCIIʸ(nullʸͤ)
- A ASCIIʸ(ڡͤ)
- b ӥåȥȥ(̥ӥåȤ̥ӥå)
- B ӥåȥȥ(̥ӥåȤ鲼̥ӥå)
- h 16ʸ(̥˥֥뤬)
- H 16ʸ(̥˥֥뤬)
- c char
- C unsigned char
- s sort
- S unsigned sort
- i int
- I unsigned int
- l long
- L unsigned int
- n ͥåȥХȥshort
- N ͥåȥХȥlong
- f ñư(¸)
- d ư(¸)
- x ʥХ
- X 1Хȸ
- @ а֤ؤΰư
-
- pop
-
- Ǥơ֤
-
- rassoc(value)
-
- Ϣۥꥹ(2ǤǤȤ)򸡺2Ǥ
- value("=="Ӥ)֤
-
- shift
-
- ƬǤơ֤
-
- sort
-
- Ƥ򥽡Ȥ롥ƥ졼ȤƸƤӽФ줿ϥ֥
- ɾͤǤ羮ꤹ롥礭
- 0顥̾Υ᥽åɤȤƸƤӽФ줿ϳ
- `<=>'Ӥ롥
-
- to_a
-
- ʬȤ֤оΤѰդƤ᥽åɤǤޤ
- 򤯤ʤ
-
- unshift(obj)
-
- objƬɲä롥
-
-Single Methods:
-
- Array[item..]
-
- ǤȤ롥
-
-** Assoc(饹)
-
-ǡ(ڥ)ɽ륯饹̾`::'黻ҤѤƹԤʤ
-롥
-
-SuperClass: Object
-
-Methods:
-
- car
-
- CONSڥΥǡCAR֤
-
- car=(val)
-
- CONSڥCARΥǡѹ롥
-
- cdr
-
- CONSڥΥǡCDR֤
-
- cdr=(val)
-
- CONSڥCDRΥǡѹ롥
-
-** Bignum(饹)
-
-̵¿ĹΥ饹黻η̤FixnumϰǤˤϼ
-ưŪ˥饹FixnumѴ롥ŪRubyץǤFixnum
-BignumѴϰۤΤ˹ԤΤǡռɬפ̵FloatȤ
-˴ؤƤϡBignum Floatgenericity⤤Τˤؤ餺
-Bignum礭ͤɽǤΤǡѴ˷ǽ
-롥
-
-
-SuperClass: Integer
-
-Methods:
-
- self + other
- self - other
- self * other
- self / other
- self % other
- self ** other
-
- ѱ黻줾¡ѡ;Ѿ֤
-
- ~ self
- self | other
- self & other
- self ^ other
-
- ӥåȱ黻줾ӥåȿž¡ѡ¾Ū¤
- ֤
-
- self << bits
- self >> bits
-
- եȱ黻줾bitsӥåȤ˥ӥåȥեȤԤʤ
-
- divmod(other)
-
- Ⱦ;2Ǥ֤
-
-** Block(饹)
-
-ƥ졼Ϥ³ޤȤ᤿֥ȡ¹Ԥ륳ɤ
-ʤƥ(ѿ)ʤɤ¸롥
-
-SuperClass: Object
-
-Methods:
-
- call(arg[,..])
-
- ֥å¹Ԥ롥
-
-Single Methods:
-
- new
-
- ֥å롥yield¹ԤǤǤΥ᥽å
- ƤФȡλǼ¹Ԥ٤ɤ߹֥
- (Block)롥
-
-** Class(饹)
-
-饹Υ饹긷̩ȥ饹ðۥ᥽åɤѾ뤿
-ˡ줾᥿饹ȸƤФ̾Τʤ饹򥯥饹Ȥƻ
-ClassϤΥ᥿饹Υ饹Ǥ(ʬä?)β⤬
-ǤʤƤ⡤RubyȤȤ˲λپʤ饹ˤðۥ᥽åɤ
-Ǥȡѡ饹줿ðۥ᥽åɤϤΥ֥饹
-ǤͭǤΤнʬǤ롥
-
-SuperClass: Module
-
-Private Methods:
-
- attr(name[, public])
-
- Υ饹Υ󥹥󥹤Фnameǻꤵ°롥
- ܤModuleattr᥽åɤι򻲾ȤΤȡ
-
-Methods:
-
- new(..)
-
- 饹Υ󥹥󥹤롥¿ξ礳Υ᥽åɤϥ֥
- 饹ðۥ᥽åɤˤäƥС饤ɤ졤饹ˤäư
- ۤʤ롥
-
-** Comparable(⥸塼)
-
-ӱ黻饹ΤMixinΥ⥸塼򥤥󥯥롼ɤ뤳
-Ȥˤäơ`<=>'黻Ҥ¾α黻ҤϤѤ
-Ǥ롥
-
-Methods:
-
- self == other
-
- selfother֤
-
- self > other
-
- selfother礭֤
-
- self >= other
-
- selfother礭֤
-
- self < other
-
- selfother꾮֤
-
- self <= other
-
- selfother꾮֤
-
- between(min, max)
-
- selfminmaxϰˤ֤
-
-** Dir(饹)
-
-ǥ쥯ȥǤ֤ǥ쥯ȥꥹȥ꡼ΤΥ饹
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- close
-
- ǥ쥯ȥꥹȥ꡼򥯥롥ʸ㳰ȯ
- 롥
-
- each
-
- ǥ쥯ȥγǤͿ륤ƥ졼
-
- getwd
- pwd
-
- ȥǥ쥯ȥ֤
-
- rewind
-
- ǥ쥯ȥꥹȥ꡼Ƭ˥ꥻåȤ롥
-
- seek(pos)
-
- ǥ쥯ȥꥹȥ꡼ΰ֤posꤹ롥
-
- tell
-
- ǥ쥯ȥꥹȥ꡼θߤΰ֤֤
-
-Single Methods:
-
- self[pat]
- glob(pat)
-
- ʸpatshΥ磻ɥɤȤŸ̤ʸ
- Ȥ֤񼰤ϰʲ̤Ǥ롥
-
- * Ǥդʸ(ʸޤ)Ȱ
- ? Ǥդ1ʸȰ
- [ ] []Τ줫1ʸȰ
- {..} {}(ޤǶڤ줿)줫ʸ
-
-
- chdir(path)
-
- ȥǥ쥯ȥpathѹ롥
-
- chroot(path)
-
- ץΥ롼ȥǥ쥯ȥѹ롤Ʊ̾Υƥॳ
- ƱƯ򤹤롥ϼ¸uidѥ桼Ǥ
- ¤Ƥ롥롼ȥǥ쥯ȥ򸵤᤹(롼ȥǥ쥯
- ѹ)ˡ󶡤Ƥʤ
-
- mkdir(path[, mode])
-
- modeǻꤵ줿⡼ɤĥǥ쥯ȥpath롥⡼
- umaskˤäƽ롥modeΥǥեͤ0777
-
- open(path)
-
- pathФǥ쥯ȥꥹȥ꡼򥪡ץ󤹤롥
-
- rmdir(path)
-
- pathǻꤵ줿ǥ쥯ȥ롥ǥ쥯ȥ϶Ǥ
- ɬפ롥
-
-** Enumerable(⥸塼)
-
-ǤФ뷫֤Ԥʤ饹ΤMixinΥ⥸塼򥤥
-롼ɤ뤿ˤϡ᥽å`each'ɬפ롥
-
-Methods:
-
- collect
-
- ǤФƥ֥åɾ̤ƴޤ֤
-
- find
-
- ǤФƥ֥åɾͤˤʤäǽǤ֤
-
- find_all
-
- ǤФƥ֥åɾͤǤäǤƴޤ
- ֤
-
- grep(pattern)
-
- =~ patternפΩƤǤޤ֤
- 졼ȤѤ줿Ͼ嵭ξΩǤФƥ֥
- ¹Ԥ롥
-
- includes(val)
-
- val`=='δطˤǤĻ֤
-
- index(val)
-
- val`=='δطˤ륪֥Ȥܤ˸줿֤
- ֺǽǤ0ˤʤ롥Ǥ¸ߤʤˤnil֤
- ʤ饹ФƤϤޤ̣ʤ
-
- length
-
- Ǥο֤
-
- min
-
- ǾǤ֤ƤǤߤ`<=>'᥽åɤӤǤ
- 뤳ȤꤷƤ롥
-
- max
-
- Ǥ֤Ǥ`<=>'᥽åɤӤǤ뤳Ȥ
- Ƥ롥
-
- reverse
-
- ƤǤս¤٤֤
-
- sort
-
- ƤǤ򥽡Ȥ֤
-
-** Etc(⥸塼)
-
-/etcǥ쥯ȥʲξ뤿Υ⥸塼롥饹˥󥯥롼
-ƻȤȤǤ롥
-
-Methods:
-Single Methods:
-
- getlogin
-
- ʬlogin֤̾줬Ԥgetpwuid()Ѥ
- ɤ
-
- getpwnam(name)
-
- /etc/passwdե(뤤DBMեNISǡ١)
- name̾passwdȥ֤ͤpasswd¤
- ΤǰʲΥФġ
-
- struct passwd
- name # 桼̾(ʸ)
- passwd # ѥ(ʸ)
- uid # 桼ID()
- gid # 롼ID()
- gecos # gecosե(ʸ)
- dir # ۡǥ쥯ȥ(ʸ)
- shell # 󥷥(ʸ)
- # ʹߤΥФϥƥˤäƤ󶡤ʤ
- change # ѥѹ()
- quota # ()
- age # ()
- class # 桼饹(ʸ)
- comment # (ʸ)
- expire # ͭ()
- end
-
- ܺ٤getpwnam(3)򻲾ȤΤȡ
-
- getpwuid([uid])
-
- uid桼IDȤpasswdȥ֤ͤgetpwnam()
- ƱͤǤ롥άˤgetuid()ͤѤ롥ܺ٤
- getpwuid(3)򻲾ȤΤȡ
-
- getgrgid(gid)
-
- /etc/groupե(뤤ϡgetpwnam)򸡺gid򥰥롼
- IDȤ륰롼ץȥ֤ͤgroup¤Τǰʲ
- Фġ
-
- struct group
- name # 롼̾(ʸ)
- passwd # 롼פΥѥ(ʸ)
- gid # 롼ID()
- mem # 롼ץ̾
- end
-
- ܺ٤getgrgid(3)򻲾ȤΤȡ
-
- getgrnam(name)
-
- nameȤ̾Υ롼ץȥ֤ͤgetgrgid()Ʊ
- ͤǤ롥ܺ٤getgrnam(3)򻲾ȡ
-
- group
-
- ƤΥ롼ץȥ˥뤿Υƥ졼
-
- passwd
-
- Ƥpasswdȥ˥뤿Υƥ졼
-
-** File(饹)
-
-ե륢ΤΥ饹᥽åopen()롥ޤ
-饹ðۥ᥽åɤȤtestΥեƥȱ黻Υ᥽åɤ
-Ƥ(FileTest⥸塼Υ᥽åɷ)
-
-SuperClass: IO
-
-Methods:
-
- atime
-
- եκǽ֤
-
- ctime
-
- եκǽơѹ֤
-
- chmod(mode)
-
- եΥѡߥåѹ(cf chmod(2))
-
- chown(owner, group)
-
- եνͭԤȥ롼פѹ(cf chown(2))nil-1
- ꤹ뤳ȤˤäƽͭԤ䥰롼פ򸽺ߤΤޤѤʤǤ
- ȤǤ롥
-
- eof
-
- եνüã˿֤
-
- lstat
-
- ե˴ؤStat¤Τ֤lstatϥե뤬ܥ
- 󥯤ǤХ󥯤ΤΤ˴ؤStat¤Τ֤¤
- ƤˤĤƤstat򻲾ȤΤȡ
-
- mtime
-
- եκǽ֤
-
- rewind
-
- եΥեݥ󥿤ΰ֤Ƭ˰ư롥
-
- path
-
- եΥѥ֤̾
-
- seek(offset, ptrname)
-
- եΥեݥ󥿤ΰ֤offset˰ư롥ptrname
- 012Τ줫Ǥäơ줾եƬ߰֡
- եνüΤΤ줫Ф򼨤
-
- stat
-
- ե˴ؤStat¤Τ֤(Struct 򻲾)
-
- struct stat
- dev # ե¸ߤǥХ
- ino # եi-nodeֹ
- mode # ⡼
- nlink # ϡɥ󥯤ο
- uid # ͭԤΥ桼ID
- gid # ͭԤΥ롼ID
- rdev # ǥХID(ڥեΤ)
- size # ե륵(byte)
- blksize # ե륷ƥˤŬڤʥ֥å
- blocks # ֥å
- atime # ǽ
- mtime # ǽ
- ctime # ǽѹ
- end
-
- ܺ٤fstat(2)򻲾ȤΤȡƥƤ
- stat¤Τ˳Фʤ0ꤵƤ롥
-
- tell
-
- եθߤΥեݥ󥿤ΰ֤֤
-
- truncate(length)
-
- եڤΤƤƺlengthХȤˤ롥եwrite⡼
- ɤǥץ󤵤ƤʤФʤʤ
-
-Single Methods:
-
- atime(filename)
-
- filenameκǽ֤
-
- ctime(filename)
-
- filenameκǽơѹ֤
-
- chmod(mode, path, file..)
-
- եΥѡߥåѹ(cf chmod(2))ѹե
- ֤fileˤϥ磻ɥɤ
-
- chown(owner, group, file..)
-
- եνͭԤȥ롼פѹ(cf chown(2))nil-1
- ꤹ뤳ȤˤäƽͭԤ䥰롼פ򸽺ߤΤޤѤʤǤ
- ȤǤ롥ѹե֤fileˤϥ磻ɥɤ
-
-
- link(old, new)
-
- oldؤΥϡɥnew롥link(2)Ʊ¤롥
-
- mtime(filename)
-
- filenameκǽ֤
-
- readlink(path)
-
- ܥåpathƤʸȤ֤
-
- rename(from, to)
-
- ե̾fromtoѹ롥rename(2)ȡtoȤ̾
- Υե뤬¸ߤˤϤޤΥե뤬롥
-
- stat(filename)
-
- filenameΥեStat¤Τ֤
-
- symlink(old, new)
-
- oldؤΥܥånew롥
-
- truncate(path, length)
-
- pathǻꤵ줿եڤΤƤƺlengthХȤˤ롥
-
- type(filename)
-
- filenameΥեΥפɽʸ֤ʸ"file"
- "directory""characterSpecial""blockSpecial""fifo"
- "link""socket"ΤΤ줫ĤǤ롥
-
- unlink(file..)
-
- ե롥ǥ쥯ȥκˤDir.rmdirȤȡ
- fileˤϥ磻ɥɤ
-
- utime(atime, mtime, file..)
-
- եΥatimeˡmtimeꤹ롥
- atimemtimeϿޤTime饹Υ󥹥󥹤ǤʤФʤ
- fileˤϥ磻ɥɤ
-
-
- ʳFileTest⥸塼Υ᥽åɤðۥ᥽åɤȤƻġ
-
-** FileTest(⥸塼)
-
-եƥѥ᥽åɤ򽸤᤿⥸塼롥󥯥롼ɤѤ뤳
-Ǥ롥
-
-Methods:
-Single Methods:
-
- b(filename)
-
- filenameΥե뤬֥åڥեǤ
-
-
- c(filename)
-
- filenameΥե뤬饯ڥեǤ
- ֤
-
- executable(filename)
- x(filename)
-
- filenameΥե뤬¹Բǽλ֤
-
- exists(filename)
- e(filename)
- a(filename)
-
- filenameΥե뤬¸ߤ֤
-
- G(filename)
-
- filenameΥեgid¸롼פgidƱ֤
-
- isdirectory(filename)
- d(filename)
-
- filenameǥ쥯ȥλ֤
-
- isfile(filename)
- f(filename)
-
- filenameΥե뤬̾եλ֤
-
- islink(filename)
- l(filename)
-
- filenameΥե뤬ܥå󥯤Ǥ֤
-
- ispipe(filename)
- p(filename)
-
- filenameΥե뤬̾Ĥѥ(FIFO)Ǥ֤
-
- issocket(filename)
- S(filename)
-
- filenameΥե뤬åȤǤ֤
-
- owned(filename)
- O(filename)
-
- filenameΥե¸桼ͭƤ֤
-
- readable(filename)
- r(filename)
-
- filenameΥեɤߤȤǽλ֤
-
- R(filename)
-
- filenameΥեuid/gidɤߤȤǽλ֤
-
- setuid(filename)
- u(filename)
-
- filenameΥեsetuidӥåȤåȤƤ֤
-
- setuid(filename)
- g(filename)
-
- filenameΥեsetuidӥåȤåȤƤ֤
-
- size(filename)
- s(filename)
-
- filenameΥե뤬¸ߤե礭֤¸ߤ
- ʤnil֤
-
- sticky(filename)
- g(filename)
-
- filenameΥեstickyӥåȤåȤƤ֤
-
- writable(filename)
- w(filename)
-
- filenameΥե뤬uid/gidǽ񤭹߲ǽλ֤
-
- W(filename)
-
- filenameΥե뤬񤭹߲ǽλ֤
-
- z(filename)
-
- filenameΥե뤬¸ߤ礭0Ǥ֤
-
-** Fixnum(饹)
-
-31bit(ޥlongĹ-1 bit)Υ饹builtin classǤ롥
-饹pointer¨ͤǤ뤿call by valueǸƤӽФħŪ
-Ǥ(¾Υ饹call by reference)黻η̤31bitۤ
-ϼưŪBignum(̵¿Ĺ)˳ĥ롥
-
-ƥ졼upto()downto()step()Ϸ֤ΤѤ졤̤
-Range饹Ѥ®Ǥ롥
-
-SuperClass: Integer
-
-Methods:
-
- self + other
- self - other
- self * other
- self / other
- self % other
- self ** other
-
- ѱ黻줾¡ѡ;Ѿ֤
-
- ~ self
- self | other
- self & other
- self ^ other
-
- ӥåȱ黻줾ӥåȿž¡ѡ¾Ū¤
- ֤
-
- self << bits
- self >> bits
-
- եȱ黻줾bitsӥåȤ˥ӥåȥեȤԤʤ
-
- self .. max
-
- ϰϻꡥself maxޤǤϰϥ֥Ȥ֤
-
- downto(min)
-
- ƥ졼selfminޤDz˷֤
-
- id2name
-
- ͤIDȤߤʤơʸ֤ʸ
- ¸ߤʤnil֤
-
- step(max, step)
-
- ƥ졼selfmaxޤstepѲʤ顤֤
-
- to_f
-
- selfFloatѴΤ֤
-
- to_i
-
- self򤽤Τޤ֤
-
- upto(max)
-
- ƥ졼selfmaxޤǷ֤
-
-** Float(饹)
-
- ưΥ饹
-
-SuperClass: Numeric
-
-Methods:
-
- self + other
- self - other
- self * other
- self / other
- self % other
- self ** other
-
- ѱ黻줾¡ѡ;Ѿ֤
-
- self == other
- self > other
-
- ӱ黻
-
- coerce(num)
-
- numfloatѴ롥FloatǤ¾ο
- FixnumBignumǤ롥
-
- to_f
-
- self򤽤Τޤ֤
-
- to_i
-
- selfѴ̤֤
-
-Single Methods:
-
- new(float)
-
- floatƱͤĿFloat֥Ȥ֤
-
-** GC(⥸塼)
-
-RubyȤ߹ߤgarbage collectorԤʤΥ⥸塼롥Υ
-塼Υ᥽åɤѤ뤳ȤˤäơŪGCߤ᤿ꡤGCε
-륿ߥ󥰤椷Ǥ롥
-
-Methods:
-
- garbage_collect
-
- GC򳫻Ϥ롥GC.startפƱ
-
-Single Methods:
-
- disable
-
- GCػߤ롥
-
- enable
-
- GCĤ롥
-
- start
-
- GC򳫻Ϥ롥
-
-** Glob(饹)
-
-磻ɥɤΥ饹磻ɥɤΥƥ<..>ȤǤ
-롥ɽȤۤƱ褦˻Ȥ뤬ϵǽʤ
-ɥɤŸǽ롥
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- self =~ string
-
- 磻ɥɤʸ˥ޥåˤϿ򡤤ʤ
- nil֤
-
- each
-
- 磻ɥɤ˥ޥåե̾Ϳ륤ƥ졼
-
-Single Methods:
-
- new(string)
-
- ʸ磻ɥɤѴ֥Ȥ֤
-
-** Hash(饹)
-
-Ϣ󤢤뤤ϥϥåɽǤդΥ֥ȤźȤǤΥ
-Ǥ롥Ϣ󥪥֥ȤϰŪˤϢ
-
- ``{a=>b,..}''
-
-ǹԤʤ롥
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- self [key]
-
- key򥭡Ȥ֤ͤ
-
- self [key]= value
-
- key򥭡ȤơvalueǼ롥valueȤnilꤹȤ
- keyФܤκȤʤ롥ĤޤꡤHashͤȤnil
- ȤϤǤʤ
-
- clear
-
- Ϣˤ롥
-
- delete(key)
-
- key򥭡ȤȤ롥
-
- delete_if
-
- Ǥ륤ƥ졼key::valueȤڥͿơ֥
- ɾͤλܤ롥
-
- each
- each_pair
-
- key::valueʤڥͿ륤ƥ졼
-
- each_key
-
- ƤkeyФƷ֤ƥ졼
-
- each_value
-
- ƤvalueФƷ֤ƥ졼
-
- has_key(key)
- includes(key)
-
- keyϢ¸ߤ֤
-
- has_value(value)
-
- valueͤȤȤϢ¸ߤ֤
-
- indexes(ary)
- indexes(key-1, ..., key-n)
-
- 1ܤηǤȤƼơǤ򥭡Ȥ
- Ǥޤ֤2ܤηǤϳưͤ򥭡Ȥ
- ޤ֤
-
- keys
-
- Ϣ¸ߤ륭Ƥޤ֤
-
- length
- size
-
- ϢǤο֤
-
- shift
-
- ϢǤļФ()key::valueʤڥ
- ֤
-
- to_a
-
- Ϣkey-valueڥǤȤ֤
-
- values
-
- Ϣ¸ߤƤޤ֤
-
-Single Methods:
-
- Hash[key, value..]
-
- ܤΰkeyܤΰvalueȤϢ
- 롥
-
- new
-
- ()Ϣ󥪥֥Ȥ֤
-
-** Integer(饹)
-
-饹ºݤϤ礭ˤäFixnumBignumĤΥ֥饹
-Ǽ¸Ƥ롥IntegerϤΥѡ饹Ȥʤݥ饹Ǥ
-롥RubyǤϤۤȤɤξ硤FixnumBignumζ̤ɬפʤߤѴ
-ϼưŪ˹Ԥʤ롥ӥåȤߤʤˤϡ̵¤Ĺ
-ĥӥåȹͤƹʤ
-
-SuperClass: Numeric
-
-Methods:
-
- self[idx]
-
- idxӥåܤåȤƤ1åȤƤʤ
- 0֤
-
- chr
-
- ο򥳡ɤȤʸޤ1ʸʸ֤̤
- Ĺ1ʾʸˤĤơδطΩ롥
-
- str[0].chr == str[0,1]
-
- ʸϰ(0..255)ˤʤ㳰ȯ롥
-
- is_integer
-
- Ĥ⿿֤
-
-** IO(饹)
-
-ϤΤδܥ饹
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- self << object
-
- objectϤ롥objectʸǤʤˤϥ᥽åto_sѤ
- ʸѴ롥selfͤȤΤǡC++Τ褦`<<'
- ϢȤ롥
-
- :
-
- $stdout << 1 << " is a " << Fixnum << "\n"
-
- close
-
- ϥݡȤ򥯥롥ʸΤΥ֥ȤФ
- ϥ顼ˤʤ롥
-
- each
-
- Ԥɤ߹Ǥ뤿Υƥ졼Ԥζڤϥƥ
- `$/'ˤäѹǤ롥ɤ߹ʸϥƥѿ`$_'
- ⥻åȤ롥
-
- each_byte()
-
- ʸɤ߹Ǥ뤿Υƥ졼ʸʸɤɽ
- FixnumǤ롥
-
- fileno
- to_i
-
- IO֥ȤȤäƤեǥץ(Fixnum)֤
-
- flush
-
- Хåեեå夹롥
-
- getc
-
- ɤ߹ǡɤ߹ߤˤϤʸ֤ե
- νãˤnil֤ͥ᥽ågetc()
- $stdin.getcƱ̣Ǥ롥
-
- gets
-
- ɤ߹ǡɤ߹ߤˤϤʸ֤ե
- νãˤnil֤
-
- isatty
-
- ϥݡȤttyǤ֤
-
- puts(obj)
-
- objϤ롥self << objפƱ̣Ǥ롥
-
- read([length])
-
- lengthХɤ߹ǡʸ֤lengthά줿
- ˤϡƤΥǡɤ߹ࡥ
-
- readlines
-
- եɤ߹dzƹԤǤȤƤ֤
-
- sync
-
- ߤνƱ⡼ɤ򿿵֤ͤƱ⡼ɤλϽϴ
- θƽ˥Хåեեå夵롥
-
- sync=(newstate)
-
- Ʊ⡼ɤꤹ롥
-
- sysread(length)
-
- stdioͳread(2)ѤϤԤʤϤ줿ǡ
- ޤʸ֤եνãˤnil֤
- read(2)ˤɬlengthХȤʸɤ߹ޤ櫓
- ǤϤʤgets()getc()ʤstdioͳ᥽åɤȺѤ
- ȤϥХåե󥰤ʤɤǻפư򤹤뤳Ȥ롥
-
- syswrite(str)
-
- stdioͳˡwrite(2)ѤƽϤԤʤΥ᥽å
- ϥХåե󥰤ʤstdioƤ뤳ȤϰڹԤʤʤ
- syswriteϼºݤ˽񤭹Хȿ֤print()printf()
- syswrite()ѤΤϿ侩Ǥʤ
-
- write(str)
-
- strϤ롥ϤХȿ֤
-
-** Kernel(饹)
-
-ƤΥ饹δ쥯饹RubyȤ߹ߤƤδؿ᥽åɤϤΥ饹
-Ƥ롥ؿ᥽åɤˤĤƤϡִؿפιܤ򻲾ȤΤȡ
-
-SuperClass: ʤ
-
-Methods:
-
- ! self
-
- ꡥNon-nilΥ֥Ȥξ˵(nil)֤Υ᥽
- ɤNil饹ǤϺ쿿֤
-
- self == other
- equal(other)
-
- ֥ȤΰȽꡥ쥷ФȰΰפ
- ֤Kernel饹ǤΥ֥ȤƱλ
- "=="᥽åɤϳƥ֥Ȥ˱ƺɬפ
- 롥"=="᥽åɤˤϡhash᥽åɤ⤽˹
- ƺɬפ롥
-
- equal()᥽åɤ"=="᥽åɤ̾ǡ"=="Ǥ
- ֥ȤƱȽԤʤѤ롥ä
- equal()᥽åɤϥ֥饹Ǻ٤ǤϤʤ
-
- self != other
-
- "=="ꡥ"=="᥽åɤƤӽФƤΤǡϺ
- ɬפϤʤ
-
- self =~ other
-
- ޥåǥեȤư"=="ƱǤ롥"=~"caseӤ
- Ѥ롥
-
- !~
-
- "=~"ꡥ"=~"᥽åɤƤӽФƤΤǡϺ
- ɬפϤʤ
-
- self :: other
-
- selfotherǤȤassocڥ֤α黻ҤϱǤ
- Τǡa::b::c (a::(b::c)) Ȳᤵ롥
-
- is_nil
-
- ֥ȤnilǤ뤫ɤKernel饹ǤϿ
- Nil饹ǺƤ롥
-
- id
-
- ƥ֥ȤФưդFixnum֤FixnumϼʬȤ
- ΤǡidפƤƱ֥ȤǤ뤳Ȥݾڤʤ
- Ĥޤꡤ
-
- obj1.id == obj2.id
-
- ΩƤ⡤ɤ餫FixnumǤСobj1obj2ƱǤ
- Ȥϸ¤ʤξFixnumǤʤȤݾڤǤС2
- ĤΥ֥ȤƱǤ뤳Ȥϳμ¤Ǥ롥
-
- hash
-
- ֥ȤΥϥå(Fixnum)֤Hash饹ǥȤʤ
- ֥ȤǼΤѤƤ.A == BפΩ
- ɬA.hash == B.hashפΩɬפΤǡ"=="
- ˤɬ⤽˹碌ƺ뤳ȡ
-
-
-** Math(⥸塼)
-
-ư黻򥵥ݡȤ륯饹Math⥸塼ƱΥ᥽å
-ðۥ᥽åɤȤξƤΤǡðۥ᥽åɤƤӽФƻ
-Ȥȡ饹˥󥯥롼ɤƻȤȤȤξǤ롥
-
- :
-
- pi = Math.atan2(1, 1) * 4;
- include Math
- pi2 = atan2(1, 1)
-
-Methods:
-Single Methods:
-
- atan2(x, y)
-
- С-ФϰϤX/YΥ󥸥Ȥ֤
-
- cos(x)
- sin(x)
- tan(x)
-
- 饸ɽ줿xλѴؿ֤ͤ
-
- exp(x)
-
- xλؿؿ֤ͤ
-
- log(x)
-
- xμп֤
-
- log10(x)
-
- xξп֤
-
- sqrt(x)
-
- xʿ֤xͤǤˤ㳰ȯ롥
-
- cbrt(x)
-
- xΩ֤
-
-** Module(饹)
-
-⥸塼Υ饹
-
-SuperClass: Object
-
-Private Methods:
-
- attr(name[, public])
-
- Υ⥸塼򥤥󥯥롼ɤ饹Υ󥹥󥹤Ф
- nameǻꤵ°ղä°Ф륢᥽åɤ
- 롥attr("attr")ϥ饹˰ʲ˼ɤɲä
- ȤۤƱǤ롥
-
- def attr; @attr; end
-
- άǽ2publicͿơĤͤnilǤʤ
- Ϥ°ˤ°᥽åɤѰդ졤ǽˤ
- 롥attr("attr", TRUE)ϥ饹˰ʲΥɤɲä
- ȤۤƱǤ롥
-
- def attr; @attr; end
- def attr=(val); @attr = val; end
-
- °᥽åɤ뤳Ȥˤäơư
- ѹǤ롥㤨
-
- attr("test", TRUE)
- def test=(val)
- print("test was ", @test, "\n")
- print("and now is ", @test = val, "\n")
- end
-
- Τ褦°ͤɽ褦ʤȤǽǤ롥attr
- ϥ᥽åɤǤƤϡǥեȤΥ
- ᥽åɤʤ
-
-Methods:
-
- include(module[, module..])
-
- ǻꤷ⥸塼򥤥󥯥롼ɤơ᥽åɡ
- ä롥饹⥸塼̤Υ⥸塼򥤥󥯥롼ɤ뤳
- Ȥˤäơꤵ줿¿ŷѾ(Mixin)¸Ǥ롥
-
- to_s
-
- ⥸塼ʸɽ֤⥸塼ξʸɽϥ
- 塼̾Ǥ롥
-
- private(name[, name..])
-
- nameǻꤵ줿᥽åɤؿǤƤӽФǽˤ롥
- Ǥprivate᥽åɤǤˤϲ⤷ʤ
-
- public(name[, name..])
-
- nameǻꤵ줿᥽åɤ̾ǸƤӽФǽˤ롥Ǥ
- public᥽åɤǤˤϲ⤷ʤ
-
-** Nil(饹)
-
-ɽ֥nilΥ饹ѿ()nilNil饹ͣΥ
-󥹥󥹤Ǥ롥
-
-SuperClass: Kernel
-
-Methods:
-
- self + other
-
- otherưʸǤother֤
-
- ! self
-
- ˿֤
-
- is_nil
-
- ˿֤
-
-** Numeric(饹)
-
-̤ɽݥ饹
-
-SuperClass: Object
-
-Included Modules: Comparable
-
-Methods:
-
- + self
-
- ֥selfΤΤ֤
-
- - self
-
- 0 - selfפ֤֥ͤ饹ǤΨŪ˺뤳
- ȤԤ롥
-
- abs
-
- ֤ͤ
-
- divmod(other)
-
- Ⱦ;Υڥ֤
-
- next
-
- ο֤οȤϤοۤǾǤ롥
-
-** Object(饹)
-
-Ƥ̾說饹Υѥ饹̾說饹Υ󥹥󥹤ΰŪʿ
-Ƥ롥Υ饹Υ֥饹Ǥʤ饹KernelNilȡ
-Ȥ߹ߴؿƤBuiltinǤ롥
-
-SuperClass: Builtin
-
-Methods:
-
- extened(module[, module..])
-
- ǻꤷ⥸塼self˥󥯥롼ɤ롥⥸塼
- Ƥ᥽åɤðۥ᥽åɤȤɲä롥
-
- initialize
-
- ֥Ȥ˸ƤӽФ롥ǥեȤϲ⤷
- ֥饹ɬפ˱ƺ뤳ȤԤƤ롥
-
- is_member_of(class)
-
- ֥self饹classΥ󥹥󥹤Ǥ֤
-
- is_kind_of(class)
-
- ֥self饹classΥ֥饹Υ󥹥󥹤
- ֤
-
- clone
-
- ֥Ȥʣ롥󥹥󥹤¨ͤǤFixnum饹
- ʳΥ饹ξ硤obj.equal(obj.clone)פϵǤ뤬¿
- ξobj == obj.cloneפϿǤ롥
-
- to_s
-
- ֥Ȥʸɽ֤Υ᥽åɤŪprint()
- format()᥽åɤѤƤ롥
-
- to_a
-
- ֥ȤѴ롥ͥ륯饹Ƥ
- եȤϡΥ֥ȼȤޤ1Ǥ֤
-
-** Process(⥸塼)
-
-ץ˴ؤԤʤΥ⥸塼롥Math⥸塼Ʊͤ
-ƤΥ᥽åɤðۥ᥽åɤȤƤ̾Υ᥽åɤȤƤȤ롥
-Processϥץ֥ȤΥ饹ǤϤʤơץΥ᥽
-ɤޤȤ᤿ΤǤ뤳Ȥդ뤳ȡ
-
-Methods:
-Single Methods:
-
- egid
-
- ץθߤμ¸GID֤
-
- egid=(gid)
-
- ץθߤμ¸GIDgid˥åȤ롥
-
- euid
-
- ץθߤμ¸UID֤
-
- euid=(uid)
-
- ץθߤμ¸UIDuid˥åȤ롥
-
- getpgrp([pid])
-
- pidǻꤵ줿ץ߽°Ƥץ롼פid
- ֤pidάpid0Ϳϸ߼¹ԤƤ
- оݤˤ롥
-
- getpriority(which, who)
-
- whichwhoǻꤵץץ롼ס桼θ
- ̤֤ͥܺ٤getpriority(2)򻲾ȡProcess⥸塼
- ǤwhichȤƻǤPRIO_PROCESSPRIO_PGRP
- PRIO_USERƤ롥
-
- gid
-
- ץθߤμGID֤
-
- gid=
-
- ץθߤμGIDgid˥åȤ.
-
- pid
-
- ץΥץID֤ϥƥѿ`$$'ͤƱ
- 롥
-
- ppid
-
- ƥץΥץΥץID֤UNIXǤľܤοƥץ
- λ硤ƥץpid1(initpid)ˤʤ롥
-
- setpgrp(pid, pgrp)
-
- pidǻꤵ줿ץΥץ롼פpgrpˤ롥pid0
- Ϳȸ߼¹Υץоݤˤ롥
-
- setpriority(which, who, prio)
-
- whichwhoǻꤵץץ롼ס桼θ
- ̤ͥprioꤹ롥ܺ٤setpriority(2)򻲾ȤΤȡ
-
- uid
-
- ץθߤμUID֤
-
- uid=
-
- ץθߤμUIDuid˥åȤ.
-
-** Range(饹)
-
-ϰϥ֥ȤΥ饹ϰϥ֥Ȥ`..'黻Ҥˤä졤
-ŪˤϰʲΤ褦ʻȤ򤹤
-
- for i in 1..5
- ...
- end
-
-ξϰʲ®.
-
- 1.upto(5) {
- ...
- }
-
-ϰϥ֥Ȥ`..'黻ҤξդComparableޤ९饹Υ
-󥹥󥹤ǤвǤ⹽ʤϰϤϻȽޤळȤդ
-.
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- self =~ other
-
- selfotherƱ饹Фϰϥ֥Ȥǡϰ
- other(start <= other <= end)֤case
- ϰϻꤹǤ롥㤨
-
- case i
- when 1, 3..5
- ...
- end case
-
- Τ褦ʥɤ񤯤ȤǤ롥
-
- each
-
- ϰ¸ߤ륪֥ȤͿ륤ƥ졼forΤ
- Ѥ롥
-
- end
-
- ϰϤν֤
-
- start
-
- ϰϤλ֤
-
-** Regexp(饹)
-
-ɽΥ饹ɽΥƥ/.../ȤɽưŪ
-뤿ˤ
-
- Regexp.new(ʸ)
-
-Ȥ롥String饹`=~'ϤȤ¿Υ᥽åɤɽ
-ؤʸͿ줿ˤŪɽΤǡ
-Ȥ󤷤Ȼפ䡤ɽʸʸζ̤Ū˻
-ꤷʤɰʳŪȻפȤϾʤϤ
-
-SuperClass: Object
-
-Methods:
-
- self =~ string
-
- ɽʸ˥ޥå硤ޥå֤֤ޥå
- ʤnil֤
-
- ~ self
-
- $_ =~ selfפƱ
-
-Single Methods:
-
- complie(string[, casefold])
- new(string[, casefold])
-
- ʸɽѴ֥Ȥ֤άǽ2
- Ϳ졤ͤnilǤʤˤϡ줿ɽ
- Ȥϥƥѿ`$='ͤ˴ؤ餺ޥåʸ
- ʸΰ㤤̵뤹롥
-
- quote(str)
-
- ʸɽǰ̣ʸ򥨥פ롥ʸ
- ֤
-
-** String(饹)
-
-ʸ󥯥饹Rubyʸϥ̥륿ߥ͡ȤǤϤʤΤǡХʥǡ
-ⰷ롥äƤɤ餫ȤñʤʸȤХǤ롥
-λۤ˴Ťơɽ˴ؤ᥽åɰʳ2byteϤʸռ
-ƤʤϺԤμȴǤϤʤտŪˤƤΤǤ(
-Ƥ)
-
-SuperClass: Object
-
-Included Modules: Comparable, Enumerable
-
-Methods:
-
- self + other
-
- ʸϢ롥Ϣ뤵줿ʸ֤
-
- self * times
-
- ʸη֤㤨
-
- "x" * 4 == "xxxx"
-
- Ǥ롥
-
- self == other
- self > other
-
- ʸӡƥѿ$=nilǤʤˤʸʸ
- ̤ӤԤʤ
-
- self =~ other
-
- ʸΥޥåotherɽʸotherʸξ
- ưŪɽѴ롥ޥåϥޥå֡
- ʤänil֤롥
-
- ~ self
-
- $_ =~ selfפƱ
-
- self[nth]
- self[beg..end]
- self[beg,len]
-
- ƤμФ1ܤηǤnthХܤΥǡFixnumȤ
- ֤2ܤηǤbegХܤendХܤޤǤʬʸ
- ֤(ξüޤ)3ܤηǤbegХܤlenХ
- ʬʬʸ֤
-
- self[nth] = val
- self[beg..end] = val
- self[beg,len] = val
-
- Ƥι1ܤηǤnthХܤΥǡval ()
- 롥2ܤηbegХܤendХܤޤǤʬʸ
- valȤͿ줿ʸ֤롥3ܤηbeg
- ܤlenХʬʬʸvalȤͿ줿ʸ
- ֤롥
-
- capitalize
-
- ʸκǽʸ(줬ե٥åȤǤ)ʸ
- ѴĤʸΥե٥åȤʸ֤롥
-
- chop
-
- ʸκǸΥХȤڤȤʸѹ뤳Ȥ
- դ뤳ȡ
-
- crypt(salt)
-
- crypt(3)ѤưŹ沽ʸ֤salt2ХȰʾĹ
- ǤդʸǤ롥
-
- delete(str)
-
- ʸΤstr˴ޤޤʸ롥ʸλtr
- ƱͤǤꡤa-babޤǤϰϤƬ^ʸ(
- ޤƤʤΤ)̣롥ʸѹ뤳Ȥ
- դ뤳ȡ
-
- downcase
-
- ʸΥե٥åȤƾʸ֤ʸ֤
-
- each
-
- ʸ󤫤1Ԥɤ߹Ǥ륤ƥ졼
-
- each_byte
-
- ʸΤ줾ΥХȤˤĤƷ֤ƥ졼
-
- gsub(pattern[, replace])
-
- ʸpattern˥ޥåʬreplace֤롥
- ʸreplace&\0ϥޥåʸˡ\1..\9nܤ
- ̤Ƥ֤롥replaceά줿ˤϥ
- 졼Ȥư֥åɾִ̤롥
-
- hex
-
- ʸ16ʿɽʸȲᤷơѴ롥
-
- index(substr[, pos])
-
- substrǽ˽и֤֤posͿȤΰ֤鸡
- 򳫻Ϥ롥Ĥʤˤnil֤
-
- intern
-
- ʸ˰դб֤ʸϥʥʸޤǤϤ
- ʤ
-
- length
- size
-
- ʸĹ(Хȿ)֤
-
- ljust(width)
- rjust(width)
- center(width)
-
- ʸ򤽤줾졤ͤᡤͤᡤ󤻤widthʸ
- ֤ʸĹwidthĹϸʸ֤ڤ
- ʤ
-
- next
-
- selfendޤǡּΡʸ֤ʸȤϿϿ
- ȤơʸϱʸȤä夬νԤʤ줿
- ΤǤ롥
-
- "aa".next => "ab"
- "99".next => "100"
- "a9".next => "b0"
-
- oct
-
- ʸ8ʿɽʸȲᤷơѴ롥8ʿ
- /[0-7]+/ǤꡤʸƬ餳Υѥ˥ޥå
- ʬѴ롥ƤϤޤʤʸФ
- Ƥ0֤perlȤϰäʸ0xϤޤäƤ뤫Ȥ
- 16ʿȸʤƤ줿ϤʤƬ08ʿ
- ǧ졤0֤
-
- reverse
-
- ʸγƥХȤս¤٤ʸ֤ʸ2ХȤ
- ʸޤǤƤ⤪ʤ˥Хñ̤ȿž롥
- split2Хʸ򤹤Τǡ2Хʸޤʸʸ
- ñ̤ȿžˤ
-
- "ʸ".split(//).reverse.join("")
-
- ȤФ褤
-
- rindex(substr[, pos])
-
- ʸsubstrǸ˽и֤֤posͿȤΰ
- Ǹλ롥Ĥʤˤnil֤indexȤ
- 1)ʸ鸡롥2)substrȤɽդ
- ʤ2Ǥ롥
-
- split([sep[, limit]])
-
- ʸsepǻꤵ줿ѥˤäơեɤʬ䤹롥
- sepά줿ΥǥեȤϥƥѿ`$;'ͤѤ
- 롥limitꤵ줿ˤϺlimitĤΥեɤʬ䤹롥
- split()ʬ䤵줿ʸޤ֤sepǻꤵ줿ѥ
- 󤬶ʸȥޥåʸ1ʸĤʬ䤵롥
-
- squeeze([str])
-
- ʸΤstr˴ޤޤʸϢ³Ƥ硤ʸ˰
- ̤롥strά줿硤٤ƤʸоݤȤ롥ʸ
- λtrƱͤǤꡤ`a-b'abޤǤϰϤƬ`^'
- ʸ(ޤޤƤʤΤ)̣롥ʸ
- 뤳Ȥդ뤳ȡ
-
- strip
-
- ʸζ
-
- sub(pattern[, replace])
-
- ʸpattern˥ޥåǽʬreplace֤롥
- ʸreplace&\0ϥޥåʸˡ\1..\9 nܤ
- ̤Ƥ֤롥replaceά줿ˤϥ
- 졼Ȥư֥åɾִ̤롥
-
- sum([bits])
-
- ʸbitsӥåȤΥå롥άͤ16Ǥ롥ruby
- ǤϰʲΥɤSystem V`sum'ץƱͤ롥
-
- while gets()
- sum += $_.sum
- end
- sum %= 65536
-
- swapcase
-
- ʸΥե٥åȤΤʸʸˡʸʸ
- ֤롥
-
- to_f
-
- ʸFloatѴ롥
-
- to_i
-
- ʸ10ʿɽʸȲᤷơѴ롥
-
- toupper
-
- ʸΥե٥åȤʸ֤ʸ֤
- tr("a-z", "A-Z")꾯®
-
- tolower
-
- ʸΥե٥åȤƾʸ֤ʸ֤
- tr("A-Z", "a-z")꾯®
-
- tr(search, replace)
-
- ʸsearchʸ˴ޤޤʸ¸ߤСreplaceʸ
- бʸ֤롥replaceʸ󤬾ά줿
- ϶ʸͿ줿ȸʤreplaceʸsearchʸ
- ûreplaceʸκǸʸ֤Ƥȸ
- searchʸûˤбʸΤʤreplace
- ñ̵뤵(BSDtrư)
-
- searchʸreplaceʸ`a-b'Ȥ줿硤
- abޤǤϰϤʸASCIIξǻꤷȤˤʤ롥
- searchʸκǽʸ`^'Ǥ硤³ʸ*ޤ
- ʤ*ʸִоݤˤʤ롥
-
- tr(1)εǽΤʸ뵡ǽϢ³ʸ򰵽̤
- ǽ̤Υ᥽åɤʬ䤵Ƥ롥εǽˤĤƤ
- deletesqueeze򻲾ȤΤȡ
-
- ؤΤᡤstr.tr(src,repl).squeeze(repl)᥽å
- tr_s(src,repl) 󶡤Ƥ롥
-
- unpack(template)
-
- ʸtemplateʸˤäƥѥåǤ
- ޤ֤templateʸArray饹pack᥽åɤȤ
- ƱͤǤ롥
-
- a ASCIIʸ(³nullʸ䥹ڡĤ)
- A ASCIIʸ(³nullʸ䥹ڡ)
- b ӥåȥȥ(̥ӥåȤ̥ӥå)
- B ӥåȥȥ(̥ӥåȤ鲼̥ӥå)
- h 16ʸ(̥˥֥뤬)
- H 16ʸ(̥˥֥뤬)
- c char
- C unsigned char
- s sort
- S unsigned sort
- i int
- I unsigned int
- l long
- L unsigned int
- n ͥåȥХȥshort
- N ͥåȥХȥlong
- f ñư(¸)
- d ư(¸)
- x 1ХɤФ
- X 1Хȸ
- @ а֤ؤΰư
-
- rubyunpackperlȰäƥåη׻ǽʤȤ
- դ뤳ȡ
-
-
- upcase
-
- ʸΥե٥åȤʸ֤ʸ֤
-
- upto(end)
-
- selfϤޤäơendޤǡּΡʸͿ륤ƥ졼
- ʸȤstr.nextͿʸǤ롥
-
- Υ᥽åɤRange:eachѤƤΤǡʲΤ褦ʽ
- ǽǤ롥
-
- for i in "a" .. "ba"
- print(i, "\n");
- end
-
- a, b, c, ... aa, ... az, baޤǤƹԤ˽Ϥ롥
-
-
- դʤФʤΤϡνλȽ羮طǤϤʤ
- `=='ȽꤵƤ뤿ᡤ`..'黻Ҥκդͤ³ʸ˱
- դʸ󤬴ޤޤƤʤʲΤ褦ʾ̵¥롼פ
- ٤äƤޤ
-
- for i in "0" .. "1a"
- print(i, "\n");
- end
-
- ԤϤ񤯤ȤˤäǤƨƤ褦ȤƤȹͤ
- ⤤뤫⤷ʤο¬
-
-Single Methods:
-
- new(string)
-
- stringƱƤĿʸ֤
-
-** Struct(饹)
-
-¤Υ饹ʣΥǡޤȤѤ(: Time::times)
-ǡޤȤˤ󥯥饹Ѥ뤳Ȥ⤢뤬(: select)
-¤ΤȤ٤ϰʲΤ褦ʾǤ롥
-
- (1) Ǥο
-
- ǤοưΤϹ¤ΤȤΤˤϸʤ
-
- (2) Ǥο¿
-
- ʹ֤٤ưפ˰복ǰο7ĤޤǤǤȤ⤬롥
- β˽СǤ4İʾ夢ǡξѤ
- 硤ǿ*2(ĤޤꥪեåȤȤΰ̣)7ۤ롥äơ
- Τ褦ʾˤϹ¤ΤȤä򤷤䤹Ȼפ롥
-
- (3) Ʊ̤ʤ
-
- ¤Τ㴳Ȥ⤤Τǡ®٤ˤʤ
- (㤨Ʊ̤ʤ)Ϲ¤ΤλѤŬڤǤʤ
- ǽ롥
-
-ƹ¤Τˤϥ̾Ʊ̾ΰΤʤ᥽åɤ롥
-
-ܥɥǡ¤Τɽ뤿ˤϰʲηȤ
-
- struct ¤̾
- ...
- end
-
-ץǤηǹ¤Τ櫓ǤϤʤ
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- self[idx]
-
- idxλidxܤǤ֤idxʸλidxƱ̾
- ΥФǤ֤
-
- values
-
- ¤ΤΥФͤǤ˻֤㤨аʲΥɤ
- ʬpasswdȥϤ뤳ȤǤ롥
-
- print(Etc.getpwuid().values.join(":"), "\n")
-
- νϤ`grep "$USER" /etc/passwd'νϤ;ʬʥեɤ
- Ĥ(ƥˤäưۤʤ)ʳƱǤ롥
-
-Single Methods:
-
- new(name, member::value..)
-
- nameȤ̾ŤΤ롥memberϹ¤ΤΥФ
- ɽʸǤꡤvalueϤͤǤ롥줿¤Τϥ
- Фǻꤵ줿̾ðۥ᥽åɤƤơΥ᥽å
- ˤäƥФƤ뤳ȤǤ롥
-
-** Time(饹)
-
-֤ɽ饹羮ӤʤɤǤ롥Time.nowǸߤλ֤뤳
-Ǥ롥ޤեΥॹפ᥽åɤͤ⤳Υ
-Υ󥹥󥹤Ǥ롥
-
-SuperClass: Object
-
-Included Modules: Comparable
-
-Methods:
-
- self <=> other
-
- otherTimeΥ󥹥󥹤Ϳ줿
- ˤ1970ǯ 1 1 00:00:00 GMTÿǤ
- ƻȤӤԤʤ
-
- asctime
- ctime
- to_s
-
- date(1)ʸѴ롥
-
- gmtime
-
- ॾνԤʤʤGMTǤλ롥Υ᥽å
- ȤäTime饹Υ󥹥󥹤ϡʸλѴGMT
- ԤʤgmtimeϼʬȤ֤
-
- ɥλɽˤ
-
- print(Time.now.gmtime, "\n")
-
- ȤФ褤
-
- localtime
-
- ॾνԤʤä(ǥե)localtime
- ϼʬȤ֤
-
- to_i
- tv_sec
-
- 1970ǯ 1 1 00:00:00 GMTޤǤÿ֤
- secondʬǤ⤢롥
-
- sec
- min
- hour
- mday
- year
- wday
- yday
- zone
- isdst
-
- ŪݻƤtm¤ΤƤ֤zoneʳ֤
- zoneϥॾɽʸ֤(cf localtime(3))
-
- strftime(format)
-
- formatʸ˽äʸѴ̤֤format
- ʸȤƻǤΤ ʲ̤Ǥ롥
-
- %A ̾(Sunday, Monday,..)
- %a ξά̾(Sun, Mon,..)
- %B ̾(January, February,..)
- %b ξά̾(Jan, Feb,..)
- %c ɽ(cf ctime(3))
- %d ʿǤ(01-31)
- %H 24λ(00-23)
- %I 12λ(01-12)
- %j ǯ̻(001-366)
- %M ʬ(00-59)
- %m ɽ(01-12)
- %p ޤϸ(AM,PM)
- %S (00-61)
- %U ɽǽ1
- Ϥޤ(00-53)
- %W ɽǽη1
- Ϥޤ(00-53)
- %w ɽ0(0-6)
- %X (: 15:01:06)
- %x (: Fri Jan 14 1994)
- %Y ɽ
- %y β2(00-99)
- %Z ॾ
- %% %
-
- usec
- tv_usec
-
- micro secondʬ֤
-
-Single Methods:
-
- now
-
- ߤλɽTime饹Υ󥹥󥹤롥
-
- at(time)
-
- timeƱɽTime饹Υ󥹥󥹤롥time
- Time饹Υ󥹥󥹤뤤Ͽ(/ư)Ǥꡤ
- ξ1970ǯ 1 1 00:00:00 GMTÿǤȤƻ
- ׻롥
-
- times
-
- ߤΥץȤλҥץ񤷤桼/ƥCPU
- ѻ¤ΤȤ֤(Struct򻲾)
-
- struct tms
- utime # ץΥ桼
- stime # ץΥƥ
- cutime # ҥץΥ桼
- cstime # ҥץΥƥ
- end
-
- ֤ñ̤äǤꡤưͿ롥ܺ٤
- times(3)򻲾ȤΤȡ
-
-* CȤΥ󥿥ե
-
-rubyCȤΥ󥿡ե󶡤C줫Υ饹⥸塼
-CǵҤ᥽åɤrubyΥ᥽åɤθƤӽФ
-졼θƤӽФ㳰ʤɤԤʤȤ롥ޤOSм
-ԻCǽ񤫤줿⥸塼ɤ뤳Ȥ롥
-
-Ūʥ󥿥ե˴ؤƤϡ̥ɥ(źեե C-IF)
-ȤΤȡ
-
-* ʸˡ
-
-ʲϵBNFǵҤrubyʸˡǤ롥ΤʵҤparse.y򻲾
-줿
-
-PROGRAM : COMPEXPR
-
-COMPEXPR : EXPR (TERM EXPR)* [TERM]
-
-EXPR : MLHS `=' ARGS
- | ASSOCS
- | return ARGS
- | fail ARGS
- | yield ARGS
- | identifier CALL_ARGS
- | PRIMARY `.' identifier CALL_ARGS
- | super CALL_ARGS
- | undef FNAME
- | alias FNAME FNAME
- | include identifier (`,' identifier)*
- | EXPR if EXPR
- | EXPR while EXPR
- | EXPR and EXPR
- | EXPR or EXPR
- | ARG
-
-ARG : LHS `=' ARG
- | LHS OP_ASGN ARG
- | ARG `..' ARG
- | ARG `...' ARG
- | ARG `+' ARG
- | ARG `-' ARG
- | ARG `*' ARG
- | ARG `/' ARG
- | ARG `%' ARG
- | ARG `**' ARG
- | `+' ARG
- | `-' ARG
- | ARG `|' ARG
- | ARG `^' ARG
- | ARG `&' ARG
- | ARG `<=>' ARG
- | ARG `>' ARG
- | ARG `>=' ARG
- | ARG `<' ARG
- | ARG `<=' ARG
- | ARG `==' ARG
- | ARG `!=' ARG
- | ARG `=~' ARG
- | ARG `!~' ARG
- | `!' ARG
- | `~' ARG
- | ARG `<<' ARG
- | ARG `>>' ARG
- | ARG `::' ARG
- | ARG `&&' ARG
- | ARG `||' ARG
- | PRIMARY
-
-PRIMARY : `(' EXPR `)'
- | LITERAL
- | VARIABLE
- | super `(' [CALL_ARGS] `)'
- | super
- | PRIMARY `[' [ARGS] `]'
- | `[' [ARGS [`,']] `]'
- | `{' [ (ARGS|ASSOCS) [`,'] ] `}'
- | redo
- | break
- | continue
- | retry
- | return
- | fail `(' ARGS `)'
- | fail `(' `)'
- | fail
- | yield `(' ARGS `)'
- | yield `(' `)'
- | yield
- | PRIMARY `{' [ITER_VAR] `|' COMPEXPR `}'
- | identifier `(' [CALL_ARGS] `)'
- | PRIMARY `.' identifier `(' [CALL_ARGS] `)'
- | PRIMARY `.' identifier
- | if EXPR THEN
- COMPEXPR
- (elsif EXPR THEN COMPEXPR)*
- [else COMPEXPR]
- end
- | while EXPR TERM COMPEXPR end
- | case COMPEXPR
- (when ARGS THEN)+
- [else COMPEXPR]
- end
- | for ITER_VAR in EXPR TERM
- COMPEXPR
- end
- | begin
- COMPEXPR
- [resque COMPEXPR]
- [ensure COMPEXPR]
- end
- | class identifier `:' identifier
- COMPEXPR
- end
- | module identifier
- COMPEXPR
- end
- | def FNAME ARGLIST
- COMPEXPR
- end
- | def SINGLETON `.' FNAME ARGLIST
- COMPEXPR
- end
-
-THEN : TERM
- | then
- | TERM then
-
-ITER_VAR : LHS
- | MLHS
-
-MLHS : LHS `,' [LHS (`,' LHS)*] [`*' LHS]
-
-LHS : VARIABLE
- | PRIMARY `[' [ARGS] `]'
- | PRIMARY `.' identifier
-
-CALL_ARGS : ARGS
- | ASSOCS
- | ARGS `,' ASSOCS
- | ARGS `,' `*' ARG
-
-ARGS : ARG
- | ARGS `,' ARG
-
-ARGLIST : `('[identifier(`,'identifier)*][`*'identifier]`)'
- | TERM
-
-SINGLETON : VARIABLE
- | `(' COMPEXPR `)'
-
-ASSOCS : ASSOC (`,' ASSOC)*
-
-ASSOC : ARG `=>' ARG
-
-VARIABLE : VARNAME
- | nil
- | self
- | `__FILE__'
- | `__LINE__'
-
-LITERAL : numeric
- | SYMBOL
- | STRING
- | REGEXP
- | GLOB
-
-TERM : `;'
- | `\n'
-
-겼ϻǧ롥
-
-SYMBOL : `:'FNAME
- | `:'VARNAME
-
-FNAME : identifier | `::' | `..' | `|' | `^' | `&'
- | `<=>' | `==' | `=~' | `>' | `>=' | `<' | `<='
- | `<<' | `>>' | `+' | `-' | `*' | `/' | `%' | `**'
- | `~' | `+@' | `-@' | `[]' | `[]='
-
-VARNAME : GLOBAL
- | `@'identifier
- | identifier
-
-GLOBAL : `$'identifier
- | `$'any_char
-
-STRING : `"' any_char* `"'
- | `'' any_char* `''
- | ``' any_char* ``'
-
-REGEXP : `/' any_char* `/'[i]
-
-GLOB : `<' any_char* `>'
-
-* ռ
-
-RubyθͤϿ¿θαƶƤ. ʲˤΤϤμ
-ʸǤ롥
-
- C, Perl, CLU, Sather, CLOS, Eiffel, Icon, tcl, AWK, bourne shell,
- Smalltalk, Emacs Lisp.
-
-ޤrubyθͤꤹ뤿˶ϤƲäʲˤ롥
-
- ͷƣϺ¼Σţáغܣģţá
- ʤֺ.ٻ(ɾά)
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/sprintf.c b/sprintf.c
index 0e2789b159..91ca246f8d 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -16,13 +16,13 @@
static void fmt_setup();
VALUE
-Fsprintf(argc, argv)
+f_sprintf(argc, argv)
int argc;
VALUE *argv;
{
struct RString *fmt;
char *buf, *p, *end;
- int i, blen, bsiz;
+ int blen, bsiz;
VALUE result;
#define FNONE 0
@@ -51,7 +51,7 @@ Fsprintf(argc, argv)
}
#define GETARG() \
- ((argc == 0)?Fail("too few argument."):(argc--, (argv++)[0]))
+ ((argc == 0)?Fail("too few argument."),0:(argc--, (argv++)[0]))
fmt = (struct RString*)GETARG();
Check_Type(fmt, T_STRING);
@@ -110,7 +110,7 @@ Fsprintf(argc, argv)
case '5': case '6': case '7': case '8': case '9':
flags |= FWIDTH;
width = 0;
- for (p; p < end && isdigit(*p); p++) {
+ for (; p < end && isdigit(*p); p++) {
width = 10 * width + (*p - '0');
}
if (p >= end) {
@@ -150,7 +150,7 @@ Fsprintf(argc, argv)
goto retry;
}
- for (p; p < end && isdigit(*p); p++) {
+ for (; p < end && isdigit(*p); p++) {
prec = 10 * prec + (*p - '0');
}
if (p >= end) {
@@ -178,22 +178,39 @@ Fsprintf(argc, argv)
{
VALUE arg = GETARG();
int len;
- char fbuf[32];
-#define MIN(a,b) ((a)<(b)?(a):(b))
str = obj_as_string(arg);
- fmt_setup(fbuf, 's', flags, width, prec);
+ len = RSTRING(str)->len;
if (flags&FPREC) {
- CHECK(prec);
- }
- else if ((flags&FWIDTH) && width > RSTRING(str)->len) {
- CHECK(width);
+ if (prec < len) {
+ CHECK(prec);
+ memcpy(&buf[blen], RSTRING(str)->ptr, prec);
+ blen += prec;
+ break;
+ }
}
- else {
- CHECK(RSTRING(str)->len);
+ if (flags&FWIDTH) {
+ if (width > len) {
+ width -= len;
+ CHECK(width);
+ if (!(flags&FMINUS)) {
+ while (width--) {
+ buf[blen++] = ' ';
+ }
+ }
+ memcpy(&buf[blen], RSTRING(str)->ptr, len);
+ blen += len;
+ if (flags&FMINUS) {
+ while (width--) {
+ buf[blen++] = ' ';
+ }
+ }
+ break;
+ }
}
- sprintf(&buf[blen], fbuf, RSTRING(str)->ptr);
- blen += strlen(&buf[blen]);
+ CHECK(len);
+ memcpy(&buf[blen], RSTRING(str)->ptr, len);
+ blen += len;
}
break;
diff --git a/st.c b/st.c
index eb3ad92871..d825a7d3c9 100644
--- a/st.c
+++ b/st.c
@@ -10,7 +10,7 @@ static char *rcsid = "$Header: /usr/ext/cvsroot/ruby/st.c,v 1.3 1994/12/09 01:28
#include "st.h"
extern void *xmalloc();
-static rehash();
+static void rehash();
#define max(a,b) ((a) > (b) ? (a) : (b))
#define nil(type) ((type *) 0)
@@ -25,8 +25,6 @@ static rehash();
* DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
* allocated initially
*
- * DEFAULT_GROW_FACTOR is the amount the hash table is expanded after
- * the density has reached max_density
*/
#define EQUAL(func, x, y) \
@@ -39,14 +37,13 @@ static rehash();
(table->hash == ST_NUMHASH) ? ((int) (key) % table->num_bins) :\
(*table->hash)((key), table->num_bins))
-st_table *st_init_table_with_params(compare, hash, size, density, grow_factor,
- reorder_flag)
-int (*compare)();
-int (*hash)();
-int size;
-int density;
-double grow_factor;
-int reorder_flag;
+st_table*
+st_init_table_with_params(compare, hash, size, density, reorder_flag)
+ int (*compare)();
+ int (*hash)();
+ int size;
+ int density;
+ int reorder_flag;
{
st_table *tbl;
@@ -55,7 +52,6 @@ int reorder_flag;
tbl->hash = hash;
tbl->num_entries = 0;
tbl->max_density = density;
- tbl->grow_factor = grow_factor;
tbl->reorder_flag = reorder_flag;
tbl->num_bins = size;
tbl->bins =
@@ -63,18 +59,19 @@ int reorder_flag;
return tbl;
}
-st_table *st_init_table(compare, hash)
-int (*compare)();
-int (*hash)();
+st_table*
+st_init_table(compare, hash)
+ int (*compare)();
+ int (*hash)();
{
return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE,
ST_DEFAULT_MAX_DENSITY,
- ST_DEFAULT_GROW_FACTOR,
ST_DEFAULT_REORDER_FLAG);
}
+int
st_free_table(table)
-st_table *table;
+ st_table *table;
{
register st_table_entry *ptr, *next;
int i;
@@ -111,10 +108,11 @@ if (PTR_NOT_EQUAL(table, ptr, key)) {\
}\
}
+int
st_lookup(table, key, value)
-st_table *table;
-register char *key;
-char **value;
+ st_table *table;
+ register char *key;
+ char **value;
{
int hash_val;
register st_table_entry *ptr;
@@ -147,10 +145,11 @@ char **value;
table->num_entries++;\
}
+int
st_insert(table, key, value)
-register st_table *table;
-register char *key;
-char *value;
+ register st_table *table;
+ register char *key;
+ char *value;
{
int hash_val;
st_table_entry *tbl;
@@ -169,10 +168,11 @@ char *value;
}
}
+int
st_add_direct(table, key, value)
-st_table *table;
-char *key;
-char *value;
+ st_table *table;
+ char *key;
+ char *value;
{
int hash_val;
st_table_entry *tbl;
@@ -181,10 +181,11 @@ char *value;
ADD_DIRECT(table, key, value, hash_val, tbl);
}
+int
st_find_or_add(table, key, slot)
-st_table *table;
-char *key;
-char ***slot;
+ st_table *table;
+ char *key;
+ char ***slot;
{
int hash_val;
st_table_entry *tbl, *ptr;
@@ -203,13 +204,14 @@ char ***slot;
}
}
-static rehash(table)
-register st_table *table;
+static void
+rehash(table)
+ register st_table *table;
{
register st_table_entry *ptr, *next, **old_bins = table->bins;
int i, old_num_bins = table->num_bins, hash_val;
- table->num_bins = table->grow_factor*old_num_bins;
+ table->num_bins = 2*old_num_bins;
if (table->num_bins%2 == 0) {
table->num_bins += 1;
@@ -234,8 +236,9 @@ register st_table *table;
free((char *) old_bins);
}
-st_table *st_copy(old_table)
-st_table *old_table;
+st_table*
+st_copy(old_table)
+ st_table *old_table;
{
st_table *new_table;
st_table_entry *ptr, *tbl;
@@ -275,10 +278,11 @@ st_table *old_table;
return new_table;
}
+int
st_delete(table, key, value)
-register st_table *table;
-register char **key;
-char **value;
+ register st_table *table;
+ register char **key;
+ char **value;
{
int hash_val;
st_table_entry *tmp;
@@ -317,10 +321,11 @@ char **value;
return 0;
}
+int
st_foreach(table, func, arg)
-st_table *table;
-enum st_retval (*func)();
-char *arg;
+ st_table *table;
+ enum st_retval (*func)();
+ char *arg;
{
st_table_entry *ptr, *last, *tmp;
enum st_retval retval;
@@ -346,14 +351,16 @@ char *arg;
}
ptr = ptr->next;
free((char *) tmp);
+ table->num_entries--;
}
}
}
}
+int
st_strhash(string, modulus)
-register char *string;
-int modulus;
+ register char *string;
+ int modulus;
{
register int val = 0;
register int c;
diff --git a/st.h b/st.h
index 04ac5c1088..0caa85b1ad 100644
--- a/st.h
+++ b/st.h
@@ -23,7 +23,6 @@ struct st_table {
int num_entries;
int max_density;
int reorder_flag;
- double grow_factor;
st_table_entry **bins;
};
@@ -49,7 +48,6 @@ st_table *st_copy();
#define ST_DEFAULT_MAX_DENSITY 5
#define ST_DEFAULT_INIT_TABLE_SIZE 11
-#define ST_DEFAULT_GROW_FACTOR 2.0
#define ST_DEFAULT_REORDER_FLAG 0
int st_strhash();
diff --git a/string.c b/string.c
index 80935255d2..15c24738b8 100644
--- a/string.c
+++ b/string.c
@@ -13,10 +13,13 @@
#include "ruby.h"
#include "re.h"
+#define BEG(no) regs.beg[no]
+#define END(no) regs.end[no]
+
#include <stdio.h>
#include <ctype.h>
-VALUE C_String;
+VALUE cString;
#define STRLEN(s) RSTRING(s)->len
@@ -26,7 +29,7 @@ str_new(ptr, len)
UINT len;
{
NEWOBJ(str, struct RString);
- OBJSETUP(str, C_String, T_STRING);
+ OBJSETUP(str, cString, T_STRING);
str->len = len;
str->orig = Qnil;
@@ -50,7 +53,7 @@ str_new3(str)
struct RString *str;
{
NEWOBJ(str2, struct RString);
- OBJSETUP(str2, C_String, T_STRING);
+ OBJSETUP(str2, cString, T_STRING);
str2->len = str->len;
str2->ptr = str->ptr;
@@ -74,11 +77,11 @@ obj_as_string(obj)
}
str = rb_funcall(obj, pr_str, 0);
if (TYPE(str) != T_STRING)
- return Fkrn_to_s(obj);
+ return krn_to_s(obj);
return str;
}
-VALUE
+static VALUE
str_clone(str)
struct RString *str;
{
@@ -92,36 +95,41 @@ str_clone(str)
return obj;
}
+VALUE
+str_dup(str)
+ struct RString *str;
+{
+ return str_new(str->ptr, str->len);
+}
+
static VALUE
-Sstr_new(class, str)
+str_s_new(class, str)
VALUE class;
struct RString *str;
{
- Check_Type(str, T_STRING);
- {
- NEWOBJ(str2, struct RString);
- OBJSETUP(str2, class, T_STRING);
+ NEWOBJ(str2, struct RString);
+ OBJSETUP(str2, class, T_STRING);
- str2->len = str->len;
- str2->ptr = ALLOC_N(char, str->len+1);
- if (str2->ptr) {
- memcpy(str2->ptr, str->ptr, str->len);
- }
- str2->ptr[str->len] = '\0';
- str2->orig = Qnil;
- return (VALUE)str2;
+ str = as_str(str);
+ str2->len = str->len;
+ str2->ptr = ALLOC_N(char, str->len+1);
+ if (str2->ptr) {
+ memcpy(str2->ptr, str->ptr, str->len);
}
+ str2->ptr[str->len] = '\0';
+ str2->orig = Qnil;
+ return (VALUE)str2;
}
static VALUE
-Fstr_length(str)
+str_length(str)
struct RString *str;
{
return INT2FIX(str->len);
}
VALUE
-Fstr_plus(str1, str2)
+str_plus(str1, str2)
struct RString *str1, *str2;
{
struct RString *str3;
@@ -136,7 +144,7 @@ Fstr_plus(str1, str2)
}
VALUE
-Fstr_times(str, times)
+str_times(str, times)
struct RString *str;
VALUE times;
{
@@ -154,20 +162,6 @@ Fstr_times(str, times)
return (VALUE)str2;
}
-extern VALUE C_Range;
-
-static VALUE
-Fstr_dot2(left, right)
- VALUE left, right;
-{
- extern VALUE C_Range;
- VALUE str;
-
- Check_Type(right, T_STRING);
- str = range_new(left, right);
- return str;
-}
-
VALUE
str_substr(str, start, len)
struct RString *str;
@@ -206,13 +200,6 @@ str_subseq(str, beg, end)
if (end < 0) end = 0;
}
- if (beg > end) {
- int tmp;
-
- Warning("start %d is bigger than end %d", beg, end);
- tmp = beg; beg = end; end = tmp;
- }
-
if (beg >= str->len) {
return str_new(0, 0);
}
@@ -222,7 +209,7 @@ str_subseq(str, beg, end)
len = end - beg + 1;
if (len < 0) {
- Fail("end %d too small(size %d)", end, str->len);
+ len = 0;
}
return str_substr(str, beg, len);
@@ -230,10 +217,13 @@ str_subseq(str, beg, end)
extern VALUE ignorecase;
+#define STR_FREEZE FL_USER1
+
void
str_modify(str)
struct RString *str;
{
+ if (FL_TEST(str, STR_FREEZE)) Fail("can't modify frozen string");
if (str->orig == Qnil) return;
str->ptr = ALLOC_N(char, str->len+1);
if (str->ptr) {
@@ -242,6 +232,32 @@ str_modify(str)
str->orig = Qnil;
}
+static VALUE
+str_freeze(str)
+ VALUE str;
+{
+ FL_SET(str, STR_FREEZE);
+ return str;
+}
+
+static VALUE
+str_frozen(str)
+ VALUE str;
+{
+ if (FL_TEST(str, STR_FREEZE))
+ return TRUE;
+ return FALSE;
+}
+
+VALUE
+str_dup_freezed(str)
+ VALUE str;
+{
+ str = str_dup(str);
+ str_freeze(str);
+ return str;
+}
+
VALUE
str_grow(str, len)
struct RString *str;
@@ -275,7 +291,7 @@ str_cat(str, ptr, len)
}
static VALUE
-Fstr_concat(str1, str2)
+str_concat(str1, str2)
struct RString *str1, *str2;
{
str2 = as_str(str2);
@@ -283,7 +299,7 @@ Fstr_concat(str1, str2)
return (VALUE)str1;
}
-static
+static int
str_hash(str)
struct RString *str;
{
@@ -305,7 +321,7 @@ str_hash(str)
}
static VALUE
-Fstr_hash(str)
+str_hash_method(str)
VALUE str;
{
int key = str_hash(str);
@@ -321,7 +337,7 @@ str_cmp(str1, str2)
UINT len;
int retval;
- if (ignorecase != Qnil) {
+ if (ignorecase != FALSE) {
return str_cicmp(str1, str2);
}
@@ -334,7 +350,7 @@ str_cmp(str1, str2)
}
static VALUE
-Fstr_equal(str1, str2)
+str_equal(str1, str2)
struct RString *str1, *str2;
{
if (TYPE(str2) != T_STRING)
@@ -348,12 +364,12 @@ Fstr_equal(str1, str2)
}
static VALUE
-Fstr_cmp(str1, str2)
+str_cmp_method(str1, str2)
VALUE str1, str2;
{
int result;
- Check_Type(str2, T_STRING);
+ str2 = obj_as_string(str2);
result = str_cmp(str1, str2);
return INT2FIX(result);
}
@@ -361,7 +377,7 @@ Fstr_cmp(str1, str2)
VALUE Freg_match();
static VALUE
-Fstr_match(x, y)
+str_match(x, y)
struct RString *x, *y;
{
VALUE reg;
@@ -369,11 +385,11 @@ Fstr_match(x, y)
switch (TYPE(y)) {
case T_REGEXP:
- return Freg_match(y, x);
+ return reg_match(y, x);
case T_STRING:
- reg = re_regcomp(y);
- start = research(reg, x, 0);
+ reg = reg_regcomp(y);
+ start = reg_search(reg, x, 0, 0);
if (start == -1) {
return FALSE;
}
@@ -386,7 +402,7 @@ Fstr_match(x, y)
}
static VALUE
-Fstr_match2(str)
+str_match2(str)
struct RString *str;
{
extern VALUE rb_lastline;
@@ -396,8 +412,8 @@ Fstr_match2(str)
if (TYPE(rb_lastline) != T_STRING)
Fail("$_ is not a string");
- reg = re_regcomp(str);
- start = research(reg, rb_lastline, 0);
+ reg = reg_regcomp(str);
+ start = reg_search(reg, rb_lastline, 0, 0);
if (start == -1) {
return Qnil;
}
@@ -427,7 +443,7 @@ str_index(str, sub, offset)
}
static VALUE
-Fstr_index(argc, argv, str)
+str_index_method(argc, argv, str)
int argc;
VALUE *argv;
struct RString *str;
@@ -445,7 +461,7 @@ Fstr_index(argc, argv, str)
switch (TYPE(sub)) {
case T_REGEXP:
- pos = research(sub, str, pos);
+ pos = reg_search(sub, str, pos, (struct re_registers *)-1);
break;
case T_STRING:
@@ -461,7 +477,7 @@ Fstr_index(argc, argv, str)
}
static VALUE
-Fstr_rindex(argc, argv, str)
+str_rindex(argc, argv, str)
int argc;
VALUE *argv;
struct RString *str;
@@ -519,7 +535,7 @@ str_next(s)
}
static VALUE
-Fstr_next(orig)
+str_next_method(orig)
struct RString *orig;
{
struct RString *str, *str2;
@@ -545,7 +561,7 @@ Fstr_next(orig)
}
VALUE
-Fstr_upto(beg, end)
+str_upto(beg, end)
VALUE beg, end;
{
VALUE current;
@@ -553,8 +569,10 @@ Fstr_upto(beg, end)
current = beg;
for (;;) {
rb_yield(current);
- if (Fstr_equal(current, end)) break;
- current = Fstr_next(current);
+ if (str_equal(current, end)) break;
+ current = str_next_method(current);
+ if (RSTRING(current)->len > RSTRING(end)->len)
+ break;
}
return Qnil;
@@ -580,8 +598,8 @@ str_aref(str, indx)
return (VALUE)INT2FIX(str->ptr[idx] & 0xff);
case T_REGEXP:
- if (Fstr_index(str, indx))
- return re_last_match(0);
+ if (str_index(str, indx))
+ return reg_last_match(0);
return Qnil;
case T_STRING:
@@ -590,26 +608,18 @@ str_aref(str, indx)
default:
/* check if indx is Range */
- if (obj_is_kind_of(indx, C_Range)) {
+ {
int beg, end;
-
- beg = rb_iv_get(indx, "start"); beg = NUM2INT(beg);
- end = rb_iv_get(indx, "end"); end = NUM2INT(end);
- if (beg > end) {
- int tmp;
-
- Warning("start %d is bigger than end %d", beg, end);
- tmp = beg; beg = end; end = tmp;
+ if (range_beg_end(indx, &beg, &end)) {
+ return str_subseq(str, beg, end);
}
-
- return str_subseq(str, beg, end);
}
Fail("Invalid index for string");
}
}
static VALUE
-Fstr_aref(argc, argv, str)
+str_aref_method(argc, argv, str)
int argc;
VALUE *argv;
struct RString *str;
@@ -674,9 +684,10 @@ str_sub(str, pat, val, once)
VALUE val;
int once;
{
- int beg, end, offset, n;
+ int beg, offset, n;
+ struct re_registers regs;
- Check_Type(val, T_STRING);
+ val = obj_as_string(val);
str_modify(str);
switch (TYPE(pat)) {
@@ -684,19 +695,19 @@ str_sub(str, pat, val, once)
break;
case T_STRING:
- return str_sub(str, re_regcomp(pat), val, once);
+ pat = (struct RRegexp*)reg_regcomp(pat);
+ break;
default:
/* type failed */
Check_Type(pat, T_REGEXP);
}
+ regs.allocated = 0;
for (offset=0, n=0;
- (beg=research(pat, str, offset)) >= 0;
- offset=BEG(0)+STRLEN(val)) {
- end = END(0)-1;
- val = re_regsub(val);
- str_replace2(str, beg, END(0)-1, val);
+ (beg=reg_search(pat, str, offset, &regs)) >= 0;
+ offset=END(0)+1) {
+ str_replace2(str, beg, END(0)-1, reg_regsub(val, str, &regs));
n++;
if (once) break;
}
@@ -739,27 +750,19 @@ str_aset(str, indx, val)
default:
/* check if indx is Range */
- if (obj_is_kind_of(indx, C_Range)) {
- Check_Type(val, T_STRING);
-
- beg = rb_iv_get(indx, "start"); beg = NUM2INT(beg);
- end = rb_iv_get(indx, "end"); end = NUM2INT(end);
- if (beg > end) {
- int tmp;
-
- Warning("start %d is bigger than end %d", beg, end);
- tmp = beg; beg = end; end = tmp;
+ {
+ int beg, end;
+ if (range_beg_end(indx, &beg, &end)) {
+ str_replace2(str, beg, end, val);
+ return val;
}
-
- str_replace2(str, beg, end, val);
- return val;
}
Fail("Invalid index for string");
}
}
static VALUE
-Fstr_aset(argc, argv, str)
+str_aset_method(argc, argv, str)
int argc;
VALUE *argv;
struct RString *str;
@@ -792,9 +795,11 @@ Fstr_aset(argc, argv, str)
static VALUE
str_sub_iter(str, pat, once)
VALUE str, pat;
+ int once;
{
VALUE val;
- int beg, end, offset, n;
+ int beg, offset;
+ struct re_registers regs;
if (!iterator_p()) {
Fail("Wrong # of arguments(1 for 2)");
@@ -806,7 +811,7 @@ str_sub_iter(str, pat, once)
break;
case T_STRING:
- pat = re_regcomp(pat);
+ pat = reg_regcomp(pat);
break;
default:
@@ -815,18 +820,20 @@ str_sub_iter(str, pat, once)
}
offset=0;
- while ((beg=research(pat, str, offset)) >= 0) {
- val = rb_yield(re_nth_match(0));
+ regs.allocated = 0;
+ while ((beg=reg_search(pat, str, offset, &regs)) >= 0) {
+ val = rb_yield(reg_nth_match(0, backref_get()));
val = obj_as_string(val);
str_replace2(str, beg, END(0)-1, val);
offset=BEG(0)+STRLEN(val);
if (once) break;
}
+ re_free_registers(&regs);
return (VALUE)str;
}
static VALUE
-Fstr_sub(argc, argv, str)
+str_sub_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
@@ -840,7 +847,16 @@ Fstr_sub(argc, argv, str)
}
static VALUE
-Fstr_gsub(argc, argv, str)
+str_sub_method(argc, argv, str)
+ int argc;
+ VALUE *argv;
+ VALUE str;
+{
+ return str_sub_bang(argc, argv, str_dup(str));
+}
+
+static VALUE
+str_gsub_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
@@ -853,10 +869,21 @@ Fstr_gsub(argc, argv, str)
return str_sub(str, pat, val, 0);
}
+static VALUE
+str_gsub(argc, argv, str)
+ int argc;
+ VALUE *argv;
+ VALUE str;
+{
+ VALUE v = str_gsub_bang(argc, argv, str_dup(str));
+ if (v) return v;
+ return str;
+}
+
extern VALUE rb_lastline;
static VALUE
-Fsub(argc, argv)
+f_sub_bang(argc, argv)
int argc;
VALUE *argv;
{
@@ -870,7 +897,23 @@ Fsub(argc, argv)
}
static VALUE
-Fgsub(argc, argv)
+f_sub(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE v;
+
+ Check_Type(rb_lastline, T_STRING);
+ v = f_sub_bang(argc, argv, str_dup(rb_lastline));
+ if (v) {
+ rb_lastline = v;
+ return v;
+ }
+ return rb_lastline;
+}
+
+static VALUE
+f_gsub_bang(argc, argv)
int argc;
VALUE *argv;
{
@@ -884,7 +927,41 @@ Fgsub(argc, argv)
}
static VALUE
-Fstr_reverse(str)
+f_gsub(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE v;
+
+ Check_Type(rb_lastline, T_STRING);
+ v = f_gsub_bang(argc, argv, str_dup(rb_lastline));
+ if (v) {
+ rb_lastline = v;
+ return v;
+ }
+ return rb_lastline;
+}
+
+static VALUE
+str_reverse_bang(str)
+ struct RString *str;
+{
+ char *s, *e, *p;
+
+ s = str->ptr;
+ e = s + str->len - 1;
+ p = ALLOCA_N(char, str->len);
+
+ while (e >= s) {
+ *p++ = *e--;
+ }
+ MEMCPY(str->ptr, p, char, str->len);
+
+ return (VALUE)str;
+}
+
+static VALUE
+str_reverse(str)
struct RString *str;
{
VALUE obj = str_new(0, str->len);
@@ -901,14 +978,14 @@ Fstr_reverse(str)
}
static VALUE
-Fstr_to_i(str)
+str_to_i(str)
struct RString *str;
{
return str2inum(str->ptr, 10);
}
static VALUE
-Fstr_to_f(str)
+str_to_f(str)
struct RString *str;
{
double atof();
@@ -918,35 +995,50 @@ Fstr_to_f(str)
}
static VALUE
-Fstr_to_s(str)
+str_to_s(str)
VALUE str;
{
return str;
}
static VALUE
-Fstr_inspect(str)
+str_inspect(str)
struct RString *str;
{
- char buf[160];
+ struct RString *str0;
char *p, *pend;
- char *b, *bend;
+ char *b;
+ int offset;
-#define CHECK(n) if (b+n > bend) break;
+ str0 = (struct RString*)str_new2("\"");
+ offset = 1;
+#define CHECK(n) do {\
+ str_cat(str0, 0, n);\
+ b = str0->ptr + offset;\
+ offset += n;\
+} while (0)
p = str->ptr; pend = p + str->len;
- b = buf; bend = b + sizeof buf - (str->len>150?4:2);
- *b++ = '"';
while (p < pend) {
char c = *p++;
- if (isprint(c)) {
- CHECK(1);
+ if (ismbchar(c) && p+1 < pend) {
+ CHECK(2);
*b++ = c;
+ *b++ = *p++;
+ }
+ else if (c == '"') {
+ CHECK(2);
+ *b++ = '\\';
+ *b++ = '"';
}
- else if (ismbchar(c)) {
+ else if (c == '\\') {
CHECK(2);
+ *b++ = '\\';
+ *b++ = '\\';
+ }
+ else if (isprint(c)) {
+ CHECK(1);
*b++ = c;
- *b++ = *p++;
}
else if (c == '\n') {
CHECK(2);
@@ -973,7 +1065,7 @@ Fstr_inspect(str)
*b++ = '\\';
*b++ = 'v';
}
- else if (c == '\1') {
+ else if (c == '\007') {
CHECK(2);
*b++ = '\\';
*b++ = 'a';
@@ -983,28 +1075,19 @@ Fstr_inspect(str)
*b++ = '\\';
*b++ = 'e';
}
- else if (iscntrl(c)) {
- CHECK(2);
- *b++ = '^';
- *b++ = c;
- }
else {
- CHECK(1);
- *b++ = c;
- }
- }
- *b++ = '"';
- if (p < pend) {
- bend = buf + sizeof buf;
- while (b < bend) {
- *b++ = '.';
+ CHECK(4);
+ *b++ = '\\';
+ sprintf(b, "%03o", c);
+ b += 3;
}
}
- return str_new(buf, b - buf);
+ str_cat(str0, "\"", 1);
+ return (VALUE)str0;
}
static VALUE
-Fstr_upcase(str)
+str_upcase_bang(str)
struct RString *str;
{
char *s, *send;
@@ -1022,7 +1105,14 @@ Fstr_upcase(str)
}
static VALUE
-Fstr_downcase(str)
+str_upcase(str)
+ struct RString *str;
+{
+ return str_upcase_bang(str_dup(str));
+}
+
+static VALUE
+str_downcase_bang(str)
struct RString *str;
{
char *s, *send;
@@ -1040,7 +1130,14 @@ Fstr_downcase(str)
}
static VALUE
-Fstr_capitalize(str)
+str_downcase(str)
+ struct RString *str;
+{
+ return str_downcase_bang(str_dup(str));
+}
+
+static VALUE
+str_capitalize_bang(str)
struct RString *str;
{
char *s, *send;
@@ -1058,7 +1155,14 @@ Fstr_capitalize(str)
}
static VALUE
-Fstr_swapcase(str)
+str_capitalize(str)
+ struct RString *str;
+{
+ return str_capitalize_bang(str_dup(str));
+}
+
+static VALUE
+str_swapcase_bang(str)
struct RString *str;
{
char *s, *send;
@@ -1079,25 +1183,20 @@ Fstr_swapcase(str)
}
static VALUE
-Fstr_toupper(str)
+str_swapcase(str)
struct RString *str;
{
- return Fstr_upcase(str_new(str->ptr, str->len));
+ return str_swapcase_bang(str_dup(str));
}
-static VALUE
-Fstr_tolower(str)
- struct RString *str;
-{
- return Fstr_downcase(str_new(str->ptr, str->len));
-}
+typedef unsigned char *USTR;
struct tr {
- unsigned char gen, now, max;
+ int gen, now, max;
char *p, *pend;
} trsrc, trrepl;
-static char
+static int
trnext(t)
struct tr *t;
{
@@ -1108,12 +1207,12 @@ trnext(t)
if (t->p < t->pend && *t->p == '-') {
t->p++;
if (t->p < t->pend) {
- if (t->now > *t->p) {
+ if (t->now > *(USTR)t->p) {
t->p++;
continue;
}
t->gen = 1;
- t->max = *t->p++;
+ t->max = *(USTR)t->p++;
}
}
return t->now;
@@ -1129,13 +1228,13 @@ trnext(t)
}
static VALUE
-Fstr_tr(str, src, repl)
+str_tr_bang(str, src, repl)
struct RString *str, *src, *repl;
{
struct tr trsrc, trrepl;
int cflag = 0;
char trans[256];
- int i, c, save;
+ int i, c;
char *s, *send, *t;
Check_Type(src, T_STRING);
@@ -1176,7 +1275,7 @@ Fstr_tr(str, src, repl)
char r;
for (i=0; i<256; i++) {
- trans[i] = 0;
+ trans[i] = i;
}
while ((c = trnext(&trsrc)) >= 0) {
r = trnext(&trrepl);
@@ -1197,6 +1296,13 @@ Fstr_tr(str, src, repl)
return (VALUE)str;
}
+static VALUE
+str_tr(str, src, repl)
+ struct RString *str, *src, *repl;
+{
+ return str_tr_bang(str_dup(str), src, repl);
+}
+
static void
tr_setup_table(str, table)
struct RString *str;
@@ -1222,7 +1328,7 @@ tr_setup_table(str, table)
}
static VALUE
-Fstr_delete(str1, str2)
+str_delete_bang(str1, str2)
struct RString *str1, *str2;
{
char *s, *send, *t;
@@ -1248,6 +1354,13 @@ Fstr_delete(str1, str2)
}
static VALUE
+str_delete(str1, str2)
+ struct RString *str1, *str2;
+{
+ return str_delete_bang(str_dup(str1), str2);
+}
+
+static VALUE
tr_squeeze(str1, str2)
struct RString *str1, *str2;
{
@@ -1284,7 +1397,7 @@ tr_squeeze(str1, str2)
}
static VALUE
-Fstr_squeeze(argc, argv, str1)
+str_squeeze_bang(argc, argv, str1)
int argc;
VALUE *argv;
VALUE str1;
@@ -1299,18 +1412,34 @@ Fstr_squeeze(argc, argv, str1)
}
static VALUE
-Fstr_tr_s(str, src, repl)
+str_squeeze(argc, argv, str)
+ int argc;
+ VALUE *argv;
+ VALUE str;
+{
+ return str_squeeze_bang(argc, argv, str_dup(str));
+}
+
+static VALUE
+str_tr_s_bang(str, src, repl)
VALUE str, src, repl;
{
Check_Type(src, T_STRING);
Check_Type(repl, T_STRING);
- Fstr_tr(str, src, repl);
+ str_tr(str, src, repl);
tr_squeeze(str, repl);
return str;
}
static VALUE
-Fstr_split(argc, argv, str)
+str_tr_s(str, src, repl)
+ VALUE str, src, repl;
+{
+ return str_tr_s_bang(str_dup(str), src, repl);
+}
+
+static VALUE
+str_split_method(argc, argv, str)
int argc;
VALUE *argv;
struct RString *str;
@@ -1343,7 +1472,7 @@ Fstr_split(argc, argv, str)
char_sep = RSTRING(spat)->ptr[0];
}
else {
- spat = (struct RRegexp*)re_regcomp(spat);
+ spat = (struct RRegexp*)reg_regcomp(spat);
}
break;
case T_REGEXP:
@@ -1401,9 +1530,11 @@ Fstr_split(argc, argv, str)
int start = beg;
int last_null = 0;
int idx;
+ struct re_registers regs;
- while ((end = research(spat, str, start)) >= 0) {
- if (start == end && BEG(0) == END(0)) {
+ regs.allocated = 0;
+ while ((end = reg_search(spat, str, start, &regs)) >= 0) {
+ if (start == end && regs.beg[0] == regs.end[0]) {
if (last_null == 1) {
if (ismbchar(str->ptr[beg]))
ary_push(result, str_substr(str, beg, 2));
@@ -1420,22 +1551,23 @@ Fstr_split(argc, argv, str)
}
else {
ary_push(result, str_substr(str, beg, end-beg));
- beg = start = END(0);
+ beg = start = regs.end[0];
if (limit && lim <= ++i) break;
}
last_null = 0;
for (idx=1; idx < 10; idx++) {
- if (BEG(idx) == -1) break;
- if (BEG(idx) == END(idx))
+ if (regs.beg[idx] == -1) break;
+ if (regs.beg[idx] == regs.end[idx])
tmp = str_new(0, 0);
else
- tmp = str_subseq(str, BEG(idx), END(idx)-1);
+ tmp = str_subseq(str, regs.beg[idx], regs.end[idx]-1);
ary_push(result, tmp);
if (limit && lim <= ++i) break;
}
}
+ re_free_registers(&regs);
}
if (str->len > beg) {
ary_push(result, str_subseq(str, beg, -1));
@@ -1444,8 +1576,19 @@ Fstr_split(argc, argv, str)
return result;
}
+VALUE
+str_split(str, sep0)
+ struct RString* str;
+ char *sep0;
+{
+ VALUE sep;
+
+ sep = str_new2(sep0);
+ return str_split_method(1, &sep, str);
+}
+
static VALUE
-Fstr_each(str)
+str_each_line(str)
struct RString* str;
{
extern VALUE RS;
@@ -1453,6 +1596,7 @@ Fstr_each(str)
int rslen;
char *p = str->ptr, *pend = p + str->len, *s;
char *ptr = p;
+ int len = str->len;
if (RS == Qnil) {
rb_yield(str);
@@ -1478,7 +1622,8 @@ Fstr_each(str)
memcmp(RSTRING(RS)->ptr, p-rslen+1, rslen) == 0)) {
rb_lastline = str_new(s, p - s + 1);
rb_yield(rb_lastline);
- if (str->ptr != ptr) Fail("string modified");
+ if (str->ptr != ptr || str->len != len)
+ Fail("string modified");
s = p + 1;
}
}
@@ -1492,7 +1637,7 @@ Fstr_each(str)
}
static VALUE
-Fstr_each_byte(str)
+str_each_byte(str)
struct RString* str;
{
int i;
@@ -1504,7 +1649,7 @@ Fstr_each_byte(str)
}
static VALUE
-Fstr_chop(str)
+str_chop_bang(str)
struct RString *str;
{
str_modify(str);
@@ -1516,11 +1661,20 @@ Fstr_chop(str)
}
static VALUE
-Fstr_strip(str)
+str_chop(str)
+ struct RString *str;
+{
+ return str_chop_bang(str_dup(str));
+}
+
+static VALUE
+str_strip_bang(str)
struct RString *str;
{
char *s, *t, *e;
+ str_modify(str);
+
s = str->ptr;
e = t = s + str->len;
/* remove spaces at head */
@@ -1531,49 +1685,55 @@ Fstr_strip(str)
while (s <= t && isspace(*t)) t--;
t++;
- if (s > str->ptr || t < e) {
+ str->len = t-s;
+ if (s > str->ptr) {
char *p = str->ptr;
- int len = t-s;
- str->ptr = ALLOC_N(char, len+1);
- memcpy(str->ptr, p, len);
- str->ptr[len] = '\0';
- if (str->orig) {
- str->orig = Qnil;
- }
- else {
- free(p);
- }
+ str->ptr = ALLOC_N(char, str->len+1);
+ memcpy(str->ptr, s, str->len);
+ str->ptr[str->len] = '\0';
+ free(p);
+ }
+ else if (t < e) {
+ str->ptr[str->len] = '\0';
}
+
return (VALUE)str;
}
static VALUE
-Fstr_hex(str)
+str_strip(str)
+ struct RString *str;
+{
+ return str_strip_bang(str_dup(str));
+}
+
+static VALUE
+str_hex(str)
struct RString *str;
{
return str2inum(str->ptr, 16);
}
static VALUE
-Fstr_oct(str)
+str_oct(str)
struct RString *str;
{
return str2inum(str->ptr, 8);
}
static VALUE
-Fstr_crypt(str, salt)
+str_crypt(str, salt)
struct RString *str, *salt;
{
- Check_Type(salt, T_STRING);
+ salt = as_str(salt);
if (salt->len < 2)
- Fail("salt too short(need 2 byte)");
+ Fail("salt too short(need >2 bytes)");
return str_new2(crypt(str->ptr, salt->ptr));
}
static VALUE
-Fstr_intern(str)
+str_intern(str)
struct RString *str;
{
if (strlen(str->ptr) != str->len)
@@ -1583,7 +1743,7 @@ Fstr_intern(str)
}
static VALUE
-Fstr_sum(argc, argv, str)
+str_sum(argc, argv, str)
int argc;
VALUE *argv;
struct RString *str;
@@ -1624,7 +1784,8 @@ Fstr_sum(argc, argv, str)
}
}
-Fstr_ljust(str, w)
+VALUE
+str_ljust(str, w)
struct RString *str;
VALUE w;
{
@@ -1642,7 +1803,8 @@ Fstr_ljust(str, w)
return (VALUE)res;
}
-Fstr_rjust(str, w)
+VALUE
+str_rjust(str, w)
struct RString *str;
VALUE w;
{
@@ -1660,7 +1822,8 @@ Fstr_rjust(str, w)
return (VALUE)res;
}
-Fstr_center(str, w)
+VALUE
+str_center(str, w)
struct RString *str;
VALUE w;
{
@@ -1684,76 +1847,97 @@ Fstr_center(str, w)
return (VALUE)res;
}
-extern VALUE C_Kernel;
-extern VALUE M_Comparable;
-extern VALUE M_Enumerable;
+extern VALUE cKernel;
+extern VALUE mComparable;
+extern VALUE mEnumerable;
+void
Init_String()
{
- C_String = rb_define_class("String", C_Object);
- rb_include_module(C_String, M_Comparable);
- rb_include_module(C_String, M_Enumerable);
- rb_define_single_method(C_String, "new", Sstr_new, 1);
- rb_define_method(C_String, "clone", str_clone, 0);
- rb_define_method(C_String, "<=>", Fstr_cmp, 1);
- rb_define_method(C_String, "==", Fstr_equal, 1);
- rb_define_method(C_String, "hash", Fstr_hash, 0);
- rb_define_method(C_String, "+", Fstr_plus, 1);
- rb_define_method(C_String, "*", Fstr_times, 1);
- rb_define_method(C_String, "..", Fstr_dot2, 1);
- rb_define_method(C_String, "[]", Fstr_aref, -1);
- rb_define_method(C_String, "[]=", Fstr_aset, -1);
- rb_define_method(C_String, "length", Fstr_length, 0);
- rb_define_alias(C_String, "size", "length");
- rb_define_method(C_String, "=~", Fstr_match, 1);
- rb_define_method(C_String, "~", Fstr_match2, 0);
- rb_define_method(C_String, "next", Fstr_next, 0);
- rb_define_method(C_String, "upto", Fstr_next, 1);
- rb_define_method(C_String, "index", Fstr_index, -1);
- rb_define_method(C_String, "rindex", Fstr_rindex, -1);
-
- rb_define_method(C_String, "to_i", Fstr_to_i, 0);
- rb_define_method(C_String, "to_f", Fstr_to_f, 0);
- rb_define_method(C_String, "to_s", Fstr_to_s, 0);
- rb_define_method(C_String, "_inspect", Fstr_inspect, 0);
-
- rb_define_method(C_String, "toupper", Fstr_toupper, 0);
- rb_define_method(C_String, "tolower", Fstr_tolower, 0);
-
- rb_define_method(C_String, "upcase", Fstr_upcase, 0);
- rb_define_method(C_String, "downcase", Fstr_downcase, 0);
- rb_define_method(C_String, "capitalize", Fstr_capitalize, 0);
- rb_define_method(C_String, "swapcase", Fstr_swapcase, 0);
-
- rb_define_method(C_String, "hex", Fstr_hex, 0);
- rb_define_method(C_String, "oct", Fstr_oct, 0);
- rb_define_method(C_String, "split", Fstr_split, -1);
- rb_define_method(C_String, "reverse", Fstr_reverse, 0);
- rb_define_method(C_String, "concat", Fstr_concat, 1);
- rb_define_method(C_String, "crypt", Fstr_crypt, 1);
- rb_define_method(C_String, "intern", Fstr_intern, 0);
-
- rb_define_method(C_String, "ljust", Fstr_ljust, 1);
- rb_define_method(C_String, "rjust", Fstr_rjust, 1);
- rb_define_method(C_String, "center", Fstr_center, 1);
-
- rb_define_method(C_String, "sub", Fstr_sub, -1);
- rb_define_method(C_String, "gsub", Fstr_gsub, -1);
- rb_define_method(C_String, "chop", Fstr_chop, 0);
- rb_define_method(C_String, "strip", Fstr_strip, 0);
-
- rb_define_method(C_String, "tr", Fstr_tr, 2);
- rb_define_method(C_String, "tr_s", Fstr_tr_s, 2);
- rb_define_method(C_String, "delete", Fstr_delete, 1);
- rb_define_method(C_String, "squeeze", Fstr_squeeze, -1);
-
- rb_define_method(C_String, "each", Fstr_each, 0);
- rb_define_method(C_String, "each_byte", Fstr_each_byte, 0);
-
- rb_define_method(C_String, "sum", Fstr_sum, -1);
-
- rb_define_private_method(C_Kernel, "sub", Fsub, -1);
- rb_define_private_method(C_Kernel, "gsub", Fgsub, -1);
+ cString = rb_define_class("String", cObject);
+ rb_include_module(cString, mComparable);
+ rb_include_module(cString, mEnumerable);
+ rb_define_singleton_method(cString, "new", str_s_new, 1);
+ rb_define_method(cString, "clone", str_clone, 0);
+ rb_define_method(cString, "dup", str_dup, 0);
+ rb_define_method(cString, "<=>", str_cmp_method, 1);
+ rb_define_method(cString, "==", str_equal, 1);
+ rb_define_method(cString, "hash", str_hash_method, 0);
+ rb_define_method(cString, "+", str_plus, 1);
+ rb_define_method(cString, "*", str_times, 1);
+ rb_define_method(cString, "[]", str_aref_method, -1);
+ rb_define_method(cString, "[]=", str_aset_method, -1);
+ rb_define_method(cString, "length", str_length, 0);
+ rb_define_alias(cString, "size", "length");
+ rb_define_method(cString, "=~", str_match, 1);
+ rb_define_method(cString, "~", str_match2, 0);
+ rb_define_method(cString, "next", str_next_method, 0);
+ rb_define_method(cString, "upto", str_next, 1);
+ rb_define_method(cString, "index", str_index_method, -1);
+ rb_define_method(cString, "rindex", str_rindex, -1);
+
+ rb_define_method(cString, "freeze", str_freeze, 0);
+ rb_define_method(cString, "frozen?", str_frozen, 0);
+
+ rb_define_method(cString, "to_i", str_to_i, 0);
+ rb_define_method(cString, "to_f", str_to_f, 0);
+ rb_define_method(cString, "to_s", str_to_s, 0);
+ rb_define_method(cString, "inspect", str_inspect, 0);
+
+ rb_define_method(cString, "upcase", str_upcase, 0);
+ rb_define_method(cString, "downcase", str_downcase, 0);
+ rb_define_method(cString, "capitalize", str_capitalize, 0);
+ rb_define_method(cString, "swapcase", str_swapcase, 0);
+
+ rb_define_method(cString, "upcase!", str_upcase_bang, 0);
+ rb_define_method(cString, "downcase!", str_downcase_bang, 0);
+ rb_define_method(cString, "capitalize!", str_capitalize_bang, 0);
+ rb_define_method(cString, "swapcase!", str_swapcase_bang, 0);
+
+ rb_define_method(cString, "hex", str_hex, 0);
+ rb_define_method(cString, "oct", str_oct, 0);
+ rb_define_method(cString, "split", str_split_method, -1);
+ rb_define_method(cString, "reverse", str_reverse, 0);
+ rb_define_method(cString, "reverse!", str_reverse_bang, 0);
+ rb_define_method(cString, "concat", str_concat, 1);
+ rb_define_method(cString, "crypt", str_crypt, 1);
+ rb_define_method(cString, "intern", str_intern, 0);
+
+ rb_define_method(cString, "ljust", str_ljust, 1);
+ rb_define_method(cString, "rjust", str_rjust, 1);
+ rb_define_method(cString, "center", str_center, 1);
+
+ rb_define_method(cString, "sub", str_sub_method, -1);
+ rb_define_method(cString, "gsub", str_gsub, -1);
+ rb_define_method(cString, "chop", str_chop, 0);
+ rb_define_method(cString, "strip", str_strip, 0);
+
+ rb_define_method(cString, "sub!", str_sub_bang, -1);
+ rb_define_method(cString, "gsub!", str_gsub_bang, -1);
+ rb_define_method(cString, "strip!", str_strip_bang, 0);
+ rb_define_method(cString, "chop!", str_chop_bang, 0);
+
+ rb_define_method(cString, "tr", str_tr, 2);
+ rb_define_method(cString, "tr_s", str_tr_s, 2);
+ rb_define_method(cString, "delete", str_delete, 1);
+ rb_define_method(cString, "squeeze", str_squeeze, -1);
+
+ rb_define_method(cString, "tr!", str_tr_bang, 2);
+ rb_define_method(cString, "tr_s!", str_tr_s_bang, 2);
+ rb_define_method(cString, "delete!", str_delete_bang, 1);
+ rb_define_method(cString, "squeeze!", str_squeeze_bang, -1);
+
+ rb_define_method(cString, "each_line", str_each_line, 0);
+ rb_define_method(cString, "each_byte", str_each_byte, 0);
+ rb_define_method(cString, "each", str_each_byte, 0);
+
+ rb_define_method(cString, "sum", str_sum, -1);
+
+ rb_define_private_method(cKernel, "sub", f_sub, -1);
+ rb_define_private_method(cKernel, "gsub", f_gsub, -1);
+
+ rb_define_private_method(cKernel, "sub!", f_sub_bang, -1);
+ rb_define_private_method(cKernel, "gsub!", f_gsub_bang, -1);
pr_str = rb_intern("to_s");
}
diff --git a/struct.c b/struct.c
index c231191736..2f4c35f397 100644
--- a/struct.c
+++ b/struct.c
@@ -9,203 +9,263 @@
************************************************/
#include "ruby.h"
-#include "env.h"
-VALUE C_Struct;
-extern VALUE M_Enumerable;
-
-char *strdup();
+ID rb_frame_last_func();
+VALUE cStruct;
+extern VALUE mEnumerable;
static VALUE
-struct_alloc(class, name)
- VALUE class;
- char *name;
+struct_ref(obj)
+ struct RStruct *obj;
{
- NEWOBJ(st, struct RStruct);
- OBJSETUP(st, class, T_STRUCT);
-
- if (name) st->name = strdup(name);
- else st->name = Qnil;
- st->len = 0;
- st->tbl = Qnil;
+ VALUE nstr, member, slot;
+ int i;
- return (VALUE)st;
+ nstr = CLASS_OF(obj);
+ member = rb_ivar_get(nstr, rb_intern("__member__"));
+ if (member == Qnil) {
+ Fail("non-initialized struct");
+ }
+ slot = INT2FIX(rb_frame_last_func());
+ for (i=0; i<RARRAY(member)->len; i++) {
+ if (RARRAY(member)->ptr[i] == slot) {
+ return obj->ptr[i];
+ }
+ }
+ Fail("not struct member");
+ return Qnil; /* not reached */
}
+static VALUE struct_ref0(obj) struct RStruct *obj; {return obj->ptr[0];}
+static VALUE struct_ref1(obj) struct RStruct *obj; {return obj->ptr[1];}
+static VALUE struct_ref2(obj) struct RStruct *obj; {return obj->ptr[2];}
+static VALUE struct_ref3(obj) struct RStruct *obj; {return obj->ptr[3];}
+static VALUE struct_ref4(obj) struct RStruct *obj; {return obj->ptr[4];}
+static VALUE struct_ref5(obj) struct RStruct *obj; {return obj->ptr[5];}
+static VALUE struct_ref6(obj) struct RStruct *obj; {return obj->ptr[6];}
+static VALUE struct_ref7(obj) struct RStruct *obj; {return obj->ptr[7];}
+static VALUE struct_ref8(obj) struct RStruct *obj; {return obj->ptr[8];}
+static VALUE struct_ref9(obj) struct RStruct *obj; {return obj->ptr[9];}
+
+VALUE (*ref_func[10])() = {
+ struct_ref0,
+ struct_ref1,
+ struct_ref2,
+ struct_ref3,
+ struct_ref4,
+ struct_ref5,
+ struct_ref6,
+ struct_ref7,
+ struct_ref8,
+ struct_ref9,
+};
+
static VALUE
-struct_find(s, id)
- struct RStruct *s;
- ID id;
+struct_set(obj, val)
+ struct RStruct *obj;
+ VALUE val;
{
- struct kv_pair *t, *tend;
+ VALUE nstr, member, slot;
+ int i;
- t = s->tbl;
- tend = t + s->len;
- while (t < tend) {
- if (t->key == id) return t->value;
- t++;
+ nstr = CLASS_OF(obj);
+ member = rb_ivar_get(nstr, rb_intern("__member__"));
+ if (member == Qnil) {
+ Fail("non-initialized struct");
}
- Fail("struct %s has no member %s", s->name, rb_id2name(id));
+ for (i=0; i<RARRAY(member)->len; i++) {
+ slot = RARRAY(member)->ptr[i];
+ if (id_attrset(FIX2INT(slot)) == rb_frame_last_func()) {
+ return obj->ptr[i] = val;
+ }
+ }
+ Fail("not struct member");
+ return Qnil; /* not reached */
}
-static VALUE
-Fstruct_access(s)
- struct RStruct *s;
-{
- return struct_find(s, the_env->last_func);
-}
+static VALUE struct_s_new();
static VALUE
-struct_add(s, mem, val)
- struct RStruct *s;
- char *mem;
- VALUE val;
+make_struct(name, member)
+ struct RString *name;
+ struct RArray *member;
{
- int pos = s->len;
+ VALUE nstr;
+ int i;
- s->len++;
- if (s->tbl == Qnil) {
- s->tbl = ALLOC_N(struct kv_pair, 1);
- }
- else {
- REALLOC_N(s->tbl, struct kv_pair, s->len);
+ nstr = rb_define_class_under(cStruct, name->ptr, cStruct);
+ rb_ivar_set(nstr, rb_intern("__size__"), INT2FIX(member->len));
+ rb_ivar_set(nstr, rb_intern("__member__"), member);
+
+ rb_define_singleton_method(nstr, "new", struct_s_new, -1);
+ for (i=0; i< member->len; i++) {
+ ID id = FIX2INT(member->ptr[i]);
+ if (i<10) {
+ rb_define_method_id(nstr, id, ref_func[i], 0);
+ }
+ else {
+ rb_define_method_id(nstr, id, struct_ref, 0);
+ }
+ rb_define_method_id(nstr, id_attrset(id), struct_set, 1);
}
- s->tbl[pos].key = rb_intern(mem);
- s->tbl[pos].value = val;
- rb_define_single_method(s, mem, Fstruct_access, 0);
+ return nstr;
}
#include <varargs.h>
VALUE
-struct_new(name, va_alist)
+struct_define(name, va_alist)
char *name;
va_dcl
{
- VALUE st;
- va_list args;
+ va_list ar;
+ VALUE nm, ary;
char *mem;
- st = struct_alloc(C_Struct,name);
- va_start(args);
- while (mem = va_arg(args, char*)) {
- struct_add(st, mem, va_arg(args, VALUE));
+ nm = str_new2(name);
+ ary = ary_new();
+
+ va_start(ar);
+ while (mem = va_arg(ar, char*)) {
+ ID slot = rb_intern(mem);
+ ary_push(ary, INT2FIX(slot));
}
- va_end(vargs);
+ va_end(ar);
- return st;
+ return make_struct(nm, ary);
}
-#define ASSOC_KEY(a) RASSOC(a)->car
-#define ASSOC_VAL(a) RASSOC(a)->cdr
-
static VALUE
-Sstruct_new(argc, argv, class)
+struct_s_def(argc, argv)
int argc;
VALUE *argv;
- VALUE class;
{
- VALUE name, st;
- struct RArray *tbl;
- int i, max;
+ struct RString *name;
+ struct RArray *rest;
+ VALUE nstr;
+ int i;
- rb_scan_args(argc, argv, "1*", &name, &tbl);
+ rb_scan_args(argc, argv, "1*", &name, &rest);
Check_Type(name, T_STRING);
+ for (i=0; i<rest->len; i++) {
+ Check_Type(rest->ptr[i], T_FIXNUM);
+ }
+ return make_struct(name, rest);
+}
- st = struct_alloc(class, RSTRING(name)->ptr);
- for (i=0, max=tbl->len; i<max; i++) {
- VALUE assoc = tbl->ptr[i];
+VALUE
+struct_alloc(class, values)
+ VALUE class;
+ struct RArray *values;
+{
+ VALUE size;
+ int n;
- Check_Type(assoc, T_ASSOC);
- Check_Type(ASSOC_KEY(assoc), T_STRING);
- struct_add(st, RSTRING(ASSOC_KEY(assoc))->ptr, ASSOC_VAL(assoc));
+ size = rb_ivar_get(class, rb_intern("__size__"));
+ n = FIX2INT(size);
+ if (n < values->len) {
+ Fail("struct size differs");
}
-
- return st;
+ else {
+ NEWOBJ(st, struct RStruct);
+ OBJSETUP(st, class, T_STRUCT);
+ st->len = n;
+ st->ptr = ALLOC_N(VALUE, n);
+ MEMCPY(st->ptr, values->ptr, VALUE, values->len);
+ MEMZERO(st->ptr+values->len, VALUE, n - values->len);
+
+ return (VALUE)st;
+ }
+ return Qnil; /* not reached */
}
-static VALUE
-Fstruct_each(s)
- struct RStruct *s;
+VALUE
+struct_new(class, va_alist)
+ VALUE class;
+ va_dcl
{
- struct kv_pair *t, *tend;
+ VALUE val, mem;
+ va_list args;
- t = s->tbl;
- tend = t + s->len;
- while (t < tend) {
- rb_yield(t->value);
- t++;
+ mem = ary_new();
+ va_start(args);
+ while (val = va_arg(args, VALUE)) {
+ ary_push(mem, val);
}
+ va_end(args);
+
+ return struct_alloc(class, mem);
}
static VALUE
-Fstruct_values(s)
- struct RStruct *s;
+struct_s_new(argc, argv, obj)
+ int argc;
+ VALUE *argv;
{
- VALUE ary;
- struct kv_pair *t, *tend;
+ VALUE member, slot;
- ary = ary_new();
- t = s->tbl;
- tend = t + s->len;
- while (t < tend) {
- ary_push(ary, t->value);
- t++;
- }
-
- return ary;
+ member = ary_new4(argc, argv);
+ return struct_alloc(obj, member);
}
static VALUE
-Fstruct_aref(s, idx)
+struct_each(s)
struct RStruct *s;
- VALUE idx;
{
- struct RArray *ary;
int i;
- if (TYPE(idx) == T_STRING)
- return struct_find(rb_intern(RSTRING(idx)->ptr));
-
- i = NUM2INT(idx);
- if (s->len <= i)
- Fail("offset %d too large for struct(size:%d)", i, s->len);
- return s->tbl[i].value;
+ for (i=0; i<s->len; i++) {
+ rb_yield(s->ptr[i]);
+ }
+ return Qnil;
}
+char *rb_class2name();
#define HDR "struct "
static VALUE
-Fstruct_to_s(s)
+struct_to_s(s)
struct RStruct *s;
{
- char *buf;
+ char *name, *buf;
- buf = ALLOCA_N(char, strlen(s->name)+sizeof(HDR)+1);
- sprintf(buf, "%s%s", HDR, s->name);
+ name = rb_class2name(CLASS_OF(s));
+ buf = ALLOCA_N(char, strlen(name)+sizeof(HDR)+1);
+ sprintf(buf, "%s%s", HDR, name);
return str_new2(buf);
}
static VALUE
-Fstruct_inspect(s)
+struct_inspect(s)
struct RStruct *s;
{
- VALUE str, str2;
- char buf[256], *p;
+ char *name = rb_class2name(CLASS_OF(s));
+ ID inspect = rb_intern("inspect");
+ VALUE str, member;
+ char buf[256];
int i;
- ID inspect = rb_intern("_inspect");
- sprintf(buf, "#<%s%s: ", HDR, s->name);
+ member = rb_ivar_get(CLASS_OF(s), rb_intern("__member__"));
+ if (member == Qnil) {
+ Fail("non-initialized struct");
+ }
+
+ sprintf(buf, "#<%s%s: ", HDR, name);
str = str_new2(buf);
for (i=0; i<s->len; i++) {
+ VALUE str2, slot;
+ char *p;
+
if (i > 0) {
str_cat(str, ", ", 2);
}
- p = rb_id2name(s->tbl[i].key);
+ slot = RARRAY(member)->ptr[i];
+ p = rb_id2name(FIX2INT(slot));
str_cat(str, p, strlen(p));
str_cat(str, "=", 1);
- str2 = rb_funcall(s->tbl[i].value, inspect, 0, Qnil);
+ str2 = rb_funcall(s->ptr[i], inspect, 0, 0);
+ str2 = obj_as_string(str2);
str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
}
str_cat(str, ">", 1);
@@ -214,47 +274,108 @@ Fstruct_inspect(s)
}
static VALUE
-Fstruct_to_a(s)
+struct_to_a(s)
+ struct RStruct *s;
+{
+ return ary_new4(s->len, s->ptr);
+}
+
+static VALUE
+struct_clone(s)
+ struct RStruct *s;
+{
+ NEWOBJ(st, struct RStruct);
+ CLONESETUP(st, s);
+ st->len = s->len;
+ st->ptr = ALLOC_N(VALUE, s->len);
+ MEMCPY(st->ptr, s->ptr, VALUE, st->len);
+
+ return (VALUE)st;
+}
+
+static VALUE
+struct_aref(s, idx)
struct RStruct *s;
+ VALUE idx;
{
- VALUE ary;
int i;
- ary = ary_new2(s->len);
- for (i=0; i<s->len; i++) {
- ary_push(ary, s->tbl[i].value);
+ i = NUM2INT(idx);
+ if (i < 0) i = s->len - i;
+ if (i < 0)
+ Fail("offset %d too small for struct(size:%d)", i, s->len);
+ if (s->len <= i)
+ Fail("offset %d too large for struct(size:%d)", i, s->len);
+ return s->ptr[i];
+}
+
+static VALUE
+struct_aset(s, idx, val)
+ struct RStruct *s;
+ VALUE idx, val;
+{
+ int i;
+
+ i = NUM2INT(idx);
+ if (i < 0) i = s->len - i;
+ if (i < 0)
+ Fail("offset %d too small for struct(size:%d)", i, s->len);
+ if (s->len <= i)
+ Fail("offset %d too large for struct(size:%d)", i, s->len);
+ return s->ptr[i] = val;
+}
+
+static VALUE
+struct_equal(s, s2)
+ struct RStruct *s, *s2;
+{
+ int i;
+
+ if (TYPE(s2) != T_STRUCT) return FALSE;
+ if (CLASS_OF(s) != CLASS_OF(s2)) return FALSE;
+ if (s->len != s2->len) {
+ Fail("incomsistent struct");
}
- return ary;
+ for (i=0; i<s->len; i++) {
+ if (!rb_equal(s->ptr[i], s2->ptr[i])) return FALSE;
+ }
+ return TRUE;
}
static VALUE
-Fstruct_clone(s)
+struct_hash(s)
struct RStruct *s;
{
- struct RStruct *st = (struct RStruct*)struct_alloc(s->name);
+ int i, h;
+ ID hash = rb_intern("hash");
- CLONESETUP(st, s);
- st->len = s->len;
- st->tbl = ALLOC_N(struct kv_pair, s->len);
- MEMCPY(st->tbl, s->tbl, struct kv_pair, st->len);
- RBASIC(st)->class = single_class_clone(RBASIC(s)->class);
- return (VALUE)st;
+ h = CLASS_OF(s);
+ for (i=0; i<s->len; i++) {
+ h ^= rb_funcall(s->ptr[i], hash, 0);
+ }
+ return INT2FIX(h);
}
+void
Init_Struct()
{
- C_Struct = rb_define_class("Struct", C_Object);
- rb_include_module(C_Struct, M_Enumerable);
+ cStruct = rb_define_class("Struct", cObject);
+ rb_include_module(cStruct, mEnumerable);
+
+ rb_define_singleton_method(cStruct, "new", struct_s_def, -1);
+
+ rb_define_method(cStruct, "clone", struct_clone, 0);
- rb_define_single_method(C_Struct, "new", Sstruct_new, -1);
- rb_define_method(C_Struct, "clone", Fstruct_clone, 0);
+ rb_define_method(cStruct, "==", struct_equal, 1);
+ rb_define_method(cStruct, "hash", struct_hash, 0);
- rb_define_method(C_Struct, "to_s", Fstruct_to_s, 0);
- rb_define_method(C_Struct, "_inspect", Fstruct_inspect, 0);
- rb_define_method(C_Struct, "to_a", Fstruct_to_a, 0);
+ rb_define_method(cStruct, "to_s", struct_to_s, 0);
+ rb_define_method(cStruct, "inspect", struct_inspect, 0);
+ rb_define_method(cStruct, "to_a", struct_to_a, 0);
+ rb_define_method(cStruct, "values", struct_to_a, 0);
- rb_define_method(C_Struct, "each", Fstruct_each, 0);
- rb_define_method(C_Struct, "values", Fstruct_values, 0);
- rb_define_method(C_Struct, "[]", Fstruct_aref, 1);
+ rb_define_method(cStruct, "each", struct_each, 0);
+ rb_define_method(cStruct, "[]", struct_aref, 1);
+ rb_define_method(cStruct, "[]=", struct_aset, 2);
}
diff --git a/time.c b/time.c
index 6dd6b98ac8..b8ebe05230 100644
--- a/time.c
+++ b/time.c
@@ -12,12 +12,27 @@
#include "ruby.h"
#include <sys/types.h>
-#include <sys/time.h>
+
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+struct timeval {
+ long tv_sec; /* seconds */
+ long tv_usec; /* and microseconds */
+};
+#endif
+
+#ifdef HAVE_SYS_TIMES_H
#include <sys/times.h>
+#endif
#include <math.h>
-static VALUE C_Time;
-extern VALUE M_Comparable;
+static VALUE cTime;
+#if defined(HAVE_TIMES) || defined(NT)
+static VALUE S_Tms;
+#endif
+extern VALUE mComparable;
struct time_object {
struct timeval tv;
@@ -37,12 +52,12 @@ static ID id_tv;
#define MakeTimeval(obj,tobj) {\
if (!id_tv) id_tv = rb_intern("tv");\
- Make_Data_Struct(obj, id_tv, struct time_object, Qnil, Qnil, tobj);\
+ Make_Data_Struct(obj, id_tv, struct time_object, 0, 0, tobj);\
tobj->tm_got=0;\
}
static VALUE
-Stime_now(class)
+time_s_now(class)
VALUE class;
{
VALUE obj = obj_alloc(class);
@@ -59,6 +74,7 @@ Stime_now(class)
static VALUE
time_new_internal(class, sec, usec)
+ VALUE class;
int sec, usec;
{
VALUE obj = obj_alloc(class);
@@ -75,7 +91,7 @@ VALUE
time_new(sec, usec)
int sec, usec;
{
- return time_new_internal(C_Time, sec, usec);
+ return time_new_internal(cTime, sec, usec);
}
struct timeval*
@@ -107,7 +123,7 @@ time_timeval(time)
break;
default:
- if (!obj_is_kind_of(time, C_Time)) {
+ if (!obj_is_kind_of(time, cTime)) {
Fail("Can't convert %s into Time", rb_class2name(CLASS_OF(time)));
}
GetTimeval(time, tobj);
@@ -118,12 +134,9 @@ time_timeval(time)
}
static VALUE
-Stime_at(class, time)
+time_s_at(class, time)
VALUE class, time;
{
- VALUE obj;
- int sec, usec;
- struct time_object *tobj;
struct timeval *tp;
tp = time_timeval(time);
@@ -132,7 +145,7 @@ Stime_at(class, time)
}
static VALUE
-Ftime_to_i(time)
+time_to_i(time)
VALUE time;
{
struct time_object *tobj;
@@ -142,7 +155,7 @@ Ftime_to_i(time)
}
static VALUE
-Ftime_to_f(time)
+time_to_f(time)
VALUE time;
{
struct time_object *tobj;
@@ -152,7 +165,7 @@ Ftime_to_f(time)
}
static VALUE
-Ftime_usec(time)
+time_usec(time)
VALUE time;
{
struct time_object *tobj;
@@ -162,14 +175,14 @@ Ftime_usec(time)
}
static VALUE
-Ftime_cmp(time1, time2)
+time_cmp(time1, time2)
VALUE time1, time2;
{
struct time_object *tobj1, *tobj2;
int i;
GetTimeval(time1, tobj1);
- if (obj_is_member_of(time2, C_Time)) {
+ if (obj_is_instance_of(time2, cTime)) {
GetTimeval(time2, tobj2);
if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) {
if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return INT2FIX(0);
@@ -186,7 +199,7 @@ Ftime_cmp(time1, time2)
}
static VALUE
-Ftime_hash(time)
+time_hash(time)
VALUE time;
{
struct time_object *tobj;
@@ -198,7 +211,7 @@ Ftime_hash(time)
}
static VALUE
-Ftime_localtime(time)
+time_localtime(time)
VALUE time;
{
struct time_object *tobj;
@@ -215,7 +228,7 @@ Ftime_localtime(time)
}
static VALUE
-Ftime_gmtime(time)
+time_gmtime(time)
VALUE time;
{
struct time_object *tobj;
@@ -232,17 +245,16 @@ Ftime_gmtime(time)
}
static VALUE
-Ftime_asctime(time)
+time_asctime(time)
VALUE time;
{
struct time_object *tobj;
- char *ct;
char buf[32];
int len;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
#ifndef HAVE_TM_ZONE
if (tobj->gmt == 1)
@@ -256,21 +268,21 @@ Ftime_asctime(time)
}
static VALUE
-Ftime_coerce(time1, time2)
+time_coerce(time1, time2)
VALUE time1, time2;
{
return time_new(CLASS_OF(time1), NUM2INT(time2), 0);
}
static VALUE
-Ftime_plus(time1, time2)
+time_plus(time1, time2)
VALUE time1, time2;
{
struct time_object *tobj1, *tobj2;
int sec, usec;
GetTimeval(time1, tobj1);
- if (obj_is_member_of(time2, C_Time)) {
+ if (obj_is_instance_of(time2, cTime)) {
GetTimeval(time2, tobj2);
sec = tobj1->tv.tv_sec + tobj2->tv.tv_sec;
usec = tobj1->tv.tv_usec + tobj2->tv.tv_usec;
@@ -287,14 +299,14 @@ Ftime_plus(time1, time2)
}
static VALUE
-Ftime_minus(time1, time2)
+time_minus(time1, time2)
VALUE time1, time2;
{
struct time_object *tobj1, *tobj2;
int sec, usec;
GetTimeval(time1, tobj1);
- if (obj_is_member_of(time2, C_Time)) {
+ if (obj_is_instance_of(time2, cTime)) {
GetTimeval(time2, tobj2);
sec = tobj1->tv.tv_sec - tobj2->tv.tv_sec;
usec = tobj1->tv.tv_usec - tobj2->tv.tv_usec;
@@ -311,124 +323,124 @@ Ftime_minus(time1, time2)
}
static VALUE
-Ftime_sec(time)
+time_sec(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_sec);
}
static VALUE
-Ftime_min(time)
+time_min(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_min);
}
static VALUE
-Ftime_hour(time)
+time_hour(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_hour);
}
static VALUE
-Ftime_mday(time)
+time_mday(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_mday);
}
static VALUE
-Ftime_mon(time)
+time_mon(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_mon);
}
static VALUE
-Ftime_year(time)
+time_year(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_year);
}
static VALUE
-Ftime_wday(time)
+time_wday(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_wday);
}
static VALUE
-Ftime_yday(time)
+time_yday(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_yday);
}
static VALUE
-Ftime_isdst(time)
+time_isdst(time)
VALUE time;
{
struct time_object *tobj;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
return INT2FIX(tobj->tm.tm_isdst);
}
static VALUE
-Ftime_zone(time)
+time_zone(time)
VALUE time;
{
struct time_object *tobj;
@@ -437,7 +449,7 @@ Ftime_zone(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
len = strftime(buf, 10, "%Z", &(tobj->tm));
@@ -445,17 +457,15 @@ Ftime_zone(time)
}
static VALUE
-Ftime_to_a(time)
+time_to_a(time)
VALUE time;
{
struct time_object *tobj;
- struct tm *tm;
- char buf[10];
VALUE ary;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
ary = ary_new3(9,
INT2FIX(tobj->tm.tm_sec),
@@ -471,7 +481,7 @@ Ftime_to_a(time)
}
static VALUE
-Ftime_strftime(time, format)
+time_strftime(time, format)
VALUE time, format;
{
struct time_object *tobj;
@@ -481,12 +491,12 @@ Ftime_strftime(time, format)
Check_Type(format, T_STRING);
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- Ftime_localtime(time);
+ time_localtime(time);
}
if (strlen(RSTRING(format)->ptr) < RSTRING(format)->len) {
/* Ruby string contains \0. */
VALUE str;
- int l, total = 0;
+ int l;
char *p = RSTRING(format)->ptr, *pe = p + RSTRING(format)->len;
str = str_new(0, 0);
@@ -503,60 +513,89 @@ Ftime_strftime(time, format)
}
static VALUE
-Stime_times(obj)
+time_s_times(obj)
VALUE obj;
{
+#ifdef HAVE_TIMES
+#ifndef HZ
+#define HZ 60 /* Universal constant :-) */
+#endif /* HZ */
struct tms buf;
if (times(&buf) == -1) rb_sys_fail(Qnil);
- return struct_new("tms",
- "utime", float_new((double)buf.tms_utime / 60.0),
- "stime", float_new((double)buf.tms_stime / 60.0),
- "cutime", float_new((double)buf.tms_cutime / 60.0),
- "cstime", float_new((double)buf.tms_cstime / 60.0),
+ return struct_new(S_Tms,
+ float_new((double)buf.tms_utime / HZ),
+ float_new((double)buf.tms_stime / HZ),
+ float_new((double)buf.tms_cutime / HZ),
+ float_new((double)buf.tms_cstime / HZ),
Qnil);
+#else
+#ifdef NT
+ FILETIME create, exit, kernel, user;
+ HANDLE hProc;
+
+ hProc = GetCurrentProcess();
+ GetProcessTimes(hProc,&create, &exit, &kernel, &user);
+ return struct_new(S_Tms,
+ float_new((double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime)/2E6),
+ float_new((double)(user.dwHighDateTime*2E32+user.dwLowDateTime)/2E6),
+ float_new((double)0),
+ float_new((double)0),
+ Qnil);
+#else
+ Fail("can't call times");
+ return Qnil;
+#endif
+#endif
}
+void
Init_Time()
{
- C_Time = rb_define_class("Time", C_Object);
- rb_include_module(C_Time, M_Comparable);
-
- rb_define_single_method(C_Time, "now", Stime_now, 0);
- rb_define_single_method(C_Time, "new", Stime_now, 0);
- rb_define_single_method(C_Time, "at", Stime_at, 1);
-
- rb_define_single_method(C_Time, "times", Stime_times, 0);
-
- rb_define_method(C_Time, "to_i", Ftime_to_i, 0);
- rb_define_method(C_Time, "to_f", Ftime_to_f, 0);
- rb_define_method(C_Time, "<=>", Ftime_cmp, 1);
- rb_define_method(C_Time, "hash", Ftime_hash, 0);
-
- rb_define_method(C_Time, "localtime", Ftime_localtime, 0);
- rb_define_method(C_Time, "gmtime", Ftime_gmtime, 0);
- rb_define_method(C_Time, "ctime", Ftime_asctime, 0);
- rb_define_method(C_Time, "asctime", Ftime_asctime, 0);
- rb_define_method(C_Time, "to_s", Ftime_asctime, 0);
- rb_define_method(C_Time, "_inspect", Ftime_asctime, 0);
- rb_define_method(C_Time, "to_a", Ftime_to_a, 0);
- rb_define_method(C_Time, "coerce", Ftime_coerce, 1);
-
- rb_define_method(C_Time, "+", Ftime_plus, 1);
- rb_define_method(C_Time, "-", Ftime_minus, 1);
-
- rb_define_method(C_Time, "sec", Ftime_sec, 0);
- rb_define_method(C_Time, "min", Ftime_min, 0);
- rb_define_method(C_Time, "hour", Ftime_hour, 0);
- rb_define_method(C_Time, "mday", Ftime_mday, 0);
- rb_define_method(C_Time, "year", Ftime_year, 0);
- rb_define_method(C_Time, "wday", Ftime_wday, 0);
- rb_define_method(C_Time, "yday", Ftime_yday, 0);
- rb_define_method(C_Time, "isdst", Ftime_isdst, 0);
-
- rb_define_method(C_Time, "tv_sec", Ftime_to_i, 0);
- rb_define_method(C_Time, "tv_usec", Ftime_usec, 0);
- rb_define_method(C_Time, "usec", Ftime_usec, 0);
-
- rb_define_method(C_Time, "strftime", Ftime_strftime, 1);
+ cTime = rb_define_class("Time", cObject);
+ rb_include_module(cTime, mComparable);
+
+ rb_define_singleton_method(cTime, "now", time_s_now, 0);
+ rb_define_singleton_method(cTime, "new", time_s_now, 0);
+ rb_define_singleton_method(cTime, "at", time_s_at, 1);
+
+ rb_define_singleton_method(cTime, "times", time_s_times, 0);
+
+ rb_define_method(cTime, "to_i", time_to_i, 0);
+ rb_define_method(cTime, "to_f", time_to_f, 0);
+ rb_define_method(cTime, "<=>", time_cmp, 1);
+ rb_define_method(cTime, "hash", time_hash, 0);
+
+ rb_define_method(cTime, "localtime", time_localtime, 0);
+ rb_define_method(cTime, "gmtime", time_gmtime, 0);
+ rb_define_method(cTime, "ctime", time_asctime, 0);
+ rb_define_method(cTime, "asctime", time_asctime, 0);
+ rb_define_method(cTime, "to_s", time_asctime, 0);
+ rb_define_method(cTime, "inspect", time_asctime, 0);
+ rb_define_method(cTime, "to_a", time_to_a, 0);
+ rb_define_method(cTime, "coerce", time_coerce, 1);
+
+ rb_define_method(cTime, "+", time_plus, 1);
+ rb_define_method(cTime, "-", time_minus, 1);
+
+ rb_define_method(cTime, "sec", time_sec, 0);
+ rb_define_method(cTime, "min", time_min, 0);
+ rb_define_method(cTime, "hour", time_hour, 0);
+ rb_define_method(cTime, "mday", time_mday, 0);
+ rb_define_method(cTime, "mon", time_mon, 0);
+ rb_define_method(cTime, "year", time_year, 0);
+ rb_define_method(cTime, "wday", time_wday, 0);
+ rb_define_method(cTime, "yday", time_yday, 0);
+ rb_define_method(cTime, "isdst", time_isdst, 0);
+ rb_define_method(cTime, "zone", time_zone, 0);
+
+ rb_define_method(cTime, "tv_sec", time_to_i, 0);
+ rb_define_method(cTime, "tv_usec", time_usec, 0);
+ rb_define_method(cTime, "usec", time_usec, 0);
+
+ rb_define_method(cTime, "strftime", time_strftime, 1);
+
+#if defined(HAVE_TIMES) || defined(NT)
+ S_Tms = struct_define("Tms", "utime", "stime", "cutime", "cstime", Qnil);
+#endif
}
diff --git a/util.c b/util.c
index 447542cc3b..19a0416794 100644
--- a/util.c
+++ b/util.c
@@ -3,7 +3,6 @@
util.c -
$Author$
- $Revision$
$Date$
created at: Fri Mar 10 17:22:34 JST 1995
diff --git a/variable.c b/variable.c
index c6b180736d..9721c1c2d4 100644
--- a/variable.c
+++ b/variable.c
@@ -10,16 +10,14 @@
#include "ruby.h"
#include "env.h"
-#include "ident.h"
#include "st.h"
st_table *rb_global_tbl;
st_table *rb_class_tbl;
#define global_tbl rb_global_tbl
#define class_tbl rb_class_tbl
-#define instance_tbl (RBASIC(Qself)->iv_tbl)
-VALUE rb_const_bound();
+VALUE rb_const_defined();
VALUE rb_const_get();
st_table *
@@ -39,11 +37,31 @@ char *
rb_class2path(class)
VALUE class;
{
- VALUE path = rb_ivar_get_1(class, rb_intern("__classpath__"));
+ VALUE path;
+
+ while (TYPE(class) == T_ICLASS) {
+ class = (VALUE)RCLASS(class)->super;
+ }
+ path = rb_ivar_get(class, rb_intern("__classpath__"));
if (TYPE(path) != T_STRING) Bug("class path does not set properly");
return RSTRING(path)->ptr;
}
+VALUE
+rb_class_path(class)
+ VALUE class;
+{
+ char *name = rb_class2path(class);
+
+ if (strchr(name, ':')) {
+ VALUE ary = str_split(str_new2(name), ":");
+ ary_pop(ary);
+ ary = ary_reverse(ary);
+ return ary_join(ary, str_new2("::"));
+ }
+ return str_new2(name);
+}
+
void
rb_set_class_path(class, under, name)
VALUE class, under;
@@ -58,7 +76,7 @@ rb_set_class_path(class, under, name)
s = rb_class2path(under);
str_cat(str, s, strlen(s));
}
- rb_ivar_set_1(class, rb_intern("__classpath__"), str);
+ rb_ivar_set(class, rb_intern("__classpath__"), str);
}
VALUE
@@ -88,7 +106,7 @@ rb_path2class(path)
}
*s = '\0';
id = rb_intern(name);
- if (!rb_const_bound(class, id))
+ if (!rb_const_defined(class, id))
Fail("%s not defined", name);
class = rb_const_get(class, id);
switch (TYPE(class)) {
@@ -106,7 +124,39 @@ rb_name_class(class, id)
VALUE class;
ID id;
{
- rb_ivar_set_1(class, rb_intern("__classname__"), INT2FIX(id));
+ rb_ivar_set(class, rb_intern("__classname__"), INT2FIX(id));
+}
+
+static st_table *autoload_tbl = 0;
+
+static void
+rb_autoload_id(id, filename)
+ ID id;
+ char *filename;
+{
+ if (!autoload_tbl) {
+ autoload_tbl = new_idhash();
+ }
+ st_insert(autoload_tbl, id, strdup(filename));
+}
+
+void
+rb_autoload(class, filename)
+ char *class, *filename;
+{
+ rb_autoload_id(rb_intern(class), filename);
+}
+
+VALUE
+f_autoload(obj, class, file)
+ VALUE obj, class;
+ struct RString *file;
+{
+ ID id = rb_to_id(class);
+
+ Check_Type(file, T_STRING);
+ rb_autoload_id(id, file->ptr);
+ return Qnil;
}
char *
@@ -130,7 +180,7 @@ rb_class2name(class)
class = (struct RClass*)class->super;
}
- name = rb_ivar_get_1(class, rb_intern("__classname__"));
+ name = rb_ivar_get(class, rb_intern("__classname__"));
if (name) {
name = FIX2INT(name);
return rb_id2name((ID)name);
@@ -138,45 +188,33 @@ rb_class2name(class)
Bug("class 0x%x not named", class);
}
+struct trace_var {
+ void (*func)();
+ void *data;
+ struct trace_var *next;
+};
+
struct global_entry {
- enum { GLOBAL_VAL, GLOBAL_VAR, GLOBAL_UNDEF } mode;
ID id;
- union {
- VALUE val;
- VALUE *var;
- } v;
- VALUE (*get_hook)();
- VALUE (*set_hook)();
void *data;
+ VALUE (*getter)();
+ void (*setter)();
+ void (*marker)();
+ int block_trace;
+ struct trace_var *trace;
};
-static
-mark_global_entry(key, entry)
- ID key;
- struct global_entry *entry;
-{
- switch (entry->mode) {
- case GLOBAL_VAL:
- gc_mark(entry->v.val); /* normal global value */
- break;
- case GLOBAL_VAR:
- if (entry->v.var)
- gc_mark(*entry->v.var); /* c variable pointer */
- break;
- default:
- break;
- }
- if (entry->data) {
- gc_mark_maybe(entry->data);
- }
- return ST_CONTINUE;
-}
+static VALUE undef_getter();
+static void undef_setter();
+static void undef_marker();
-void
-gc_mark_global_tbl()
-{
- st_foreach(global_tbl, mark_global_entry, 0);
-}
+static VALUE val_getter();
+static void val_setter();
+static void val_marker();
+
+static VALUE var_getter();
+static void var_setter();
+static void var_marker();
struct global_entry*
rb_global_entry(id)
@@ -188,22 +226,129 @@ rb_global_entry(id)
entry = ALLOC(struct global_entry);
st_insert(global_tbl, id, entry);
entry->id = id;
- entry->mode = GLOBAL_UNDEF;
- entry->v.var = Qnil;
- entry->get_hook = entry->set_hook = Qnil;
+ entry->data = 0;
+ entry->getter = undef_getter;
+ entry->setter = undef_setter;
+ entry->marker = undef_marker;
+
+ entry->block_trace = 0;
+ entry->trace = 0;
}
return entry;
}
-void
-rb_define_variable(name, var, get_hook, set_hook, data)
- char *name;
- VALUE *var;
- VALUE (*get_hook)();
- VALUE (*set_hook)();
+static VALUE
+undef_getter(id)
+ ID id;
+{
+ Warning("global var %s not initialized", rb_id2name(id));
+ return Qnil;
+}
+
+static void
+undef_setter(val, id, data, entry)
+ VALUE val;
+ ID id;
+ void *data;
+ struct global_entry *entry;
+{
+ entry->getter = val_getter;
+ entry->setter = val_setter;
+ entry->marker = val_marker;
+
+ entry->data = (void*)val;
+}
+
+static void
+undef_marker()
+{
+}
+
+static VALUE
+val_getter(id, val)
+ ID id;
+ VALUE val;
+{
+ return val;
+}
+
+static void
+val_setter(val, id, data, entry)
+ VALUE val;
+ ID id;
+ void *data;
+ struct global_entry *entry;
+{
+ entry->data = (void*)val;
+}
+
+static void
+val_marker(data)
void *data;
{
+ if (data) gc_mark_maybe(data);
+}
+
+static VALUE
+var_getter(id, var)
+ ID id;
+ VALUE *var;
+{
+ if (!var || !*var) return Qnil;
+ return *var;
+}
+
+static void
+var_setter(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ *var = val;
+}
+
+static void
+var_marker(var)
+ VALUE **var;
+{
+ if (var) gc_mark_maybe(*var);
+}
+
+static void
+readonly_setter(id, var, val)
+ ID id;
+ void *var;
+ VALUE val;
+{
+ Fail("Can't set variable %s", rb_id2name(id));
+}
+
+static int
+mark_global_entry(key, entry)
+ ID key;
struct global_entry *entry;
+{
+ struct trace_var *trace;
+
+ (*entry->marker)(entry->data);
+ trace = entry->trace;
+ while (trace) {
+ if (trace->data) gc_mark_maybe(trace->data);
+ trace = trace->next;
+ }
+ return ST_CONTINUE;
+}
+
+void
+gc_mark_global_tbl()
+{
+ st_foreach(global_tbl, mark_global_entry, 0);
+}
+
+static ID
+global_id(name)
+ char *name;
+{
ID id;
if (name[0] == '$') id = rb_intern(name);
@@ -213,80 +358,143 @@ rb_define_variable(name, var, get_hook, set_hook, data)
strcpy(buf+1, name);
id = rb_intern(buf);
}
+ return id;
+}
+
+void
+rb_define_hooked_variable(name, var, getter, setter)
+ char *name;
+ VALUE *var;
+ VALUE (*getter)();
+ void (*setter)();
+{
+ struct global_entry *entry;
+ ID id = global_id(name);
entry = rb_global_entry(id);
- entry->mode = GLOBAL_VAR;
- entry->v.var = var;
- entry->get_hook = get_hook;
- entry->set_hook = set_hook;
- entry->data = data;
+ entry->data = (void*)var;
+ entry->getter = getter?getter:var_getter;
+ entry->setter = setter?setter:var_setter;
+ entry->marker = var_marker;
}
void
-rb_define_varhook(name, get_hook, set_hook, data)
+rb_define_variable(name, var)
char *name;
- VALUE (*get_hook)();
- VALUE (*set_hook)();
- void *data;
+ VALUE *var;
{
- struct global_entry *entry;
+ rb_define_hooked_variable(name, var, 0, 0);
+}
+
+void
+rb_define_readonly_variable(name, var)
+ char *name;
+ VALUE *var;
+{
+ rb_define_hooked_variable(name, var, 0, readonly_setter);
+}
+
+void
+rb_define_virtual_variable(name, getter, setter)
+ char *name;
+ VALUE (*getter)();
+ void (*setter)();
+{
+ if (!getter) getter = val_getter;
+ if (!setter) setter = readonly_setter;
+ rb_define_hooked_variable(name, 0, getter, setter);
+}
+
+void rb_trace_eval();
+
+void
+rb_trace_eval(cmd, val)
+ VALUE cmd, val;
+{
+ rb_eval_cmd(cmd, ary_new3(1, val));
+}
+
+VALUE
+f_trace_var(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE var, cmd;
ID id;
+ struct global_entry *entry;
+ struct trace_var *trace;
- if (name[0] == '$') id = rb_intern(name);
- else {
- char *buf = ALLOCA_N(char, strlen(name)+2);
- buf[0] = '$';
- strcpy(buf+1, name);
- id = rb_intern(buf);
+ if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
+ cmd = f_lambda();
}
-
+ id = rb_to_id(var);
if (!st_lookup(global_tbl, id, &entry)) {
- entry = ALLOC(struct global_entry);
- entry->id = id;
- entry->mode = GLOBAL_VAL;
- st_insert(global_tbl, id, entry);
- }
- else if (entry->mode == GLOBAL_UNDEF) {
- entry->mode = GLOBAL_VAL;
- }
- entry->v.val = Qnil;
- entry->get_hook = get_hook;
- entry->set_hook = set_hook;
- if (data) {
- entry->data = data;
+ Fail("undefined global variable %s", rb_id2name(id));
}
+ trace = ALLOC(struct trace_var);
+ trace->next = entry->trace;
+ trace->func = rb_trace_eval;
+ trace->data = (void*)cmd;
+ entry->trace = trace;
+
+ return Qnil;
}
VALUE
-rb_readonly_hook(val, id)
- VALUE val;
- ID id;
+f_untrace_var(obj, var)
+ VALUE obj, var;
{
- Fail("Can't set variable %s", rb_id2name(id));
- /* not reached */
+ ID id;
+ struct global_entry *entry;
+ struct trace_var *trace;
+ VALUE ary;
+
+ id = rb_to_id(var);
+ if (!st_lookup(global_tbl, id, &entry)) {
+ Fail("undefined global variable %s", rb_id2name(id));
+ }
+ ary = ary_new();
+ trace = entry->trace;
+ while (trace) {
+ struct trace_var *next = trace->next;
+ ary_push(ary, trace->data);
+ free(trace);
+ trace = next;
+ }
+ entry->trace = 0;
+
+ return ary;
}
VALUE
rb_gvar_get(entry)
struct global_entry *entry;
{
- VALUE val;
-
- if (entry->get_hook)
- val = (*entry->get_hook)(entry->id, entry->data);
- switch (entry->mode) {
- case GLOBAL_VAL:
- return entry->v.val;
+ return (*entry->getter)(entry->id, entry->data, entry);
+}
- case GLOBAL_VAR:
- if (entry->v.var == Qnil) return val;
- return *entry->v.var;
+struct trace_data {
+ struct trace_var *trace;
+ VALUE val;
+};
+
+static void
+trace_ev(data)
+ struct trace_data *data;
+{
+ struct trace_var *trace = data->trace;
- default:
- break;
+ while (trace) {
+ (*trace->func)(trace->data, data->val);
+ trace = trace->next;
}
- Warning("global var %s not initialized", rb_id2name(entry->id));
- return Qnil;
+}
+
+static void
+trace_en(entry)
+ struct global_entry *entry;
+{
+ entry->block_trace = 0;
}
VALUE
@@ -294,19 +502,15 @@ rb_gvar_set(entry, val)
struct global_entry *entry;
VALUE val;
{
- if (entry->set_hook)
- (*entry->set_hook)(val, entry->id, entry->data);
+ struct trace_data trace;
- if (entry->mode == GLOBAL_VAR) {
- if (entry->v.var) {
- *entry->v.var = val;
- }
- }
- else {
- if (entry->mode == GLOBAL_UNDEF) {
- entry->mode = GLOBAL_VAL;
- }
- entry->v.val = val;
+ (*entry->setter)(val, entry->id, entry->data, entry);
+
+ if (!entry->block_trace) {
+ entry->block_trace = 1;
+ trace.trace = entry->trace;
+ trace.val = val;
+ rb_ensure(trace_ev, &trace, trace_en, entry);
}
return val;
}
@@ -317,19 +521,21 @@ rb_gvar_set2(name, val)
VALUE val;
{
struct global_entry *entry;
- ID id;
- id = rb_intern(name);
- if (!st_lookup(global_tbl, id, &entry)) {
- entry = rb_global_entry(id);
- }
- rb_gvar_set(entry, val);
+ entry = rb_global_entry(global_id(name));
+ return rb_gvar_set(entry, val);
+}
- return val;
+VALUE
+rb_gvar_defined(entry)
+ struct global_entry *entry;
+{
+ if (entry->getter == undef_getter) return FALSE;
+ return TRUE;
}
VALUE
-rb_ivar_get_1(obj, id)
+rb_ivar_get(obj, id)
struct RObject *obj;
ID id;
{
@@ -352,14 +558,7 @@ rb_ivar_get_1(obj, id)
}
VALUE
-rb_ivar_get(id)
- ID id;
-{
- return rb_ivar_get_1(Qself, id);
-}
-
-VALUE
-rb_ivar_set_1(obj, id, val)
+rb_ivar_set(obj, id, val)
struct RObject *obj;
ID id;
VALUE val;
@@ -368,7 +567,7 @@ rb_ivar_set_1(obj, id, val)
case T_OBJECT:
case T_CLASS:
case T_MODULE:
- if (obj->iv_tbl == Qnil) obj->iv_tbl = new_idhash();
+ if (!obj->iv_tbl) obj->iv_tbl = new_idhash();
st_insert(obj->iv_tbl, id, val);
break;
default:
@@ -380,11 +579,19 @@ rb_ivar_set_1(obj, id, val)
}
VALUE
-rb_ivar_set(id, val)
+rb_ivar_defined(obj, id)
+ struct RObject *obj;
ID id;
- VALUE val;
{
- return rb_ivar_set_1(Qself, id, val);
+ switch (TYPE(obj)) {
+ case T_OBJECT:
+ case T_CLASS:
+ case T_MODULE:
+ if (obj->iv_tbl && st_lookup(obj->iv_tbl, id, 0))
+ return TRUE;
+ break;
+ }
+ return FALSE;
}
VALUE
@@ -393,40 +600,58 @@ rb_const_get(class, id)
ID id;
{
VALUE value;
+ struct RClass *tmp;
- while (class) {
- if (class->iv_tbl && st_lookup(class->iv_tbl, id, &value)) {
+ tmp = class;
+ while (tmp) {
+ if (tmp->iv_tbl && st_lookup(tmp->iv_tbl, id, &value)) {
return value;
}
- if (BUILTIN_TYPE(class) == T_MODULE) {
- class = RCLASS(C_Object);
- }
- else {
- class = class->super;
- }
+ tmp = tmp->super;
+ }
+ if (BUILTIN_TYPE(class) == T_MODULE) {
+ return rb_const_get(cObject, id);
}
/* pre-defined class */
if (st_lookup(class_tbl, id, &value)) return value;
- /* here comes autoload code in the future. */
+ /* autoload */
+ if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
+ char *modname;
+ VALUE module;
- Fail("Uninitialized constant %s", rb_id2name(id));
+ st_delete(autoload_tbl, &id, &modname);
+ module = str_new2(modname);
+ free(modname);
+ f_require(Qnil, module);
+ return rb_const_get(class, id);
+ }
+
+ /* Uninitialized constant */
+ if (class && (VALUE)class != cObject)
+ Fail("Uninitialized constant %s::%s",
+ RSTRING(rb_class_path(class))->ptr,
+ rb_id2name(id));
+ else
+ Fail("Uninitialized constant %s",rb_id2name(id));
/* not reached */
}
VALUE
-rb_const_bound(class, id)
+rb_const_defined(class, id)
struct RClass *class;
ID id;
{
while (class) {
- if (class->iv_tbl && st_lookup(class->iv_tbl, id, Qnil)) {
+ if (class->iv_tbl && st_lookup(class->iv_tbl, id, 0)) {
return TRUE;
}
class = class->super;
}
- if (st_lookup(class_tbl, id, Qnil))
+ if (st_lookup(class_tbl, id, 0))
+ return TRUE;
+ if (autoload_tbl && st_lookup(autoload_tbl, id, 0))
return TRUE;
return FALSE;
}
@@ -437,10 +662,10 @@ rb_const_set(class, id, val)
ID id;
VALUE val;
{
- if (rb_const_bound(class, id))
- Fail("already initialized constnant");
+ if (rb_const_defined(class, id))
+ Fail("already initialized constnant %s", rb_id2name(id));
- if (class->iv_tbl == Qnil) class->iv_tbl = new_idhash();
+ if (!class->iv_tbl) class->iv_tbl = new_idhash();
st_insert(class->iv_tbl, id, val);
}
@@ -460,7 +685,7 @@ rb_iv_get(obj, name)
{
ID id = rb_intern(name);
- return rb_ivar_get_1(obj, id);
+ return rb_ivar_get(obj, id);
}
VALUE
@@ -471,5 +696,35 @@ rb_iv_set(obj, name, val)
{
ID id = rb_intern(name);
- return rb_ivar_set_1(obj, id, val);
+ return rb_ivar_set(obj, id, val);
+}
+
+VALUE
+backref_get()
+{
+ int cnt, max;
+
+ if (!the_scope->local_vars) return Qnil;
+ for (cnt=1, max=the_scope->local_tbl[0]+1; cnt<max ;cnt++) {
+ if (the_scope->local_tbl[cnt] == '~') {
+ cnt--;
+ if (the_scope->local_vars[cnt])
+ return the_scope->local_vars[cnt];
+ else
+ return 1;
+ }
+ }
+ return Qnil;
+}
+
+void
+backref_set(val)
+ VALUE val;
+{
+ int cnt, max;
+
+ for (cnt=1, max=the_scope->local_tbl[0]+1; cnt<max ;cnt++) {
+ if (the_scope->local_tbl[cnt] == '~') break;
+ }
+ the_scope->local_vars[cnt-1] = val;
}
diff --git a/version.c b/version.c
index 57e32cd6ca..dba5f6c8b5 100644
--- a/version.c
+++ b/version.c
@@ -15,18 +15,21 @@
#include "version.h"
#include <stdio.h>
-extern VALUE C_Kernel;
+extern VALUE cKernel;
+void
Init_version()
{
- rb_define_const(C_Kernel, "VERSION", str_new2(RUBY_VERSION));
+ rb_define_const(cKernel, "VERSION", str_new2(RUBY_VERSION));
}
+void
show_version()
{
fprintf(stderr, "ruby - version %s (%s)\n", RUBY_VERSION, VERSION_DATE);
}
+void
show_copyright()
{
fprintf(stderr, "ruby - Copyright (C) 1993-1995 Yukihiro Matsumoto\n");
diff --git a/version.h b/version.h
index 9a1dc5c8d4..f019bbdae3 100644
--- a/version.h
+++ b/version.h
@@ -1,2 +1,2 @@
-#define RUBY_VERSION "0.76"
-#define VERSION_DATE "95/05/19"
+#define RUBY_VERSION "0.95"
+#define VERSION_DATE "95/12/21"