summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1996-12-24 15:20:58 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 22:09:32 +0900
commit554b989ba1623b9f6a0b76f00824c83a23fbcbc1 (patch)
tree71f06227fe259bebaa5ca4bf05cc398184bced68
parentfca49a8a69a0f6bb4feae74c6cd0e93d7fac8b36 (diff)
version 0.99.4-961224v0_99_4_961224
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.99.4-961224.tar.gz Tue Dec 24 15:20:58 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.4-961224 * configure.in: charがunsignedかどうかもチェック * regex.c (SIGN_EXTEND_CHAR): __CHAR_UNSIGNED__にも対応 * pack.c (pack_unpack): 明示的にsigned charを指定. Mon Dec 23 14:41:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby.c (load_file): 標準入力からのスクリプトで一時ファイルを使わ ないように * object.c (f_integer): `0x', `0'などでbaseを解釈するように. Fri Dec 20 01:44:39 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * Makefile.in (flock.o): flockに対応 Thu Dec 19 20:13:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.4-961219 Wed Dec 18 00:06:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * glob.c (glob_filename): strrchrがマクロの場合に対応 * configure.in: <sys/select.h>をチェック * ext/kconv/kconv.c: 1.62ベースに * ext/kconv/kconv.c: Kconvモジュール * string.c (str_substr): lenが元の文字列より長い時に対応 * parse.y (iterator): 「$bar do .. end」などは許さないように * parse.y (iterator): FID(foo!,foo?)をdo形式のイテレータにできる. * missing/flock.c (flock): lockf()を使って代替 * file.c (file_flock): flockを実装 Tue Dec 17 12:13:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.4-961217 Fri Dec 13 02:05:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * configure.in: RUBYLIBのカレントを後回し(@mix/awk offline) * dln.c: AIXに対応した?(@mix/awk offline) * eval.c (thread_schedule): critical sectionでも明示的なコンテキス トスイッチは起きないとまずい * re.c (reg_search): matchに失敗した時に$~をnilに. * re.c (reg_search): 毎回matchを生成するように Thu Dec 12 17:03:30 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * numeric.c (flo_to_s): 2.0.to_s -> 2.0に * eval.c (thread_save_context): $_, $~をthread毎に保存 * eval.c (thread_kill): main threadではexit(0) * string.c (str_split_method): 間違った結果を返していた Thu Dec 12 15:32:48 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * dir.c: CYGWIN32対応 * ext/socket/socket.c: CYGWIN32対応 * io.c: CYGWIN32対応 Thu Dec 12 14:43:51 1996 Jun Kuroda <j_kuro@pluto.ai.kutech.ac.jp> * lib/tk.rb: wish4.2も探索候補に含める * config.guess: JCC対応 Thu Dec 12 00:41:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.4-961212 * parse.y (parse_string): """..."""はやはり無くすことにした * parse.y (parse_regx): %r|...|でterminatorを \ でエスケープできる ように * signal.c (posix_signal): sigactionを使うsignal * configure.in: posix signal/bsd signalの検出 Wed Dec 11 17:47:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_schedule): critical sectionではコンテキストスイッ チが起きないように * lib/thread.rb: SharedMutexクラス * lib/jcode.rb: String#scanを使うように Tue Dec 10 12:21:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961210 * string.c (str_split_method): 正規表現に()を含む時にバグ * lib/jcode.rb: ちょっとましになった * string.c (tr_setup_table): 置換文字が短すぎる(2文字)のときのバグ Mon Dec 9 11:38:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_scan): 文字列のマッチを行う.イテレータとしても動 作する * regex.c (re_copy_registers): allocatedが初期化されていなかった * re.c (match_to_s): $~の文字列化 * re.c (match_to_a): $~を配列化できるように * re.c (match_getter): レジスタが初期化されていなかった Thu Dec 5 11:06:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_split_method): マッチしなかった括弧は空文字列を pushするべきではない * string.c (str_succ): アルファベットを含まない文字に対応 Wed Dec 4 10:48:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961204 * io.c (io_binmode): DJGPPでのbinmode対応 * sprintf.c (f_sprintf): intの範囲の数値は直接sprintfで変換する * sprintf.c (f_sprintf): "%02s"に頼らない * re.c (reg_search): indexでSEGV Tue Dec 3 10:09:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961203 * ext/extmk.rb.in (install): INSTALL_DATAからINSTALLに変更 * dln.c: hpux対応 * string.c (str_aset_method): 負の値を含む範囲でも例外を起こさない * array.c (ary_replace): 負の値を含む範囲でも例外を起こさない * array.c (beg_len): beg==endの時,長さ0に Mon Dec 2 14:07:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * configure.in: HP shl対応 * string.c (str_upto): beg > endの時無限ループに落ちるのを止めた * range.c (range_each): String#uptoが再定義された場合に対応 * string.c (str_split_method): "ABC".split(/(B)/)が誤動作 Sat Nov 30 01:43:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_eval): undefでSEGV Fri Nov 29 12:17:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-parse-region): %Q#..#などに対応.しか し,区切り文字が演算子で行末にある場合には対応できなかった. * re.c (reg_raise): 例外でもスラッシュをエスケープ * re.c (reg_inspect): スラッシュをエスケープ * parse.y (parse_string): `%[QqXxRr](.)..\1'なる文字列形式(テスト 採用) * parse.y (parse_qstring): '''...'''の形式 * ext/dbm/dbm.c (Init_dbm): 述語key?,value?の追加 * ext/dbm/dbm.c (Init_dbm): includes->include? * hash.c (Init_Hash): 述語key?,value?,include?の追加 * eval.c (rb_eval): else節が実行されない(うーん) * string.c (str_sub_iter_s): イテレータブロック内でマッチが行われ ると位置がずれる(時に無限ループに落ちる) * string.c (str_resize): lenが0の時sizeの調整が行われなかった Thu Nov 28 00:59:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961128 * parse.y (parse_string): 3-quote styleの文字列(例:"""abc"d"e""") * configure.in (EXTSTATIC): extを静的にリンクする時にはrubyはdllを 使うように * io.c (Init_IO): getsの引数が間違っていた * string.c (str_each_line): RSを明示的に指定できるように Wed Nov 27 12:37:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961127 * eval.c (rb_eval): iver defined? でselfを指定するのを忘れた * io.c: gets等でRSを明示的に指定できるように * ext/extmk.rb.in (install): static linkに失敗 Tue Nov 26 10:33:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961126 * string.c (str_sub_s): 置換後の文字列長さが間違っていた Mon Nov 25 09:11:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * numeric.c (fix_rshift): 32以上の右シフトで0を返すように(Cの rshiftは(x>>(y%32))を返していた). * string.c (str_gsub): 置換が行われない場合があった * string.c (str_resize): 本当に必要な時だけrealloc Thu Nov 21 04:13:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * configure.in (EXTSTATIC): --with-static-linked-extで全てのモジュー ルを静的リンクするように * pack.c (pack_unpack): 行末の改行がない時にもチェックサムをスキッ プするように Wed Nov 20 96 21:42:51 1996 Yasuo OHBA <jammy@shljapan.co.jp> * configure.in: freebsd対応 Wed Nov 20 10:24:24 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/extmk.rb.in (install): 通常リンク用のLDFLAGSとダイナミックリ ンク用のDLDFALGSを分離 * ext/extmk.rb.in (install): コンパイルの成功したものを静的リンク のリストに追加する * eval.c (f_missing): オブジェクトの文字列表現が長すぎる時バッファ を書き潰していた * process.c (proc_exec_v): forkした後例外を発生させてはいけない Tue Nov 19 13:28:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961119 * eval.c (mod_method_defined): Module#method_defined? の追加 * parse.y (call_args): 引数が唯一のコマンドコールである時のバグ(戻 り値が展開されてしまう) Mon Nov 18 13:28:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_sub): 失敗した時にnilを返していた * string.c (str_split_method): 検索開始位置が移動してなかった * ext/socket/socket.c (sock_s_getservbyaname): まだ間違っていた * version 0.99.3-961118 * string.c (str_sub_s): 元の文字列を置換するのを止めた * pack.c (encodes): 領域外をアクセスしていた Fri Nov 15 17:10:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * bignum.c (big_divmod): Bignumが引数の場合の対応忘れ * sample/ruby-mode.el (ruby-expr-beg): word?形式への対応が不完全 Wed Nov 13 15:42:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_tr_s_bang): tr_sでtrが行われていなかった * eval.c (rb_eval): autoloadクラスのチェック * string.c (f_sub): subがsub!と同じ動作になっていた * eval.c (thread_sleep): stopとsleepの分離 Mon Nov 11 13:53:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961111 * numeric.c (fix_step): to, stepが整数以外の場合に対応 * eval.c (rb_call): dynamic varがdynamic scopingになっていた(これ はまずい) * string.c (str_chop_bang): 長さ0の文字列のchopで,領域外のアクセ スが発生していた. * parse.y (yyerror): 割り当てた領域外をアクセスしていた Fri Nov 8 11:54:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_yield): scopeをheapにコピー Thu Nov 7 09:56:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * numeric.c (num_coerce): とりあえず両辺をFloatに変換することに Wed Nov 6 10:45:13 1996 Yasuo OHBA <jammy@shljapan.co.jp> * lib/parsearg.rb: 第2引数を変更. Tue Nov 5 14:21:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961105 Sat Nov 2 01:11:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * bignum.c (big_pow): typo (dy -> dx) * bignum.c (big_divmod): 知らない型はfloatに変換してみる * numeric.c (fix_lshift): 境界条件のバグ(負になっていた) * bignum.c (big_pow): 無駄なfloatへの変換をなくした * math.c (math_atan2): typo(x -> y) Fri Nov 1 15:30:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/socket/socket.c (sock_gethostname): gethostnameがない時には unameを使ってホスト名を得る * ext/etc/etc.c (etc_getlogin): getloginがNULLを返しても環境変数を 調べるように * object.c (krn_clone): オブジェクトのフラグもコピー * hash.c (rb_cmp): ハッシュの比較を`=='でなく`eql?'に変更 * math.c (Need_Float): Float()を使って変換する * compar.c (cmp_gt): 以前の右辺を返す仕様の名残が残っていた Thu Oct 31 12:55:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961031 * numeric.c (Init_Numeric): typo * eval.c (error_print): 長すぎるtrace backを途中省略する * regex.c (re_compile_pattern): 全角のrangeに対応 Wed Oct 30 03:03:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.3-961030 * io.c (f_ungetc): 関数を追加 * eval.c (dyna_var_asgn): return値忘れ Tue Oct 29 10:05:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (f_split): 関数splitを追加 * eval.c (rb_call): ネストした外側のクラス/モジュールの定数を参照 できるように Mon Oct 28 09:51:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_sub): offsetが文字の末尾にある時のチェック * regex.c (re_match): 割り当てるレジスタの数が1多かった * io.c (io_gets): $/ = ""の動作をperlに合わせる(awkとはちょっと違 うらしい) * io.c (io_gets): $/ = nilの時少し高速化 * string.c (str_split_method): 括弧がnullにマッチした時にも無視し ないように * string.c (str_split_method): 括弧にマッチした分はlimitの数に含め ないように. * numeric.c (num_coerce_bin): coerceの定義を変更,2要素の配列 [x,y]を返すように * sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"の対応を改 善した. Sat Oct 26 01:43:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/marshal/marshal.c (w_object): ビルトインクラスのサブクラスを 正しく復旧できるように * ext/marshal/marshal.c (w_object): ユーザ定義dumpの優先 * numeric.c (flo_coerce): Float()を使って定義 * numeric.c (Init_Numeric): Numericのnewのundefはまずい * ext/marshal/marshal.c (w_symbol): シンボルの内容(文字列)は一度し かファイルに書き出さない. * sample/ruby-mode.el (ruby-parse-region): if/while修飾子に対応し なくなっていた * bignum.c (Init_Bignum): Bignum.newを除く * eval.c (rb_eval): 引数評価後にファイル名と行番号を再設定 * numeric.c (flo_div): typo * sample/ruby-mode.el (ruby-parse-region): def /, def `に対応 Fri Oct 25 09:26:29 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"に対応 * array.c (ary_aset): indexがfixnumの場合ちょっと高速化 * eval.c (thread_fd_writable): 書き込み前のselectチェック * array.c (ary_assoc): 無限ループに落ちた * eval.c (thread_wait_for): selectがエラー終了した時,linux以外で の動作が正しくなかった. Thu Oct 24 08:26:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (backtrace): `$@'を文字列から配列に変更した. * eval.c (eval): eval中の例外発生位置を保存する * bignum.c (bigsub): オペランドの大小比較の失敗 * re.c (reg_search): 直接参照がない時にも`$~'がセットされるように Wed Oct 23 10:40:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-961023 * ext/marshal/marshal.c (r_bytes): mallocをやめ,allocaを使う * sample/ruby-mode.el (ruby-calculate-indent): 括弧の対応を変更. ()内ではインデントをレベルを合わせるように Tue Oct 22 12:59:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * hash.c (hash_s_new): sizeを指定できるように * ext/marshal/marshal.c (w_object): dumpする深さ制限を指定できるよ うに * array.c (ary_s_new): sizeを指定した時の初期化忘れ * object.c (f_float): big2dblの宣言忘れ. * bignum.c (bigsub): 大きさの近いBignum同士の演算で結果が負になる 場合に間違いがあった. * array.c (ary_aset): 置換先と置換元が同じ長さの時内容を shift(memmove)しないように. * ext/marshal/marshal.c (marshal_dump): ファイルフォーマットにバー ジョンを埋め込むように * ext/marshal/marshal.c (tmpnam): linux-aout-dln用に定義 Mon Oct 21 08:40:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/socket/socket.c (sock_s_gethostbyname): hostent構造体の情報 を返す (sock_s_gethostbyaddr): IPアドレスからhostent構造体を得る (sock_s_getservbyaname): getservbyname(3) Fri Oct 18 10:37:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-indent-to): 移動先カラムが負になるバグ * eval.c (compile): evalで元ソースの行番号でエラーを表示する Thu Oct 17 09:52:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (eval): evalで文法エラーがあった時にSEGV * lib/safe.rb: Restricted.evalの中だけ制限を加える. * eval.c (error_print): バックトレースの出力.callerで例外発生位置 を調整した時に問題が出る(そんなことをしなければ良いのだが…) * eval.c (make_backtrace): バックトレースの生成 Wed Oct 16 12:56:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby-man-0.99.2-jp/index.html: 日本語版ドキュメントの完成(長かった…) * re.c (reg_regcomp): $=がnilの時の処理 * string.c (f_chop): $_に対するchop Tue Oct 15 11:04:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-961015 Mon Oct 14 18:22:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_schedule): BOW対応.selectが-1を返した時にバグ(実 はdo .. whileがcontinueで先頭にジャンプすると思い込んでいた.条 件の直前だったのね ^^);;;;; * sample/ruby-mode.el (ruby-mode-syntax-table): ?のsyntaxが"/"では まずいらしい * hash.c (rb_hash): name conflict Fri Oct 11 00:23:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-961011 * ext/marshal/marshal.c (w_object): 結局動いていなかった循環オブジェ クト対応を外した. * hash.c (rb_hash): Fixnumと文字列の高速化 * ext/marshal/marshal.c (w_object): 無駄なデータの削除(フォーマッ トの非互換性) * io.c (io_readline): 戻り値の不備 * ext/marshal/marshal.c (marshal_dumps): MSDOS対応 * ruby.c (load_file): MSDOS対応 Wed Oct 9 17:46:27 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/extmk.rb.in (install): 無駄なコピーを避ける * string.c (str_sub_method): マッチがなかった時のString#subの値が 違っていた. * eval.c (obj_extend): extendした時にobject_extendedを呼ぶように Tue Oct 8 00:55:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_alloc): 割当の平均化 * eval.c (thread_schedule): joinのバグを修正 * eval.c (thread_wait_for): selectへの割込みなどに対応 * eval.c (thread_select): linuxのselectの挙動に対応(timeoutが変化 する) Mon Oct 7 09:47:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-961007 * eval.c (PUSH_BLOCK): the_classの保存を忘れていた. * ext/dbm/dbm.c (fdbm_store): sizeの保存する場所が間違っていた * ext/socket/socket.c (s_accept): thread対応していなかった Sat Oct 5 01:32:27 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * io.c (io_readchar): EOFで例外を発生させる Fri Oct 4 11:59:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/marshal/marshal.c (w_object): HashとObjectの復旧に必要なハッ シュテーブルが渡されていなかった. * variable.c (rb_path2class): ユーザ定義クラスの復旧に失敗していた * variable.c (rb_path2class): クラスが存在しない時のエラーをFatal からNameErrorへ. * range.c (range_s_new): first,lastが両方Numericの時エラーになって いた. * range.c: start->first, end->last Wed Oct 2 02:02:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c: DJGPPでchmod,chownを使えるように(ってDOSにchownがあるのか?) * class.c (rb_singleton_class): ビルトインクラスもextendしたり特異 メソッドを追加したりできるように * variable.c (rb_set_class_path): ユーザ定義のトップレベルクラスに pathを設定しない * eval.c (eval): 例外がRuntimeErrorに化けていた * eval.c (eval): eval中の例外の表現の改善 * eval.c (eval): eval_with_bindingとの一本化 * eval.c (rb_eval): クラス/モジュール定義の中から定義中のクラス/モ ジュールが参照できるように Tue Oct 1 01:40:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-961001 * parse.y: cur_crefが2度宣言されていた * signal.c (trap): SIGSEGV,SIGBUSのない機種に対応 * io.c (Init_IO): 引数タイプの指定間違い Mon Sep 30 15:28:00 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-960930 * config.guess,config.sub: $host_osが正しく設定されない * eval.c (rb_eval): yieldで正しくないselfが設定されていた * eval.c (ruby_run): toplevelの例外処理のバグ Mon Sep 30 09:13:26 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * djgpp対応 Sat Sep 28 02:45:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-960928 * sample/ruby-mode.el (ruby-beginning-of-block): ブロックの先頭に 移動(正しくインデントしていないと動作しない) (ruby-end-of-block): 同上 * eval.c (class_s_new): Class#newがイテレータとして呼ばれた時は initializeもイテレータとして呼ばれるように * signal.c (sigsegv): SEGVでbacktraceを表示するように Fri Sep 27 09:51:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-960927 * eval.c (error_print): 引数のないraiseでメッセージが正しく表示さ れるように. * eval.c (rb_longjmp): mesgがnilの時RuntimeErrorを生成する. * eval.c (f_raise): 引数がない時に対応 * eval.c (thread_mark): stack上にないデータのアドレス変換を行って いた. * eval.c (Init_Thread): 割込みの間隔が1秒と長すぎた. Thu Sep 26 16:02:45 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_schedule): 一度ペンディングになるとフラグがクリア されていなかった. * process.c (rb_proc_exec): system/execの引数が空文字列であった場 合,例外を発生すべきだった. * config.sub/config.guess: 新しいものに置き換え Thu Sep 26 15:41:35 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * io.c (next_argv): -i.bakをBOWとDOSに対応. Thu Sep 26 01:31:43 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * io.c (io_sysread): EOFで例外 * io.c (f_readline): EOFで例外を発生するように.getsは互換性のため nilを返すままにする * eval.c (proc_call): lambdaからのreturnでIN_BLOCKフラグが立ったま まだった * eval.c (PUSH_BLOCK2): threadに対応するためBlockを一度stackにコピー Wed Sep 25 11:54:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (method_call): Const::method()形式を使えるようにしてみた. 引数括弧は省略できない. * sample/test.rb: Process.killの存在を確かめてからテストを行う * eval.c (eval_with_binding): 第2引数としてbinding(またはlambda)を 与えるとその環境でevalを実行するようにした * eval.c (f_binding): 現在のbindingを返す関数 * eval.c: block構造体にthe_classを保存するメンバを追加 * process.c (Init_process): kill,wait,waitpidをProcessに移動 Tue Sep 24 02:44:43 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el: いろいろ問題が多いので以前の高速化は破棄. 別のアプローチを使った. * lib/tk.rb (Tk.pack): 複数のウィンドウを受け付けるpack Sat Sep 21 11:08:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (exprs): 空文も受け付けるように文法を変更.今までは改行 の連続だけが許されていた. Fri Sep 20 11:39:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * Failの大半を名前つき例外に変更. * re.c (Init_Regexp): 名前つき例外を導入. * eval.c (f_missing): Objectはinspectしない. * object.c (inspect_i): Object#inspectでloopに対応. * regex.c (re_search): /^$/が""にマッチしなかった. Thu Sep 19 19:25:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * regex.c (re_search): /^$/が非空行にマッチしていた. Tue Sep 17 10:28:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-960917 Mon Sep 16 10:47:56 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-calculate-indent): 演算子継続の場合の 文字列の判定のバグ * sample/ruby-mode.el (ruby-calculate-indent): elseなどの次の行の インデント計算を正しく. Sat Sep 14 08:37:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.2-960914 Fri Sep 13 08:06:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/socket/socket.c (tcpaddr): port番号にntohsをつけ忘れ * dln.c (link_undef): テーブルの種類が間違っていた. * bignum.c (bigadd): 引き算が発生する時に計算違いが起きていた. * parse.y (iter_do_block): do..endでもdynamic variableを. * bignum.c (big_pow): より正確な計算を(整数同士ではfloatに変換しな い). Thu Sep 12 13:11:55 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * variable.c (rb_set_class_path): Stringクラスが初期化される前に Stringを作っていた.組込みクラスにはpathはいらない * parse.y (yylex): 0.1が0になっていた * parse.y (yylex): 行番号の不整合 * gc.c (oblist_live_obj): 今「生きている」全部のオブジェクトを返す イテレータ.そのクラス(またはサブクラス)の全部のインスタンスを返 すeach_object_ofも定義した. * class.c (rb_define_class_id): 無駄なクラスを割り当てていた.結果 として未初期化のクラスオブジェクトが存在していた. Wed Sep 11 00:56:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (yylex): octalの定数の検出をより正確に(090はエラーとか). * bignum.c (big_minus): yがxより大きい場合にエラー. * parse.y (yylex): エラー行番号の表示をより正確に * sample/ruby-mode.el (ruby-expr-beg): 変数名が1文字の時誤動作して いた. * sample/ruby-mode.el (ruby-calculate-indent): ?/でループに落ちい たバグを修正. * enum.c (enum_min,enum_max): sortのようにイテレータとしても動作す るように. * enum.c (enum_find_all): typo Tue Sep 10 12:07:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * node.h (nd_line): NODEのlineをflagsに押し込めてオブジェクトサイ ズを小さくした.制限:32bit intのマシンの場合,ファイルの行数が 32767を越えると正常に表示されない. * st.c: hashとcompareの関数メンバを構造体にパック,クラス的な使い 方を行う.1 tableあたり4 byteの節約. Mon Sep 9 16:35:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c (file_truncate): 提供されない時には特別な例外を発生するよ うに. * eval.c (Init_Proc): 不適切な位置のlocal-jumpを例外に. Sat Sep 7 17:06:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (proc_call): まだスコープがスタック上にある時には局所脱出 を有効にする.これで,procを生成してcallすることは,スコープを脱 出しない限り,yieldと同じ意味を持つことになる. Fri Sep 6 13:30:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-indent-to): インデントが変わらない時に はバッファを変更しない. (ruby-calculate-indent): まず文字列の内部か判断してから,前の行 からパーズを行う.defunが大きくなった時の高速化. (ruby-in-string-p): 文字列の内部かどうかを判断する関数(以前の parseから分離) (ruby-parse-region): 文字列に対する処理をはずす. (ruby-beginning-of-block): ブロックの先頭に (ruby-end-of-block): ブロックの末尾に(遅い…) Thu Sep 5 14:23:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c (file_s_split): [dirname,basename]にsplitする. * eval.c (rb_eval): evalの中でも定数の値が正しくなるように.これで 定数に関しては静的なスコープが保証されるようになった. * st.c (rehash): ハッシュ拡大の系数を2から1.79に.割算がより良い値 を返すように. Thu Sep 5 00:32:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (class_superclass) クラスのスーパークラスを返すメソッド. Wed Sep 4 16:54:56 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * random.c (f_rand): Bignumやlongの範囲を越えるFloatに対する乱数も 発生できるように. * struct.c (struct_alloc): Fatalではなく例外を発生させるように(通 常の使用で発生しうる). * struct.c (struct_s_members): Structの特異メソッドではなく,生成 されたStructクラスの特異メソッドにした. * st.c (st_init_table): ruby専用にパラメタを固定にした(サイ ズが減った) Mon Sep 2 11:37:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * array.c (ary_shift): capaがあまりにも大きい時には領域をREALLOC (ary_pop): 同上 * string.c (str_inspect): multibyte character 対応にミス. (str_inspect): unsigned charにしないと符号展開されてしまう * parse.y (primary): `::'をprimaryに移動 Foo::Bar.Bazがエラーにな らないように. * parse.y (primary): オペレータ形式の特異メソッドが定義できない * random.c (f_rand): maxが0の時に対応 * io.c (io_printf): 関数を定義していたがインタプリタに登録していな かった. * file.c (file_s_basename): 第2引数が無い時にエラー. Thu Aug 29 10:49:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (expr): イテレータの新形式に「method do .. end」形式を採 用した.もちろん昔の形式も有効. * sample/ruby-mode.el (ruby-calculate-indent): endの数の方が多い場 合にもエラーを起こさないように. Wed Aug 28 09:41:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * numeric.c (upto,downto,step,times): 対象がfixnumの範囲を越えても 動作するように. Mon Aug 26 10:04:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * missing/setenv.c (envix): typo(missing `== 0' for memcmp) * dir.c (dir_foreach): foreach(dir open -> read loop -> closeまで) * io.c (io_foreach): foreach(file open -> read loop -> closeまで) * Fatalのうち捕捉可能ないくつかを例外に. Sat Aug 24 23:56:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * bignum.c (bigdivmod): FIX2INT -> INT2FIX 大間違い Fri Aug 23 18:13:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * regex.c (re_free_registers): allocateしていない時には当然 free してはいけない. Thu Aug 22 01:20:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_create): 外側から強制終了させられたthreadは cleanupする必要が無い. Wed Aug 21 09:57:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_create): threadを終了させた大域脱出の情報を main_threadに渡すように. * parse.y (call_args): 最終引数に括弧を省略したメソッド呼出しを置 けるように(例: print foo bar, baz == print(foo(bar,baz))) Tue Aug 20 13:37:16 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (masign): 多重代入とrest引数の動作を合わせて空の配列を代 入するように. * parse.y (arg): defined?の強度をもうちょっと強く * eval.c (error_print): -wで例外名も表示するように * eval.c (rb_eval): 新構文に対応 (handle_rescue): 捕捉する例外を kind_of? で同定 * parse.y (primary): rescueの構文を変更(同定引数の追加,複数rescue) * Fail()のかなりを適当な例外を使うように * eval.c (thread_interrupt): Interrupt(今はnon-local jump)は main-threadに送られるように. * eval.c (rb_longjmp): $! の内容を文字列から例外クラスに変更 (rb_raise): rb_fail から名称変更 (rb_interrupt): 例外化 (rb_exit): 例外化 * error.c (Init_Exception): 例外クラスの新設(文字列のサブクラス) Mon Aug 19 19:40:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * signal.c (trap): 古いハンドラを返すように. Wed Aug 14 00:07:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_trap_eval): ハンドラのためにthreadをforkすることを止 めた. * eval.c (thread_mark): thread毎の $!, $@ をマークし忘れ * ext/dbm/dbm.c (fdbm_delete): イテレータとして呼ばれた場合,要素 が無ければブロックを評価する. * hash.c (hash_delete): イテレータとして呼ばれた場合,要素が無けれ ばブロックを評価する. * array.c (ary_delete): イテレータとして呼ばれた場合,要素が無けれ ばブロックを評価する. * eval.c (rb_interrupt): SIGINTのデフォルトをexitから特別な大域脱 出に.やはり割り込まれた位置の表示が無いのは寂しいので. Tue Aug 13 01:34:00 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_exit): sub-thread内でのexitもstatusを保存するように (thread_create): 自thread内のexitに対応 * signal.c (sighandle): SIGINTのデフォルトハンドラはexitするように (以前は例外を発生していた). * 例外の一部をFatalに. * string.c (str_aset): 文字列の置換の対象が部分文字列でなかった時, 例外を発生させないように * eval.c (proc_call): Procの中からbreak/nextは通し,他のものは通さ ないように Mon Aug 12 14:15:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * object.c (krn_type): 文字列を返す * eval.c (thread_create): sub-thread内でのexitに対応 * numeric.c (fix_type): 文字列を返す * io.c (f_p): デバッグ用データ表示メソッド * eval.c (f_missing): nil/TRUE/FALSEを特別扱い * string.c (str_inspect): 長い文字列を短縮表示.inspectの働きを human readable stringの生成に統一(re-generatable string は正式に 無くなった). Sat Aug 10 16:54:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * object.c (Init_Object): kernel/nil/false/trueのクラス名を変更(小 文字に),rubyスクリプトからアクセスできないように. * eval.c (rb_eval): CONSTANTのアクセス先を単純化.crefを使わない. * eval.c (f_eval): 特異メソッド内でも定数の値が正しくなるように Fri Aug 9 12:23:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * array.c (ary_concat): append -> concat Stringに合わせた * parse.y (yylex): `$;'が使えなかった. * array.c (ary_push_method): 複数引数を受け付けるように. (ary_unshift): 複数引数を受け付けるように. * io.c (io_popen): IO.popenでcommand pipeが開けるように. * object.c (Init_Object): KernelとNilをruby scriptからアクセスでき ないように. Thu Aug 8 01:21:47 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * object.c (f_integer): 整数への変換関数 (f_float): 実数への変換関数 (f_string): 文字列への変換関数 (f_array): 配列への変換関数 * bignum.c (big_to_i): FIXNUMの範囲でない時はBignumのまま返すよう に変更. Wed Aug 7 09:28:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99.1-960807 * parse.y (mlhs): 「*foo = 1,2,3」タイプの多重代入も可能に. * object.c (Init_Object): クラスTrue/Falseをruby scriptからアクセ スできないように. * object.c (nil_inspect): inspect表現は"nil"に * io.c (io_print): nilのprintをnilに. * object.c (nil_to_s): nilの文字列表現を""に. Tue Aug 6 01:12:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * dir.c (dir_s_open): file descripterが足りない時にはgcしてからも う一度openしてみる. * io.c (rb_fopen): すべてのfopen()についてfile descripterが足りな い時にはgcしてからもう一度openしてみる. * ext/socket/socket.c (Init_socket): 定数の追加. * sample/ruby-mode.el (ruby-indent-to): インデント後のカーソル位置 の調整を正しく. * gc.c (gc): 割込みチェックを行わない(Cコードの中で安心して malloc()が使えなくなるので). * st.c (call_hash_func): signalとthreadによる割込みに対応. * sig.h (DEFER_INTS): 割込み禁止区間の指定 * eval.c (f_require): threadによるrequireの競合に対応(最初の requireが終了するまで他のthreadは待つ). * bignum.c (str2inum): 0x80000000の値が負になっていた * sprintf.c (f_sprintf): 文字列末尾,行末の単独の`%'に対応 * bignum.c (big_cmp): 比較の結果が逆になる時があった. Mon Aug 5 10:58:13 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * process.c (proc_exec_v): 例外のメッセージを分かりやすく. * ext/dbm/dbm.c (fdbm_store): nilを格納すると要素の削除になる * ext/dbm/dbm.c: サイズをキャッシュ. Sat Aug 3 01:52:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_fail): `fail'が引数無しで呼ばれた時だけ以前の`$@'を保 存するように. * eval.c (f_fail): frameの調整 Fri Aug 2 11:26:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/socket/socket.c (bsock_setopt): valとしてTRUE/FALSE/Fixnumも 受け付けるように. * ext/socket/socket.c (Init_socket): SO_REUSEADDR等の定数の追加 * ext/md5/md5init.c: md5モジュール(初の複数ファイルからなるモジュー ルでもある) * ruby.h (Make_Data_Struct): Data: objectのinstance変数に格納 -> Data型のObjectに(Dir,Time,Proc,Thread,DBM) Thu Aug 1 11:38:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/dbm/dbm.c (fdbm_store): valueが文字で無い時に対応 Wed Jul 31 10:53:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/socket/socket.c (open_inet): htonsが必要であった (tcpaddr): ntohlで変換した * process.c (rb_proc_exec): execvp -> execv Tue Jul 30 17:48:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c: `$?'をthread localに * Makefile.in (install): install時にstripを行う * configure.in: install時のstripの検出 * configure.in: NEXTSTEP対応 * version 0.99.1-960730 Tue Jul 30 16:40:35 1996 SHIROYAMA Takayuki <psi@fortune.nest.or.jp> * dln.c (dln_load): NeXT dln(mach-o)対応.configureは未対応 Tue Jul 30 09:46:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * process.c (f_system): 複数引数もとれるように * process.c (f_exec): 複数引数もとれるように * array.c (ary_append): 配列(またはEnum)の要素を破壊的に追加 * array.c (ary_plus): Enumはその要素を追加 * file.c (file_s_open): File.openを追加 * struct.c (struct_new): FIX2INTを忘れていた * file.c (Init_File): exists? -> exist? * object.c (obj_is_kind_of): is_kind_of? -> kind_of?, is_a? * object.c (obj_is_instance_of): is_instance_of? -> instance_of? Mon Jul 29 16:40:02 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (parse_regx): 式展開を行った場合,casefoldの設定ができて いなかった. * object.c (true_type): TRUE/FALSEにtypeを実装. * parse.y (read_escape): 3文字以内のoctalに対応(\0とか) Fri Jul 26 00:31:45 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * array.c (ary_reverse_bang): in-placeで配列を反転させる (ary_sort_bang): in-placeでsortする (ary_sort): sortした配列を返すように (ary_delete_at): 指定した位置の要素を削除する * eval.c (rb_call): stack深さチェックを毎回は行わないように * error.c (Warning): 実行中のwarningが表示されていなかった * eval.c (compile): 例外発生を分離. * eval.c (f_eval): 変数rb_in_evalを正しく管理するように * ext/dbm/dbm.c (fdbm_store): 格納するkeyを文字列に変換 * eval.c (rb_call): 無限再帰のチェックを大域脱出を行うC methodにも 対応させた.threadのstack深さチェックルーチンを流用. * parse.y (yylex): 第1引数のunary -/+の判定が間違っていた. * parse.y (yylex): unary +で数字を余計に読んでいた(ex. +5 -> 55) Thu Jul 25 12:15:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (yylex): 曖昧でない引数に対して警告を出していた. * eval.c (iterator_p): 引数で呼んでも正しい結果を返すように. * parse.y: break/next/redo/retryのメソッド化. * sample/ruby-mode.el (ruby-calculate-indent): nestのチェックミス * sample/ruby-mode.el (ruby-parse-region): 予約語のチェックを強化 * parse.y (primary): unless/untilの復活 Tue Jul 23 18:50:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * array.c (Array#empty?), Hash.c (Hash#empty?), ext/dbm/dbm.c (DBM#empty?): 空の判定述語 * eval.c (f_unless): ifの逆をするイテレータ * eval.c (f_until): whileの逆をするイテレータ * parse.y: notの優先順位をand/orより高く * parse.y (expr): `!'を引数括弧を省略したcallでも有効に Mon Jul 22 10:15:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99-960722 * array.c (ary_print_on): OFSのNILチェックが不完全 * ruby.c (load_file): 標準入力からのスクリプトが空の時に対応. * ruby.c (proc_options): -wでは引数無しの時には標準入力からスクリ プトをとる(-vではたんに終了する). * array.c (ary_compact): nilの要素を取り除くメソッド * array.c (ary_nitems): nilでない要素を数えるメソッド Sun Jul 20 00:51:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby.c (proc_options): -w optionを追加 * parse.y: {}が閉じていない時には展開しない文字列を Fri Jul 19 16:16:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99-960719 * lib/find.rb: 石塚版(pruneの拡張付き) * file.c (test_l): lstatで調べないとね. * eval.c (f_throw): 第2引数を省略可能に. * parse.y (str_extend): {}のネストに対応 Thu Jul 18 18:25:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99-960718 * parse.y (str_extend): 文字列中の式展開に \" ' ` / を含む事ができ るように. Tue Jul 16 15:55:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-parse-region): 正規表現内のエスケープ に対応 * version 0.99-960716 Fri Jul 12 10:06:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * io.c (f_select): 引数のclose check. * ruby.c (load_file): #!行の引数チェックを第1引数に限定(実をいうと DOS改行対策) Wed Jul 10 17:18:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99-960710 * time.c (time_s_timegm/time_s_timelocal): 時間を生成するメソッド Mon Jun 17 15:59:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99-960617 * parse.y (yyerror): エラー表示の簡略化. Wed Jun 12 14:11:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * signal.c (rb_trap_exit): trap 0はthreadを生成せずに処理する. Fri Jun 7 10:17:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * array.c/hash.c (indexes): 配列1引数のパターンを無くした.配列の 場合は`*ary'を使ってもらおう. * eval.c (thread_wait_threads): main_threadが終了する前に他の threadを待つ(強制的には終了させない). (ruby_run): 他のthreadを待っている間にシグナルが来たら,全thread を強制終了させる. * eval.c (rb_fail): メソッド名を`$!'に埋め込む. * eval.c (thread_create): main_threadのコンテクストがセーブされな い場合があった. * process.c (f_sleep): 時間を指定せず,threadがひとつしかない状況 にも対応. * eval.c (thread_create): create後,fnを呼び出す前にcontext switch が起きると違うcontextでfnが実行されてしまうバグ. Mon Jun 3 08:03:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * struct.c (struct_s_def): メンバの指定を文字列,シンボル(FIXNUM) 双方で可能にした. * ext/etc/etc.c (Init_etc): 構造体オブジェクトをGCから保護した. * error.c (rb_sys_fail): nil/FALSEを引数として受け付けるように. Thu May 30 16:19:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_select): EINTRに対応. Wed May 29 11:04:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (f_catch): catch/throwを実装した. Tue May 28 13:30:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99-960528 * eval.c (thread_cleanup): main threadが終了すると他のthreadも終了 することの明確化. * signal.c (trap): SIGINTのデフォルトの設定ミス(本当にSIG_DFLでは まずかった).rubyではちゃんとハンドルしないと. * eval.c (thread_interrupt): SIGINTはmain_threadに例外を発生させる ように. Mon May 27 15:13:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_status): threadの状態を返すメソッド.threadの終了 を待たない. * eval.c (thread_value): 一種のpromiseを実装するためのメソッド. * eval.c (thread_join): 待っているthreadが例外を起こした時には, joinがその例外を発生するように. * eval.c (thread_create): threadでの例外をpropagateしないように. Fri May 24 10:47:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * enum.c (Init_Enumerable): `size' as alias to the `length' * eval.c (thread_save_context): `$@', `$!'をスレッド毎にセーブ. * eval.c (superclass): エラー表示をより親切に. Thu May 23 10:38:41 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.99-960523 * eval.c (superclass): エラー時にスーパークラス名を(分かれば)表示 するように. Wed May 22 19:48:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (superclass): スーパークラスの指定子を`:'から`<'に変更. Tue May 21 09:27:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * lib/thread.rb: threadをサポートするクラス(Mutex, Queue). Mon May 20 09:39:49 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * time.c (time_cmp): 浮動小数点数も扱えるように. (time_minus): Time - Timeが浮動小数点数を返すように. Fri May 17 15:40:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * process.c (rb_proc_exec): Thread対応時にexecの直前に ITIMER_VIRTUALをリセットする. Tue May 14 02:12:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * signal.c (sighandle): SIGINTに対してデフォルトで例外を発生させる のをやめ,status 130でexitするようにした. * eval.c (thread_schedule): Threadのバグはほとんどとれたようだ. Fri May 10 11:21:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (thread_schedule): ユーザレベルThread機能.効率はともかく 移植性はある.今後,thread間の通信機能を実装する予定. Thu May 2 21:22:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * time.c (time_timeval): struct timevalを直接返すように(static変数 を使わない). Wed May 1 17:27:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * process.c (f_sleep): 整数以外のtimeを指定できるように. Thu Apr 25 08:19:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c (file_s_dirname): ファイル名が"/"を含まない時,"."を返す ように(GNU dirnameの仕様). * file.c (file_s_basename): まだnilと0を混同しているソースが残って いた. * parse.y (exprs): エラーリカバリを追加. Wed Apr 24 15:51:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_chop_bang): CRLFの場合2 bytesをchop!するように. * ext/socket/socket.c (tcp_svr_s_open): まだnilと0を混同しているソー スが残っていた. Tue Apr 23 18:14:25 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * pack.c (pack_pack): "A/a"のバグ.余計なpaddingが入っていた. Thu Apr 18 13:02:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * configure.in: アーキテクチャ依存部を別ディレクトリにインストール するように. * parse.y (yyerror): エラー発生時にエラー行とその位置を表示するよ うに. Wed Apr 17 14:22:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * defines.h: SAFE_SIGHANDLEを無くし,危険な選択はできないように. * io.c (io_ungetc): 新機能. * ruby.c (load_file): ファイルからの読み込み方式が変わったのに対応. * parse.y (compile_file): ファイルからの入力を一度全部読み込むのを 止めて,getsを使うことにした. Wed Apr 10 17:40:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.98 Tue Apr 9 09:54:30 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (iter_block): イテレータブロックの指定をメソッド呼び出し に限定.文法の明確化. * eval.c (rb_eval): 条件式の正規表現の比較をinline化. * eval.c (rb_eval): defined? の 定義情報(種別)を文字列で返す. * node.h: NODE_BEGIN -> NODE_RESCUE, NODE_ENSUREに分離. * eval.c (rb_eval): option -n/-pのトップレベルループのinline展開. * parse.y (cond0): 条件式中の文字列は比較の対象としない Wed Mar 27 12:33:54 1996 Tairo Nomura <tairo@hucom.tp.titech.ac.jp> * defines.h: NeXT対応 Wed Mar 27 10:02:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y: 予約語の変更 continue -> next Mon Mar 25 07:34:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (parse_regx): o(once)オプションを追加. Fri Mar 22 14:25:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.97d * eval.c (dyna_var_defined): 動的ローカル変数の定義チェック用ルー チン. * parse.y (gettable): eval()の中での動的ローカル変数(既に値を持っ ているもの)の検出に失敗していた. Tue Mar 19 10:46:47 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.97c * re.c (reg_s_new): compile時にsegmentation fault. * parse.y (str_extend): いつもevalするように. Wed Mar 13 11:00:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (str_extend): 文字列中の式展開の不備を無くした. * parse.y: 下手なエラーリカバリを外した. Tue Mar 12 12:30:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rescue): 間違ってensureでも例外を捕捉していた. Wed Mar 6 12:11:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (var_extend): 変数展開"#{}"で,任意の式を書けるようにし た,これで「変数」展開では無くなっちゃったなあ. * regex.c (init_syntax_once): `_'をwordに追加. * regex.c (re_compile_pattern): `\w',`\W'の判定をsyntax tableを使 うように. Tue Feb 27 10:15:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * object.c (obj_inspect): 表示するインスタンス変数が無い時には, to_sを使う. * configure.in: dlnの検出を自動的に. Mon Feb 26 19:55:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby.c (readin): read(2)で一度にファイルが読み込めない場合に対応. Sat Feb 24 14:47:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.97b Fri Feb 23 11:26:02 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * class.c (rb_define_module): C言語で定義されたモジュールのPATHの 設定忘れ.文字列化でcore dump. * eval.c (mod_include): 戻り値をnilに. * version 0.97a Thu Feb 22 21:03:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * array.c (ary_times): 「配列*文字列」がjoinと同じ働きをするように. Wed Feb 21 11:18:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * configure.in : fileCountをcache. * configure.in : LinuxでELF環境を自動的に検出できるよう. Tue Feb 20 11:18:09 1996 Mitsuhide Satou <mit-sato@aries.bekkoame.or.jp> * FreeBSD dynamic link対応. Fri Feb 16 08:50:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * object.c (obj_inspect): インスタンス変数を持たないオブジェクトも 正しく表示されるように. Wed Feb 14 16:56:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_eval): 条件式の`2..2'など左辺成立直後に右辺が成立する パターンにバグ. Tue Feb 13 18:22:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.97 Fri Feb 9 21:32:55 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * lib/tkscrollbox.rb: スクロールでtclの設定を行い,ruby<->wishの不 要な通信を無くした. Wed Feb 7 10:26:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_aref): indexをunsigned intでとっていた. * string.c (str_aref): 範囲外のindexに対してnilを返す. * parse.y (special_local_set): `$_'が宣言無しに使われた場合に対応. 関数をvariable.cから移動. * string.c (str_sub): 置換開始位置が間違っていた. Tue Feb 6 16:17:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-parse-region): コメントの読み飛ばしの バグ. Fri Feb 2 18:35:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * variable.c (lastline_get): `$_'を`$~'と同じようにSCOPEローカルな 変数にした. Thu Feb 1 14:14:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c: statのcacheをやめた. Wed Jan 31 07:13:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (proc_s_new): procの中でyieldを呼ばれた時にcore dumpして いた.とりあえず例外を発生させる. * variable.c (rb_class2path): singleton classに対応. * ext/etc/etc.c (Init_etc): struct_defineのターミネータがnilだった (0でなければならない). * ext/marshal/marshal.c: TRUE/FALSEを吐き出せるように. * eval.c (rb_get_method_body): キャッシュのalias対応,いままでは aliasはキャッシュに入っていなかった. Tue Jan 30 09:55:13 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_eval): NODE_BLOCK - tail recursive(というほどでもない が). * io.c (io_pipe): pipe(2)を実装した. * eval.c (rb_eval): Qselfをなくした.thread対応への第一歩.先は遠 いが…. * eval.c (proc_call): procの中でのreturnはprocの終了を意味するよう に.ただし,procからのyieldの中でのreturnは例外を発生する. Wed Jan 24 11:33:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.96a * dir.c (dir_each): `$_'の値を変更するのをやめた. * io.c (f_readlines): nilとFALSEの分離のあおりで無限ループに落ちて いた. * ruby.c (ruby_options): $0の設定ミス. Tue Jan 23 15:28:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_eval): ``は文字列を引数とするメソッド(`)呼び出しのシ ンタックスシュガーであるとした. * ruby.c (addpath): `-I'オプションでディレクトリが「前に」追加され るように変更. Fri Jan 19 11:23:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * dln.c (load_1): N_INDR対応(出来たような気がする). Thu Jan 18 18:14:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby.texi: FALSEとnilの分離を反映した. Tue Jan 16 17:39:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.96 - とりあえずnilとFALSEを区別する版 Wed Jan 10 15:31:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * re.c (reg_match): マッチしなかった時の戻り値はFALSE. * object.c (rb_equal): `0 == nil'がTRUEになるバグ. Tue Jan 9 00:44:58 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * nilとFALSEが分離可能に変更. * nilとFALSEと0の区別を厳密に. * struct.c (struct_new): 引数を0で終る必要が無くなった. * object.c (inspect_i): オブジェクトのチェックのバグ(Fixnumでcore dumpしていた). * range.c (range_to_s): Rangeの表示を改善. * object.c (true_inspect): TRUEの表示を`TRUE'に. Mon Jan 8 15:02:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * numeric.c (fix_mul): divide by zero errorが発生した(オーバーフロー 検出のバグ) * texinfo.texをパッケージに含めた. Sun Dec 31 00:08:49 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_eval): `::'では,そのクラスで定義された定数を参照する ように変更. * string.c (Init_String): eachをeach_lineに戻した. Thu Dec 28 12:31:55 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_eval): caseの演算子を`=~'から`==='に. * variable.c (rb_const_set): クラス定数の再定義を許す(同じクラスで は不可).警告は出す. Wed Dec 27 13:27:52 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.95c * ext/tkutil/tkutil.c: wishがあってもなくても一応コンパイルだけは するように. * lib/tk.rb: 環境変数PATHから{wish|wish4.0}を探すように. Tue Dec 26 01:03:42 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-parse-region): 正規表現の検出強化. * numeric.c (fix_mul): 乗算のオーバーフロー検出アルゴリズムのバグ. * ext/extmk.rb.in: ./install-shを使う場合のPATHを調整. * Makefile.in (install): lib/*.rbを一つずつインストール. * io.c (io_each_line): イテレータの戻り値をnilで統一. Fri Dec 22 10:34:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.95b * variable.c (f_untrace_var): 第2引数を指定すると特定のtraceを削除 できるように. * variable.c (f_trace_var): 第2引数がnilの時,traceを削除する. * lib/tk.rb (file_readable/file_writable): 第2引数をnilにすること によるevent handlerの削除. * parse.y (variable): ドキュメントに`__FILE__'と`__LINE__'が残って いた.`caller(0)'で代用したはずだったのに. * eval.c (f_eval): $!のリセット. * error.c (err_sprintf): 勝手に"\n"を付加するのを止めた. * parse.y (f_arglist): 引数リスト直後のif/whileの読み間違い. lex_stateの値が設定されていなかった. Co-authored-by: Jun Kuroda <j_kuro@pluto.ai.kutech.ac.jp> Co-authored-by: Mitsuhide Satou <mit-sato@aries.bekkoame.or.jp> Co-authored-by: SHIROYAMA Takayuki <psi@fortune.nest.or.jp> Co-authored-by: Tairo Nomura <tairo@hucom.tp.titech.ac.jp> Co-authored-by: WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> Co-authored-by: Yasuo OHBA <jammy@shljapan.co.jp>
-rw-r--r--ChangeLog1799
-rw-r--r--MANIFEST30
-rw-r--r--Makefile.in30
-rw-r--r--README182
-rw-r--r--README.EXT973
-rw-r--r--README.jp159
-rw-r--r--ToDo8
-rw-r--r--array.c459
-rw-r--r--bignum.c440
-rw-r--r--class.c45
-rw-r--r--compar.c10
-rw-r--r--config.dj35
-rwxr-xr-xconfig.guess139
-rwxr-xr-xconfig.sub177
-rw-r--r--configure.bat5
-rw-r--r--configure.in242
-rw-r--r--defines.h13
-rw-r--r--dir.c64
-rw-r--r--dln.c161
-rw-r--r--enum.c100
-rw-r--r--env.h7
-rw-r--r--error.c714
-rw-r--r--eval.c3252
-rw-r--r--ext/Setup4
-rw-r--r--ext/Setup.dj8
-rw-r--r--ext/dbm/MANIFEST1
-rw-r--r--ext/dbm/dbm.c188
-rw-r--r--ext/dbm/dbm.doc107
-rw-r--r--ext/dbm/extconf.rb2
-rw-r--r--ext/etc/etc.c36
-rw-r--r--ext/extmk.rb.in148
-rw-r--r--ext/kconv/MANIFEST2
-rw-r--r--ext/kconv/kconv.c1934
-rw-r--r--ext/marshal/MANIFEST1
-rw-r--r--ext/marshal/extconf.rb2
-rw-r--r--ext/marshal/marshal.c519
-rw-r--r--ext/marshal/marshal.doc5
-rw-r--r--ext/md5/MANIFEST6
-rw-r--r--ext/md5/depend2
-rw-r--r--ext/md5/md5.doc36
-rw-r--r--ext/md5/md5.h86
-rw-r--r--ext/md5/md5c.c337
-rw-r--r--ext/md5/md5init.c90
-rw-r--r--ext/socket/MANIFEST1
-rw-r--r--ext/socket/extconf.rb7
-rw-r--r--ext/socket/socket.c426
-rw-r--r--ext/socket/socket.doc227
-rw-r--r--ext/tkutil/MANIFEST2
-rw-r--r--ext/tkutil/depend1
-rw-r--r--ext/tkutil/extconf.rb11
-rw-r--r--ext/tkutil/tkutil.c1
-rw-r--r--file.c403
-rw-r--r--gc.c171
-rw-r--r--glob.c8
-rw-r--r--hash.c137
-rw-r--r--inits.c8
-rw-r--r--io.c885
-rw-r--r--io.h14
-rw-r--r--lib/base64.rb2
-rw-r--r--lib/cgi-lib.rb56
-rw-r--r--lib/complex.rb490
-rw-r--r--lib/find.rb47
-rw-r--r--lib/getopts.rb173
-rw-r--r--lib/jcode.rb174
-rw-r--r--lib/mailread.rb19
-rw-r--r--lib/mathn.rb307
-rw-r--r--lib/observer.rb40
-rw-r--r--lib/parsearg.rb103
-rw-r--r--lib/rational.rb361
-rw-r--r--lib/safe.rb78
-rw-r--r--lib/thread.rb153
-rw-r--r--lib/tk.rb557
-rw-r--r--lib/tkcanvas.rb47
-rw-r--r--lib/tkcore.rb521
-rw-r--r--lib/tkentry.rb2
-rw-r--r--lib/tkscrollbox.rb27
-rw-r--r--lib/tktext.rb18
-rw-r--r--lib/tkthcore.rb546
-rw-r--r--main.c4
-rw-r--r--math.c9
-rw-r--r--missing/flock.c90
-rw-r--r--missing/mkdir.c4
-rw-r--r--missing/setenv.c4
-rw-r--r--missing/strftime.c1094
-rw-r--r--node.h84
-rw-r--r--numeric.c417
-rw-r--r--object.c384
-rw-r--r--pack.c74
-rw-r--r--parse.y1586
-rw-r--r--process.c386
-rw-r--r--random.c28
-rw-r--r--range.c153
-rw-r--r--re.c247
-rw-r--r--re.h2
-rw-r--r--regex.c76
-rw-r--r--regex.h2
-rw-r--r--ruby.c239
-rw-r--r--ruby.h123
-rw-r--r--ruby.texi5044
-rw-r--r--sample/clnt.rb6
-rw-r--r--sample/dir.rb4
-rw-r--r--sample/eval.rb41
-rw-r--r--sample/evaldef.rb26
-rw-r--r--sample/export.rb2
-rw-r--r--sample/fact.rb8
-rwxr-xr-xsample/from.rb14
-rw-r--r--sample/fullpath.pl22
-rw-r--r--sample/fullpath.rb6
-rwxr-xr-xsample/getopts.test25
-rw-r--r--sample/io.rb4
-rwxr-xr-xsample/less.rb4
-rw-r--r--sample/list.rb14
-rwxr-xr-xsample/mpart.rb6
-rw-r--r--sample/observ.rb31
-rw-r--r--sample/philos.rb54
-rw-r--r--sample/pi.rb18
-rw-r--r--sample/rcs.rb2
-rw-r--r--sample/regx.rb23
-rw-r--r--sample/ruby-mode.el575
-rw-r--r--sample/sieve.rb2
-rw-r--r--sample/svr.rb2
-rw-r--r--sample/test.rb981
-rwxr-xr-xsample/time.rb2
-rw-r--r--sample/tkbiff.rb46
-rw-r--r--sample/tkbrowse.rb8
-rw-r--r--sample/tkfrom.rb13
-rw-r--r--sample/tkline.rb25
-rw-r--r--sample/trojan.pl12
-rw-r--r--sample/tsvr.rb23
-rwxr-xr-xsample/uumerge.rb8
-rw-r--r--sig.h46
-rw-r--r--signal.c161
-rw-r--r--sprintf.c72
-rw-r--r--st.c202
-rw-r--r--st.h22
-rw-r--r--string.c674
-rw-r--r--struct.c95
-rw-r--r--time.c251
-rw-r--r--top.sed37
-rw-r--r--util.c2
-rw-r--r--util.h2
-rw-r--r--variable.c206
-rw-r--r--version.c8
-rw-r--r--version.h4
144 files changed, 20373 insertions, 12047 deletions
diff --git a/ChangeLog b/ChangeLog
index 9a7479823d..78867f67d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,1771 @@
+Tue Dec 24 15:20:58 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.4-961224
+
+ * configure.in: charunsignedɤå
+
+ * regex.c (SIGN_EXTEND_CHAR): __CHAR_UNSIGNED__ˤб
+
+ * pack.c (pack_unpack): Ūsigned charꡥ
+
+Mon Dec 23 14:41:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ruby.c (load_file): ɸϤΥץȤǰեȤ
+ ʤ褦
+
+ * object.c (f_integer): `0x', `0'ʤɤbase᤹褦ˡ
+
+Fri Dec 20 01:44:39 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * Makefile.in (flock.o): flockб
+
+Thu Dec 19 20:13:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.4-961219
+
+Wed Dec 18 00:06:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * glob.c (glob_filename): strrchrޥξб
+
+ * configure.in: <sys/select.h>å
+
+ * ext/kconv/kconv.c: 1.62١
+
+ * ext/kconv/kconv.c: Kconv⥸塼
+
+ * string.c (str_substr): lenʸĹб
+
+ * parse.y (iterator): $bar do .. endפʤɤϵʤ褦
+
+ * parse.y (iterator): FID(foo!,foo?)doΥƥ졼ˤǤ롥
+
+ * missing/flock.c (flock): lockf()Ȥä
+
+ * file.c (file_flock): flock
+
+Tue Dec 17 12:13:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.4-961217
+
+Fri Dec 13 02:05:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * configure.in: RUBYLIBΥȤ(@mix/awk offline)
+
+ * dln.c: AIXб(@mix/awk offline)
+
+ * eval.c (thread_schedule): critical sectionǤŪʥƥ
+ ȥåϵʤȤޤ
+
+ * re.c (reg_search): match˼Ԥ$~nilˡ
+
+ * re.c (reg_search): match褦
+
+Thu Dec 12 17:03:30 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * numeric.c (flo_to_s): 2.0.to_s -> 2.0
+
+ * eval.c (thread_save_context): $_, $~thread¸
+
+ * eval.c (thread_kill): main threadǤexit(0)
+
+ * string.c (str_split_method): ְä̤֤Ƥ
+
+Thu Dec 12 15:32:48 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * dir.c: CYGWIN32б
+
+ * ext/socket/socket.c: CYGWIN32б
+
+ * io.c: CYGWIN32б
+
+Thu Dec 12 14:43:51 1996 Jun Kuroda <j_kuro@pluto.ai.kutech.ac.jp>
+
+ * lib/tk.rb: wish4.2õ˴ޤ
+
+ * config.guess: JCCб
+
+Thu Dec 12 00:41:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.4-961212
+
+ * parse.y (parse_string): """..."""ϤϤ̵Ȥˤ
+
+ * parse.y (parse_regx): %r|...|terminator \ ǥפǤ
+ 褦
+
+ * signal.c (posix_signal): sigactionȤsignal
+
+ * configure.in: posix signal/bsd signalθ
+
+Wed Dec 11 17:47:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_schedule): critical sectionǤϥƥȥ
+ ʤ褦
+
+ * lib/thread.rb: SharedMutex饹
+
+ * lib/jcode.rb: String#scanȤ褦
+
+Tue Dec 10 12:21:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961210
+
+ * string.c (str_split_method): ɽ()ޤ˥Х
+
+ * lib/jcode.rb: äȤޤˤʤä
+
+ * string.c (tr_setup_table): ִʸû(2ʸ)ΤȤΥХ
+
+Mon Dec 9 11:38:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * string.c (str_scan): ʸΥޥåԤƥ졼ȤƤư
+ 
+
+ * regex.c (re_copy_registers): allocatedƤʤä
+
+ * re.c (match_to_s): $~ʸ
+
+ * re.c (match_to_a): $~󲽤Ǥ褦
+
+ * re.c (match_getter): 쥸Ƥʤä
+
+Thu Dec 5 11:06:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * string.c (str_split_method): ޥåʤä̤϶ʸ
+ push٤ǤϤʤ
+
+ * string.c (str_succ): ե٥åȤޤޤʤʸб
+
+Wed Dec 4 10:48:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961204
+
+ * io.c (io_binmode): DJGPPǤbinmodeб
+
+ * sprintf.c (f_sprintf): intϰϤοͤľsprintfѴ
+
+ * sprintf.c (f_sprintf): "%02s"ʤ
+
+ * re.c (reg_search): indexSEGV
+
+Tue Dec 3 10:09:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961203
+
+ * ext/extmk.rb.in (install): INSTALL_DATAINSTALLѹ
+
+ * dln.c: hpuxб
+
+ * string.c (str_aset_method): ͤޤϰϤǤ㳰򵯤ʤ
+
+ * array.c (ary_replace): ͤޤϰϤǤ㳰򵯤ʤ
+
+ * array.c (beg_len): beg==endλĹ0
+
+Mon Dec 2 14:07:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * configure.in: HP shlб
+
+ * string.c (str_upto): beg > endλ̵¥롼פΤߤ᤿
+
+ * range.c (range_each): String#upto줿б
+
+ * string.c (str_split_method): "ABC".split(/(B)/)ư
+
+Sat Nov 30 01:43:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_eval): undefSEGV
+
+Fri Nov 29 12:17:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el (ruby-parse-region): %Q#..#ʤɤб
+ ڤʸ黻ҤǹˤˤбǤʤä
+
+ * re.c (reg_raise): 㳰Ǥ⥹å򥨥
+
+ * re.c (reg_inspect): å򥨥
+
+ * parse.y (parse_string): `%[QqXxRr](.)..\1'ʤʸ(ƥ
+ )
+
+ * parse.y (parse_qstring): '''...'''η
+
+ * ext/dbm/dbm.c (Init_dbm): Ҹkey?,value?ɲ
+
+ * ext/dbm/dbm.c (Init_dbm): includes->include?
+
+ * hash.c (Init_Hash): Ҹkey?,value?,include?ɲ
+
+ * eval.c (rb_eval): else᤬¹Ԥʤ()
+
+ * string.c (str_sub_iter_s): ƥ졼֥åǥޥåԤ
+ Ȱ֤(̵¥롼פ)
+
+ * string.c (str_resize): len0λsizeĴԤʤä
+
+Thu Nov 28 00:59:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961128
+
+ * parse.y (parse_string): 3-quote styleʸ(:"""abc"d"e""")
+
+ * configure.in (EXTSTATIC): extŪ˥󥯤ˤrubydll
+ Ȥ褦
+
+ * io.c (Init_IO): getsΰְäƤ
+
+ * string.c (str_each_line): RSŪ˻Ǥ褦
+
+Wed Nov 27 12:37:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961127
+
+ * eval.c (rb_eval): iver defined? selfꤹΤ˺줿
+
+ * io.c: getsRSŪ˻Ǥ褦
+
+ * ext/extmk.rb.in (install): static link˼
+
+Tue Nov 26 10:33:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961126
+
+ * string.c (str_sub_s): ִʸĹְäƤ
+
+Mon Nov 25 09:11:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * numeric.c (fix_rshift): 32ʾαեȤ0֤褦(C
+ rshift(x>>(y%32))֤Ƥ)
+
+ * string.c (str_gsub): ִԤʤ礬ä
+
+ * string.c (str_resize): ɬפʻrealloc
+
+Thu Nov 21 04:13:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * configure.in (EXTSTATIC): --with-static-linked-extƤΥ⥸塼
+ Ū󥯤褦
+
+ * pack.c (pack_unpack): βԤʤˤå򥹥
+ פ褦
+
+Wed Nov 20 96 21:42:51 1996 Yasuo OHBA <jammy@shljapan.co.jp>
+
+ * configure.in: freebsdб
+
+Wed Nov 20 10:24:24 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/extmk.rb.in (install): ̾ѤLDFLAGSȥʥߥå
+ ѤDLDFALGSʬΥ
+
+ * ext/extmk.rb.in (install): ѥΤŪ
+ ΥꥹȤɲä
+
+ * eval.c (f_missing): ֥ȤʸɽĹХåե
+ ٤Ƥ
+
+ * process.c (proc_exec_v): fork㳰ȯƤϤʤ
+
+Tue Nov 19 13:28:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961119
+
+ * eval.c (mod_method_defined): Module#method_defined? ɲ
+
+ * parse.y (call_args): ͣΥޥɥǤΥХ(
+ ͤŸƤޤ)
+
+Mon Nov 18 13:28:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * string.c (str_sub): Ԥnil֤Ƥ
+
+ * string.c (str_split_method): ϰ֤ưƤʤä
+
+ * ext/socket/socket.c (sock_s_getservbyaname): ޤְäƤ
+
+ * version 0.99.3-961118
+
+ * string.c (str_sub_s): ʸִΤߤ᤿
+
+ * pack.c (encodes): ΰ賰򥢥Ƥ
+
+Fri Nov 15 17:10:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * bignum.c (big_divmod): Bignumξб˺
+
+ * sample/ruby-mode.el (ruby-expr-beg): word?ؤбԴ
+
+Wed Nov 13 15:42:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * string.c (str_tr_s_bang): tr_strԤƤʤä
+
+ * eval.c (rb_eval): autoload饹Υå
+
+ * string.c (f_sub): subsub!ƱưˤʤäƤ
+
+ * eval.c (thread_sleep): stopsleepʬΥ
+
+Mon Nov 11 13:53:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961111
+
+ * numeric.c (fix_step): to, stepʳξб
+
+ * eval.c (rb_call): dynamic vardynamic scopingˤʤäƤ(
+ Ϥޤ)
+
+ * string.c (str_chop_bang): Ĺ0ʸchopǡΰ賰Υ
+ ȯƤ
+
+ * parse.y (yyerror): Ƥΰ賰򥢥Ƥ
+
+Fri Nov 8 11:54:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_yield): scopeheap˥ԡ
+
+Thu Nov 7 09:56:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * numeric.c (num_coerce): ȤꤢξդFloatѴ뤳Ȥ
+
+Wed Nov 6 10:45:13 1996 Yasuo OHBA <jammy@shljapan.co.jp>
+
+ * lib/parsearg.rb: 2ѹ
+
+Tue Nov 5 14:21:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961105
+
+Sat Nov 2 01:11:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * bignum.c (big_pow): typo (dy -> dx)
+
+ * bignum.c (big_divmod): ΤʤfloatѴƤߤ
+
+ * numeric.c (fix_lshift): ΥХ(ˤʤäƤ)
+
+ * bignum.c (big_pow): ̵̤floatؤѴʤ
+
+ * math.c (math_atan2): typo(x -> y)
+
+Fri Nov 1 15:30:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/socket/socket.c (sock_gethostname): gethostnameʤˤ
+ unameȤäƥۥ̾
+
+ * ext/etc/etc.c (etc_getlogin): getloginNULL֤ƤĶѿ
+ Ĵ٤褦
+
+ * object.c (krn_clone): ֥ȤΥե饰⥳ԡ
+
+ * hash.c (rb_cmp): ϥåӤ`=='Ǥʤ`eql?'ѹ
+
+ * math.c (Need_Float): Float()ȤäѴ
+
+ * compar.c (cmp_gt): αդ֤ͤ̾ĤĤäƤ
+
+Thu Oct 31 12:55:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961031
+
+ * numeric.c (Init_Numeric): typo
+
+ * eval.c (error_print): Ĺtrace backά
+
+ * regex.c (re_compile_pattern): Ѥrangeб
+
+Wed Oct 30 03:03:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.3-961030
+
+ * io.c (f_ungetc): ؿɲ
+
+ * eval.c (dyna_var_asgn): return˺
+
+Tue Oct 29 10:05:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * string.c (f_split): ؿsplitɲ
+
+ * eval.c (rb_call): ͥȤ¦Υ饹/⥸塼򻲾
+ Ǥ褦
+
+Mon Oct 28 09:51:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * string.c (str_sub): offsetʸˤΥå
+
+ * regex.c (re_match): Ƥ쥸ο1¿ä
+
+ * io.c (io_gets): $/ = ""ưperl˹碌(awkȤϤäȰ
+ 餷)
+
+ * io.c (io_gets): $/ = nilλ®
+
+ * string.c (str_split_method): ̤null˥ޥåˤ̵뤷
+ ʤ褦
+
+ * string.c (str_split_method): ̤˥ޥåʬlimitο˴ޤ
+ ʤ褦ˡ
+
+ * numeric.c (num_coerce_bin): coerceѹ2Ǥ
+ [x,y]֤褦
+
+ * sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"б
+
+
+Sat Oct 26 01:43:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/marshal/marshal.c (w_object): ӥȥ󥯥饹Υ֥饹
+ Ǥ褦
+
+ * ext/marshal/marshal.c (w_object): 桼dumpͥ
+
+ * numeric.c (flo_coerce): Float()Ȥä
+
+ * numeric.c (Init_Numeric): NumericnewundefϤޤ
+
+ * ext/marshal/marshal.c (w_symbol): ܥ(ʸ)ϰ٤
+ ե˽񤭽Фʤ
+
+ * sample/ruby-mode.el (ruby-parse-region): if/whileҤб
+ ʤʤäƤ
+
+ * bignum.c (Init_Bignum): Bignum.new
+
+ * eval.c (rb_eval): ɾ˥ե̾ȹֹ
+
+ * numeric.c (flo_div): typo
+
+ * sample/ruby-mode.el (ruby-parse-region): def /, def `б
+
+Fri Oct 25 09:26:29 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"б
+
+ * array.c (ary_aset): indexfixnumξäȹ®
+
+ * eval.c (thread_fd_writable): 񤭹selectå
+
+ * array.c (ary_assoc): ̵¥롼פ
+
+ * eval.c (thread_wait_for): select顼λlinuxʳ
+ ưʤä
+
+Thu Oct 24 08:26:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (backtrace): `$@'ʸ󤫤ѹ
+
+ * eval.c (eval): eval㳰ȯ֤¸
+
+ * bignum.c (bigsub): ڥɤ羮Ӥμ
+
+ * re.c (reg_search): ľܻȤʤˤ`$~'åȤ褦
+
+Wed Oct 23 10:40:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-961023
+
+ * ext/marshal/marshal.c (r_bytes): mallocᡤallocaȤ
+
+ * sample/ruby-mode.el (ruby-calculate-indent): ̤бѹ
+ ()ǤϥǥȤ٥碌褦
+
+Tue Oct 22 12:59:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * hash.c (hash_s_new): sizeǤ褦
+
+ * ext/marshal/marshal.c (w_object): dump뿼¤Ǥ
+
+
+ * array.c (ary_s_new): sizeꤷν˺
+
+ * object.c (f_float): big2dbl˺졥
+
+ * bignum.c (bigsub): 礭ζᤤBignumƱΤα黻Ƿ̤ˤʤ
+ ˴ְ㤤ä
+
+ * array.c (ary_aset): ִִƱĹλƤ
+ shift(memmove)ʤ褦ˡ
+
+ * ext/marshal/marshal.c (marshal_dump): եեޥåȤ˥С
+ 褦
+
+ * ext/marshal/marshal.c (tmpnam): linux-aout-dlnѤ
+
+Mon Oct 21 08:40:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/socket/socket.c (sock_s_gethostbyname): hostent¤Τξ
+ ֤
+ (sock_s_gethostbyaddr): IPɥ쥹hostent¤Τ
+ (sock_s_getservbyaname): getservbyname(3)
+
+Fri Oct 18 10:37:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el (ruby-indent-to): ư襫बˤʤХ
+
+ * eval.c (compile): evalǸιֹǥ顼ɽ
+
+Thu Oct 17 09:52:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (eval): evalʸˡ顼äSEGV
+
+ * lib/safe.rb: Restricted.eval¤ä롥
+
+ * eval.c (error_print): Хåȥ졼νϡcaller㳰ȯ
+ Ĵ꤬Ф(ʤȤ򤷤ʤɤΤ)
+
+ * eval.c (make_backtrace): Хåȥ졼
+
+Wed Oct 16 12:56:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ruby-man-0.99.2-jp/index.html: ܸǥɥȤδ(Ĺä)
+
+ * re.c (reg_regcomp): $=nilλν
+
+ * string.c (f_chop): $_Фchop
+
+Tue Oct 15 11:04:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-961015
+
+Mon Oct 14 18:22:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_schedule): BOWбselect-1֤˥Х(
+ do .. whilecontinueƬ˥פȻפǤ
+ ľäΤ ^^);;;;;
+
+ * sample/ruby-mode.el (ruby-mode-syntax-table): ?syntax"/"Ǥ
+ ޤ餷
+
+ * hash.c (rb_hash): name conflict
+
+Fri Oct 11 00:23:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-961011
+
+ * ext/marshal/marshal.c (w_object): ưƤʤä۴ĥ֥
+ б򳰤
+
+ * hash.c (rb_hash): Fixnumʸι®
+
+ * ext/marshal/marshal.c (w_object): ̵̤ʥǡκ(եޥ
+ Ȥߴ)
+
+ * io.c (io_readline): ͤ
+
+ * ext/marshal/marshal.c (marshal_dumps): MSDOSб
+
+ * ruby.c (load_file): MSDOSб
+
+Wed Oct 9 17:46:27 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/extmk.rb.in (install): ̵̤ʥԡ򤱤
+
+ * string.c (str_sub_method): ޥåʤäString#subͤ
+ äƤ
+
+ * eval.c (obj_extend): extendobject_extendedƤ֤褦
+
+Tue Oct 8 00:55:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_alloc): ʿѲ
+
+ * eval.c (thread_schedule): joinΥХ
+
+ * eval.c (thread_wait_for): selectؤγߤʤɤб
+
+ * eval.c (thread_select): linuxselectεưб(timeoutѲ
+ )
+
+Mon Oct 7 09:47:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-961007
+
+ * eval.c (PUSH_BLOCK): the_class¸˺Ƥ
+
+ * ext/dbm/dbm.c (fdbm_store): size¸ְ꤬äƤ
+
+ * ext/socket/socket.c (s_accept): threadбƤʤä
+
+Sat Oct 5 01:32:27 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * io.c (io_readchar): EOF㳰ȯ
+
+Fri Oct 4 11:59:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/marshal/marshal.c (w_object): HashObjectɬפʥϥ
+ ơ֥뤬ϤƤʤä
+
+ * variable.c (rb_path2class): 桼饹˼ԤƤ
+
+ * variable.c (rb_path2class): 饹¸ߤʤΥ顼Fatal
+ NameErrorء
+
+ * range.c (range_s_new): first,lastξNumericλ顼ˤʤä
+
+
+ * range.c: start->first, end->last
+
+Wed Oct 2 02:02:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * file.c: DJGPPchmod,chownȤ褦(äDOSchownΤ?)
+
+ * class.c (rb_singleton_class): ӥȥ󥯥饹extendð
+ ᥽åɤɲäǤ褦
+
+ * variable.c (rb_set_class_path): 桼Υȥåץ٥륯饹
+ pathꤷʤ
+
+ * eval.c (eval): 㳰RuntimeError˲Ƥ
+
+ * eval.c (eval): eval㳰ɽβ
+
+ * eval.c (eval): eval_with_bindingȤΰܲ
+
+ * eval.c (rb_eval): 饹/⥸塼椫Υ饹/
+ 塼뤬ȤǤ褦
+
+Tue Oct 1 01:40:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-961001
+
+ * parse.y: cur_cref2Ƥ
+
+ * signal.c (trap): SIGSEGVSIGBUSΤʤб
+
+ * io.c (Init_IO): פλְ㤤
+
+Mon Sep 30 15:28:00 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-960930
+
+ * config.guess,config.sub: $host_osꤵʤ
+
+ * eval.c (rb_eval): yieldʤselfꤵƤ
+
+ * eval.c (ruby_run): toplevel㳰ΥХ
+
+Mon Sep 30 09:13:26 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * djgppб
+
+Sat Sep 28 02:45:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-960928
+
+ * sample/ruby-mode.el (ruby-beginning-of-block): ֥åƬ
+ ư(ǥȤƤʤưʤ)
+ (ruby-end-of-block): Ʊ
+
+ * eval.c (class_s_new): Class#newƥ졼ȤƸƤФ줿
+ initialize⥤ƥ졼ȤƸƤФ褦
+
+ * signal.c (sigsegv): SEGVbacktraceɽ褦
+
+Fri Sep 27 09:51:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-960927
+
+ * eval.c (error_print): Τʤraiseǥåɽ
+ 褦ˡ
+
+ * eval.c (rb_longjmp): mesgnilλRuntimeError롥
+
+ * eval.c (f_raise): ʤб
+
+ * eval.c (thread_mark): stackˤʤǡΥɥ쥹ѴԤä
+
+
+ * eval.c (Init_Thread): ߤδֳ֤1äĹ
+
+Thu Sep 26 16:02:45 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_schedule): ٥ڥǥ󥰤ˤʤȥե饰ꥢ
+ Ƥʤä
+
+ * process.c (rb_proc_exec): system/execΰʸǤä
+ 硤㳰ȯ٤ä
+
+ * config.sub/config.guess: Τ֤
+
+Thu Sep 26 15:41:35 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * io.c (next_argv): -i.bakBOWDOSб
+
+Thu Sep 26 01:31:43 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * io.c (io_sysread): EOF㳰
+
+ * io.c (f_readline): EOF㳰ȯ褦ˡgetsϸߴΤ
+ nil֤ޤޤˤ
+
+ * eval.c (proc_call): lambdareturnIN_BLOCKե饰Ωä
+ ޤä
+
+ * eval.c (PUSH_BLOCK2): threadб뤿Blockstack˥ԡ
+
+Wed Sep 25 11:54:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (method_call): Const::method()Ȥ褦ˤƤߤ
+ ̤ϾάǤʤ
+
+ * sample/test.rb: Process.kill¸ߤΤƤƥȤԤ
+
+ * eval.c (eval_with_binding): 2Ȥbinding(ޤlambda)
+ ͿȤδĶeval¹Ԥ褦ˤ
+
+ * eval.c (f_binding): ߤbinding֤ؿ
+
+ * eval.c: block¤Τthe_class¸Фɲ
+
+ * process.c (Init_process): kill,wait,waitpidProcess˰ư
+
+Tue Sep 24 02:44:43 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el: ꤬¿Τǰι®˴
+ ̤ΥץȤä
+
+ * lib/tk.rb (Tk.pack): ʣΥɥդpack
+
+Sat Sep 21 11:08:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (exprs): ʸդ褦ʸˡѹޤǤϲ
+ Ϣ³Ƥ
+
+Fri Sep 20 11:39:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * FailȾ̾Ĥ㳰ѹ
+
+ * re.c (Init_Regexp): ̾Ĥ㳰Ƴ
+
+ * eval.c (f_missing): Objectinspectʤ
+
+ * object.c (inspect_i): Object#inspectloopб
+
+ * regex.c (re_search): /^$/""˥ޥåʤä
+
+Thu Sep 19 19:25:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * regex.c (re_search): /^$/Ԥ˥ޥåƤ
+
+Tue Sep 17 10:28:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-960917
+
+Mon Sep 16 10:47:56 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el (ruby-calculate-indent): 黻ҷ³ξ
+ ʸȽΥХ
+
+ * sample/ruby-mode.el (ruby-calculate-indent): elseʤɤμιԤ
+ ǥȷ׻
+
+Sat Sep 14 08:37:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.2-960914
+
+Fri Sep 13 08:06:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/socket/socket.c (tcpaddr): portֹntohsĤ˺
+
+ * dln.c (link_undef): ơ֥μबְäƤ
+
+ * bignum.c (bigadd): ȯ˷׻㤤Ƥ
+
+ * parse.y (iter_do_block): do..endǤdynamic variable
+
+ * bignum.c (big_pow): Τʷ׻(ƱΤǤfloatѴ
+ )
+
+Thu Sep 12 13:11:55 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * variable.c (rb_set_class_path): String饹
+ StringäƤȹߥ饹ˤpathϤʤ
+
+ * parse.y (yylex): 0.10ˤʤäƤ
+
+ * parse.y (yylex): ֹ
+
+ * gc.c (oblist_live_obj): ƤΥ֥Ȥ֤
+ ƥ졼Υ饹(ޤϥ֥饹)Υ󥹥󥹤
+ each_object_of
+
+ * class.c (rb_define_class_id): ̵̤ʥ饹ƤƤ
+ Ȥ̤Υ饹֥Ȥ¸ߤƤ
+
+Wed Sep 11 00:56:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (yylex): octalθФΤ(090ϥ顼Ȥ)
+
+ * bignum.c (big_minus): yx礭˥顼
+
+ * parse.y (yylex): 顼ֹɽΤ
+
+ * sample/ruby-mode.el (ruby-expr-beg): ѿ̾1ʸλư
+
+
+ * sample/ruby-mode.el (ruby-calculate-indent): ?/ǥ롼פ
+ Х
+
+ * enum.c (enum_min,enum_max): sortΤ褦˥ƥ졼ȤƤư
+ 褦ˡ
+
+ * enum.c (enum_find_all): typo
+
+Tue Sep 10 12:07:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * node.h (nd_line): NODElineflags˲ƥ֥ȥ
+ 򾮤:32bit intΥޥξ硤եιԿ
+ 32767ۤɽʤ
+
+ * st.c: hashcompareδؿФ¤Τ˥ѥå饹ŪʻȤ
+ Ԥ1 table4 byte
+
+Mon Sep 9 16:35:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * file.c (file_truncate): 󶡤ʤˤ̤㳰ȯ
+ ˡ
+
+ * eval.c (Init_Proc): Ŭڤʰ֤local-jump㳰ˡ
+
+Sat Sep 7 17:06:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (proc_call): ޤפåˤˤ϶ɽæ
+ ͭˤ롥ǡproccall뤳Ȥϡפæ
+ Фʤ¤ꡤyieldƱ̣ĤȤˤʤ롥
+
+Fri Sep 6 13:30:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el (ruby-indent-to): ǥȤѤʤ
+ ϥХåեѹʤ
+ (ruby-calculate-indent): ޤʸȽǤƤ顤ι
+ ѡԤdefun礭ʤäι®
+ (ruby-in-string-p): ʸɤȽǤؿ(
+ parseʬΥ)
+ (ruby-parse-region): ʸФϤ
+ (ruby-beginning-of-block): ֥åƬ
+ (ruby-end-of-block): ֥å(٤)
+
+Thu Sep 5 14:23:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * file.c (file_s_split): [dirname,basename]split롥
+
+ * eval.c (rb_eval): evalǤͤʤ褦ˡ
+ ˴ؤƤŪʥפݾڤ褦ˤʤä
+
+ * st.c (rehash): ϥåηϿ21.79ˡ任ɤ
+ ֤褦ˡ
+
+Thu Sep 5 00:32:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (class_superclass) 饹Υѡ饹֤᥽åɡ
+
+Wed Sep 4 16:54:56 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * random.c (f_rand): BignumlongϰϤۤFloatФ
+ ȯǤ褦ˡ
+
+ * struct.c (struct_alloc): FatalǤϤʤ㳰ȯ褦(
+ λѤȯ)
+
+ * struct.c (struct_s_members): Structðۥ᥽åɤǤϤʤ
+ 줿Struct饹ðۥ᥽åɤˤ
+
+ * st.c (st_init_table): rubyѤ˥ѥ᥿ˤ(
+ ä)
+
+Mon Sep 2 11:37:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * array.c (ary_shift): capaޤˤ礭ˤΰREALLOC
+ (ary_pop): Ʊ
+
+ * string.c (str_inspect): multibyte character б˥ߥ
+ (str_inspect): unsigned charˤʤŸƤޤ
+
+ * parse.y (primary): `::'primary˰ư Foo::Bar.Baz顼ˤ
+ ʤ褦ˡ
+
+ * parse.y (primary): ڥ졼ðۥ᥽åɤǤʤ
+
+ * random.c (f_rand): max0λб
+
+ * io.c (io_printf): ؿƤ󥿥ץ꥿ϿƤ
+ ä
+
+ * file.c (file_s_basename): 2̵˥顼
+
+Thu Aug 29 10:49:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (expr): ƥ졼οˡmethod do .. end׷
+ ѤΤηͭ
+
+ * sample/ruby-mode.el (ruby-calculate-indent): endο¿
+ ˤ⥨顼򵯤ʤ褦ˡ
+
+Wed Aug 28 09:41:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * numeric.c (upto,downto,step,times): оݤfixnumϰϤۤƤ
+ ư褦ˡ
+
+Mon Aug 26 10:04:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * missing/setenv.c (envix): typo(missing `== 0' for memcmp)
+
+ * dir.c (dir_foreach): foreach(dir open -> read loop -> closeޤ)
+
+ * io.c (io_foreach): foreach(file open -> read loop -> closeޤ)
+
+ * FatalΤªǽʤĤ㳰ˡ
+
+Sat Aug 24 23:56:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * bignum.c (bigdivmod): FIX2INT -> INT2FIX ְ㤤
+
+Fri Aug 23 18:13:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * regex.c (re_free_registers): allocateƤʤˤ free
+ ƤϤʤ
+
+Thu Aug 22 01:20:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_create): ¦鶯λ줿thread
+ cleanupɬפ̵
+
+Wed Aug 21 09:57:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_create): threadλæФξ
+ main_threadϤ褦ˡ
+
+ * parse.y (call_args): ǽ˳̤ά᥽åɸƽФ
+ 褦(: print foo bar, baz == print(foo(bar,baz)))
+
+Tue Aug 20 13:37:16 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (masign): ¿restư碌ƶ
+ 褦ˡ
+
+ * parse.y (arg): defined?ζ٤⤦äȶ
+
+ * eval.c (error_print): -w㳰̾ɽ褦
+
+ * eval.c (rb_eval): ʸб
+ (handle_rescue): ª㳰 kind_of? Ʊ
+
+ * parse.y (primary): rescueιʸѹ(Ʊɲáʣrescue)
+
+ * Fail()ΤʤŬ㳰Ȥ褦
+
+ * eval.c (thread_interrupt): Interrupt(non-local jump)
+ main-thread褦ˡ
+
+ * eval.c (rb_longjmp): $! Ƥʸ󤫤㳰饹ѹ
+ (rb_raise): rb_fail ̾ѹ
+ (rb_interrupt): 㳰
+ (rb_exit): 㳰
+
+ * error.c (Init_Exception): 㳰饹ο(ʸΥ֥饹)
+
+Mon Aug 19 19:40:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * signal.c (trap): Ťϥɥ֤褦ˡ
+
+Wed Aug 14 00:07:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_trap_eval): ϥɥΤthreadfork뤳Ȥ
+ ᤿
+
+ * eval.c (thread_mark): thread $!, $@ ޡ˺
+
+ * ext/dbm/dbm.c (fdbm_delete): ƥ졼ȤƸƤФ줿硤
+ ̵Х֥åɾ롥
+
+ * hash.c (hash_delete): ƥ졼ȤƸƤФ줿硤Ǥ̵
+ Х֥åɾ롥
+
+ * array.c (ary_delete): ƥ졼ȤƸƤФ줿硤Ǥ̵
+ Х֥åɾ롥
+
+ * eval.c (rb_interrupt): SIGINTΥǥեȤexit̤æ
+ ФˡϤޤ줿֤ɽ̵Τϼ䤷Τǡ
+
+Tue Aug 13 01:34:00 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_exit): sub-threadǤexitstatus¸褦
+ (thread_create): threadexitб
+
+ * signal.c (sighandle): SIGINTΥǥեȥϥɥexit褦
+ (㳰ȯƤ)
+
+ * 㳰ΰFatalˡ
+
+ * string.c (str_aset): ʸִоݤʬʸǤʤä
+ 㳰ȯʤ褦
+
+ * eval.c (proc_call): Proc椫break/next̤¾ΤΤ̤
+ ʤ褦
+
+Mon Aug 12 14:15:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * object.c (krn_type): ʸ֤
+
+ * eval.c (thread_create): sub-threadǤexitб
+
+ * numeric.c (fix_type): ʸ֤
+
+ * io.c (f_p): ǥХåѥǡɽ᥽å
+
+ * eval.c (f_missing): nil/TRUE/FALSḚ
+
+ * string.c (str_inspect): ĹʸûɽinspectƯ
+ human readable string(re-generatable string
+ ̵ʤä)
+
+Sat Aug 10 16:54:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * object.c (Init_Object): kernel/nil/false/trueΥ饹̾ѹ(
+ ʸ)rubyץȤ饢Ǥʤ褦ˡ
+
+ * eval.c (rb_eval): CONSTANTΥñ㲽crefȤʤ
+
+ * eval.c (f_eval): ðۥ᥽åǤͤʤ褦
+
+Fri Aug 9 12:23:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * array.c (ary_concat): append -> concat String˹碌
+
+ * parse.y (yylex): `$;'Ȥʤä
+
+ * array.c (ary_push_method): ʣդ褦ˡ
+ (ary_unshift): ʣդ褦ˡ
+
+ * io.c (io_popen): IO.popencommand pipe褦ˡ
+
+ * object.c (Init_Object): KernelNilruby script饢Ǥ
+ ʤ褦ˡ
+
+Thu Aug 8 01:21:47 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * object.c (f_integer): ؤѴؿ
+ (f_float): ¿ؤѴؿ
+ (f_string): ʸؤѴؿ
+ (f_array): ؤѴؿ
+
+ * bignum.c (big_to_i): FIXNUMϰϤǤʤBignumΤޤ֤褦
+ ѹ
+
+Wed Aug 7 09:28:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99.1-960807
+
+ * parse.y (mlhs): *foo = 1,2,3ץפ¿ǽˡ
+
+ * object.c (Init_Object): 饹True/Falseruby script饢
+ Ǥʤ褦ˡ
+
+ * object.c (nil_inspect): inspectɽ"nil"
+
+ * io.c (io_print): nilprintnilˡ
+
+ * object.c (nil_to_s): nilʸɽ""ˡ
+
+Tue Aug 6 01:12:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * dir.c (dir_s_open): file descripter­ʤˤgcƤ
+ openƤߤ롥
+
+ * io.c (rb_fopen): ٤Ƥfopen()ˤĤfile descripter­
+ ˤgcƤ⤦openƤߤ롥
+
+ * ext/socket/socket.c (Init_socket): ɲá
+
+ * sample/ruby-mode.el (ruby-indent-to): ǥȸΥ
+ Ĵ
+
+ * gc.c (gc): ߥåԤʤ(Cɤǰ¿
+ malloc()ȤʤʤΤ)
+
+ * st.c (call_hash_func): signalthreadˤߤб
+
+ * sig.h (DEFER_INTS): ߶ػ߶֤λ
+
+ * eval.c (f_require): threadˤrequireζб(ǽ
+ requireλޤ¾threadԤ)
+
+ * bignum.c (str2inum): 0x80000000ͤˤʤäƤ
+
+ * sprintf.c (f_sprintf): ʸñȤ`%'б
+
+ * bignum.c (big_cmp): Ӥη̤դˤʤä
+
+Mon Aug 5 10:58:13 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * process.c (proc_exec_v): 㳰Υåʬ䤹
+
+ * ext/dbm/dbm.c (fdbm_store): nilǼǤκˤʤ
+
+ * ext/dbm/dbm.c: 򥭥å塥
+
+Sat Aug 3 01:52:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_fail): `fail'̵ǸƤФ줿`$@'
+ ¸褦ˡ
+
+ * eval.c (f_fail): frameĴ
+
+Fri Aug 2 11:26:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/socket/socket.c (bsock_setopt): valȤTRUE/FALSE/Fixnum
+ դ褦ˡ
+
+ * ext/socket/socket.c (Init_socket): SO_REUSEADDRɲ
+
+ * ext/md5/md5init.c: md5⥸塼(ʣե뤫ʤ⥸塼
+ Ǥ⤢)
+
+ * ruby.h (Make_Data_Struct): Data: objectinstanceѿ˳Ǽ ->
+ DataObject(Dir,Time,Proc,Thread,DBM)
+
+Thu Aug 1 11:38:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/dbm/dbm.c (fdbm_store): valueʸ̵б
+
+Wed Jul 31 10:53:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ext/socket/socket.c (open_inet): htonsɬפǤä
+ (tcpaddr): ntohlѴ
+
+ * process.c (rb_proc_exec): execvp -> execv
+
+Tue Jul 30 17:48:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c: `$?'thread local
+
+ * Makefile.in (install): installstripԤ
+
+ * configure.in: installstripθ
+
+ * configure.in: NEXTSTEPб
+
+ * version 0.99.1-960730
+
+Tue Jul 30 16:40:35 1996 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * dln.c (dln_load): NeXT dln(mach-o)бconfigure̤б
+
+Tue Jul 30 09:46:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * process.c (f_system): ʣȤ褦
+
+ * process.c (f_exec): ʣȤ褦
+
+ * array.c (ary_append): (ޤEnum)Ǥ˲Ūɲ
+
+ * array.c (ary_plus): EnumϤǤɲ
+
+ * file.c (file_s_open): File.openɲ
+
+ * struct.c (struct_new): FIX2INT˺Ƥ
+
+ * file.c (Init_File): exists? -> exist?
+
+ * object.c (obj_is_kind_of): is_kind_of? -> kind_of?, is_a?
+
+ * object.c (obj_is_instance_of): is_instance_of? -> instance_of?
+
+Mon Jul 29 16:40:02 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (parse_regx): ŸԤä硤casefold꤬Ǥ
+ ʤä
+
+ * object.c (true_type): TRUE/FALSEtype
+
+ * parse.y (read_escape): 3ʸoctalб(\0Ȥ)
+
+Fri Jul 26 00:31:45 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * array.c (ary_reverse_bang): in-placeȿž
+ (ary_sort_bang): in-placesort
+ (ary_sort): sort֤褦
+ (ary_delete_at): ꤷ֤Ǥ
+
+ * eval.c (rb_call): stackåϹԤʤ褦
+
+ * error.c (Warning): ¹warningɽƤʤä
+
+ * eval.c (compile): 㳰ȯʬΥ
+
+ * eval.c (f_eval): ѿrb_in_eval褦
+
+ * ext/dbm/dbm.c (fdbm_store): ǼkeyʸѴ
+
+ * eval.c (rb_call): ̵ºƵΥåæФԤC methodˤ
+ бthreadstackå롼ήѡ
+
+ * parse.y (yylex): 1unary -/+Ƚְ꤬äƤ
+
+ * parse.y (yylex): unary +ǿ;פɤǤ(ex. +5 -> 55)
+
+Thu Jul 25 12:15:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (yylex): ۣǤʤФƷٹФƤ
+
+ * eval.c (iterator_p): ǸƤǤ̤֤褦ˡ
+
+ * parse.y: break/next/redo/retryΥ᥽åɲ
+
+ * sample/ruby-mode.el (ruby-calculate-indent): nestΥåߥ
+
+ * sample/ruby-mode.el (ruby-parse-region): ͽΥå򶯲
+
+ * parse.y (primary): unless/until
+
+Tue Jul 23 18:50:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * array.c (Array#empty?), Hash.c (Hash#empty?), ext/dbm/dbm.c (DBM#empty?):
+ ȽҸ
+
+ * eval.c (f_unless): ifεդ򤹤륤ƥ졼
+
+ * eval.c (f_until): whileεդ򤹤륤ƥ졼
+
+ * parse.y: not̤ͥand/or⤯
+
+ * parse.y (expr): `!'̤άcallǤͭ
+
+Mon Jul 22 10:15:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99-960722
+
+ * array.c (ary_print_on): OFSNILåԴ
+
+ * ruby.c (load_file): ɸϤΥץȤλб
+
+ * ruby.c (proc_options): -wǤϰ̵λˤɸϤ饹
+ ץȤȤ(-vǤϤ˽λ)
+
+ * array.c (ary_compact): nilǤ᥽å
+
+ * array.c (ary_nitems): nilǤʤǤ᥽å
+
+Sun Jul 20 00:51:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ruby.c (proc_options): -w optionɲ
+
+ * parse.y: {}ĤƤʤˤŸʤʸ
+
+Fri Jul 19 16:16:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99-960719
+
+ * lib/find.rb: (pruneγĥդ)
+
+ * file.c (test_l): lstatĴ٤ʤȤ͡
+
+ * eval.c (f_throw): 2άǽˡ
+
+ * parse.y (str_extend): {}ΥͥȤб
+
+Thu Jul 18 18:25:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99-960718
+
+ * parse.y (str_extend): ʸμŸ \" ' ` / ޤǤ
+ 褦ˡ
+
+Tue Jul 16 15:55:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el (ruby-parse-region): ɽΥ
+ б
+
+ * version 0.99-960716
+
+Fri Jul 12 10:06:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * io.c (f_select): close check.
+
+ * ruby.c (load_file): #!Ԥΰå1˸(¤򤤤
+ DOSк)
+
+Wed Jul 10 17:18:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99-960710
+
+ * time.c (time_s_timegm/time_s_timelocal): ֤᥽å
+
+Mon Jun 17 15:59:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99-960617
+
+ * parse.y (yyerror): 顼ɽδά
+
+Wed Jun 12 14:11:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * signal.c (rb_trap_exit): trap 0thread˽롥
+
+Fri Jun 7 10:17:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * array.c/hash.c (indexes): 1Υѥ̵
+ `*ary'ȤäƤ餪
+
+ * eval.c (thread_wait_threads): main_threadλ¾
+ threadԤ(ŪˤϽλʤ)
+ (ruby_run): ¾threadԤäƤ֤˥ʥ뤬褿顤thread
+ λ롥
+
+ * eval.c (rb_fail): ᥽å̾`$!'ࡥ
+
+ * eval.c (thread_create): main_threadΥƥȤ֤
+ 礬ä
+
+ * process.c (f_sleep): ֤ꤻthreadҤȤĤʤ
+ ˤб
+
+ * eval.c (thread_create): create塤fnƤӽФcontext switch
+ Ȱ㤦contextfn¹ԤƤޤХ
+
+Mon Jun 3 08:03:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * struct.c (struct_s_def): Фλʸ󡤥ܥ(FIXNUM)
+ Dzǽˤ
+
+ * ext/etc/etc.c (Init_etc): ¤Υ֥ȤGCݸ
+
+ * error.c (rb_sys_fail): nil/FALSEȤƼդ褦ˡ
+
+Thu May 30 16:19:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_select): EINTRб
+
+Wed May 29 11:04:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (f_catch): catch/throw
+
+Tue May 28 13:30:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99-960528
+
+ * eval.c (thread_cleanup): main threadλ¾thread⽪λ
+ 뤳Ȥβ
+
+ * signal.c (trap): SIGINTΥǥեȤߥ(SIG_DFLǤ
+ ޤä)rubyǤϤȥϥɥ뤷ʤȡ
+
+ * eval.c (thread_interrupt): SIGINTmain_thread㳰ȯ
+ 褦ˡ
+
+Mon May 27 15:13:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_status): threadξ֤֤᥽åɡthreadνλ
+ Ԥʤ
+
+ * eval.c (thread_value): promise뤿Υ᥽åɡ
+
+ * eval.c (thread_join): ԤäƤthread㳰򵯤ˤϡ
+ join㳰ȯ褦ˡ
+
+ * eval.c (thread_create): threadǤ㳰propagateʤ褦ˡ
+
+Fri May 24 10:47:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * enum.c (Init_Enumerable): `size' as alias to the `length'
+
+ * eval.c (thread_save_context): `$@', `$!'򥹥å˥֡
+
+ * eval.c (superclass): 顼ɽڤˡ
+
+Thu May 23 10:38:41 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.99-960523
+
+ * eval.c (superclass): 顼˥ѡ饹̾(ʬ)ɽ
+ 褦ˡ
+
+Wed May 22 19:48:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (superclass): ѡ饹λҤ`:'`<'ѹ
+
+Tue May 21 09:27:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * lib/thread.rb: thread򥵥ݡȤ륯饹(Mutex, Queue)
+
+Mon May 20 09:39:49 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * time.c (time_cmp): ưⰷ褦ˡ
+ (time_minus): Time - Timeư֤褦ˡ
+
+Fri May 17 15:40:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * process.c (rb_proc_exec): Threadбexecľ
+ ITIMER_VIRTUALꥻåȤ롥
+
+Tue May 14 02:12:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * signal.c (sighandle): SIGINTФƥǥեȤ㳰ȯ
+ Τᡤstatus 130exit褦ˤ
+
+ * eval.c (thread_schedule): ThreadΥХϤۤȤɤȤ줿褦
+
+Fri May 10 11:21:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (thread_schedule): 桼٥ThreadǽΨϤȤ⤫
+ ܿϤ롥塤thread֤̿ǽͽꡥ
+
+Thu May 2 21:22:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * time.c (time_timeval): struct timevalľ֤褦(staticѿ
+ Ȥʤ)
+
+Wed May 1 17:27:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * process.c (f_sleep): ʳtimeǤ褦ˡ
+
+Thu Apr 25 08:19:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * file.c (file_s_dirname): ե̾"/"ޤޤʤ"."֤
+ 褦(GNU dirnameλ)
+
+ * file.c (file_s_basename): ޤnil0ƱƤ륽Ĥä
+
+
+ * parse.y (exprs): 顼ꥫХɲá
+
+Wed Apr 24 15:51:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * string.c (str_chop_bang): CRLFξ2 byteschop!褦ˡ
+
+ * ext/socket/socket.c (tcp_svr_s_open): ޤnil0ƱƤ륽
+ ĤäƤ
+
+Tue Apr 23 18:14:25 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * pack.c (pack_pack): "A/a"ΥХ;פpaddingäƤ
+
+Thu Apr 18 13:02:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * configure.in: ƥ¸̥ǥ쥯ȥ˥󥹥ȡ
+ 褦ˡ
+
+ * parse.y (yyerror): 顼ȯ˥顼ԤȤΰ֤ɽ
+ ˡ
+
+Wed Apr 17 14:22:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * defines.h: SAFE_SIGHANDLE̵ϤǤʤ褦ˡ
+
+ * io.c (io_ungetc): ǽ
+
+ * ruby.c (load_file): ե뤫ɤ߹ѤäΤб
+
+ * parse.y (compile_file): ե뤫Ϥɤ߹Τ
+ ߤơgetsȤȤˤ
+
+Wed Apr 10 17:40:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.98
+
+Tue Apr 9 09:54:30 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (iter_block): ƥ졼֥åλ᥽åɸƤӽФ
+ ˸ꡥʸˡβ
+
+ * eval.c (rb_eval): PɽӤinline
+
+ * eval.c (rb_eval): defined? ()ʸ֤
+
+ * node.h: NODE_BEGIN -> NODE_RESCUE, NODE_ENSUREʬΥ
+
+ * eval.c (rb_eval): option -n/-pΥȥåץ٥롼פinlineŸ
+
+ * parse.y (cond0): PʸӤоݤȤʤ
+
+Wed Mar 27 12:33:54 1996 Tairo Nomura <tairo@hucom.tp.titech.ac.jp>
+
+ * defines.h: NeXTб
+
+Wed Mar 27 10:02:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y: ͽѹ continue -> next
+
+Mon Mar 25 07:34:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (parse_regx): o(once)ץɲá
+
+Fri Mar 22 14:25:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.97d
+
+ * eval.c (dyna_var_defined): ưŪѿåѥ롼
+
+
+ * parse.y (gettable): eval()ǤưŪѿ(ͤ
+ Ƥ)θФ˼ԤƤ
+
+Tue Mar 19 10:46:47 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.97c
+
+ * re.c (reg_s_new): compilesegmentation fault
+
+ * parse.y (str_extend): Ĥeval褦ˡ
+
+Wed Mar 13 11:00:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (str_extend): ʸμŸ̵
+
+ * parse.y: ʥ顼ꥫХ򳰤
+
+Tue Mar 12 12:30:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rescue): ְäensureǤ㳰ªƤ
+
+Wed Mar 6 12:11:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * parse.y (var_extend): ѿŸ"#{}"ǡǤդμ񤱤褦ˤ
+ ǡѿŸǤ̵ʤääʤ
+
+ * regex.c (init_syntax_once): `_'wordɲá
+
+ * regex.c (re_compile_pattern): `\w',`\W'Ƚsyntax table
+ 褦ˡ
+
+Tue Feb 27 10:15:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * object.c (obj_inspect): ɽ륤󥹥ѿ̵ˤϡ
+ to_sȤ
+
+ * configure.in: dlnθФưŪˡ
+
+Mon Feb 26 19:55:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ruby.c (readin): read(2)ǰ٤˥ե뤬ɤ߹ʤб
+
+Sat Feb 24 14:47:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.97b
+
+Fri Feb 23 11:26:02 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * class.c (rb_define_module): C줿⥸塼PATH
+ ˺졥ʸ󲽤core dump
+
+ * eval.c (mod_include): ͤnilˡ
+
+ * version 0.97a
+
+Thu Feb 22 21:03:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * array.c (ary_times): *ʸפjoinƱƯ򤹤褦ˡ
+
+Wed Feb 21 11:18:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * configure.in : fileCountcache
+
+ * configure.in : LinuxELFĶưŪ˸ФǤ褦
+
+Tue Feb 20 11:18:09 1996 Mitsuhide Satou <mit-sato@aries.bekkoame.or.jp>
+
+ * FreeBSD dynamic linkб
+
+Fri Feb 16 08:50:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * object.c (obj_inspect): 󥹥ѿʤ֥Ȥ
+ ɽ褦ˡ
+
+Wed Feb 14 16:56:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_eval): P`2..2'ʤɺΩľ˱դΩ
+ ѥ˥Х
+
+Tue Feb 13 18:22:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.97
+
+Fri Feb 9 21:32:55 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * lib/tkscrollbox.rb: tclԤruby<->wish
+ פ̵̿
+
+Wed Feb 7 10:26:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * string.c (str_aref): indexunsigned intǤȤäƤ
+
+ * string.c (str_aref): ϰϳindexФnil֤
+
+ * parse.y (special_local_set): `$_'̵˻Ȥ줿б
+ ؿvariable.cư
+
+ * string.c (str_sub): ִϰְ֤äƤ
+
+Tue Feb 6 16:17:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el (ruby-parse-region): ȤɤФ
+ Х
+
+Fri Feb 2 18:35:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * variable.c (lastline_get): `$_'`$~'Ʊ褦SCOPE
+ ѿˤ
+
+Thu Feb 1 14:14:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * file.c: statcache᤿
+
+Wed Jan 31 07:13:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (proc_s_new): procyieldƤФ줿core dump
+ Ȥꤢ㳰ȯ롥
+
+ * variable.c (rb_class2path): singleton classб
+
+ * ext/etc/etc.c (Init_etc): struct_defineΥߥ͡nilä
+ (0ǤʤФʤʤ)
+
+ * ext/marshal/marshal.c: TRUE/FALSEǤФ褦ˡ
+
+ * eval.c (rb_get_method_body): åaliasбޤޤǤ
+ aliasϥåäƤʤä
+
+Tue Jan 30 09:55:13 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_eval): NODE_BLOCK - tail recursive(ȤۤɤǤʤ
+ )
+
+ * io.c (io_pipe): pipe(2)
+
+ * eval.c (rb_eval): Qselfʤthreadбؤ⡥ϱ
+ ġ
+
+ * eval.c (proc_call): procǤreturnprocνλ̣褦
+ ˡprocyieldǤreturn㳰ȯ롥
+
+Wed Jan 24 11:33:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.96a
+
+ * dir.c (dir_each): `$_'ͤѹΤ᤿
+
+ * io.c (f_readlines): nilFALSEʬΥΤ̵¥롼פ
+
+
+ * ruby.c (ruby_options): $0ߥ
+
+Tue Jan 23 15:28:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_eval): ``ʸȤ᥽å(`)ƤӽФΥ
+ 󥿥å奬ǤȤ
+
+ * ruby.c (addpath): `-I'ץǥǥ쥯ȥ꤬ˡɲä
+ 褦ѹ
+
+Fri Jan 19 11:23:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * dln.c (load_1): N_INDRб(褿褦ʵ)
+
+Thu Jan 18 18:14:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * ruby.texi: FALSEnilʬΥȿǤ
+
+Tue Jan 16 17:39:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.96 - ȤꤢnilFALSE̤
+
+Wed Jan 10 15:31:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * re.c (reg_match): ޥåʤäͤFALSE
+
+ * object.c (rb_equal): `0 == nil'TRUEˤʤХ
+
+Tue Jan 9 00:44:58 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * nilFALSEʬΥǽѹ
+
+ * nilFALSE0ζ̤̩ˡ
+
+ * struct.c (struct_new): 0ǽɬפ̵ʤä
+
+ * object.c (inspect_i): ֥ȤΥåΥХ(Fixnumcore
+ dumpƤ)
+
+ * range.c (range_to_s): Rangeɽ
+
+ * object.c (true_inspect): TRUEɽ`TRUE'ˡ
+
+Mon Jan 8 15:02:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * numeric.c (fix_mul): divide by zero errorȯ(Сե
+ ФΥХ)
+
+ * texinfo.texѥå˴ޤ᤿
+
+Sun Dec 31 00:08:49 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_eval): `::'ǤϡΥ饹줿򻲾Ȥ
+ 褦ѹ
+
+ * string.c (Init_String): eacheach_lineᤷ
+
+Thu Dec 28 12:31:55 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * eval.c (rb_eval): caseα黻Ҥ`=~'`==='ˡ
+
+ * variable.c (rb_const_set): 饹κ(Ʊ饹
+ Բ)ٹϽФ
+
+Wed Dec 27 13:27:52 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.95c
+
+ * ext/tkutil/tkutil.c: wishäƤʤƤѥ
+ 褦ˡ
+
+ * lib/tk.rb: ĶѿPATH{wish|wish4.0}õ褦ˡ
+
+Tue Dec 26 01:03:42 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * sample/ruby-mode.el (ruby-parse-region): ɽθж
+
+ * numeric.c (fix_mul): 軻ΥСեХ르ꥺΥХ
+
+ * ext/extmk.rb.in: ./install-shȤPATHĴ
+
+ * Makefile.in (install): lib/*.rbĤĥ󥹥ȡ롥
+
+ * io.c (io_each_line): ƥ졼ͤnil졥
+
+Fri Dec 22 10:34:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
+
+ * version 0.95b
+
+ * variable.c (f_untrace_var): 2ꤹtrace
+ Ǥ褦ˡ
+
+ * variable.c (f_trace_var): 2nilλtrace롥
+
+ * lib/tk.rb (file_readable/file_writable): 2nilˤ뤳
+ ˤevent handlerκ
+
+ * parse.y (variable): ɥȤ`__FILE__'`__LINE__'Ĥä
+ `caller(0)'ѤϤäΤˡ
+
+ * eval.c (f_eval): $!Υꥻåȡ
+
+ * error.c (err_sprintf): "\n"ղäΤߤ᤿
+
+ * parse.y (f_arglist): ꥹľif/whileɤߴְ㤤
+ lex_stateͤꤵƤʤä
+
Thu Dec 21 00:56:57 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
+ * version 0.95a - ^^;;;
+
+ * lib/tkscrollbox.rb: ѥåäƤʤä
+
+ * configure.in: FILE structureΥå˥Х
+
+ * Makefile.in (clean): extʲinstallƤ
+
+ * ext/socket/extconf.rb: Solarisˤ-lnlsΥå
+
+ * array.c (beg_len): Хäġᤷ
+
* version 0.95 - fj.sources
* eval.c (rb_eval): rescueΥårb_rescue()˰층
@@ -204,8 +1970,8 @@ Fri Oct 13 13:19:19 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* string.c (str_strip_bang): ʸθĹĴԤƤ
ʤä
- * re.c (reg_search): $&, $1...Τϥ«褦ˤʤä
- ƤӽФ᥽åɤǤΥޥåϸפ$&ʤɤͤ˱ƶʤ
+ * re.c (reg_search): $&, $1...ϥ«褦ˤʤä
+ ӽФ᥽åɤǤΥޥåϸפ$&ʤɤͤ˱ƶʤ
ޥåξ򥹥׳Ȥˤ$~Ȥä«
Фɬפ롥
@@ -352,7 +2118,7 @@ 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>
+ Wed Sep 13 15:44:35 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* string.c (Fstr_tr_bang): ϰϳʸФѴХ
@@ -441,7 +2207,7 @@ Fri Aug 11 14:37:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
* io.c: ޥREAD_DATA_PENDINGѹ(Linuxб)
- * io.c (io_fptr_finalize): ftprγνǤ褦ˡ
+ * io.c (io_fptr_finalize): fptrγνǤ褦ˡ
Wed Aug 9 16:52:41 1995 Yukihiro Matsumoto <matz@caelum.co.jp>
@@ -722,8 +2488,8 @@ Thu May 18 12:27:23 1995 Yukihiro Matsumoto <matz@ix-02>
⤢ä̤Ȥtr񤭴Τǡcopyright
̵ʤä(Ȼפ)
- * gc.c (gc): the_scopeޡƤʤäΤǡѿ
- äƳ礬ä
+ * gc.c (gc): the_scopeޡƤʤäΤǡѿλ
+ Ƥ륪֥ȤְäƳ礬ä
* gc.c (mark_locations_array): 㴳ι®
@@ -789,8 +2555,8 @@ Thu Apr 20 12:31:24 1995 Yukihiro Matsumoto (matz@ix-02)
* env.h, gc.c, regex.c: IRIXؤΰܿб
- * configure: picoptionθФΤᡤƥॿפ
- 褦ˡ
+ * configure: dlopenѤpicoptionθФΤᡤƥॿ
+ פå褦ˡ
Tue Apr 18 19:08:17 1995 Yukihiro Matsumoto (matz@ix-02)
@@ -808,7 +2574,7 @@ Mon Apr 10 18:36:06 1995 Yukihiro Matsumoto (matz@ix-02)
Fri Apr 7 13:51:08 1995 Yukihiro Matsumoto (matz@ix-02)
* cons.c->assoc.c: cons;פʵǽϳpairȤƤεǽ
- ĤenumerableincludeΤ᤿
+ ĤEnumerableincludeΤ᤿
* string.c(esub): ʸִƥ졼perls///e롥
@@ -885,8 +2651,8 @@ Fri Mar 10 18:35:46 1995 Yukihiro Matsumoto (matz@ix-02)
* eval.c: MathΤ褦ʥ⥸塼ϼʬȤextend롥
- * eval.c: 饹⥸塼Ʊ̾ΤΤɲ
- Ȥʤ褦ˡsuper饹ΰ㤤ʤɤϥå롥
+ * eval.c: 饹⥸塼Ʊ̾ΤΤ
+ Ȥʤ褦ˡsuper饹ΰ㤤ʤɤϥå롥
* regex.c: debug.
@@ -933,8 +2699,8 @@ Thu Feb 23 11:19:19 1995 Yukihiro Matsumoto (matz@ix-02)
* eval.c(rb_clear_cache): åΥꥢ˺줬ä
* eval.c: Υפ򥯥饹Ūפѹ
- äơðۥ᥽åɤϻȤϡ쥷ФΥ饹Ǥ
- ʤ줿פΥ饹Ȥʤ롥
+ äơðۥ᥽åɤ黲Ȥϡ쥷ФΥ饹ǤϤ
+ 줿פΥ饹Ȥʤ롥
Wed Feb 22 00:51:38 1995 Yukihiro Matsumoto (matz@dyna)
@@ -985,8 +2751,9 @@ Fri Feb 10 16:30:00 1995 Yukihiro Matsumoto (matz@ix-02)
* ruby.c(load_file): scriptɤ߹"#!"βϤԤ褦ˡ
- * ruby.c(readin): եɤ߹߻Ƭ"#!"ꡤruby˰
- ͿƤСΰͭˤʤ롥
+ * ruby.c(readin): եɤ߹߻Ƭ"#!"ꡤιԤ
+ "ruby"Ȥʸޤruby˰ͿƤСΰ
+ ͭˤʤ롥
* parse.y(yylex): ȹԤν꤬`\'ǤäιԤ˷³
ƤȤߤʤ褦ˤ
@@ -1056,7 +2823,7 @@ Tue Jan 17 11:11:27 1995 Yukihiro Matsumoto (matz@ix-02)
Ѿ롥ǽλϺޤǤƱǥե(ȥåץ
ǴؿŪ饹̾᥽å)
- * object.c(Class::new): ֥Ȥ˴ؿŪ᥽å
+ * object.c(Class#new): ֥Ȥ˴ؿŪ᥽å
init_objectɬƤФ褦ѹ
* eval.c: ̤Υ᥽åɤФunknown᥽åɤƤФ褦
diff --git a/MANIFEST b/MANIFEST
index 81c7a3a646..3b0ba3e0d0 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -2,6 +2,7 @@ ChangeLog
MANIFEST
Makefile.in
README
+README.jp
README.EXT
ToDo
array.c
@@ -9,7 +10,9 @@ bignum.c
class.c
compar.c
configure
+configure.bat
configure.in
+config.dj
config.guess
config.sub
defines.h
@@ -47,7 +50,6 @@ regex.c
regex.h
ruby.c
ruby.h
-ruby.texi
sig.h
signal.c
sprintf.c
@@ -56,27 +58,41 @@ st.h
string.c
struct.c
time.c
+top.sed
util.h
util.c
variable.c
version.c
version.h
ext/Setup
+ext/Setup.dj
ext/extmk.rb.in
lib/base64.rb
+lib/cgi-lib.rb
+lib/complex.rb
lib/find.rb
lib/getopts.rb
+lib/jcode.rb
lib/mailread.rb
+lib/mathn.rb
+lib/observer.rb
lib/parsearg.rb
lib/parsedate.rb
+lib/rational.rb
+lib/safe.rb
+lib/thread.rb
lib/tk.rb
+lib/tkcore.rb
lib/tkcanvas.rb
+lib/tkclass.rb
lib/tkentry.rb
+lib/tkscrollbox.rb
lib/tktext.rb
-lib/tkclass.rb
+lib/tkthcore.rb
missing/alloca.c
missing/crypt.c
missing/dup2.c
+missing/flock.c
missing/memmove.c
missing/mkdir.c
missing/nt.c
@@ -93,16 +109,16 @@ sample/cbreak.rb
sample/clnt.rb
sample/dbm.rb
sample/dir.rb
-sample/evaldef.rb
+sample/eval.rb
sample/export.rb
sample/exyacc.rb
+sample/fact.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
@@ -113,12 +129,16 @@ sample/list3.rb
sample/marshal.rb
sample/mkproto.rb
sample/mpart.rb
+sample/observ.rb
sample/occur.pl
sample/occur.rb
sample/occur2.rb
+sample/philos.rb
+sample/pi.rb
sample/rcs.awk
sample/rcs.dat
sample/rcs.rb
+sample/regx.rb
sample/ruby-mode.el
sample/sieve.rb
sample/svr.rb
@@ -131,6 +151,6 @@ sample/tkfrom.rb
sample/tkhello.rb
sample/tkline.rb
sample/tktimer.rb
-sample/trojan.pl
sample/trojan.rb
+sample/tsvr.rb
sample/uumerge.rb
diff --git a/Makefile.in b/Makefile.in
index 81e3feca79..aa018968ff 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -77,30 +77,30 @@ 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
+ cd ext; ../miniruby ./extmk.rb @EXTSTATIC@; fi
$(PROGRAM): $(OBJS)
@rm -f $(PROGRAM)
$(PURIFY) $(CC) $(STATIC) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
-$(bindir)/ruby: extruby
- $(INSTALL_PROGRAM) ruby $(bindir)/ruby
- strip $(bindir)/ruby
-
-install: $(bindir)/ruby
+install:; $(INSTALL_PROGRAM) ruby $(bindir)/ruby
+ @-@STRIP@ $(bindir)/ruby
+ @test -d $(libdir) || mkdir $(libdir)
cd ext; ../miniruby ./extmk.rb install
- $(INSTALL_DATA) lib/*.rb $(libdir)
+ @for rb in `grep '^lib/' MANIFEST`; do \
+ $(INSTALL_DATA) $$rb $(libdir); \
+ done
clean:; @rm -f $(OBJS)
@rm -f ext/extinit.c ext/extinit.o
- cd ext; ../ruby ./extmk.rb install
+ cd ext; ../miniruby ./extmk.rb clean
realclean: clean
@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;\
+test:; @-./ruby sample/test.rb > ./ruby_test 2>&1; \
if grep '^end of test' ./ruby_test > /dev/null; then \
echo "test succeeded"; \
else \
@@ -122,6 +122,9 @@ crypt.o: missing/crypt.c
dup2.o: missing/dup2.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/dup2.c
+flock.o: missing/flock.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/flock.c
+
memmove.o: missing/memmove.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/memmove.c
@@ -162,22 +165,21 @@ bignum.o: bignum.c ruby.h config.h defines.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
dir.o: dir.c ruby.h config.h defines.h
-dln.o: dln.c config.h defines.h dln.h
+dln.o: dln.c config.h defines.h dln.h st.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
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 re.h regex.h
+gc.o: gc.c ruby.h config.h defines.h env.h sig.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 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
+numeric.o: numeric.c ruby.h config.h defines.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 sig.h st.h
@@ -190,7 +192,7 @@ 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
+struct.o: struct.c ruby.h config.h defines.h
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 st.h
diff --git a/README b/README
index ad239f98d2..debf3e4b1c 100644
--- a/README
+++ b/README
@@ -1,151 +1,115 @@
-* RubyȤ
+* What's Ruby
-Rubyϥץ뤫ĶϤʥ֥ȻظץȸǤ
-RubyϺǽ餫ʥ֥ȻظȤ߷פƤ
-顤֥Ȼظץߥ󥰤ڤ˹Ԥ
-̾μ³Υץߥ󥰤ǽǤ
+Ruby is the interpreted scripting language for quick and
+easy object-oriented programming. It has many features to
+process text files and to do system management tasks (as in
+perl). It is simple, straight-forward, and extensible.
-RubyϥƥȽطǽϤʤɤͥ졤perlƱ餤
-Ǥ˥ץʸˡȡ㳰䥤ƥ졼ʤɤε
-ˤäơʬ䤹ץߥ󥰤ޤ
+* Features of ruby
-* RubyĹ
+ + Simple Syntax
+ + *Normal* Object-Oriented features(ex. class, method calls)
+ + *Advanced* Object-Oriented features(ex. Mix-in, Singleton-method)
+ + Operator Overloading
+ + Exception Handling
+ + Iterators and Closures
+ + Garbage Collection
+ + Dynamic Loading of Object files(on some architecture)
+ + Highly Portable(works on many UNIX machines)
- + ץʸˡ
- + ̤Υ֥Ȼظǽ(饹᥽åɥʤ)
- + üʥ֥Ȼظǽ(Mixin, ðۥ᥽åɤʤ)
- + 黻ҥС
- + 㳰ǽ
- + ƥ졼ȥ
- + ١쥯
- + ʥߥåǥ (ƥˤ)
- + ܿ⤤¿UNIXư
+* How to get ruby
-* ˡ
+** by ftp
-** ftp
+The ruby distribution can be found on
-ʲξˤƤޤ
+ ftp://ftp.caelum.co.jp/pub/lang/ruby/
- ftp://ftp.kk.info.kanagawa-u.ac.jp/pub/languages/ruby/
+** by mail
-** ᥤ
-
-ʲΥɥ쥹`send'ȤSubjectΥᥤäƲ
+Send the mail which subject is 'send' to the address below.
ruby-archive@caelum.co.jp
-ʸˤϲ񤤤Ƥ⹽ޤޤ֤ǿǤruby
-
-* ᥤ󥰥ꥹ
-
- Ruby˴ؤΤΥᥤ󥰥ꥹȤ⤷ޤ
- ɥ쥹
-
- ruby-list@caelum.co.jp
-
- ǤΥɥ쥹˥ᥤСưŪϿޤ
-
-* ѥ롦󥹥ȡ
-
-ʲμǹԤäƤ
-
- 1. configure¹ԤMakefileʤɤ
-
- 2. (ɬפʤ)defines.hԽ
-
- ¿ʬɬ̵Ȼפޤ
-
- 3. (ɬפʤ)ext/SetupŪ˥󥯤ĥ⥸塼
- ꤹ
+You will receive the uuencoded gzipped tar file of the newest ruby
+distribution.
- ext/Setup˵Ҥ⥸塼Ū˥󥯤ޤ
+* How to compile and install
- ʥߥåǥ󥰤򥵥ݡȤƤʤƥ
- ǤSetup1ܤΡoption nodynamicפȤԤΥ
- Ȥ򳰤ɬפޤޤΥƥ
- ĥ⥸塼Ѥ뤿ˤϡ餫Ū˥
- Ƥɬפޤ
+This is what you need to do to compile and install ruby:
- 4. make¹Ԥƥѥ뤹
+ 1. Run ./configure, which will generate config.h and Makefile.
- 5. make testǥƥȤԤ
+ 2. Edit defines.h if you need. Probably this step will not need.
- test succeededפɽǤ
+ 3. Remove comment mark(#) before the module names from ext/Setup, if
+ you want to link modules statically.
- 6. make install
+ If you want to link all the extension modules, remove comment
+ mark from the line "#option nodynamic".
-⤷ѥ˥顼ȯˤϥ顼Υȥ
-OSμޤǤܤݡȤԤäƤ
-¾Τˤʤޤ
+ 4. Run make.
-* ܿ
+ 5. Optionally, run 'make test' to check that the compiled ruby
+ interpreter works well. If you see the message "test succeeded",
+ your ruby works as it should.
-UNIXǤconfigureۤȤɤκۤۼƤϤ
-פ̸Ȥä(˰㤤ʤ)Ԥˤ
-ȤݡȤСǤ뤫Τޤ
+ 6. Run 'make install'
-ƥˤäȤ¸ΤGCǤrubyGCо
-Υƥ㤬setjmp()ˤäơƤΥ쥸 jmp_buf
-˳Ǽ뤳Ȥȡjmp_bufȥå32bit饤Ȥ
-Ƥ뤳ȤꤷƤޤԤΩʤбϺ
-ˤǤ礦ԤβŪñǡgc.cǥå
-ޡƤʬ˥饤ȤΥХȿ餷ƥޡ
-륳ɤɲäǺѤߤޤdefined(THINK_C)פ
-Ƥʬ򻲹ͤˤƤ
+If you fail to compile ruby, please send the detailed error report with
+the error log and machine/OS type, to help others.
-# ºݤˤrubyThink CǥѥǤޤ
+* Copying
-sparcʳΥ쥸ɥCPUǤϡ쥸
-եå夹륳ɤɲäɬפ뤫Τޤ
+Ruby is copyrighted by Yukihiro Matsumoto <matz@caelum.co.jp>.
-* ۾
+This source is distributed under the conditions blow:
-Rubyۤ˴ؤݻԤǤ<matz@caelum.co.jp>
-ϰʲξĤޤ
+ 1. You may make and give away verbatim copies of the source form of
+ the software without restriction, provided that you do not modify
+ the original distribution file.
- +
+ If you want to distribute the modified version in any way, contact
+ the author.
- ʤŪǤ켫ͳǤǽĥХ
- ԤؤΥեɥХåԤޤ(ǤϤ
- ޤ)
+ 2. You may distribute the software in object code or executable
+ form, provided that you distribute it with instructions on where
+ to get the software.
- + ¾Υץؤΰ
+ 3. You may modify the software in any way, provided that you do not
+ distribute the modified version.
- ʤŪǤ켫ͳǤruby˴ޤޤ¾κ
- Ԥˤ륳ɤϡ줾κԤΰոˤ¤ä
- ޤŪˤgc.c()regex.[ch]fnmatch.[ch]
- glob.c, st.[ch]missingǥ쥯ȥ겼Υե뷲
- ޤ
+ 4. You may modify and include the part of the software into any other
+ software (possibly commercial). But some files in the
+ distribution are not written by the author, so that they are not
+ under this terms. They are gc.c(partly)regex.[ch]fnmatch.[ch]
+ glob.c, st.[ch] and somme files under ./missing directory. See
+ each files for the condition.
- +
+ 5. The scripts and library files supplied as input to or produced as
+ output from the software do not automatically fall under the
+ copyright of the software, but belong to whomever generated them,
+ and may be sold commercially, and may be aggregated with this
+ software.
- ֤ۤݻ¤꼫ͳǤѹԤäΤ
- ۤ뤳Ȥ˾ˤϺԤϢƤ
- ʥrubyΤ˶̤Ǥ褦ǤСۤǧ
- ˤǤ
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE.
- ѹԤʤʤruby򥳥ѥ뤷Хʥۤ϶ػ
- ޤ󤬡ѥ˵ȥ֥򸺤餹
- ˡѥξǤܤ˾
- ޤ
+* ruby home-page
- + RubyץȤθ
+ The URL of the ruby home-page is:
- ƤrubyץȤθϤ줾Ԥ°ޤ
- ԤϤ˴ؤưڤθĥޤ󡥤ޤruby
- Ȥ߹िγĥ⥸塼˴ؤƤƱͤǤ
+ http://www.caelum.co.jp/~matz/ruby/index-en.html
- + ̵ݾ
+* The Author
- Ruby̵ݾڤǤԤruby򥵥ݡȤջ֤Ϥޤ
- rubyȤΥХ뤤rubyץȤΥХʤɤȯ
- 뤤ʤ»ФƤǤޤ
+Feel free to send comments and bug reports to the author. Here is the
+author's latest mail address:
-*
+ matz@ruby.club.or.jp
-ȡХݡȤ¾ matz@caelum.co.jp ޤǡ
-------------------------------------------------------
created at: Thu Aug 3 11:57:36 JST 1995
Local variables:
diff --git a/README.EXT b/README.EXT
index efa627a24a..fdf8c96af7 100644
--- a/README.EXT
+++ b/README.EXT
@@ -1,308 +1,1029 @@
.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995
-Rubyĥ뤿ˡ⤹롥
+rubyγĥ⥸塼κޤ
+
+1μ
+
+CѿˤϷꡤǡˤϷޤ󡥤Ǥ顤
+ȤХݥ󥿤intѿȡͤȤƼ
+갷ޤդrubyѿˤϷʤǡ˷
+ΰ㤤ΤᡤCrubyߤѴʤСߤ
+ǡ򥢥Ǥޤ
+
+rubyΥǡVALUEȤCηɽޤVALUEΥǡ
+ϤΥǡפʬΤäƤޤΥǡפ
+Τϥǡ(֥)μºݤι¤̣Ƥơruby
+Υ饹ȤϤޤäΤǤ
+
+VALUECˤȤäựΤǡФˤ
+
+ (1) VALUEΥǡפΤ
+ (2) VALUECΥǡѴ
+
+ξɬפǤ(1)˺ȴְäǡѴԤ
+ơǰץबcore dumpޤ
+
+1.1 ǡ
+
+rubyˤϥ桼ȤǽΤʲΥפޤ
-RubyCɤ񤯤Ȥˤäơñ˵ǽɲäǤ롥ޤʼ
-ϰʲ̤Ǥ롥
+ T_NIL nil
+ T_OBJECT ̾Υ֥
+ T_CLASS 饹
+ T_MODULE ⥸塼
+ T_FLOAT ư
+ T_STRING ʸ
+ T_REGEXP ɽ
+ T_ARRAY
+ T_FIXNUM Fixnum(31bitĹ)
+ T_HASH Ϣ
+ T_STRUCT (ruby)¤
+ T_BIGNUM ¿Ĺ
+ T_TRUE
+ T_FALSE
+ T_DATA ǡ
- 1. եѰդ
+¾ѤƤʲΥפޤ
- extǥ쥯ȥβ˳ĥ⥸塼ѤΥǥ쥯ȥѰդơ
- ۲˰ʲΥեѰդɬפ롥
+ T_ICLASS
+ T_MATCH
+ T_VARMAP
+ T_SCOPE
+ T_NODE
- + MANIFESTɬפʥեΰ
+ĤΥפCι¤ΤǼƤޤ
- ɬɬסŪʥեʳƤΥե̾11ե
- ηǵҤ뤳ȡ
+1.2 VALUEΥǡפå
- + CΥե롥
+ruby.hǤTYPE()ȤޥƤơVALUEΥǡ
+פΤ뤳ȤޤTYPE()ޥϾǾҲ𤷤T_XXXX
+η֤ޤVALUEΥǡפ˱ƽ
+ˤϡTYPE()ͤʬ뤳Ȥˤʤޤ
- ⥸塼뤬1եʤϥ⥸塼̾Ʊ̾Υե
- ̾(⥸塼.c)Ĥ롥դ˥⥸塼뤬ʣʤ
- ⥸塼̾ΤĤե򤱤뤳ȡ
+ switch (TYPE(obj)) {
+ case T_FIXNUM:
+ /* FIXNUMν */
+ break;
+ case T_STRING:
+ /* ʸν */
+ break;
+ case T_ARRAY:
+ /* ν */
+ break;
+ default:
+ /* 㳰ȯ */
+ Fail("not valid value");
+ break;
+ }
- + extconf.rb(optional)ѥե롥
+ȥǡפåơʤ㳰ȯ
+ؿѰդƤޤ
- ؿ饤֥ꡤإå¸ߥå򤷤ꡤ⥸塼̾
- ɤꤹ롥Υե뤬̵ƥǥեȤǥѥ
- 롥
+ void Check_Type(VALUE value, int type)
- + depend(optional)Makefile˥󥯥롼ɤ뤿Υե
- ΰ¸ط򵭽Ҥե롥
+δؿvaluetype̵С㳰ȯޤ
+Ϳ줿VALUEΥǡפɤå
+뤿ˤϡδؿȤޤ
- `gcc -MM *.c > depend'ȤмưŪǤ롥
+1.3 VALUECΥǡѴ
- 2. CΥեѰդ
+ǡפT_NIL, T_FALSE, T_TRUEǤǡϤ줾
+nil, FALSE, TRUEǤΥǡפΥ֥ȤϤҤ
+ĤĤ¸ߤޤ
- ɬInit_⥸塼̾פȤؿѰդǡѿ䥯
- 䡤饹ؤΥ᥽åɤϿʤɤνԤȡ
- ؿθƤӽФϥ󥿥ץ꥿ν(Ū󥯤ξ)⥸塼
- Υɻ(ưŪ󥯤ξ)˼ưŪ˹Ԥ롥
+ǡפT_FIXNUMλ31bitΥ
+FIXNUMCѴ뤿ˤϥޥFIX2INT()פ
+ޤ줫顤FIXNUM˸¤餺rubyΥǡѴ
+NUM2INT()פȤޥޤΥޥϥǡ
+פΥå̵ǻȤޤ(ѴǤʤˤ㳰
+ȯ)
-* Ruby API
+ʳΥǡפбCι¤Τޤб
+빽¤ΤΤVALUEϤΤޤޥ㥹(Ѵ)й¤Τ
+ݥ󥿤ѴǤޤ
-C줫RubyεǽѤAPIϰʲ̤Ǥ롥
+¤Τϡstruct RXxxxxפȤ̾ruby.hƤ
+㤨ʸϡstruct RStringפǤºݤ˻Ȥǽ
+Τʸ󤯤餤Ȼפޤ
+
+ruby.hǤϹ¤Τإ㥹ȤޥRXXXXX()(ʸ
+ˤ)Ȥ̾󶡤Ƥޤ(: RSTRING())
+
+㤨СʸstrĹ뤿ˤϡRSTRING(str)->lenפ
+ʸstrchar*Ȥ뤿ˤϡRSTRING(str)->ptr
+Ȥޤξˤϡ줾RARRAT(str)->lenס
+RARRAT(str)->ptrפȤʤޤ
+
+rubyι¤Τľܥ˵ĤʤФʤʤ
+Ȥϡʸι¤ΤȤϻȤǡľѹ
+ʤȤǤľѹ硤֥ȤƤ
+Ȥʤʤäơפ̥Хθˤʤޤ
+
+1.4 CΥǡVALUEѴ
+
+VALUEμºݤι¤
+
+ * FIXNUMξ
+
+ 1bitեȤơLSBΩƤ롥
+
+ * ¾Υݥ󥿤ξ
+
+ ΤޤVALUE˥㥹Ȥ롥
+
+ȤʤäƤޤäơLSBåVALUEFIXNUM
+狼櫓Ǥ(ݥ󥿤LSBΩäƤʤȤꤷ
+)
+
+Ǥ顤FIXNUMʳrubyΥ֥Ȥι¤ΤñVALUE
+˥㥹ȤVALUEѴޤǤդι¤
+ΤVALUE˥㥹Ƚ櫓ǤϤޤ󡥥㥹Ȥ
+rubyΤäƤ빽¤(ruby.hƤstruct RXxxx
+Τ)ˤƤƤ
+
+FIXNUM˴ؤƤѴޥͳɬפޤC
+VALUEѴޥϰʲΤΤޤɬפ˱
+ƻȤʬƤ
+
+ INT2FIX() Ȥ31bit˼ޤ
+ INT2NUM() ǤդVALUE
+
+INT2NUM()FIXNUMϰϤ˼ޤʤ硤BignumѴ
+Ƥޤ(٤)
+
+1.5 rubyΥǡ
+
+Ҥ٤̤ꡤrubyι¤Τ򥢥Ƥι
+ԤȤϴޤ󡥤ǡrubyΥǡˤ
+rubyѰդƤؿѤƤ
+
+ǤϤäȤȤǤʸ/
+ؿ򤢤ޤ(ǤϤʤǤ)
+
+ ʸФؿ
+
+ str_new(char *ptr, int len)
+
+ rubyʸ롥
+
+ str_new2(char *ptr)
+
+ Cʸ󤫤rubyʸ롥δؿεǽ
+ str_new(ptr, strlen(ptr))ƱǤ롥
+
+ str_cat(VALUE str, char *ptr, int len)
+
+ rubyʸstrlenХȤʸptrɲä롥
+
+ Фؿ
+
+ ary_new()
+
+ Ǥ0롥
+
+ ary_new2(int len)
+
+ Ǥ0롥lenʬΰ򤢤餫
+ ƤƤ
+
+ ary_new3(int n, ...)
+
+ ǻꤷnǤޤ롥
+
+ ary_new4(int n, VALUE elts[])
+
+ ͿnǤ롥
+
+ ary_push(VALUE ary)
+ ary_pop(VALUE ary, VALUE val)
+ ary_shift(VALUE ary)
+ ary_unshift(VALUE ary, VALUE val)
+ ary_entry(VALUE ary, int idx)
+
+ ArrayƱ̾Υ᥽åɤƱƯ򤹤ؿ1ɬ
+ ǤʤФʤʤ
+
+2rubyεǽȤ
+
+Ūrubyǽ񤱤뤳ȤCǤ񤱤ޤrubyΤΤCǵ
+ҤƤǤ顤ȤʤǤɡ
+rubyγĥ˻ȤȤ¿ͽ¬뵡ǽ濴˾
+𤷤ޤ
+
+2.1 ruby˵ǽɲä
+
+ruby󶡤ƤؿȤruby󥿥ץ꥿˿ǽ
+ɲä뤳ȤǤޤrubyǤϰʲεǽɲäؿ
+󶡤Ƥޤ
+
+ * 饹⥸塼
+ * ᥽åɡðۥ᥽åɤʤ
+ *
+
+ǤϽ˾Ҳ𤷤ޤ
+
+2.1.1 饹/⥸塼
+
+饹⥸塼뤿ˤϡʲδؿȤޤ
+
+ VALUE rb_define_class(char *name, VALUE super)
+ VALUE rb_define_module(char *name)
+
+δؿϿ줿饹⥸塼֤ޤ
+᥽åɤˤͤɬפʤΤǡۤȤɤξ
+ͤѿ˳ǼƤɬפǤ礦
+
+2.1.2 ᥽å/ðۥ᥽å
+
+᥽åɤðۥ᥽åɤˤϰʲδؿȤޤ
+
+ void rb_define_method(VALUE class, char *name,
+ VALUE (*func)(), int argc)
+
+ void rb_define_sigleton_method(VALUE object, char *name,
+ VALUE (*func)(), int argc)
+
+
+ǰΤȡðۥ᥽åɡפȤϡΥ֥
+ȤФƤͭʥ᥽åɤǤrubyǤϤ褯Smalltalkˤ
+륯饹᥽åɤȤơ饹Фðۥ᥽åɤȤ
+
+δؿ argcȤCδؿϤο(
+)ޤargcλϴؿ˰Ϥο̣
+ޤ16İʾΰϻȤޤ(פޤ͡
+ʤ)
+
+argcλϰοǤϤʤꤷȤˤʤޤ
+argc-1λϰϤޤargc-2λϰ
+rubyȤϤޤ
+
+᥽åɤؿϤ⤦ĤޤҤȤĤprivate
+åɤؿǡrb_define_method()ƱǤ
+
+ void rb_define_private_method(VALUE class, char *name,
+ VALUE (*func)(), int argc)
+
+private᥽åɤȤϴؿǤƤӽФȤνʤ᥽
+ɤǤ
+
+⤦ҤȤĤϥ⥸塼ؿΤǤ⥸塼ؿ
+Ȥϥ⥸塼ðۥ᥽åɤǤꡤƱprivate᥽åɤ
+⤢ΤǤ򤢤Math⥸塼sqrt()ʤɤ
+ޤΥ᥽åɤ
+
+ Math.sqrt(4)
+
+ȤǤ
+
+ include Math
+ sqrt(4)
+
+ȤǤȤޤ⥸塼ؿؿϰʲ
+̤Ǥ
+
+ void rb_define_module_method(VALUE module, char *name,
+ VALUE (*func)(), int argc)
+
+2.1.3
+
+ĥ⥸塼뤬ɬפϤ餫Ƥɤ
+Ǥ礦ؿĤޤ
+
+ void rb_define_const(VALUE class, char *name, VALUE val)
+ void rb_define_global_const(char *name, VALUE val)
+
+ԤΥ饹/⥸塼°Ρ
+ԤϥХΤǤ
+
+2.2 rubyεǽCƤӽФ
+
+ˡ1.5 rubyΥǡ٤ǰҲ𤷤褦ʴؿ
+ȤСrubyεǽ¸ƤؿľܸƤӽФȤ
+
+# Τ褦ʴؿΰɽϤޤΤȤޤ󡥥
+# 뤷ʤǤ͡
+
+ʳˤrubyεǽƤӽФˡϤĤޤ
+
+2.2.1 rubyΥץeval
+
+CrubyεǽƤӽФäȤñˡȤơʸ
+Ϳ줿rubyΥץɾؿޤ
+
+ VALUE rb_eval_string(char *str)
+
+ɾϸߤδĶǹԤޤĤޤꡤߤΥѿ
+selfʤɤѤޤ
+
+2.2.2 IDޤϥܥ
+
+CʸͳrubyΥ᥽åɤƤӽФȤǤ
+ˡruby󥿥ץ꥿ǥ᥽åɤѿ̾ꤹ
+˻ȤƤIDˤĤƤޤ礦
+
+IDȤѿ̾᥽å̾ɽǤrubyǤ
+
+ :̻
+
+ǥǤޤC餳뤿ˤϴؿ
+
+ rb_intern(char *name)
+
+Ȥޤ
+
+2.2.3 CrubyΥ᥽åɤƤӽФ
+
+CʸͳrubyΥ᥽åɤƤӽФˤϰʲ
+δؿȤޤ
+
+ VALUE rb_funcall(VALUE recv, ID mid, int argc, ...)
+
+δؿϥ֥recvmidǻꤵ᥽åɤƤӽ
+
+2.2.4 ѿ/򻲾/
+
+CؿȤäƻȡǤΤϡ饹󥹥
+ѿǤѿϰΤΤCѿȤƥ
+Ǥޤѿ򻲾ȤˡϸƤޤ
+
+֥ȤΥ󥹥ѿ򻲾ȡؿϰʲ
+
+ VALUE rb_ivar_get(VALUE obj, ID id)
+ VALUE rb_ivar_get(VALUE obj, ID id, VALUE val)
+
+idrb_intern()ΤȤäƤ
+
+饹򻲾ȤˤϰʲδؿȤäƤ
+
+ VALUE rb_const_get(VALUE obj, ID id)
+
+饹򿷤뤿ˤϡ2.1.3 ٤ǾҲ
+ƤؿȤäƤ
+
+3rubyCȤξͭ
+
+Crubyδ֤ǾͭˡˤĤƲ⤷ޤ
+
+3.1 C黲ȤǤruby
+
+ʲrubyCΥ٥뤫黲ȤǤ롥
+
+ TRUE
+ FALSE
+
+͡FALSECǤ⵶Ȥߤʤ롥
+
+ Qnil
+
+C줫鸫nilס
+
+3.2 CrubyǶͭѿ
+
+CrubyѿȤäƾͭǤޤͭǤ
+ѿˤϤĤμबޤΤʤǤäȤɤȤ
+ȻפΤrb_define_variable()Ǥ
+
+ void rb_define_variable(char *name, VALUE *var)
+
+δؿrubyCȤǶͭѿޤѿ̾
+`$'ǻϤޤʤˤϼưŪɲäޤѿͤ
+ȼưŪrubyбѿͤѤޤ
+
+ޤruby¦ϹǤʤѿ⤢ޤread only
+ѿϰʲδؿޤ
+
+ void rb_define_readonly_variable(char *name, VALUE *var)
+
+ѿ¾hookĤѿǤޤhookդ
+ѿϰʲδؿѤޤ
+
+ void rb_define_hooked_variable(char *name, VALUE *var,
+ VALUE (*getter)(), VALUE (*setter)())
+
+δؿCδؿˤähookΤĤ줿ѿ
+ѿȤ줿ˤϴؿgetterѿͤåȤ
+ˤϴؿsetterƤФޤhookꤷʤgetter
+setter0ꤷƤ
+
+# gettersetter0ʤrb_define_variable()ƱƯ
+# ޤ
+
+줫顤CδؿˤäƼ¸rubyѿ
+ؿޤ
+
+ void rb_define_virtual_variable(char *name,
+ VALUE (*getter)(), VALUE (*setter)())
+
+δؿˤä줿rubyѿȤ줿ˤ
+getterѿͤåȤ줿ˤsetterƤФޤ
+
+3.3 CΥǡruby֥Ȥˤ
+
+C줿ǡ(¤)rubyΥ֥ȤȤ
+갷礬ꤨޤΤ褦ʾˤϡDataȤ
+ruby֥ȤCι¤(ؤΥݥ)򤯤ळȤruby
+֥ȤȤƼ갷褦ˤʤޤ
+
+Data֥Ȥƹ¤Τruby֥Ȥ˥ץ
+뤿ˤϡʲΥޥȤޤ
+
+ Make_Data_Struct(class, type, mark, free, sval)
+
+classϿ륤󥹥󥹤Υ饹type
+ץ벽CΥǡη(¤)ǤmarkϤι¤Τ
+rubyΥ֥ȤؤλȤ˻ȤؿǤΤ褦
+Ȥޤޤʤˤ0ꤷޤfreeϤι¤Τ⤦
+פˤʤä˸ƤФؿǤδؿ١쥯
+ƤФޤsvaltypeѿǡMake_Data_Struct
+Ȥޤ
+
+ޥMake_Data_StructData֥Ȥơ
+Ȥ֤ޤ
+
+ΥޥƤӽФsval˹¤Τmalloc()졤
+Ĥι¤Τ򥫥ץ벽Data֥Ȥ󥹥
+ѿȤobj˥åȤޤ
+
+Data֥ȤCݥ󥿤ФˤϰʲΥޥ
+Ȥޤ
+
+ Get_Data_Struct(obj, type, sval)
+
+Data֥ȤtypeCݥ󥿤Фơsval
+
+DataλȤϤäʬˤΤǡ
+򻲾ȤƤ
+
+4 - dbmѥå
+
+ޤǤǤȤꤢĥ⥸塼ϺϤǤ
+rubyextǥ쥯ȥˤǤ˴ޤޤƤdbm⥸塼
+ʳŪޤ
+
+(1) ǥ쥯ȥ
+
+ % mkdir ext/dbm
+
+rubyŸǥ쥯ȥβextǥ쥯ȥ˳ĥ
+塼ѤΥǥ쥯ȥޤ̾Ŭǹ
+
+
+(2) MANIFESTե
+
+ % cd ext/dbm
+ % touch MANIFEST
+
+ĥ⥸塼Υǥ쥯ȥβˤMANIFESTȤե뤬
+ɬפʤΤǡȤꤢΥեäƤޤǤ
+եˤɬפʥե뤳Ȥˤʤޤ
+
+MANIFESTȤեϡmakeλ˥ǥ쥯ȥ꤬ĥ⥸塼
+ޤǤ뤫ɤȽꤹ뤿˻ȤƤޤ
+
+(3) ߷פ
+
+ޤʤǤɡɤǽ¸뤫ɤޤ
+פɬפޤɤʥ饹Ĥ뤫Υ饹ˤ
+ɤʥ᥽åɤ뤫饹󶡤ʤɤˤĤ߷
+ޤdbm饹ˤĤƤext/dbm.doc򻲾ȤƤ
+
+(4) Cɤ
+
+ĥ⥸塼ΤȤʤCΥ񤭤ޤCΥ
+ҤȤĤλˤϡ֥⥸塼̾.cפ֤ɤǤ礦C
+Υʣξˤϵդˡ֥⥸塼̾.cפȤե
+̾򤱤ɬפޤ֥ȥեȥ⥸塼
+Ū֥⥸塼̾.oפȤե
+Ȥͤ뤫Ǥ
+
+rubyϳĥ⥸塼ɤˡInit_⥸塼̾פ
+ؿưŪ˼¹Ԥޤdbm⥸塼ξInit_dbm
+Ǥδؿǥ饹⥸塼롤᥽åɡʤɤ
+Ԥޤdbm.cѤޤ
+
+--
+Init_dbm()
+{
+ /* DBM饹 */
+ cDBM = rb_define_class("DBM", cObject);
+ /* DBMEnumerate⥸塼򥤥󥯥롼ɤ */
+ rb_include_module(cDBM, mEnumerable);
+
+ /* DBM饹Υ饹᥽åopen(): CǼ */
+ rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
+
+ /* DBM饹Υ᥽åclose(): Ϥʤ */
+ rb_define_method(cDBM, "close", fdbm_close, 0);
+ /* DBM饹Υ᥽å[]: 1 */
+ rb_define_method(cDBM, "[]", fdbm_fetch, 1);
+ :
+}
+--
+
+DBM⥸塼dbmΥǡб륪֥ȤˤʤϤ
+顤Cdbmruby˼ɬפޤ
+
+dbm.cǤDBMΥǡǼ뤿˰ʲΤ褦ʹ¤ΤȤ
+Ƥޤ
+
+struct dbmdata {
+ int di_size;
+ DBM *di_dbm;
+};
+
+RubyDBM֥Ȥ뤿ˤϰʲΤ褦ʥɤ
+ȤäƤޤ
+
+ obj = Make_Data_Struct(class,struct dbmdata,0,free_dbm,dbmp);
+ dbmp->di_dbm = dbm;
+ dbmp->di_size = -1;
+
+DBM֥ȤCDBMݥ󥿤ФˤϰʲΤ
+ʥޥȤäƤޤ
+
+#define GetDBM(obj, dbmp) {\
+ Get_Data_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp->di_dbm == 0) closeddbm();\
+}
+
+DBM饹ˤϤ᥽åɤޤʬह3
+μޤҤȤĤϰοΤΤǡ
+Ƥdelete᥽åɤޤdelete᥽åɤƤ
+fdbm_delete()ϤΤ褦ˤʤäƤޤ
+
+--
+static VALUE
+fdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ :
+}
+--
+
+οΥפ1self2ʹߤ᥽å
+ΰȤʤޤ
+
+οΤΤCǼΤrubyǼ
+ΤȤޤdbm⥸塼ǡCǼ
+DBMΥ饹᥽åɤǤopen()ǤƤ
+fdbm_s_open()ϤʤäƤޤ
+
+--
+static VALUE
+fdbm_s_open(argc, argv, class)
+ int argc;
+ VALUE *argv;
+ VALUE class;
+{
+ :
+ if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
+ mode = 0666; /* default value */
+ }
+ :
+}
+--
+
+Υפδؿ1Ϳ줿ο2Ϳ
+줿äƤˤʤޤself3ȤͿ
+
+Ϳ줿Ϥ뤿δؿopen()ǤȤ
+Ƥrb_scan_args()Ǥ3˻ꤷեޥåȤ
+4ѿʹߤ˻ꤷѿͤƤޤ
+եޥåȤϡ1ʸܤάǤʤο2ʸܤ
+άǤο3ʸܤб̵꤬ޤΰ
+뤫ɤ򼨤"*"Ǥ2ʸܤ3ʸܤϾάǤ
+dbm.cǤϡեޥåȤ"11"Ǥ顤Ϻ1
+ǡ2ĤޤǵȤ̣ˤʤޤάƤ
+ѿͤnil(CΥ٥ǤQnil)ˤʤޤ
+
+rubyǰΤindexesޤϤ
+
+--
+static VALUE
+fdbm_indexes(obj, args)
+ VALUE obj;
+ struct RArray *args;
+{
+ :
+}
+--
+
+1self2rubyǤǤϥ㥹Ȥ
+餹 struct RArray* ǼƤޤVALUEǤƱ
+
+** ջ
+
+rubyȶͭϤʤrubyΥ֥ȤǼǽΤ
+CѿϰʲδؿȤäruby󥿥ץ꥿ѿ¸
+򶵤ƤƤǤʤGCǥȥ֥򵯤ǽ
+
+ void rb_global_variable(VALUE *var)
+
+(5) extconf.rbѰդ
+
+⤷ǥ쥯ȥˡextconf.rbפȤե뤬¸ߤС
+make˼¹ԤޤʤŬMakefileޤ
+
+extconf.rbϥ⥸塼ΥѥɬפʾΥåʤ
+ԤȤŪǤextconf.rbǤϰʲrubyؿȤ
+Ȥޤ
+
+ have_library(lib, func): 饤֥¸ߥå
+ have_func(func): ؿ¸ߥå
+ have_header(header): إåե¸ߥå
+ create_makefile(target): Makefile
+
+⥸塼򥳥ѥ뤹郎·ʤΥ⥸塼ϥ
+ѥ뤷ʤˤcreate_makefileƤФʤɤ
+
+(6) dependѰդ
+
+⤷ǥ쥯ȥdependȤե뤬¸ߤС
+Makefile¸طåƤޤ
+
+ % gcc -MM *.c > depend
+
+ʤɤǺ뤳Ȥޤä»̵Ǥ礦
+
+(7) MANIFESTե˥ե̾
+
+ % ls > MANIFEST
+ % vi MANIFEST
+
+*.o, *~ʤɬפʥեʳMANIFESTɲäƤޤ
+makeˤMANIFESTƤϻȤޤΤǡΤޤޤǤ
+ϵʤǤɡѥå󥰤λ˻Ȥ뤳Ȥ
+ɬפʥե̤ǤǡѰդƤɤ
+礦
+
+(8) make
+
+rubyΥǥ쥯ȥmake¹ԤMakefileƤ
+Makefileгĥ⥸塼Υǥ쥯ȥ
+make뤳ȤǤޤextconf.rb񤭴ʤɤ
+MakefileκɬפʻϤޤrubyǥ쥯ȥmakeƤ
+
+
+(9) ǥХå
+
+ޤǥХåʤưʤǤ礦͡ext/Setup˥ǥ
+ȥ̾񤯤Ū˥󥯤ΤǥǥХåȤ褦ˤ
+ޤʬѥ뤬٤ʤޤɡ
+
+(10) Ǥ
+
+ϤäȤʤꡤʤꡤʤꡤͳˤ
+ȤrubyκԤϳĥ⥸塼˴ؤưڤθ
+ĥޤ
+
+Appendix A. rubyΥɤʬ
+
+rubyΥϤĤʬह뤳ȤޤΤ
+饤֥ʬϴŪ˳ĥ⥸塼Ʊˤʤ
+ƤޤΥϺޤǤǤۤȤǤ
+פޤ
+
+rubyΥ
+
+ class.c
+ error.c
+ eval.c
+ gc.c
+ object.c
+ parse.y
+ variable.c
+
+桼ƥƥؿ
+
+ dln.c
+ fnmatch.c
+ glob.c
+ regex.c
+ st.c
+ util.c
+
+rubyޥɤμ
+
+ dmyext.c
+ inits.c
+ main.c
+ ruby.c
+ version.c
+
+饹饤֥
+
+ array.c
+ bignum.c
+ compar.c
+ dir.c
+ enum.c
+ file.c
+ hash.c
+ io.c
+ math.c
+ numeric.c
+ pack.c
+ process.c
+ random.c
+ range.c
+ re.c
+ signal.c
+ sprintf.c
+ string.c
+ struct.c
+ time.c
+
+Appendix B. ĥѴؿե
+
+C줫rubyεǽѤAPIϰʲ̤Ǥ롥
**
VALUE
- Ruby֥Ȥɽ뷿ɬפ˱ƥ㥹ȤѤ롥Ȥ
- ߷ɽCηruby.h˵ҤƤRǻϤޤ빽¤ΤǤ롥
- VALUE򤳤˥㥹Ȥ뤿RǻϤޤ빽¤̾ʸ
- ̾ΥޥѰդƤ롥
+ruby֥Ȥɽ뷿ɬפ˱ƥ㥹ȤѤ롥
+Ȥ߹߷ɽCηruby.h˵ҤƤRǻϤޤ빽¤
+ΤǤ롥VALUE򤳤˥㥹Ȥ뤿RǻϤޤ빽¤
+̾ʸˤ̾ΥޥѰդƤ롥
** ѿ
Qnil
- : nil֥
-
- Qself
-
- ѿ: ߤself֥Ȥ̤͡˥᥽åɤˤselfؤ
- ͿΤ, ѿ˥ɬפϤʤѿͤ
- ѹϰʸselfͤΤΤѤäƤޤΤ, ̤ʻ
- ʤ¤ƤϤʤʤ
+: nil֥
TRUE
- : t֥(Υǥե)
+: TRUE֥(Υǥե)
FALSE
- : nil֥
+: FALSE֥
** CǡΥץ벽
VALUE data_new(void *sval, void (*mark)(), void (*free)())
- CǤդΥݥ󥿤򥫥ץ벽ruby֥Ȥ֤Υݥ
- ruby饢ʤʤäfreeǻꤷؿƤФ롥
- ޤΥݥ󥿤λؤǡ¾ruby֥ȤؤƤ
- 硤mark˻ꤹؿǥޡɬפ롥
+CǤդΥݥ󥿤򥫥ץ벽ruby֥Ȥ֤
+Υݥ󥿤ruby饢ʤʤäfreeǻꤷ
+ؿƤФ롥ޤΥݥ󥿤λؤǡ¾ruby
+ȤؤƤ硤mark˻ꤹؿǥޡɬ
+롥
Make_Data_Struct(obj, iv, type, mark, free, sval)
- typeΥmallocѿsval塤򥫥ץ벽
- ǡobjΥ󥹥ѿivޥ
+typeΥmallocѿsval塤򥫥ץ
+벽ǡobjΥ󥹥ѿivޥ
Get_Data_Struct(obj, iv, type, sval)
- objΥ󥹥ѿivؤǡtypeΥݥ󥿤Ф
- ѿsvalޥ
+objΥ󥹥ѿivؤǡtypeΥݥ󥿤
+Фѿsvalޥ
** 饹/⥸塼
VALUE rb_define_class(char *name, VALUE super)
- superΥ֥饹ȤƿRuby饹롥
+superΥ֥饹Ȥƿruby饹롥
+
+ VALUE rb_define_class_under(VALUE module, char *name, VALUE super)
+
+superΥ֥饹Ȥƿruby饹module
+Ȥ롥
VALUE rb_define_module(char *name)
- Ruby⥸塼롥
+ruby⥸塼롥
+
+ VALUE rb_define_module_under(VALUE module, char *name, VALUE super)
+
+ruby⥸塼moduleȤ롥
void rb_include_module(VALUE class, VALUE module)
- ⥸塼򥤥󥯥롼ɤ롥classǤmodule򥤥󥯥롼ɤ
- ˤϲ⤷ʤ(¿ť󥯥롼ɤζػ)
+⥸塼򥤥󥯥롼ɤ롥classǤmodule򥤥󥯥롼
+ɤƤˤϲ⤷ʤ(¿ť󥯥롼ɤζػ)
void rb_extend_object(VALUE object, VALUE module)
- ֥Ȥ⥸塼(Ƥ᥽å)dzĥ롥
+֥Ȥ⥸塼(Ƥ᥽å)dzĥ롥
** ѿ
void rb_define_variable(char *name, VALUE *var)
- RubyCȤǶͭ륰Хѿ롥ѿ̾`$'ǻϤޤ
- ˤϼưŪɲä롥nameȤrubyμ̻ҤȤƵʤ
- ʸ(㤨` ')ޤˤrubyץफϸʤʤ롥
+rubyCȤǶͭ륰Хѿ롥ѿ̾`$'ǻ
+ޤʤˤϼưŪɲä롥nameȤrubyμ̻ҤȤ
+Ƶʤʸ(㤨` ')ޤˤrubyץफ
+ϸʤʤ롥
void rb_define_readonly_variable(char *name, VALUE *var)
- RubyCȤǶͭread onlyΥХѿ롥read only
- 뤳Ȱʳrb_define_variable()Ʊ
+rubyCȤǶͭread onlyΥХѿ롥read
+onlyǤ뤳Ȱʳrb_define_variable()Ʊ
void rb_define_virtual_variable(char *name,
VALUE (*getter)(), VALUE (*setter)())
- ؿˤäƼ¸Rubyѿ롥ѿȤ줿ˤ
- getterؿͤåȤ줿ˤsetterƤФ롥
+ؿˤäƼ¸rubyѿ롥ѿȤ줿
+ˤgetterѿͤåȤ줿ˤsetterƤФ롥
void rb_define_hooked_variable(char *name, VALUE *var,
VALUE (*getter)(), VALUE (*setter)())
- ؿˤähookΤĤ줿Хѿ롥ѿȤ
- 줿ˤgetterؿͤåȤ줿ˤsetterƤФ롥
- gettersetter0ꤷˤhookꤷʤΤƱˤʤ롥
+ؿˤähookΤĤ줿Хѿ롥ѿ
+Ȥ줿ˤgetterؿͤåȤ줿ˤsetter
+ƤФ롥gettersetter0ꤷˤhookꤷ
+ΤƱˤʤ롥
void rb_global_variable(VALUE *var)
- GCΤᡤRubyץफϥʤ, Ruby֥
- ޤѿޡ롥
+GCΤᡤrubyץफϥʤ, ruby֥
+Ȥޤѿޡ롥
** 饹
void rb_define_const(VALUE class, char *name, VALUE val)
- 饹롥
+饹롥
+
+ void rb_define_global_const(char *name, VALUE val)
+
+롥
+
+ rb_define_const(cKernal, name, 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)ȤͿ롥
+᥽åɤ롥argcselfοargc-1λ,
+ؿˤϰο(selfޤޤʤ)1, 2
+ȤͿ(3self)argc-2λ, 1
+self, 2args(argsϰޤruby)Ȥ
+Ϳ롥
rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc)
- private᥽åɤ롥rb_define_method()Ʊ
+private᥽åɤ롥rb_define_method()Ʊ
rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc)
- ðۥ᥽åɤ롥rb_define_method()Ʊ
+ðۥ᥽åɤ롥rb_define_method()Ʊ
rb_scan_args(int atgc, VALUE *argv, char *fmt, ...)
- argc,argvͿ줿ʬ򤹤롥fmtɬܰο, ղð
- ο, Ĥΰ뤫ꤹʸ, "*"Ȥ
- Ǥ롥 2 ܤο"*"Ϥ줾άǽǤ롥ɬܰ
- ʤ0ꤹ롥3ʹߤѿؤΥݥ󥿤,
- Ǥѿ˳Ǽ롥ղðбͿƤ
- ѿQnil롥
+argc,argvͿ줿ʬ򤹤롥fmtɬܰο,
+ղðο, Ĥΰ뤫ꤹʸ, "
+*"ȤǤ롥 2 ܤο"*"Ϥ줾άǽ
+롥ɬܰĤʤ0ꤹ롥3ʹߤ
+ؤΥݥ󥿤, Ǥѿ˳Ǽ롥ղð
+бͿƤʤѿQnil
+롥
-** Ruby᥽åɸƤӽФ
+** ruby᥽åɸƤӽФ
VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)
- ᥽åɸƤӽФʸ󤫤mid뤿ˤrb_intern()Ȥ
+᥽åɸƤӽФʸ󤫤mid뤿ˤrb_intern()Ȥ
VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
- ᥽åɸƤӽФargc,argvϤ
+᥽åɸƤӽФargc,argvϤ
VALUE rb_eval_string(char *str)
- ʸrubyȥץȤƥѥ롦¹Ԥ롥
+ʸrubyȥץȤƥѥ롦¹Ԥ롥
ID rb_intern(char *name)
- ʸбID֤
+ʸбID֤
char *rb_id2name(ID id)
- IDбʸ֤(ǥХå)
+IDбʸ֤(ǥХå)
char *rb_class2name(VALUE class)
- class֤̾(ǥХå)class̾ʤˤ, ֶ
- ̾ĥ饹֤̾
+class֤̾(ǥХå)class̾ʤˤ,
+̤ä̾ĥ饹֤̾
** 󥹥ѿ
VALUE rb_iv_get(VALUE obj, char *name)
- objΥ󥹥ѿͤ롥`@'ǻϤޤʤ󥹥ѿ
- Rubyץफ饢Ǥʤֱ줿ץ󥹥ѿˤʤ롥
+objΥ󥹥ѿͤ롥`@'ǻϤޤʤ󥹥
+ѿ rubyץफ饢Ǥʤֱ줿ץ󥹥
+ѿˤʤ롥
VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
- objΥ󥹥ѿval˥åȤ롥
+objΥ󥹥ѿval˥åȤ롥
** 湽¤
VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
- func2֥åȤꤷ, func1򥤥ƥ졼ȤƸƤ֡ func1
- arg1ȤϤ, func2ˤ1˥ƥ졼Ϳ
- , 2arg2Ϥ롥
+func2֥åȤꤷ, func1򥤥ƥ졼ȤƸƤ֡
+func1ˤ arg1ȤϤ, func2ˤ1˥ƥ졼
+Ϳ줿, 2arg2Ϥ롥
VALUE rb_yield(VALUE val)
- valͤȤƥƥ졼֥åƤӽФ
+valͤȤƥƥ졼֥åƤӽФ
VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
- ؿfunc1arg1˸ƤӽФfunc1μ¹㳰ȯ
- func2arg2ȤƸƤ֡ͤ㳰ȯʤä
- func1, 㳰ȯˤfunc2ͤǤ롥
+ؿfunc1arg1˸ƤӽФfunc1μ¹㳰ȯ
+ˤ func2arg2ȤƸƤ֡ͤ㳰ȯ
+äfunc1, 㳰ȯˤfunc2ͤ
+롥
VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)
- ؿfunc1arg1ȤƼ¹Ԥ, ¹Խλ(Ȥ㳰ȯ
- ) func2arg2ȤƼ¹Ԥ롥ͤfunc1ͤǤ(
- ȯʤ)
+ؿfunc1arg1ȤƼ¹Ԥ, ¹Խλ(Ȥ㳰ȯ
+Ƥ) func2arg2ȤƼ¹Ԥ롥ͤfunc1
+ͤǤ(㳰ȯʤ)
** 㳰顼
void Warning(char *fmt, ...)
- verboseɸ२顼Ϥ˷ٹɽ롥printf()Ʊ
+verboseɸ२顼Ϥ˷ٹɽ롥printf()Ʊ
void Fail(char *fmt, ...)
- 㳰ȯ롥printf()Ʊ
+㳰ȯ롥printf()Ʊ
void Fatal(char *fmt, ...)
- ̿Ū㳰ȯ롥̾㳰ϹԤʤ줺, 󥿡ץ꥿
- λ(ensureǻꤵ줿ɤϽλ˼¹Ԥ)
+̿Ū㳰ȯ롥̾㳰ϹԤʤ줺, 󥿡
+ץ꥿λ(ensureǻꤵ줿ɤϽλ˼
+Ԥ)
void Bug(char *fmt, ...)
- 󥿡ץ꥿ʤɥץΥХǤȯϤΤʤλ
- Ƥ֡󥿡ץ꥿ϥפľ˽λ롥㳰ϰڹ
- ʤʤ
+󥿡ץ꥿ʤɥץΥХǤȯϤΤʤ
+λƤ֡󥿡ץ꥿ϥפľ˽λ롥㳰
+ϰڹԤʤʤ
** rubyν¹
-Ruby򥢥ץꥱˤϰʲΥ󥿥եȤ
-γĥ⥸塼ˤɬפʤ
+ruby򥢥ץꥱˤϰʲΥ󥿥ե
+Ȥ̾γĥ⥸塼ˤɬפʤ
void ruby_init(int argc, char **argv, char **envp)
- ruby󥿥ץ꥿νԤʤ
+ruby󥿥ץ꥿νԤʤ
void ruby_run()
- ruby󥿥ץ꥿¹Ԥ롥
+ruby󥿥ץ꥿¹Ԥ롥
void ruby_script(char *name)
- rubyΥץ̾($0)ꤹ롥
+rubyΥץ̾($0)ꤹ롥
-* extconf.rbε
+Appendix B. extconf.rbǻȤؿ
-ĥ⥸塼Υǥ쥯ȥ`extconf.rb'Ȥե뤬¸ߤ
-ϡ줬¹Ԥ졤⥸塼ΥѥɬפʾΥåʤɤ
-Ԥ롥extconf.rbǤϰʲδؿȤǤ롥
+extconf.rbǤѲǽʥѥåδؿϰ
+̤Ǥ롥
have_library(lib, func)
- ؿfuncƤ饤֥lib¸ߤå롥饤֥
- ¸ߤTRUE֤
+ؿfuncƤ饤֥lib¸ߤå롥
+֥꤬¸ߤTRUE֤
have_func(func)
- ؿfunc¸ߤå롥funcɸǤϥ󥯤ʤ饤֥
- ΤΤǤˤhave_libraryǤΥ饤֥å
- Ƥؿ¸ߤTRUE֤
+ؿfunc¸ߤå롥funcɸǤϥ󥯤ʤ
+֥ΤΤǤˤhave_libraryǤΥ饤֥
+åƤؿ¸ߤTRUE֤
have_header(header)
- إåե¸ߤå롥إåե뤬¸ߤTRUE
- ֤
+إåե¸ߤå롥إåե뤬¸ߤ
+TRUE֤
create_makefile(target)
- ĥ⥸塼ѤMakefile롥δؿƤФʤФΥ
- 塼ϥѥ뤵ʤ
+ĥ⥸塼ѤMakefile롥δؿƤФʤ
+Υ⥸塼ϥѥ뤵ʤtargetϥ⥸塼̾ɽ
+
/*
* Local variables:
- * fill-column: 70
+ * fill-column: 60
* end:
*/
diff --git a/README.jp b/README.jp
new file mode 100644
index 0000000000..06c0832b10
--- /dev/null
+++ b/README.jp
@@ -0,0 +1,159 @@
+* RubyȤ
+
+Rubyϥץ뤫ĶϤʥ֥ȻظץȸǤ
+RubyϺǽ餫ʥ֥ȻظȤ߷פƤ
+顤֥Ȼظץߥ󥰤ڤ˹Ԥ
+̾μ³Υץߥ󥰤ǽǤ
+
+RubyϥƥȽطǽϤʤɤͥ졤perlƱ餤
+Ǥ˥ץʸˡȡ㳰䥤ƥ졼ʤɤε
+ˤäơʬ䤹ץߥ󥰤ޤ
+
+* RubyĹ
+
+ + ץʸˡ
+ + ̤Υ֥Ȼظǽ(饹᥽åɥʤ)
+ + üʥ֥Ȼظǽ(Mixin, ðۥ᥽åɤʤ)
+ + 黻ҥС
+ + 㳰ǽ
+ + ƥ졼ȥ
+ + ١쥯
+ + ʥߥåǥ (ƥˤ)
+ + ܿ⤤¿UNIXư
+
+* ˡ
+
+** ftp
+
+ʲξˤƤޤ
+
+ ftp://ftp.caelum.co.jp/pub/lang/ruby/
+
+** ᥤ
+
+ʲΥɥ쥹`send'ȤSubjectΥᥤäƲ
+
+ ruby-archive@caelum.co.jp
+
+ʸˤϲ񤤤Ƥ⹽ޤޤ֤ǿǤruby
+
+* ۡڡ
+
+ RubyΥۡڡURL
+
+ http://www.caelum.co.jp/~matz/ruby/
+
+ Ǥ
+
+* ᥤ󥰥ꥹ
+
+ Ruby˴ؤΤΥᥤ󥰥ꥹȤߤޤ
+ ɥ쥹
+
+ ruby-list@caelum.co.jp
+
+ ǤΥɥ쥹˥ᥤСưŪϿޤ
+
+* ѥ롦󥹥ȡ
+
+ʲμǹԤäƤ
+
+ 1. configure¹ԤMakefileʤɤ
+
+ 2. (ɬפʤ)defines.hԽ
+
+ ¿ʬɬ̵Ȼפޤ
+
+ 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ǤϥѥǤޤ
+
+쥸ɥCPUǤϡ쥸ɥ򥹥
+˥եå夹륢֥饳ɤɲäɬפ뤫
+
+* ۾
+
+ԤϰʲξΤȤrubyۤޤ
+
+ +
+
+ ֤ۤݻ¤꼫ͳǤѹԤäΤ
+ ۤ뤳Ȥ˾ˤϺԤϢƤ
+
+ ѹԤʤʤruby򥳥ѥ뤷Хʥۤ϶ػ
+ ޤ󤬡ХʥäͤǤ
+ ˡˡƤ
+
+ + ѹ
+
+ ۤԤʤ¤ꡤʤŪǤ켫ͳǤ
+ ǽĥХϺԤؤΥեɥХåԤޤ
+ (ǤϤޤ)
+
+ + ¾Υץؤΰ
+
+ ʤŪǤ켫ͳǤruby˴ޤޤ¾κ
+ Ԥˤ륳ɤϡ줾κԤΰոˤ¤ä
+ ޤŪˤgc.c()regex.[ch]fnmatch.[ch]
+ glob.c, st.[ch]missingǥ쥯ȥ겼Υե뷲
+ ޤ
+
+ + RubyץȤθ
+
+ ƤrubyץȤθϤ줾Ԥ°ޤ
+ ԤϤ˴ؤưڤθĥޤ󡥤ޤruby
+ Ȥ߹िγĥ⥸塼˴ؤƤƱͤǤ
+
+ + ̵ݾ
+
+ Ruby̵ݾڤǤԤruby򥵥ݡȤջ֤Ϥޤ
+ rubyȤΥХ뤤rubyץȤΥХʤɤȯ
+ 뤤ʤ»ФƤǤޤ
+
+*
+
+ȡХݡȤ¾ matz@ruby.club.or.jp ޤǡ
+-------------------------------------------------------
+created at: Thu Aug 3 11:57:36 JST 1995
+Local variables:
+mode: indented-text
+end:
diff --git a/ToDo b/ToDo
index 5322a83b25..c39e13625d 100644
--- a/ToDo
+++ b/ToDo
@@ -1,9 +1,7 @@
-* threadб
-* Hand written parser(recursive decent)
-* 饹饤֥θľ(UNIX¸򸺤餹)
+* """..."""%Q#...#ΤɤĤ뤤ξ褫
+* ѥåޤѿΥ
* formatǽ
* here document
* perlΤ褦setuid check
* write debugger for ruby
-* re-write regex code for speed
-* byte code interpretor
+* re-write regex code for speed and copyright
diff --git a/array.c b/array.c
index 91f7aace9f..040a18403c 100644
--- a/array.c
+++ b/array.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:18 $
created at: Fri Aug 6 09:46:12 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -18,6 +18,16 @@ VALUE rb_to_a();
#define ARY_DEFAULT_SIZE 16
+void
+memclear(mem, size)
+ VALUE *mem;
+ int size;
+{
+ while (size--) {
+ *mem++ = Qnil;
+ }
+}
+
VALUE
ary_new2(len)
int len;
@@ -29,8 +39,10 @@ ary_new2(len)
ary->capa = len;
if (len == 0)
ary->ptr = 0;
- else
+ else {
ary->ptr = ALLOC_N(VALUE, len);
+ memclear(ary->ptr, len);
+ }
return (VALUE)ary;
}
@@ -53,7 +65,7 @@ ary_new3(n, va_alist)
int i;
if (n < 0) {
- Fail("Negative number of items(%d)", n);
+ IndexError("Negative number of items(%d)", n);
}
ary = (struct RArray*)ary_new2(n<ARY_DEFAULT_SIZE?ARY_DEFAULT_SIZE:n);
@@ -96,15 +108,20 @@ assoc_new(car, cdr)
}
static VALUE
-ary_s_new(class)
+ary_s_new(argc, argv, class)
+ int argc;
+ VALUE *argv;
VALUE class;
{
+ VALUE size;
NEWOBJ(ary, struct RArray);
OBJSETUP(ary, class, T_ARRAY);
+ rb_scan_args(argc, argv, "01", &size);
ary->len = 0;
- ary->capa = ARY_DEFAULT_SIZE;
- ary->ptr = ALLOC_N(VALUE, ARY_DEFAULT_SIZE);
+ ary->capa = NIL_P(size)?ARY_DEFAULT_SIZE:NUM2INT(size);
+ ary->ptr = ALLOC_N(VALUE, ary->capa);
+ memclear(ary->ptr, ary->capa);
return (VALUE)ary;
}
@@ -138,7 +155,7 @@ astore(ary, idx, val)
VALUE val;
{
if (idx < 0) {
- Fail("negative index for array");
+ IndexError("negative index for array");
}
if (idx >= ary->capa) {
@@ -146,7 +163,7 @@ astore(ary, idx, val)
REALLOC_N(ary->ptr, VALUE, ary->capa);
}
if (idx > ary->len) {
- MEMZERO(ary->ptr+ary->len, VALUE, idx-ary->len+1);
+ memclear(ary->ptr+ary->len, idx-ary->len+1);
}
if (idx >= ary->len) {
@@ -165,11 +182,14 @@ ary_push(ary, item)
}
static VALUE
-ary_append(ary, item)
+ary_push_method(argc, argv, ary)
+ int argc;
+ VALUE *argv;
struct RArray *ary;
- VALUE item;
{
- astore(ary, ary->len, item);
+ while (argc--) {
+ astore(ary, ary->len, *argv++);
+ }
return (VALUE)ary;
}
@@ -178,6 +198,10 @@ ary_pop(ary)
struct RArray *ary;
{
if (ary->len == 0) return Qnil;
+ if (ary->len * 10 < ary->capa && ary->capa > ARY_DEFAULT_SIZE) {
+ ary->capa = ary->len * 2;
+ REALLOC_N(ary->ptr, VALUE, ary->capa);
+ }
return ary->ptr[--ary->len];
}
@@ -194,6 +218,10 @@ ary_shift(ary)
/* sliding items */
MEMMOVE(ary->ptr, ary->ptr+1, VALUE, ary->len);
+ if (ary->len * 10 < ary->capa && ary->capa > ARY_DEFAULT_SIZE) {
+ ary->capa = ary->len * 2;
+ REALLOC_N(ary->ptr, VALUE, ary->capa);
+ }
return top;
}
@@ -215,6 +243,18 @@ ary_unshift(ary, item)
return ary->ptr[0] = item;
}
+static VALUE
+ary_unshift_method(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ while (argc--) {
+ ary_unshift(ary, argv[argc]);
+ }
+ return (VALUE)ary;
+}
+
VALUE
ary_entry(ary, offset)
struct RArray *ary;
@@ -244,10 +284,10 @@ ary_subseq(ary, beg, len)
if (beg < 0) beg = 0;
}
if (len < 0) {
- Fail("negative length for sub-array(size: %d)", ary->len);
+ IndexError("negative length %d", ary->len);
}
if (len == 0) {
- return ary_new();
+ return ary_new2(0);
}
if (beg + len > ary->len) {
len = ary->len - beg;
@@ -270,6 +310,10 @@ beg_len(range, begp, lenp, len)
if (!range_beg_end(range, &beg, &end)) return FALSE;
+ if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
+ IndexError("end smaller than beg [%d..%d]", beg, end);
+ }
+
if (beg < 0) {
beg = len + beg;
if (beg < 0) beg = 0;
@@ -281,10 +325,10 @@ beg_len(range, begp, lenp, len)
else {
if (end < 0) {
end = len + end;
- if (end < 0) end = 0;
+ if (end < 0) end = -1;
}
- if (len < end) end = len;
- if (beg < end) {
+ if (end > len) end = len;
+ if (beg > end) {
*lenp = 0;
}
else {
@@ -301,10 +345,9 @@ ary_aref(argc, argv, ary)
struct RArray *ary;
{
VALUE arg1, arg2;
+ int beg, len;
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
- int beg, len;
-
beg = NUM2INT(arg1);
len = NUM2INT(arg2);
if (len <= 0) {
@@ -315,17 +358,17 @@ ary_aref(argc, argv, ary)
/* special case - speeding up */
if (FIXNUM_P(arg1)) {
- return ary_entry(ary, NUM2INT(arg1));
+ return ary_entry(ary, FIX2INT(arg1));
}
-
- /* check if idx is Range */
- {
- int beg, len;
-
+ else {
+ /* check if idx is Range */
if (beg_len(arg1, &beg, &len, ary->len)) {
return ary_subseq(ary, beg, len);
}
}
+ if (TYPE(arg1) == T_BIGNUM) {
+ IndexError("index too big");
+ }
return ary_entry(ary, NUM2INT(arg1));
}
@@ -340,7 +383,7 @@ ary_index(ary, val)
if (rb_equal(ary->ptr[i], val))
return INT2FIX(i);
}
- return Qnil; /* should be FALSE? */
+ return Qnil;
}
static VALUE
@@ -351,8 +394,8 @@ ary_indexes(ary, args)
VALUE new_ary;
int i = 0;
- if (!args || args->len == 1) {
- args = (struct RArray*)rb_to_a(args->ptr[0]);
+ if (!args || NIL_P(args)) {
+ return ary_new2(0);
}
new_ary = ary_new2(args->len);
@@ -365,6 +408,53 @@ ary_indexes(ary, args)
return new_ary;
}
+static void
+ary_replace(ary, beg, len, rpl)
+ struct RArray *ary, *rpl;
+ int beg, len;
+{
+ if (TYPE(rpl) != T_ARRAY) {
+ rpl = (struct RArray*)rb_to_a(rpl);
+ }
+ if (beg < 0) {
+ beg = ary->len + beg;
+ if (beg < 0) beg = 0;
+ }
+ if (beg >= ary->len) {
+ len = beg + rpl->len;
+ if (len >= ary->capa) {
+ ary->capa=len;
+ REALLOC_N(ary->ptr, VALUE, ary->capa);
+ }
+ memclear(ary->ptr+ary->len, beg-ary->len);
+ MEMCPY(ary->ptr+beg, rpl->ptr, VALUE, rpl->len);
+ ary->len = len;
+ }
+ else {
+ int alen;
+
+ if (beg + len > ary->len) {
+ len = ary->len - beg;
+ }
+ if (len < 0) {
+ IndexError("negative length %d", ary->len);
+ }
+
+ alen = ary->len + rpl->len - len;
+ if (alen >= ary->capa) {
+ ary->capa=alen;
+ REALLOC_N(ary->ptr, VALUE, ary->capa);
+ }
+
+ if (len != RARRAY(rpl)->len) {
+ MEMMOVE(ary->ptr+beg+rpl->len, ary->ptr+beg+len,
+ VALUE, ary->len-(beg+len));
+ ary->len = alen;
+ }
+ MEMCPY(ary->ptr+beg, rpl->ptr, VALUE, rpl->len);
+ }
+}
+
static VALUE
ary_aset(argc, argv, ary)
int argc;
@@ -374,90 +464,29 @@ ary_aset(argc, argv, ary)
VALUE arg1, arg2;
struct RArray *arg3;
int offset;
+ int beg, len;
if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
- int beg, len;
-
beg = NUM2INT(arg1);
- if (TYPE(arg3) != T_ARRAY) {
- arg3 = (struct RArray*)rb_to_a(arg3);
- }
- if (beg < 0) {
- beg = ary->len + beg;
- if (beg < 0) {
- Fail("negative index for array(size: %d)", ary->len);
- }
- }
- if (beg >= ary->len) {
- len = beg + arg3->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, arg3->ptr, VALUE, arg3->len);
- ary->len = len;
- }
- else {
- int alen;
-
- len = NUM2INT(arg2);
- if (beg + len > ary->len) {
- len = ary->len - beg;
- }
- if (len < 0) {
- Fail("negative length for sub-array(size: %d)", ary->len);
- }
-
- alen = ary->len + arg3->len - len;
- if (alen >= ary->capa) {
- ary->capa=alen;
- REALLOC_N(ary->ptr, VALUE, ary->capa);
- }
-
- 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;
- }
+ len = NUM2INT(arg2);
+ ary_replace(ary, beg, len, arg3);
return (VALUE)arg3;
}
-
- /* check if idx is Range */
- {
- int beg, len;
-
- 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;
- }
- 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;
- }
- return arg2;
- }
+ else if (FIXNUM_P(arg1)) {
+ offset = FIX2INT(arg1);
+ goto fixnum;
+ }
+ else if (beg_len(arg1, &beg, &len, ary->len)) {
+ /* check if idx is Range */
+ ary_replace(ary, beg, len, arg2);
+ return arg2;
+ }
+ if (TYPE(arg1) == T_BIGNUM) {
+ IndexError("index too big");
}
offset = NUM2INT(arg1);
+ fixnum:
if (offset < 0) {
offset = ary->len + offset;
}
@@ -471,15 +500,10 @@ ary_each(ary)
{
int i;
- if (iterator_p()) {
- for (i=0; i<ary->len; i++) {
- rb_yield(ary->ptr[i]);
- }
- return Qnil;
- }
- else {
- return (VALUE)ary;
+ for (i=0; i<ary->len; i++) {
+ rb_yield(ary->ptr[i]);
}
+ return Qnil;
}
static VALUE
@@ -502,6 +526,15 @@ ary_length(ary)
}
static VALUE
+ary_empty_p(ary)
+ struct RArray *ary;
+{
+ if (ary->len == 0)
+ return TRUE;
+ return FALSE;
+}
+
+static VALUE
ary_clone(ary)
struct RArray *ary;
{
@@ -540,7 +573,7 @@ ary_join(ary, sep)
default:
tmp = obj_as_string(tmp);
}
- if (sep) str_cat(result, sep->ptr, sep->len);
+ if (!NIL_P(sep)) str_cat(result, sep->ptr, sep->len);
str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len);
}
@@ -556,9 +589,9 @@ ary_join_method(argc, argv, ary)
VALUE sep;
rb_scan_args(argc, argv, "01", &sep);
- if (sep == Qnil) sep = OFS;
+ if (NIL_P(sep)) sep = OFS;
- if (sep != Qnil)
+ if (!NIL_P(sep))
Check_Type(sep, T_STRING);
return ary_join(ary, sep);
@@ -569,7 +602,7 @@ ary_to_s(ary)
VALUE ary;
{
VALUE str = ary_join(ary, OFS);
- if (str == Qnil) return str_new(0, 0);
+ if (NIL_P(str)) return str_new(0, 0);
return str;
}
@@ -581,7 +614,7 @@ ary_print_on(ary, port)
int i;
for (i=0; i<ary->len; i++) {
- if (OFS && i>1) {
+ if (!NIL_P(OFS) && i>0) {
io_write(port, OFS);
}
io_write(port, ary->ptr[i]);
@@ -602,7 +635,7 @@ ary_inspect(ary)
len = 1;
for (i=0; i<ary->len; i++) {
- s = rb_funcall(ary->ptr[i], rb_intern("inspect"), 0, 0);
+ s = rb_inspect(ary->ptr[i]);
if (i > 0) str_cat(str, ", ", 2);
str_cat(str, RSTRING(s)->ptr, RSTRING(s)->len);
len += RSTRING(s)->len + 2;
@@ -635,15 +668,27 @@ VALUE
ary_reverse(ary)
struct RArray *ary;
{
- VALUE ary2 = ary_new2(ary->len);
- int i, j;
+ VALUE *p1, *p2;
+ VALUE tmp;
+
+ p1 = ary->ptr;
+ p2 = p1 + ary->len - 1; /* points last item */
- for (i=ary->len-1, j=0; i >=0; i--, j++) {
- RARRAY(ary2)->ptr[j] = ary->ptr[i];
+ while (p1 < p2) {
+ tmp = *p1;
+ *p1 = *p2;
+ *p2 = tmp;
+ p1++; p2--;
}
- RARRAY(ary2)->len = ary->len;
- return ary2;
+ return (VALUE)ary;
+}
+
+static VALUE
+ary_reverse_method(ary)
+ struct RArray *ary;
+{
+ return ary_reverse(ary_clone(ary));
}
static ID cmp;
@@ -662,19 +707,25 @@ sort_2(a, b)
{
VALUE retval;
- if (!cmp) cmp = rb_intern("<=>");
retval = rb_funcall(*a, cmp, 1, *b);
return NUM2INT(retval);
}
VALUE
-ary_sort(ary)
+ary_sort_bang(ary)
struct RArray *ary;
{
qsort(ary->ptr, ary->len, sizeof(VALUE), iterator_p()?sort_1:sort_2);
return (VALUE)ary;
}
+VALUE
+ary_sort(ary)
+ VALUE ary;
+{
+ return ary_sort_bang(ary_clone(ary));
+}
+
static VALUE
ary_delete(ary, item)
struct RArray *ary;
@@ -689,11 +740,40 @@ ary_delete(ary, item)
}
i2++;
}
- ary->len = i2;
+ if (ary->len == i2) {
+ if (iterator_p()) rb_yield(Qnil);
+ }
+ else {
+ ary->len = i2;
+ }
return (VALUE)ary;
}
+VALUE
+ary_delete_at(ary, at)
+ struct RArray *ary;
+ VALUE at;
+{
+ int i1, i2, pos;
+ VALUE del = Qnil;
+
+ pos = NUM2INT(at);
+ for (i1 = i2 = 0; i1 < ary->len; i1++) {
+ if (i1 == pos) {
+ del = ary->ptr[i1];
+ continue;
+ }
+ if (i1 != i2) {
+ ary->ptr[i2] = ary->ptr[i1];
+ }
+ i2++;
+ }
+ ary->len = i2;
+
+ return del;
+}
+
static VALUE
ary_delete_if(ary)
struct RArray *ary;
@@ -717,6 +797,10 @@ ary_clear(ary)
struct RArray *ary;
{
ary->len = 0;
+ if (ARY_DEFAULT_SIZE*3 < ary->capa) {
+ ary->capa = ARY_DEFAULT_SIZE * 2;
+ REALLOC_N(ary->ptr, VALUE, ary->capa);
+ }
return (VALUE)ary;
}
@@ -731,7 +815,7 @@ ary_fill(argc, argv, ary)
VALUE *p, *pend;
rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
- if (arg2 == Qnil && beg_len(arg1, &beg, &len, ary->len)) {
+ if (NIL_P(arg2) && beg_len(arg1, &beg, &len, ary->len)) {
/* beg and len set already */
}
else {
@@ -754,7 +838,7 @@ ary_fill(argc, argv, ary)
REALLOC_N(ary->ptr, VALUE, ary->capa);
}
if (beg > ary->len) {
- MEMZERO(ary->ptr+ary->len, VALUE, end-ary->len);
+ memclear(ary->ptr+ary->len, end-ary->len);
}
ary->len = end;
}
@@ -766,28 +850,43 @@ ary_fill(argc, argv, ary)
return (VALUE)ary;
}
-static VALUE
+VALUE
ary_plus(x, y)
struct RArray *x, *y;
{
struct RArray *z;
- switch (TYPE(y)) {
- case T_ARRAY:
- z = (struct RArray*)ary_new2(x->len + y->len);
- MEMCPY(z->ptr, x->ptr, VALUE, x->len);
- MEMCPY(z->ptr+x->len, y->ptr, VALUE, y->len);
- z->len = x->len + RARRAY(y)->len;
- break;
-
- default:
- z = (struct RArray*)ary_clone(x);
- ary_push(z, y);
- break;
+ if (TYPE(y) != T_ARRAY) {
+ return ary_plus(x, rb_to_a(y));
}
+
+ z = (struct RArray*)ary_new2(x->len + y->len);
+ MEMCPY(z->ptr, x->ptr, VALUE, x->len);
+ MEMCPY(z->ptr+x->len, y->ptr, VALUE, y->len);
+ z->len = x->len + RARRAY(y)->len;
return (VALUE)z;
}
+VALUE
+ary_concat(x, y)
+ struct RArray *x, *y;
+{
+ struct RArray *z;
+ VALUE *p, *pend;
+
+ if (TYPE(y) != T_ARRAY) {
+ return ary_concat(x, rb_to_a(y));
+ }
+
+ p = y->ptr;
+ pend = p + y->len;
+ while (p < pend) {
+ astore(x, x->len, *p);
+ p++;
+ }
+ return (VALUE)x;
+}
+
static VALUE
ary_times(ary, times)
struct RArray *ary;
@@ -796,6 +895,10 @@ ary_times(ary, times)
struct RArray *ary2;
int i, len;
+ if (TYPE(times) == T_STRING) {
+ return ary_join(ary, times);
+ }
+
len = NUM2INT(times) * ary->len;
ary2 = (struct RArray*)ary_new2(len);
ary2->len = len;
@@ -820,8 +923,9 @@ ary_assoc(ary, key)
&& RARRAY(*p)->len > 1
&& rb_equal(RARRAY(*p)->ptr[0], key))
return *p;
+ p++;
}
- return Qnil; /* should be FALSE? */
+ return Qnil;
}
VALUE
@@ -834,11 +938,12 @@ ary_rassoc(ary, value)
p = ary->ptr; pend = p + ary->len;
while (p < pend) {
if (TYPE(*p) == T_ARRAY
- && RARRAY(*p)->len > 2
+ && RARRAY(*p)->len > 1
&& rb_equal(RARRAY(*p)->ptr[1], value))
return *p;
+ p++;
}
- return Qnil; /* should be FALSE? */
+ return Qnil;
}
static VALUE
@@ -944,7 +1049,47 @@ ary_or(ary1, ary2)
return ary3;
}
-extern VALUE cKernel;
+static VALUE
+ary_compact_bang(ary)
+ struct RArray *ary;
+{
+ VALUE *p, *t, *end;
+
+ p = t = ary->ptr;
+ end = p + ary->len;
+ while (t < end) {
+ if (NIL_P(*t)) t++;
+ else *p++ = *t++;
+ }
+ ary->len = ary->capa = (p - ary->ptr);
+ REALLOC_N(ary->ptr, VALUE, ary->len);
+
+ return (VALUE)ary;
+}
+
+static VALUE
+ary_compact(ary)
+ struct RArray *ary;
+{
+ return ary_compact_bang(ary_clone(ary));
+}
+
+static VALUE
+ary_nitems(ary)
+ struct RArray *ary;
+{
+ int n = 0;
+ VALUE *p, *pend;
+
+ p = ary->ptr;
+ pend = p + ary->len;
+ while (p < pend) {
+ if (!NIL_P(*p)) n++;
+ p++;
+ }
+ return INT2FIX(n);
+}
+
extern VALUE mEnumerable;
void
@@ -953,7 +1098,7 @@ Init_Array()
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, "new", ary_s_new, -1);
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);
@@ -965,26 +1110,32 @@ Init_Array()
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, "concat", ary_concat, 1);
+ rb_define_method(cArray, "<<", ary_push, 1);
+ rb_define_method(cArray, "push", ary_push_method, -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, "unshift", ary_unshift_method, -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, "empty?", ary_empty_p, 0);
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, "reverse", ary_reverse_method, 0);
+ rb_define_method(cArray, "reverse!", ary_reverse, 0);
rb_define_method(cArray, "sort", ary_sort, 0);
+ rb_define_method(cArray, "sort!", ary_sort_bang, 0);
rb_define_method(cArray, "delete", ary_delete, 1);
+ rb_define_method(cArray, "delete_at", ary_delete_at, 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, "include?", ary_includes, 1);
+ rb_define_method(cArray, "includes?", ary_includes, 1); /* obsolate */
rb_define_method(cArray, "assoc", ary_assoc, 1);
rb_define_method(cArray, "rassoc", ary_rassoc, 1);
@@ -995,4 +1146,10 @@ Init_Array()
rb_define_method(cArray, "-", ary_diff, 1);
rb_define_method(cArray, "&", ary_and, 1);
rb_define_method(cArray, "|", ary_or, 1);
+
+ rb_define_method(cArray, "compact", ary_compact, 0);
+ rb_define_method(cArray, "compact!", ary_compact_bang, 0);
+ rb_define_method(cArray, "nitems", ary_nitems, 0);
+
+ cmp = rb_intern("<=>");
}
diff --git a/bignum.c b/bignum.c
index a9bbe9b272..73316de894 100644
--- a/bignum.c
+++ b/bignum.c
@@ -40,15 +40,6 @@ bignew_1(class, len, sign)
#define bignew(len,sign) bignew_1(cBignum,len,sign)
-static VALUE
-big_s_new(class, y)
- VALUE class;
- struct RBignum *y;
-{
- Check_Type(y, T_BIGNUM);
- return bignew_1(class, y->len, y->sign);
-}
-
VALUE
big_clone(x)
struct RBignum *x;
@@ -136,7 +127,7 @@ int2big(n)
}
big = (struct RBignum*)uint2big(n);
if (neg) {
- big->sign = FALSE;
+ big->sign = 0;
}
return (VALUE)big;
}
@@ -198,11 +189,20 @@ str2inum(str, base)
}
if (len <= (sizeof(VALUE)*CHAR_BIT)) {
- int result = strtoul(str, 0, base);
+ UINT val = strtoul(str, 0, base);
- if (!sign) result = -result;
- if (FIXABLE(result)) return INT2FIX(result);
- return int2big(result);
+ if (POSFIXABLE(val)) {
+ if (sign) return INT2FIX(val);
+ else {
+ int result = -(int)val;
+ return INT2FIX(result);
+ }
+ }
+ else {
+ VALUE big = uint2big(val);
+ RBIGNUM(big)->sign = sign;
+ return big;
+ }
}
len = (len/(sizeof(USHORT)*CHAR_BIT))+1;
@@ -262,7 +262,7 @@ big2str(x, base)
return fix2str(x, base);
}
i = x->len;
- if (x->len == 0) return str_new2("0");
+ if (i == 0) return str_new2("0");
if (base == 10) {
j = (sizeof(USHORT)/sizeof(char)*CHAR_BIT*i*241L)/800+2;
hbase = 10000;
@@ -332,7 +332,7 @@ big2int(x)
USHORT *ds;
if (len > sizeof(long)/sizeof(USHORT))
- Fail("Bignum too big to convert into fixnum");
+ ArgError("Bignum too big to convert into fixnum");
ds = BDIGITS(x);
num = 0;
while (len--) {
@@ -347,12 +347,7 @@ VALUE
big_to_i(x)
VALUE x;
{
- int v = big2int(x);
-
- if (FIXABLE(v)) {
- return INT2FIX(v);
- }
- return x;
+ return bignorm(x);
}
VALUE
@@ -389,7 +384,9 @@ big2dbl(x)
UINT i = x->len;
USHORT *ds = BDIGITS(x);
- while (i--) d = ds[i] + BIGRAD*d;
+ while (i--) {
+ d = ds[i] + BIGRAD*d;
+ }
if (!x->sign) d = -d;
return d;
}
@@ -402,6 +399,38 @@ big_to_f(x)
}
static VALUE
+big_cmp(x, y)
+ struct RBignum *x, *y;
+{
+ int xlen = x->len;
+
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = (struct RBignum*)int2big(FIX2INT(y));
+ break;
+
+ case T_BIGNUM:
+ break;
+
+ default:
+ return num_coerce_bin(x, y);
+ }
+
+ if (x->sign > y->sign) return INT2FIX(1);
+ if (x->sign < y->sign) return INT2FIX(-1);
+ if (xlen < y->len)
+ return (x->sign) ? INT2FIX(-1) : INT2FIX(1);
+ if (xlen > y->len)
+ return (x->sign) ? INT2FIX(1) : INT2FIX(-1);
+
+ while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen]));
+ if (-1 == xlen) return INT2FIX(0);
+ return (BDIGITS(x)[xlen] > BDIGITS(y)[xlen]) ?
+ (x->sign ? INT2FIX(1) : INT2FIX(-1)) :
+ (x->sign ? INT2FIX(-1) : INT2FIX(1));
+}
+
+static VALUE
big_uminus(x)
struct RBignum *x;
{
@@ -413,6 +442,84 @@ big_uminus(x)
}
static VALUE
+big_neg(x)
+ struct RBignum *x;
+{
+ VALUE z = big_clone(x);
+ UINT i = x->len;
+ USHORT *ds = BDIGITS(z);
+
+ if (!x->sign) big_2comp(z);
+ while (i--) ds[i] = ~ds[i];
+ if (x->sign) big_2comp(z);
+ RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
+
+ return bignorm(z);
+}
+
+static VALUE
+bigsub(x, y)
+ struct RBignum *x, *y;
+{
+ struct RBignum *z = 0;
+ USHORT *zds;
+ long num;
+ UINT i;
+
+ i = x->len;
+ /* if x is larger than y, swap */
+ if (x->len < y->len) {
+ z = x; x = y; y = z; /* swap x y */
+ }
+ else if (x->len == y->len) {
+ while (i > 0) {
+ i--;
+ if (BDIGITS(x)[i] > BDIGITS(y)[i]) {
+ break;
+ }
+ if (BDIGITS(x)[i] < BDIGITS(y)[i]) {
+ z = x; x = y; y = z; /* swap x y */
+ break;
+ }
+ }
+ }
+
+ z = (struct RBignum*)bignew(x->len, (z == 0)?1:0);
+ zds = BDIGITS(z);
+
+ i = x->len;
+ while (i--) zds[i] = BDIGITS(x)[i];
+
+ i = 0; num = 0;
+ do {
+ num += (long)zds[i] - BDIGITS(y)[i];
+ if (num < 0) {
+ zds[i] = num + BIGRAD;
+ num = -1;
+ }
+ else {
+ zds[i] = BIGLO(num);
+ num = 0;
+ }
+ } while (++i < y->len);
+ if (num) {
+ while (num && i < x->len) {
+ num += zds[i];
+ if (num < 0) {
+ zds[i++] = num + BIGRAD;
+ num = -1;
+ }
+ else {
+ zds[i++] = BIGLO(num);
+ num = 0;
+ }
+ }
+ }
+
+ return bignorm(z);
+}
+
+static VALUE
bigadd(x, y, sign)
struct RBignum *x, *y;
char sign;
@@ -422,6 +529,11 @@ bigadd(x, y, sign)
long num;
UINT i, len;
+ if (x->sign == (y->sign ^ sign)) {
+ if (y->sign == sign) return bigsub(y, x);
+ return bigsub(x, y);
+ }
+
if (x->len > y->len) {
len = x->len + 1;
}
@@ -437,53 +549,18 @@ bigadd(x, y, sign)
while (i--) zds[i] = BDIGITS(y)[i];
i = 0; num = 0;
- if (x->sign == z->sign) {
- do {
- num += (long)zds[i] + BDIGITS(x)[i];
- zds[i++] = BIGLO(num);
+ do {
+ num += (long)zds[i] + BDIGITS(x)[i];
+ zds[i++] = BIGLO(num);
num = BIGDN(num);
- } while (i < x->len);
- if (num) {
- while (i < y->len) {
- num += zds[i];
- zds[i++] = BIGLO(num);
- num = BIGDN(num);
- }
- BDIGITS(z)[i] = num;
- }
- }
- else {
- do {
- num += (long)zds[i] - BDIGITS(x)[i];
- if (num < 0) {
- zds[i] = num + BIGRAD;
- num = -1;
- }
- else {
- zds[i] = BIGLO(num);
- num = 0;
- }
- } while (++i < x->len);
- if (num && x->len == y->len) {
- num = 1; i = 0;
- z->sign = 1;
- do {
- num += (BIGRAD-1) - zds[i];
- zds[i++] = BIGLO(num);
- num = BIGDN(num);
- } while (i < y->len);
- }
- else while (i < y->len) {
+ } while (i < x->len);
+ if (num) {
+ while (i < y->len) {
num += zds[i];
- if (num < 0) {
- zds[i++] = num + BIGRAD;
- num = -1;
- }
- else {
- zds[i++] = BIGLO(num);
- num = 0;
- }
+ zds[i++] = BIGLO(num);
+ num = BIGDN(num);
}
+ BDIGITS(z)[i] = num;
}
return bignorm(z);
@@ -495,26 +572,40 @@ big_plus(x, y)
{
VALUE z;
- if (FIXNUM_P(y)) y = int2big(FIX2INT(y));
- else {
- Check_Type(x, T_BIGNUM);
- }
- z = bigadd(x, y, 1);
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = int2big(FIX2INT(y));
+ /* fall through */
+ case T_BIGNUM:
+ return bigadd(x, y, 1);
- return z;
+ case T_FLOAT:
+ return float_new(big2dbl(x) + RFLOAT(y)->value);
+
+ default:
+ return num_coerce_bin(x, y);
+ }
}
VALUE
big_minus(x, y)
VALUE x, y;
{
- if (FIXNUM_P(y)) y = int2big(FIX2INT(y));
- else {
- Check_Type(y, T_BIGNUM);
- }
- x = bigadd(x, y, 0);
+ VALUE cmp;
- return x;
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = int2big(FIX2INT(y));
+ /* fall through */
+ case T_BIGNUM:
+ return bigadd(x, y, 0);
+
+ case T_FLOAT:
+ return float_new(big2dbl(x) - RFLOAT(y)->value);
+
+ default:
+ return num_coerce_bin(x, y);
+ }
}
VALUE
@@ -527,9 +618,19 @@ big_mul(x, y)
USHORT *zds;
if (FIXNUM_P(x)) x = (struct RBignum*)int2big(FIX2INT(x));
- if (FIXNUM_P(y)) y = (struct RBignum*)int2big(FIX2INT(y));
- else {
- Check_Type(y, T_BIGNUM);
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = (struct RBignum*)int2big(FIX2INT(y));
+ break;
+
+ case T_BIGNUM:
+ break;
+
+ case T_FLOAT:
+ return float_new(big2dbl(x) * RFLOAT(y)->value);
+
+ default:
+ return num_coerce_bin(x, y);
}
j = x->len + y->len + 1;
@@ -567,7 +668,7 @@ bigdivmod(x, y, div, mod)
USHORT dd, q;
yds = BDIGITS(y);
- if (ny == 0 && yds[0] == 0) Fail("divided by 0");
+ if (ny == 0 && yds[0] == 0) num_zerodiv();
if (nx < ny) {
if (div) *div = INT2FIX(0);
if (mod) *mod = bignorm(x);
@@ -587,7 +688,7 @@ bigdivmod(x, y, div, mod)
if (div) *div = bignorm(z);
if (mod) {
if (!y->sign) t2 = -t2;
- *mod = FIX2INT(t2);
+ *mod = INT2FIX(t2);
}
return;
}
@@ -683,9 +784,19 @@ big_div(x, y)
{
VALUE z;
- if (FIXNUM_P(y)) y = int2big(FIX2INT(y));
- else {
- Check_Type(y, T_BIGNUM);
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = int2big(FIX2INT(y));
+ break;
+
+ case T_BIGNUM:
+ break;
+
+ case T_FLOAT:
+ return float_new(big2dbl(x) / RFLOAT(y)->value);
+
+ default:
+ return num_coerce_bin(x, y);
}
bigdivmod(x, y, &z, 0);
@@ -698,9 +809,20 @@ big_mod(x, y)
{
VALUE z;
- if (FIXNUM_P(y)) y = int2big(FIX2INT(y));
- else {
- Check_Type(y, T_BIGNUM);
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = int2big(FIX2INT(y));
+ break;
+
+ case T_BIGNUM:
+ break;
+
+ case T_FLOAT:
+ y = dbl2big(RFLOAT(y)->value);
+ break;
+
+ default:
+ return num_coerce_bin(x, y);
}
bigdivmod(x, y, 0, &z);
@@ -713,9 +835,20 @@ big_divmod(x, y)
{
VALUE div, mod;
- if (FIXNUM_P(y)) y = int2big(FIX2INT(y));
- else {
- Check_Type(y, T_BIGNUM);
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = int2big(FIX2INT(y));
+ break;
+
+ case T_FLOAT:
+ y = dbl2big(RFLOAT(y)->value);
+ break;
+
+ case T_BIGNUM:
+ break;
+
+ default:
+ return num_coerce_bin(x, y);
}
bigdivmod(x, y, &div, &mod);
@@ -726,22 +859,37 @@ VALUE
big_pow(x, y)
VALUE x, y;
{
+ double d;
VALUE z;
- int n;
+
+ if (y == INT2FIX(0)) return INT2FIX(1);
+ switch (TYPE(y)) {
+ case T_FLOAT:
+ d = RFLOAT(y)->value;
+ break;
- if (TYPE(y) == T_FLOAT) {
- return float_new(pow(big2dbl(x), RFLOAT(y)->value));
- }
- n = NUM2INT(y);
- if (n == 0) return INT2FIX(1);
- if (n < 0) {
- return float_new(pow(big2dbl(x), (double)n));
+ case T_BIGNUM:
+ if (RBIGNUM(y)->sign) goto pos_big;
+ d = big2dbl(y);
+ break;
+
+ case T_FIXNUM:
+ if (FIX2INT(y) > 0) goto pos_big;
+ d = (double)FIX2INT(y);
+ break;
+
+ default:
+ return num_coerce_bin(x, y);
}
+ return float_new(pow(big2dbl(x), d));
+ pos_big:
z = x;
- while (--n) {
- while (!(n % 2)) {
- n = n /2;
+ for (;;) {
+ y = rb_funcall(y, '-', 1, INT2FIX(1));
+ if (y == INT2FIX(0)) break;
+ while (rb_funcall(y, '%', 1, INT2FIX(2)) == INT2FIX(0)) {
+ y = rb_funcall(y, '/', 1, INT2FIX(2));
x = big_mul(x, x);
}
z = big_mul(z, x);
@@ -906,22 +1054,6 @@ big_xor(x, y)
return bignorm(z);
}
-static VALUE
-big_neg(x)
- struct RBignum *x;
-{
- VALUE z = big_clone(x);
- UINT i = x->len;
- USHORT *ds = BDIGITS(z);
-
- if (!x->sign) big_2comp(z);
- while (i--) ds[i] = ~ds[i];
- if (x->sign) big_2comp(z);
- RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
-
- return bignorm(z);
-}
-
static VALUE big_rshift();
VALUE
@@ -1014,32 +1146,6 @@ big_aref(x, y)
}
static VALUE
-big_cmp(x, y)
- struct RBignum *x, *y;
-{
- int xlen = x->len;
-
- 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)
- return (x->sign) ? INT2FIX(-1) : INT2FIX(1);
- if (xlen > y->len)
- return (x->sign) ? INT2FIX(1) : INT2FIX(-1);
-
- while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen]));
- if (-1 == xlen) return INT2FIX(0);
- return (BDIGITS(x)[xlen] < BDIGITS(y)[xlen]) ?
- (x->sign ? INT2FIX(1) : INT2FIX(-1)) :
- (x->sign ? INT2FIX(-1) : INT2FIX(1));
-}
-
-static VALUE
big_hash(x)
struct RBignum *x;
{
@@ -1059,13 +1165,12 @@ big_coerce(x, y)
VALUE y;
{
if (FIXNUM_P(y)) {
- return int2big(FIX2INT(y));
+ return assoc_new(int2big(FIX2INT(y)), x);
}
else {
- Fail("can't coerce %s to Bignum", rb_class2name(CLASS_OF(y)));
+ TypeError("can't coerce %s to Bignum", rb_class2name(CLASS_OF(y)));
}
/* not reached */
- return Qnil;
}
static VALUE
@@ -1079,11 +1184,43 @@ big_abs(x)
return (VALUE)x;
}
+/* !!!warnig!!!!
+ this is not really a random number!!
+*/
+
+VALUE
+big_rand(max)
+ struct RBignum *max;
+{
+ struct RBignum *v;
+ int len;
+
+ len = max->len;
+ v = RBIGNUM(bignew(len,1));
+ while (len--) {
+#ifdef HAVE_RANDOM
+ BDIGITS(v)[len] = random();
+#else
+ BDIGITS(v)[len] = rand();
+#endif
+ }
+
+ return big_mod(v, max);
+}
+
+static VALUE
+big_size(big)
+ struct RBignum *big;
+{
+ return INT2FIX(big->len*2);
+}
+
void
Init_Bignum()
{
cBignum = rb_define_class("Bignum", cInteger);
- rb_define_singleton_method(cBignum, "new", big_s_new, 1);
+
+ rb_undef_method(CLASS_OF(cBignum), "new");
rb_define_method(cBignum, "to_s", big_to_s, 0);
rb_define_method(cBignum, "coerce", big_coerce, 1);
@@ -1107,5 +1244,6 @@ Init_Bignum()
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);
+ rb_define_method(cBignum, "abs", big_abs, 0);
+ rb_define_method(cBignum, "size", big_size, 0);
}
diff --git a/class.c b/class.c
index 204c476fa7..3e8ce517a6 100644
--- a/class.c
+++ b/class.c
@@ -39,7 +39,7 @@ singleton_class_new(super)
{
struct RClass *cls = (struct RClass*)class_new(super);
- FL_SET(cls, FL_SINGLE);
+ FL_SET(cls, FL_SINGLETON);
return (VALUE)cls;
}
@@ -58,7 +58,7 @@ VALUE
singleton_class_clone(class)
struct RClass *class;
{
- if (!FL_TEST(class, FL_SINGLE))
+ if (!FL_TEST(class, FL_SINGLETON))
return (VALUE)class;
else {
/* copy singleton(unnamed) class */
@@ -68,7 +68,7 @@ singleton_class_clone(class)
clone->super = class->super;
clone->m_tbl = new_idhash();
st_foreach(class->m_tbl, clone_method, clone->m_tbl);
- FL_SET(clone, FL_SINGLE);
+ FL_SET(clone, FL_SINGLETON);
return (VALUE)clone;
}
}
@@ -78,7 +78,7 @@ rb_define_class_id(id, super)
ID id;
struct RBasic *super;
{
- struct RClass *cls = (struct RClass*)class_new(super);
+ struct RClass *cls;
if (!super) super = (struct RBasic*)cClass;
cls = (struct RClass*)class_new(super);
@@ -100,7 +100,6 @@ rb_define_class(name, super)
id = rb_intern(name);
class = rb_define_class_id(id, super);
st_add_direct(rb_class_tbl, id, class);
- rb_set_class_path(class, 0, name);
return class;
}
@@ -128,7 +127,7 @@ module_new()
NEWOBJ(mdl, struct RClass);
OBJSETUP(mdl, cModule, T_MODULE);
- mdl->super = Qnil;
+ mdl->super = 0;
mdl->m_tbl = new_idhash();
return (VALUE)mdl;
@@ -171,6 +170,7 @@ rb_define_module_under(under, name)
id = rb_intern(name);
module = rb_define_module_id(id);
rb_const_set(under, id, module);
+ rb_set_class_path(module, under, name);
return module;
}
@@ -201,7 +201,7 @@ rb_include_module(class, module)
{
struct RClass *p;
- if (!module) return;
+ if (NIL_P(module)) return;
switch (TYPE(module)) {
case T_MODULE:
@@ -212,10 +212,8 @@ rb_include_module(class, module)
}
if (class == module) return;
- if (BUILTIN_TYPE(class) == T_CLASS) {
- rb_clear_cache(class);
- }
-
+ rb_clear_cache();
+
while (module) {
/* ignore if the module included already in superclasses */
for (p = class->super; p; p = p->super) {
@@ -258,7 +256,7 @@ rb_undef_method(class, name)
struct RClass *class;
char *name;
{
- rb_add_method(class, rb_intern(name), Qnil, NOEX_PUBLIC);
+ rb_add_method(class, rb_intern(name), 0, NOEX_PUBLIC);
}
void
@@ -275,18 +273,7 @@ VALUE
rb_singleton_class(obj)
struct RBasic *obj;
{
- switch (TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- case T_STRUCT:
- break;
- default:
- Fail("can't define singleton method for built-in class");
- break;
- }
-
- if (FL_TEST(obj->class, FL_SINGLE)) {
+ if (FL_TEST(obj->class, FL_SINGLETON)) {
return (VALUE)obj->class;
}
return obj->class = singleton_class_new(obj->class);
@@ -338,10 +325,10 @@ rb_define_attr(class, id, pub)
attreq = rb_intern(buf);
sprintf(buf, "@%s", name);
attriv = rb_intern(buf);
- if (rb_method_boundp(class, attr) == FALSE) {
+ if (!rb_method_boundp(class, attr)) {
rb_add_method(class, attr, NEW_IVAR(attriv), 0);
}
- if (pub && rb_method_boundp(class, attreq) == FALSE) {
+ if (pub && !rb_method_boundp(class, attreq)) {
rb_add_method(class, attreq, NEW_ATTRSET(attriv), 0);
}
}
@@ -372,7 +359,7 @@ rb_scan_args(argc, argv, fmt, va_alist)
if (isdigit(*p)) {
n = *p - '0';
if (n > argc)
- Fail("Wrong number of arguments (%d for %d)", argc, n);
+ ArgError("Wrong # of arguments (%d for %d)", argc, n);
for (i=0; i<n; i++) {
var = va_arg(vargs, VALUE*);
*var = argv[i];
@@ -408,7 +395,7 @@ rb_scan_args(argc, argv, fmt, va_alist)
}
else if (*p == '\0') {
if (argc > i) {
- Fail("Wrong # of arguments(%d for %d)", argc, i);
+ ArgError("Wrong # of arguments(%d for %d)", argc, i);
}
}
else {
@@ -419,6 +406,6 @@ rb_scan_args(argc, argv, fmt, va_alist)
return argc;
error:
- Fail("bad scan arg format: %s", fmt);
+ Fatal("bad scan arg format: %s", fmt);
return 0;
}
diff --git a/compar.c b/compar.c
index e7d1e62d79..e406a0f0fe 100644
--- a/compar.c
+++ b/compar.c
@@ -6,7 +6,7 @@
$Date: 1994/10/14 06:19:05 $
created at: Thu Aug 26 14:39:48 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -34,7 +34,7 @@ cmp_gt(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t > 0) return y;
+ if (t > 0) return TRUE;
return FALSE;
}
@@ -45,7 +45,7 @@ cmp_ge(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t >= 0) return y;
+ if (t >= 0) return TRUE;
return FALSE;
}
@@ -56,7 +56,7 @@ cmp_lt(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t < 0) return y;
+ if (t < 0) return TRUE;
return FALSE;
}
@@ -67,7 +67,7 @@ cmp_le(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t <= 0) return y;
+ if (t <= 0) return TRUE;
return FALSE;
}
diff --git a/config.dj b/config.dj
new file mode 100644
index 0000000000..13f4e6ddb6
--- /dev/null
+++ b/config.dj
@@ -0,0 +1,35 @@
+#define THREAD 1
+#define HAVE_DIRENT_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_SYS_FILE_H 1
+#define HAVE_PWD_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TIMES_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_WAIT_H 1
+#define HAVE_STRING_H 1
+#define HAVE_UTIME_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_ST_BLKSIZE 1
+#define HAVE_ST_RDEV 1
+#define GETGROUPS_T gid_t
+#define RETSIGTYPE void
+#define HAVE_ALLOCA 1
+#define vfork fork
+#define HAVE_FMOD 1
+#define HAVE_RANDOM 1
+#define HAVE_WAITPID 1
+#define HAVE_GETCWD 1
+#define HAVE_TRUNCATE 1
+#define HAVE_CHSIZE 1
+#define HAVE_TIMES 1
+#define HAVE_UTIMES 1
+/* #define HAVE_FCNTL 1 */
+/* #define HAVE_SETITIMER 1 */
+#define HAVE_GETGROUPS 1
+#define HAVE_SIGPROCMASK 1
+#define FILE_COUNT _cnt
+#define DLEXT ".so"
+#define RUBY_LIB ";/usr/local/lib/ruby;."
+#define RUBY_ARCHLIB "/usr/local/lib/ruby/i386-msdos"
diff --git a/config.guess b/config.guess
index a3d6a9f1bf..ce6e12a8fd 100755
--- a/config.guess
+++ b/config.guess
@@ -1,6 +1,6 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -51,14 +51,19 @@ trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- alpha:OSF1:V*:*)
- # After 1.2, OSF1 uses "V1.3" for uname -r.
- echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'`
- exit 0 ;;
alpha:OSF1:*:*)
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo alpha-dec-osf${UNAME_RELEASE}
- exit 0 ;;
+ echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
amiga:NetBSD:*:*)
echo m68k-cbm-netbsd${UNAME_RELEASE}
exit 0 ;;
@@ -75,6 +80,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
sun4*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
@@ -93,15 +101,30 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
+ mips:*:4*:UMIPS)
+ echo mips-mips-riscos4sysv
+ exit 0 ;;
mips:*:5*:RISCos)
echo mips-mips-riscos${UNAME_RELEASE}
exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit 0 ;;
@@ -112,12 +135,17 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo m88k-motorola-sysv3
exit 0 ;;
AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
+ else echo i586-dg-dgux${UNAME_RELEASE}
+ fi
exit 0 ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
@@ -169,10 +197,8 @@ EOF
else
IBM_ARCH=powerpc
fi
- if grep bos410 /usr/include/stdio.h >/dev/null 2>&1; then
- IBM_REV=4.1
- elif grep bos411 /usr/include/stdio.h >/dev/null 2>&1; then
- IBM_REV=4.1.1
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=4.${UNAME_RELEASE}
fi
@@ -185,7 +211,7 @@ EOF
echo romp-ibm-bsd4.4
exit 0 ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit 0 ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
@@ -203,7 +229,7 @@ EOF
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/7?? | 9000/8?7 ) HP_ARCH=hppa1.1 ;;
+ 9000/7?? | 9000/8?[679] ) HP_ARCH=hppa1.1 ;;
9000/8?? ) HP_ARCH=hppa1.0 ;;
esac
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
@@ -239,18 +265,21 @@ EOF
rm -f dummy.c dummy
echo unknown-hitachi-hiuxwe2
exit 0 ;;
- 9000/7??:4.3bsd:*:* | 9000/8?7:4.3bsd:*:* )
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit 0 ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit 0 ;;
- hp7??:OSF1:*:* | hp8?7:OSF1:*:* )
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit 0 ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit 0 ;;
@@ -269,20 +298,23 @@ EOF
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit 0 ;;
- CRAY*X-MP:UNICOS:*:*)
+ CRAY*X-MP:*:*:*)
echo xmp-cray-unicos
exit 0 ;;
- CRAY*Y-MP:UNICOS:*:*)
- echo ymp-cray-unicos
- exit 0 ;;
- CRAY-2:UNICOS:*:*)
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*C90:*:*:*)
+ echo c90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
echo cray2-cray-unicos
exit 0 ;;
hp3[0-9][05]:NetBSD:*:*)
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
i[34]86:BSD/386:*:* | *:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit 0 ;;
*:FreeBSD:*:*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
@@ -290,11 +322,20 @@ EOF
*:NetBSD:*:*)
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
+ i*:CYGWIN*:*)
+ echo i386-pc-cygwin32
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
*:GNU:*:*)
echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux
+ echo ${UNAME_MACHINE}-pc-linux
exit 0 ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
@@ -305,23 +346,25 @@ EOF
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
else
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
fi
exit 0 ;;
i[34]86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
- echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
- echo ${UNAME_MACHINE}-unknown-sysv32
+ echo ${UNAME_MACHINE}-pc-sysv32
fi
exit 0 ;;
Intel:Mach:3*:*)
- echo i386-unknown-mach3
+ echo i386-pc-mach3
exit 0 ;;
paragon:*:*:*)
echo i860-intel-osf1
@@ -345,19 +388,19 @@ EOF
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
- m680[234]0:LynxOS:2.2*:*)
+ m680[234]0:LynxOS:2.[23]*:*)
echo m68k-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit 0 ;;
- i[34]86:LynxOS:2.2*:*)
+ i[34]86:LynxOS:2.[23]*:*)
echo i386-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
- TSUNAMI:LynxOS:2.2*:*)
+ TSUNAMI:LynxOS:2.[23]*:*)
echo sparc-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
- rs6000:LynxOS:2.2*:*)
+ rs6000:LynxOS:2.[23]*:*)
echo rs6000-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
RM*:SINIX-*:*:*)
@@ -371,12 +414,29 @@ EOF
echo ns32k-sni-sysv
fi
exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ R3000:*System_V*:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ powerpc:JCC_BSD+:*:*)
+ echo powerpc-jcc-bsd4.4
+ exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
main ()
{
#if defined (sony)
@@ -427,7 +487,7 @@ main ()
#endif
#if defined (__386BSD__)
- printf ("i386-unknown-bsd\n"); exit (0);
+ printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
@@ -440,7 +500,18 @@ main ()
#endif
#if defined (_SEQUENT_)
- printf ("i386-sequent-ptx\n"); exit (0);
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
#endif
#if defined (vax)
diff --git a/config.sub b/config.sub
index 5641cc1ce6..27819cc8dc 100755
--- a/config.sub
+++ b/config.sub
@@ -1,9 +1,9 @@
#! /bin/sh
# Configuration validation subroutine script, version 1.1.
-# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+# Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
+# can handle that machine. It does not imply ALL GNU software can.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,7 +17,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -40,6 +41,8 @@
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
if [ x$1 = x ]
@@ -61,11 +64,21 @@ case $1 in
;;
esac
-# Separate what the user gave into CPU-COMPANY and OS (if any).
-basic_machine=`echo $1 | sed 's/-[^-]*$//'`
-if [ $basic_machine != $1 ]
-then os=`echo $1 | sed 's/.*-/-/'`
-else os=; fi
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ linux-gnu*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work. We also
@@ -80,38 +93,43 @@ case $os in
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp )
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple)
os=
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
+ -sco5)
+ os=sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
-sco4)
os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*)
os=-lynxos
@@ -122,33 +140,43 @@ case $os in
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
+ -psos*)
+ os=-psos
+ ;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
- tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm | pyramid \
+ tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
+ | arme[lb] | pyramid \
| tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
- | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \
- | powerpc | sparc64 | 1750a | dsp16xx | mips64 | mipsel \
+ | alpha | we32k | ns16k | clipper | i370 | sh \
+ | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
| pdp11 | mips64el | mips64orion | mips64orionel \
- | sparc)
- basic_machine=$basic_machine-unknown
- ;;
+ | sparc | sparclet | sparclite | sparc64)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i[3456]86)
+ basic_machine=$basic_machine-pc
+ ;;
# Object if more than one company name word.
*-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
;;
# Recognize the basic CPU types with company name.
- vax-* | tahoe-* | i[345]86-* | i860-* | m68k-* | m68000-* | m88k-* \
+ vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
| sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
- | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
| none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
| hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
| pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
- | pdp11-* | sh-* | powerpc-* | sparc64-* | mips64-* | mipsel-* \
+ | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
| mips64el-* | mips64orion-* | mips64orionel-*)
;;
# Recognize the various machine names and aliases which stand
@@ -188,6 +216,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-sysv
;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
balance)
basic_machine=ns32k-sequent
os=-dynix
@@ -220,6 +252,10 @@ case $basic_machine in
basic_machine=cray2-cray
os=-unicos
;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
crds | unos)
basic_machine=m68k-crds
;;
@@ -256,6 +292,10 @@ case $basic_machine in
encore | umax | mmax)
basic_machine=ns32k-encore
;;
+ ews4800)
+ basic_machine=mips-nec
+ os=-sysv4
+ ;;
fx2800)
basic_machine=i860-alliant
;;
@@ -306,20 +346,20 @@ case $basic_machine in
os=-mvs
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
- i[345]86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ i[3456]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
- i[345]86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ i[3456]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
- i[345]86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ i[3456]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
- i[345]86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ i[3456]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
iris | iris4d)
@@ -417,14 +457,41 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
- pentium-*)
- # We will change tis to say i586 once there has been
- # time for various packages to start to recognize that.
- basic_machine=i486-`echo $basic_machine | sed 's/^[^-]*-//'`
+ pentium | p5)
+ basic_machine=i586-intel
+ ;;
+ pentiumpro | p6)
+ basic_machine=i686-intel
+ ;;
+ pentium-* | p5-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ k5)
+ # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+ basic_machine=i586-amd
+ ;;
+ nexen)
+ # We don't have specific support for Nexgen yet, so just call it a Pentium
+ basic_machine=i586-nexgen
;;
pn)
basic_machine=pn-gould
;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
ps2)
basic_machine=i386-ibm
;;
@@ -519,6 +586,10 @@ case $basic_machine in
basic_machine=m68k-wrs
os=-vxworks
;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
xmp)
basic_machine=xmp-cray
os=-unicos
@@ -586,6 +657,8 @@ esac
if [ x"$os" != x"" ]
then
case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
@@ -597,21 +670,25 @@ case $os in
os=-sysv4
;;
-gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux|'`
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# The portable systems comes first.
- # Each alternative must end in a *, to match a version number.
+ # Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[345]* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
- | -amigados* | -msdos* | -newsos* | -unicos* | -aos* \
+ | -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \
| -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \
- | -riscos* | -linux* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta | -udi | -eabi)
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -cygwin32* | -pe* | -psos* | -moss* | -proelf* \
+ | -linux*)
+ # Remember, each alternative MUST END IN *, to match a version number.
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
@@ -637,6 +714,9 @@ case $os in
-ctix* | -uts*)
os=-sysv
;;
+ -ns2 )
+ os=-nextstep2
+ ;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
@@ -690,6 +770,9 @@ case $basic_machine in
*-acorn)
os=-riscix1.2
;;
+ arm*-semi)
+ os=-aout
+ ;;
pdp11-*)
os=-none
;;
@@ -741,6 +824,9 @@ case $basic_machine in
m88k-omron*)
os=-luna
;;
+ *-next )
+ os=-nextstep
+ ;;
*-sequent)
os=-ptx
;;
@@ -825,6 +911,9 @@ case $basic_machine in
-vxworks*)
vendor=wrs
;;
+ -aux*)
+ vendor=apple
+ ;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
diff --git a/configure.bat b/configure.bat
new file mode 100644
index 0000000000..84e5191bbe
--- /dev/null
+++ b/configure.bat
@@ -0,0 +1,5 @@
+@echo off
+sed -f top.sed Makefile.in >Makefile
+sed -f top.sed ext/extmk.rb.in > ext\extmk.rb
+copy ext\Setup.dj ext\Setup
+copy config.dj config.h
diff --git a/configure.in b/configure.in
index fc87754cb8..7f89f5e69c 100644
--- a/configure.in
+++ b/configure.in
@@ -21,6 +21,17 @@ then
(it is also a good idea to do 'make clean' before compiling))
fi
+dnl checks for thread
+rb_thread=yes
+AC_ARG_ENABLE(thread, [--disable-thread never use user-level thread], [
+ rb_thread=$enableval
+])
+if test $rb_thread = yes; then
+ AC_DEFINE(THREAD)
+fi
+
+AC_CANONICAL_HOST
+
dnl Checks for programs.
AC_PROG_CC
AC_PROG_GCC_TRADITIONAL
@@ -29,19 +40,18 @@ 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(crypt, crypt)
-AC_CHECK_LIB(dl, dlopen, [:]) # Dynamic linking for SunOS/Solaris and SYSV
+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(limits.h sys/file.h sys/ioctl.h pwd.h\
- sys/time.h sys/times.h sys/param.h unistd.h\
+AC_CHECK_HEADERS(unistd.h limits.h sys/file.h sys/ioctl.h pwd.h sys/select.h\
+ sys/time.h sys/times.h sys/param.h sys/wait.h\
syscall.h a.out.h string.h utime.h memory.h)
dnl Checks for typedefs, structures, and compiler characteristics.
@@ -57,40 +67,75 @@ AC_TYPE_SIGNAL
AC_FUNC_ALLOCA
AC_FUNC_VFORK
AC_REPLACE_FUNCS(dup2 setenv memmove mkdir strerror strftime\
- strstr strtoul strdup crypt)
+ strstr strtoul strdup strcasecmp crypt flock)
AC_CHECK_FUNCS(fmod killpg random wait4 waitpid syscall getcwd\
- truncate chsize times utimes fcntl\
+ truncate chsize times utimes fcntl lockf setitimer\
setruid seteuid setreuid setrgid setegid setregid\
- getgroups getpriority sigprocmask dlopen)
-if test "$ac_cv_func strftime" = no; then
+ getgroups getpgid getpriority dlopen sigprocmask sigaction)
+if test "$ac_cv_func_strftime" = no; then
AC_STRUCT_TIMEZONE
AC_TRY_LINK([],
[extern int daylight; int i = daylight;], AC_DEFINE(HAVE_DAYLIGHT))
fi
+if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then
+ AC_DEFINE(POSIX_SIGNAL)
+else
+ AC_MSG_CHECKING(for BSD signal semantics)
+ AC_CACHE_VAL(rb_cv_bsd_signal,
+ [AC_TRY_RUN([
+#include <stdio.h>
+#include <signal.h>
+
+void sig_handler(dummy)
+ int dummy;
+{
+}
+
+int main(argc, argv)
+ int argc;
+ char ** argv;
+{
+ signal(SIGINT, sig_handler);
+ kill(getpid(), SIGINT);
+ kill(getpid(), SIGINT);
+ return 0;
+}
+],
+ rb_cv_bsd_signal=yes,
+ rb_cv_bsd_signal=no,
+ [:])])
+ AC_MSG_RESULT($rb_cv_bsd_signal)
+ if test "$rb_cv_bsd_signal" = yes; then
+ AC_DEFINE(BSD_SIGNAL)
+ fi
+fi
+
AC_C_BIGENDIAN
+AC_CHAR_UNSIGNED
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
+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
+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
+if test "$rb_cv_fcnt" = ""; then
AC_TRY_COMPILE([#include <stdio.h>],
- [FILE *f = stdin; f->readCount = 0;], rb_cv_fcnt="readCount", )
+ [FILE *f = stdin; f->readCount = 0;],
+ rb_cv_fcnt="readCount", rb_cv_fcnt="not found")
fi])
-if test "$rb_cv_fcnt"; then
+if test "$rb_cv_fcnt" = "not found"; then
+ AC_MSG_RESULT([not found(OK if using GNU libc)])
+else
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
if test "$ac_cv_func_getpwent" = yes; then
@@ -105,31 +150,45 @@ if test "$ac_cv_func_getpwent" = yes; then
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], [
+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)
- cat confdefs.h > config.h
- AC_CACHE_VAL(rb_cv_dln_a_out,
- [AC_TRY_COMPILE([
-#define USE_DLN_A_OUT
-#include "dln.c"
+case "$host_os" in
+ linux*)
+ AC_MSG_CHECKING(whether ELF binaries are produced)
+ AC_CACHE_VAL(rb_cv_linux_elf,
+ [AC_TRY_RUN([
+/* Test for whether ELF binaries are produced */
+#include <fcntl.h>
+#include <stdlib.h>
+main() {
+ char buffer[4];
+ int i=open("conftest",O_RDONLY);
+ if(i==-1)
+ exit(1); /* fail */
+ if(read(i,&buffer[0],4)<4)
+ exit(1); /* fail */
+ if(buffer[0] != 127 || buffer[1] != 'E' ||
+ buffer[2] != 'L' || buffer[3] != 'F')
+ exit(1); /* fail */
+ exit(0); /* succeed (yes, it's ELF) */
+}
],
- [],
- 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
+ rb_cv_linux_elf=yes,
+ rb_cv_linux_elf=no,
+ [:])])
+ AC_MSG_RESULT($rb_cv_linux_elf)
+ if test "$rb_cv_linux_elf" = no; then
+ with_dln_a_out=yes
+ else
+ LDFLAGS="-rdynamic"
+ fi;;
+esac
+
+AC_SUBST(DLDFLAGS)dnl
AC_SUBST(STATIC)dnl
AC_SUBST(CCDLFLAGS)dnl
@@ -138,7 +197,63 @@ AC_SUBST(DLEXT)dnl
STATIC=
-if test "$rb_cv_dln_a_out" = yes; then
+if test "$with_dln_a_out" != yes; then
+ rb_cv_dlopen=unknown
+ AC_MSG_CHECKING(whether OS depend dynamic link works)
+ if test "$GCC" = yes; then
+ CCDLFLAGS=-fpic
+ else
+ case "$host_os" in
+ hpux*) CCDLFLAGS='+z';;
+ solaris*|irix*) CCDLFLAGS='-K pic' ;;
+ sunos*) CCDLFLAGS='-pic' ;;
+ svr4*|esix*) CCDLFLAGS='-Kpic' ;;
+ *) CCDLFLAGS='' ;;
+ esac
+ fi
+
+ case "$host_os" in
+ hpux*) DLDFLAGS="-E"
+ LDSHARED='ld -b'
+ LDFLAGS="-Wl,-E"
+ rb_cv_dlopen=yes;;
+ solaris*) LDSHARED='ld -G'
+ rb_cv_dlopen=yes;;
+ sunos*) LDSHARED='ld -assert nodefinitions'
+ rb_cv_dlopen=yes;;
+ svr4*|esix*) LDSHARED="ld -G"
+ rb_cv_dlopen=yes ;;
+ linux*) LDSHARED="gcc -shared"
+ rb_cv_dlopen=yes ;;
+ freebsd*) LDSHARED="ld -Bshareable"
+ rb_cv_dlopen=yes ;;
+ *) LDSHARED='ld' ;;
+ esac
+ AC_MSG_RESULT($rb_cv_dlopen)
+fi
+
+dln_a_out_works=no
+if test "$ac_cv_header_a_out_h" = yes; then
+ if test "$with_dln_a_out" = yes || test "$rb_cv_dlopen" = unknown; then
+ AC_MSG_CHECKING(whether matz's dln works)
+ cat confdefs.h > config.h
+ AC_CACHE_VAL(rb_cv_dln_a_out,
+ [AC_TRY_COMPILE([
+#define USE_DLN_A_OUT
+#include "dln.c"
+],
+ [],
+ 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
+ dln_a_out_works=yes
+ AC_DEFINE(USE_DLN_A_OUT)
+ fi
+ fi
+fi
+
+if test "$dln_a_out_works" = yes; then
if test "$GCC" = yes; then
STATIC=-static
else
@@ -147,45 +262,48 @@ if test "$rb_cv_dln_a_out" = yes; then
DLEXT=o
AC_DEFINE(DLEXT, ".o")
CCDLFLAGS=
- LDCMD=
-
else
-
- AC_CANONICAL_HOST
case "$host_os" in
hpux*) DLEXT=sl
AC_DEFINE(DLEXT, ".sl");;
+ nextstep*) DLEXT=o
+ AC_DEFINE(DLEXT, ".o");;
*) DLEXT=so
AC_DEFINE(DLEXT, ".so");;
esac
+fi
- if test "$GCC" = yes; then
- CCDLFLAGS=-fpic
- else
- case "$host_os" in
- hpux*) CCDLFLAGS='+z';;
- solaris*|irix*) CCDLFLAGS='-K pic' ;;
- sunos*) CCDLFLAGS='-pic' ;;
- svr4*|esix*) CCDLFLAGS='-Kpic' ;;
- *) CCDLFLAGS='' ;;
- esac
- fi
-
- case "$host_os" in
- 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
+AC_SUBST(STRIP)dnl
+if test "$with_dln_a_out" = yes; then
+ STRIP=true
+else
+ STRIP=strip
fi
+case "$host_os" in
+ linux*)
+ STRIP='strip -S -x';;
+ nextstep*)
+ STRIP='strip -A -n';;
+esac
+
+EXTSTATIC=
+AC_SUBST(EXTSTATIC)dnl
+AC_ARG_WITH(static-linked-ext,
+ [--with-static-linked-ext link external modules statically],
+ [case $withval in
+ yes) STATIC=
+ EXTSTATIC=static;;
+ *) ;;
+ esac])
+
if test "$prefix" = NONE; then
- AC_DEFINE_UNQUOTED(RUBY_LIB, ".:${ac_default_prefix}/lib/ruby")
-else
- AC_DEFINE_UNQUOTED(RUBY_LIB, ".:${prefix}/lib/ruby")
+ prefix=$ac_default_prefix
fi
+AC_DEFINE_UNQUOTED(RUBY_LIB, "${prefix}/lib/ruby:.")
+AC_SUBST(archlib)dnl
+archlib="${prefix}/lib/ruby/${host_cpu}-${host_os}"
+AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "$archlib")
echo "creating config.h"
cat confdefs.h > config.h
diff --git a/defines.h b/defines.h
index 2eb509f214..bef61b00fa 100644
--- a/defines.h
+++ b/defines.h
@@ -16,10 +16,21 @@
#define EUC
#undef SJIS
-#define SAFE_SIGHANDLE
+#ifdef NeXT
+#define S_IXUSR _S_IXUSR /* execute/search permission, owner */
+#define S_IXGRP 0000010 /* execute/search permission, group */
+#define S_IXOTH 0000001 /* execute/search permission, other */
+#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))
+#endif /* NeXT */
#ifdef NT
#include "missing/nt.h"
#endif
+#ifdef sparc
+#define FLUSH_REGISTER_WINDOWS asm("ta 3")
+#else
+#define FLUSH_REGISTER_WINDOWS /* empty */
+#endif
+
#endif
diff --git a/dir.c b/dir.c
index f291b94da2..a1a6114406 100644
--- a/dir.c
+++ b/dir.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:28 $
created at: Wed Jan 5 09:51:01 JST 1994
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -43,10 +43,11 @@
# endif
#endif
+#include <errno.h>
+
char *getenv();
static VALUE cDir;
-static ID id_dir;
static void
free_dir(dir)
@@ -66,11 +67,17 @@ dir_s_open(dir_class, dirname)
Check_Type(dirname, T_STRING);
dirp = opendir(dirname->ptr);
- if (dirp == NULL) Fail("Can't open directory %s", dirname->ptr);
+ if (dirp == NULL) {
+ if (errno == EMFILE || errno == ENFILE) {
+ gc();
+ dirp = opendir(dirname->ptr);
+ }
+ if (dirp == NULL) {
+ rb_sys_fail(dirname->ptr);
+ }
+ }
- obj = obj_alloc(dir_class);
- if (!id_dir) id_dir = rb_intern("dir");
- Make_Data_Struct(obj, id_dir, DIR*, 0, free_dir, d);
+ obj = Make_Data_Struct(dir_class, DIR*, 0, free_dir, d);
*d = dirp;
return obj;
@@ -84,8 +91,7 @@ closeddir()
#define GetDIR(obj, dirp) {\
DIR **_dp;\
- if (!id_dir) id_dir = rb_intern("dir");\
- Get_Data_Struct(obj, id_dir, DIR*, _dp);\
+ Get_Data_Struct(obj, DIR*, _dp);\
dirp = *_dp;\
if (dirp == NULL) closeddir();\
}
@@ -94,14 +100,14 @@ static VALUE
dir_each(dir)
VALUE dir;
{
- extern VALUE rb_lastline;
DIR *dirp;
struct dirent *dp;
+ VALUE file;
GetDIR(dir, dirp);
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- rb_lastline = str_new(dp->d_name, NAMLEN(dp));
- rb_yield(rb_lastline);
+ file = str_new(dp->d_name, NAMLEN(dp));
+ rb_yield(file);
}
return dir;
}
@@ -113,9 +119,13 @@ dir_tell(dir)
DIR *dirp;
int pos;
+#if !defined(__CYGWIN32__)
GetDIR(dir, dirp);
pos = telldir(dirp);
return int2inum(pos);
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -124,9 +134,13 @@ dir_seek(dir, pos)
{
DIR *dirp;
+#if !defined(__CYGWIN32__)
GetDIR(dir, dirp);
seekdir(dirp, NUM2INT(pos));
return dir;
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -146,8 +160,8 @@ dir_close(dir)
{
DIR **dirpp;
- Get_Data_Struct(dir, id_dir, DIR*, dirpp);
- if (*dirpp == NULL) Fail("already closed directory");
+ Get_Data_Struct(dir, DIR*, dirpp);
+ if (*dirpp == NULL) closeddir();
closedir(*dirpp);
*dirpp = NULL;
@@ -176,7 +190,7 @@ dir_s_chdir(argc, argv, obj)
}
if (chdir(dist) < 0)
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
return INT2FIX(0);
}
@@ -189,9 +203,9 @@ dir_s_getwd(dir)
char path[MAXPATHLEN];
#ifdef HAVE_GETCWD
- if (getcwd(path, sizeof(path)) == 0) Fail(path);
+ if (getcwd(path, sizeof(path)) == 0) rb_sys_fail(path);
#else
- if (getwd(path) == 0) Fail(path);
+ if (getwd(path) == 0) rb_sys_fail(path);
#endif
return str_new2(path);
@@ -201,12 +215,16 @@ static VALUE
dir_s_chroot(dir, path)
VALUE dir, path;
{
+#if !defined(DJGPP) && !defined(__CYGWIN32__)
Check_Type(path, T_STRING);
if (chroot(RSTRING(path)->ptr) == -1)
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
return INT2FIX(0);
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -346,6 +364,17 @@ dir_s_glob(dir, str)
return ary;
}
+static VALUE
+dir_foreach(io, dirname)
+ VALUE io;
+ struct RString *dirname;
+{
+ VALUE dir;
+
+ dir = dir_s_open(cDir, dirname);
+ return rb_ensure(dir_each, dir, dir_close, dir);
+}
+
void
Init_Dir()
{
@@ -356,6 +385,7 @@ Init_Dir()
rb_include_module(cDir, mEnumerable);
rb_define_singleton_method(cDir, "open", dir_s_open, 1);
+ rb_define_singleton_method(cDir, "foreach", dir_foreach, 1);
rb_define_method(cDir,"each", dir_each, 0);
rb_define_method(cDir,"rewind", dir_rewind, 0);
diff --git a/dln.c b/dln.c
index 84ffef3aac..b4005e973c 100644
--- a/dln.c
+++ b/dln.c
@@ -6,10 +6,14 @@
$Date: 1994/12/09 01:28:23 $
created at: Tue Jan 18 17:05:06 JST 1994
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
+#ifdef _AIX
+#pragma alloca
+#endif
+
#include "config.h"
#include "defines.h"
#include "dln.h"
@@ -57,7 +61,7 @@ int eaccess();
#endif
#ifndef FUNCNAME_PATTERN
-# if defined(hpux) || defined(__NetBSD__) || defined(__BORLANDC__)
+# if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__) || defined(__FreeBSD__)
# define FUNCNAME_PATTERN "_Init_%.200s"
# else
# define FUNCNAME_PATTERN "Init_%.200s"
@@ -276,7 +280,7 @@ sym_hash(hdrp, syms)
struct nlist *sym = syms;
struct nlist *end = syms + (hdrp->a_syms / sizeof(struct nlist));
- tbl = st_init_table(strcmp, st_strhash);
+ tbl = st_init_strtable();
if (tbl == NULL) {
dln_errno = errno;
return NULL;
@@ -345,12 +349,11 @@ dln_init(prog)
p++;
}
*p = '\0';
- printf("%s\n", buf);
return dln_init(buf);
}
dln_init_p = 1;
- undef_tbl = st_init_table(strcmp, st_strhash);
+ undef_tbl = st_init_strtable();
close(fd);
return 0;
@@ -462,7 +465,7 @@ link_undef(name, base, reloc)
break;
}
if (reloc_tbl == NULL) {
- reloc_tbl = st_init_table(ST_NUMCMP, ST_NUMHASH);
+ reloc_tbl = st_init_numtable();
}
st_insert(reloc_tbl, u_no++, obj);
}
@@ -548,6 +551,25 @@ unlink_undef(name, value)
st_foreach(reloc_tbl, reloc_undef, &arg);
}
+#ifdef N_INDR
+struct indr_data {
+ char *name0, *name1;
+};
+
+static int
+reloc_repl(no, undef, data)
+ int no;
+ struct undef *undef;
+ struct indr_data *data;
+{
+ if (strcmp(data->name0, undef->name) == 0) {
+ free(undef->name);
+ undef->name = strdup(data->name1);
+ }
+ return ST_CONTINUE;
+}
+#endif
+
static int
load_1(fd, disp, need_init)
int fd;
@@ -581,6 +603,32 @@ load_1(fd, disp, need_init)
struct nlist *old_sym;
int value = sym->n_value;
+#ifdef N_INDR
+ if (sym->n_type == (N_INDR | N_EXT)) {
+ char *key = sym->n_un.n_name;
+
+ if (st_lookup(sym_tbl, sym[1].n_un.n_name, &old_sym)) {
+ if (st_delete(undef_tbl, &key, NULL)) {
+ unlink_undef(key, old_sym->n_value);
+ free(key);
+ }
+ }
+ else {
+ struct indr_data data;
+
+ data.name0 = sym->n_un.n_name;
+ data.name1 = sym[1].n_un.n_name;
+ st_foreach(reloc_tbl, reloc_repl, &data);
+
+ st_insert(undef_tbl, strdup(sym[1].n_un.n_name), NULL);
+ if (st_delete(undef_tbl, &key, NULL)) {
+ free(key);
+ }
+ }
+ sym += 2;
+ continue;
+ }
+#endif
if (sym->n_type == (N_UNDF | N_EXT)) {
if (st_lookup(sym_tbl, sym->n_un.n_name, &old_sym) == 0) {
old_sym = NULL;
@@ -624,7 +672,7 @@ load_1(fd, disp, need_init)
sym = syms;
while (sym < end) {
struct nlist *new_sym;
- char *key;
+ char *key, *name;
switch (sym->n_type) {
case N_COMM:
@@ -764,7 +812,7 @@ load_1(fd, disp, need_init)
if (strcmp(name+1, "libs_to_be_linked") == 0) {
libs_to_be_linked = (char**)sym->n_value;
}
- if (strcmp(name+1, buf) == 0) {
+ else if (strcmp(name+1, buf) == 0) {
init_p = 1;
((int (*)())sym->n_value)();
}
@@ -808,6 +856,7 @@ search_undef(key, value, lib_tbl)
int value;
st_table *lib_tbl;
{
+#if 0
static char *last = "";
int offset;
@@ -817,6 +866,13 @@ search_undef(key, value, lib_tbl)
target_offset = offset;
}
return ST_STOP;
+#else
+ int offset;
+
+ if (st_lookup(lib_tbl, key, &offset) == 0) return ST_CONTINUE;
+ target_offset = offset;
+ return ST_STOP;
+#endif
}
struct symdef {
@@ -879,7 +935,7 @@ load_lib(lib)
if (strncmp(ahdr.ar_name, "__.SYMDEF", 9) == 0) {
/* make hash table from __.SYMDEF */
- lib_tbl = st_init_table(strcmp, st_strhash);
+ lib_tbl = st_init_strtable();
data = (int*)xmalloc(size);
if (data == NULL) goto syserr;
size = read(fd, data, size);
@@ -1020,6 +1076,11 @@ dln_sym(name)
#include <ctype.h> /* for isdigit() */
#include <errno.h> /* for global errno */
#include <string.h> /* for strerror() */
+#include <sys/ldr.h>
+#endif
+
+#ifdef NeXT
+/*#include <mach-o/rld.h>*/
#endif
static char *
@@ -1095,8 +1156,8 @@ aix_loaderror(char *pathname)
ERRBUF_APPEND("\n");
}
errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
- Fail(errbuf);
-return;
+ LoadError(errbuf);
+ return;
}
#endif
@@ -1125,9 +1186,12 @@ dln_load(file)
# ifndef RTLD_LAZY
# define RTLD_LAZY 1
# endif
+# ifndef RTLD_GLOBAL
+# define RTLD_GLOBAL 0
+# endif
/* Load file */
- if ((handle = dlopen(file, RTLD_LAZY)) == NULL) {
+ if ((handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
goto failed;
}
@@ -1150,13 +1214,14 @@ dln_load(file)
flags = BIND_DEFERRED;
lib = shl_load(file, flags, 0);
if (lib == NULL) {
- char buf[256];
- Fail("Failed to load %.200s", file);
+ rb_sys_fail(file);
}
shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct);
if (init_fct == NULL) {
- shl_findsym(&lib, buf, TYPE_DATA, (void*)&init_fct);
+ shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct);
if (init_fct == NULL) {
+ extern int errno;
+ errno = ENOSYM;
rb_sys_fail(file);
}
}
@@ -1179,14 +1244,54 @@ dln_load(file)
}
#endif /* _AIX */
+#ifdef NeXT
+#define DLN_DEFINED
+/*----------------------------------------------------
+ By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
+
+ Special Thanks...
+ Yu tomoak-i@is.aist-nara.ac.jp,
+ Mi hisho@tasihara.nest.or.jp,
+ and... Miss ARAI Akino(^^;)
+ ----------------------------------------------------*/
+ {
+ unsigned long init_address;
+ char *object_files[2] = {NULL, NULL};
+
+ void (*init_fct)();
+ int len = strlen(file);
+ char *point;
+ char init_name[len +7];
+
+ object_files[0] = file;
+
+ /* Load object file, if return value ==0 , load failed*/
+ if(rld_load(NULL, NULL, object_files, NULL) == 0) {
+ LoadError("Failed to load %.200s", file);
+ }
+
+ /* lookup the initial function */
+ if(rld_lookup(NULL, buf, &init_address) == 0) {
+ LoadError("Failed to lookup Init function %.200s",file);
+ }
+
+ /* Cannot call *init_address directory, so copy this value to
+ funtion pointer */
+
+ init_fct = (void(*)())init_address;
+ (*init_fct)();
+ return ;
+ }
+#endif
+
#ifndef DLN_DEFINED
- Fail("dynamic link not supported");
+ rb_notimplement("dynamic link not supported");
#endif
#endif /* USE_DLN_A_OUT */
-#ifndef _AIX
+#if !defined(_AIX) && !defined(NeXT)
failed:
- Fail("%s - %s", dln_strerror(), file);
+ LoadError("%s - %s", dln_strerror(), file);
#endif
}
@@ -1228,8 +1333,7 @@ dln_find_1(fname, path, exe_flag)
if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0)
return fname;
- for (dp = path;; dp = ++ep)
- {
+ for (dp = path;; dp = ++ep) {
register int l;
int i;
int fspace;
@@ -1243,8 +1347,7 @@ dln_find_1(fname, path, exe_flag)
l = ep - dp;
bp = fbuf;
fspace = sizeof fbuf - 2;
- if (l > 0)
- {
+ if (l > 0) {
/*
** If the length of the component is zero length,
** start from the current directory. If the
@@ -1253,13 +1356,11 @@ dln_find_1(fname, path, exe_flag)
** take the path literally.
*/
- if (*dp == '~' && (l == 1 || dp[1] == '/'))
- {
+ if (*dp == '~' && (l == 1 || dp[1] == '/')) {
char *home;
home = getenv("HOME");
- if (home != NULL)
- {
+ if (home != NULL) {
i = strlen(home);
if ((fspace -= i) < 0)
goto toolong;
@@ -1269,8 +1370,7 @@ dln_find_1(fname, path, exe_flag)
dp++;
l--;
}
- if (l > 0)
- {
+ if (l > 0) {
if ((fspace -= l) < 0)
goto toolong;
memcpy(bp, dp, l);
@@ -1284,9 +1384,8 @@ dln_find_1(fname, path, exe_flag)
/* now append the file name */
i = strlen(fname);
- if ((fspace -= i) < 0)
- {
- toolong:
+ if ((fspace -= i) < 0) {
+ toolong:
fprintf(stderr, "openpath: pathname too long (ignored)\n");
*bp = '\0';
fprintf(stderr, "\tDirectory \"%s\"\n", fbuf);
diff --git a/enum.c b/enum.c
index df277a504a..39c09dbec8 100644
--- a/enum.c
+++ b/enum.c
@@ -6,20 +6,19 @@
$Date: 1995/01/10 10:42:29 $
created at: Fri Oct 1 15:15:19 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
VALUE mEnumerable;
-static ID id_each, id_match, id_cmp;
+static ID id_each, id_eqq, id_cmp;
void
rb_each(obj)
VALUE obj;
{
- if (!id_each) id_each = rb_intern("each");
rb_funcall(obj, id_each, 0, 0);
}
@@ -27,8 +26,7 @@ static void
grep_i(i, arg)
VALUE i, *arg;
{
- if (!id_match) id_match = rb_intern("=~");
- if (rb_funcall(arg[0], id_match, 1, i)) {
+ if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
ary_push(arg[1], i);
}
}
@@ -37,8 +35,7 @@ static void
grep_iter_i(i, pat)
VALUE i, pat;
{
- if (!id_match) id_match = rb_intern("=~");
- if (rb_funcall(pat, id_match, 1, i)) {
+ if (RTEST(rb_funcall(pat, id_eqq, 1, i))) {
rb_yield(i);
}
}
@@ -61,33 +58,47 @@ enum_grep(obj, pat)
}
}
+struct find_arg {
+ int found;
+ VALUE val;
+};
+
static void
-find_i(i, foundp)
+find_i(i, arg)
VALUE i;
- int *foundp;
+ struct find_arg *arg;
{
- if (rb_yield(i)) {
- *foundp = TRUE;
+ if (RTEST(rb_yield(i))) {
+ arg->found = TRUE;
+ arg->val = i;
rb_break();
}
}
static VALUE
-enum_find(obj)
+enum_find(argc, argv, obj)
+ int argc;
+ VALUE argv;
VALUE obj;
{
- int enum_found;
-
- enum_found = FALSE;
- rb_iterate(rb_each, obj, find_i, &enum_found);
- return enum_found;
+ struct find_arg arg;
+ VALUE if_none;
+
+ rb_scan_args(argc, argv, "01", &if_none);
+ arg.found = FALSE;
+ rb_iterate(rb_each, obj, find_i, &arg);
+ if (arg.found) {
+ return arg.val;
+ }
+ if (NIL_P(if_none)) return Qnil;
+ return rb_eval_cmd(if_none, Qnil);
}
static void
find_all_i(i, tmp)
VALUE i, tmp;
{
- if (rb_yield(i)) {
+ if (RTEST(rb_yield(i))) {
ary_push(tmp, i);
}
}
@@ -99,7 +110,7 @@ enum_find_all(obj)
VALUE tmp;
tmp = ary_new();
- rb_iterate(rb_each, obj, find_all_i, 0);
+ rb_iterate(rb_each, obj, find_all_i, tmp);
return tmp;
}
@@ -111,7 +122,7 @@ collect_i(i, tmp)
VALUE retval;
retval = rb_yield(i);
- if (retval) {
+ if (RTEST(retval)) {
ary_push(tmp, retval);
}
}
@@ -179,23 +190,37 @@ min_i(i, min)
{
VALUE cmp;
- if (*min == Qnil)
+ if (NIL_P(*min))
*min = i;
else {
- if (!id_cmp) id_cmp = rb_intern("<=>");
cmp = rb_funcall(i, id_cmp, 1, *min);
if (FIX2INT(cmp) < 0)
*min = i;
}
}
+static void
+min_ii(i, min)
+ VALUE i, *min;
+{
+ VALUE cmp;
+
+ if (NIL_P(*min))
+ *min = i;
+ else {
+ cmp = rb_yield(assoc_new(i, *min));
+ if (FIX2INT(cmp) < 0)
+ *min = i;
+ }
+}
+
static VALUE
enum_min(obj)
VALUE obj;
{
VALUE min = Qnil;
- rb_iterate(rb_each, obj, min_i, &min);
+ rb_iterate(rb_each, obj, iterator_p()?min_ii:min_i, &min);
return min;
}
@@ -205,23 +230,37 @@ max_i(i, max)
{
VALUE cmp;
- if (*max == Qnil)
+ if (NIL_P(*max))
*max = i;
else {
- if (!id_cmp) id_cmp = rb_intern("<=>");
cmp = rb_funcall(i, id_cmp, 1, *max);
if (FIX2INT(cmp) > 0)
*max = i;
}
}
+static void
+max_ii(i, max)
+ VALUE i, *max;
+{
+ VALUE cmp;
+
+ if (NIL_P(*max))
+ *max = i;
+ else {
+ cmp = rb_yield(assoc_new(i, *max));
+ if (FIX2INT(cmp) > 0)
+ *max = i;
+ }
+}
+
static VALUE
enum_max(obj)
VALUE obj;
{
VALUE max = Qnil;
- rb_iterate(rb_each, obj, max_i, &max);
+ rb_iterate(rb_each, obj, iterator_p()?max_ii:max_i, &max);
return max;
}
@@ -291,7 +330,7 @@ length_i(i, length)
(*length)++;
}
-static VALUE
+VALUE
enum_length(obj)
VALUE obj;
{
@@ -310,7 +349,7 @@ Init_Enumerable()
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", enum_find, -1);
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);
@@ -319,4 +358,9 @@ Init_Enumerable()
rb_define_method(mEnumerable,"index", enum_index, 1);
rb_define_method(mEnumerable,"member?", enum_member, 1);
rb_define_method(mEnumerable,"length", enum_length, 0);
+ rb_define_method(mEnumerable,"size", enum_length, 0);
+
+ id_eqq = rb_intern("===");
+ id_each = rb_intern("each");
+ id_cmp = rb_intern("<=>");
}
diff --git a/env.h b/env.h
index 5f31e5cebc..ff53def099 100644
--- a/env.h
+++ b/env.h
@@ -16,9 +16,11 @@ extern struct FRAME {
VALUE *argv;
ID last_func;
struct RClass *last_class;
+ VALUE cbase;
struct FRAME *prev;
char *file;
int line;
+ int iter;
} *the_frame;
extern struct SCOPE {
@@ -28,8 +30,9 @@ extern struct SCOPE {
int flag;
} *the_scope;
-#define SCOPE_ALLOCA 0
-#define SCOPE_MALLOC 1
+#define SCOPE_ALLOCA 0
+#define SCOPE_MALLOC 1
+#define SCOPE_NOSTACK 2
extern int rb_in_eval;
diff --git a/error.c b/error.c
index 6634663eb1..61d5468c0d 100644
--- a/error.c
+++ b/error.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:31 $
created at: Mon Aug 9 16:11:34 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -32,32 +32,41 @@ err_sprintf(buf, fmt, args)
sprintf(buf, "%s:%d: ", sourcefile, sourceline);
vsprintf((char*)buf+strlen(buf), fmt, args);
}
- if (buf[strlen(buf)-1] != '\n')
- strcat(buf, "\n");
}
static void
-err_print(fmt, args)
- char *fmt;
- va_list args;
+err_append(s)
+ char *s;
{
- extern errstr;
- char buf[BUFSIZ];
+ extern VALUE errinfo;
- err_sprintf(buf, fmt, args);
if (rb_in_eval) {
- if (errstr == Qnil) {
- errstr = str_new2(buf);
+ if (NIL_P(errinfo)) {
+ errinfo = str_new2(s);
}
else {
- str_cat(errstr, buf, strlen(buf));
+ str_cat(errinfo, "\n", 1);
+ str_cat(errinfo, s, strlen(s));
}
}
else {
- fputs(buf, stderr);
+ fputs(s, stderr);
+ fputs("\n", stderr);
+ fflush(stderr);
}
}
+static void
+err_print(fmt, args)
+ char *fmt;
+ va_list args;
+{
+ char buf[BUFSIZ];
+
+ err_sprintf(buf, fmt, args);
+ err_append(buf);
+}
+
void
Error(fmt, va_alist)
char *fmt;
@@ -71,18 +80,18 @@ Error(fmt, va_alist)
nerrs++;
}
-int
-yyerror(msg)
- char *msg;
+void
+Error_Append(fmt, va_alist)
+ char *fmt;
+ va_dcl
{
- static char *f;
- static int line;
+ va_list args;
+ char buf[BUFSIZ];
- if (line == sourceline && strcmp(f, sourcefile) == 0)
- return;
- f = sourcefile; line = sourceline;
- Error("%s", msg);
- return 0;
+ va_start(args);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+ err_append(buf);
}
void
@@ -103,32 +112,226 @@ Warning(fmt, va_alist)
}
void
-Fatal(fmt, va_alist)
+Bug(fmt, va_alist)
char *fmt;
va_dcl
{
+ char buf[BUFSIZ];
va_list args;
+ sprintf(buf, "[BUG] %s", fmt);
+ rb_in_eval = 0;
+
va_start(args);
- err_print(fmt, args);
+ err_print(buf, args);
va_end(args);
- rb_exit(1);
+ abort();
}
+static struct types {
+ int type;
+ char *name;
+} builtin_types[] = {
+ T_NIL, "nil",
+ T_OBJECT, "Object",
+ T_CLASS, "Class",
+ T_ICLASS, "iClass", /* internal use: mixed-in module holder */
+ T_MODULE, "Module",
+ T_FLOAT, "Float",
+ T_STRING, "String",
+ T_REGEXP, "Regexp",
+ T_ARRAY, "Array",
+ T_FIXNUM, "Fixnum",
+ T_HASH, "Hash",
+ T_STRUCT, "Struct",
+ T_BIGNUM, "Bignum",
+ T_FILE, "File",
+ T_TRUE, "TRUE",
+ T_FALSE, "FALSE",
+ T_DATA, "Data", /* internal use: wrapped C pointers */
+ T_MATCH, "Match", /* data of $~ */
+ T_VARMAP, "Varmap", /* internal use: dynamic variables */
+ T_SCOPE, "Scope", /* internal use: variable scope */
+ T_NODE, "Node", /* internal use: syntax tree node */
+ -1, 0,
+};
+
+extern void TypeError();
+
void
-Bug(fmt, va_alist)
+Check_Type(x, t)
+ VALUE x;
+ int t;
+{
+ struct types *type = builtin_types;
+
+ if (TYPE(x)!=(t)) {
+ while (type->type >= 0) {
+ if (type->type == t) {
+ TypeError("wrong argument type %s (expected %s)",
+ rb_class2name(CLASS_OF(x)), type->name);
+ }
+ type++;
+ }
+ Bug("unknown type 0x%x", t);
+ }
+}
+
+/* exception classes */
+#include "errno.h"
+
+extern VALUE cString;
+VALUE eGlobalExit, eException;
+VALUE eSystemExit, eInterrupt, eFatal;
+VALUE eRuntimeError;
+VALUE eSyntaxError;
+VALUE eTypeError;
+VALUE eArgError;
+VALUE eNameError;
+VALUE eIndexError;
+VALUE eNotImpError;
+VALUE eLoadError;
+
+VALUE eSystemCallError;
+VALUE mErrno;
+
+VALUE
+exc_new0(etype, ptr, len)
+ VALUE etype;
+ char *ptr;
+ UINT len;
+{
+ NEWOBJ(exc, struct RString);
+ OBJSETUP(exc, etype, T_STRING);
+
+ exc->len = len;
+ exc->orig = 0;
+ exc->ptr = ALLOC_N(char,len+1);
+ if (ptr) {
+ memcpy(exc->ptr, ptr, len);
+ }
+ exc->ptr[len] = '\0';
+ return (VALUE)exc;
+}
+
+VALUE
+exc_new(etype, s)
+ VALUE etype;
+ char *s;
+{
+ return exc_new0(etype, s, strlen(s));
+}
+
+VALUE
+exc_new2(etype, str)
+ VALUE etype;
+ struct RString *str;
+{
+ Check_Type(str, T_STRING);
+ return exc_new(etype, str->ptr, str->len);
+}
+
+static VALUE
+exc_s_new(argc, argv, etype)
+ int argc;
+ VALUE *argv;
+ VALUE etype;
+{
+ VALUE arg;
+
+ if (rb_scan_args(argc, argv, "01", &arg) == 0) {
+ return exc_new0(etype, 0, 0);
+ }
+ Check_Type(arg, T_STRING);
+ return exc_new2(etype, arg);
+}
+
+static VALUE *syserr_list;
+
+static void
+set_syserr(i, name)
+ int i;
+ char *name;
+{
+ syserr_list[i] = rb_define_class_under(mErrno, name, eSystemCallError);
+ rb_global_variable(&syserr_list[i]);
+}
+
+static void init_syserr();
+
+void
+Init_Exception()
+{
+ eGlobalExit = rb_define_class("GlobalExit", cString);
+ rb_define_method(eGlobalExit, "new", exc_s_new, -1);
+
+ eSystemExit = rb_define_class("SystemExit", eGlobalExit);
+ eFatal = rb_define_class("fatal", eGlobalExit);
+ eInterrupt = rb_define_class("Interrupt", eGlobalExit);
+
+ eException = rb_define_class("Exception", eGlobalExit);
+ eSyntaxError = rb_define_class("SyntaxError", eException);
+ eTypeError = rb_define_class("TypeError", eException);
+ eArgError = rb_define_class("ArgumentError", eException);
+ eNameError = rb_define_class("NameError", eException);
+ eIndexError = rb_define_class("IndexError", eException);
+ eNotImpError = rb_define_class("NotImplementError", eException);
+ eLoadError = rb_define_class("LoadError", eException);
+
+ eRuntimeError = rb_define_class("RuntimeError", eException);
+
+ init_syserr();
+}
+
+#define RAISE_ERROR(class) {\
+ va_list args;\
+ char buf[BUFSIZ];\
+\
+ va_start(args);\
+ vsprintf(buf, fmt, args);\
+ va_end(args);\
+\
+ rb_raise(exc_new(class, buf));\
+}
+
+void
+Raise(exc, fmt, va_alist)
char *fmt;
va_dcl
{
- char buf[BUFSIZ];
- va_list args;
+ RAISE_ERROR(exc);
+}
- sprintf(buf, "[BUG] %s", fmt);
+void
+TypeError(fmt, va_alist)
+ char *fmt;
+ va_dcl
+{
+ RAISE_ERROR(eTypeError);
+}
- va_start(args);
- err_print(buf, args);
- va_end(args);
- abort();
+void
+ArgError(fmt, va_alist)
+ char *fmt;
+ va_dcl
+{
+ RAISE_ERROR(eArgError);
+}
+
+void
+NameError(fmt, va_alist)
+ char *fmt;
+ va_dcl
+{
+ RAISE_ERROR(eNameError);
+}
+
+void
+IndexError(fmt, va_alist)
+ char *fmt;
+ va_dcl
+{
+ RAISE_ERROR(eIndexError);
}
void
@@ -136,6 +339,30 @@ Fail(fmt, va_alist)
char *fmt;
va_dcl
{
+ RAISE_ERROR(eRuntimeError);
+}
+
+void
+rb_notimplement()
+{
+ Raise(eNotImpError,
+ "The %s() function is unimplemented on this machine",
+ rb_id2name(the_frame->last_func));
+}
+
+void
+LoadError(fmt, va_alist)
+ char *fmt;
+ va_dcl
+{
+ RAISE_ERROR(eLoadError);
+}
+
+void
+Fatal(fmt, va_alist)
+ char *fmt;
+ va_dcl
+{
va_list args;
char buf[BUFSIZ];
@@ -143,7 +370,8 @@ Fail(fmt, va_alist)
vsprintf(buf, fmt, args);
va_end(args);
- rb_fail(str_new2(buf));
+ rb_in_eval = 0;
+ rb_fatal(exc_new(eFatal, buf));
}
void
@@ -153,39 +381,397 @@ rb_sys_fail(mesg)
char *strerror();
char buf[BUFSIZ];
extern int errno;
+ int n = errno;
- if (mesg == Qnil)
- sprintf(buf, "%s", strerror(errno));
- else
+ if (RTEST(mesg))
sprintf(buf, "%s - %s", strerror(errno), mesg);
+ else
+ sprintf(buf, "%s", strerror(errno));
errno = 0;
- rb_fail(str_new2(buf));
-}
-
-static char *builtin_types[] = {
- "Nil",
- "Object",
- "Class",
- "iClass",
- "Module",
- "Float",
- "String",
- "Regexp",
- "Array",
- "Fixnum",
- "Hash",
- "Struct",
- "Bignum",
- "Data",
- "Match",
-};
+ if (!syserr_list[n]) {
+ char name[6];
-void
-WrongType(x, t)
- VALUE x;
- int t;
+ sprintf(name, "E%03d", n);
+ set_syserr(n, name);
+ }
+ rb_raise(exc_new(syserr_list[n], buf));
+}
+
+extern int sys_nerr;
+
+static void
+init_syserr()
{
- Fail("wrong argument type %s (expected %s)",
- rb_class2name(CLASS_OF(x)), builtin_types[t]);
+ eSystemCallError = rb_define_class("SystemCallError", eException);
+ mErrno = rb_define_module("Errno");
+ syserr_list = ALLOC_N(VALUE, sys_nerr+1);
+ MEMZERO(syserr_list, VALUE, sys_nerr+1);
+
+#ifdef EPERM
+ set_syserr(EPERM, "EPERM");
+#endif
+#ifdef ENOENT
+ set_syserr(ENOENT, "ENOENT");
+#endif
+#ifdef ESRCH
+ set_syserr(ESRCH, "ESRCH");
+#endif
+#ifdef EINTR
+ set_syserr(EINTR, "EINTR");
+#endif
+#ifdef EIO
+ set_syserr(EIO, "EIO");
+#endif
+#ifdef ENXIO
+ set_syserr(ENXIO, "ENXIO");
+#endif
+#ifdef E2BIG
+ set_syserr(E2BIG, "E2BIG");
+#endif
+#ifdef ENOEXEC
+ set_syserr(ENOEXEC, "ENOEXEC");
+#endif
+#ifdef EBADF
+ set_syserr(EBADF, "EBADF");
+#endif
+#ifdef ECHILD
+ set_syserr(ECHILD, "ECHILD");
+#endif
+#ifdef EAGAIN
+ set_syserr(EAGAIN, "EAGAIN");
+#endif
+#ifdef ENOMEM
+ set_syserr(ENOMEM, "ENOMEM");
+#endif
+#ifdef EACCES
+ set_syserr(EACCES, "EACCES");
+#endif
+#ifdef EFAULT
+ set_syserr(EFAULT, "EFAULT");
+#endif
+#ifdef ENOTBLK
+ set_syserr(ENOTBLK, "ENOTBLK");
+#endif
+#ifdef EBUSY
+ set_syserr(EBUSY, "EBUSY");
+#endif
+#ifdef EEXIST
+ set_syserr(EEXIST, "EEXIST");
+#endif
+#ifdef EXDEV
+ set_syserr(EXDEV, "EXDEV");
+#endif
+#ifdef ENODEV
+ set_syserr(ENODEV, "ENODEV");
+#endif
+#ifdef ENOTDIR
+ set_syserr(ENOTDIR, "ENOTDIR");
+#endif
+#ifdef EISDIR
+ set_syserr(EISDIR, "EISDIR");
+#endif
+#ifdef EINVAL
+ set_syserr(EINVAL, "EINVAL");
+#endif
+#ifdef ENFILE
+ set_syserr(ENFILE, "ENFILE");
+#endif
+#ifdef EMFILE
+ set_syserr(EMFILE, "EMFILE");
+#endif
+#ifdef ENOTTY
+ set_syserr(ENOTTY, "ENOTTY");
+#endif
+#ifdef ETXTBSY
+ set_syserr(ETXTBSY, "ETXTBSY");
+#endif
+#ifdef EFBIG
+ set_syserr(EFBIG, "EFBIG");
+#endif
+#ifdef ENOSPC
+ set_syserr(ENOSPC, "ENOSPC");
+#endif
+#ifdef ESPIPE
+ set_syserr(ESPIPE, "ESPIPE");
+#endif
+#ifdef EROFS
+ set_syserr(EROFS, "EROFS");
+#endif
+#ifdef EMLINK
+ set_syserr(EMLINK, "EMLINK");
+#endif
+#ifdef EPIPE
+ set_syserr(EPIPE, "EPIPE");
+#endif
+#ifdef EDOM
+ set_syserr(EDOM, "EDOM");
+#endif
+#ifdef ERANGE
+ set_syserr(ERANGE, "ERANGE");
+#endif
+#ifdef EDEADLK
+ set_syserr(EDEADLK, "EDEADLK");
+#endif
+#ifdef ENAMETOOLONG
+ set_syserr(ENAMETOOLONG, "ENAMETOOLONG");
+#endif
+#ifdef ENOLCK
+ set_syserr(ENOLCK, "ENOLCK");
+#endif
+#ifdef ENOSYS
+ set_syserr(ENOSYS, "ENOSYS");
+#endif
+#ifdef ENOTEMPTY
+ set_syserr(ENOTEMPTY, "ENOTEMPTY");
+#endif
+#ifdef ELOOP
+ set_syserr(ELOOP, "ELOOP");
+#endif
+#ifdef EWOULDBLOCK
+ set_syserr(EWOULDBLOCK, "EWOULDBLOCK");
+#endif
+#ifdef ENOMSG
+ set_syserr(ENOMSG, "ENOMSG");
+#endif
+#ifdef EIDRM
+ set_syserr(EIDRM, "EIDRM");
+#endif
+#ifdef ECHRNG
+ set_syserr(ECHRNG, "ECHRNG");
+#endif
+#ifdef EL2NSYNC
+ set_syserr(EL2NSYNC, "EL2NSYNC");
+#endif
+#ifdef EL3HLT
+ set_syserr(EL3HLT, "EL3HLT");
+#endif
+#ifdef EL3RST
+ set_syserr(EL3RST, "EL3RST");
+#endif
+#ifdef ELNRNG
+ set_syserr(ELNRNG, "ELNRNG");
+#endif
+#ifdef EUNATCH
+ set_syserr(EUNATCH, "EUNATCH");
+#endif
+#ifdef ENOCSI
+ set_syserr(ENOCSI, "ENOCSI");
+#endif
+#ifdef EL2HLT
+ set_syserr(EL2HLT, "EL2HLT");
+#endif
+#ifdef EBADE
+ set_syserr(EBADE, "EBADE");
+#endif
+#ifdef EBADR
+ set_syserr(EBADR, "EBADR");
+#endif
+#ifdef EXFULL
+ set_syserr(EXFULL, "EXFULL");
+#endif
+#ifdef ENOANO
+ set_syserr(ENOANO, "ENOANO");
+#endif
+#ifdef EBADRQC
+ set_syserr(EBADRQC, "EBADRQC");
+#endif
+#ifdef EBADSLT
+ set_syserr(EBADSLT, "EBADSLT");
+#endif
+#ifdef EDEADLOCK
+ set_syserr(EDEADLOCK, "EDEADLOCK");
+#endif
+#ifdef EBFONT
+ set_syserr(EBFONT, "EBFONT");
+#endif
+#ifdef ENOSTR
+ set_syserr(ENOSTR, "ENOSTR");
+#endif
+#ifdef ENODATA
+ set_syserr(ENODATA, "ENODATA");
+#endif
+#ifdef ETIME
+ set_syserr(ETIME, "ETIME");
+#endif
+#ifdef ENOSR
+ set_syserr(ENOSR, "ENOSR");
+#endif
+#ifdef ENONET
+ set_syserr(ENONET, "ENONET");
+#endif
+#ifdef ENOPKG
+ set_syserr(ENOPKG, "ENOPKG");
+#endif
+#ifdef EREMOTE
+ set_syserr(EREMOTE, "EREMOTE");
+#endif
+#ifdef ENOLINK
+ set_syserr(ENOLINK, "ENOLINK");
+#endif
+#ifdef EADV
+ set_syserr(EADV, "EADV");
+#endif
+#ifdef ESRMNT
+ set_syserr(ESRMNT, "ESRMNT");
+#endif
+#ifdef ECOMM
+ set_syserr(ECOMM, "ECOMM");
+#endif
+#ifdef EPROTO
+ set_syserr(EPROTO, "EPROTO");
+#endif
+#ifdef EMULTIHOP
+ set_syserr(EMULTIHOP, "EMULTIHOP");
+#endif
+#ifdef EDOTDOT
+ set_syserr(EDOTDOT, "EDOTDOT");
+#endif
+#ifdef EBADMSG
+ set_syserr(EBADMSG, "EBADMSG");
+#endif
+#ifdef EOVERFLOW
+ set_syserr(EOVERFLOW, "EOVERFLOW");
+#endif
+#ifdef ENOTUNIQ
+ set_syserr(ENOTUNIQ, "ENOTUNIQ");
+#endif
+#ifdef EBADFD
+ set_syserr(EBADFD, "EBADFD");
+#endif
+#ifdef EREMCHG
+ set_syserr(EREMCHG, "EREMCHG");
+#endif
+#ifdef ELIBACC
+ set_syserr(ELIBACC, "ELIBACC");
+#endif
+#ifdef ELIBBAD
+ set_syserr(ELIBBAD, "ELIBBAD");
+#endif
+#ifdef ELIBSCN
+ set_syserr(ELIBSCN, "ELIBSCN");
+#endif
+#ifdef ELIBMAX
+ set_syserr(ELIBMAX, "ELIBMAX");
+#endif
+#ifdef ELIBEXEC
+ set_syserr(ELIBEXEC, "ELIBEXEC");
+#endif
+#ifdef EILSEQ
+ set_syserr(EILSEQ, "EILSEQ");
+#endif
+#ifdef ERESTART
+ set_syserr(ERESTART, "ERESTART");
+#endif
+#ifdef ESTRPIPE
+ set_syserr(ESTRPIPE, "ESTRPIPE");
+#endif
+#ifdef EUSERS
+ set_syserr(EUSERS, "EUSERS");
+#endif
+#ifdef ENOTSOCK
+ set_syserr(ENOTSOCK, "ENOTSOCK");
+#endif
+#ifdef EDESTADDRREQ
+ set_syserr(EDESTADDRREQ, "EDESTADDRREQ");
+#endif
+#ifdef EMSGSIZE
+ set_syserr(EMSGSIZE, "EMSGSIZE");
+#endif
+#ifdef EPROTOTYPE
+ set_syserr(EPROTOTYPE, "EPROTOTYPE");
+#endif
+#ifdef ENOPROTOOPT
+ set_syserr(ENOPROTOOPT, "ENOPROTOOPT");
+#endif
+#ifdef EPROTONOSUPPORT
+ set_syserr(EPROTONOSUPPORT, "EPROTONOSUPPORT");
+#endif
+#ifdef ESOCKTNOSUPPORT
+ set_syserr(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT");
+#endif
+#ifdef EOPNOTSUPP
+ set_syserr(EOPNOTSUPP, "EOPNOTSUPP");
+#endif
+#ifdef EPFNOSUPPORT
+ set_syserr(EPFNOSUPPORT, "EPFNOSUPPORT");
+#endif
+#ifdef EAFNOSUPPORT
+ set_syserr(EAFNOSUPPORT, "EAFNOSUPPORT");
+#endif
+#ifdef EADDRINUSE
+ set_syserr(EADDRINUSE, "EADDRINUSE");
+#endif
+#ifdef EADDRNOTAVAIL
+ set_syserr(EADDRNOTAVAIL, "EADDRNOTAVAIL");
+#endif
+#ifdef ENETDOWN
+ set_syserr(ENETDOWN, "ENETDOWN");
+#endif
+#ifdef ENETUNREACH
+ set_syserr(ENETUNREACH, "ENETUNREACH");
+#endif
+#ifdef ENETRESET
+ set_syserr(ENETRESET, "ENETRESET");
+#endif
+#ifdef ECONNABORTED
+ set_syserr(ECONNABORTED, "ECONNABORTED");
+#endif
+#ifdef ECONNRESET
+ set_syserr(ECONNRESET, "ECONNRESET");
+#endif
+#ifdef ENOBUFS
+ set_syserr(ENOBUFS, "ENOBUFS");
+#endif
+#ifdef EISCONN
+ set_syserr(EISCONN, "EISCONN");
+#endif
+#ifdef ENOTCONN
+ set_syserr(ENOTCONN, "ENOTCONN");
+#endif
+#ifdef ESHUTDOWN
+ set_syserr(ESHUTDOWN, "ESHUTDOWN");
+#endif
+#ifdef ETOOMANYREFS
+ set_syserr(ETOOMANYREFS, "ETOOMANYREFS");
+#endif
+#ifdef ETIMEDOUT
+ set_syserr(ETIMEDOUT, "ETIMEDOUT");
+#endif
+#ifdef ECONNREFUSED
+ set_syserr(ECONNREFUSED, "ECONNREFUSED");
+#endif
+#ifdef EHOSTDOWN
+ set_syserr(EHOSTDOWN, "EHOSTDOWN");
+#endif
+#ifdef EHOSTUNREACH
+ set_syserr(EHOSTUNREACH, "EHOSTUNREACH");
+#endif
+#ifdef EALREADY
+ set_syserr(EALREADY, "EALREADY");
+#endif
+#ifdef EINPROGRESS
+ set_syserr(EINPROGRESS, "EINPROGRESS");
+#endif
+#ifdef ESTALE
+ set_syserr(ESTALE, "ESTALE");
+#endif
+#ifdef EUCLEAN
+ set_syserr(EUCLEAN, "EUCLEAN");
+#endif
+#ifdef ENOTNAM
+ set_syserr(ENOTNAM, "ENOTNAM");
+#endif
+#ifdef ENAVAIL
+ set_syserr(ENAVAIL, "ENAVAIL");
+#endif
+#ifdef EISNAM
+ set_syserr(EISNAM, "EISNAM");
+#endif
+#ifdef EREMOTEIO
+ set_syserr(EREMOTEIO, "EREMOTEIO");
+#endif
+#ifdef EDQUOT
+ set_syserr(EDQUOT, "EDQUOT");
+#endif
}
diff --git a/eval.c b/eval.c
index c1363a6840..43a4bf07f6 100644
--- a/eval.c
+++ b/eval.c
@@ -11,8 +11,8 @@
************************************************/
#include "ruby.h"
-#include "env.h"
#include "node.h"
+#include "env.h"
#include "sig.h"
#include <stdio.h>
@@ -23,30 +23,21 @@
#ifdef HAVE_STRING_H
# include <string.h>
#else
-char *strchr();
char *strrchr();
#endif
-VALUE cProc;
+static VALUE cProc;
static VALUE proc_call();
-static void rb_clear_cache_body();
-static void rb_clear_cache_entry();
-
-/* #define TEST /* prints cache miss */
-#ifdef TEST
-#include <stdio.h>
-#endif
-
#define CACHE_SIZE 0x200
#define CACHE_MASK 0x1ff
#define EXPR1(c,m) ((((int)(c)>>3)^(m))&CACHE_MASK)
struct cache_entry { /* method hash table. */
ID mid; /* method's id */
+ ID mid0; /* method's original id */
struct RClass *class; /* receiver's class */
struct RClass *origin; /* where method defined */
- int nargs; /* # of args */
NODE *method;
int noex;
};
@@ -62,14 +53,7 @@ rb_add_method(class, mid, node, noex)
{
NODE *body;
- 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);
- }
- else {
- rb_clear_cache_entry(class, mid);
- }
+ if (NIL_P(class)) class = (struct RClass*)cObject;
body = NEW_METHOD(node, noex);
st_insert(class->m_tbl, mid, body);
}
@@ -83,7 +67,7 @@ search_method(class, id, origin)
while (!st_lookup(class->m_tbl, id, &body)) {
class = class->super;
- if (class == Qnil) return Qnil;
+ if (!class) return 0;
}
if (origin) *origin = class;
@@ -102,29 +86,25 @@ rb_get_method_body(classp, idp, noexp)
struct RClass *origin;
struct cache_entry *ent;
- if ((body = search_method(class, id, &origin)) == FALSE) {
- return Qnil;
+ if ((body = search_method(class, id, &origin)) == 0) {
+ return 0;
}
- if (body->nd_body == Qnil) return Qnil;
+ if (!body->nd_body) return 0;
- ent = cache + EXPR1(class, id);
-#ifdef TEST
- if (ent->mid != 0) {
- fprintf(stderr, "0x%x 0x%x %x\n", class, id, EXPR1(class, id));
- }
-#endif
/* store in cache */
+ ent = cache + EXPR1(class, id);
ent->class = class;
ent->noex = body->nd_noex;
body = body->nd_body;
if (nd_type(body) == NODE_FBODY) {
+ ent->mid = id;
*classp = ent->origin = (struct RClass*)body->nd_orig;
- *idp = ent->mid = body->nd_mid;
+ *idp = ent->mid0 = body->nd_mid;
body = ent->method = body->nd_head;
}
else {
*classp = ent->origin = origin;
- ent->mid = id;
+ ent->mid = ent->mid0 = id;
ent->method = body;
}
@@ -142,17 +122,9 @@ rb_alias(class, name, def)
if (name == def) return;
body = search_method(class, def, &origin);
- if (body == Qnil || body->nd_body == Qnil) {
- Fail("undefined method `%s' for class `%s'",
- rb_id2name(def), rb_class2name(class));
- }
-
- if (st_lookup(class->m_tbl, name, &old)) {
- Warning("redefine %s", rb_id2name(name));
- rb_clear_cache_body(body);
- }
- else {
- rb_clear_cache_entry(class, name);
+ if (!body || !body->nd_body) {
+ NameError("undefined method `%s' for class `%s'",
+ rb_id2name(def), rb_class2name(class));
}
st_insert(class->m_tbl, name,
@@ -170,9 +142,9 @@ rb_export_method(class, name, noex)
struct RClass *origin;
body = search_method(class, name, &origin);
- if (body == Qnil) {
- Fail("undefined method `%s' for class `%s'",
- rb_id2name(name), rb_class2name(class));
+ if (!body) {
+ NameError("undefined method `%s' for class `%s'",
+ rb_id2name(name), rb_class2name(class));
}
if (body->nd_noex != noex) {
if (class == origin) {
@@ -200,85 +172,56 @@ method_boundp(class, id, ex)
return FALSE;
}
-VALUE
+int
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;
-{
- struct cache_entry *ent, *end;
-
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->method == body) {
- ent->class = Qnil;
- ent->mid = Qnil;
- }
- ent++;
- }
-}
-
-static void
-rb_clear_cache_entry(class, mid)
- struct RClass *class;
- ID mid;
-{
- struct cache_entry *ent;
-
- /* is it in the method cache? */
- ent = cache + EXPR1(class, mid);
- if (ent->mid == mid && ent->class == class) {
- ent->class = Qnil;
- ent->mid = Qnil;
- }
+ if (method_boundp(class, id, NOEX_PRIVATE))
+ return TRUE;
+ return FALSE;
}
void
-rb_clear_cache(class)
- struct RClass *class;
+rb_clear_cache()
{
struct cache_entry *ent, *end;
ent = cache; end = ent + CACHE_SIZE;
while (ent < end) {
- if (ent->origin == class) {
- ent->class = Qnil;
- ent->mid = Qnil;
- }
+ ent->mid = 0;
ent++;
}
}
-static ID match, each, aref, aset;
-VALUE errstr, errat;
+static ID init, eqq, each, aref, aset;
+VALUE errinfo = Qnil, errat = Qnil;
extern NODE *eval_tree;
extern int nerrs;
-extern VALUE TopSelf;
-VALUE Qself;
-
-#define PUSH_SELF(s) { \
- VALUE __saved_self__ = Qself; \
- Qself = s; \
+extern VALUE cKernel;
+extern VALUE eGlobalExit;
+extern VALUE eInterrupt;
+extern VALUE eSystemExit;
+extern VALUE eException;
+extern VALUE eRuntimeError;
+extern VALUE eSyntaxError;
+static VALUE eLocalJumpError;
-#define POP_SELF() Qself = __saved_self__; }
+extern VALUE TopSelf;
struct FRAME *the_frame;
struct SCOPE *the_scope;
static struct FRAME *top_frame;
-static struct SCOPE *top_scope;
+static struct SCOPE *top_scope;
#define PUSH_FRAME() { \
struct FRAME _frame; \
_frame.prev = the_frame; \
_frame.file = sourcefile; \
_frame.line = sourceline; \
+ _frame.iter = the_iter->iter; \
+ _frame.cbase = the_frame->cbase; \
the_frame = &_frame; \
#define POP_FRAME() the_frame = _frame.prev; }
@@ -289,6 +232,7 @@ struct BLOCK {
VALUE self;
struct FRAME frame;
struct SCOPE *scope;
+ struct RClass *class;
int level;
int iter;
struct RVarmap *d_vars;
@@ -297,24 +241,29 @@ struct BLOCK {
#define PUSH_BLOCK(v,b) { \
struct BLOCK _block; \
- _block.level = tag_level; \
+ _block.level = (int)&prot_tag; \
_block.var = v; \
_block.body = b; \
- _block.self = Qself; \
+ _block.self = self; \
_block.frame = *the_frame; \
+ _block.class = the_class; \
_block.frame.file = sourcefile; \
_block.frame.line = sourceline; \
_block.scope = the_scope; \
_block.d_vars = the_dyna_vars; \
_block.prev = the_block; \
- _block.iter = iter->iter; \
+ _block.iter = the_iter->iter; \
the_block = &_block; \
#define PUSH_BLOCK2(b) { \
- b->prev = the_block; \
- the_block = b; \
-
-#define POP_BLOCK() the_block = the_block->prev; }
+ struct BLOCK _block; \
+ _block = *b; \
+ _block.prev = the_block; \
+ the_block = &_block;
+
+#define POP_BLOCK() \
+ the_block = the_block->prev; \
+}
struct RVarmap *the_dyna_vars;
#define PUSH_VARS() { \
@@ -324,13 +273,28 @@ struct RVarmap *the_dyna_vars;
#define POP_VARS() the_dyna_vars = _old; }
VALUE
+dyna_var_defined(id)
+ ID id;
+{
+ struct RVarmap *vars = the_dyna_vars;
+
+ while (vars && vars->id) {
+ if (vars->id == id) return TRUE;
+ vars = vars->next;
+ }
+ return FALSE;
+}
+
+VALUE
dyna_var_ref(id)
ID id;
{
struct RVarmap *vars = the_dyna_vars;
- while (vars) {
- if (vars->id == id) return vars->val;
+ while (vars && vars->id) {
+ if (vars->id == id) {
+ return vars->val;
+ }
vars = vars->next;
}
return Qnil;
@@ -343,16 +307,16 @@ dyna_var_asgn(id, value)
{
struct RVarmap *vars = the_dyna_vars;
- while (vars) {
+ while (vars && vars->id) {
if (vars->id == id) {
vars->val = value;
- return;
+ return value;
}
vars = vars->next;
}
{
NEWOBJ(_vars, struct RVarmap);
- OBJSETUP(_vars, Qnil, T_VARMAP);
+ OBJSETUP(_vars, 0, T_VARMAP);
_vars->id = id;
_vars->val = value;
_vars->next = the_dyna_vars;
@@ -360,11 +324,22 @@ dyna_var_asgn(id, value)
}
return value;
}
-
+
+static VALUE
+dyna_var_mark()
+{
+ NEWOBJ(_vars, struct RVarmap);
+ OBJSETUP(_vars, 0, T_VARMAP);
+ _vars->id = 0;
+ _vars->val = Qnil;
+ _vars->next = the_dyna_vars;
+ the_dyna_vars = _vars;
+}
+
static struct iter {
int iter;
struct iter *prev;
-} *iter;
+} *the_iter;
#define ITER_NOT 0
#define ITER_PRE 1
@@ -372,20 +347,16 @@ static struct iter {
#define PUSH_ITER(i) { \
struct iter _iter; \
- _iter.prev = iter; \
+ _iter.prev = the_iter; \
_iter.iter = (i); \
- iter = &_iter; \
+ the_iter = &_iter; \
#define POP_ITER() \
- iter = _iter.prev; \
+ the_iter = _iter.prev; \
}
-static int tag_level, target_level;
static struct tag {
- int level;
jmp_buf buf;
- struct gc_list *gclist;
- VALUE self;
struct FRAME *frame;
struct iter *iter;
struct tag *prev;
@@ -393,57 +364,50 @@ static struct tag {
#define PUSH_TAG() { \
struct tag _tag; \
- _tag.level= ++tag_level; \
- _tag.self = Qself; \
_tag.frame = the_frame; \
- _tag.iter = iter; \
+ _tag.iter = the_iter; \
_tag.prev = prot_tag; \
- prot_tag = &_tag; \
+ prot_tag = &_tag;
-#define EXEC_TAG() (setjmp(prot_tag->buf))
+#define EXEC_TAG() ((NODE*)setjmp(prot_tag->buf))
-#define JUMP_TAG(val) { \
- Qself = prot_tag->self; \
+#define JUMP_TAG(st) { \
the_frame = prot_tag->frame; \
- iter = prot_tag->iter; \
- longjmp(prot_tag->buf,(val)); \
+ the_iter = prot_tag->iter; \
+ longjmp(prot_tag->buf,(int)(st)); \
}
+#define JUMP_TAG3(val,data1,data2) \
+ JUMP_TAG(newnode(NODE_TAG,(val),(data1),(data2)))
+
+#define JUMP_TAG2(val,data) JUMP_TAG3((val),(data),0)
+
#define POP_TAG() \
- tag_level--; \
prot_tag = _tag.prev; \
}
-#define TAG_RETURN 1
-#define TAG_BREAK 2
-#define TAG_CONTINUE 3
-#define TAG_RETRY 4
-#define TAG_REDO 5
-#define TAG_FAIL 6
-#define TAG_EXIT 7
+#define TAG_RETURN 0x1
+#define TAG_BREAK 0x2
+#define TAG_NEXT 0x3
+#define TAG_RETRY 0x4
+#define TAG_REDO 0x5
+#define TAG_RAISE 0x6
+#define TAG_THROW 0x7
+#define TAG_FATAL 0x8
-#define IN_BLOCK 0x08
+#define IN_BLOCK 0x10
struct RClass *the_class;
-struct class_link {
- struct RClass *class;
- struct class_link *prev;
-} *class_link;
#define PUSH_CLASS() { \
- struct class_link _link; \
- _link.class = the_class; \
- _link.prev = class_link; \
- class_link = &_link \
+ struct RClass *_class = the_class; \
-#define POP_CLASS() \
- the_class = class_link->class; \
- class_link = _link.prev; }
+#define POP_CLASS() the_class = _class; }
#define PUSH_SCOPE() { \
struct SCOPE *_old; \
NEWOBJ(_scope, struct SCOPE); \
- OBJSETUP(_scope, Qnil, T_SCOPE); \
+ OBJSETUP(_scope, 0, T_SCOPE); \
_old = the_scope; \
the_scope = _scope; \
@@ -452,54 +416,96 @@ struct class_link {
the_scope->local_vars = 0;\
the_scope->local_tbl = 0;\
}\
+ the_scope->flag |= SCOPE_NOSTACK;\
the_scope = _old;\
}
static VALUE rb_eval();
-static VALUE f_eval();
+static VALUE eval();
+static NODE *compile();
static VALUE rb_call();
VALUE rb_apply();
-VALUE rb_xstring();
-void rb_fail();
-
-VALUE rb_rescue();
static void module_setup();
static VALUE masign();
static void asign();
-static VALUE last_val;
-
extern VALUE rb_stderr;
extern int sourceline;
extern char *sourcefile;
-static ID last_func;
static void
-error_print(last_func)
- ID last_func;
+error_pos()
{
- if (errat) {
- fwrite(RSTRING(errat)->ptr, 1, RSTRING(errat)->len, stderr);
- if (last_func) {
- fprintf(stderr, ":in `%s': ", rb_id2name(last_func));
+ if (sourcefile) {
+ if (the_frame->last_func) {
+ fprintf(stderr, "%s:%d:in `%s': ", sourcefile, sourceline,
+ rb_id2name(the_frame->last_func));
}
else {
- fprintf(stderr, ": ");
+ fprintf(stderr, "%s:%d: ", sourcefile, sourceline);
}
}
+}
- if (errstr) {
- fwrite(RSTRING(errstr)->ptr, 1, RSTRING(errstr)->len, stderr);
- if (RSTRING(errstr)->ptr[RSTRING(errstr)->len - 1] != '\n') {
- putc('\n', stderr);
+static void
+error_print(state)
+ NODE *state;
+{
+ struct FRAME *frame = the_frame;
+ VALUE etype;
+
+ if (!NIL_P(errat)) {
+ VALUE mesg;
+
+ switch (TYPE(errat)) {
+ case T_STRING:
+ mesg = errat;
+ errat = Qnil;
+ break;
+ case T_ARRAY:
+ mesg = RARRAY(errat)->ptr[0];
+ break;
}
+ fwrite(RSTRING(mesg)->ptr, 1, RSTRING(mesg)->len, stderr);
+ fprintf(stderr, ": ");
+ }
+
+ etype = rb_class_path(CLASS_OF(errinfo));
+
+ if (verbose) {
+ fwrite(RSTRING(etype)->ptr, 1, RSTRING(etype)->len, stderr);
+ putc('|', stderr);
+ }
+ if (RSTRING(errinfo)->len == 0) {
+ fprintf(stderr, "unhandled exception.\n");
}
else {
- fprintf(stderr, "unhandled failure.\n");
+ fwrite(RSTRING(errinfo)->ptr, 1, RSTRING(errinfo)->len, stderr);
+ if (RSTRING(errinfo)->ptr[RSTRING(errinfo)->len - 1] != '\n') {
+ putc('\n', stderr);
+ }
+ }
+
+ if (!NIL_P(errat)) {
+ int i;
+ struct RArray *ep = RARRAY(errat);
+
+#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
+#define TRACE_HEAD 8
+#define TRACE_TAIL 5
+
+ for (i=1; i<ep->len; i++) {
+ fprintf(stderr, "\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
+ if (i == TRACE_HEAD && ep->len > TRACE_MAX) {
+ fprintf(stderr, "\t ... %d levels...\n",
+ ep->len - TRACE_HEAD - TRACE_TAIL);
+ i = ep->len - TRACE_TAIL;
+ }
+ }
}
}
@@ -511,9 +517,12 @@ ruby_init(argc, argv, envp)
int argc;
char **argv, **envp;
{
- int state;
static struct FRAME frame;
+ static struct iter iter;
+ NODE *state;
+
the_frame = top_frame = &frame;
+ the_iter = &iter;
origenviron = environ;
#ifdef NT
@@ -526,144 +535,171 @@ ruby_init(argc, argv, envp)
the_scope->local_tbl = 0;
top_scope = the_scope;
- PUSH_TAG();
- PUSH_ITER(ITER_NOT);
+ PUSH_TAG()
if ((state = EXEC_TAG()) == 0) {
rb_call_inits();
the_class = (struct RClass*)cObject;
+ the_frame->cbase = (VALUE)newnode(NODE_CREF,cObject,0,0);
ruby_options(argc, argv, envp);
}
- POP_ITER();
POP_TAG();
+ if (state) error_print(state);
POP_SCOPE();
the_scope = top_scope;
-
- if (state == TAG_EXIT) {
- rb_trap_exit();
- exit(FIX2UINT(last_val));
- }
- if (state) {
- error_print(last_func);
- }
}
static VALUE
-Eval()
+eval_node(self)
+ VALUE self;
{
VALUE result = Qnil;
NODE *tree;
- int state;
- if (!eval_tree) return Qnil;
+ if (!eval_tree) return FALSE;
tree = eval_tree;
eval_tree = 0;
- result = rb_eval(tree);
+ result = rb_eval(self, tree);
return result;
}
+int rb_in_eval;
+
+#ifdef THREAD
+static void thread_cleanup();
+static void thread_wait_other_threads();
+#endif
+
+static int exit_status;
+
void
ruby_run()
{
- int state;
+ NODE *state;
+ static NODE *ex;
if (nerrs > 0) exit(nerrs);
init_stack();
- rb_define_variable("$!", &errstr);
errat = Qnil; /* clear for execution */
PUSH_TAG();
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
- Eval();
+ eval_node(TopSelf);
+ }
+ POP_ITER();
+ POP_TAG();
+
+ if (state && !ex) ex = state;
+ PUSH_TAG();
+ PUSH_ITER(ITER_NOT);
+ if ((state = EXEC_TAG()) == 0) {
rb_trap_exit();
+#ifdef THREAD
+ thread_cleanup();
+ thread_wait_other_threads();
+#endif
+ }
+ else {
+ ex = state;
}
POP_ITER();
POP_TAG();
- switch (state) {
- case 0:
- break;
+ if (!ex) {
+ exit(0);
+ }
+
+ switch (ex->nd_tag) {
case TAG_RETURN:
- Fatal("unexpected return");
+ error_pos();
+ fprintf(stderr, "unexpected return\n");
+ exit(1);
break;
- case TAG_CONTINUE:
- Fatal("unexpected continue");
+ case TAG_NEXT:
+ error_pos();
+ fprintf(stderr, "unexpected next\n");
+ exit(1);
break;
case TAG_BREAK:
- Fatal("unexpected break");
+ error_pos();
+ fprintf(stderr, "unexpected break\n");
+ exit(1);
break;
case TAG_REDO:
- Fatal("unexpected redo");
+ error_pos();
+ fprintf(stderr, "unexpected redo\n");
+ exit(1);
break;
case TAG_RETRY:
- Fatal("retry outside of protect clause");
+ error_pos();
+ fprintf(stderr, "retry outside of protect clause\n");
+ exit(1);
break;
- case TAG_FAIL:
- error_print(last_func);
+ case TAG_RAISE:
+ case TAG_FATAL:
+ if (obj_is_kind_of(errinfo, eSystemExit)) {
+ exit(exit_status);
+ }
+ error_print(ex);
exit(1);
break;
- case TAG_EXIT:
- exit(FIX2UINT(last_val));
+ case TAG_THROW:
+ error_pos();
+ fprintf(stderr, "uncaught throw `%s'\n", rb_id2name(ex->nd_tlev));
+ exit(1);
break;
default:
- Bug("Unknown longjmp status %d", state);
+ Bug("Unknown longjmp status %d", ex->nd_tag);
break;
}
- exit(0);
}
static void
-syntax_error()
+compile_error(at)
+ char *at;
{
VALUE mesg;
- mesg = errstr;
+ mesg = errinfo;
nerrs = 0;
- errstr = str_new2("syntax error in eval():\n");
- str_cat(errstr, RSTRING(mesg)->ptr, RSTRING(mesg)->len);
- rb_fail(errstr);
+ errinfo = exc_new(eSyntaxError, "compile error in ");
+ str_cat(errinfo, at, strlen(at));
+ str_cat(errinfo, ":\n", 2);
+ str_cat(errinfo, RSTRING(mesg)->ptr, RSTRING(mesg)->len);
+ rb_raise(errinfo);
}
VALUE
rb_eval_string(str)
char *str;
{
+ VALUE v;
char *oldsrc = sourcefile;
- lex_setsrc("(eval)", str, strlen(str));
- eval_tree = 0;
- PUSH_VARS();
- yyparse();
- POP_VARS();
+ sourcefile = "(eval)";
+ v = eval(TopSelf, str_new2(str), Qnil);
sourcefile = oldsrc;
- if (nerrs == 0) {
- return Eval();
- }
- else {
- syntax_error();
- }
- return Qnil; /* not reached */
+
+ return v;
}
void
rb_eval_cmd(cmd, arg)
VALUE cmd, arg;
{
- int state;
+ NODE *state;
struct SCOPE *saved_scope;
if (TYPE(cmd) != T_STRING) {
- if (TYPE(cmd) == T_OBJECT
- && obj_is_kind_of(cmd, cProc)) {
+ if (obj_is_kind_of(cmd, cProc)) {
proc_call(cmd, arg);
return;
}
}
- PUSH_SELF(TopSelf);
PUSH_CLASS();
PUSH_TAG();
saved_scope = the_scope;
@@ -672,31 +708,29 @@ rb_eval_cmd(cmd, arg)
the_class = (struct RClass*)cObject;
if ((state = EXEC_TAG()) == 0) {
- f_eval(Qself, cmd);
+ eval(TopSelf, cmd, Qnil);
}
the_scope = saved_scope;
POP_TAG();
POP_CLASS();
- POP_SELF();
- switch (state) {
- case 0:
- break;
+ if (state == 0) return;
+ switch (state->nd_tag) {
case TAG_RETURN:
- Fatal("unexpected return");
+ Raise(eLocalJumpError, "unexpected return");
break;
- case TAG_CONTINUE:
- Fatal("unexpected continue");
+ case TAG_NEXT:
+ Raise(eLocalJumpError, "unexpected next");
break;
case TAG_BREAK:
- Fatal("unexpected break");
+ Raise(eLocalJumpError, "unexpected break");
break;
case TAG_REDO:
- Fatal("unexpected redo");
+ Raise(eLocalJumpError, "unexpected redo");
break;
case TAG_RETRY:
- Fatal("retry outside of protect clause");
+ Raise(eLocalJumpError, "retry outside of protect clause");
break;
default:
JUMP_TAG(state);
@@ -709,8 +743,7 @@ rb_trap_eval(cmd, sig)
VALUE cmd;
int sig;
{
-#ifdef SAFE_SIGHANDLE
- int state;
+ NODE *state;
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
@@ -721,9 +754,74 @@ rb_trap_eval(cmd, sig)
trap_immediate = 0;
JUMP_TAG(state);
}
-#else
- rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig)));
-#endif
+}
+
+static VALUE
+superclass(self, node)
+ VALUE self;
+ NODE *node;
+{
+ VALUE val;
+ NODE *state;
+
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ val = rb_eval(self, node);
+ }
+ POP_TAG();
+ if ((state && state->nd_tag == TAG_RAISE) || !val || TYPE(val) != T_CLASS){
+ switch (nd_type(node)) {
+ case NODE_COLON2:
+ TypeError("undefined superclass `%s'", rb_id2name(node->nd_mid));
+ case NODE_CVAR:
+ case NODE_CONST:
+ TypeError("undefined superclass `%s'", rb_id2name(node->nd_vid));
+ }
+ if (state) JUMP_TAG(state);
+ TypeError("superclass undefined");
+ }
+ if (state) JUMP_TAG(state);
+
+ return val;
+}
+
+static VALUE
+ev_const_defined(cref, id)
+ NODE *cref;
+ ID id;
+{
+ NODE *cbase = cref;
+
+ while (cbase && cbase->nd_clss != cObject) {
+ struct RClass *class = RCLASS(cbase->nd_clss);
+
+ if (class->iv_tbl &&
+ st_lookup(class->iv_tbl, id, 0)) {
+ return TRUE;
+ }
+ cbase = cbase->nd_next;
+ }
+ return rb_const_defined(cref->nd_clss, id);
+}
+
+static VALUE
+ev_const_get(cref, id)
+ NODE *cref;
+ ID id;
+{
+ NODE *cbase = cref;
+ VALUE result;
+
+ while (cbase && cbase->nd_clss != cObject) {
+ struct RClass *class = RCLASS(cbase->nd_clss);
+
+ if (class->iv_tbl &&
+ st_lookup(class->iv_tbl, id, &result)) {
+ return result;
+ }
+ cbase = cbase->nd_next;
+ }
+ return rb_const_get(cref->nd_clss, id);
}
#define SETUP_ARGS {\
@@ -739,9 +837,11 @@ rb_trap_eval(cmd, sig)
n = node->nd_args;\
argv = ALLOCA_N(VALUE,argc);\
for (i=0;i<argc;i++) {\
- argv[i] = rb_eval(n->nd_head);\
+ argv[i] = rb_eval(self,n->nd_head);\
n=n->nd_next;\
}\
+ sourceline = nd_line(node);\
+ sourcefile = node->file;\
}\
else {\
argc = 0;\
@@ -749,73 +849,111 @@ rb_trap_eval(cmd, sig)
}\
}\
else {\
- VALUE args = rb_eval(n);\
+ VALUE args = rb_eval(self,n);\
if (TYPE(args) != T_ARRAY)\
args = rb_to_a(args);\
argc = RARRAY(args)->len;\
argv = ALLOCA_N(VALUE, argc);\
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\
+ sourceline = nd_line(node);\
+ sourcefile = node->file;\
}\
}
-#define RETURN(v) do { result = (v); goto finish; } while (0)
+int
+rb_test_false_or_nil(v)
+ VALUE v;
+{
+ return (v != Qnil) && (v != FALSE);
+}
+
+static int handle_rescue();
+VALUE rb_yield_0();
static VALUE
-rb_eval(node)
+rb_eval(self, node)
+ VALUE self;
register NODE *node;
{
- int state;
+ NODE *state;
VALUE result = Qnil;
+#define RETURN(v) { result = (v); goto finish; }
+
again:
- if (node == Qnil) RETURN(Qnil);
+ if (!node) RETURN(Qnil);
- sourceline = node->line;
+ sourceline = nd_line(node);
sourcefile = node->file;
switch (nd_type(node)) {
case NODE_BLOCK:
while (node) {
- result = rb_eval(node->nd_head);
+ result = rb_eval(self, node->nd_head);
node = node->nd_next;
}
break;
+ /* begin .. end without clauses */
+ case NODE_BEGIN:
+ node = node->nd_body;
+ goto again;
+
+ /* nodes for speed-up(default match) */
+ case NODE_MATCH:
+ result = reg_match2(node->nd_head->nd_lit);
+ break;
+
+ /* nodes for speed-up(top-level loop for -n/-p) */
+ case NODE_OPT_N:
+ while (!NIL_P(f_gets())) {
+ rb_eval(self, node->nd_body);
+ }
+ RETURN(Qnil);
+
case NODE_SELF:
- RETURN(Qself);
+ RETURN(self);
case NODE_NIL:
RETURN(Qnil);
case NODE_IF:
- if (rb_eval(node->nd_cond)) {
+ if (RTEST(rb_eval(self, node->nd_cond))) {
node = node->nd_body;
}
else {
node = node->nd_else;
}
- if (node) goto again;
- RETURN(Qnil);
+ goto again;
+
+ case NODE_UNLESS:
+ if (!RTEST(rb_eval(self, node->nd_cond))) {
+ node = node->nd_body;
+ }
+ else {
+ node = node->nd_else;
+ }
+ goto again;
case NODE_CASE:
{
VALUE val;
- val = rb_eval(node->nd_head);
+ val = rb_eval(self, node->nd_head);
node = node->nd_body;
while (node) {
- if (nd_type(node) == NODE_WHEN) {
- NODE *tag = node->nd_head;
+ NODE *tag;
- while (tag) {
- if (rb_funcall(rb_eval(tag->nd_head), match, 1, val)){
- RETURN(rb_eval(node->nd_body));
- }
- tag = tag->nd_next;
- }
+ if (nd_type(node) != NODE_WHEN) {
+
+ RETURN(rb_eval(self, node));
}
- else {
- RETURN(rb_eval(node));
+ tag = node->nd_head;
+ while (tag) {
+ if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head),eqq,1,&val))){
+ RETURN(rb_eval(self, node->nd_body));
+ }
+ tag = tag->nd_next;
}
node = node->nd_next;
}
@@ -824,60 +962,62 @@ rb_eval(node)
case NODE_WHILE:
PUSH_TAG();
- switch (state = EXEC_TAG()) {
- case 0:
- while_cont:
- while (rb_eval(node->nd_cond)) {
+ if ((state = EXEC_TAG()) == 0) {
+ while_next:
+ for (;;) {
+ if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond)))
+ break;
while_redo:
- rb_eval(node->nd_body);
+ rb_eval(self, node->nd_body);
+ if (!node->nd_state && !RTEST(rb_eval(self, node->nd_cond)))
+ break;
+ }
+ }
+ else {
+ switch (state->nd_tag) {
+ case TAG_REDO:
+ state = 0;
+ goto while_redo;
+ case TAG_NEXT:
+ state = 0;
+ goto while_next;
+ default:
+ break;
}
- break;
- case TAG_REDO:
- state = 0;
- goto while_redo;
- case TAG_CONTINUE:
- state = 0;
- goto while_cont;
- default:
- break;
}
POP_TAG();
- switch (state) {
- case 0:
- case TAG_BREAK:
- break;
- default:
+ if (state && state->nd_tag != TAG_BREAK) {
JUMP_TAG(state);
- break;
}
RETURN(Qnil);
- case NODE_WHILE2:
+ case NODE_UNTIL:
PUSH_TAG();
- switch (state = EXEC_TAG()) {
- case 0:
- while2_cont:
- do {
- while2_redo:
- rb_eval(node->nd_body);
- } while (rb_eval(node->nd_cond));
- break;
- case TAG_REDO:
- state = 0;
- goto while2_redo;
- case TAG_CONTINUE:
- state = 0;
- goto while2_cont;
- default:
- case TAG_BREAK:
- break;
+ if ((state = EXEC_TAG()) == 0) {
+ until_next:
+ for (;;) {
+ if (node->nd_state && RTEST(rb_eval(self, node->nd_cond)))
+ break;
+ until_redo:
+ rb_eval(self, node->nd_body);
+ if (!node->nd_state && RTEST(rb_eval(self, node->nd_cond)))
+ break;
+ }
+ }
+ else {
+ switch (state->nd_tag) {
+ case TAG_REDO:
+ state = 0;
+ goto while_redo;
+ case TAG_NEXT:
+ state = 0;
+ goto while_next;
+ default:
+ break;
+ }
}
POP_TAG();
- switch (state) {
- case 0:
- case TAG_BREAK:
- break;
- default:
+ if (state && state->nd_tag != TAG_BREAK) {
JUMP_TAG(state);
}
RETURN(Qnil);
@@ -885,6 +1025,8 @@ rb_eval(node)
case NODE_ITER:
case NODE_FOR:
{
+ int tag_level;
+
iter_retry:
PUSH_BLOCK(node->nd_var, node->nd_body);
PUSH_TAG();
@@ -893,36 +1035,37 @@ rb_eval(node)
if (state == 0) {
if (nd_type(node) == NODE_ITER) {
PUSH_ITER(ITER_PRE);
- result = rb_eval(node->nd_iter);
+ result = rb_eval(self, node->nd_iter);
POP_ITER();
}
else {
VALUE recv;
- recv = rb_eval(node->nd_iter);
+ recv = rb_eval(self, node->nd_iter);
PUSH_ITER(ITER_PRE);
+ sourceline = nd_line(node);
+ sourcefile = node->file;
result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
POP_ITER();
}
}
POP_TAG();
+ tag_level = the_block->level;
POP_BLOCK();
- switch (state) {
- case 0:
- break;
-
+ if (state == 0) break;
+ switch (state->nd_tag) {
case TAG_RETRY:
goto iter_retry;
case IN_BLOCK|TAG_BREAK:
- if (target_level != tag_level) {
+ if (state->nd_tlev != tag_level) {
JUMP_TAG(state);
}
result = Qnil;
break;
case IN_BLOCK|TAG_RETURN:
- if (target_level == tag_level) {
- state &= ~IN_BLOCK;
+ if (state->nd_tlev == tag_level) {
+ state->nd_tag &= ~IN_BLOCK;
}
/* fall through */
default:
@@ -931,79 +1074,91 @@ rb_eval(node)
}
break;
- case NODE_FAIL:
- {
- VALUE mesg = rb_eval(node->nd_stts);
- if (mesg) Check_Type(mesg, T_STRING);
- rb_fail(mesg);
- }
- break;
-
case NODE_YIELD:
- result = rb_yield(rb_eval(node->nd_stts));
+ result = rb_yield_0(rb_eval(self, node->nd_stts), 0);
break;
- case NODE_BEGIN:
- if (node->nd_resq == Qnil && node->nd_ensr == Qnil) {
- node = node->nd_head;
- goto again;
+ case NODE_RESCUE:
+ retry_entry:
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_eval(self, node->nd_head);
}
- else {
- VALUE (*r_proc)();
-
- 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);
- }
- POP_TAG();
- /* ensure clause */
- rb_eval(node->nd_ensr);
- if (state) {
- JUMP_TAG(state);
+ POP_TAG();
+ if (state) {
+ if (state->nd_tag == TAG_RAISE) {
+ NODE *resq = node->nd_resq;
+ while (resq) {
+ if (handle_rescue(self, resq)) {
+ state = 0;
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_eval(self, resq->nd_body);
+ }
+ POP_TAG();
+ if (state == 0) {
+ errat = Qnil;
+ }
+ else if (state->nd_tag == TAG_RETRY) {
+ state = 0;
+ goto retry_entry;
+ }
+ break;
+ }
+ resq = resq->nd_head; /* next rescue */
}
}
- else {
- result = rb_rescue(rb_eval, node->nd_head, r_proc, node->nd_resq);
+ if (state) {
+ JUMP_TAG(state);
}
}
break;
+ case NODE_ENSURE:
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_eval(self, node->nd_head);
+ }
+ POP_TAG();
+ rb_eval(self, node->nd_ensr);
+ if (state) {
+ JUMP_TAG(state);
+ }
+ break;
+
case NODE_AND:
- if ((result = rb_eval(node->nd_1st)) == FALSE) RETURN(result);
+ result = rb_eval(self, node->nd_1st);
+ if (!RTEST(result)) break;
node = node->nd_2nd;
goto again;
case NODE_OR:
- if ((result = rb_eval(node->nd_1st)) != FALSE) RETURN(result);
+ result = rb_eval(self, node->nd_1st);
+ if (RTEST(result)) break;
node = node->nd_2nd;
goto again;
case NODE_NOT:
- if (rb_eval(node->nd_body)) result = FALSE;
+ if (RTEST(rb_eval(self, 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)));
+ RETURN(range_new(rb_eval(self, node->nd_beg), rb_eval(self, 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;
+ if (RTEST(rb_eval(self, node->nd_beg))) {
+ node->nd_state = rb_eval(self, node->nd_end)?0:1;
result = TRUE;
}
- result = FALSE;
+ else {
+ result = FALSE;
+ }
}
else {
- if (rb_eval(node->nd_end)) {
+ if (RTEST(rb_eval(self, node->nd_end))) {
node->nd_state = 0;
}
result = TRUE;
@@ -1012,39 +1167,22 @@ rb_eval(node)
case NODE_FLIP3: /* like SED */
if (node->nd_state == 0) {
- if (rb_eval(node->nd_beg)) {
+ if (RTEST(rb_eval(self, node->nd_beg))) {
node->nd_state = 1;
result = TRUE;
}
result = FALSE;
}
else {
- if (rb_eval(node->nd_end)) {
+ if (RTEST(rb_eval(self, node->nd_end))) {
node->nd_state = 0;
}
result = TRUE;
}
break;
- case NODE_BREAK:
- JUMP_TAG(TAG_BREAK);
- break;
-
- case NODE_CONTINUE:
- JUMP_TAG(TAG_CONTINUE);
- break;
-
- case NODE_REDO:
- JUMP_TAG(TAG_REDO);
- break;
-
- case NODE_RETRY:
- JUMP_TAG(TAG_RETRY);
- break;
-
case NODE_RETURN:
- if (node->nd_stts) last_val = rb_eval(node->nd_stts);
- JUMP_TAG(TAG_RETURN);
+ JUMP_TAG2(TAG_RETURN,(node->nd_stts)?rb_eval(self, node->nd_stts):Qnil);
break;
case NODE_CALL:
@@ -1053,7 +1191,7 @@ rb_eval(node)
int argc; VALUE *argv; /* used in SETUP_ARGS */
PUSH_ITER(ITER_NOT);
- recv = rb_eval(node->nd_recv);
+ recv = rb_eval(self, node->nd_recv);
SETUP_ARGS;
POP_ITER();
result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
@@ -1067,7 +1205,7 @@ rb_eval(node)
PUSH_ITER(ITER_NOT);
SETUP_ARGS;
POP_ITER();
- result = rb_call(CLASS_OF(Qself),Qself,node->nd_mid,argc,argv,1);
+ result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1);
}
break;
@@ -1086,8 +1224,8 @@ rb_eval(node)
POP_ITER();
}
- PUSH_ITER(iter->iter?ITER_PRE:ITER_NOT);
- result = rb_call(the_frame->last_class->super, Qself,
+ PUSH_ITER(the_iter->iter?ITER_PRE:ITER_NOT);
+ result = rb_call(the_frame->last_class->super, self,
the_frame->last_func, argc, argv, 1);
POP_ITER();
}
@@ -1095,11 +1233,14 @@ rb_eval(node)
case NODE_SCOPE:
{
+ VALUE save = the_frame->cbase;
+
PUSH_SCOPE();
PUSH_TAG();
- if (node->nd_cnt > 0) {
- the_scope->local_vars = ALLOCA_N(VALUE, node->nd_cnt);
- MEMZERO(the_scope->local_vars, VALUE, node->nd_cnt);
+ if (node->nd_rval) the_frame->cbase = (VALUE)node->nd_rval;
+ if (node->nd_tbl) {
+ the_scope->local_vars = ALLOCA_N(VALUE, node->nd_tbl[0]);
+ memclear(the_scope->local_vars, node->nd_tbl[0]);
the_scope->local_tbl = node->nd_tbl;
}
else {
@@ -1107,11 +1248,12 @@ rb_eval(node)
the_scope->local_tbl = 0;
}
if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(node->nd_body);
+ result = rb_eval(self, node->nd_body);
}
POP_TAG();
POP_SCOPE();
- if (state != 0) JUMP_TAG(state);
+ the_frame->cbase = save;
+ if (state) JUMP_TAG(state);
}
break;
@@ -1120,12 +1262,12 @@ rb_eval(node)
VALUE recv, args, val;
NODE *rval;
- recv = rb_eval(node->nd_recv);
+ recv = rb_eval(self, node->nd_recv);
rval = node->nd_args->nd_head;
- args = rb_eval(node->nd_args->nd_next);
+ args = rb_eval(self, node->nd_args->nd_next);
val = rb_apply(recv, aref, args);
- val = rb_funcall(val, node->nd_mid, 1, rb_eval(rval));
+ val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval));
ary_push(args, val);
rb_apply(recv, aset, args);
result = val;
@@ -1134,38 +1276,40 @@ rb_eval(node)
case NODE_OP_ASGN2:
{
- ID id = node->nd_aid;
+ ID id = node->nd_next->nd_vid;
VALUE recv, val;
- recv = rb_funcall(rb_eval(node->nd_recv), id, 0);
+ recv = rb_eval(self, node->nd_recv);
+ val = rb_funcall(recv, id, 0);
- id = id_attrset(id);
+ val = rb_funcall(recv, node->nd_next->nd_mid, 2, val,
+ rb_eval(self, node->nd_value));
- val = rb_eval(node->nd_value);
- rb_funcall(recv, id, 1, val);
+ rb_funcall2(recv, id_attrset(id), 1, &val);
result = val;
}
break;
case NODE_MASGN:
- result = masign(node, rb_eval(node->nd_value));
+ result = masign(self, node, rb_eval(self, node->nd_value));
break;
case NODE_LASGN:
if (the_scope->local_vars == 0)
Bug("unexpected local variable asignment");
- result = the_scope->local_vars[node->nd_cnt] = rb_eval(node->nd_value);
+ the_scope->local_vars[node->nd_cnt] = rb_eval(self, node->nd_value);
+ result = the_scope->local_vars[node->nd_cnt];
break;
case NODE_DASGN:
- result = dyna_var_asgn(node->nd_vid, rb_eval(node->nd_value));
+ result = dyna_var_asgn(node->nd_vid, rb_eval(self, node->nd_value));
break;
case NODE_GASGN:
{
VALUE val;
- val = rb_eval(node->nd_value);
+ val = rb_eval(self, node->nd_value);
rb_gvar_set(node->nd_entry, val);
result = val;
}
@@ -1175,8 +1319,8 @@ rb_eval(node)
{
VALUE val;
- val = rb_eval(node->nd_value);
- rb_ivar_set(Qself, node->nd_vid, val);
+ val = rb_eval(self, node->nd_value);
+ rb_ivar_set(self, node->nd_vid, val);
result = val;
}
break;
@@ -1185,15 +1329,21 @@ rb_eval(node)
{
VALUE val;
- val = rb_eval(node->nd_value);
+ val = rb_eval(self, node->nd_value);
+ /* check for static scope constants */
+ if (verbose && ev_const_defined(the_frame->cbase, node->nd_vid)) {
+ Warning("already initialized constnant %s",
+ rb_id2name(node->nd_vid));
+ }
rb_const_set(the_class, node->nd_vid, val);
result = val;
}
break;
case NODE_LVAR:
- if (the_scope->local_vars == 0)
+ if (the_scope->local_vars == 0) {
Bug("unexpected local variable");
+ }
result = the_scope->local_vars[node->nd_cnt];
break;
@@ -1206,18 +1356,13 @@ rb_eval(node)
break;
case NODE_IVAR:
- result = rb_ivar_get(Qself, node->nd_vid);
+ result = rb_ivar_get(self, node->nd_vid);
break;
case NODE_CVAR:
- {
- VALUE val;
-
- val = rb_const_get(node->nd_rval->nd_clss, node->nd_vid);
- nd_set_type(node, NODE_CONST);
- node->nd_cval = val;
- result = val;
- }
+ result = ev_const_get(the_frame->cbase, node->nd_vid);
+ nd_set_type(node, NODE_CONST);
+ node->nd_cval = result;
break;
case NODE_CONST:
@@ -1228,7 +1373,7 @@ rb_eval(node)
{
VALUE cls;
- cls = rb_eval(node->nd_head);
+ cls = rb_eval(self, node->nd_head);
switch (TYPE(cls)) {
case T_CLASS:
case T_MODULE:
@@ -1237,7 +1382,7 @@ rb_eval(node)
Check_Type(cls, T_CLASS);
break;
}
- result = rb_const_get(cls, node->nd_mid);
+ result = rb_const_get_at(cls, node->nd_mid);
}
break;
@@ -1273,11 +1418,11 @@ rb_eval(node)
list = node->nd_head;
while (list) {
- key = rb_eval(list->nd_head);
+ key = rb_eval(self, list->nd_head);
list = list->nd_next;
if (list == 0)
Bug("odd number list for Hash");
- val = rb_eval(list->nd_head);
+ val = rb_eval(self, list->nd_head);
list = list->nd_next;
hash_aset(hash, key, val);
}
@@ -1297,7 +1442,7 @@ rb_eval(node)
i = node->nd_alen;
ary = ary_new2(i);
for (i=0;node;node=node->nd_next) {
- RARRAY(ary)->ptr[i++] = rb_eval(node->nd_head);
+ RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
RARRAY(ary)->len = i;
}
@@ -1309,9 +1454,10 @@ rb_eval(node)
result = str_new3(node->nd_lit);
break;
- case NODE_STR2:
- case NODE_XSTR2:
+ case NODE_DSTR:
+ case NODE_DXSTR:
case NODE_DREGX:
+ case NODE_DREGX_ONCE:
{
VALUE str, str2;
NODE *list = node->nd_next;
@@ -1322,7 +1468,15 @@ rb_eval(node)
str2 = list->nd_head->nd_lit;
}
else {
- str2 = rb_eval(list->nd_head);
+ if (nd_type(list->nd_head) == NODE_EVSTR) {
+ rb_in_eval++;
+ list->nd_head = compile(list->nd_head->nd_lit);
+ rb_in_eval--;
+ if (!node) {
+ compile_error("string expand");
+ }
+ }
+ str2 = rb_eval(self, list->nd_head);
}
if (str2) {
str2 = obj_as_string(str2);
@@ -1330,22 +1484,29 @@ rb_eval(node)
}
list = list->nd_next;
}
- if (nd_type(node) == NODE_DREGX) {
- 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);
- }
- else {
+ switch (nd_type(node)) {
+ case NODE_DREGX:
+ result = reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ node->nd_cflag);
+ break;
+ case NODE_DREGX_ONCE: /* regexp expand once */
+ result = reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ node->nd_cflag);
+ nd_set_type(node, NODE_LIT);
+ node->nd_lit = result;
+ break;
+ case NODE_DXSTR:
+ result = rb_funcall(self, '`', 1, str);
+ break;
+ default:
result = str;
+ break;
}
}
break;
case NODE_XSTR:
- result = rb_xstring(node->nd_lit);
+ result = rb_funcall(self, '`', 1, node->nd_lit);
break;
case NODE_LIT:
@@ -1354,8 +1515,8 @@ rb_eval(node)
case NODE_ATTRSET:
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]);
+ ArgError("Wrong # of arguments(%d for 1)", the_frame->argc);
+ result = rb_ivar_set(self, node->nd_vid, the_frame->argv[0]);
break;
case NODE_DEFN:
@@ -1365,9 +1526,17 @@ rb_eval(node)
int noex;
body = search_method(the_class, node->nd_mid, &origin);
- if (body && verbose && origin != (VALUE)the_class
- && body->nd_noex != node->nd_noex) {
- Warning("change method %s's scope", rb_id2name(node->nd_mid));
+ if (body) {
+ if (origin == (VALUE)the_class) {
+ Warning("redefine %s", rb_id2name(node->nd_mid));
+ }
+ else {
+ if (body->nd_noex != node->nd_noex) {
+ Warning("change method %s's scope",
+ rb_id2name(node->nd_mid));
+ }
+ }
+ rb_clear_cache();
}
if (body) noex = body->nd_noex;
@@ -1380,23 +1549,38 @@ rb_eval(node)
case NODE_DEFS:
if (node->nd_defn) {
- VALUE recv = rb_eval(node->nd_recv);
+ VALUE recv = rb_eval(self, node->nd_recv);
+ VALUE class;
+ NODE *body;
+
+ if (NIL_P(recv)) {
+ TypeError("Can't define method \"%s\" for nil",
+ rb_id2name(node->nd_mid));
+ }
- if (recv == Qnil) {
- Fail("Can't define method \"%s\" for nil",
- rb_id2name(node->nd_mid));
+ class = rb_singleton_class(recv);
+ if (st_lookup(RCLASS(class)->m_tbl, node->nd_mid, &body)) {
+ Warning("redefine %s", rb_id2name(node->nd_mid));
}
+ rb_clear_cache();
rb_funcall(recv, rb_intern("singleton_method_added"),
1, INT2FIX(node->nd_mid));
- rb_add_method(rb_singleton_class(recv),node->nd_mid,node->nd_defn,
- NOEX_PUBLIC);
+ rb_add_method(class, node->nd_mid, node->nd_defn, NOEX_PUBLIC);
result = Qnil;
}
break;
case NODE_UNDEF:
- rb_add_method(the_class, node->nd_mid, Qnil, NOEX_PUBLIC);
- result = Qnil;
+ {
+ NODE *body;
+
+ if (st_lookup(the_class->m_tbl, node->nd_mid, &body)) {
+ Warning("redefine %s", rb_id2name(node->nd_mid));
+ }
+ rb_clear_cache();
+ rb_add_method(the_class, node->nd_mid, 0, NOEX_PUBLIC);
+ result = Qnil;
+ }
break;
case NODE_ALIAS:
@@ -1410,35 +1594,33 @@ rb_eval(node)
struct RClass *tmp;
if (node->nd_super) {
- super = rb_eval(node->nd_super);
- if (super == Qnil || TYPE(super) != T_CLASS) {
- Fail("superclass undefined");
- }
+ super = superclass(self, node->nd_super);
}
else {
- super = Qnil;
+ super = 0;
}
- if (rb_const_defined(the_class, node->nd_cname)) {
+ if (!rb_autoload_defined(node->nd_cname) &&
+ ev_const_defined(the_frame->cbase, node->nd_cname)) {
class = rb_const_get(the_class, node->nd_cname);
+ if (TYPE(class) != T_CLASS)
+ TypeError("%s is not a class", rb_id2name(node->nd_cname));
if (super) {
- if (TYPE(class) != T_CLASS)
- Fail("%s is not a class", rb_id2name(node->nd_cname));
tmp = RCLASS(class)->super;
- while (FL_TEST(tmp, FL_SINGLE)) {
+ while (FL_TEST(tmp, FL_SINGLETON)) {
tmp = RCLASS(tmp)->super;
}
while (TYPE(tmp) == T_ICLASS) {
tmp = RCLASS(tmp)->super;
}
if (tmp != RCLASS(super))
- Fail("superclass mismatch for %s",
- rb_id2name(node->nd_cname));
+ TypeError("superclass mismatch for %s",
+ rb_id2name(node->nd_cname));
}
Warning("extending class %s", rb_id2name(node->nd_cname));
}
else {
- if (super == Qnil) super = cObject;
+ if (!super) 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));
@@ -1453,10 +1635,11 @@ rb_eval(node)
{
VALUE module;
- if (rb_const_defined(the_class, node->nd_cname)) {
+ if (!rb_autoload_defined(node->nd_cname) &&
+ ev_const_defined(the_frame->cbase, 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));
+ TypeError("%s is not a module", rb_id2name(node->nd_cname));
Warning("extending module %s", rb_id2name(node->nd_cname));
}
else {
@@ -1473,8 +1656,11 @@ rb_eval(node)
case NODE_DEFINED:
{
VALUE obj;
+ char buf[20];
+ char *desc = 0;
node = node->nd_head;
+
switch (nd_type(node)) {
case NODE_SUPER:
case NODE_ZSUPER:
@@ -1486,17 +1672,16 @@ rb_eval(node)
break;
case NODE_FCALL:
- obj = CLASS_OF(Qself);
+ obj = CLASS_OF(self);
goto check_bound;
case NODE_CALL:
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
- obj = rb_eval(node->nd_recv);
+ obj = rb_eval(self, node->nd_recv);
}
POP_TAG();
- if (state == TAG_FAIL) {
- result = FALSE;
+ if (state) {
break;
}
else {
@@ -1505,27 +1690,23 @@ rb_eval(node)
check_bound:
if (method_boundp(obj, node->nd_mid,
nd_type(node)== NODE_CALL)) {
- result = TRUE;
+ desc = "method";
}
- else result = FALSE;
}
break;
case NODE_YIELD:
- result = iterator_p();
+ if (iterator_p()) {
+ desc = "iterator";
+ }
break;
- case NODE_BREAK:
- case NODE_CONTINUE:
- case NODE_REDO:
- case NODE_RETRY:
-
case NODE_SELF:
+ desc = "self"; break;
case NODE_NIL:
- case NODE_FAIL:
- case NODE_ATTRSET:
- case NODE_DEFINED:
+ desc = "nil"; break;
+ case NODE_ATTRSET:
case NODE_OP_ASGN1:
case NODE_OP_ASGN2:
case NODE_MASGN:
@@ -1534,60 +1715,80 @@ rb_eval(node)
case NODE_GASGN:
case NODE_IASGN:
case NODE_CASGN:
+ desc = "asignment"; break;
+
case NODE_LVAR:
+ desc = "local-variable"; break;
case NODE_DVAR:
- result = TRUE;
- break;
+ desc = "dynamic-local-variable"; break;
case NODE_GVAR:
- result = rb_gvar_defined(node->nd_entry);
+ if (rb_gvar_defined(node->nd_entry)) {
+ desc = "global-variable";
+ }
break;
case NODE_IVAR:
- result = rb_ivar_defined(node->nd_vid);
+ if (rb_ivar_defined(self, node->nd_vid)) {
+ desc = "instance-variable";
+ }
break;
case NODE_CVAR:
- result = rb_const_defined(node->nd_rval->nd_clss, node->nd_vid);
- break;
-
- case NODE_CONST:
- result = TRUE;
+ if (ev_const_defined(the_frame->cbase, node->nd_vid)) {
+ case NODE_CONST: /* jump in */
+ desc = "class-constant";
+ }
break;
case NODE_COLON2:
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
- obj = rb_eval(node->nd_head);
+ obj = rb_eval(self, node->nd_head);
}
POP_TAG();
- if (state == TAG_FAIL) result = FALSE;
+ if (state) {
+ break;
+ }
else {
if (state) JUMP_TAG(state);
- result = rb_const_defined(obj, node->nd_mid);
+ switch (TYPE(obj)) {
+ case T_CLASS:
+ case T_MODULE:
+ if (rb_const_defined_at(obj, node->nd_mid))
+ desc = "class-constant";
+ break;
+ }
}
break;
case NODE_NTH_REF:
- result = reg_nth_defined(node->nd_nth, MATCH_DATA);
+ if (reg_nth_defined(node->nd_nth, MATCH_DATA)) {
+ sprintf(buf, "$%d", node->nd_nth);
+ desc = buf;
+ }
break;
case NODE_BACK_REF:
- result = reg_nth_defined(0, MATCH_DATA);
+ if (reg_nth_defined(0, MATCH_DATA)) {
+ sprintf(buf, "$%c", node->nd_nth);
+ desc = buf;
+ }
break;
default:
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
- rb_eval(node);
+ rb_eval(self, node);
}
POP_TAG();
- if (state == TAG_FAIL) result = FALSE;
+ if (state) break;
else {
- if (state) JUMP_TAG(state);
- result = TRUE;
+ desc = "expression";
}
}
+ if (desc) result = str_new2(desc);
+ else result = FALSE;
}
break;
@@ -1595,12 +1796,8 @@ rb_eval(node)
Bug("unknown node type %d", nd_type(node));
}
finish:
-#ifdef SAFE_SIGHANDLE
- if (trap_pending) {
- rb_trap_exec();
- }
-#endif
- return result; /* not reached */
+ CHECK_INTS;
+ return result;
}
static void
@@ -1608,7 +1805,8 @@ module_setup(module, node)
VALUE module;
NODE *node;
{
- int state;
+ NODE *state;
+ VALUE save = the_frame->cbase;
/* fill c-ref */
node->nd_clss = module;
@@ -1616,12 +1814,12 @@ module_setup(module, node)
PUSH_CLASS();
the_class = (struct RClass*)module;
- PUSH_SELF((VALUE)the_class);
PUSH_SCOPE();
- if (node->nd_cnt > 0) {
- the_scope->local_vars = ALLOCA_N(VALUE, node->nd_cnt);
- MEMZERO(the_scope->local_vars, VALUE, node->nd_cnt);
+ if (node->nd_rval) the_frame->cbase = node->nd_rval;
+ if (node->nd_tbl) {
+ the_scope->local_vars = ALLOCA_N(VALUE, node->nd_tbl[0]);
+ memclear(the_scope->local_vars, node->nd_tbl[0]);
the_scope->local_tbl = node->nd_tbl;
}
else {
@@ -1631,21 +1829,48 @@ module_setup(module, node)
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
- rb_eval(node->nd_body);
+ rb_eval((VALUE)the_class, node->nd_body);
}
POP_TAG();
POP_SCOPE();
- POP_SELF();
POP_CLASS();
+ the_frame->cbase = save;
if (state) JUMP_TAG(state);
}
-VALUE
-rb_responds_to(obj, id)
+int
+rb_respond_to(obj, id)
VALUE obj;
ID id;
{
- if (rb_method_boundp(CLASS_OF(obj), id)) {
+ if (rb_method_boundp(CLASS_OF(obj), id, 0)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static VALUE
+krn_respond_to(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE mid, priv;
+ ID id;
+
+ rb_scan_args(argc, argv, "11", &mid, &priv);
+ id = rb_to_id(mid);
+ if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static VALUE
+mod_method_defined(mod, mid)
+ VALUE mod, mid;
+{
+ if (rb_method_boundp(mod, rb_to_id(mid), TRUE)) {
return TRUE;
}
return FALSE;
@@ -1655,11 +1880,11 @@ void
rb_exit(status)
int status;
{
- last_val = INT2FIX(status);
- if (prot_tag)
- JUMP_TAG(TAG_EXIT);
- rb_trap_exit();
- exit(FIX2UINT(last_val));
+ if (prot_tag) {
+ exit_status = status;
+ rb_raise(exc_new(eSystemExit, ""));
+ }
+ exit(status);
}
static VALUE
@@ -1671,71 +1896,141 @@ f_exit(argc, argv, obj)
VALUE status;
if (rb_scan_args(argc, argv, "01", &status) == 1) {
- Need_Fixnum(status);
+ status = NUM2INT(status);
}
else {
- status = INT2FIX(0);
+ status = 0;
}
- last_val = status;
- JUMP_TAG(TAG_EXIT);
-
- return Qnil; /* not reached */
+ rb_exit(status);
+ /* not reached */
}
void
rb_break()
{
- JUMP_TAG(TAG_BREAK);
+ JUMP_TAG2(TAG_BREAK, 0);
}
-void
-rb_redo()
+static VALUE
+f_break()
+{
+ JUMP_TAG2(TAG_BREAK, 0);
+}
+
+static VALUE
+f_next()
+{
+ JUMP_TAG2(TAG_NEXT, 0);
+}
+
+static VALUE
+f_redo()
+{
+ JUMP_TAG2(TAG_REDO, 0);
+}
+
+static VALUE
+f_retry()
+{
+ JUMP_TAG2(TAG_RETRY, 0);
+}
+
+#ifdef __GNUC__
+static volatile voidfn rb_longjmp;
+#endif
+
+static VALUE make_backtrace();
+
+static void
+rb_longjmp(tag, mesg)
+ int tag;
+ VALUE mesg;
{
- JUMP_TAG(TAG_REDO);
+ if (NIL_P(errat) && NIL_P(mesg)) {
+ errinfo = exc_new(eRuntimeError, "");
+ }
+
+ if (sourcefile && (NIL_P(errat) || !NIL_P(mesg))) {
+ errat = make_backtrace();
+ }
+
+ if (!NIL_P(mesg)) {
+ if (obj_is_kind_of(mesg, eGlobalExit)) {
+ errinfo = mesg;
+ }
+ else {
+ errinfo = exc_new2(eRuntimeError, mesg);
+ }
+ str_freeze(errinfo);
+ }
+
+ JUMP_TAG2(tag, 0);
}
void
-rb_retry()
+rb_raise(mesg)
+ VALUE mesg;
{
- JUMP_TAG(TAG_RETRY);
+ rb_longjmp(TAG_RAISE, mesg);
}
void
-rb_fail(mesg)
+rb_fatal(mesg)
VALUE mesg;
{
- char buf[BUFSIZ];
+ rb_longjmp(TAG_FATAL, mesg);
+}
- if (errat == Qnil && mesg == Qnil) {
- errstr = Qnil;
+void
+rb_interrupt()
+{
+ rb_raise(exc_new(eInterrupt, "Interrupt"));
+}
+
+static VALUE
+f_raise(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE arg1, arg2;
+ VALUE etype, mesg;
+
+ etype = eRuntimeError;
+ mesg = Qnil;
+ switch (rb_scan_args(argc, argv, "02", &arg1, &arg2)) {
+ case 1:
+ mesg = arg1;
+ break;
+ case 2:
+ etype = arg1;
+ mesg = arg2;
+ break;
}
- if (errat == Qnil && sourcefile) {
- if (the_frame->last_func) {
- last_func = the_frame->last_func;
+ if (!NIL_P(mesg)) {
+ Check_Type(mesg, T_STRING);
+ if (!obj_is_kind_of(mesg, eException)) {
+ mesg = exc_new2(etype, mesg);
}
- sprintf(buf, "%s:%d", sourcefile, sourceline);
- errat = str_new2(buf);
}
- if (mesg) {
- errstr = mesg;
- }
- if (prot_tag->level == 0) error_print(last_func);
- JUMP_TAG(TAG_FAIL);
+ PUSH_FRAME(); /* fake frame */
+ *the_frame = *_frame.prev->prev;
+ rb_raise(mesg);
+ POP_FRAME();
}
-VALUE
+int
iterator_p()
{
- if (iter->iter) return TRUE;
+ if (the_frame->iter) return TRUE;
return FALSE;
}
static VALUE
f_iterator_p()
{
- if (iter->prev && iter->prev->iter) return TRUE;
+ if (the_frame->prev && the_frame->prev->iter) return TRUE;
return FALSE;
}
@@ -1743,18 +2038,19 @@ VALUE
rb_yield_0(val, self)
VALUE val, self;
{
- struct BLOCK *block;
NODE *node;
- int state;
+ NODE *state;
VALUE result = Qnil;
+ struct BLOCK *block;
struct SCOPE *old_scope;
struct FRAME frame;
if (!iterator_p()) {
- Fail("yield called out of iterator");
+ Raise(eLocalJumpError, "yield called out of iterator");
}
PUSH_VARS();
+ PUSH_CLASS();
block = the_block;
frame = block->frame;
frame.prev = the_frame;
@@ -1763,52 +2059,53 @@ rb_yield_0(val, self)
the_scope = block->scope;
the_block = block->prev;
the_dyna_vars = block->d_vars;
+ the_class = block->class;
+ if (!self) self = block->self;
+ node = block->body;
if (block->var) {
if (nd_type(block->var) == NODE_MASGN)
- masign(block->var, val);
+ masign(self, block->var, val);
else
- asign(block->var, val);
+ asign(self, block->var, val);
}
- node = block->body;
-
PUSH_ITER(block->iter);
- PUSH_SELF(self?self:block->self);
PUSH_TAG();
- switch (state = EXEC_TAG()) {
+ if ((state = EXEC_TAG()) == 0) {
redo:
- case 0:
if (!node) {
result = Qnil;
}
else if (nd_type(node) == NODE_CFUNC) {
- result = (*node->nd_cfnc)(val,node->nd_argc);
+ result = (*node->nd_cfnc)(val,node->nd_argc,self);
}
else {
- result = rb_eval(node);
+ result = rb_eval(self, node);
+ }
+ }
+ else {
+ switch (state->nd_tag) {
+ case TAG_REDO:
+ goto redo;
+ case TAG_NEXT:
+ state = 0;
+ break;
+ case TAG_BREAK:
+ case TAG_RETURN:
+ state->nd_tlev = block->level;
+ state->nd_tag = IN_BLOCK|state->nd_tag;
+ break;
+ default:
+ break;
}
- break;
- case TAG_REDO:
- goto redo;
- case TAG_CONTINUE:
- state = 0;
- break;
- case TAG_BREAK:
- case TAG_RETURN:
- target_level = block->level;
- state = IN_BLOCK|state;
- break;
- default:
- break;
}
POP_TAG();
- POP_SELF();
POP_ITER();
+ POP_CLASS();
POP_VARS();
the_block = block;
the_frame = the_frame->prev;
the_scope = old_scope;
if (state) JUMP_TAG(state);
-
return result;
}
@@ -1823,11 +2120,10 @@ static VALUE
f_loop()
{
for (;;) { rb_yield(Qnil); }
- return Qnil;
}
static VALUE
-masign(node, val)
+masign(self, node, val)
NODE *node;
VALUE val;
{
@@ -1842,30 +2138,31 @@ masign(node, val)
}
len = RARRAY(val)->len;
for (i=0; list && i<len; i++) {
- asign(list->nd_head, RARRAY(val)->ptr[i]);
+ asign(self, list->nd_head, RARRAY(val)->ptr[i]);
list = list->nd_next;
}
if (node->nd_args) {
if (!list && i<len) {
- asign(node->nd_args, ary_new4(len-i, RARRAY(val)->ptr+i));
+ asign(self, node->nd_args, ary_new4(len-i, RARRAY(val)->ptr+i));
}
else {
- asign(node->nd_args, Qnil);
+ asign(self, node->nd_args, ary_new2(0));
}
}
}
else if (node->nd_args) {
- asign(node->nd_args, Qnil);
+ asign(self, node->nd_args, Qnil);
}
while (list) {
- asign(list->nd_head, Qnil);
+ asign(self, list->nd_head, Qnil);
list = list->nd_next;
}
return val;
}
static void
-asign(lhs, val)
+asign(self, lhs, val)
+ VALUE self;
NODE *lhs;
VALUE val;
{
@@ -1875,7 +2172,7 @@ asign(lhs, val)
break;
case NODE_IASGN:
- rb_ivar_set(Qself, lhs->nd_vid, val);
+ rb_ivar_set(self, lhs->nd_vid, val);
break;
case NODE_LASGN:
@@ -1895,16 +2192,16 @@ asign(lhs, val)
case NODE_CALL:
{
VALUE recv;
- recv = rb_eval(lhs->nd_recv);
- if (lhs->nd_args->nd_head == Qnil) {
+ recv = rb_eval(self, lhs->nd_recv);
+ if (!lhs->nd_args->nd_head) {
/* attr set */
- rb_funcall(recv, lhs->nd_mid, 1, val);
+ rb_funcall2(recv, lhs->nd_mid, 1, &val);
}
else {
/* array set */
VALUE args;
- args = rb_eval(lhs->nd_args);
+ args = rb_eval(self, lhs->nd_args);
RARRAY(args)->ptr[RARRAY(args)->len-1] = val;
rb_apply(recv, lhs->nd_mid, args);
}
@@ -1922,13 +2219,15 @@ rb_iterate(it_proc, data1, bl_proc, data2)
VALUE (*it_proc)(), (*bl_proc)();
void *data1, *data2;
{
- int state;
+ NODE *state;
VALUE retval = Qnil;
NODE *node = NEW_CFUNC(bl_proc, data2);
+ VALUE self = TopSelf;
+ int tag_level;
iter_retry:
PUSH_ITER(ITER_PRE);
- PUSH_BLOCK(Qnil, node);
+ PUSH_BLOCK(0, node);
PUSH_TAG();
state = EXEC_TAG();
@@ -1937,33 +2236,53 @@ rb_iterate(it_proc, data1, bl_proc, data2)
}
POP_TAG();
+ tag_level = the_block->level;
POP_BLOCK();
POP_ITER();
- switch (state) {
- case 0:
- break;
+ if (state) {
+ switch (state->nd_tag) {
+ case TAG_RETRY:
+ goto iter_retry;
- case TAG_RETRY:
- goto iter_retry;
+ case IN_BLOCK|TAG_BREAK:
+ if (state->nd_tlev != tag_level) {
+ JUMP_TAG(state);
+ }
+ retval = Qnil;
+ break;
- case IN_BLOCK|TAG_BREAK:
- if (target_level != tag_level) {
+ case IN_BLOCK|TAG_RETURN:
+ if (state->nd_tlev == tag_level) {
+ state->nd_tag &= ~IN_BLOCK;
+ }
+ /* fall through */
+ default:
JUMP_TAG(state);
}
- retval = Qnil;
- break;
+ }
+ return retval;
+}
- case IN_BLOCK|TAG_RETURN:
- if (target_level == tag_level) {
- state &= ~IN_BLOCK;
- }
- /* fall through */
- default:
- JUMP_TAG(state);
+static int
+handle_rescue(self, node)
+ VALUE self;
+ NODE *node;
+{
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+
+ if (!node->nd_args) {
+ return obj_is_kind_of(errinfo, eException);
}
- return retval;
+ PUSH_ITER(ITER_NOT);
+ SETUP_ARGS;
+ POP_ITER();
+ while (argc--) {
+ if (obj_is_kind_of(errinfo, argv[0])) return 1;
+ argv++;
+ }
+ return 0;
}
VALUE
@@ -1971,43 +2290,36 @@ rb_rescue(b_proc, data1, r_proc, data2)
VALUE (*b_proc)(), (*r_proc)();
void *data1, *data2;
{
- int state;
- VALUE result = Qnil;
- volatile SIGHANDLE handle;
+ NODE *state;
+ VALUE result;
PUSH_TAG();
- switch (state = EXEC_TAG()) {
- case 0:
- handle = sig_beg();
+ if ((state = EXEC_TAG()) == 0) {
retry_entry:
result = (*b_proc)(data1);
- break;
-
- case TAG_FAIL:
- sig_end(handle);
- if (r_proc) {
- PUSH_TAG();
- state = EXEC_TAG();
- if (state == 0) {
- result = (*r_proc)(data2);
+ }
+ else {
+ if (state->nd_tag == TAG_RAISE) {
+ if (r_proc) {
+ PUSH_TAG();
+ state = EXEC_TAG();
+ if (state == 0) {
+ result = (*r_proc)(data2, errinfo);
+ }
+ POP_TAG();
+ if (state && state->nd_tag == TAG_RETRY) {
+ state = 0;
+ goto retry_entry;
+ }
}
- POP_TAG();
- if (state == TAG_RETRY) {
- goto retry_entry;
+ else {
+ result = Qnil;
+ state = 0;
+ }
+ if (state == 0) {
+ errat = Qnil;
}
}
- else {
- state = 0;
- }
- if (state == 0) {
- errat = Qnil;
- last_func = 0;
- }
- break;
-
- default:
- sig_end(handle);
- break;
}
POP_TAG();
if (state) JUMP_TAG(state);
@@ -2020,7 +2332,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
VALUE (*b_proc)(), (*e_proc)();
void *data1, *data2;
{
- int state;
+ NODE *state;
VALUE result = Qnil;
PUSH_TAG();
@@ -2030,7 +2342,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
POP_TAG();
(*e_proc)(data2);
- if (state != 0) {
+ if (state) {
JUMP_TAG(state);
}
return result;
@@ -2044,7 +2356,7 @@ f_missing(argc, argv, obj)
VALUE *argv;
VALUE obj;
{
- VALUE desc;
+ VALUE desc = 0;
ID id;
char *format;
struct FRAME *frame;
@@ -2052,27 +2364,44 @@ f_missing(argc, argv, obj)
id = FIX2INT(argv[0]);
argc--; argv++;
- if (TYPE(obj) == T_STRING) {
- desc = krn_inspect(obj);
- }
- else {
+ switch (TYPE(obj)) {
+ case T_NIL:
+ format = "undefined method `%s' for nil";
+ break;
+ case T_TRUE:
+ format = "undefined method `%s' for TRUE";
+ break;
+ case T_FALSE:
+ format = "undefined method `%s' for FALSE";
+ break;
+ case T_OBJECT:
desc = obj_as_string(obj);
+ break;
+ default:
+ desc = rb_inspect(obj);
+ break;
+ }
+ if (desc) {
+ if (last_noex)
+ format = "private method `%s' called for %s(%s)";
+ else if (argc == 0) {
+ format = "undefined local variable or method `%s' for %s(%s)";
+ }
+ else {
+ format = "undefined method `%s' for %s(%s)";
+ }
+ if (RSTRING(desc)->len > 65) {
+ desc = krn_to_s(obj);
+ }
}
- if (last_noex)
- format = "method `%s' not available for %s(%s)";
- else
- format = "undefined method `%s' for %s(%s)";
- /* 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)));
+ PUSH_FRAME(); /* fake frame */
+ *the_frame = *_frame.prev->prev;
+
+ NameError(format,
+ rb_id2name(id),
+ desc?RSTRING(desc)->ptr:"",
+ desc?rb_class2name(CLASS_OF(obj)):"");
POP_FRAME();
}
@@ -2095,8 +2424,20 @@ 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;
+#define STACK_LEVEL_MAX 655350
+extern VALUE *gc_stack_start;
+static int
+stack_length()
+{
+ VALUE pos;
+
+#ifdef sparc
+ return gc_stack_start - &pos + 0x80;
+#else
+ return (&pos < gc_stack_start) ? gc_stack_start - &pos
+ : &pos - gc_stack_start;
+#endif
+}
static VALUE
rb_call(class, recv, mid, argc, argv, scope)
@@ -2109,38 +2450,30 @@ rb_call(class, recv, mid, argc, argv, scope)
{
NODE *body;
int noex;
- VALUE result = Qnil;
+ ID id = mid;
struct cache_entry *ent;
+ VALUE result = Qnil;
int itr;
enum node_type type;
+ static int tick;
/* is it in the method cache? */
ent = cache + EXPR1(class, mid);
if (ent->mid == mid && ent->class == class) {
class = ent->origin;
- mid = ent->mid;
- body = ent->method;
+ id = ent->mid0;
noex = ent->noex;
+ body = ent->method;
}
- else {
- ID id = mid;
-
- if ((body = rb_get_method_body(&class, &id, &noex)) == FALSE) {
- return rb_undefined(recv, mid, argc, argv, 0);
- }
- mid = id;
+ else if ((body = rb_get_method_body(&class, &id, &noex)) == 0) {
+ return rb_undefined(recv, mid, argc, argv, 0);
}
- switch (noex) {
- case NOEX_PUBLIC:
- break;
- case NOEX_PRIVATE:
- if (scope == 0) /* receiver specified */
- return rb_undefined(recv, mid, argc, argv, 1);
- break;
- }
+ /* receiver specified form for private method */
+ if (noex == NOEX_PRIVATE && scope == 0)
+ return rb_undefined(recv, mid, argc, argv, 1);
- switch (iter->iter) {
+ switch (the_iter->iter) {
case ITER_PRE:
itr = ITER_CUR;
break;
@@ -2153,16 +2486,15 @@ rb_call(class, recv, mid, argc, argv, scope)
type = nd_type(body);
if (type == NODE_ZSUPER) {
/* for re-scoped method */
- return rb_call(class->super, recv, mid, argc, argv, scope?scope:1);
+ return rb_call(class->super, recv, id, argc, argv, scope?scope:1);
}
- if (stack_level++ > STACK_LEVEL_MAX)
- Fail("stack level too deep");
+ if (++tick % 1000 == 0 && stack_length() > STACK_LEVEL_MAX)
+ Fatal("stack level too deep");
PUSH_ITER(itr);
- PUSH_SELF(recv);
PUSH_FRAME();
- the_frame->last_func = mid;
+ the_frame->last_func = id;
the_frame->last_class = class;
the_frame->argc = argc;
the_frame->argv = argv;
@@ -2173,7 +2505,7 @@ rb_call(class, recv, mid, argc, argv, scope)
int len = body->nd_argc;
if (len >= 0 && argc != len) {
- Fail("Wrong # of arguments(%d for %d)", argc, len);
+ ArgError("Wrong # of arguments(%d for %d)", argc, len);
}
switch (len) {
@@ -2273,7 +2605,7 @@ rb_call(class, recv, mid, argc, argv, scope)
len, rb_class2name(class), rb_id2name(mid));
}
else {
- Fail("too many arguments(%d)", len);
+ ArgError("too many arguments(%d)", len);
}
break;
}
@@ -2283,19 +2615,20 @@ rb_call(class, recv, mid, argc, argv, scope)
/* for attr get/set */
case NODE_ATTRSET:
case NODE_IVAR:
- result = rb_eval(body);
+ result = rb_eval(recv, body);
break;
default:
{
- int state;
+ NODE *state;
VALUE *local_vars;
PUSH_SCOPE();
- if (body->nd_cnt > 0) {
- local_vars = ALLOCA_N(VALUE, body->nd_cnt);
- MEMZERO(local_vars, VALUE, body->nd_cnt);
+ if (body->nd_rval) the_frame->cbase = body->nd_rval;
+ if (body->nd_tbl) {
+ local_vars = ALLOCA_N(VALUE, body->nd_tbl[0]);
+ memclear(local_vars, body->nd_tbl[0]);
the_scope->local_tbl = body->nd_tbl;
the_scope->local_vars = local_vars;
}
@@ -2306,6 +2639,8 @@ rb_call(class, recv, mid, argc, argv, scope)
body = body->nd_body;
PUSH_TAG();
+ PUSH_VARS();
+ dyna_var_mark();
state = EXEC_TAG();
if (state == 0) {
if (nd_type(body) == NODE_BLOCK) {
@@ -2321,7 +2656,7 @@ rb_call(class, recv, mid, argc, argv, scope)
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);
+ ArgError("Wrong # of arguments(%d for %d)", argc, i);
}
if (local_vars) {
@@ -2333,56 +2668,54 @@ rb_call(class, recv, mid, argc, argv, scope)
NODE *opt = node->nd_opt;
while (opt && argc) {
- asign(opt->nd_head, *argv);
+ asign(recv, opt->nd_head, *argv);
argv++; argc--;
opt = opt->nd_next;
}
- rb_eval(opt);
+ rb_eval(recv, 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);
+ local_vars[node->nd_rest]=ary_new2(0);
}
}
}
else if (nd_type(body) == NODE_ARGS) {
body = 0;
}
- result = rb_eval(body);
+ result = rb_eval(recv, body);
}
+ POP_VARS();
POP_TAG();
POP_SCOPE();
- switch (state) {
- case 0:
- break;
- case TAG_CONTINUE:
- Fatal("unexpected continue");
- break;
- case TAG_BREAK:
- Fatal("unexpected break");
- break;
- case TAG_REDO:
- Fatal("unexpected redo");
- break;
- case TAG_RETURN:
- result = last_val;
- break;
- case TAG_RETRY:
- if (!iterator_p()) {
- Fatal("retry outside of rescue clause");
+ if (state) {
+ switch (state->nd_tag) {
+ case TAG_NEXT:
+ Raise(eLocalJumpError, "unexpected next");
+ break;
+ case TAG_BREAK:
+ Raise(eLocalJumpError, "unexpected break");
+ break;
+ case TAG_REDO:
+ Raise(eLocalJumpError, "unexpected redo");
+ break;
+ case TAG_RETURN:
+ result = state->nd_tval;
+ break;
+ case TAG_RETRY:
+ if (!iterator_p()) {
+ Raise(eLocalJumpError, "retry outside of rescue clause");
+ }
+ default:
+ JUMP_TAG(state);
}
- default:
- stack_level--;
- JUMP_TAG(state);
}
}
}
POP_FRAME();
- POP_SELF();
POP_ITER();
- stack_level--;
return result;
}
@@ -2410,7 +2743,7 @@ f_send(argc, argv, recv)
VALUE vid;
ID mid;
- if (argc == 0) Fail("no method name given");
+ if (argc == 0) ArgError("no method name given");
vid = argv[0]; argc--; argv++;
if (TYPE(vid) == T_STRING) {
@@ -2463,26 +2796,31 @@ rb_funcall2(recv, mid, argc, argv)
}
static VALUE
-f_caller(argc, argv)
- int argc;
- VALUE *argv;
+backtrace(lev)
+ int lev;
{
- VALUE level;
struct FRAME *frame = the_frame;
- int lev, n;
char buf[BUFSIZ];
+ VALUE ary;
- 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);
+ ary = ary_new();
+ if (lev < 0) {
+ if (frame->last_func) {
+ sprintf(buf, "%s:%d:in `%s'", sourcefile, sourceline,
+ rb_id2name(frame->last_func));
+ }
+ else {
+ sprintf(buf, "%s:%d", sourcefile, sourceline);
+ }
+ ary_push(ary, str_new2(buf));
+ }
else {
- while (n-- > 0) {
+ while (lev-- > 0) {
frame = frame->prev;
if (!frame) return Qnil;
}
- if (!frame->file) return Qnil;
+ }
+ while (frame && frame->file) {
if (frame->prev && frame->prev->last_func) {
sprintf(buf, "%s:%d:in `%s'",
frame->file, frame->line,
@@ -2491,73 +2829,169 @@ f_caller(argc, argv)
else {
sprintf(buf, "%s:%d", frame->file, frame->line);
}
+ ary_push(ary, str_new2(buf));
+ frame = frame->prev;
}
- return str_new2(buf);
+ return ary;
+}
+
+static VALUE
+f_caller(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE level;
+ struct FRAME *frame = the_frame;
+ int lev;
+
+ rb_scan_args(argc, argv, "01", &level);
+
+ if (NIL_P(level)) lev = 1;
+ else lev = NUM2INT(level);
+ if (lev < 0) ArgError("negative level(%d)", lev);
+
+ return backtrace(lev);
}
void
rb_backtrace()
{
- VALUE c, lev;
- int n = 0;
+ int i, lev;
+ VALUE ary, c;
- lev = INT2FIX(n);
- while (c = f_caller(1, &lev)) {
- printf("%s\n", RSTRING(c)->ptr);
- n++;
- lev = INT2FIX(n);
+ lev = INT2FIX(0);
+ ary = backtrace(-1);
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ printf("\tfrom %s\n", RSTRING(RARRAY(ary)->ptr)->ptr);
}
}
+static VALUE
+make_backtrace()
+{
+ VALUE lev;
+
+ lev = INT2FIX(0);
+ return backtrace(-1);
+}
+
ID
rb_frame_last_func()
{
return the_frame->last_func;
}
-int rb_in_eval = 0;
+static NODE*
+compile(src)
+ struct RString *src;
+{
+ NODE *node;
+
+ Check_Type(src, T_STRING);
+
+ errinfo = Qnil;
+ node = compile_string(sourcefile, src->ptr, src->len);
+
+ if (nerrs == 0) return node;
+ return 0;
+}
+
+static void blk_free();
static VALUE
-f_eval(obj, src)
- VALUE obj;
+eval(self, src, scope)
+ VALUE self;
struct RString *src;
+ struct RData *scope;
{
+ struct BLOCK *data;
VALUE result = Qnil;
- int state;
NODE *node;
+ NODE *state;
+ struct BLOCK *old_block;
+ struct SCOPE *old_scope;
+ struct FRAME frame;
+ char *file = sourcefile;
+ int line = sourceline;
- Check_Type(src, T_STRING);
PUSH_TAG();
- rb_in_eval = 1;
- node = eval_tree;
-
PUSH_CLASS();
+ if (!NIL_P(scope)) {
+ if (TYPE(scope) != T_DATA || scope->dfree != blk_free) {
+ TypeError("wrong argument type %s (expected Proc/Binding)",
+ rb_class2name(CLASS_OF(scope)));
+ }
+
+ Get_Data_Struct(scope, struct BLOCK, data);
+
+ /* PUSH BLOCK from data */
+ frame = data->frame;
+ frame.prev = the_frame;
+ the_frame = &(frame);
+ old_scope = the_scope;
+ the_scope = data->scope;
+ old_block = the_block;
+ the_block = data->prev;
+ the_dyna_vars = data->d_vars;
+ the_class = data->class;
+ self = data->self;
+ }
+
+ rb_in_eval++;
if (TYPE(the_class) == T_ICLASS) {
the_class = (struct RClass*)RBASIC(the_class)->class;
}
-
if ((state = EXEC_TAG()) == 0) {
- lex_setsrc("(eval)", src->ptr, src->len);
- eval_tree = 0;
- PUSH_VARS();
- yyparse();
- POP_VARS();
- if (nerrs == 0) {
- result = Eval();
+ if (!compile(src)) {
+ rb_in_eval--;
+ compile_error("eval()");
}
+ result = eval_node(self);
+ }
+ if (!NIL_P(scope)) {
+ the_frame = the_frame->prev;
+ the_scope = old_scope;
+ the_block = old_block;
}
- eval_tree = node;
POP_CLASS();
POP_TAG();
- if (state) JUMP_TAG(state);
-
- if (nerrs > 0) {
- syntax_error();
+ rb_in_eval--;
+ if (state) {
+ VALUE err ;
+
+ switch (state->nd_tag) {
+ case TAG_RAISE:
+ sourcefile = file;
+ sourceline = line;
+ if (strcmp(sourcefile, "(eval)") == 0) {
+ err = errat;
+ if (sourceline != 1) {
+ str_cat(err, ": ", 2);
+ str_cat(err, RSTRING(errinfo)->ptr, RSTRING(errinfo)->len);
+ }
+ errat = Qnil;
+ rb_raise(exc_new2(CLASS_OF(errinfo), err));
+ }
+ rb_raise(Qnil);
+ }
+ JUMP_TAG(state);
}
return result;
}
+static VALUE
+f_eval(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE src, scope;
+
+ rb_scan_args(argc, argv, "11", &src, &scope);
+ return eval(self, src, scope);
+}
+
VALUE rb_load_path;
char *dln_find_file();
@@ -2567,20 +3001,18 @@ find_file(file)
char *file;
{
extern VALUE rb_load_path;
- VALUE sep, vpath;
+ VALUE vpath;
char *path;
if (file[0] == '/') return file;
if (rb_load_path) {
Check_Type(rb_load_path, T_ARRAY);
- sep = str_new2(":");
- vpath = ary_join(rb_load_path, sep);
+ vpath = ary_join(rb_load_path, str_new2(":"));
path = RSTRING(vpath)->ptr;
- sep = Qnil;
}
else {
- path = Qnil;
+ path = 0;
}
return dln_find_file(file, path);
@@ -2591,36 +3023,39 @@ f_load(obj, fname)
VALUE obj;
struct RString *fname;
{
- int state, in_eval = rb_in_eval;
+ NODE *state;
char *file, *src;
+ volatile ID last_func;
Check_Type(fname, T_STRING);
file = find_file(fname->ptr);
- if (!file) Fail("No such file to load -- %s", fname->ptr);
+ if (!file) LoadError("No such file to load -- %s", fname->ptr);
- PUSH_SELF(TopSelf);
PUSH_TAG();
PUSH_CLASS();
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;
+
state = EXEC_TAG();
+ last_func = the_frame->last_func;
+ the_frame->last_func = 0;
if (state == 0) {
+ rb_in_eval++;
rb_load_file(file);
+ rb_in_eval--;
if (nerrs == 0) {
- Eval();
+ eval_node(TopSelf);
}
}
+ the_frame->last_func = last_func;
top_scope->flag = the_scope->flag;
POP_SCOPE();
POP_CLASS();
POP_TAG();
- POP_SELF();
- rb_in_eval = in_eval;
if (nerrs > 0) {
- rb_fail(errstr);
+ rb_raise(errinfo);
}
if (state) JUMP_TAG(state);
@@ -2629,16 +3064,17 @@ f_load(obj, fname)
static VALUE rb_features;
-static VALUE
+static int
rb_provided(feature)
char *feature;
{
+ struct RArray *features = RARRAY(rb_features);
VALUE *p, *pend;
char *f;
int len;
- p = RARRAY(rb_features)->ptr;
- pend = p + RARRAY(rb_features)->len;
+ p = features->ptr;
+ pend = p + features->len;
while (p < pend) {
Check_Type(*p, T_STRING);
f = RSTRING(*p)->ptr;
@@ -2653,6 +3089,11 @@ rb_provided(feature)
return FALSE;
}
+#ifdef THREAD
+static int thread_loading();
+static void thread_loading_done();
+#endif
+
void
rb_provide(feature)
char *feature;
@@ -2670,7 +3111,8 @@ f_require(obj, fname)
VALUE load;
Check_Type(fname, T_STRING);
- if (rb_provided(fname->ptr)) return FALSE;
+ if (rb_provided(fname->ptr))
+ return FALSE;
ext = strrchr(fname->ptr, '.');
if (ext) {
@@ -2680,9 +3122,9 @@ f_require(obj, fname)
if (file) goto rb_load;
}
else if (strcmp(".o", ext) == 0) {
- feature = fname->ptr;
+ file = feature = fname->ptr;
if (strcmp(".o", DLEXT) != 0) {
- buf = ALLOCA_N(char, strlen(fname->ptr) + 3);
+ buf = ALLOCA_N(char, strlen(fname->ptr)+sizeof(DLEXT)+1);
strcpy(buf, feature);
ext = strrchr(buf, '.');
strcpy(ext, DLEXT);
@@ -2696,7 +3138,7 @@ f_require(obj, fname)
if (file) goto dyna_load;
}
}
- buf = ALLOCA_N(char, strlen(fname->ptr) + 4);
+ buf = ALLOCA_N(char, strlen(fname->ptr) + 5);
sprintf(buf, "%s.rb", fname->ptr);
file = find_file(buf);
if (file) {
@@ -2710,58 +3152,80 @@ f_require(obj, fname)
feature = buf;
goto dyna_load;
}
- Fail("No such file to load -- %s", fname->ptr);
+ LoadError("No such file to load -- %s", fname->ptr);
dyna_load:
- load = str_new2(file);
- file = RSTRING(load)->ptr;
- dln_load(file);
- rb_provide(feature);
+#ifdef THREAD
+ if (thread_loading(feature)) return FALSE;
+ else {
+ NODE *state;
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+#endif
+ load = str_new2(file);
+ file = RSTRING(load)->ptr;
+ dln_load(file);
+ rb_provide(feature);
+#ifdef THREAD
+ }
+ POP_TAG();
+ thread_loading_done();
+ if (state) JUMP_TAG(state);
+ }
+#endif
return TRUE;
rb_load:
- f_load(obj, fname);
- rb_provide(feature);
+#ifdef THREAD
+ if (thread_loading(feature)) return FALSE;
+ else {
+ NODE *state;
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+#endif
+ f_load(obj, fname);
+ rb_provide(feature);
+#ifdef THREAD
+ }
+ POP_TAG();
+ thread_loading_done();
+ if (state) JUMP_TAG(state);
+ }
+#endif
return TRUE;
}
static void
-set_method_visibility(argc, argv, ex)
+set_method_visibility(self, argc, argv, ex)
+ VALUE self;
int argc;
VALUE *argv;
int ex;
{
- 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);
+ rb_export_method(self, rb_to_id(argv[i]), ex);
}
}
static VALUE
-mod_public(argc, argv)
+mod_public(argc, argv, module)
int argc;
VALUE *argv;
+ VALUE module;
{
- set_method_visibility(argc, argv, NOEX_PUBLIC);
+ set_method_visibility(module, argc, argv, NOEX_PUBLIC);
return Qnil;
}
static VALUE
-mod_private(argc, argv)
+mod_private(argc, argv, module)
int argc;
VALUE *argv;
+ VALUE module;
{
- set_method_visibility(argc, argv, NOEX_PRIVATE);
+ set_method_visibility(module, argc, argv, NOEX_PRIVATE);
return Qnil;
}
@@ -2775,19 +3239,13 @@ mod_modfunc(argc, argv, module)
ID id;
NODE *body, *old;
- set_method_visibility(argc, argv, NOEX_PRIVATE);
+ set_method_visibility(module, argc, argv, NOEX_PRIVATE);
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);
- }
+ id = rb_to_id(argv[i]);
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));
+ NameError("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);
}
@@ -2806,7 +3264,21 @@ mod_include(argc, argv, module)
Check_Type(argv[i], T_MODULE);
rb_include_module(module, argv[i]);
}
- return (VALUE)module;
+ return Qnil;
+}
+
+VALUE /* moved from object.c for push_iter */
+class_s_new(argc, argv, class)
+ int argc;
+ VALUE *argv;
+ VALUE class;
+{
+ VALUE obj = obj_alloc(class);
+
+ PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT);
+ rb_funcall2(obj, init, argc, argv);
+ POP_ITER();
+ return obj;
}
static VALUE
@@ -2823,7 +3295,13 @@ obj_extend(argc, argv, obj)
VALUE *argv;
VALUE obj;
{
- return mod_include(argc, argv, rb_singleton_class(obj));
+ int i;
+
+ mod_include(argc, argv, rb_singleton_class(obj));
+ for (i=0; i<argc; i++) {
+ rb_funcall(argv[i], rb_intern("object_extended"), 1, obj);
+ }
+ return Qnil;
}
void
@@ -2833,16 +3311,66 @@ rb_extend_object(obj, module)
rb_include_module(rb_singleton_class(obj), module);
}
-extern VALUE cKernel;
extern VALUE cModule;
VALUE f_trace_var();
VALUE f_untrace_var();
+extern VALUE rb_str_setter();
+
+static VALUE
+errat_setter(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ if (!NIL_P(val) && TYPE(val) != T_ARRAY) {
+ TypeError("value of $@ must be Array of String");
+ }
+ return *var = val;
+}
+
+static VALUE
+f_catch(dmy, tag)
+{
+ NODE *state;
+ ID t;
+ VALUE val;
+
+ t = rb_to_id(tag);
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ val = rb_yield(tag);
+ }
+ POP_TAG();
+ if (state) {
+ if (state->nd_tag == TAG_THROW && state->nd_tlev == t) {
+ return state->nd_tval;
+ }
+ JUMP_TAG(state);
+ }
+ return val;
+}
+
+static VALUE
+f_throw(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE tag, value;
+ ID t;
+
+ rb_scan_args(argc, argv, "11", &tag, &value);
+ t = rb_to_id(tag);
+ JUMP_TAG3(TAG_THROW, value, t);
+ /* not reached */
+}
+
void
Init_eval()
{
- match = rb_intern("=~");
+ init = rb_intern("initialize");
+ eqq = rb_intern("===");
each = rb_intern("each");
aref = rb_intern("[]");
@@ -2851,25 +3379,49 @@ Init_eval()
rb_global_variable(&top_scope);
rb_global_variable(&eval_tree);
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_hooked_variable("$@", &errat, 0, errat_setter);
+ rb_define_hooked_variable("$!", &errinfo, 0, rb_str_setter);
+
+ 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_method(cKernel, "respond_to?", krn_respond_to, -1);
+
+ rb_define_private_method(cKernel, "break", f_break, 0);
+ rb_define_alias(cKernel, "break!", "break");
+ rb_define_private_method(cKernel, "next", f_next, 0);
+ rb_define_alias(cKernel, "next!", "next");
+ rb_define_alias(cKernel, "continue", "next");
+ rb_define_private_method(cKernel, "redo", f_redo, 0);
+ rb_define_alias(cKernel, "redo!", "redo");
+ rb_define_private_method(cKernel, "retry", f_retry, 0);
+ rb_define_alias(cKernel, "retry!", "retry");
+ rb_define_private_method(cKernel, "raise", f_raise, -1);
+ rb_define_alias(cKernel, "fail", "raise");
+
rb_define_private_method(cKernel, "caller", f_caller, -1);
+ rb_define_private_method(cKernel, "exit", f_exit, -1);
+
+ rb_define_private_method(cKernel, "catch", f_catch, 1);
+ rb_define_private_method(cKernel, "throw", f_throw, -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(cModule, "method_defined?", mod_method_defined, 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);
+ rb_define_private_method(cKernel, "untrace_var", f_untrace_var, -1);
}
VALUE f_autoload();
@@ -2909,8 +3461,6 @@ scope_dup(scope)
}
}
-static ID blkdata;
-
static void
blk_mark(data)
struct BLOCK *data;
@@ -2931,6 +3481,29 @@ blk_free(data)
}
static VALUE
+f_binding(self)
+ VALUE self;
+{
+ extern VALUE cData;
+ struct BLOCK *data;
+ VALUE bind;
+
+ PUSH_BLOCK(0,0);
+ bind = Make_Data_Struct(cData, struct BLOCK, blk_mark, blk_free, data);
+ MEMCPY(data, the_block, struct BLOCK, 1);
+
+ data->iter = ITER_NOT;
+ data->frame.last_func = 0;
+ 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);
+ POP_BLOCK();
+
+ return bind;
+}
+
+static VALUE
proc_s_new(class)
VALUE class;
{
@@ -2938,15 +3511,13 @@ proc_s_new(class)
struct BLOCK *data;
if (!iterator_p() && !f_iterator_p()) {
- Fail("tryed to create Procedure-Object out of iterator");
+ ArgError("tryed to create Procedure-Object out of iterator");
}
- proc = obj_alloc(class);
-
- if (!blkdata) blkdata = rb_intern("blk");
- Make_Data_Struct(proc, blkdata, struct BLOCK, blk_mark, blk_free, data);
- MEMCPY(data, the_block, struct BLOCK, 1);
+ proc = Make_Data_Struct(class, struct BLOCK, blk_mark, blk_free, data);
+ *data = *the_block;
+ data->iter = ITER_NOT;
data->frame.argv = ALLOC_N(VALUE, data->frame.argc);
MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc);
@@ -2967,7 +3538,8 @@ proc_call(proc, args)
{
struct BLOCK *data;
VALUE result = Qnil;
- int state;
+ NODE *state;
+ int tag_level;
if (TYPE(args) == T_ARRAY) {
switch (RARRAY(args)->len) {
@@ -2980,11 +3552,12 @@ proc_call(proc, args)
}
}
- Get_Data_Struct(proc, blkdata, struct BLOCK, data);
+ Get_Data_Struct(proc, struct BLOCK, data);
/* PUSH BLOCK from data */
PUSH_BLOCK2(data);
PUSH_ITER(ITER_CUR);
+ the_frame->iter = ITER_CUR;
PUSH_TAG();
state = EXEC_TAG();
@@ -2994,34 +3567,1047 @@ proc_call(proc, args)
POP_TAG();
POP_ITER();
+ tag_level = the_block->level;
POP_BLOCK();
- switch (state) {
- case 0:
- break;
- case TAG_BREAK:
- case IN_BLOCK|TAG_BREAK:
- Fail("break from block-closure");
- break;
- case TAG_RETURN:
- case IN_BLOCK|TAG_RETURN:
- Fail("return from block-closure");
- break;
- default:
+ if (state) {
+ if (data->scope && (data->scope->flag & SCOPE_NOSTACK)) {
+ /* orphan procedure */
+ switch (state->nd_tag) {
+ case TAG_BREAK: /* never happen */
+ break;
+ case IN_BLOCK|TAG_BREAK:
+ if (state->nd_tlev != tag_level)
+ Raise(eLocalJumpError, "break from proc-closure");
+ break;
+ case TAG_RETRY:
+ Raise(eLocalJumpError, "retry from proc-closure");
+ break;
+ case TAG_RETURN: /* never happen */
+ case IN_BLOCK|TAG_RETURN:
+ Raise(eLocalJumpError, "return from proc-closure");
+ break;
+ }
+ }
+ else {
+ state->nd_tag &= ~IN_BLOCK;
+ }
JUMP_TAG(state);
}
-
return result;
}
void
Init_Proc()
{
- cProc = rb_define_class("Proc", cObject);
+ eLocalJumpError = rb_define_class("LocalJumpError", eException);
+ cProc = rb_define_class("Proc", cObject);
rb_define_singleton_method(cProc, "new", proc_s_new, 0);
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);
+ rb_define_private_method(cKernel, "lambda", f_lambda, 0);
+ rb_define_private_method(cKernel, "binding", f_binding, 0);
}
+
+#ifdef THREAD
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+int thread_pending = 0;
+
+static VALUE cThread;
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+
+extern VALUE last_status;
+
+enum thread_status {
+ THREAD_RUNNABLE,
+ THREAD_STOPPED,
+ THREAD_TO_KILL,
+ THREAD_KILLED,
+};
+
+#define WAIT_FD (1<<0)
+#define WAIT_TIME (1<<1)
+#define WAIT_JOIN (1<<2)
+
+/* +infty, for this purpose */
+#define DELAY_INFTY 1E30
+
+typedef struct thread * thread_t;
+
+struct thread {
+ struct thread *next, *prev;
+ jmp_buf context;
+ VALUE (*func)();
+ void *arg;
+
+ VALUE result;
+
+ int stk_len;
+ int stk_max;
+ VALUE*stk_ptr;
+ VALUE*stk_pos;
+
+ struct FRAME *frame;
+ struct SCOPE *scope;
+ struct RClass *class;
+ struct RVarmap *dyna_vars;
+ struct BLOCK *block;
+ struct iter *iter;
+ struct tag *tag;
+
+ char *file;
+ int line;
+
+ VALUE errat, errinfo;
+ VALUE last_status;
+ VALUE last_line;
+ VALUE last_match;
+
+ enum thread_status status;
+ int wait_for;
+ int fd;
+ double delay;
+ thread_t join;
+ VALUE thread;
+};
+
+static thread_t curr_thread;
+static int num_waiting_on_fd;
+static int num_waiting_on_timer;
+static int num_waiting_on_join;
+
+thread_curr() {return (int)curr_thread;}
+
+#define FOREACH_THREAD(x) x = curr_thread; do { x = x->next;
+#define END_FOREACH(x) } while (x != curr_thread)
+
+/* Return the current time as a floating-point number */
+static double
+timeofday()
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
+}
+
+static thread_t main_thread;
+
+#define ADJ(addr) (void*)(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr)
+#define STACK(addr) (th->stk_pos<(addr) && (addr)<th->stk_pos+th->stk_len)
+
+static void
+thread_mark(th)
+ thread_t th;
+{
+ struct FRAME *frame;
+ struct BLOCK *block;
+
+ gc_mark(th->result);
+ gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len);
+#ifdef THINK_C
+ gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
+#endif
+ gc_mark(th->thread);
+ if (th->join) gc_mark(th->join->thread);
+
+ gc_mark(th->scope);
+ gc_mark(th->dyna_vars);
+ gc_mark(th->errat);
+ gc_mark(th->errinfo);
+ gc_mark(th->last_line);
+ gc_mark(th->last_match);
+
+ /* mark data in copied stack */
+ frame = th->frame;
+ while (frame && frame != top_frame) {
+ frame = ADJ(frame);
+ if (frame->argv && !STACK(frame->argv)) {
+ gc_mark_frame(frame);
+ }
+ frame = frame->prev;
+ }
+ block = th->block;
+ while (block) {
+ block = ADJ(block);
+ if (block->frame.argv && !STACK(block->frame.argv)) {
+ gc_mark_frame(&block->frame);
+ }
+ block = block->prev;
+ }
+}
+
+void
+gc_mark_threads()
+{
+ thread_t th;
+
+ FOREACH_THREAD(th) {
+ thread_mark(th);
+ } END_FOREACH(th);
+}
+
+static void
+thread_free(th)
+ thread_t th;
+{
+ if (th->stk_ptr) free(th->stk_ptr);
+ th->stk_ptr = 0;
+}
+
+static thread_t
+thread_check(data)
+ struct RData *data;
+{
+ if (TYPE(data) != T_DATA || data->dfree != thread_free) {
+ TypeError("wrong argument type %s (expected Thread)",
+ rb_class2name(CLASS_OF(data)));
+ }
+ return (thread_t)data->data;
+}
+
+VALUE lastline_get();
+void lastline_set();
+VALUE backref_get();
+void backref_set();
+
+static int
+thread_save_context(th)
+ thread_t th;
+{
+ VALUE v;
+
+ th->stk_len = stack_length();
+ th->stk_pos = (gc_stack_start<(VALUE*)&v)?gc_stack_start
+ :gc_stack_start - th->stk_len;
+ if (th->stk_len > th->stk_max) {
+ th->stk_max = th->stk_len;
+ REALLOC_N(th->stk_ptr, VALUE, th->stk_max);
+ }
+ FLUSH_REGISTER_WINDOWS;
+ MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
+
+ th->frame = the_frame;
+ th->scope = the_scope;
+ th->class = the_class;
+ th->dyna_vars = the_dyna_vars;
+ th->block = the_block;
+ th->iter = the_iter;
+ th->tag = prot_tag;
+ th->errat = errat;
+ th->errinfo = errinfo;
+ th->last_status = last_status;
+ th->last_line = lastline_get();
+ th->last_match = backref_get();
+
+ th->file = sourcefile;
+ th->line = sourceline;
+}
+
+static void thread_restore_context();
+
+static void
+stack_extend(th, exit)
+ thread_t th;
+ int exit;
+{
+ VALUE space[1024];
+
+ memset(space, 0, 1); /* prevent array from optimization */
+ thread_restore_context(th, exit);
+}
+
+static void
+thread_restore_context(th, exit)
+ thread_t th;
+ int exit;
+{
+ VALUE v;
+ static thread_t tmp;
+ static int ex;
+
+ if (!th->stk_ptr) Bug("unsaved context");
+
+ if (&v < gc_stack_start) {
+ /* Stack grows downward */
+ if (&v > th->stk_pos) stack_extend(th, exit);
+ }
+ else {
+ /* Stack grows upward */
+ if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
+ }
+
+ the_frame = th->frame;
+ the_scope = th->scope;
+ the_class = th->class;
+ the_dyna_vars = th->dyna_vars;
+ the_block = th->block;
+ the_iter = th->iter;
+ prot_tag = th->tag;
+ the_class = th->class;
+ errat = th->errat;
+ errinfo = th->errinfo;
+ last_status = th->last_status;
+
+ lastline_set(th->last_line);
+ backref_set(th->last_match);
+
+ sourcefile = th->file;
+ sourceline = th->line;
+
+ tmp = th;
+ ex = exit;
+ FLUSH_REGISTER_WINDOWS;
+ MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
+
+ switch (ex) {
+ case 1:
+ JUMP_TAG2(TAG_FATAL, INT2FIX(0));
+ break;
+
+ case 2:
+ rb_interrupt();
+ break;
+
+ default:
+ longjmp(tmp->context, 1);
+ }
+}
+
+static void
+thread_ready(th)
+ thread_t th;
+{
+ /* The thread is no longer waiting on anything */
+ if (th->wait_for & WAIT_FD) {
+ num_waiting_on_fd--;
+ }
+ if (th->wait_for & WAIT_TIME) {
+ num_waiting_on_timer--;
+ }
+ if (th->wait_for & WAIT_JOIN) {
+ num_waiting_on_join--;
+ }
+ th->wait_for = 0;
+ th->status = THREAD_RUNNABLE;
+}
+
+static void
+thread_remove()
+{
+ thread_ready(curr_thread);
+ curr_thread->status = THREAD_KILLED;
+ curr_thread->prev->next = curr_thread->next;
+ curr_thread->next->prev = curr_thread->prev;
+ thread_schedule();
+}
+
+static int
+thread_dead(th)
+ thread_t th;
+{
+ return th->status == THREAD_KILLED;
+}
+
+void
+thread_schedule()
+{
+ thread_t next;
+ thread_t th;
+ thread_t curr;
+
+ thread_pending = 0;
+ if (curr_thread == curr_thread->next) return;
+
+ next = 0;
+ curr = curr_thread; /* real current thread */
+
+ if (curr_thread->status == THREAD_KILLED) {
+ curr_thread = curr_thread->prev;
+ }
+
+ again:
+ FOREACH_THREAD(th) {
+ if (th->status != THREAD_STOPPED && th->status != THREAD_KILLED) {
+ next = th;
+ break;
+ }
+ }
+ END_FOREACH(th);
+
+ if (num_waiting_on_join) {
+ FOREACH_THREAD(th) {
+ if ((th->wait_for & WAIT_JOIN) && thread_dead(th->join)) {
+ th->join = 0;
+ th->wait_for &= ~WAIT_JOIN;
+ th->status = THREAD_RUNNABLE;
+ num_waiting_on_join--;
+ if (!next) next = th;
+ }
+ }
+ END_FOREACH(th);
+ }
+
+ if (num_waiting_on_fd > 0 || num_waiting_on_timer > 0) {
+ fd_set readfds;
+ struct timeval delay_tv, *delay_ptr;
+ double delay, now;
+
+ int n, max;
+
+ do {
+ select_err:
+ max = 0;
+ FD_ZERO(&readfds);
+ if (num_waiting_on_fd > 0) {
+ FOREACH_THREAD(th) {
+ if (th->wait_for & WAIT_FD) {
+ FD_SET(th->fd, &readfds);
+ if (th->fd > max) max = th->fd;
+ }
+ }
+ END_FOREACH(th);
+ }
+
+ delay = DELAY_INFTY;
+ if (num_waiting_on_timer > 0) {
+ now = timeofday();
+ FOREACH_THREAD(th) {
+ if (th->wait_for & WAIT_TIME) {
+ if (th->delay <= now) {
+ th->delay = 0.0;
+ th->wait_for &= ~WAIT_TIME;
+ th->status = THREAD_RUNNABLE;
+ num_waiting_on_timer--;
+ next = th;
+ } else if (th->delay < delay) {
+ delay = th->delay;
+ }
+ }
+ }
+ END_FOREACH(th);
+ }
+ /* Do the select if needed */
+ if (num_waiting_on_fd > 0 || !next) {
+ /* Convert delay to a timeval */
+ /* If a thread is runnable, just poll */
+ if (next) {
+ delay_tv.tv_sec = 0;
+ delay_tv.tv_usec = 0;
+ delay_ptr = &delay_tv;
+ }
+ else if (delay == DELAY_INFTY) {
+ delay_ptr = 0;
+ }
+ else {
+ delay -= now;
+ delay_tv.tv_sec = (unsigned int)delay;
+ delay_tv.tv_usec = (delay - (double)delay_tv.tv_sec) * 1e6;
+ delay_ptr = &delay_tv;
+ }
+ n = select(max+1, &readfds, 0, 0, delay_ptr);
+ if (n > 0) {
+ /* Some descriptors are ready.
+ Make the corresponding threads runnable. */
+ FOREACH_THREAD(th)
+ if ((th->wait_for&WAIT_FD)
+ && FD_ISSET(th->fd, &readfds)) {
+ /* Wake up only one thread per fd. */
+ FD_CLR(th->fd, &readfds);
+ th->status = THREAD_RUNNABLE;
+ th->fd = 0;
+ th->wait_for &= ~WAIT_FD;
+ num_waiting_on_fd--;
+ if (!next) next = th; /* Found one. */
+ }
+ END_FOREACH(th);
+ }
+ if (n < 0 && !next) goto select_err;
+ }
+ /* The delays for some of the threads should have expired.
+ Go through the loop once more, to check the delays. */
+ } while (!next && delay != DELAY_INFTY);
+ }
+
+ if (!next) {
+ FOREACH_THREAD(th) {
+ fprintf(stderr, "%s:%d:deadlock 0x%x: %d:%d %s\n",
+ th->file, th->line, th->thread, th->status,
+ th->wait_for, th==main_thread?"(main)":"");
+ }
+ END_FOREACH(th);
+ Fatal("Thread: deadlock");
+ }
+ if (next == curr) {
+ return;
+ }
+
+ /* context switch */
+ if (curr == curr_thread) {
+ thread_save_context(curr);
+ if (setjmp(curr->context)) {
+ return;
+ }
+ }
+
+ curr_thread = next;
+ if (next->status == THREAD_TO_KILL) {
+ /* execute ensure-clause if any */
+ thread_restore_context(next, 1);
+ }
+ thread_restore_context(next, 0);
+}
+
+void
+thread_wait_fd(fd)
+ int fd;
+{
+ if (curr_thread == curr_thread->next) return;
+
+ curr_thread->status = THREAD_STOPPED;
+ curr_thread->fd = fd;
+ num_waiting_on_fd++;
+ curr_thread->wait_for |= WAIT_FD;
+ thread_schedule();
+}
+
+void
+thread_fd_writable(fd)
+ int fd;
+{
+ struct timeval zero;
+ fd_set fds;
+
+ zero.tv_sec = zero.tv_usec = 0;
+ if (curr_thread == curr_thread->next) return;
+
+ for (;;) {
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ if (select(fd+1, 0, &fds, 0, &zero) == 1) break;
+ thread_schedule();
+ }
+}
+
+void
+thread_wait_for(time)
+ struct timeval time;
+{
+ double date;
+
+ if (curr_thread == curr_thread->next) {
+ int n;
+#ifndef linux
+ double d, limit;
+ limit = timeofday()+(double)time.tv_sec+(double)time.tv_usec*1e-6;
+#endif
+ for (;;) {
+ TRAP_BEG;
+ n = select(0, 0, 0, 0, &time);
+ TRAP_END;
+ if (n == 0) return;
+
+#ifndef linux
+ d = limit - timeofday();
+
+ time.tv_sec = (int)d;
+ time.tv_usec = (int)((d - (int)d)*1e6);
+ if (time.tv_usec < 0) {
+ time.tv_usec += 1e6;
+ time.tv_sec -= 1;
+ }
+ if (time.tv_sec < 0) return;
+#endif
+ }
+ }
+
+ date = timeofday() + (double)time.tv_sec + (double)time.tv_usec*1e-6;
+ curr_thread->status = THREAD_STOPPED;
+ curr_thread->delay = date;
+ num_waiting_on_timer++;
+ curr_thread->wait_for |= WAIT_TIME;
+ thread_schedule();
+}
+
+void thread_sleep();
+
+int
+thread_select(max, read, write, except, timeout)
+ int max;
+ fd_set *read, *write, *except;
+ struct timeval *timeout;
+{
+ double limit;
+ struct timeval zero;
+ fd_set r, *rp, w, *wp, x, *xp;
+ int n;
+
+ if (!read && !write && !except) {
+ if (!timeout) {
+ thread_sleep();
+ return;
+ }
+ thread_wait_for(*timeout);
+ return 0;
+ }
+
+ if (timeout) {
+ limit = timeofday()+
+ (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
+ }
+
+ if (curr_thread == curr_thread->next) { /* no other thread */
+#ifndef linux
+ struct timeval tv, *tvp = timeout;
+
+ if (timeout) {
+ tv = *timeout;
+ tvp = &tv;
+ }
+ for (;;) {
+ TRAP_BEG;
+ n = select(max, read, write, except, tvp);
+ TRAP_END;
+ if (n < 0 && errno == EINTR) {
+ if (timeout) {
+ double d = timeofday() - limit;
+
+ tv.tv_sec = (unsigned int)d;
+ tv.tv_usec = (d - (double)tv.tv_sec) * 1e6;
+ }
+ continue;
+ }
+ return n;
+ }
+#else
+ for (;;) {
+ TRAP_BEG;
+ n = select(max, read, write, except, timeout);
+ TRAP_END;
+ if (n < 0 && errno == EINTR) {
+ continue;
+ }
+ return n;
+ }
+#endif
+
+ }
+
+ for (;;) {
+ zero.tv_sec = zero.tv_usec = 0;
+ if (read) {rp = &r; r = *read;} else {rp = 0;}
+ if (write) {wp = &w; w = *write;} else {wp = 0;}
+ if (except) {xp = &x; x = *except;} else {xp = 0;}
+ n = select(max, rp, wp, xp, &zero);
+ if (n > 0) {
+ /* write back fds */
+ if (read) {*read = r;}
+ if (write) {*write = w;}
+ if (except) {*except = x;}
+ return n;
+ }
+ if (n < 0 && errno != EINTR) {
+ return n;
+ }
+ if (timeout) {
+ if (timeout->tv_sec == 0 && timeout->tv_usec == 0) return 0;
+ if (limit <= timeofday()) return 0;
+ }
+
+ thread_schedule();
+ CHECK_INTS;
+ }
+}
+
+static VALUE
+thread_join(dmy, data)
+ VALUE dmy;
+ struct RData *data;
+{
+ thread_t th = thread_check(data);
+
+ if (thread_dead(th)) return Qnil;
+ if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread)
+ Fatal("Thread.join: deadlock");
+ curr_thread->status = THREAD_STOPPED;
+ curr_thread->join = th;
+ num_waiting_on_join++;
+ curr_thread->wait_for |= WAIT_JOIN;
+ thread_schedule();
+
+ return Qnil;
+}
+
+static VALUE
+thread_current()
+{
+ return curr_thread->thread;
+}
+
+int
+th_cur()
+{
+ return (int)curr_thread;
+}
+
+static VALUE
+thread_run(data)
+ struct RData *data;
+{
+ thread_t th = thread_check(data);
+
+ if (th->status == THREAD_KILLED) Fail("killed thread");
+ thread_ready(th);
+ thread_schedule();
+
+ return (VALUE)data;
+}
+
+static VALUE
+thread_kill(data)
+ struct RData *data;
+{
+ thread_t th = thread_check(data);
+
+ if (th->status == THREAD_TO_KILL) return Qnil;
+ if (th->status == THREAD_KILLED) return Qnil;
+ if (th == th->next || th == main_thread) rb_exit(0);
+
+ thread_ready(th);
+ th->status = THREAD_TO_KILL;
+ thread_schedule();
+ /* not reached */
+}
+
+static VALUE
+thread_s_kill(obj, th)
+ VALUE obj, th;
+{
+ return thread_kill(th);
+}
+
+static VALUE
+thread_exit()
+{
+ return thread_kill(curr_thread->thread);
+}
+
+static VALUE
+thread_stop_method(data)
+ struct RData *data;
+{
+ thread_t th = thread_check(data);
+
+ th->status = THREAD_STOPPED;
+ thread_schedule();
+
+ return Qnil;
+}
+
+static void
+thread_stop()
+{
+ thread_stop_method(curr_thread->thread);
+}
+
+void
+thread_sleep()
+{
+ if (curr_thread == curr_thread->next) {
+ TRAP_BEG;
+ sleep((32767<<16)+32767);
+ TRAP_END;
+ return;
+ }
+ thread_stop_method(curr_thread->thread);
+}
+
+static thread_t
+thread_alloc()
+{
+ thread_t th;
+
+ th = ALLOC(struct thread);
+ th->status = THREAD_RUNNABLE;
+ th->func = 0;
+ th->arg = 0;
+
+ th->status = 0;
+ th->result = 0;
+ th->errinfo = Qnil;
+ th->errat = Qnil;
+
+ th->stk_ptr = 0;
+ th->stk_len = 0;
+ th->stk_max = 0;
+ th->wait_for = 0;
+ th->fd = 0;
+ th->delay = 0.0;
+ th->join = 0;
+
+ th->frame = 0;
+ th->scope = 0;
+ th->class = 0;
+ th->dyna_vars = 0;
+ th->block = 0;
+ th->iter = 0;
+ th->tag = 0;
+
+ th->thread = data_object_alloc(cThread, th, 0, thread_free);
+
+ if (curr_thread) {
+ th->prev = curr_thread;
+ curr_thread->next->prev = th;
+ th->next = curr_thread->next;
+ curr_thread->next = th;
+ }
+ else {
+ curr_thread = th->prev = th->next = th;
+ th->status = THREAD_RUNNABLE;
+ }
+
+ return th;
+}
+
+VALUE
+thread_create(fn, arg)
+ VALUE (*fn)();
+ void *arg;
+{
+ thread_t th = thread_alloc();
+ NODE *state;
+
+ thread_save_context(curr_thread);
+ if (setjmp(curr_thread->context)) {
+ return th->thread;
+ }
+
+ th->func = fn;
+ th->arg = arg;
+
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ thread_save_context(th);
+ if (setjmp(th->context) == 0) {
+ curr_thread = th;
+ th->result = (*th->func)(th->arg, th);
+ }
+ }
+ POP_TAG();
+ if (state && th->status != THREAD_TO_KILL) {
+ /* global exit within this thread */
+ main_thread->errat = errat;
+ main_thread->errinfo = errinfo;
+ thread_cleanup();
+ }
+ thread_remove();
+}
+
+static void
+thread_yield(arg, th)
+ thread_t th;
+{
+ scope_dup(the_block->scope);
+ rb_yield(th->thread);
+}
+
+static VALUE
+thread_start()
+{
+ if (!iterator_p()) {
+ Raise(eLocalJumpError, "must be called as iterator");
+ }
+ return thread_create(thread_yield, 0);
+}
+
+static VALUE
+thread_value(data)
+ struct RData *data;
+{
+ thread_t th = thread_check(data);
+
+ thread_join(0, data);
+ return th->result;
+}
+
+static VALUE
+thread_status(data)
+ struct RData *data;
+{
+ thread_t th = thread_check(data);
+
+ return thread_dead(th)?FALSE:TRUE;
+}
+
+static VALUE
+thread_stopped(data)
+ struct RData *data;
+{
+ thread_t th = thread_check(data);
+
+ if (thread_dead(th)) return TRUE;
+ if (th->status == THREAD_STOPPED) return TRUE;
+ return FALSE;
+}
+
+static void
+thread_wait_other_threads()
+{
+ /* wait other threads to terminate */
+ while (curr_thread != curr_thread->next) {
+ thread_schedule();
+ }
+}
+
+static void
+thread_cleanup()
+{
+ thread_t th;
+
+ FOREACH_THREAD(th) {
+ if (th != curr_thread && th->status != THREAD_KILLED) {
+ th->status = THREAD_TO_KILL;
+ th->wait_for = 0;
+ }
+ }
+ END_FOREACH(th);
+}
+
+int thread_critical;
+
+static VALUE
+thread_exclusive()
+{
+ NODE *state;
+
+ thread_critical++;
+
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ rb_yield(Qnil);
+ }
+ POP_TAG();
+ thread_critical--;
+
+ if (state) JUMP_TAG(state);
+ thread_schedule();
+ return Qnil;
+}
+
+void
+thread_interrupt()
+{
+ thread_t th = main_thread;
+
+ thread_ready(main_thread);
+ if (th == curr_thread) {
+ rb_interrupt();
+ }
+ curr_thread = main_thread;
+ thread_restore_context(curr_thread, 2);
+}
+
+static thread_t loading_thread;
+static int loading_nest;
+
+static int
+thread_loading(feature)
+ char *feature;
+{
+ if (curr_thread != curr_thread->next && loading_thread) {
+ while (loading_thread != curr_thread) {
+ thread_schedule();
+ CHECK_INTS;
+ }
+ if (rb_provided(feature)) return TRUE; /* no need to load */
+ }
+
+ loading_thread = curr_thread;
+ loading_nest++;
+
+ return FALSE;
+}
+
+static void
+thread_loading_done()
+{
+ if (--loading_nest == 0) {
+ loading_thread = 0;
+ }
+}
+
+#if defined(HAVE_SETITIMER) && !defined(__BOW__)
+static void
+catch_timer(sig)
+ int sig;
+{
+#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
+ signal(sig, catch_timer);
+#endif
+ if (!thread_critical) {
+ if (trap_immediate) {
+ trap_immediate = 0;
+ thread_schedule();
+ }
+ else thread_pending = 1;
+ }
+}
+#else
+int thread_tick = THREAD_TICK;
+#endif
+
+void
+Init_Thread()
+{
+ cThread = rb_define_class("Thread", cObject);
+
+ rb_define_singleton_method(cThread, "new", thread_start, 0);
+ rb_define_singleton_method(cThread, "start", thread_start, 0);
+ rb_define_singleton_method(cThread, "fork", thread_start, 0);
+
+ rb_define_singleton_method(cThread, "stop", thread_stop, 0);
+ rb_define_singleton_method(cThread, "kill", thread_s_kill, 1);
+ rb_define_singleton_method(cThread, "exit", thread_exit, 0);
+ rb_define_singleton_method(cThread, "pass", thread_schedule, 0);
+ rb_define_singleton_method(cThread, "join", thread_join, 1);
+ rb_define_singleton_method(cThread, "current", thread_current, 0);
+ rb_define_singleton_method(cThread, "exclusive", thread_exclusive, 0);
+
+ rb_define_method(cThread, "run", thread_run, 0);
+ rb_define_method(cThread, "stop", thread_stop_method, 0);
+ rb_define_method(cThread, "exit", thread_kill, 0);
+ rb_define_method(cThread, "value", thread_value, 0);
+ rb_define_method(cThread, "status", thread_status, 0);
+ rb_define_method(cThread, "stop?", thread_stopped, 0);
+ rb_define_method(cThread, "stopped?", thread_stopped, 0);
+
+ /* allocate main thread */
+ main_thread = thread_alloc();
+
+#if defined(HAVE_SETITIMER) && !defined(__BOW__)
+ {
+ struct itimerval tval;
+
+#ifdef POSIX_SIGNAL
+ posix_signal(SIGVTALRM, catch_timer);
+#else
+ signal(SIGVTALRM, catch_timer);
+#endif
+
+ tval.it_interval.tv_sec = 0;
+ tval.it_interval.tv_usec = 50000;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+ }
+#endif
+}
+#endif
diff --git a/ext/Setup b/ext/Setup
index 93586ea0e6..4ea6aea10a 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -2,6 +2,8 @@
#dbm
#etc
+#kconv
#marshal
+#md5
#socket
-tkutil
+#tkutil
diff --git a/ext/Setup.dj b/ext/Setup.dj
new file mode 100644
index 0000000000..eb60525de0
--- /dev/null
+++ b/ext/Setup.dj
@@ -0,0 +1,8 @@
+option nodynamic
+
+dbm
+#etc
+marshal
+md5
+#socket
+#tkutil
diff --git a/ext/dbm/MANIFEST b/ext/dbm/MANIFEST
index 141b8dd601..8beec6783d 100644
--- a/ext/dbm/MANIFEST
+++ b/ext/dbm/MANIFEST
@@ -1,5 +1,4 @@
MANIFEST
dbm.c
-dbm.doc
depend
extconf.rb
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index dbdd99c0ca..5d8a12e3f9 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -17,10 +17,14 @@
#include <errno.h>
VALUE cDBM;
-static ID id_dbm;
extern VALUE mEnumerable;
+struct dbmdata {
+ int di_size;
+ DBM *di_dbm;
+};
+
static void
closeddbm()
{
@@ -28,24 +32,15 @@ closeddbm()
}
#define GetDBM(obj, dbmp) {\
- DBM **_dbm;\
- Get_Data_Struct(obj, id_dbm, DBM*, _dbm);\
- dbmp = *_dbm;\
- if (dbmp == Qnil) closeddbm();\
+ Get_Data_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp->di_dbm == 0) closeddbm();\
}
static void
free_dbm(dbmp)
- DBM **dbmp;
+ struct dbmdata *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;\
+ if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
}
static VALUE
@@ -55,7 +50,8 @@ fdbm_s_open(argc, argv, class)
VALUE class;
{
VALUE file, vmode;
- DBM *dbm, **dbm2;
+ DBM *dbm;
+ struct dbmdata *dbmp;
int mode;
VALUE obj;
@@ -70,7 +66,7 @@ fdbm_s_open(argc, argv, class)
}
Check_Type(file, T_STRING);
- dbm = Qnil;
+ dbm = 0;
if (mode >= 0)
dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
if (!dbm)
@@ -83,8 +79,9 @@ fdbm_s_open(argc, argv, class)
rb_sys_fail(RSTRING(file)->ptr);
}
- obj = obj_alloc(class);
- MakeDBM(obj, dbm);
+ obj = Make_Data_Struct(class,struct dbmdata,0,free_dbm,dbmp);
+ dbmp->di_dbm = dbm;
+ dbmp->di_size = -1;
return obj;
}
@@ -93,12 +90,12 @@ static VALUE
fdbm_close(obj)
VALUE obj;
{
- DBM **dbmp;
+ struct dbmdata *dbmp;
- Get_Data_Struct(obj, id_dbm, DBM*, dbmp);
- if (*dbmp == Qnil) Fail("already closed DBM file");
- dbm_close(*dbmp);
- *dbmp = Qnil;
+ Get_Data_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_dbm == 0) closeddbm();
+ dbm_close(dbmp->di_dbm);
+ dbmp->di_dbm = 0;
return Qnil;
}
@@ -108,15 +105,17 @@ fdbm_fetch(obj, keystr)
VALUE obj, keystr;
{
datum key, value;
+ struct dbmdata *dbmp;
DBM *dbm;
Check_Type(keystr, T_STRING);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
value = dbm_fetch(dbm, key);
- if (value.dptr == Qnil) {
+ if (value.dptr == 0) {
return Qnil;
}
return str_new(value.dptr, value.dsize);
@@ -128,38 +127,47 @@ fdbm_indexes(obj, args)
struct RArray *args;
{
VALUE *p, *pend;
- struct RArray *new;
+ VALUE 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);
+ args = (struct RArray*)rb_to_a(args);
+ new = ary_new2(args->len);
p = args->ptr; pend = p + args->len;
while (p < pend) {
- new->ptr[i++] = fdbm_fetch(obj, *p++);
- new->len = i;
+ ary_push(new, fdbm_fetch(obj, *p++));
}
- return (VALUE)new;
+ return new;
}
static VALUE
fdbm_delete(obj, keystr)
VALUE obj, keystr;
{
- datum key;
+ datum key, value;
+ struct dbmdata *dbmp;
DBM *dbm;
Check_Type(keystr, T_STRING);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ value = dbm_fetch(dbm, key);
+ if (value.dptr == 0) {
+ if (iterator_p()) rb_yield(Qnil);
+ return Qnil;
+ }
+
if (dbm_delete(dbm, key)) {
+ dbmp->di_size = -1;
Fail("dbm_delete failed");
}
+ else if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
return obj;
}
@@ -168,10 +176,12 @@ fdbm_shift(obj)
VALUE obj;
{
datum key, val;
+ struct dbmdata *dbmp;
DBM *dbm;
VALUE keystr, valstr;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
key = dbm_firstkey(dbm);
if (!key.dptr) return Qnil;
@@ -188,17 +198,19 @@ fdbm_delete_if(obj)
VALUE obj;
{
datum key, val;
+ struct dbmdata *dbmp;
DBM *dbm;
VALUE keystr, valstr;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
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");
+ if (RTEST(rb_yield(assoc_new(keystr, valstr)))) {
+ if (dbm_delete(dbm, key)) {
+ Fail("dbm_delete failed");
+ }
}
}
return obj;
@@ -209,9 +221,12 @@ fdbm_clear(obj)
VALUE obj;
{
datum key;
+ struct dbmdata *dbmp;
DBM *dbm;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
if (dbm_delete(dbm, key)) {
Fail("dbm_delete failed");
@@ -225,6 +240,7 @@ fdbm_store(obj, keystr, valstr)
VALUE obj, keystr, valstr;
{
datum key, val;
+ struct dbmdata *dbmp;
DBM *dbm;
if (valstr == Qnil) {
@@ -232,19 +248,26 @@ fdbm_store(obj, keystr, valstr)
return Qnil;
}
- Check_Type(keystr, T_STRING);
+ keystr = obj_as_string(keystr);
+
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- Check_Type(valstr, T_STRING);
+
+ if (NIL_P(valstr)) return fdbm_delete(obj, keystr);
+
+ valstr = obj_as_string(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbm);
+ Get_Data_Struct(obj, struct dbmdata, dbmp);
+ dbmp->di_size = -1;
+ dbm = dbmp->di_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;
}
@@ -253,24 +276,56 @@ fdbm_length(obj)
VALUE obj;
{
datum key;
+ struct dbmdata *dbmp;
DBM *dbm;
int i = 0;
- GetDBM(obj, dbm);
+ Get_Data_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
+ dbm = dbmp->di_dbm;
+
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
i++;
}
+ dbmp->di_size = i;
+
return INT2FIX(i);
}
static VALUE
+fdbm_empty(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ int i = 0;
+
+ Get_Data_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_size < 0) {
+ dbm = dbmp->di_dbm;
+
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ i++;
+ }
+ }
+ else {
+ i = dbmp->di_size;
+ }
+ if (i == 0) return TRUE;
+ return FALSE;
+}
+
+static VALUE
fdbm_each_value(obj)
VALUE obj;
{
datum key, val;
+ struct dbmdata *dbmp;
DBM *dbm;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_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));
@@ -283,9 +338,11 @@ fdbm_each_key(obj)
VALUE obj;
{
datum key;
+ struct dbmdata *dbmp;
DBM *dbm;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
rb_yield(str_new(key.dptr, key.dsize));
}
@@ -298,9 +355,11 @@ fdbm_each_pair(obj)
{
datum key, val;
DBM *dbm;
+ struct dbmdata *dbmp;
VALUE keystr, valstr;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
@@ -317,11 +376,14 @@ fdbm_keys(obj)
VALUE obj;
{
datum key;
+ struct dbmdata *dbmp;
DBM *dbm;
VALUE ary;
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
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));
}
@@ -334,11 +396,14 @@ fdbm_values(obj)
VALUE obj;
{
datum key, val;
+ struct dbmdata *dbmp;
DBM *dbm;
VALUE ary;
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
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));
@@ -352,13 +417,15 @@ fdbm_has_key(obj, keystr)
VALUE obj, keystr;
{
datum key, val;
+ struct dbmdata *dbmp;
DBM *dbm;
Check_Type(keystr, T_STRING);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
val = dbm_fetch(dbm, key);
if (val.dptr) return TRUE;
return FALSE;
@@ -369,13 +436,15 @@ fdbm_has_value(obj, valstr)
VALUE obj, valstr;
{
datum key, val;
+ struct dbmdata *dbmp;
DBM *dbm;
Check_Type(valstr, T_STRING);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
if (val.dsize == RSTRING(valstr)->len &&
@@ -390,10 +459,12 @@ fdbm_to_a(obj)
VALUE obj;
{
datum key, val;
+ struct dbmdata *dbmp;
DBM *dbm;
VALUE ary;
- GetDBM(obj, dbm);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
ary = ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
@@ -417,6 +488,7 @@ Init_dbm()
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, "empty?", fdbm_empty, 0);
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);
@@ -427,9 +499,11 @@ Init_dbm()
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, "include?", 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, "key?", fdbm_has_key, 1);
+ rb_define_method(cDBM, "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
deleted file mode 100644
index 45f174b7aa..0000000000
--- a/ext/dbm/dbm.doc
+++ /dev/null
@@ -1,107 +0,0 @@
-.\" 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/extconf.rb b/ext/dbm/extconf.rb
index 5105cd662f..2302ee2d5d 100644
--- a/ext/dbm/extconf.rb
+++ b/ext/dbm/extconf.rb
@@ -1,4 +1,4 @@
-have_library("dbm", "dbm_open")
+have_library("gdbm", "dbm_open") or have_library("dbm", "dbm_open")
if have_func("dbm_open")
create_makefile("dbm")
end
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index e4e4098f8a..524800bd03 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -24,12 +24,16 @@ static VALUE
etc_getlogin(obj)
VALUE obj;
{
+ char *getenv();
+ char *login;
+
#ifdef HAVE_GETLOGIN
char *getlogin();
- char *login = getlogin();
+
+ login = getlogin();
+ if (!login) login = getenv("USER");
#else
- char *getenv();
- char *login = getenv("USER");
+ login = getenv("USER");
#endif
if (login)
@@ -42,7 +46,7 @@ static VALUE
setup_passwd(pwd)
struct passwd *pwd;
{
- if (pwd == Qnil) rb_sys_fail("/etc/passwd");
+ if (pwd == 0) rb_sys_fail("/etc/passwd");
return struct_new(sPasswd,
str_new2(pwd->pw_name),
str_new2(pwd->pw_passwd),
@@ -69,7 +73,8 @@ setup_passwd(pwd)
#ifdef PW_EXPIRE
INT2FIX(pwd->pw_expire),
#endif
- Qnil);
+ 0 /*dummy*/
+ );
}
#endif
@@ -91,7 +96,7 @@ etc_getpwuid(argc, argv, obj)
uid = getuid();
}
pwd = getpwuid(uid);
- if (pwd == Qnil) Fail("can't find user for %d", uid);
+ if (pwd == 0) Fail("can't find user for %d", uid);
return setup_passwd(pwd);
#else
return Qnil;
@@ -107,7 +112,7 @@ etc_getpwnam(obj, nam)
Check_Type(nam, T_STRING);
pwd = getpwnam(RSTRING(nam)->ptr);
- if (pwd == Qnil) Fail("can't find user for %s", RSTRING(nam)->ptr);
+ if (pwd == 0) Fail("can't find user for %s", RSTRING(nam)->ptr);
return setup_passwd(pwd);
#else
return Qnil;
@@ -130,7 +135,7 @@ etc_passwd(obj)
return obj;
}
pw = getpwent();
- if (pw == Qnil) Fail("can't fetch next -- /etc/passwd");
+ if (pw == 0) Fail("can't fetch next -- /etc/passwd");
return setup_passwd(pw);
#else
return Qnil;
@@ -155,8 +160,7 @@ setup_group(grp)
str_new2(grp->gr_name),
str_new2(grp->gr_passwd),
INT2FIX(grp->gr_gid),
- mem,
- Qnil);
+ mem);
}
#endif
@@ -170,7 +174,7 @@ etc_getgrgid(obj, id)
gid = NUM2INT(id);
grp = getgrgid(gid);
- if (grp == Qnil) Fail("can't find group for %d", gid);
+ if (grp == 0) Fail("can't find group for %d", gid);
return setup_group(grp);
#else
return Qnil;
@@ -186,7 +190,7 @@ etc_getgrnam(obj, nam)
Check_Type(nam, T_STRING);
grp = getgrnam(RSTRING(nam)->ptr);
- if (grp == Qnil) Fail("can't find group for %s", RSTRING(nam)->ptr);
+ if (grp == 0) Fail("can't find group for %s", RSTRING(nam)->ptr);
return setup_group(grp);
#else
return Qnil;
@@ -214,7 +218,7 @@ etc_group(obj)
#endif
}
-VALUE mEtc;
+static VALUE mEtc;
void
Init_etc()
@@ -252,9 +256,11 @@ Init_etc()
#ifdef PW_EXPIRE
"expire",
#endif
- Qnil);
+ 0);
+ rb_global_variable(&sPasswd);
#ifdef HAVE_GETGRENT
- sGroup = struct_define("Group", "name", "passwd", "gid", "mem", Qnil);
+ sGroup = struct_define("Group", "name", "passwd", "gid", "mem", 0);
+ rb_global_variable(&sGroup);
#endif
}
diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in
index b61ccd222f..bd4eed306b 100644
--- a/ext/extmk.rb.in
+++ b/ext/extmk.rb.in
@@ -1,21 +1,24 @@
#! /usr/local/bin/ruby
-if $ARGV[0] == 'install'
+if ARGV[0] == 'static'
+ $force_static = TRUE
+ ARGV.shift
+elsif ARGV[0] == 'install'
$install = TRUE
- $ARGV.shift
-end
-
-if $ARGV[0] == 'clean'
+ ARGV.shift
+elsif ARGV[0] == 'clean'
$clean = TRUE
- $ARGV.shift
+ ARGV.shift
end
+$extlist = []
+
$cache_mod = FALSE;
$lib_cache = {}
$func_cache = {}
$hdr_cache = {}
-if File.exists?("config.cache") then
+if File.exist?("config.cache") then
f = open("config.cache", "r")
while f.gets
case $_
@@ -31,10 +34,10 @@ if File.exists?("config.cache") then
end
def older(file1, file2)
- if !File.exists?(file1) then
+ if !File.exist?(file1) then
return TRUE
end
- if !File.exists?(file2) then
+ if !File.exist?(file2) then
return FALSE
end
if File.mtime(file1) < File.mtime(file2)
@@ -61,7 +64,7 @@ def have_library(lib, func)
end
cfile = open("conftest.c", "w")
- printf cfile, "\
+ cfile.printf "\
int main() { return 0; }
int t() { %s(); return 0; }
", func
@@ -99,7 +102,7 @@ def have_func(func)
end
cfile = open("conftest.c", "w")
- printf cfile, "\
+ cfile.printf "\
char %s();
int main() { return 0; }
int t() { %s(); return 0; }
@@ -136,7 +139,7 @@ def have_header(header)
end
cfile = open("conftest.c", "w")
- printf cfile, "\
+ cfile.printf "\
#include <%s>
", header
cfile.close
@@ -162,7 +165,7 @@ def create_header()
hfile = open("extconf.h", "w")
for line in $defs
line =~ /^-D(.*)/
- printf hfile, "#define %s 1\n", $1
+ hfile.printf "#define %s 1\n", $1
end
hfile.close
end
@@ -180,7 +183,7 @@ def create_makefile(target)
$libs = "" if not $libs
mfile = open("Makefile", "w")
- printf mfile, "\
+ mfile.printf "\
SHELL = /bin/sh
#### Start of system configuration section. ####
@@ -191,36 +194,37 @@ VPATH = @srcdir@
CC = @CC@
CFLAGS = %s #$CFLAGS %s
+LDFLAGS = @LDFLAGS@
+DLDFLAGS = @DLDFLAGS@
LDSHARED = @LDSHARED@
", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ")
- printf mfile, "\
+ mfile.printf "\
prefix = @prefix@
-binprefix =
exec_prefix = @exec_prefix@
bindir = $(exec_prefix)/bin
-libdir = @prefix@/lib/ruby
+libdir = @archlib@
@SET_MAKE@
#### End of system configuration section. ####
"
- printf mfile, "LIBS = %s\n", $libs
- printf mfile, "OBJS = "
+ mfile.printf "LIBS = %s\n", $libs
+ mfile.printf "OBJS = "
if !$objs then
$objs = Dir["*.c"]
for f in $objs
f.sub!(/\.c$/, ".o")
end
end
- printf mfile, $objs.join(" ")
- printf mfile, "\n"
+ mfile.printf $objs.join(" ")
+ mfile.printf "\n"
- printf mfile, "\
+ dots = if "@INSTALL@" =~ /^\// then "" else "../" end
+ mfile.printf "\
TARGET = %s.%s
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
+INSTALL = %s@INSTALL@
all: $(TARGET)
@@ -229,56 +233,53 @@ clean:; @rm -f *.o *.so *.sl
@rm -f core ruby *~
realclean: clean
-", target, if $static then "o" else "@DLEXT@" end
+", target,
+ if $static then "o" else "@DLEXT@" end, dots
if !$static
- printf mfile, "\
+ mfile.printf "\
install: $(libdir)/$(TARGET)
$(libdir)/$(TARGET): $(TARGET)
@test -d $(libdir) || mkdir $(libdir)
- $(INSTALL_DATA) $(TARGET) $(libdir)/$(TARGET)
+ $(INSTALL) $(TARGET) $(libdir)/$(TARGET)
"
else
- printf mfile, "\
+ mfile.printf "\
install:;
"
end
if !$static && "@DLEXT@" != "o"
- printf mfile, "\
+ mfile.printf "\
$(TARGET): $(OBJS)
- $(LDSHARED) -o $(TARGET) $(OBJS) $(LIBS)
+ $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
"
- elsif !File.exists?(target + ".c")
- printf mfile, "\
+ elsif !File.exist?(target + ".c")
+ mfile.printf "\
$(TARGET): $(OBJS)
- ld $(LDDLFLAGS) -r $(TARGET) $(OBJS)
+ ld $(LDFLAGS) -r -o $(TARGET) $(OBJS)
"
end
- if File.exists?("depend")
+ if File.exist?("depend")
dfile = open("depend", "r")
- printf mfile, "###\n"
+ mfile.printf "###\n"
while line = dfile.gets()
- printf mfile, "%s", line
+ mfile.printf "%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)
+ $extlist.push [$static,target]
end
end
def extmake(target)
- if $static_ext[target]
+ if $force_static or $static_ext[target]
$static = target
else
$static = FALSE
@@ -294,19 +295,19 @@ def extmake(target)
begin
Dir.chdir target
if $static_ext.size > 0 ||
- !File.exists?("./Makefile") ||
+ !File.exist?("./Makefile") ||
older("./Makefile", "../Setup") ||
older("./Makefile", "../extmk.rb") ||
older("./Makefile", "./extconf.rb")
then
$defs = []
- if File.exists?("extconf.rb")
+ if File.exist?("extconf.rb")
load "extconf.rb"
else
create_makefile(target);
end
end
- if File.exists?("./Makefile")
+ if File.exist?("./Makefile")
if $install
system "make install"
elsif $clean
@@ -328,10 +329,10 @@ if File.file? "./Setup"
while f.gets()
$_.chop!
sub!(/#.*$/, '')
- continue if /^\s*$/
+ next if /^\s*$/
if /^option +nodynamic/
$nodynamic = TRUE
- continue
+ next
end
$static_ext[$_.split[0]] = TRUE
end
@@ -339,36 +340,56 @@ if File.file? "./Setup"
end
for d in Dir["*"]
- File.directory?(d) || continue
- File.file?(d + "/MANIFEST") || continue
+ File.directory?(d) || next
+ File.file?(d + "/MANIFEST") || next
d = $1 if d =~ /\/([\/]*)$/
- print "compiling ", d, "\n"
-
+ if $install
+ print "installing ", d, "\n"
+ elsif $clean
+ print "cleaning ", d, "\n"
+ else
+ print "compiling ", d, "\n"
+ end
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
+ f.printf "lib: %s %s\n", k, v
end
for k,v in $func_cache
- printf f, "func: %s %s\n", k, v
+ f.printf "func: %s %s\n", k, v
end
for k,v in $hdr_cache
- printf f, "hdr: %s %s\n", k, v
+ f.printf "hdr: %s %s\n", k, v
end
f.close
end
-exit if $install
-if $extobjs
+exit if $install or $clean
+if $extlist.size > 0
+ for s,t in $extlist
+ f = format("%s/%s.o", s, t)
+ if File.exist?(f)
+ $extinit += format("\
+\tInit_%s();\n\
+\trb_provide(\"%s.o\");\n\
+", t, t)
+ $extobjs += "ext/"
+ $extobjs += f
+ $extobjs += " "
+ else
+ FALSE
+ end
+ end
+
if older("extinit.c", "Setup")
f = open("extinit.c", "w")
- printf f, "void Init_ext() {\n"
- printf f, $extinit
- printf f, "}\n"
+ f.printf "void Init_ext() {\n"
+ f.printf $extinit
+ f.printf "}\n"
f.close
end
if older("extinit.o", "extinit.c")
@@ -378,16 +399,19 @@ if $extobjs
end
Dir.chdir ".."
- $extobjs = "ext/extinit.o " + $extobjs
if older("ruby", "ext/Setup") or older("ruby", "miniruby")
`rm -f ruby`
end
+
+ $extobjs = "ext/extinit.o " + $extobjs
system format('make ruby PROGRAM=ruby EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs)
else
Dir.chdir ".."
- `rm -f ruby`
- `cp miniruby ruby`
+ if older("ruby", "miniruby")
+ `rm -f ruby`
+ `cp miniruby ruby`
+ end
end
#Local variables:
diff --git a/ext/kconv/MANIFEST b/ext/kconv/MANIFEST
new file mode 100644
index 0000000000..8f37a9e166
--- /dev/null
+++ b/ext/kconv/MANIFEST
@@ -0,0 +1,2 @@
+MANIFEST
+kconv.c
diff --git a/ext/kconv/kconv.c b/ext/kconv/kconv.c
new file mode 100644
index 0000000000..fd6c3bed0a
--- /dev/null
+++ b/ext/kconv/kconv.c
@@ -0,0 +1,1934 @@
+/** Network Kanji Filter. (PDS Version)
+************************************************************************
+** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
+** Ϣ衧 ʳٻ̸ꡡեȣ
+** E-Mail Address: ichikawa@flab.fujitsu.co.jp
+** Copyright (C) 1996
+** Ϣ衧 ΰؾ󹩳ز mine/X0208 support
+** E-Mail Address: kono@ie.u-ryukyu.ac.jp
+** Ϣ衧 COW for DOS & Win16 & Win32 & OS/2
+** E-Mail Address: GHG00637@niftyserve.or.jp
+** ŪȤʤ¤ꡢΥΤʤ
+** ʣ̡ѡޤκݤˤϡʬĤȡ
+** ΥץˤĤƤä˲ݾڤ⤷ʤ餺
+** Everyone is permitted to do anything on this program
+** including copying, modifying, improving
+** as long as you don't try to make money off it,
+** or pretend that you wrote it.
+** i.e., the above copyright notice has to appear in all copies.
+** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
+***********************************************************************/
+
+/***********************************************************************
+** 1996/03/10 modified for Kconv - by Ikuo Nakagawa
+***********************************************************************/
+/***********************************************************************
+** 1996/12/18 modified for kconv(ruby) - by matz@ruby.club.or.jp
+***********************************************************************/
+
+static char *CopyRight =
+ "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1996 S. Kono, COW";
+static char *Version =
+ "1.62";
+static char *Patchlevel =
+ "5/9612/Shinji Kono, COW matz";
+
+/*
+**
+**
+**
+** USAGE: nkf [flags] [file]
+**
+** Flags:
+** b Output is bufferred (DEFAULT)
+** u Output is unbufferred
+**
+** t no operation
+**
+** j Outout code is JIS 7 bit (DEFAULT SELECT)
+** s Output code is MS Kanji (DEFAULT SELECT)
+** e Output code is AT&T JIS (DEFAULT SELECT)
+** l Output code is JIS 7bit and ISO8859-1 Latin-1
+**
+** m MIME conversion for ISO-2022-JP
+** i_ Output sequence to designate JIS-kanji (DEFAULT_J)
+** o_ Output sequence to designate single-byte roman characters (DEFAULT_R)
+**
+** r {de/en}crypt ROT13/47
+**
+** v display Version
+**
+** T Text mode output (for MS-DOS)
+**
+** x Do not convert X0201 kana into X0208
+** Z Convert X0208 alphabet to ASCII
+**
+** f60 fold option
+**
+** m MIME decode
+** B try to fix broken JIS, missing Escape
+** B[1-9] broken level
+**
+** O Output to 'nkf.out' file
+** d Delete \r in line feed
+** c Add \r in line feed
+**/
+/******************************/
+/* ǥեȤνϥ */
+/* Select DEFAULT_CODE */
+#define DEFAULT_CODE_JIS
+/* #define DEFAULT_CODE_SJIS */
+/* #define DEFAULT_CODE_EUC */
+/******************************/
+/* ץȥפ */
+#define ANSI_C_PROTOTYPE
+/******************************/
+
+/* for Kconv: _AUTO, _EUC, _SJIS, _JIS */
+#define _AUTO 0
+#define _JIS 1
+#define _EUC 2
+#define _SJIS 3
+
+#ifdef __STDC__
+#define ANSI_C_PROTOTYPE
+#endif
+
+#if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS)
+#define MSDOS
+#endif
+
+#include <stdio.h>
+
+#if defined(MSDOS) || defined(__OS2__)
+#include <stdlib.h>
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+#ifdef MSDOS
+#ifdef LSI_C
+#define setbinmode(fp) fsetbin(fp)
+#else /* Microsoft C, Turbo C */
+#define setbinmode(fp) setmode(fileno(fp), O_BINARY)
+#endif
+#else /* UNIX,OS/2 */
+#define setbinmode(fp)
+#endif
+
+#ifdef _IOFBF /* SysV and MSDOS */
+#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size)
+#else /* BSD */
+#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size)
+#endif
+
+/*Borland C++ 4.5 EasyWin*/
+#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
+#define EASYWIN
+#include <windows.h>
+#endif
+
+#define FALSE 0
+#define TRUE 1
+
+/* state of output_mode and input_mode */
+
+#define ASCII 0
+#define X0208 1
+#define X0201 2
+#define NO_X0201 3
+#define JIS_INPUT 4
+#define SJIS_INPUT 5
+#define LATIN1_INPUT 6
+#define FIXED_MIME 7
+#define DOUBLE_SPACE -2
+
+#define NL 0x0a
+#define ESC 0x1b
+#define SP 0x20
+#define AT 0x40
+#define SSP 0xa0
+#define DEL 0x7f
+#define SI 0x0f
+#define SO 0x0e
+#define SSO 0x8e
+
+#define HOLD_SIZE 32
+#define IOBUF_SIZE 16384
+
+#define DEFAULT_J 'B'
+#define DEFAULT_R 'B'
+
+#define SJ0162 0x00e1 /* 01 - 62 ku offset */
+#define SJ6394 0x0161 /* 63 - 94 ku offset */
+
+
+/* MIME preprocessor */
+
+#define _GETC() (*inptr ? (int)(*inptr++) : EOF)
+#define _UNGETC(c) (*--inptr = (c))
+#define PUTCHAR(c) (outlen + 1 < outsiz ? \
+ ((outptr[outlen++] = (c)), (outptr[outlen] = '\0')) : EOF)
+#define GETC() ((!mime_mode)?_GETC():mime_getc())
+#define UNGETC(c) ((!mime_mode)?_UNGETC(c):mime_ungetc(c))
+
+#ifdef EASYWIN /*Easy Win */
+extern POINT _BufferSize;
+#endif
+
+/* buffers */
+
+static unsigned char hold_buf[HOLD_SIZE*2];
+static int hold_count;
+static unsigned char *inptr;
+static char *outptr;
+static int outsiz;
+static int outlen;
+
+/* MIME preprocessor fifo */
+
+#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */
+#define MIME_BUF_MASK (MIME_BUF_SIZE-1)
+#define Fifo(n) mime_buf[(n)&MIME_BUF_MASK]
+static unsigned char mime_buf[MIME_BUF_SIZE];
+static unsigned int mime_top = 0;
+static unsigned int mime_last = 0; /* decoded */
+static unsigned int mime_input = 0; /* undecoded */
+
+/* flags */
+static int unbuf_f = FALSE;
+static int estab_f = FALSE;
+#ifdef notdef
+static int nop_f = FALSE;
+static int binmode_f = TRUE; /* binary mode */
+#endif
+static int rot_f = FALSE; /* rot14/43 mode */
+static int input_f = FALSE; /* non fixed input code */
+static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */
+static int mime_f = FALSE; /* convert MIME B base64 or Q */
+static int mimebuf_f = FALSE; /* MIME buffered input */
+static int broken_f = FALSE; /* convert ESC-less broken JIS */
+static int iso8859_f = FALSE; /* ISO8859 through */
+#if defined(MSDOS) || defined(__OS2__)
+static int x0201_f = TRUE; /* Assume JISX0201 kana */
+#else
+static int x0201_f = NO_X0201; /* Assume NO JISX0201 */
+#endif
+
+/* X0208 -> ASCII converter */
+
+static int c1_return;
+
+/* fold parameter */
+static int line = 0; /* chars in line */
+static int prev = 0;
+static int fold_f = FALSE;
+static int fold_len = 0;
+
+/* options */
+static char kanji_intro = DEFAULT_J,
+ ascii_intro = DEFAULT_R;
+
+/* Folding */
+
+static int fold();
+#define FOLD_MARGIN 10
+#define DEFAULT_FOLD 60
+
+/* Global states */
+static int output_mode = ASCII, /* output kanji mode */
+ input_mode = ASCII, /* input kanji mode */
+ shift_mode = FALSE; /* TRUE shift out, or X0201 */
+static int mime_mode = FALSE; /* MIME mode B base64, Q hex */
+
+/* X0208 -> ASCII translation table */
+
+static unsigned char cv[],dv[],ev[],fv[];
+
+#ifdef notdef
+static int file_out = FALSE;
+static int end_check;
+#endif
+static int add_cr = FALSE;
+static int del_cr = FALSE;
+
+/* function prototype */
+#ifdef ANSI_C_PROTOTYPE
+static void (*iconv) (register int c2,register int c1); /* s_iconv or oconv */
+static void (*oconv) (register int c2,register int c1); /* [ejs]_oconv */
+static int do_kconv(char *i, char *o, int siz, int out_code, int in_code);
+static void h_conv(register int c2,register int c1);
+static int push_hold_buf(int c2,int c1);
+static void s_iconv(register int c2,register int c1);
+static void e_oconv(register int c2,register int c1);
+static void s_oconv(register int c2,register int c1);
+static void j_oconv(register int c2,register int c1);
+static int fold(register int c2,register int c1);
+static int pre_convert(register int c1,register int c2);
+static int mime_begin();
+static int mime_getc();
+static int mime_ungetc(unsigned int c);
+static int mime_integrity(unsigned char *p);
+static int base64decode(int c);
+#else
+static void (*iconv) (); /* s_iconv or oconv */
+static void (*oconv) (); /* [ejs]_oconv */
+static int s_iconv ();
+static int e_oconv ();
+static int j_oconv ();
+static int s_oconv ();
+static int noconvert ();
+static int do_kconv();
+static void h_conv ();
+static int push_hold_buf ();
+#endif
+
+#ifdef notdef
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ register FILE *fin;
+ register char *cp;
+
+#ifdef EASYWIN /*Easy Win */
+ _BufferSize.y = 400;/*Set Scroll Buffer Size*/
+#endif
+#ifdef DEFAULT_CODE_JIS
+ oconv = j_oconv; /* DEFAULT Code is JIS */
+#endif
+#ifdef DEFAULT_CODE_SJIS
+ oconv = s_oconv; /* DEFAULT Code is S-JIS */
+#endif
+#ifdef DEFAULT_CODE_EUC
+ oconv = e_oconv; /* DEFAULT Code is EUC */
+#endif
+
+ for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
+ cp = *argv;
+ while (*cp) {
+ switch (*cp++) {
+ case 'b': /* buffered mode */
+ unbuf_f = FALSE;
+ continue;
+ case 'u': /* non bufferd mode */
+ unbuf_f = TRUE;
+ continue;
+ case 't': /* transparent mode */
+ nop_f = TRUE;
+ continue;
+ case 'j': /* JIS output */
+ case 'n':
+ oconv = j_oconv;
+ continue;
+ case 'e': /* AT&T EUC output */
+ oconv = e_oconv;
+ continue;
+ case 's': /* SJIS output */
+ oconv = s_oconv;
+ continue;
+ case 'l': /* ISO8859 Latin-1 support, no conversion */
+ iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
+ input_f = LATIN1_INPUT;
+ continue;
+ case 'i': /* Kanji IN ESC-$-@/B */
+ if(*cp=='@'||*cp=='B')
+ kanji_intro = *cp++;
+ continue;
+ case 'o': /* ASCII IN ESC-(-J/B */
+ if(*cp=='J'||*cp=='B'||*cp=='H')
+ ascii_intro = *cp++;
+ continue;
+ case 'r':
+ rot_f = TRUE;
+ continue;
+#if defined(MSDOS) || defined(__OS2__)
+ case 'T':
+ binmode_f = FALSE;
+ continue;
+#endif
+ case 'v':
+ usage();
+ exit(1);
+ break;
+ /* Input code assumption */
+ case 'J': /* JIS input */
+ case 'E': /* AT&T EUC input */
+ input_f = JIS_INPUT;
+ continue;
+ case 'S': /* MS Kanji input */
+ input_f = SJIS_INPUT;
+ if(x0201_f==NO_X0201) x0201_f=TRUE;
+ continue;
+ case 'Z': /* Convert X0208 alphabet to asii */
+ /* bit:0 Convert X0208
+ bit:1 Convert Kankaku to one space
+ bit:2 Convert Kankaku to two spaces
+ */
+ if('9'>= *cp && *cp>='0')
+ alpha_f |= 1<<(*cp++ -'0');
+ else
+ alpha_f |= TRUE;
+ continue;
+ case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
+ x0201_f = FALSE; /* No X0201->X0208 conversion */
+ /* accept X0201
+ ESC-(-I in JIS, EUC, MS Kanji
+ SI/SO in JIS, EUC, MS Kanji
+ SSO in EUC, JIS, not in MS Kanji
+ MS Kanji (0xa0-0xdf)
+ output X0201
+ ESC-(-I in JIS (0x20-0x5f)
+ SSO in EUC (0xa0-0xdf)
+ 0xa0-0xd in MS Kanji (0xa0-0xdf)
+ */
+ continue;
+ case 'X': /* Assume X0201 kana */
+ /* Default value is NO_X0201 for EUC/MS-Kanji mix */
+ x0201_f = TRUE;
+ continue;
+ case 'f': /* folding -f60 or -f */
+ fold_f = TRUE;
+ fold_len = atoi(cp);
+ if(!(0<fold_len && fold_len<BUFSIZ))
+ fold_len = DEFAULT_FOLD;
+ while('0'<= *cp && *cp <='9') cp++;
+ continue;
+ case 'm': /* MIME support */
+ mime_f = TRUE;
+ if(*cp=='B'||*cp=='Q') {
+ mime_mode = *cp++;
+ mimebuf_f = FIXED_MIME;
+ }
+ continue;
+ case 'B': /* Broken JIS support */
+ /* bit:0 no ESC JIS
+ bit:1 allow any x on ESC-(-x or ESC-$-x
+ bit:2 reset to ascii on NL
+ */
+ if('9'>= *cp && *cp>='0')
+ broken_f |= 1<<(*cp++ -'0');
+ else
+ broken_f |= TRUE;
+ continue;
+ case 'O':/* for Output file */
+ file_out = TRUE;
+ continue;
+ case 'c':/* add cr code */
+ add_cr = TRUE;
+ continue;
+ case 'd':/* delete cr code */
+ del_cr = TRUE;
+ continue;
+ default:
+ /* bogus option but ignored */
+ continue;
+ }
+ }
+ }
+
+ if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
+ fprintf(stderr,"Mixed ISO8859/JISX0201/SJIS/EUC output is not allowed.\n");
+ exit(1);
+ }
+
+ if(binmode_f == TRUE)
+#ifdef __OS2__
+ if(freopen("","wb",stdout) == NULL)
+ return (-1);
+#else
+ setbinmode(stdout);
+#endif
+
+ if(unbuf_f)
+ setbuf (stdout, (char *) NULL);
+ else
+ setvbuffer (stdout, stdobuf, IOBUF_SIZE);
+
+ if(argc == 0) {
+ if(binmode_f == TRUE)
+#ifdef __OS2__
+ if(freopen("","rb",stdin) == NULL) return (-1);
+#else
+ setbinmode(stdin);
+#endif
+ setvbuffer (stdin, stdibuf, IOBUF_SIZE);
+ if(nop_f)
+ noconvert (stdin);
+ else
+ convert (stdin);
+ } else {
+ while (argc--) {
+ if((fin = fopen (*argv++, "r")) == NULL) {
+ perror (*--argv);
+ return (-1);
+ } else {
+/* reopen file for stdout */
+ if(file_out == TRUE){
+ if(argc == 1 ) {
+ if(freopen(*argv++, "w", stdout) == NULL) {
+ perror (*--argv);
+ return (-1);
+ }
+ argc--;
+ } else {
+ if(freopen("nkf.out", "w", stdout) == NULL) {
+ perror (*--argv);
+ return (-1);
+ }
+ }
+ if(binmode_f == TRUE) {
+#ifdef __OS2__
+ if(freopen("","wb",stdout) == NULL)
+ return (-1);
+#else
+ setbinmode(stdout);
+#endif
+ }
+ }
+ if(binmode_f == TRUE)
+#ifdef __OS2__
+ if(freopen("","rb",fin) == NULL)
+ return (-1);
+#else
+ setbinmode(fin);
+#endif
+ setvbuffer (fin, stdibuf, IOBUF_SIZE);
+ if(nop_f)
+ noconvert (fin);
+ else
+ convert (fin);
+ fclose (fin);
+ }
+ }
+ }
+#ifdef EASYWIN /*Easy Win */
+ if(file_out == FALSE)
+ scanf("%d",&end_check);
+ else
+ fclose(stdout);
+#else /* for Other OS */
+ if(file_out == TRUE)
+ fclose(stdout);
+#endif
+ return (0);
+}
+
+int
+noconvert (f)
+ register FILE *f;
+{
+ register int c;
+
+ while ((c = getc (f)) != EOF)
+ putchar (c);
+ return 1;
+}
+
+#endif /* notdef */
+
+static int
+do_kconv(i, o, siz, out_code, in_code)
+ char *i;
+ char *o;
+ int siz, out_code, in_code;
+{
+ register int c1,
+ c2;
+
+ c2 = 0;
+
+ if (siz <= 0) {
+ return 0;
+ }
+ *o = '\0';
+
+ inptr = (unsigned char *)i; /* input buffer */
+ outptr = o; /* output buffer */
+ outsiz = siz; /* output buffer size */
+ outlen = 0; /* current length of output string */
+ x0201_f = FALSE; /* don't assume JISX0201 kana */
+ rot_f = FALSE; /* rot14/43 mode */
+ input_f = FALSE; /* non fixed input code */
+ alpha_f = FALSE; /* convert JISX0208 alphbet to ASCII */
+ mime_f = TRUE; /* convert MIME base64 */
+ broken_f = FALSE; /* convert ESC-less broken JIS */
+
+ switch (out_code) {
+ case _SJIS:
+ oconv = s_oconv;
+ break;
+ case _EUC:
+ oconv = e_oconv;
+ break;
+ default:
+ oconv = j_oconv;
+ break;
+ }
+
+ switch (in_code) {
+ case _SJIS:
+ input_f = SJIS_INPUT;
+ x0201_f = TRUE;
+ break;
+ case _EUC:
+ case _JIS:
+ input_f = JIS_INPUT;
+ break;
+ default:
+ input_f = FALSE;
+ break;
+ }
+
+ if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
+ estab_f = TRUE; iconv = oconv;
+ } else if(input_f == SJIS_INPUT) {
+ estab_f = TRUE; iconv = s_iconv;
+ } else {
+ estab_f = FALSE; iconv = oconv;
+ }
+ input_mode = ASCII;
+ output_mode = ASCII;
+ shift_mode = FALSE;
+ mime_mode = FALSE;
+
+#define NEXT continue /* no output, get next */
+#define SEND ; /* output c1 and c2, get next */
+#define LAST break /* end of loop, go closing */
+
+ while ((c1 = GETC()) != EOF) {
+ if(!c2 && !input_mode && c1<DEL && !mime_mode && !output_mode
+ && !shift_mode && !fold_f && !rot_f) {
+ /* plain ASCII tight loop, no conversion and no fold */
+ while(c1!='=' && c1!=SO && c1!=EOF &&
+ c1!=ESC && c1!='$' && c1<DEL && c1!='\r' && c1!='\n') {
+ PUTCHAR(c1);
+ c1 = _GETC();
+ }
+ if(c1==EOF) LAST;
+ }
+ if(c2) {
+ /* second byte */
+ if(c2 > DEL) {
+ /* in case of 8th bit is on */
+ if(!estab_f) {
+ /* in case of not established yet */
+ if(c1 > SSP) {
+ /* It is still ambiguious */
+ h_conv (c2, c1);
+ c2 = 0;
+ NEXT;
+ } else if(c1 < AT) {
+ /* ignore bogus code */
+ c2 = 0;
+ NEXT;
+ } else {
+ /* established */
+ /* it seems to be MS Kanji */
+ estab_f = TRUE;
+ iconv = s_iconv;
+ SEND;
+ }
+ } else
+ /* in case of already established */
+ if(c1 < AT) {
+ /* ignore bogus code */
+ c2 = 0;
+ NEXT;
+ } else
+ SEND;
+ } else
+ /* 7 bit code */
+ /* it might be kanji shitfted */
+ if((c1 == DEL) || (c1 <= SP)) {
+ /* ignore bogus first code */
+ c2 = 0;
+ NEXT;
+ } else
+ SEND;
+ } else {
+ /* first byte */
+ if(c1 > DEL) {
+ /* 8 bit code */
+ if(!estab_f && !iso8859_f) {
+ /* not established yet */
+ if(c1 < SSP) {
+ /* it seems to be MS Kanji */
+ estab_f = TRUE;
+ iconv = s_iconv;
+ } else if(c1 < 0xe0) {
+ /* it seems to be EUC */
+ estab_f = TRUE;
+ iconv = oconv;
+ } else {
+ /* still ambiguious */
+ }
+ c2 = c1;
+ NEXT;
+ } else { /* estab_f==TRUE */
+ if(iso8859_f) {
+ SEND;
+ } else if(SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
+ /* SJIS X0201 Case... */
+ /* This is too arrogant, but ... */
+ if(x0201_f==NO_X0201) {
+ iconv = oconv;
+ c2 = c1;
+ NEXT;
+ } else
+ if(x0201_f) {
+ if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
+ /* look ahead for X0201/X0208conversion */
+ if((c2 = GETC()) == EOF) {
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ LAST;
+ } else if(c2==(0xde)) { /* */
+ (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
+ c2=0;
+ NEXT;
+ } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) {
+ /* Ⱦ */
+ (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
+ c2=0;
+ NEXT;
+ }
+ UNGETC(c2); c2 = 0;
+ }
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ NEXT;
+ } else
+ SEND;
+ } else if(c1==SSO && iconv != s_iconv) {
+ /* EUC X0201 Case */
+ /* This is too arrogant
+ if(x0201_f == NO_X0201) {
+ estab_f = FALSE;
+ c2 = 0;
+ NEXT;
+ } */
+ c1 = GETC(); /* skip SSO */
+ euc_1byte_check:
+ if(x0201_f && SSP<=c1 && c1<0xe0) {
+ if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
+ if((c2 = GETC()) == EOF) {
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ LAST;
+ }
+ /* forward lookup /Ⱦ */
+ if(c2 != SSO) {
+ UNGETC(c2); c2 = 0;
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ NEXT;
+ } else if((c2 = GETC()) == EOF) {
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ (*oconv)(0,SSO);
+ LAST;
+ } else if(c2==(0xde)) { /* */
+ (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
+ c2=0;
+ NEXT;
+ } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) {
+ /* Ⱦ */
+ (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
+ c2=0;
+ NEXT;
+ } else {
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ /* we have to check this c2 */
+ /* and no way to push back SSO */
+ c1 = c2; c2 = 0;
+ goto euc_1byte_check;
+ }
+ }
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ NEXT;
+ } else
+ SEND;
+ } else if(c1 < SSP && iconv != s_iconv) {
+ /* strange code in EUC */
+ iconv = s_iconv; /* try SJIS */
+ c2 = c1;
+ NEXT;
+ } else {
+ /* already established */
+ c2 = c1;
+ NEXT;
+ }
+ }
+ } else if((c1 > SP) && (c1 != DEL)) {
+ /* in case of Roman characters */
+ if(shift_mode) {
+ c1 |= 0x80;
+ /* output 1 shifted byte */
+ if(x0201_f && (!iso8859_f||input_mode==X0201) &&
+ SSP<=c1 && c1<0xe0 ) {
+ if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
+ if((c2 = GETC()) == EOF) {
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ LAST;
+ } else if(c2==(0xde&0x7f)) { /* */
+ (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
+ c2=0;
+ NEXT;
+ } else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) {
+ /* Ⱦ */
+ (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
+ c2=0;
+ NEXT;
+ }
+ UNGETC(c2); c2 = 0;
+ }
+ (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
+ NEXT;
+ } else
+ SEND;
+ } else if(c1 == '(' && broken_f && input_mode == X0208
+ && !mime_mode ) {
+ /* Try to recover missing escape */
+ if((c1 = GETC()) == EOF) {
+ (*oconv) (0, '(');
+ LAST;
+ } else {
+ if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
+ input_mode = ASCII; shift_mode = FALSE;
+ NEXT;
+ } else {
+ (*oconv) (0, '(');
+ /* do not modify various input_mode */
+ /* It can be vt100 sequence */
+ SEND;
+ }
+ }
+ } else if(input_mode == X0208) {
+ /* in case of Kanji shifted */
+ c2 = c1;
+ NEXT;
+ /* goto next_byte */
+ } else if(c1 == '=' && mime_f && !mime_mode ) {
+ if((c1 = _GETC()) == EOF) {
+ (*oconv) (0, '=');
+ LAST;
+ } else if(c1 == '?') {
+ /* =? is mime conversion start sequence */
+ if(mime_begin() == EOF) /* check in detail */
+ LAST;
+ else
+ NEXT;
+ } else {
+ (*oconv) (0, '=');
+ _UNGETC(c1);
+ NEXT;
+ }
+ } else if(c1 == '$' && broken_f && !mime_mode) {
+ /* try to recover missing escape */
+ if((c1 = GETC()) == EOF) {
+ (*oconv) (0, '$');
+ LAST;
+ } else if(c1 == '@'|| c1 == 'B') {
+ /* in case of Kanji in ESC sequence */
+ input_mode = X0208;
+ shift_mode = FALSE;
+ NEXT;
+ } else {
+ /* sorry */
+ (*oconv) (0, '$');
+ (*oconv) (0, c1);
+ NEXT;
+ }
+ } else
+ SEND;
+ } else if(c1 == SI) {
+ shift_mode = FALSE;
+ NEXT;
+ } else if(c1 == SO) {
+ shift_mode = TRUE;
+ NEXT;
+ } else if(c1 == ESC ) {
+ if((c1 = GETC()) == EOF) {
+ (*oconv) (0, ESC);
+ LAST;
+ } else if(c1 == '$') {
+ if((c1 = GETC()) == EOF) {
+ (*oconv) (0, ESC);
+ (*oconv) (0, '$');
+ LAST;
+ } else if(c1 == '@'|| c1 == 'B') {
+ /* This is kanji introduction */
+ input_mode = X0208;
+ shift_mode = FALSE;
+ NEXT;
+ } else if(broken_f&0x2) {
+ input_mode = X0208;
+ shift_mode = FALSE;
+ NEXT;
+ } else {
+ (*oconv) (0, ESC);
+ (*oconv) (0, '$');
+ (*oconv) (0, c1);
+ NEXT;
+ }
+ } else if(c1 == '(') {
+ if((c1 = GETC()) == EOF) {
+ (*oconv) (0, ESC);
+ (*oconv) (0, '(');
+ LAST;
+ } else {
+ if(c1 == 'I') {
+ /* This is X0201 kana introduction */
+ input_mode = X0201; shift_mode = X0201;
+ NEXT;
+ } else if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
+ /* This is X0208 kanji introduction */
+ input_mode = ASCII; shift_mode = FALSE;
+ NEXT;
+ } else if(broken_f&0x2) {
+ input_mode = ASCII; shift_mode = FALSE;
+ NEXT;
+ } else {
+ (*oconv) (0, ESC);
+ (*oconv) (0, '(');
+ /* maintain various input_mode here */
+ SEND;
+ }
+ }
+ } else {
+ /* lonely ESC */
+ (*oconv) (0, ESC);
+ SEND;
+ }
+ } else if(c1 == NL && broken_f&4) {
+ input_mode = ASCII;
+ SEND;
+ } else
+ SEND;
+ }
+ /* send: */
+ if(input_mode == X0208)
+ (*oconv) (c2, c1); /* this is JIS, not SJIS/EUC case */
+ else
+ (*iconv) (c2, c1); /* can be EUC/SJIS */
+ c2 = 0;
+ continue;
+ /* goto next_word */
+ }
+
+ /* epilogue */
+ (*iconv) (EOF, 0);
+ return outlen;
+}
+
+
+static void
+h_conv (c2, c1)
+ register int c1,
+ c2;
+{
+ register int wc;
+
+
+ /** it must NOT be in the kanji shifte sequence */
+ /** it must NOT be written in JIS7 */
+ /** and it must be after 2 byte 8bit code */
+
+ hold_count = 0;
+ push_hold_buf (c2, c1);
+ c2 = 0;
+
+ while ((c1 = GETC()) != EOF) {
+ if(c2) {
+ /* second byte */
+ if(!estab_f) {
+ /* not established */
+ if(c1 > SSP) {
+ /* it is still ambiguious yet */
+ SEND;
+ } else if(c1 < AT) {
+ /* ignore bogus first byte */
+ c2 = 0;
+ SEND;
+ } else {
+ /* now established */
+ /* it seems to be MS Kanji */
+ estab_f = TRUE;
+ iconv = s_iconv;
+ SEND;
+ }
+ } else
+ SEND;
+ } else {
+ /* First byte */
+ if(c1 > DEL) {
+ /* 8th bit is on */
+ if(c1 < SSP) {
+ /* it seems to be MS Kanji */
+ estab_f = TRUE;
+ iconv = s_iconv;
+ } else if(c1 < 0xe0) {
+ /* it seems to be EUC */
+ estab_f = TRUE;
+ iconv = oconv;
+ } else {
+ /* still ambiguious */
+ }
+ c2 = c1;
+ NEXT;
+ } else
+ /* 7 bit code , then send without any process */
+ SEND;
+ }
+ /* send: */
+ if((push_hold_buf (c2, c1) == EOF) || estab_f)
+ break;
+ c2 = 0;
+ continue;
+ }
+
+ /** now,
+ ** 1) EOF is detected, or
+ ** 2) Code is established, or
+ ** 3) Buffer is FULL (but last word is pushed)
+ **
+ ** in 1) and 3) cases, we continue to use
+ ** Kanji codes by oconv and leave estab_f unchanged.
+ **/
+
+ for (wc = 0; wc < hold_count; wc += 2) {
+ c2 = hold_buf[wc];
+ c1 = hold_buf[wc+1];
+ (*iconv) (c2, c1);
+ }
+ return;
+}
+
+
+
+int
+push_hold_buf (c2, c1)
+ int c2,
+ c1;
+{
+ if(hold_count >= HOLD_SIZE*2)
+ return (EOF);
+ hold_buf[hold_count++] = c2;
+ hold_buf[hold_count++] = c1;
+ return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
+}
+
+
+static void
+s_iconv (c2, c1)
+ register int c2,
+ c1;
+{
+ if((c2 == EOF) || (c2 == 0)) {
+ /* NOP */
+ } else {
+ c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
+ if(c1 < 0x9f)
+ c1 = c1 - ((c1 > DEL) ? SP : 0x1f);
+ else {
+ c1 = c1 - 0x7e;
+ c2++;
+ }
+ }
+ (*oconv) (c2, c1);
+}
+
+
+static void
+e_oconv (c2, c1)
+ register int c2,
+ c1;
+{
+ c2 = pre_convert(c1,c2); c1 = c1_return;
+ if(fold_f) {
+ switch(fold(c2,c1)) {
+ case '\n':
+ if(add_cr == TRUE) {
+ PUTCHAR('\r');
+ c1 = '\n';
+ }
+ PUTCHAR('\n');
+ break;
+ case 0: return;
+ case '\r':
+ c1 = '\n'; c2 = 0;
+ break;
+ case '\t':
+ case ' ':
+ c1 = ' '; c2 = 0;
+ break;
+ }
+ }
+ if(c2==DOUBLE_SPACE) {
+ PUTCHAR(' '); PUTCHAR(' ');
+ return;
+ }
+ if(c2 == EOF)
+ return;
+ else if(c2 == 0 && (c1&0x80)) {
+ PUTCHAR(SSO); PUTCHAR(c1);
+ } else if(c2 == 0) {
+ if(c1 == '\n' && add_cr == TRUE)
+ PUTCHAR('\r');
+ if(c1 != '\r')
+ PUTCHAR(c1);
+ else if(del_cr == FALSE)
+ PUTCHAR(c1);
+ } else {
+ if((c1<0x20 || 0x7e<c1) ||
+ (c2<0x20 || 0x7e<c2)) {
+ estab_f = FALSE;
+ return; /* too late to rescue this char */
+ }
+ PUTCHAR(c2 | 0x080);
+ PUTCHAR(c1 | 0x080);
+ }
+}
+
+
+static void
+s_oconv (c2, c1)
+ register int c2,
+ c1;
+{
+ c2 = pre_convert(c1,c2); c1 = c1_return;
+ if(fold_f) {
+ switch(fold(c2,c1)) {
+ case '\n':
+ if(add_cr == TRUE) {
+ PUTCHAR('\r');
+ c1 = '\n';
+ }
+ PUTCHAR('\n');
+ break;
+ case '\r':
+ c1 = '\n'; c2 = 0;
+ break;
+ case 0: return;
+ case '\t':
+ case ' ':
+ c1 = ' '; c2 = 0;
+ break;
+ }
+ }
+ if(c2==DOUBLE_SPACE) {
+ PUTCHAR(' '); PUTCHAR(' ');
+ return;
+ }
+ if(c2 == EOF)
+ return;
+ else if(c2 == 0) {
+ if(c1 == '\n' && add_cr == TRUE)
+ PUTCHAR('\r');
+ if(c1 != '\r')
+ PUTCHAR(c1);
+ else if(del_cr == FALSE)
+ PUTCHAR(c1);
+ } else {
+ if((c1<0x20 || 0x7e<c1) ||
+ (c2<0x20 || 0x7e<c2)) {
+ estab_f = FALSE;
+ return; /* too late to rescue this char */
+ }
+ PUTCHAR((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
+ PUTCHAR((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
+ }
+}
+
+static void
+j_oconv (c2, c1)
+ register int c2,
+ c1;
+{
+ c2 = pre_convert(c1,c2); c1 = c1_return;
+ if(fold_f) {
+ switch(fold(c2,c1)) {
+ case '\n':
+ if(output_mode) {
+ PUTCHAR(ESC);
+ PUTCHAR('(');
+ PUTCHAR(ascii_intro);
+ }
+ if(add_cr == TRUE) {
+ PUTCHAR('\r');
+ c1 = '\n';
+ }
+ PUTCHAR('\n');
+ output_mode = ASCII;
+ break;
+ case '\r':
+ c1 = '\n'; c2 = 0;
+ break;
+ case '\t':
+ case ' ':
+ c1 = ' '; c2 = 0;
+ break;
+ case 0: return;
+ }
+ }
+ if(c2 == EOF) {
+ if(output_mode) {
+ PUTCHAR(ESC);
+ PUTCHAR('(');
+ PUTCHAR(ascii_intro);
+ }
+ } else if(c2 == 0 && (c1 & 0x80)) {
+ if(input_mode==X0201 || !iso8859_f) {
+ if(output_mode!=X0201) {
+ PUTCHAR(ESC);
+ PUTCHAR('(');
+ PUTCHAR('I');
+ output_mode = X0201;
+ }
+ c1 &= 0x7f;
+ } else {
+ /* iso8859 introduction, or 8th bit on */
+ /* Can we convert in 7bit form using ESC-'-'-A ?
+ Is this popular? */
+ }
+ PUTCHAR(c1);
+ } else if(c2 == 0) {
+ if(output_mode) {
+ PUTCHAR(ESC);
+ PUTCHAR('(');
+ PUTCHAR(ascii_intro);
+ output_mode = ASCII;
+ }
+ if(c1 == '\n' && add_cr == TRUE)
+ PUTCHAR('\r');
+ if(c1 != '\r')
+ PUTCHAR(c1);
+ else if(del_cr == FALSE)
+ PUTCHAR(c1);
+ } else if(c2 == DOUBLE_SPACE) {
+ if(output_mode) {
+ PUTCHAR(ESC);
+ PUTCHAR('(');
+ PUTCHAR(ascii_intro);
+ output_mode = ASCII;
+ }
+ PUTCHAR(' ');
+ if(c1 == '\n' && add_cr == TRUE)
+ PUTCHAR('\r');
+ if(c1 != '\r')
+ PUTCHAR(c1);
+ else if(del_cr == FALSE)
+ PUTCHAR(c1);
+ } else {
+ if(output_mode != X0208) {
+ PUTCHAR(ESC);
+ PUTCHAR('$');
+ PUTCHAR(kanji_intro);
+ output_mode = X0208;
+ }
+ if(c1<0x20 || 0x7e<c1)
+ return;
+ if(c2<0x20 || 0x7e<c2)
+ return;
+ PUTCHAR(c2);
+ if(c1 == '\n' && add_cr == TRUE)
+ PUTCHAR('\r');
+ if(c1 != '\r')
+ PUTCHAR(c1);
+ else if(del_cr == FALSE)
+ PUTCHAR(c1);
+ }
+}
+
+
+#define rot13(c) ( \
+ ( c < 'A' ) ? c: \
+ (c <= 'M') ? (c + 13): \
+ (c <= 'Z') ? (c - 13): \
+ (c < 'a') ? (c): \
+ (c <= 'm') ? (c + 13): \
+ (c <= 'z') ? (c - 13): \
+ (c) \
+)
+
+#define rot47(c) ( \
+ ( c < '!' ) ? c: \
+ ( c <= 'O' ) ? (c + 47) : \
+ ( c <= '~' ) ? (c - 47) : \
+ c \
+)
+
+/*
+ Return value of fold()
+
+ \n add newline and output char
+ \r add newline and output nothing
+ ' ' space
+ 0 skip
+ 1 (or else) normal output
+
+ fold state in prev (previous character)
+
+ >0x80 Japanese (X0208/X0201)
+ <0x80 ASCII
+ \n new line
+ ' ' space
+
+ This fold algorthm does not preserve heading space in a line.
+ This is the main difference from fmt.
+*/
+
+int
+fold(c2,c1)
+register int c2,c1;
+{
+ int prev0;
+ if(c1=='\r')
+ return 0; /* ignore cr */
+ if(c1== 8) {
+ if(line>0) line--;
+ return 1;
+ }
+ if(c2==EOF && line != 0) /* close open last line */
+ return '\n';
+ /* new line */
+ if(c1=='\n') {
+ if(prev == c1) { /* duplicate newline */
+ if(line) {
+ line = 0;
+ return '\n'; /* output two newline */
+ } else {
+ line = 0;
+ return 1;
+ }
+ } else {
+ if(prev&0x80) { /* Japanese? */
+ prev = c1;
+ return 0; /* ignore given single newline */
+ } else if(prev==' ') {
+ return 0;
+ } else {
+ prev = c1;
+ if(++line<=fold_len)
+ return ' ';
+ else {
+ line = 0;
+ return '\r'; /* fold and output nothing */
+ }
+ }
+ }
+ }
+ if(c1=='\f') {
+ prev = '\n';
+ if(line==0)
+ return 1;
+ line = 0;
+ return '\n'; /* output newline and clear */
+ }
+ /* X0208 kankaku or ascii space */
+ if( (c2==0&&c1==' ')||
+ (c2==0&&c1=='\t')||
+ (c2==DOUBLE_SPACE)||
+ (c2=='!'&& c1=='!')) {
+ if(prev == ' ') {
+ return 0; /* remove duplicate spaces */
+ }
+ prev = ' ';
+ if(++line<=fold_len)
+ return ' '; /* output ASCII space only */
+ else {
+ prev = ' '; line = 0;
+ return '\r'; /* fold and output nothing */
+ }
+ }
+ prev0 = prev; /* we still need this one... , but almost done */
+ prev = c1;
+ if(c2 || (SSP<=c1 && c1<=0xdf))
+ prev |= 0x80; /* this is Japanese */
+ line += (c2==0)?1:2;
+ if(line<=fold_len) { /* normal case */
+ return 1;
+ }
+ if(line>=fold_len+FOLD_MARGIN) { /* too many kinsou suspension */
+ line = (c2==0)?1:2;
+ return '\n'; /* We can't wait, do fold now */
+ }
+ /* simple kinsoku rules return 1 means no folding */
+ if(c2==0) {
+ if(c1==0xde) return 1; /* */
+ if(c1==0xdf) return 1; /* */
+ if(c1==0xa4) return 1; /* */
+ if(c1==0xa3) return 1; /* */
+ if(c1==0xa1) return 1; /* */
+ if(c1==0xb0) return 1; /* - */
+ if(SSP<=c1 && c1<=0xdf) { /* X0201 */
+ line = 1;
+ return '\n';/* add one new line before this character */
+ }
+ /* fold point in ASCII { [ ( */
+ if(( c1!=')'&&
+ c1!=']'&&
+ c1!='}'&&
+ c1!='.'&&
+ c1!=','&&
+ c1!='!'&&
+ c1!='?'&&
+ c1!='/'&&
+ c1!=':'&&
+ c1!=';')&&
+ ((prev0=='\n')|| (prev0==' ')|| /* ignored new line */
+ (prev0&0x80)) /* X0208 - ASCII */
+ ) {
+ line = 1;
+ return '\n';/* add one new line before this character */
+ }
+ return 1; /* default no fold in ASCII */
+ } else {
+ if(c2=='!') {
+ if(c1=='"') return 1; /* */
+ if(c1=='#') return 1; /* */
+ if(c1=='$') return 1; /* */
+ if(c1=='%') return 1; /* */
+ if(c1=='\'') return 1; /* */
+ if(c1=='(') return 1; /* */
+ if(c1==')') return 1; /* */
+ if(c1=='*') return 1; /* */
+ if(c1=='+') return 1; /* */
+ if(c1==',') return 1; /* */
+ }
+ line = 2;
+ return '\n'; /* add one new line before this character */
+ }
+}
+
+int
+pre_convert(c1,c2)
+register int c1,c2;
+{
+ if(c2) c1 &= 0x7f;
+ c1_return = c1;
+ if(c2==EOF) return c2;
+ c2 &= 0x7f;
+ if(rot_f) {
+ if(c2) {
+ c1 = rot47(c1);
+ c2 = rot47(c2);
+ } else {
+ if(!(c1 & 0x80))
+ c1 = rot13(c1);
+ }
+ c1_return = c1;
+ }
+ /* JISX0208 Alphabet */
+ if(alpha_f && c2 == 0x23 ) return 0;
+ /* JISX0208 Kigou */
+ if(alpha_f && c2 == 0x21 ) {
+ if(0x21==c1) {
+ if(alpha_f&0x2) {
+ c1_return = ' ';
+ return 0;
+ } else if(alpha_f&0x4) {
+ c1_return = ' ';
+ return DOUBLE_SPACE;
+ } else {
+ return c2;
+ }
+ } else if(0x20<c1 && c1<0x7f && fv[c1-0x20]) {
+ c1_return = fv[c1-0x20];
+ return 0;
+ }
+ }
+ return c2;
+}
+
+
+/* X0201 / X0208 conversion tables */
+
+/* X0201 kana conversion table */
+/* 90-9F A0-DF */
+unsigned char cv[]= {
+0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
+0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
+0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
+0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
+0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
+0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
+0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
+0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
+0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
+0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
+0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
+0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
+0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
+0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
+0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
+0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
+0x00,0x00};
+
+
+/* X0201 kana conversion table for daguten */
+/* 90-9F A0-DF */
+unsigned char dv[]= {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
+0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
+0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
+0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
+0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
+0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00};
+
+/* X0201 kana conversion table for han-daguten */
+/* 90-9F A0-DF */
+unsigned char ev[]= {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
+0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00};
+
+
+/* X0208 kigou conversion table */
+/* 0x8140 - 0x819e */
+unsigned char fv[] = {
+
+0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
+0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
+0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
+0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
+0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
+0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
+0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+} ;
+
+
+/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */
+
+unsigned char *mime_pattern[] = {
+ (unsigned char *)"\075?ISO-8859-1?Q?",
+ (unsigned char *)"\075?ISO-2022-JP?B?",
+ (unsigned char *)"\075?ISO-2022-JP?Q?",
+ NULL
+};
+
+int mime_encode[] = {
+ 'Q', 'B', 'Q',
+ 0
+};
+
+int iso8859_f_save;
+
+#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c)
+/* I don't trust portablity of toupper */
+
+int
+mime_begin()
+{
+ int c1;
+ int i,j,k;
+ unsigned char *p,*q;
+ int r[20]; /* recovery buffer, max mime pattern lenght */
+
+ mime_mode = FALSE;
+ /* =? has been checked */
+ j = 0;
+ p = mime_pattern[j];
+ r[0]='='; r[1]='?';
+
+ for(i=2;p[i]>' ';i++) { /* start at =? */
+ if( ((r[i] = c1 = _GETC())==EOF) || nkf_toupper(c1) != p[i] ) {
+ /* pattern fails, try next one */
+ q = p;
+ while (p = mime_pattern[++j]) {
+ for(k=2;k<i;k++) /* assume length(p) > i */
+ if(p[k]!=q[k]) break;
+ if(k==i && nkf_toupper(c1)==p[k]) break;
+ }
+ if(p) continue; /* found next one, continue */
+ /* all fails, output from recovery buffer */
+ _UNGETC(c1);
+ for(j=0;j<i;j++) {
+ (*oconv)(0,r[j]);
+ }
+ return c1;
+ }
+ }
+ iso8859_f_save = iso8859_f;
+ if(j==0) {
+ iso8859_f = TRUE;
+ }
+ mime_mode = mime_encode[j];
+ if(mime_mode=='B') {
+ mimebuf_f = unbuf_f;
+ if(!unbuf_f) {
+ /* do MIME integrity check */
+ return mime_integrity(mime_pattern[j]);
+ }
+ }
+ mimebuf_f = TRUE;
+ return c1;
+}
+
+#define mime_getc0() (mimebuf_f?_GETC():Fifo(mime_input++))
+#define mime_ungetc0(c) (mimebuf_f?_UNGETC(c):mime_input--)
+
+int
+mime_getc()
+{
+ int c1, c2, c3, c4, cc;
+ int t1, t2, t3, t4, mode, exit_mode;
+
+ if(mime_top != mime_last) { /* Something is in FIFO */
+ return Fifo(mime_top++);
+ }
+
+ if(mimebuf_f == FIXED_MIME)
+ exit_mode = mime_mode;
+ else
+ exit_mode = FALSE;
+ if(mime_mode == 'Q') {
+ if((c1 = mime_getc0()) == EOF) return (EOF);
+ if(c1=='_') return ' ';
+ if(c1!='=' && c1!='?')
+ return c1;
+ mime_mode = exit_mode; /* prepare for quit */
+ if(c1<=' ') return c1;
+ if((c2 = mime_getc0()) == EOF) return (EOF);
+ if(c2<=' ') return c2;
+ if(c1=='?'&&c2=='=') {
+ /* end Q encoding */
+ input_mode = exit_mode;
+ iso8859_f = iso8859_f_save;
+ return _GETC();
+ }
+ if(c1=='?') {
+ mime_mode = 'Q'; /* still in MIME */
+ mime_ungetc0(c2);
+ return c1;
+ }
+ if((c3 = mime_getc0()) == EOF) return (EOF);
+ if(c2<=' ') return c2;
+ mime_mode = 'Q'; /* still in MIME */
+#define hex(c) (('0'<=c&&c<='9')?(c-'0'):\
+ ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
+ return ((hex(c2)<<4) + hex(c3));
+ }
+
+ if(mime_mode != 'B') {
+ mime_mode = FALSE;
+ return _GETC();
+ }
+
+
+ /* Base64 encoding */
+ /*
+ MIME allows line break in the middle of
+ Base64, but we are very pessimistic in decoding
+ in unbuf mode because MIME encoded code may broken by
+ less or editor's control sequence (such as ESC-[-K in unbuffered
+ mode. ignore incomplete MIME.
+ */
+ mode = mime_mode;
+ mime_mode = exit_mode; /* prepare for quit */
+
+ while ((c1 = mime_getc0())<=' ') {
+ if(c1==EOF)
+ return (EOF);
+ }
+ if((c2 = mime_getc0())<=' ') {
+ if(c2==EOF)
+ return (EOF);
+ if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+ return c2;
+ }
+ if((c1 == '?') && (c2 == '=')) {
+ input_mode = ASCII;
+ while((c1 = _GETC())==' ' /* || c1=='\n' || c1=='\r' */);
+ return c1;
+ }
+ if((c3 = mime_getc0())<=' ') {
+ if(c3==EOF)
+ return (EOF);
+ if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+ return c3;
+ }
+ if((c4 = mime_getc0())<=' ') {
+ if(c4==EOF)
+ return (EOF);
+ if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+ return c4;
+ }
+
+ mime_mode = mode; /* still in MIME sigh... */
+
+ /* BASE 64 decoding */
+
+ t1 = 0x3f & base64decode(c1);
+ t2 = 0x3f & base64decode(c2);
+ t3 = 0x3f & base64decode(c3);
+ t4 = 0x3f & base64decode(c4);
+ cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
+ if(c2 != '=') {
+ Fifo(mime_last++) = cc;
+ cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
+ if(c3 != '=') {
+ Fifo(mime_last++) = cc;
+ cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
+ if(c4 != '=')
+ Fifo(mime_last++) = cc;
+ }
+ } else {
+ return c1;
+ }
+ return Fifo(mime_top++);
+}
+
+int
+mime_ungetc(c)
+unsigned int c;
+{
+ Fifo(mime_last++) = c;
+ return c;
+}
+
+
+int
+mime_integrity(p)
+unsigned char *p;
+{
+ int c,d;
+ unsigned int q;
+ /* In buffered mode, read until =? or NL or buffer full
+ */
+ mime_input = mime_top;
+ mime_last = mime_top;
+ while(*p) Fifo(mime_input++) = *p++;
+ d = 0;
+ q = mime_input;
+ while((c=_GETC())!=EOF) {
+ if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break;
+ if(c=='=' && d=='?') {
+ /* checked. skip header, start decode */
+ Fifo(mime_input++) = c;
+ mime_input = q;
+ return 1;
+ }
+ if(!( (c=='+'||c=='/'|| c=='=' || c=='?' ||
+ ('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))))
+ break;
+ /* Should we check length mod 4? */
+ Fifo(mime_input++) = c;
+ d=c;
+ }
+ /* In case of Incomplete MIME, no MIME decode */
+ Fifo(mime_input++) = c;
+ mime_last = mime_input; /* point undecoded buffer */
+ mime_mode = 1; /* no decode on Fifo last in mime_getc */
+ return 1;
+}
+
+int
+base64decode(c)
+ int c;
+{
+ int i;
+ if(c > '@')
+ if(c < '[')
+ i = c - 'A'; /* A..Z 0-25 */
+ else
+ i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */
+ else if(c > '/')
+ i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */
+ else if(c == '+')
+ i = '>' /* 62 */ ; /* + 62 */
+ else
+ i = '?' /* 63 */ ; /* / 63 */
+ return (i);
+}
+
+#ifdef notdef
+int
+usage()
+{
+ fprintf(stderr,"USAGE: nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
+ fprintf(stderr,"Flags:\n");
+ fprintf(stderr,"b,u Output is bufferred (DEFAULT),Output is unbufferred\n");
+#ifdef DEFAULT_CODE_SJIS
+ fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC)\n");
+#endif
+#ifdef DEFAULT_CODE_JIS
+ fprintf(stderr,"j,s,e Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC)\n");
+#endif
+#ifdef DEFAULT_CODE_EUC
+ fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT)\n");
+#endif
+ fprintf(stderr,"J,S,E Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC)\n");
+ fprintf(stderr,"t no conversion\n");
+ fprintf(stderr,"i_ Output sequence to designate JIS-kanji (DEFAULT B)\n");
+ fprintf(stderr,"o_ Output sequence to designate ASCII (DEFAULT B)\n");
+ fprintf(stderr,"r {de/en}crypt ROT13/47\n");
+ fprintf(stderr,"v Show this usage\n");
+ fprintf(stderr,"m[BQ] MIME decode [B:base64 stream,Q:quoted stream]\n");
+ fprintf(stderr,"l ISO8859-1 (Latin-1) support\n");
+ fprintf(stderr,"f Folding: -f60 or -f\n");
+ fprintf(stderr,"Z[0-2] Convert X0208 alphabet to ASCII 1: Kankaku to space,2: 2 spaces\n");
+ fprintf(stderr,"X,x Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
+ fprintf(stderr,"B[0-2] Broken input 0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
+#ifdef MSDOS
+ fprintf(stderr,"T Text mode output\n");
+#endif
+ fprintf(stderr,"O Output to File (DEFAULT 'nkf.out')\n");
+ fprintf(stderr,"d,c Delete \\r in line feed, Add \\r in line feed\n");
+ fprintf(stderr,"Network Kanji Filter Version %s (%s) "
+#if defined(MSDOS) && !defined(_Windows)
+ "for DOS"
+#endif
+#if !defined(__WIN32__) && defined(_Windows)
+ "for Win16"
+#endif
+#if defined(__WIN32__) && defined(_Windows)
+ "for Win32"
+#endif
+#ifdef __OS2__
+ "for OS/2"
+#endif
+ ,Version,Patchlevel);
+ fprintf(stderr,"\n%s\n",CopyRight);
+ return 0;
+}
+#endif /* notdef */
+
+#include "ruby.h"
+
+static VALUE
+kconv_kconv(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ struct RString *src, *dst;
+ VALUE in, out;
+ int in_code, out_code;
+
+ rb_scan_args(argc, argv, "12", &src, &out, &in);
+ Check_Type(src, T_STRING);
+
+ if (NIL_P(out)) {
+ out_code = _JIS;
+ }
+ else {
+ out_code = NUM2INT(out);
+ }
+ if (NIL_P(in)) {
+ in_code = _AUTO;
+ }
+ else {
+ in_code = NUM2INT(in);
+ }
+
+ dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */
+ dst->len = do_kconv(src->ptr, dst->ptr, dst->len, out_code, in_code);
+
+ return (VALUE)dst;
+}
+
+static VALUE
+kconv_tojis(obj, src)
+ VALUE obj;
+ struct RString *src;
+{
+ struct RString *dst;
+
+ Check_Type(src, T_STRING);
+
+ dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */
+ dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _JIS, _AUTO);
+
+ return (VALUE)dst;
+}
+
+static VALUE
+kconv_toeuc(obj, src)
+ VALUE obj;
+ struct RString* src;
+{
+ struct RString *dst;
+
+ Check_Type(src, T_STRING);
+
+ dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */
+ dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _EUC, _AUTO);
+
+ return (VALUE)dst;
+}
+
+static VALUE
+kconv_tosjis(obj, src)
+ VALUE obj;
+ struct RString* src;
+{
+ struct RString *dst;
+
+ Check_Type(src, T_STRING);
+
+ dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */
+ dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _SJIS, _AUTO);
+
+ return (VALUE)dst;
+}
+
+void
+Init_kconv()
+{
+ VALUE mKconv = rb_define_module("Kconv");
+
+ rb_define_module_function(mKconv, "kconv", kconv_kconv, -1);
+ rb_define_module_function(mKconv, "tojis", kconv_tojis, 1);
+ rb_define_module_function(mKconv, "toeuc", kconv_toeuc, 1);
+ rb_define_module_function(mKconv, "tosjis", kconv_tosjis, 1);
+
+ rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO));
+ rb_define_const(mKconv, "JIS", INT2FIX(_JIS));
+ rb_define_const(mKconv, "EUC", INT2FIX(_EUC));
+ rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS));
+}
+
+/**
+ ** ѥå
+ ** void@merope.pleiades.or.jp (Kusakabe Youichi)
+ ** NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
+ ** ohta@src.ricoh.co.jp (Junn Ohta)
+ ** inouet@strl.nhk.or.jp (Tomoyuki Inoue)
+ ** kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
+ ** Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
+ ** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
+ ** kono@ie.u-ryukyu.ac.jp (Shinji Kono)
+ ** GHG00637@nifty-serve.or.jp (COW)
+ ** j_kuro@pluto.ai.kyutech.ac.jp (Jun Kuroda)
+ **
+ ** ǽ
+ ** 1996.12.18
+ **/
+
+/* end */
diff --git a/ext/marshal/MANIFEST b/ext/marshal/MANIFEST
index 53b0849484..54870ec71f 100644
--- a/ext/marshal/MANIFEST
+++ b/ext/marshal/MANIFEST
@@ -1,4 +1,5 @@
MANIFEST
depend
+extconf.rb
marshal.c
marshal.doc
diff --git a/ext/marshal/extconf.rb b/ext/marshal/extconf.rb
new file mode 100644
index 0000000000..65923049e5
--- /dev/null
+++ b/ext/marshal/extconf.rb
@@ -0,0 +1,2 @@
+have_func("tmpnam")
+create_makefile("marshal")
diff --git a/ext/marshal/marshal.c b/ext/marshal/marshal.c
index 0b29ad5ab8..eae8d7fe09 100644
--- a/ext/marshal/marshal.c
+++ b/ext/marshal/marshal.c
@@ -13,24 +13,52 @@
#include "io.h"
#include "st.h"
+#define MARSHAL_MAJOR 2
+#define MARSHAL_MINOR 1
+
#define TYPE_NIL '0'
+#define TYPE_TRUE 'T'
+#define TYPE_FALSE 'F'
#define TYPE_FIXNUM 'i'
#define TYPE_OBJECT 'o'
-#define TYPE_LINK '@'
+#define TYPE_USERDEF 'u'
#define TYPE_FLOAT 'f'
#define TYPE_BIGNUM 'l'
#define TYPE_STRING '"'
+#define TYPE_STRING2 '\''
#define TYPE_REGEXP '/'
#define TYPE_ARRAY '['
+#define TYPE_ARRAY2 ']'
#define TYPE_HASH '{'
+#define TYPE_HASH2 '}'
#define TYPE_STRUCT 'S'
+#define TYPE_SYMBOL ':'
+#define TYPE_SYMLINK ';'
+
+VALUE cString;
+VALUE cArray;
+VALUE cHash;
+
char *rb_class2path();
VALUE rb_path2class();
static ID s_dump, s_load;
+#if (defined(linux) && defined(USE_DLN_A_OUT)) || !defined(HAVE_TMPNAM)
+#define tmpnam(s) ltmpnam(s)
+static char *
+tmpnam(s)
+ char *s;
+{
+ static int n = 0;
+
+ sprintf(s, "/tmp/rb-mrsr-%x%x", getpid(), n++);
+ return s;
+}
+#endif
+
#define w_byte(c, fp) putc((c), fp)
#define w_bytes(s, n, fp) (w_long((n), fp),fwrite(s, 1, n, fp))
@@ -66,70 +94,119 @@ w_float(d, fp)
}
static void
-w_symbol(id, fp)
+w_symbol(id, fp, table)
ID id;
FILE *fp;
+ st_table *table;
{
char *sym = rb_id2name(id);
+ int num;
- w_bytes(sym, strlen(sym), fp);
+ if (st_lookup(table, id, &num)) {
+ w_byte(TYPE_SYMLINK, fp);
+ w_long(num, fp);
+ }
+ else {
+ w_byte(TYPE_SYMBOL, fp);
+ w_bytes(sym, strlen(sym), fp);
+ st_insert(table, id, table->num_entries);
+ }
+}
+
+static void
+w_unique(s, fp, table)
+ char *s;
+ FILE *fp;
+ st_table *table;
+{
+ w_symbol(rb_intern(s), fp, table);
}
static void w_object();
extern VALUE cBignum, cStruct;
+struct each_arg {
+ FILE *fp;
+ VALUE limit;
+ st_table *table;
+};
+
static int
-hash_each(key, value, fp)
+hash_each(key, value, arg)
VALUE key, value;
- FILE *fp;
+ struct each_arg *arg;
{
- w_object(key, fp);
- w_object(value, fp);
+ w_object(key, arg->fp, arg->limit, arg->table);
+ w_object(value, arg->fp, arg->limit, arg->table);
return ST_CONTINUE;
}
static int
-obj_each(id, value, fp)
+obj_each(id, value, arg)
ID id;
VALUE value;
- FILE *fp;
+ struct each_arg *arg;
{
- w_symbol(id, fp);
- w_object(value, fp);
+ w_symbol(id, arg->fp, arg->table);
+ w_object(value, arg->fp, arg->limit, arg->table);
return ST_CONTINUE;
}
-struct st_table *new_idhash();
-
static void
-w_object(obj, fp, port, table)
- VALUE obj, port;
+w_object(obj, fp, limit, table)
+ VALUE obj;
FILE *fp;
+ int limit;
st_table *table;
{
+ struct each_arg arg;
+ int n;
+
+ if (limit == 0) {
+ Fail("exceed depth limit");
+ }
+ limit--;
+
+ arg.fp = fp;
+ arg.limit = limit;
+ arg.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 (obj == TRUE) {
+ w_byte(TYPE_TRUE, fp);
+ }
+ else if (obj == FALSE) {
+ w_byte(TYPE_FALSE, fp);
}
- else if (st_lookup(table, obj, 0)) {
- w_byte(TYPE_LINK, fp);
- w_long(obj, fp);
+ else if (FIXNUM_P(obj)) {
+ if (sizeof(long) == 4) {
+ w_byte(TYPE_FIXNUM, fp);
+ w_long(FIX2INT(obj), fp);
+ }
}
else {
- st_insert(table, obj, 0);
+ if (rb_respond_to(obj, s_dump)) {
+ VALUE v;
+
+ w_byte(TYPE_USERDEF, fp);
+ w_unique(rb_class2path(CLASS_OF(obj)), fp, table);
+ v = rb_funcall(obj, s_dump, 1, limit);
+ if (TYPE(v) != T_STRING) {
+ TypeError("_dump_to must return String");
+ }
+ w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, fp);
+ return;
+ }
switch (BUILTIN_TYPE(obj)) {
case T_FLOAT:
w_byte(TYPE_FLOAT, fp);
- w_long(obj, fp);
w_float(RFLOAT(obj)->value, fp);
- break;
+ return;
case T_BIGNUM:
w_byte(TYPE_BIGNUM, fp);
- w_long(obj, fp);
{
char sign = RBIGNUM(obj)->sign?'+':'-';
int len = RBIGNUM(obj)->len;
@@ -142,80 +219,92 @@ w_object(obj, fp, port, table)
d++;
}
}
- break;
+ return;
+ }
+ switch (BUILTIN_TYPE(obj)) {
case T_STRING:
- w_byte(TYPE_STRING, fp);
- w_long(obj, fp);
- w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp);
- break;
+ if (CLASS_OF(obj) == cString) {
+ w_byte(TYPE_STRING, fp);
+ w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp);
+ }
+ else {
+ w_byte(TYPE_STRING2, fp);
+ w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp);
+ w_unique(rb_class2path(CLASS_OF(obj)), fp, table);
+ }
+ return;
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;
+ return;
case T_ARRAY:
- w_byte(TYPE_ARRAY, fp);
- w_long(obj, fp);
+ if (CLASS_OF(obj) == cArray) w_byte(TYPE_ARRAY, fp);
+ else w_byte(TYPE_ARRAY2, fp);
{
int len = RARRAY(obj)->len;
VALUE *ptr = RARRAY(obj)->ptr;
w_long(len, fp);
while (len--) {
- w_object(*ptr, fp, port, table);
+ w_object(*ptr, fp, limit, table);
ptr++;
}
}
+ if (CLASS_OF(obj) != cArray) {
+ w_unique(rb_class2path(CLASS_OF(obj)), fp, table);
+ }
break;
case T_HASH:
+ if (CLASS_OF(obj) == cHash) w_byte(TYPE_HASH, fp);
+ else w_byte(TYPE_HASH2, fp);
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);
+ st_foreach(RHASH(obj)->tbl, hash_each, &arg);
+ if (CLASS_OF(obj) != cHash) {
+ w_unique(rb_class2path(CLASS_OF(obj)), fp, table);
+ }
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_unique(path, fp, table);
w_long(len, fp);
mem = rb_ivar_get(CLASS_OF(obj), rb_intern("__member__"));
if (mem == Qnil) {
- Fail("non-initialized struct");
+ Fatal("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);
+ w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), fp, table);
+ w_object(RSTRUCT(obj)->ptr[i], fp, limit, table);
}
}
break;
case T_OBJECT:
w_byte(TYPE_OBJECT, fp);
- w_long(obj, fp);
{
VALUE class = CLASS_OF(obj);
- char *path = rb_class2path(class);
+ char *path;
- w_bytes(path, strlen(path), fp);
- if (rb_responds_to(obj, s_dump)) {
- w_long(-1, fp);
- rb_funcall(obj, s_dump, 1, port);
+ if (FL_TEST(class, FL_SINGLETON)) {
+ TypeError("singleton can't be dumped");
}
- else if (ROBJECT(obj)->iv_tbl) {
+ path = rb_class2path(class);
+ w_unique(path, fp, table);
+ if (ROBJECT(obj)->iv_tbl) {
w_long(ROBJECT(obj)->iv_tbl->num_entries, fp);
- st_foreach(ROBJECT(obj)->iv_tbl, obj_each, fp);
+ st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &arg);
}
else {
w_long(0, fp);
@@ -224,59 +313,108 @@ w_object(obj, fp, port, table)
break;
default:
- Fail("can't dump %s", rb_class2name(CLASS_OF(obj)));
+ TypeError("can't dump %s", rb_class2name(CLASS_OF(obj)));
break;
}
}
}
+struct dump_arg {
+ VALUE obj;
+ FILE *fp;
+ int limit;
+ st_table *table;
+};
+
static VALUE
-marshal_dump(self, obj, port)
- VALUE self, obj, port;
+dump(arg)
+ struct dump_arg *arg;
+{
+ w_object(arg->obj, arg->fp, arg->limit, arg->table);
+}
+
+static VALUE
+dump_ensure(arg)
+ struct dump_arg *arg;
+{
+ st_free_table(arg->table);
+}
+
+static VALUE
+dump_on(obj, port, limit)
+ VALUE obj, port;
+ int limit;
{
extern VALUE cIO;
FILE *fp;
OpenFile *fptr;
- st_table *table;
+ struct dump_arg arg;
if (obj_is_kind_of(port, cIO)) {
GetOpenFile(port, fptr);
- if (!(fptr->mode & FMODE_WRITABLE)) {
- Fail("not opened for writing");
- }
+ io_writable(fptr);
fp = (fptr->f2) ? fptr->f2 : fptr->f;
}
else {
- Fail("instance of IO needed");
+ TypeError("instance of IO needed");
}
- table = new_idhash();
+ w_byte(MARSHAL_MAJOR, fp);
+ w_byte(MARSHAL_MINOR, fp);
- w_object(obj, fp, port, table);
+ arg.obj = obj;
+ arg.fp = fp;
+ arg.limit = limit;
+ arg.table = st_init_numtable();
+ rb_ensure(dump, &arg, dump_ensure, &arg);
- st_free_table(table);
return Qnil;
}
static VALUE
-marshal_dumps(self, obj)
- VALUE self, obj;
+marshal_dump(argc, argv)
+ int argc;
+ VALUE argv;
+{
+ VALUE obj, port, lim;
+ int limit;
+
+ rb_scan_args(argc, argv, "21", &obj, &port, &lim);
+ if (NIL_P(lim)) limit = 100;
+ else limit = NUM2INT(lim);
+
+ dump_on(obj, port, limit);
+}
+
+static VALUE
+marshal_dumps(argc, argv)
+ int argc;
+ VALUE argv;
{
+ VALUE obj, lim;
+ int limit;
VALUE str = str_new(0, 0);
VALUE port;
- FILE *fp = Qnil;
+ FILE *fp = 0;
char buf[BUFSIZ];
int n;
- sprintf(buf, "/tmp/rb-mrsr-%x", getpid()^(int)buf);
+ rb_scan_args(argc, argv, "11", &obj, &lim);
+ if (NIL_P(lim)) limit = 100;
+ else limit = NUM2INT(lim);
+
+ tmpnam(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)");
+ fp = rb_fopen(buf, "r");
+#if !defined(MSDOS) && !defined(__BOW__)
unlink(buf);
+#endif
- marshal_dump(self, obj, port);
+ dump_on(obj, port, limit);
io_close(port);
+#if defined(MSDOS) || defined(__BOW__)
+ unlink(buf);
+#endif
while (n = fread(buf, 1, BUFSIZ, fp)) {
str_cat(str, buf, n);
@@ -310,67 +448,96 @@ r_long(fp)
/* 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;
+
+#define r_bytes(s, fp) \
+ (s = (char*)r_long(fp), r_bytes0(&s,ALLOCA_N(char,(int)s),(int)s,fp))
+
+static char
+r_bytes0(sp, s, len, fp)
+ char **sp, *s;
+ int len;
FILE *fp;
{
- int len = r_long(fp);
- *s = ALLOC_N(char, len+1);
+ fread(s, 1, len, fp);
+ (s)[len] = '\0';
+ *sp = s;
- fread(*s, 1, len, fp);
- (*s)[len] = '\0';
return len;
}
static ID
-r_symbol(fp)
+r_symbol(fp, table)
FILE *fp;
+ st_table *table;
{
char *buf;
ID id;
+ char type;
+ if (r_byte(fp) == TYPE_SYMLINK) {
+ int num = r_long(fp);
+
+ if (st_lookup(table, num, &id)) {
+ return id;
+ }
+ TypeError("bad symbol");
+ }
r_bytes(buf, fp);
id = rb_intern(buf);
- free(buf);
+ st_insert(table, table->num_entries, id);
+
return id;
}
+static char*
+r_unique(fp, table)
+ FILE *fp;
+ st_table *table;
+{
+ return rb_id2name(r_symbol(fp, table));
+}
+
static VALUE
-r_object(fp, port, table)
+r_string(fp)
+ FILE *fp;
+{
+ char *buf;
+ int len = r_bytes(buf, fp);
+ VALUE v;
+
+ v = str_new(buf, len);
+
+ return v;
+}
+
+static VALUE
+r_object(fp, 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");
+ eof_error("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_TRUE:
+ return TRUE;
+
+ case TYPE_FALSE:
+ return FALSE;
case TYPE_FIXNUM:
{
int i = r_long(fp);
return INT2FIX(i);
}
- }
- id = r_long(fp);
- switch (type) {
case TYPE_FLOAT:
{
double atof();
@@ -378,9 +545,8 @@ r_object(fp, port, table)
r_bytes(buf, fp);
v = float_new(atof(buf));
- free(buf);
+ return v;
}
- break;
case TYPE_BIGNUM:
{
@@ -395,18 +561,16 @@ r_object(fp, port, table)
while (len--) {
*digits++ = r_short(fp);
}
- v = (VALUE)big;
+ return (VALUE)big;
}
- break;
case TYPE_STRING:
- {
- char *buf;
- int len = r_bytes(buf, fp);
- v = str_new(buf, len);
- free(buf);
- }
- break;
+ return r_string(fp);
+
+ case TYPE_STRING2:
+ v = r_string(fp);
+ RBASIC(v)->class = rb_path2class(r_unique(fp, table));
+ return v;
case TYPE_REGEXP:
{
@@ -414,19 +578,18 @@ r_object(fp, port, table)
int len = r_bytes(buf, fp);
int ci = r_byte(fp);
v = reg_new(buf, len, ci);
- free(buf);
+ return v;
}
- break;
case TYPE_ARRAY:
{
int len = r_long(fp);
v = ary_new2(len);
while (len--) {
- ary_push(v, r_object(fp, port, table));
+ ary_push(v, r_object(fp, table));
}
+ return v;
}
- break;
case TYPE_HASH:
{
@@ -434,120 +597,150 @@ r_object(fp, port, table)
v = hash_new();
while (len--) {
- VALUE key = r_object(fp, port, table);
- VALUE value = r_object(fp, port, table);
+ VALUE key = r_object(fp, table);
+ VALUE value = r_object(fp, table);
hash_aset(v, key, value);
}
+ return v;
}
- break;
case TYPE_STRUCT:
{
VALUE class, mem, values;
- char *path;
int i, len;
- r_bytes(path, fp);
- class = rb_path2class(path);
- free(path);
+ class = rb_path2class(r_unique(fp, table));
mem = rb_ivar_get(class, rb_intern("__member__"));
if (mem == Qnil) {
- Fail("non-initialized struct");
+ Fatal("non-initialized struct");
}
len = r_long(fp);
- values = ary_new();
+ values = ary_new2(len);
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));
+ for (i=0; i<len; i++) {
+ ID slot = r_symbol(fp, table);
+ if (RARRAY(mem)->ptr[i] != INT2FIX(slot))
+ TypeError("struct not compatible");
+ ary_push(values, r_object(fp, table));
}
v = struct_alloc(class, values);
}
break;
+ case TYPE_USERDEF:
+ {
+ VALUE class;
+ int len;
+
+ class = rb_path2class(r_unique(fp, table));
+ if (rb_respond_to(class, s_load)) {
+ v = rb_funcall(class, s_load, 1, r_string(fp));
+ }
+ else {
+ TypeError("class %s needs to have method `_load_from'",
+ rb_class2name(class));
+ }
+ }
+ break;
case TYPE_OBJECT:
{
VALUE class;
int len;
- char *path;
- r_bytes(path, fp);
- class = rb_path2class(path);
- free(path);
+ class = rb_path2class(r_unique(fp, table));
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);
- }
+ v = obj_alloc(class);
+ if (len > 0) {
+ while (len--) {
+ ID id = r_symbol(fp, table);
+ VALUE val = r_object(fp, table);
+ rb_ivar_set(v, id, val);
}
}
}
break;
default:
- Fail("dump format error(0x%x)", type);
+ ArgError("dump format error(0x%x)", type);
break;
}
- st_insert(table, id, v);
return v;
}
+struct load_arg {
+ FILE *fp;
+ st_table *table;
+};
+
+static VALUE
+load(arg)
+ struct load_arg *arg;
+{
+ return r_object(arg->fp, arg->table);
+}
+
+static VALUE
+load_ensure(arg)
+ struct load_arg *arg;
+{
+ st_free_table(arg->table);
+}
+
static VALUE
marshal_load(self, port)
VALUE self, port;
{
extern VALUE cIO;
- void *fp;
+ FILE *fp;
+ int major;
VALUE v;
OpenFile *fptr;
- st_table *table;
+ char buf[32];
+#if defined(MSDOS) || defined(__BOW__)
+ int need_unlink_tmp = 0;
+#endif
+ struct load_arg arg;
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");
+ tmpnam(buf);
+ fp = rb_fopen(buf, "w");
v = file_open(buf, "r");
- if (!v) rb_sys_fail("tmp file(read)");
+#if defined(MSDOS) || defined(__BOW__)
+ need_unlink_tmp = 0;
+#else
unlink(buf);
+#endif
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");
- }
+ io_readable(fptr);
fp = fptr->f;
}
else {
- Fail("instance of IO needed");
+ TypeError("instance of IO needed");
}
- table = new_idhash();
-
- v = r_object(fp, port, table);
-
- st_free_table(table);
+ major = r_byte(fp);
+ if (major == MARSHAL_MAJOR) {
+ if (r_byte(fp) != MARSHAL_MINOR) {
+ Warning("Old marshal file format (can be read)");
+ }
+ arg.fp = fp;
+ arg.table = st_init_numtable();
+ v = rb_ensure(load, &arg, load_ensure, &arg);
+ }
+#if defined(MSDOS) || defined(__BOW__)
+ if (need_unlink_tmp) unlink(buf);
+#endif
+ if (major != MARSHAL_MAJOR) {
+ TypeError("Old marshal file format (can't read)");
+ }
return v;
}
@@ -558,8 +751,8 @@ Init_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, "dump", marshal_dump, -1);
+ 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
index 8c3b63072e..7529e7942f 100644
--- a/ext/marshal/marshal.doc
+++ b/ext/marshal/marshal.doc
@@ -10,7 +10,7 @@ ruby֥Ȥե˽񤭽Фꡤɤߤ٤ꤹ뵡ǽ
Methods:
Single Methods:
- dump(obj, port)
+ dump(obj, port[, limit])
objƵŪ˥ե˽񤭽Фե˽񤭽Фʤ饹Υ
󥹥󥹤ե˽񤭽ФȤ㳰ȯ롥ե
@@ -28,6 +28,9 @@ Single Methods:
`_dump_to'ĥ饹ɬƱեޥåȤɤ᤹ðۥ᥽å
`_load_from'ɬפ롥
+ limitꤷ硤limitʰʾ忼󥯤֥Ȥ
+ Ǥʤ(ǥեȤ100٥)limitꤹȿå
+ Ԥʤ
dumps(obj)
diff --git a/ext/md5/MANIFEST b/ext/md5/MANIFEST
new file mode 100644
index 0000000000..e4f0004b4a
--- /dev/null
+++ b/ext/md5/MANIFEST
@@ -0,0 +1,6 @@
+MANIFEST
+depend
+md5.doc
+md5.h
+md5c.c
+md5init.c
diff --git a/ext/md5/depend b/ext/md5/depend
new file mode 100644
index 0000000000..be56da89b9
--- /dev/null
+++ b/ext/md5/depend
@@ -0,0 +1,2 @@
+md5c.o: md5c.c md5.h
+md5init.o: md5init.c ../../ruby.h ../../config.h ../../defines.h md5.h
diff --git a/ext/md5/md5.doc b/ext/md5/md5.doc
new file mode 100644
index 0000000000..2203404602
--- /dev/null
+++ b/ext/md5/md5.doc
@@ -0,0 +1,36 @@
+.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996
+
+** MD5(饹)
+
+RFC1321˵ҤƤRSA Data Security, Inc. MD5 Message-Digest
+Algorithm륯饹
+
+SuperClass: Object
+
+Class Methods:
+
+ new([str])
+ md5([str])
+
+ MD5֥Ȥ롥ʸͿȤ
+ ɲä(see update)
+
+Methods:
+
+ clone
+
+ MD5֥Ȥʣ
+
+ digest
+
+ ޤǤɲäʸФϥåͤ16ХĹʸ
+ ֤
+
+ update(str)
+
+ key򥭡Ȥ֤ͤ
+
+-------------------------------------------------------
+Local variables:
+fill-column: 70
+end:
diff --git a/ext/md5/md5.h b/ext/md5/md5.h
new file mode 100644
index 0000000000..81a6d7ff36
--- /dev/null
+++ b/ext/md5/md5.h
@@ -0,0 +1,86 @@
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* ========== include global.h ========== */
+/* GLOBAL.H - RSAREF types and constants
+ */
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+ function argument prototyping.
+The following makes PROTOTYPES default to 0 if it has not already
+ been defined with C compiler flags.
+ */
+#ifdef HAVE_PROTOTYPES
+#define PROTOTYPES 1
+#endif
+#ifndef PROTOTYPES
+#define PROTOTYPES 0
+#endif
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+/* Wild guess */
+#define LONG_MAX 2147483647L
+#endif
+
+/* UINT4 defines a four byte word */
+#if defined(INT_MAX) && INT_MAX == 2147483647
+typedef unsigned int UINT4;
+#else
+#if defined(LONG_MAX) && LONG_MAX == 2147483647L
+typedef unsigned long int UINT4;
+#endif
+/* Too bad if neither is */
+#endif
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+ returns an empty list.
+ */
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else
+#define PROTO_LIST(list) ()
+#endif
+/* ========== End global.h; continue md5.h ========== */
+
+/* MD5 context. */
+typedef struct {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD5_CTX;
+
+void MD5Init PROTO_LIST ((MD5_CTX *));
+void MD5Update PROTO_LIST
+ ((MD5_CTX *, unsigned char *, unsigned int));
+void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
diff --git a/ext/md5/md5c.c b/ext/md5/md5c.c
new file mode 100644
index 0000000000..d7c7e4fb27
--- /dev/null
+++ b/ext/md5/md5c.c
@@ -0,0 +1,337 @@
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "md5.h"
+
+/* Constants for MD5Transform routine.
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
+static void Encode PROTO_LIST
+ ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST
+ ((UINT4 *, unsigned char *, unsigned int));
+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (context)
+MD5_CTX *context; /* context */
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants.
+*/
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void MD5Update (context, input, inputLen)
+MD5_CTX *context; /* context */
+unsigned char *input; /* input block */
+unsigned int inputLen; /* length of input block */
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4)inputLen << 3))
+ < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /* Transform as many times as possible.
+*/
+ if (inputLen >= partLen) {
+ MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform (context->state, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+ inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+void MD5Final (digest, context)
+unsigned char digest[16]; /* message digest */
+MD5_CTX *context; /* context */
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64.
+*/
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ MD5Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5Update (context, bits, 8);
+
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information.
+*/
+ MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (state, block)
+UINT4 state[4];
+unsigned char block[64];
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information.
+*/
+ MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ a multiple of 4.
+ */
+static void Decode (output, input, len)
+UINT4 *output;
+unsigned char *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+
+static void MD5_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD5_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ ((char *)output)[i] = (char)value;
+}
diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c
new file mode 100644
index 0000000000..85f0847e71
--- /dev/null
+++ b/ext/md5/md5init.c
@@ -0,0 +1,90 @@
+/************************************************
+
+ md5init.c -
+
+ $Author: matz $
+ created at: Fri Aug 2 09:24:12 JST 1996
+
+ Copyright (C) 1995 Yukihiro Matsumoto
+
+************************************************/
+/* This module provides an interface to the RSA Data Security,
+ Inc. MD5 Message-Digest Algorithm, described in RFC 1321.
+ It requires the files md5c.c and md5.h (which are slightly changed
+ from the versions in the RFC to avoid the "global.h" file.) */
+
+#include "ruby.h"
+#include "md5.h"
+
+static VALUE cMD5;
+
+static VALUE
+md5_update(obj, str)
+ VALUE obj;
+ struct RString *str;
+{
+ MD5_CTX *md5;
+
+ Check_Type(str, T_STRING);
+ Get_Data_Struct(obj, MD5_CTX, md5);
+ MD5Update(md5, str->ptr, str->len);
+
+ return Qnil;
+}
+static VALUE
+md5_digest(obj)
+ VALUE obj;
+{
+ MD5_CTX *md5, ctx;
+ unsigned char digest[16];
+
+ Get_Data_Struct(obj, MD5_CTX, md5);
+ ctx = *md5;
+ MD5Final(digest, &ctx);
+
+ return str_new(digest, 16);
+}
+
+static VALUE
+md5_clone(obj)
+ VALUE obj;
+{
+ VALUE clone;
+ MD5_CTX *md5, *md5_new;
+
+ Get_Data_Struct(obj, MD5_CTX, md5);
+ obj = Make_Data_Struct(CLASS_OF(obj), MD5_CTX, 0, 0, md5_new);
+ *md5_new = *md5;
+
+ return obj;
+}
+
+static VALUE
+md5_new(argc, argv, class)
+{
+ int i;
+ VALUE arg, obj;
+ MD5_CTX *md5;
+
+ rb_scan_args(argc, argv, "01", &arg);
+ if (!NIL_P(arg)) Check_Type(arg, T_STRING);
+
+ obj = Make_Data_Struct(class, MD5_CTX, 0, 0, md5);
+ MD5Init(md5);
+ if (!NIL_P(arg)) {
+ md5_update(obj, arg);
+ }
+
+ return obj;
+}
+
+Init_md5()
+{
+ cMD5 = rb_define_class("MD5", cObject);
+
+ rb_define_singleton_method(cMD5, "new", md5_new, -1);
+
+ rb_define_method(cMD5, "update", md5_update, 1);
+ rb_define_method(cMD5, "digest", md5_digest, 0);
+ rb_define_method(cMD5, "clone", md5_clone, 0);
+}
diff --git a/ext/socket/MANIFEST b/ext/socket/MANIFEST
index 836caada41..d41d9e0b69 100644
--- a/ext/socket/MANIFEST
+++ b/ext/socket/MANIFEST
@@ -2,4 +2,3 @@ MANIFEST
depend
extconf.rb
socket.c
-socket.doc
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 60d6deeb84..f2ec0578d5 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -1,6 +1,11 @@
-have_library("inet", "gethostbyname")
have_library("socket", "socket")
+have_library("inet", "gethostbyname")
+have_library("nsl", "gethostbyname")
have_header("sys/un.h")
if have_func("socket")
+ have_func("hsterror")
+ unless have_func("gethostname")
+ have_func("uname")
+ end
create_makefile("socket")
end
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 5671b2762c..6b4f0f5559 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -18,11 +18,11 @@
#include <errno.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
-#else
-#undef AF_UNIX
#endif
extern VALUE cIO;
+extern VALUE cInteger;
+
VALUE cBasicSocket;
VALUE cTCPsocket;
VALUE cTCPserver;
@@ -32,6 +32,9 @@ VALUE cUNIXserver;
#endif
VALUE cSocket;
+extern VALUE eException;
+static VALUE eSocket;
+
FILE *rb_fdopen();
char *strdup();
@@ -52,8 +55,9 @@ sock_new(class, fd)
VALUE class;
int fd;
{
- VALUE sock = obj_alloc(class);
OpenFile *fp;
+ NEWOBJ(sock, struct RFile);
+ OBJSETUP(sock, class, T_FILE);
MakeOpenFile(sock, fp);
#ifdef NT
@@ -64,7 +68,7 @@ sock_new(class, fd)
fp->f2 = rb_fdopen(fd, "w");
fp->mode = FMODE_READWRITE|FMODE_SYNC;
- return sock;
+ return (VALUE)sock;
}
static VALUE
@@ -86,34 +90,53 @@ bsock_shutdown(argc, argv, sock)
}
GetOpenFile(sock, fptr);
if (shutdown(fileno(fptr->f), how) == -1)
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
return INT2FIX(0);
}
static VALUE
-bsock_setopt(sock, lev, optname, val)
+bsock_setsockopt(sock, lev, optname, val)
VALUE sock, lev, optname;
struct RString *val;
{
int level, option;
OpenFile *fptr;
+ int i;
+ char *v;
+ int vlen;
level = NUM2INT(lev);
option = NUM2INT(optname);
- Check_Type(val, T_STRING);
+ switch (TYPE(val)) {
+ case T_FIXNUM:
+ i = FIX2INT(val);
+ goto numval;
+ case T_FALSE:
+ i = 0;
+ goto numval;
+ case T_TRUE:
+ i = 1;
+ numval:
+ v = (char*)&i; vlen = sizeof(i);
+ break;
+ default:
+ Check_Type(val, T_STRING);
+ v = val->ptr; vlen = val->len;
+ }
GetOpenFile(sock, fptr);
- if (setsockopt(fileno(fptr->f), level, option, val->ptr, val->len) < 0)
+ if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0)
rb_sys_fail(fptr->path);
return INT2FIX(0);
}
static VALUE
-bsock_getopt(sock, lev, optname)
+bsock_getsockopt(sock, lev, optname)
VALUE sock, lev, optname;
{
+#if !defined(__CYGWIN32__)
int level, option, len;
struct RString *val;
OpenFile *fptr;
@@ -128,7 +151,11 @@ bsock_getopt(sock, lev, optname)
if (getsockopt(fileno(fptr->f), level, option, val->ptr, &len) < 0)
rb_sys_fail(fptr->path);
val->len = len;
+
return (VALUE)val;
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -184,8 +211,14 @@ open_inet(class, h, serv, server)
if (hostaddr == -1) {
if (server && !strlen(host))
hostaddr = INADDR_ANY;
- else
- rb_sys_fail(host);
+ else {
+#ifdef HAVE_HSTRERROR
+ extern int h_errno;
+ Raise(eSocket, (char *)hstrerror(h_errno));
+#else
+ Raise(eSocket, "host not found");
+#endif
+ }
}
_hostent.h_addr_list = (char **)hostaddrPtr;
_hostent.h_addr_list[0] = (char *)&hostaddr;
@@ -203,27 +236,31 @@ open_inet(class, h, serv, server)
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);
+ servport = strtoul(RSTRING(serv)->ptr, 0, 0);
+ if (servport == -1) {
+ Raise(eSocket, "no such servce %s", RSTRING(serv)->ptr);
+ }
setup_servent:
- _servent.s_port = servport;
- _servent.s_proto = "tcp";
+ _servent.s_port = htons(servport);
+ _servent.s_proto = "tcp";
servent = &_servent;
}
protoent = getprotobyname(servent->s_proto);
- if (protoent == NULL) Fail("no such proto %s", servent->s_proto);
+ if (protoent == NULL) {
+ Raise(eSocket, "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 {
+ if (h) {
memcpy((char *)&(sockaddr.sin_addr.s_addr),
(char *) hostent->h_addr_list[0],
(size_t) hostent->h_length);
}
+ else {
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+ }
sockaddr.sin_port = servent->s_port;
if (server) {
@@ -248,7 +285,7 @@ open_inet(class, h, serv, server)
}
static VALUE
-tcp_s_sock_open(class, host, serv)
+tcp_s_open(class, host, serv)
VALUE class, host, serv;
{
Check_Type(host, T_STRING);
@@ -266,7 +303,7 @@ tcp_svr_s_open(argc, argv, class)
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);
+ return open_inet(class, 0, arg1, 1);
}
static VALUE
@@ -279,10 +316,15 @@ s_accept(class, fd, sockaddr, len)
int fd2;
retry:
+#ifdef THREAD
+ thread_wait_fd(fd);
+#endif
+ TRAP_BEG;
fd2 = accept(fd, sockaddr, len);
+ TRAP_END;
if (fd2 < 0) {
if (errno == EINTR) goto retry;
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
}
return sock_new(class, fd2);
}
@@ -301,7 +343,7 @@ tcp_accept(sock)
(struct sockaddr*)&from, &fromlen);
}
-#ifdef AF_UNIX
+#ifdef HAVE_SYS_UN_H
static VALUE
open_unix(class, path, server)
VALUE class;
@@ -346,11 +388,63 @@ open_unix(class, path, server)
}
#endif
+static void
+setipaddr(name, addr)
+ char *name;
+ struct sockaddr_in *addr;
+{
+ int d1, d2, d3, d4;
+ char ch;
+ struct hostent *hp;
+ long x;
+ unsigned char *a;
+ char buf[16];
+
+ if (name[0] == 0) {
+ addr->sin_addr.s_addr = INADDR_ANY;
+ }
+ else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
+ addr->sin_addr.s_addr = INADDR_BROADCAST;
+ }
+ else if (sscanf(name, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
+ 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
+ 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
+ addr->sin_addr.s_addr = htonl(
+ ((long) d1 << 24) | ((long) d2 << 16) |
+ ((long) d3 << 8) | ((long) d4 << 0));
+ }
+ else {
+ hp = gethostbyname(name);
+ if (!hp) {
+#ifdef HAVE_HSTRERROR
+ extern int h_errno;
+ Raise(eSocket, (char *)hstrerror(h_errno));
+#else
+ Raise(eSocket, "host not found");
+#endif
+ }
+ memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length);
+ }
+}
+
+static VALUE
+mkipaddr(x)
+ unsigned long x;
+{
+ char buf[16];
+
+ x = ntohl(x);
+ sprintf(buf, "%d.%d.%d.%d",
+ (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
+ (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
+ return str_new2(buf);
+}
+
static VALUE
tcpaddr(sockaddr)
struct sockaddr_in *sockaddr;
{
- VALUE family, port, addr;
+ VALUE family, port, addr1, addr2;
VALUE ary;
struct hostent *hostent;
@@ -358,17 +452,15 @@ tcpaddr(sockaddr)
hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr,
sizeof(sockaddr->sin_addr),
AF_INET);
+ addr1 = 0;
if (hostent) {
- addr = str_new2(hostent->h_name);
+ addr1 = 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);
+ addr2 = mkipaddr(sockaddr->sin_addr.s_addr);
+ if (!addr1) addr1 = addr2;
+
+ port = INT2FIX(ntohs(sockaddr->sin_port));
+ ary = ary_new3(4, family, port, addr1, addr2);
return ary;
}
@@ -399,11 +491,30 @@ tcp_peeraddr(sock)
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
+ rb_sys_fail("getpeername(2)");
return tcpaddr(&addr);
}
-#ifdef AF_UNIX
+static VALUE
+tcp_s_getaddress(obj, host)
+ VALUE obj, host;
+{
+ struct sockaddr_in addr;
+ struct hostent *h;
+
+ if (obj_is_kind_of(host, cInteger)) {
+ int i = NUM2INT(host);
+ addr.sin_addr.s_addr = htonl(i);
+ }
+ else {
+ Check_Type(host, T_STRING);
+ setipaddr(RSTRING(host)->ptr, &addr);
+ }
+
+ return mkipaddr(addr.sin_addr.s_addr);
+}
+
+#ifdef HAVE_SYS_UN_H
static VALUE
unix_s_sock_open(sock, path)
VALUE sock, path;
@@ -418,11 +529,11 @@ unix_path(sock)
OpenFile *fptr;
GetOpenFile(sock, fptr);
- if (fptr->path == Qnil) {
+ if (fptr->path == 0) {
struct sockaddr_un addr;
int len = sizeof(addr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
fptr->path = strdup(addr.sun_path);
}
return str_new2(fptr->path);
@@ -515,7 +626,7 @@ setup_domain_and_type(domain, dv, type, tv)
*dv = PF_IPX;
#endif
else
- Fail("Unknown socket domain %s", ptr);
+ Raise(eSocket, "Unknown socket domain %s", ptr);
}
else {
*dv = NUM2INT(domain);
@@ -543,7 +654,7 @@ setup_domain_and_type(domain, dv, type, tv)
*tv = SOCK_PACKET;
#endif
else
- Fail("Unknown socket type %s", ptr);
+ Raise(eSocket, "Unknown socket type %s", ptr);
}
else {
*tv = NUM2INT(type);
@@ -559,7 +670,7 @@ sock_s_open(class, domain, type, protocol)
setup_domain_and_type(domain, &d, type, &t);
fd = socket(d, t, NUM2INT(protocol));
- if (fd < 0) rb_sys_fail("socke(2)");
+ if (fd < 0) rb_sys_fail("socket(2)");
return sock_new(class, fd);
}
@@ -574,6 +685,7 @@ static VALUE
sock_s_socketpair(class, domain, type, protocol)
VALUE class, domain, type, protocol;
{
+#if !defined(__CYGWIN32__)
int fd;
int d, t, sp[2];
@@ -582,6 +694,9 @@ sock_s_socketpair(class, domain, type, protocol)
rb_sys_fail("socketpair(2)");
return assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1]));
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -665,6 +780,9 @@ sock_send(argc, argv, sock)
GetOpenFile(sock, fptr);
f = fptr->f2?fptr->f2:fptr->f;
fd = fileno(f);
+#ifdef THREAD
+ thread_fd_writable(fd);
+#endif
if (to) {
Check_Type(to, T_STRING);
n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags),
@@ -703,8 +821,15 @@ s_recv(sock, argc, argv, from)
GetOpenFile(sock, fptr);
fd = fileno(fptr->f);
- if ((str->len = recvfrom(fd, str->ptr, str->len, flags,
- (struct sockaddr*)buf, &alen)) < 0) {
+#ifdef THREAD
+ thread_wait_fd(fd);
+#endif
+ TRAP_BEG;
+ str->len = recvfrom(fd, str->ptr, str->len, flags,
+ (struct sockaddr*)buf, &alen);
+ TRAP_END;
+
+ if (str->len < 0) {
rb_sys_fail("recvfrom(2)");
}
@@ -732,28 +857,173 @@ sock_recvfrom(argc, argv, sock)
return s_recv(sock, argc, argv, 1);
}
+#ifdef HAVE_GETHOSTNAME
+static VALUE
+sock_gethostname(obj)
+ VALUE obj;
+{
+ char buf[1024];
+
+ if (gethostname(buf, (int)sizeof buf - 1) < 0)
+ rb_sys_fail("gethostname");
+
+ buf[sizeof buf - 1] = '\0';
+ return str_new2(buf);
+}
+#else
+#ifdef HAVE_UNAME
+
+#include <sys/utsname.h>
+
+static VALUE
+sock_gethostname(obj)
+ VALUE obj;
+{
+ struct utsname un;
+
+ uname(&un);
+ return str_new2(un.nodename);
+}
+#else
+static VALUE
+sock_gethostname(obj)
+ VALUE obj;
+{
+ rb_notimplement();
+}
+#endif
+#endif
+
+static VALUE
+mkhostent(h)
+ struct hostent *h;
+{
+ struct sockaddr_in addr;
+ char **pch;
+ VALUE ary, names;
+
+ if (h == NULL) {
+#ifdef HAVE_HSTRERROR
+ extern int h_errno;
+ Raise(eSocket, (char *)hstrerror(h_errno));
+#else
+ Raise(eSocket, "host not found");
+#endif
+ }
+ ary = ary_new();
+ ary_push(ary, str_new2(h->h_name));
+ names = ary_new();
+ ary_push(ary, names);
+ for (pch = h->h_aliases; *pch; pch++) {
+ ary_push(names, str_new2(*pch));
+ }
+ ary_push(ary, INT2FIX(h->h_length));
+#ifdef h_addr
+ for (pch = h->h_addr_list; *pch; pch++) {
+ ary_push(ary, str_new(*pch, h->h_length));
+ }
+#else
+ ary_push(ary, str_new(h->h_addr, h->h_length));
+#endif
+
+ return ary;
+}
+
+static VALUE
+sock_s_gethostbyname(obj, host)
+ VALUE obj, host;
+{
+ struct sockaddr_in addr;
+ struct hostent *h;
+
+ if (obj_is_kind_of(host, cInteger)) {
+ int i = NUM2INT(host);
+ addr.sin_addr.s_addr = htonl(i);
+ }
+ else {
+ Check_Type(host, T_STRING);
+ setipaddr(RSTRING(host)->ptr, &addr);
+ }
+ h = gethostbyaddr((char *)&addr.sin_addr,
+ sizeof(addr.sin_addr),
+ AF_INET);
+
+ return mkhostent(h);
+}
+
+sock_s_gethostbyaddr(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE vaddr, vtype;
+ int type;
+
+ struct sockaddr_in *addr;
+ struct hostent *h;
+
+ rb_scan_args(argc, argv, "11", &addr, &type);
+ Check_Type(addr, T_STRING);
+ if (!NIL_P(type)) {
+ type = NUM2INT(vtype);
+ }
+ else {
+ type = AF_INET;
+ }
+
+ h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, type);
+
+ return mkhostent(h);
+}
+
+static VALUE
+sock_s_getservbyaname(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE service, protocol;
+ char *name, *proto;
+ struct servent *sp;
+ int port;
+
+ rb_scan_args(argc, argv, "11", &service, &protocol);
+ Check_Type(service, T_STRING);
+ if (NIL_P(protocol)) proto = "tcp";
+ else proto = RSTRING(protocol)->ptr;
+
+ sp = getservbyname(RSTRING(service)->ptr, proto);
+ if (!sp) {
+ Raise(eSocket, "service/proto not found");
+ }
+ port = ntohs(sp->s_port);
+
+ return INT2FIX(port);
+}
+
Init_socket ()
{
+ eSocket = rb_define_class("SocketError", eException);
+
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, "setsockopt", bsock_setsockopt, 3);
+ rb_define_method(cBasicSocket, "getsockopt", bsock_getsockopt, 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_singleton_method(cTCPsocket, "open", tcp_s_open, 2);
+ rb_define_singleton_method(cTCPsocket, "new", tcp_s_open, 2);
rb_define_method(cTCPsocket, "addr", tcp_addr, 0);
rb_define_method(cTCPsocket, "peeraddr", tcp_peeraddr, 0);
+ rb_define_singleton_method(cTCPsocket, "getaddress", tcp_s_getaddress, 1);
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
+#ifdef HAVE_SYS_UN_H
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);
@@ -782,4 +1052,64 @@ Init_socket ()
rb_define_method(cSocket, "recvfrom", sock_recv, -1);
rb_define_singleton_method(cSocket, "socketpair", sock_s_socketpair, 3);
+ rb_define_singleton_method(cSocket, "pair", sock_s_socketpair, 3);
+ rb_define_singleton_method(cSocket, "gethostname", sock_gethostname, 0);
+ rb_define_singleton_method(cSocket, "gethostbyname", sock_s_gethostbyname, 1);
+ rb_define_singleton_method(cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
+ rb_define_singleton_method(cSocket, "getservbyname", sock_s_getservbyaname, -1);
+
+ /* constants */
+ rb_define_const(cSocket, "AF_INET", INT2FIX(AF_INET));
+ rb_define_const(cSocket, "PF_INET", INT2FIX(PF_INET));
+#ifdef AF_UNIX
+ rb_define_const(cSocket, "AF_UNIX", INT2FIX(AF_UNIX));
+ rb_define_const(cSocket, "PF_UNIX", INT2FIX(PF_UNIX));
+#endif
+#ifdef AF_IPX
+ rb_define_const(cSocket, "AF_IPX", INT2FIX(AF_IPX));
+ rb_define_const(cSocket, "PF_IPX", INT2FIX(PF_IPX));
+#endif
+#ifdef AF_APPLETALK
+ rb_define_const(cSocket, "AF_APPLETALK", INT2FIX(AF_APPLETALK));
+ rb_define_const(cSocket, "PF_APPLETALK", INT2FIX(PF_APPLETALK));
+#endif
+
+ rb_define_const(cSocket, "MSG_OOB", INT2FIX(MSG_OOB));
+ rb_define_const(cSocket, "MSG_PEEK", INT2FIX(MSG_PEEK));
+ rb_define_const(cSocket, "MSG_DONTROUTE", INT2FIX(MSG_DONTROUTE));
+
+ rb_define_const(cSocket, "SOCK_STREAM", INT2FIX(SOCK_STREAM));
+ rb_define_const(cSocket, "SOCK_DGRAM", INT2FIX(SOCK_DGRAM));
+ rb_define_const(cSocket, "SOCK_RAW", INT2FIX(SOCK_RAW));
+#ifdef SOCK_RDM
+ rb_define_const(cSocket, "SOCK_RDM", INT2FIX(SOCK_RDM));
+#endif
+#ifdef SOCK_SEQPACKET
+ rb_define_const(cSocket, "SOCK_SEQPACKET", INT2FIX(SOCK_SEQPACKET));
+#endif
+#ifdef SOCK_PACKET
+ rb_define_const(cSocket, "SOCK_PACKET", INT2FIX(SOCK_PACKET));
+#endif
+
+ rb_define_const(cSocket, "SOL_SOCKET", INT2FIX(SOL_SOCKET));
+#ifdef SOL_IP
+ rb_define_const(cSocket, "SOL_IP", INT2FIX(SOL_IP));
+#endif
+#ifdef SOL_IPX
+ rb_define_const(cSocket, "SOL_IPX", INT2FIX(SOL_IPX));
+#endif
+#ifdef SOL_ATALK
+ rb_define_const(cSocket, "SOL_ATALK", INT2FIX(SOL_ATALK));
+#endif
+#ifdef SOL_TCP
+ rb_define_const(cSocket, "SOL_TCP", INT2FIX(SOL_TCP));
+#endif
+#ifdef SOL_UDP
+ rb_define_const(cSocket, "SOL_UDP", INT2FIX(SOL_UDP));
+#endif
+
+ rb_define_const(cSocket, "SO_DEBUG", INT2FIX(SO_DEBUG));
+ rb_define_const(cSocket, "SO_REUSEADDR", INT2FIX(SO_REUSEADDR));
+ rb_define_const(cSocket, "SO_KEEPALIVE", INT2FIX(SO_KEEPALIVE));
+ rb_define_const(cSocket, "SO_LINGER", INT2FIX(SO_LINGER));
}
diff --git a/ext/socket/socket.doc b/ext/socket/socket.doc
deleted file mode 100644
index aa5bfedbff..0000000000
--- a/ext/socket/socket.doc
+++ /dev/null
@@ -1,227 +0,0 @@
-.\" 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
index 98df4663b3..870e04b586 100644
--- a/ext/tkutil/MANIFEST
+++ b/ext/tkutil/MANIFEST
@@ -1,3 +1,3 @@
MANIFEST
-extconf.rb
tkutil.c
+depend
diff --git a/ext/tkutil/depend b/ext/tkutil/depend
new file mode 100644
index 0000000000..ead83eda57
--- /dev/null
+++ b/ext/tkutil/depend
@@ -0,0 +1 @@
+tkutil.o: tkutil.c ../../ruby.h ../../config.h ../../defines.h
diff --git a/ext/tkutil/extconf.rb b/ext/tkutil/extconf.rb
deleted file mode 100644
index b61a7ac01c..0000000000
--- a/ext/tkutil/extconf.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-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
index 2b74b254c2..51e3412ab5 100644
--- a/ext/tkutil/tkutil.c
+++ b/ext/tkutil/tkutil.c
@@ -47,7 +47,6 @@ 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 0691545c6a..447cba5b52 100644
--- a/file.c
+++ b/file.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:36 $
created at: Mon Nov 15 12:24:34 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -26,7 +26,7 @@
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#else
-struct timeval {
+stuct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
@@ -60,28 +60,37 @@ VALUE
file_open(fname, mode)
char *fname, *mode;
{
- VALUE port;
OpenFile *fptr;
-
- port = obj_alloc(cFile);
-
+ NEWOBJ(port, struct RFile);
+ OBJSETUP(port, cFile, T_FILE);
MakeOpenFile(port, fptr);
- fptr->mode = io_mode_flags(mode);
- fptr->f = fopen(fname, mode);
- if (fptr->f == NULL) {
- if (errno == EMFILE) {
- gc();
- fptr->f = fopen(fname, mode);
- }
- if (fptr->f == NULL) {
- rb_sys_fail(fname);
- }
- }
+ fptr->mode = io_mode_flags(mode);
+ fptr->f = rb_fopen(fname, mode);
fptr->path = strdup(fname);
- return port;
+ return (VALUE)port;
+}
+
+static VALUE
+file_s_open(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE fname, vmode;
+ char *mode;
+
+ rb_scan_args(argc, argv, "11", &fname, &mode);
+ Check_Type(fname, T_STRING);
+ if (!NIL_P(mode)) {
+ Check_Type(mode, T_STRING);
+ mode = RSTRING(mode)->ptr;
+ }
+ else {
+ mode = "r";
+ }
+ return file_open(RSTRING(fname)->ptr, mode);
}
static int
@@ -113,7 +122,7 @@ file_tell(obj)
GetOpenFile(obj, fptr);
pos = ftell(fptr->f);
- if (ferror(fptr->f) != 0) rb_sys_fail(Qnil);
+ if (ferror(fptr->f) != 0) rb_sys_fail(0);
return int2inum(pos);
}
@@ -128,7 +137,7 @@ file_seek(obj, offset, ptrname)
GetOpenFile(obj, fptr);
pos = fseek(fptr->f, NUM2INT(offset), NUM2INT(ptrname));
- if (pos != 0) rb_sys_fail(Qnil);
+ if (pos != 0) rb_sys_fail(0);
clearerr(fptr->f);
return obj;
@@ -143,7 +152,7 @@ file_set_pos(obj, offset)
GetOpenFile(obj, fptr);
pos = fseek(fptr->f, NUM2INT(offset), 0);
- if (pos != 0) rb_sys_fail(Qnil);
+ if (pos != 0) rb_sys_fail(0);
clearerr(fptr->f);
return obj;
@@ -156,7 +165,7 @@ file_rewind(obj)
OpenFile *fptr;
GetOpenFile(obj, fptr);
- if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(Qnil);
+ if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(0);
clearerr(fptr->f);
return obj;
@@ -191,14 +200,14 @@ file_isatty(obj)
}
#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/file.h>
+#include <sys/stat.h>
static VALUE
stat_new(st)
struct stat *st;
{
- if (st == Qnil) Bug("stat_new() called with nil");
+ if (!st) Bug("stat_new() called with bad value");
return struct_new(sStat,
INT2FIX((int)st->st_dev),
INT2FIX((int)st->st_ino),
@@ -224,26 +233,7 @@ stat_new(st)
#endif
time_new(st->st_atime, 0),
time_new(st->st_mtime, 0),
- time_new(st->st_ctime, 0),
- Qnil);
-}
-
-static struct stat laststat;
-
-int
-cache_stat(path, st)
- char *path;
- struct stat *st;
-{
- if (strcmp("&", path) == 0) {
- *st = laststat;
- return 0;
- }
- if (stat(path, st) == -1)
- return -1;
-
- laststat = *st;
- return 0;
+ time_new(st->st_ctime, 0));
}
static VALUE
@@ -254,7 +244,7 @@ file_s_stat(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) == -1) {
+ if (stat(fname->ptr, &st) == -1) {
rb_sys_fail(fname->ptr);
}
return stat_new(&st);
@@ -265,12 +255,13 @@ file_stat(obj)
VALUE obj;
{
OpenFile *fptr;
+ struct stat st;
GetOpenFile(obj, fptr);
- if (fstat(fileno(fptr->f), &laststat) == -1) {
+ if (fstat(fileno(fptr->f), &st) == -1) {
rb_sys_fail(fptr->path);
}
- return stat_new(&laststat);
+ return stat_new(&st);
}
static VALUE
@@ -278,6 +269,7 @@ file_s_lstat(obj, fname)
VALUE obj;
struct RString *fname;
{
+#if !defined(MSDOS)
struct stat st;
Check_Type(fname, T_STRING);
@@ -285,12 +277,16 @@ file_s_lstat(obj, fname)
rb_sys_fail(fname->ptr);
}
return stat_new(&st);
+#else
+ rb_notimplement();
+#endif
}
static VALUE
file_lstat(obj)
VALUE obj;
{
+#if !defined(MSDOS)
OpenFile *fptr;
struct stat st;
@@ -299,6 +295,9 @@ file_lstat(obj)
rb_sys_fail(fptr->path);
}
return stat_new(&st);
+#else
+ rb_notimplement();
+#endif
}
static int
@@ -339,7 +338,7 @@ eaccess(path, mode)
struct stat st;
static int euid = -1;
- if (cache_stat(path, &st) < 0) return (-1);
+ if (stat(path, &st) < 0) return (-1);
if (euid == -1)
euid = geteuid ();
@@ -378,7 +377,7 @@ test_d(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (S_ISDIR(st.st_mode)) return TRUE;
return FALSE;
}
@@ -396,7 +395,7 @@ test_p(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (S_ISFIFO(st.st_mode)) return TRUE;
#endif
@@ -426,7 +425,7 @@ test_l(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (lstat(fname->ptr, &st) < 0) return FALSE;
if (S_ISLNK(st.st_mode)) return TRUE;
#endif
@@ -456,7 +455,7 @@ test_S(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (S_ISSOCK(st.st_mode)) return TRUE;
#endif
@@ -478,7 +477,7 @@ test_b(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (S_ISBLK(st.st_mode)) return TRUE;
#endif
@@ -497,7 +496,7 @@ test_c(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (S_ISBLK(st.st_mode)) return TRUE;
return FALSE;
@@ -511,7 +510,7 @@ test_e(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
return TRUE;
}
@@ -583,7 +582,7 @@ test_f(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (S_ISREG(st.st_mode)) return TRUE;
return FALSE;
}
@@ -596,7 +595,7 @@ test_z(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (st.st_size == 0) return TRUE;
return FALSE;
}
@@ -609,7 +608,7 @@ test_s(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (st.st_size == 0) return FALSE;
return int2inum(st.st_size);
}
@@ -622,7 +621,7 @@ test_owned(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (st.st_uid == geteuid()) return TRUE;
return FALSE;
}
@@ -635,7 +634,7 @@ test_rowned(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (st.st_uid == getuid()) return TRUE;
return FALSE;
}
@@ -649,7 +648,7 @@ test_grpowned(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) return FALSE;
+ if (stat(fname->ptr, &st) < 0) return FALSE;
if (st.st_gid == getegid()) return TRUE;
#else
Check_Type(fname, T_STRING);
@@ -665,7 +664,7 @@ check3rdbyte(file, mode)
{
struct stat st;
- if (cache_stat(file, &st) < 0) return FALSE;
+ if (stat(file, &st) < 0) return FALSE;
if (st.st_mode & mode) return TRUE;
return FALSE;
}
@@ -719,7 +718,7 @@ file_s_type(obj, fname)
char *t;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr);
+ if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr);
if (S_ISREG(st.st_mode)) {
t = "file";
@@ -763,7 +762,7 @@ file_s_atime(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr);
+ if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr);
return time_new(st.st_atime, 0);
}
@@ -789,7 +788,7 @@ file_s_mtime(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr);
+ if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr);
return time_new(st.st_mtime, 0);
}
@@ -815,7 +814,7 @@ file_s_ctime(obj, fname)
struct stat st;
Check_Type(fname, T_STRING);
- if (cache_stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr);
+ if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr);
return time_new(st.st_ctime, 0);
}
@@ -868,8 +867,13 @@ file_chmod(obj, vmode)
mode = NUM2INT(vmode);
GetOpenFile(obj, fptr);
+#if defined(DJGPP) || defined(__CYGWIN32__)
+ if (chmod(fptr->path, mode) == -1)
+ rb_sys_fail(fptr->path);
+#else
if (fchmod(fileno(fptr->f), mode) == -1)
rb_sys_fail(fptr->path);
+#endif
return INT2FIX(0);
}
@@ -897,13 +901,13 @@ file_s_chown(argc, argv)
int n;
rb_scan_args(argc, argv, "2*", &o, &g, &rest);
- if (o == Qnil) {
+ if (NIL_P(o)) {
arg.owner = -1;
}
else {
arg.owner = NUM2INT(o);
}
- if (g == Qnil) {
+ if (NIL_P(g)) {
arg.group = -1;
}
else {
@@ -921,13 +925,18 @@ file_chown(obj, owner, group)
OpenFile *fptr;
GetOpenFile(obj, fptr);
+#if defined(DJGPP) || defined(__CYGWIN32__)
+ if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1)
+ rb_sys_fail(fptr->path);
+#else
if (fchown(fileno(fptr->f), NUM2INT(owner), NUM2INT(group)) == -1)
rb_sys_fail(fptr->path);
+#endif
return INT2FIX(0);
}
-struct timeval *time_timeval();
+struct timeval time_timeval();
#ifdef HAVE_UTIMES
@@ -951,8 +960,8 @@ file_s_utime(argc, argv)
rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest);
- tvp[0] = *time_timeval(atime);
- tvp[1] = *time_timeval(mtime);
+ tvp[0] = time_timeval(atime);
+ tvp[1] = time_timeval(mtime);
n = apply2files(utime_internal, rest, tvp);
return INT2FIX(n);
@@ -987,15 +996,15 @@ file_s_utime(argc, argv)
{
VALUE atime, mtime, rest;
int n;
- struct timeval *tv;
+ struct timeval tv;
struct utimbuf utbuf;
rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest);
tv = time_timeval(atime);
- utbuf.actime = tv->tv_sec;
+ utbuf.actime = tv.tv_sec;
tv = time_timeval(mtime);
- utbuf.modtime = tv->tv_sec;
+ utbuf.modtime = tv.tv_sec;
n = apply2files(utime_internal, rest, &utbuf);
return INT2FIX(n);
@@ -1021,12 +1030,16 @@ file_s_symlink(obj, from, to)
VALUE obj;
struct RString *from, *to;
{
+#if !defined(MSDOS)
Check_Type(from, T_STRING);
Check_Type(to, T_STRING);
if (symlink(from->ptr, to->ptr) < 0)
rb_sys_fail(from->ptr);
return TRUE;
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -1034,6 +1047,7 @@ file_s_readlink(obj, path)
VALUE obj;
struct RString *path;
{
+#if !defined(MSDOS)
char buf[MAXPATHLEN];
int cc;
@@ -1043,6 +1057,9 @@ file_s_readlink(obj, path)
rb_sys_fail(path->ptr);
return str_new(buf, cc);
+#else
+ rb_notimplement();
+#endif
}
static void
@@ -1060,7 +1077,7 @@ file_s_unlink(obj, args)
{
int n;
- n = apply2files(unlink_internal, args, Qnil);
+ n = apply2files(unlink_internal, args, 0);
return INT2FIX(n);
}
@@ -1093,82 +1110,11 @@ file_s_umask(argc, argv)
omask = umask(NUM2INT(argv[1]));
}
else {
- Fail("wrong # of argument");
+ ArgError("wrong # of argument");
}
return INT2FIX(omask);
}
-#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE)
-static VALUE
-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
-file_truncate(obj, len)
- VALUE obj, len;
-{
- OpenFile *fptr;
-
- GetOpenFile(obj, fptr);
-
- 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
-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;
@@ -1218,7 +1164,7 @@ file_s_expand_path(obj, fname)
#ifdef HAVE_GETCWD
getcwd(buf, MAXPATHLEN);
#else
- getwd(buf)l
+ getwd(buf);
#endif
p = &buf[strlen(buf)];
}
@@ -1292,17 +1238,17 @@ file_s_basename(argc, argv)
rb_scan_args(argc, argv, "11", &fname, &ext);
Check_Type(fname, T_STRING);
- if (ext) Check_Type(ext, T_STRING);
+ if (!NIL_P(ext)) Check_Type(ext, T_STRING);
p = strrchr(fname->ptr, '/');
- if (p == Qnil) {
- if (ext) {
+ if (!p) {
+ if (!NIL_P(ext)) {
f = rmext(fname->ptr, ext->ptr);
if (f) return str_new(fname->ptr, f);
}
return (VALUE)fname;
}
p++; /* skip last `/' */
- if (ext) {
+ if (!NIL_P(ext)) {
f = rmext(p, ext->ptr);
if (f) return str_new(p, f);
}
@@ -1315,12 +1261,119 @@ file_s_dirname(obj, fname)
struct RString *fname;
{
char *p;
+
Check_Type(fname, T_STRING);
p = strrchr(fname->ptr, '/');
- if (p == Qnil) return (VALUE)fname;
+ if (!p) {
+ return str_new(0,0);
+ }
return str_new(fname->ptr, p - fname->ptr);
}
+static VALUE separator;
+
+static VALUE
+file_s_split(obj, path)
+ VALUE obj, path;
+{
+ return assoc_new(file_s_dirname(Qnil, path), file_s_basename(1,&path));
+}
+
+static VALUE
+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);
+ }
+# else
+ rb_notimplement();
+# endif
+#endif
+ return TRUE;
+}
+
+static VALUE
+file_truncate(obj, len)
+ VALUE obj, len;
+{
+ OpenFile *fptr;
+
+ GetOpenFile(obj, fptr);
+
+ 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);
+# else
+ rb_notimplement();
+# endif
+#endif
+ return TRUE;
+}
+
+static VALUE
+file_fcntl(obj, req, arg)
+ VALUE obj, req;
+ struct RString *arg;
+{
+#ifdef HAVE_FCNTL
+ io_ctl(obj, req, arg, 0);
+#else
+ rb_notimplement();
+#endif
+ return obj;
+}
+
+static VALUE
+file_flock(obj, operation)
+ VALUE obj;
+ VALUE operation;
+{
+ OpenFile *fptr;
+
+ GetOpenFile(obj, fptr);
+
+ if (flock(fileno(fptr->f), NUM2INT(operation)) < 0) {
+#ifdef EWOULDBLOCK
+ if (errno = EWOULDBLOCK) {
+ return FALSE;
+ }
+#endif
+ rb_sys_fail(fptr->path);
+ }
+ return obj;
+}
+
static void
test_check(n, argc, argv)
int n, argc;
@@ -1329,7 +1382,7 @@ test_check(n, argc, argv)
int i;
n+=1;
- if (n < argc) Fail("Wrong # of arguments(%d for %d)", argc, n);
+ if (n < argc) ArgError("Wrong # of arguments(%d for %d)", argc, n);
for (i=1; i<n; i++) {
Check_Type(argv[i], T_STRING);
}
@@ -1344,7 +1397,7 @@ f_test(argc, argv)
{
int cmd;
- if (argc == 0) Fail("Wrong # of arguments");
+ if (argc == 0) ArgError("Wrong # of arguments");
Need_Fixnum(argv[0]);
cmd = FIX2INT(argv[0]);
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
@@ -1423,7 +1476,7 @@ f_test(argc, argv)
struct stat st;
CHECK(1);
- if (cache_stat(RSTRING(argv[1])->ptr, &st) == -1) {
+ if (stat(RSTRING(argv[1])->ptr, &st) == -1) {
rb_sys_fail(RSTRING(argv[1])->ptr);
}
@@ -1474,7 +1527,8 @@ Init_File()
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, "exist?", test_e, 1);
+ rb_define_module_function(mFileTest, "exists?", test_e, 1); /* temporary */
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);
@@ -1501,9 +1555,11 @@ Init_File()
cFile = rb_define_class("File", cIO);
rb_extend_object(cFile, CLASS_OF(mFileTest));
+ rb_define_singleton_method(cFile, "open", file_s_open, -1);
+
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, "ftype", file_s_type, 1);
rb_define_singleton_method(cFile, "atime", file_s_atime, 1);
rb_define_singleton_method(cFile, "mtime", file_s_mtime, 1);
@@ -1521,13 +1577,15 @@ Init_File()
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);
+ separator = INT2FIX('/');
+ rb_define_const(cFile, "Separator", separator);
+ rb_define_singleton_method(cFile, "split", file_s_split, 1);
+
rb_define_method(cFile, "stat", file_stat, 0);
rb_define_method(cFile, "lstat", file_lstat, 0);
@@ -1537,9 +1595,7 @@ Init_File()
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);
@@ -1553,9 +1609,26 @@ Init_File()
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, "flock", file_flock, 1);
+
+# ifndef LOCK_SH
+# define LOCK_SH 1
+# endif
+# ifndef LOCK_EX
+# define LOCK_EX 2
+# endif
+# ifndef LOCK_NB
+# define LOCK_NB 4
+# endif
+# ifndef LOCK_UN
+# define LOCK_UN 8
+# endif
+
+ rb_define_const(cFile, "LOCK_SH", INT2FIX(LOCK_SH));
+ rb_define_const(cFile, "LOCK_EX", INT2FIX(LOCK_EX));
+ rb_define_const(cFile, "LOCK_UN", INT2FIX(LOCK_UN));
+ rb_define_const(cFile, "LOCK_NB", INT2FIX(LOCK_NB));
rb_define_method(cFile, "path", file_path, 0);
@@ -1564,5 +1637,5 @@ Init_File()
sStat = struct_define("Stat", "dev", "ino", "mode",
"nlink", "uid", "gid", "rdev",
"size", "blksize", "blocks",
- "atime", "mtime", "ctime", Qnil);
+ "atime", "mtime", "ctime", 0);
}
diff --git a/gc.c b/gc.c
index e3c809cded..c1817b7cd0 100644
--- a/gc.c
+++ b/gc.c
@@ -6,18 +6,23 @@
$Date: 1995/01/12 08:54:47 $
created at: Tue Oct 5 09:44:46 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
-#include "env.h"
+#include "sig.h"
#include "st.h"
#include "node.h"
+#include "env.h"
#include "re.h"
#include <stdio.h>
#include <setjmp.h>
+#ifdef _AIX
+#pragma alloca
+#endif
+
void *malloc();
void *calloc();
void *realloc();
@@ -36,10 +41,10 @@ xmalloc(size)
if (size == 0) size = 1;
mem = malloc(size);
- if (mem == Qnil) {
+ if (!mem) {
gc();
mem = malloc(size);
- if (mem == Qnil)
+ if (!mem)
Fatal("failed to allocate memory");
}
@@ -65,12 +70,12 @@ xrealloc(ptr, size)
{
void *mem;
- if (ptr == Qnil) return xmalloc(size);
+ if (!ptr) return xmalloc(size);
mem = realloc(ptr, size);
- if (mem == Qnil) {
+ if (!mem) {
gc();
mem = realloc(ptr, size);
- if (mem == Qnil)
+ if (!mem)
Fatal("failed to allocate memory(realloc)");
}
@@ -107,12 +112,6 @@ Paradigm Associates Inc Phone: 617-492-6079
Cambridge, MA 02138
*/
-#ifdef sparc
-#define FLUSH_REGISTER_WINDOWS asm("ta 3")
-#else
-#define FLUSH_REGISTER_WINDOWS /* empty */
-#endif
-
static int dont_gc;
VALUE
@@ -136,10 +135,9 @@ gc_s_disable()
VALUE mGC;
static struct gc_list {
- int n;
VALUE *varptr;
struct gc_list *next;
-} *Global_List = Qnil;
+} *Global_List = 0;
void
rb_global_variable(var)
@@ -150,7 +148,6 @@ rb_global_variable(var)
tmp = ALLOC(struct gc_list);
tmp->next = Global_List;
tmp->varptr = var;
- tmp->n = 1;
Global_List = tmp;
}
@@ -171,6 +168,7 @@ typedef struct RVALUE {
struct RData data;
struct RStruct rstruct;
struct RBignum bignum;
+ struct RFile file;
struct RNode node;
struct RMatch match;
struct RVarmap varmap;
@@ -236,15 +234,15 @@ newobj()
}
VALUE
-data_new(datap, dmark, dfree)
+data_object_alloc(class, datap, dmark, dfree)
+ VALUE class;
void *datap;
void (*dfree)();
void (*dmark)();
{
- extern VALUE cData;
struct RData *data = (struct RData*)newobj();
- OBJSETUP(data, cData, T_DATA);
+ OBJSETUP(data, class, T_DATA);
data->data = datap;
data->dfree = dfree;
data->dmark = dmark;
@@ -253,9 +251,9 @@ data_new(datap, dmark, dfree)
}
extern st_table *rb_class_tbl;
-static VALUE *stack_start_ptr;
+VALUE *gc_stack_start;
-static long
+static int
looks_pointerp(p)
register RVALUE *p;
{
@@ -288,8 +286,8 @@ mark_locations_array(x, n)
}
}
-static void
-mark_locations(start, end)
+void
+gc_mark_locations(start, end)
VALUE *start, *end;
{
VALUE *tmp;
@@ -351,8 +349,8 @@ gc_mark(obj)
register RVALUE *obj;
{
Top:
- if (obj == Qnil) return; /* nil not marked */
if (FIXNUM_P(obj)) return; /* fixnum not marked */
+ if (rb_special_const_p(obj)) return; /* special const not marked */
if (obj->as.basic.flags == 0) return; /* free cell */
if (obj->as.basic.flags & FL_MARK) return; /* marked */
@@ -408,7 +406,10 @@ gc_mark(obj)
break;
case T_STRING:
- if (obj->as.string.orig) gc_mark(obj->as.string.orig);
+ if (obj->as.string.orig) {
+ obj = (RVALUE*)obj->as.string.orig;
+ goto Top;
+ }
break;
case T_DATA:
@@ -419,6 +420,7 @@ gc_mark(obj)
if (obj->as.object.iv_tbl) mark_tbl(obj->as.object.iv_tbl);
break;
+ case T_FILE:
case T_MATCH:
case T_REGEXP:
case T_FLOAT:
@@ -426,7 +428,9 @@ gc_mark(obj)
break;
case T_VARMAP:
- gc_mark(obj->as.varmap.next);
+ gc_mark(obj->as.varmap.val);
+ obj = (RVALUE*)obj->as.varmap.next;
+ goto Top;
break;
case T_SCOPE:
@@ -435,7 +439,7 @@ gc_mark(obj)
VALUE *tbl = obj->as.scope.local_vars;
while (n--) {
- gc_mark(*tbl);
+ gc_mark_maybe(*tbl);
tbl++;
}
}
@@ -512,12 +516,12 @@ obj_free(obj)
break;
case T_MODULE:
case T_CLASS:
- rb_clear_cache(obj);
+ rb_clear_cache();
st_free_table(obj->as.class.m_tbl);
if (obj->as.object.iv_tbl) st_free_table(obj->as.object.iv_tbl);
break;
case T_STRING:
- if (obj->as.string.orig == Qnil) free(obj->as.string.ptr);
+ if (!obj->as.string.orig) free(obj->as.string.ptr);
break;
case T_ARRAY:
free(obj->as.array.ptr);
@@ -538,17 +542,26 @@ obj_free(obj)
free(obj->as.match.regs);
if (obj->as.match.ptr) free(obj->as.match.ptr);
break;
+ case T_FILE:
+ io_fptr_finalize(obj->as.file.fptr);
+ free(obj->as.file.fptr);
+ break;
case T_ICLASS:
/* iClass shares table with the module */
+ break;
+
case T_FLOAT:
case T_VARMAP:
+ case T_TRUE:
+ case T_FALSE:
break;
+
case T_BIGNUM:
- free(obj->as.bignum.digits);
+ if (obj->as.bignum.digits) free(obj->as.bignum.digits);
break;
case T_NODE:
- if (nd_type(obj) == NODE_SCOPE && obj->as.node.nd_tbl) {
- free(obj->as.node.nd_tbl);
+ if (nd_type(obj) == NODE_SCOPE && obj->as.node.u1.tbl) {
+ free(obj->as.node.u1.tbl);
}
return; /* no need to free iv_tbl */
@@ -576,7 +589,7 @@ gc_mark_frame(frame)
VALUE *tbl = frame->argv;
while (n--) {
- gc_mark(*tbl);
+ gc_mark_maybe(*tbl);
tbl++;
}
}
@@ -601,18 +614,23 @@ gc()
gc_mark_frame(frame);
}
gc_mark(the_scope);
+ gc_mark(the_dyna_vars);
FLUSH_REGISTER_WINDOWS;
/* This assumes that all registers are saved into the jmp_buf */
setjmp(save_regs_gc_mark);
- mark_locations((VALUE*)save_regs_gc_mark,
- (VALUE*)(((char*)save_regs_gc_mark)+sizeof(save_regs_gc_mark)));
- mark_locations(stack_start_ptr, (VALUE*) &stack_end);
-#if defined(THINK_C)
- mark_locations((VALUE*)((char*)stack_start_ptr + 2),
+ gc_mark_locations((VALUE*)save_regs_gc_mark,
+ (VALUE*)(((char*)save_regs_gc_mark)+sizeof(save_regs_gc_mark)));
+ gc_mark_locations(gc_stack_start, (VALUE*) &stack_end);
+#ifdef THINK_C
+ gc_mark_locations((VALUE*)((char*)gc_stack_start + 2),
(VALUE*)((char*)&stack_end + 2));
#endif
+#ifdef THREAD
+ gc_mark_threads();
+#endif
+
/* mark protected global variables */
for (list = Global_List; list; list = list->next) {
gc_mark(*list->varptr);
@@ -631,7 +649,7 @@ init_stack()
{
VALUE start;
- stack_start_ptr = &start;
+ gc_stack_start = &start;
}
void
@@ -641,12 +659,87 @@ init_heap()
add_heap();
}
+static VALUE
+os_live_obj(obj)
+ VALUE obj;
+{
+ int i;
+ int n = 0;
+
+ for (i = 0; i < heaps_used; i++) {
+ RVALUE *p, *pend;
+
+ p = heaps[i]; pend = p + HEAP_SLOTS;
+ for (;p < pend; p++) {
+ if (p->as.basic.flags) {
+ switch (TYPE(p)) {
+ case T_ICLASS:
+ case T_VARMAP:
+ case T_SCOPE:
+ case T_NODE:
+ continue;
+ case T_CLASS:
+ if (FL_TEST(p, FL_SINGLETON)) continue;
+ default:
+ rb_yield(p);
+ n++;
+ }
+ }
+ }
+ }
+
+ return INT2FIX(n);
+}
+
+static VALUE
+os_obj_of(obj, of)
+ VALUE obj, of;
+{
+ int i;
+ int n = 0;
+
+ for (i = 0; i < heaps_used; i++) {
+ RVALUE *p, *pend;
+
+ p = heaps[i]; pend = p + HEAP_SLOTS;
+ for (;p < pend; p++) {
+ if (p->as.basic.flags) {
+ switch (TYPE(p)) {
+ case T_ICLASS:
+ case T_VARMAP:
+ case T_SCOPE:
+ case T_NODE:
+ continue;
+ case T_CLASS:
+ if (FL_TEST(p, FL_SINGLETON)) continue;
+ default:
+ if (obj_is_kind_of(p, of)) {
+ rb_yield(p);
+ n++;
+ }
+ }
+ }
+ }
+ }
+
+ return INT2FIX(n);
+}
+
+extern VALUE cModule;
+
void
Init_GC()
{
+ VALUE mObSpace;
+
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);
+
+ mObSpace = rb_define_module("ObjectSpace");
+ rb_define_module_function(mObSpace, "each_live_object", os_live_obj, 0);
+ rb_define_module_function(mObSpace, "each_object_of", os_obj_of, 1);
+ rb_define_module_function(mObSpace, "garbage_collect", gc, 0);
}
diff --git a/glob.c b/glob.c
index b0c750f243..7599c1ca72 100644
--- a/glob.c
+++ b/glob.c
@@ -48,7 +48,7 @@
# endif /* !USG */
#endif /* !HAVE_DIRENT_H */
-#if defined (_POSIX_SOURCE)
+#if defined (_POSIX_SOURCE) || defined(DJGPP)
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
# define REAL_DIR_ENTRY(dp) 1
@@ -70,11 +70,15 @@
# define bcopy(s, d, n) (memcpy ((d), (s), (n)))
+#ifdef _AIX
+#pragma alloca
+#else
#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
#include <alloca.h>
#else
char *alloca ();
#endif
+#endif
#include "fnmatch.h"
@@ -376,7 +380,9 @@ char **
glob_filename (pathname)
char *pathname;
{
+#ifndef strrchr
char *strrchr();
+#endif
char **result;
unsigned int result_size;
diff --git a/hash.c b/hash.c
index da4671409f..d2ee598869 100644
--- a/hash.c
+++ b/hash.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:26 $
created at: Mon Nov 22 18:51:18 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -27,38 +27,85 @@ static VALUE envtbl;
static ID hash;
VALUE f_getenv(), f_setenv();
-static VALUE
+static int
rb_cmp(a, b)
VALUE a, b;
{
- return rb_equal(a, b)?0:1;
+ if (FIXNUM_P(a)) {
+ if (FIXNUM_P(b)) return a != b;
+ }
+
+ if (TYPE(a) == T_STRING) {
+ if (TYPE(b) == T_STRING) return str_cmp(a, b);
+ }
+
+ return !rb_eql(a, b);
}
-static VALUE
+static int
rb_hash(a, mod)
VALUE a;
int mod;
{
- return rb_funcall(a, hash, 0) % mod;
+ unsigned int hval;
+
+ switch (TYPE(a)) {
+ case T_FIXNUM:
+ hval = a;
+ break;
+
+ case T_STRING:
+ hval = str_hash(a);
+ break;
+
+ default:
+ hval = rb_funcall(a, hash, 0);
+ hval = FIX2INT(hval);
+ }
+ return hval % mod;
}
-#define ASSOC_KEY(a) RASSOC(a)->car
-#define ASSOC_VAL(a) RASSOC(a)->cdr
+static struct st_hash_type objhash = {
+ rb_cmp,
+ rb_hash,
+};
static VALUE
-hash_s_new(class)
+hash_s_new(argc, argv, class)
+ int argc;
+ VALUE *argv;
VALUE class;
{
+ VALUE sz;
+ int size;
+
NEWOBJ(hash, struct RHash);
OBJSETUP(hash, class, T_HASH);
- hash->tbl = st_init_table(rb_cmp, rb_hash);
+ rb_scan_args(argc, argv, "01", &sz);
+ if (NIL_P(sz)) size = 0;
+ else size = NUM2INT(sz);
+
+ hash->tbl = st_init_table_with_size(&objhash, size);
return (VALUE)hash;
}
static VALUE hash_clone();
+VALUE
+hash_new2(class)
+ VALUE class;
+{
+ return hash_s_new(0, 0, class);
+}
+
+VALUE
+hash_new()
+{
+ return hash_new2(cHash);
+}
+
static VALUE
hash_s_create(argc, argv, class)
int argc;
@@ -80,9 +127,9 @@ hash_s_create(argc, argv, class)
}
if (argc % 2 != 0) {
- Fail("odd number args for Hash");
+ ArgError("odd number args for Hash");
}
- hash = (struct RHash*)hash_s_new(class);
+ hash = (struct RHash*)hash_new2(class);
for (i=0; i<argc; i+=2) {
st_insert(hash->tbl, argv[i], argv[i+1]);
@@ -91,12 +138,6 @@ hash_s_create(argc, argv, class)
return (VALUE)hash;
}
-VALUE
-hash_new()
-{
- return hash_s_new(cHash);
-}
-
static VALUE
hash_clone(hash)
struct RHash *hash;
@@ -109,7 +150,7 @@ hash_clone(hash)
return (VALUE)hash2;
}
-static VALUE
+VALUE
hash_aref(hash, key)
struct RHash *hash;
VALUE key;
@@ -128,29 +169,21 @@ hash_indexes(hash, args)
struct RArray *args;
{
VALUE *p, *pend;
- struct RArray *new_hash;
+ struct RArray *indexes;
int i = 0;
- if (!args || args->len == 0) {
- Fail("wrong # of argment");
- }
- else if (args->len == 1) {
- if (TYPE(args->ptr[0])) {
- args = (struct RArray*)rb_to_a(args->ptr[0]);
- }
- else {
- args = (struct RArray*)args->ptr[0];
- }
+ if (!args || NIL_P(args)) {
+ return ary_new2(0);
}
- new_hash = (struct RArray*)ary_new2(args->len);
+ indexes = (struct RArray*)ary_new2(args->len);
p = args->ptr; pend = p + args->len;
while (p < pend) {
- new_hash->ptr[i++] = hash_aref(hash, *p++);
+ indexes->ptr[i++] = hash_aref(hash, *p++);
}
- new_hash->len = i;
- return (VALUE)new_hash;
+ indexes->len = i;
+ return (VALUE)indexes;
}
static VALUE
@@ -162,6 +195,7 @@ hash_delete(hash, key)
if (st_delete(hash->tbl, &key, &val))
return val;
+ if (iterator_p()) rb_yield(Qnil);
return Qnil;
}
@@ -209,7 +243,7 @@ static VALUE
hash_delete_if(hash)
struct RHash *hash;
{
- st_foreach(hash->tbl, delete_if_i, Qnil);
+ st_foreach(hash->tbl, delete_if_i, 0);
return (VALUE)hash;
}
@@ -235,7 +269,7 @@ hash_aset(hash, key, val)
struct RHash *hash;
VALUE key, val;
{
- if (val == Qnil) {
+ if (NIL_P(val)) {
hash_delete(hash, key);
return Qnil;
}
@@ -253,6 +287,15 @@ hash_length(hash)
return INT2FIX(hash->tbl->num_entries);
}
+VALUE
+hash_empty_p(hash)
+ struct RHash *hash;
+{
+ if (hash->tbl->num_entries == 0)
+ return TRUE;
+ return FALSE;
+}
+
static int
each_value_i(key, value)
VALUE key, value;
@@ -327,15 +370,14 @@ inspect_i(key, value, str)
struct RString *str;
{
VALUE str2;
- ID inspect = rb_intern("inspect");
if (str->len > 1) {
str_cat(str, ", ", 2);
}
- str2 = rb_funcall(key, inspect, 0, 0);
+ str2 = rb_inspect(key);
str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
str_cat(str, "=>", 2);
- str2 = rb_funcall(value, inspect, 0, 0);
+ str2 = rb_inspect(value);
str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
return ST_CONTINUE;
@@ -554,7 +596,7 @@ f_getenv(obj, name)
Check_Type(name, T_STRING);
if (strlen(name->ptr) != name->len)
- Fail("Bad environment name");
+ ArgError("Bad environment name");
env = getenv(name->ptr);
if (env) {
@@ -569,7 +611,7 @@ f_setenv(obj, name, value)
struct RString *name, *value;
{
Check_Type(name, T_STRING);
- if (value == Qnil) {
+ if (NIL_P(value)) {
env_delete(obj, name);
return Qnil;
}
@@ -577,9 +619,9 @@ f_setenv(obj, name, value)
Check_Type(value, T_STRING);
if (strlen(name->ptr) != name->len)
- Fail("Bad environment name");
+ ArgError("Bad environment name");
if (strlen(value->ptr) != value->len)
- Fail("Bad environment value");
+ ArgError("Bad environment value");
setenv(name->ptr, value->ptr, 1);
return TRUE;
@@ -588,7 +630,7 @@ f_setenv(obj, name, value)
static VALUE
env_to_s()
{
- return str_new2("$ENV");
+ return str_new2("ENV");
}
void
@@ -603,7 +645,7 @@ Init_Hash()
rb_include_module(cHash, mEnumerable);
- rb_define_singleton_method(cHash, "new", hash_s_new, 0);
+ rb_define_singleton_method(cHash, "new", hash_s_new, -1);
rb_define_singleton_method(cHash, "[]", hash_s_create, -1);
rb_define_method(cHash,"clone", hash_clone, 0);
@@ -619,6 +661,8 @@ Init_Hash()
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,"empty?", hash_empty_p, 0);
+
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);
@@ -632,8 +676,11 @@ Init_Hash()
rb_define_method(cHash,"delete_if", hash_delete_if, 0);
rb_define_method(cHash,"clear", hash_clear, 0);
+ rb_define_method(cHash,"include?", hash_has_key, 1);
rb_define_method(cHash,"has_key?", hash_has_key, 1);
rb_define_method(cHash,"has_value?", hash_has_value, 1);
+ rb_define_method(cHash,"key?", hash_has_key, 1);
+ rb_define_method(cHash,"value?", hash_has_value, 1);
envtbl = obj_alloc(cObject);
rb_extend_object(envtbl, mEnumerable);
@@ -645,5 +692,5 @@ Init_Hash()
rb_define_singleton_method(envtbl,"to_s", env_to_s, 0);
rb_define_readonly_variable("$ENV", &envtbl);
- rb_define_const(cKernel, "ENV", envtbl);
+ rb_define_global_const("ENV", envtbl);
}
diff --git a/inits.c b/inits.c
index 673b6eed4b..a6eb7f5150 100644
--- a/inits.c
+++ b/inits.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:38 $
created at: Tue Dec 28 16:01:58 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -18,16 +18,20 @@ rb_call_inits()
Init_sym();
Init_var_tables();
Init_Object();
+#ifdef THREAD
+ Init_Thread();
+#endif
Init_GC();
Init_eval();
Init_Comparable();
Init_Enumerable();
+ Init_String();
+ Init_Exception();
Init_Numeric();
Init_Bignum();
Init_Array();
Init_Hash();
Init_Struct();
- Init_String();
Init_Regexp();
Init_pack();
Init_Range();
diff --git a/io.c b/io.c
index 47bd4b0fb0..43e2458668 100644
--- a/io.c
+++ b/io.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:39 $
created at: Fri Oct 15 18:08:59 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -16,8 +16,9 @@
#include <errno.h>
#include <sys/types.h>
-#include <sys/stat.h>
+#ifndef DJGPP
#include <sys/ioctl.h>
+#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
@@ -31,26 +32,94 @@ struct timeval {
#include <vfork.h>
#endif
+#include <sys/stat.h>
+
+#ifdef DJGPP
+#include <fcntl.h>
+#endif
+
VALUE rb_ad_string();
VALUE cIO;
extern VALUE cFile;
+VALUE eEOFError;
+VALUE eIOError;
VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout;
VALUE FS, OFS;
VALUE RS, ORS;
+VALUE RS_default;
static VALUE argf;
ID id_write, id_fd, id_print_on;
+VALUE lastline_get();
+void lastline_set();
+
extern char *inplace;
+struct timeval time_timeval();
+
+#ifdef _STDIO_USES_IOSTREAM /* GNU libc */
+# 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
+# ifdef FILE_COUNT
+# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
+# else
+/* requires systems own version of the ReadDataPending() */
+extern int ReadDataPending();
+# define READ_DATA_PENDING(fp) ReadDataPending(fp)
+# endif
+#endif
+
+#ifndef THREAD
+# define READ_CHECK(fp) 0
+#else
+# define READ_CHECK(fp) do {\
+ if (!READ_DATA_PENDING(fp)) thread_wait_fd(fileno(fp));\
+} while(0)
+#endif
+
+void
+eof_error()
+{
+ Raise(eEOFError, "End of file reached");
+}
+
+void
+io_writable(fptr)
+ OpenFile *fptr;
+{
+ if (!(fptr->mode & FMODE_WRITABLE)) {
+ Raise(eIOError, "not opened for writing");
+ }
+}
+
+void
+io_readable(fptr)
+ OpenFile *fptr;
+{
+ if (!(fptr->mode & FMODE_READABLE)) {
+ Raise(eIOError, "not opened for reading");
+ }
+}
+
+static void
+closed()
+{
+ Raise(eIOError, "closed stream");
+}
+
/* writing functions */
VALUE
-io_write(obj, str)
- VALUE obj;
+io_write(io, str)
+ VALUE io;
struct RString *str;
{
OpenFile *fptr;
@@ -58,19 +127,17 @@ io_write(obj, str)
VALUE out;
int n;
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_WRITABLE)) {
- Fail("not opened for writing");
- }
+ GetOpenFile(io, fptr);
+ io_writable(fptr);
f = (fptr->f2) ? fptr->f2 : fptr->f;
- if (f == NULL) Fail("closed stream");
+ if (f == NULL) closed();
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);
+ n = fwrite(str->ptr, 1, str->len, f);
if (n == 0 || ferror(f)) {
rb_sys_fail(fptr->path);
}
@@ -82,44 +149,43 @@ io_write(obj, str)
}
static VALUE
-io_puts(obj, str)
- VALUE obj, str;
+io_puts(io, str)
+ VALUE io, str;
{
- io_write(obj, str);
- return obj;
+ io_write(io, str);
+ return io;
}
static VALUE
-io_flush(obj)
- VALUE obj;
+io_flush(io)
+ VALUE io;
{
OpenFile *fptr;
FILE *f;
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_WRITABLE)) {
- Fail("not opend for writing");
- }
+ GetOpenFile(io, fptr);
+ io_writable(fptr);
f = (fptr->f2) ? fptr->f2 : fptr->f;
- if (f == NULL) Fail("closed stream");
+ if (f == NULL) closed();
- if (fflush(f) == EOF) rb_sys_fail(Qnil);
+ if (fflush(f) == EOF) rb_sys_fail(0);
- return obj;
+ return io;
}
static VALUE
-io_eof(obj)
- VALUE obj;
+io_eof(io)
+ VALUE io;
{
OpenFile *fptr;
int ch;
- GetOpenFile(obj, fptr);
-#ifdef STDSTDIO /* (the code works without this) */
- if (fptr->f->_cnt > 0) /* cheat a little, since */
- return FALSE; /* this is the most usual case */
-#endif
+ GetOpenFile(io, fptr);
+ io_readable(fptr);
+ if (fptr->f == NULL) closed();
+
+ if (READ_DATA_PENDING(fptr->f)) return FALSE;
+ if (feof(fptr->f)) return TRUE;
TRAP_BEG;
ch = getc(fptr->f);
@@ -129,31 +195,27 @@ io_eof(obj)
(void)ungetc(ch, fptr->f);
return FALSE;
}
-#ifdef STDSTDIO
- if (fptr->f->_cnt < -1)
- fptr->f->_cnt = -1;
-#endif
return TRUE;
}
static VALUE
-io_sync(obj)
- VALUE obj;
+io_sync(io)
+ VALUE io;
{
OpenFile *fptr;
- GetOpenFile(obj, fptr);
+ GetOpenFile(io, fptr);
return (fptr->mode & FMODE_SYNC) ? TRUE : FALSE;
}
static VALUE
-io_set_sync(obj, mode)
- VALUE obj, mode;
+io_set_sync(io, mode)
+ VALUE io, mode;
{
OpenFile *fptr;
- GetOpenFile(obj, fptr);
- if (mode) {
+ GetOpenFile(io, fptr);
+ if (RTEST(mode)) {
fptr->mode |= FMODE_SYNC;
}
else {
@@ -163,13 +225,13 @@ io_set_sync(obj, mode)
}
static VALUE
-io_fileno(obj)
- VALUE obj;
+io_fileno(io)
+ VALUE io;
{
OpenFile *fptr;
int fd;
- GetOpenFile(obj, fptr);
+ GetOpenFile(io, fptr);
fd = fileno(fptr->f);
return INT2FIX(fd);
}
@@ -185,54 +247,50 @@ read_all(port)
int n;
GetOpenFile(port, fptr);
- if (!(fptr->mode & FMODE_READABLE)) {
- Fail("not opend for reading");
- }
- if (fptr->f == NULL) Fail("closed stream");
+ io_readable(fptr);
+ if (fptr->f == NULL) closed();
str = str_new(0, 0);
for (;;) {
+ READ_CHECK(fptr->f);
TRAP_BEG;
n = fread(buf, 1, BUFSIZ, fptr->f);
TRAP_END;
- if (n == 0) {
- if (feof(fptr->f)) break;
- rb_sys_fail(Qnil);
- }
+ if (n == 0) break;
+ if (n < 0) rb_sys_fail(0);
str_cat(str, buf, n);
}
return str;
}
static VALUE
-io_read(argc, argv, obj)
+io_read(argc, argv, io)
int argc;
VALUE *argv;
- VALUE obj;
+ VALUE io;
{
OpenFile *fptr;
int n, lgt;
VALUE len, str;
if (rb_scan_args(argc, argv, "01", &len) == 0) {
- return read_all(obj);
+ return read_all(io);
}
lgt = NUM2INT(len);
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_READABLE)) {
- Fail("not opend for reading");
- }
- if (fptr->f == NULL) Fail("closed stream");
+ GetOpenFile(io, fptr);
+ io_readable(fptr);
+ if (fptr->f == NULL) closed();
str = str_new(0, lgt);
+ READ_CHECK(fptr->f);
TRAP_BEG;
n = fread(RSTRING(str)->ptr, 1, RSTRING(str)->len, fptr->f);
TRAP_END;
if (n == 0) {
if (feof(fptr->f)) return Qnil;
- rb_sys_fail(Qnil);
+ rb_sys_fail(fptr->path);
}
RSTRING(str)->len = n;
@@ -241,42 +299,54 @@ io_read(argc, argv, obj)
return str;
}
-VALUE rb_lastline;
static VALUE lineno;
-static VALUE
-io_gets(obj)
- VALUE obj;
+VALUE
+io_gets_method(argc, argv, io)
+ int argc;
+ VALUE argv;
+ VALUE io;
{
OpenFile *fptr;
FILE *f;
struct RString *str;
int c, newline;
- int rslen;
+ char *rsptr;
+ int rslen, rspara = 0;
+ VALUE rs;
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_READABLE)) {
- Fail("not opend for reading");
+ if (rb_scan_args(argc, argv, "01", &rs) == 1) {
+ if (!NIL_P(rs)) Check_Type(rs, T_STRING);
}
+ else {
+ rs = RS;
+ }
+
+ GetOpenFile(io, fptr);
+ io_readable(fptr);
f = fptr->f;
- if (f == NULL) Fail("closed stream");
+ if (f == NULL) closed();
- if (RS) {
- rslen = RSTRING(RS)->len;
+ if (!NIL_P(rs)) {
+ rslen = RSTRING(rs)->len;
if (rslen == 0) {
- newline = '\n';
+ rsptr = "\n\n";
+ rslen = 2;
+ rspara = 1;
}
else {
- newline = RSTRING(RS)->ptr[rslen-1];
+ rsptr = RSTRING(rs)->ptr;
}
}
else {
- newline = 0777; /* non matching char */
- rslen = 1;
+ rsptr = 0;
+ rslen = 0;
}
+ newline = rslen ? rsptr[rslen - 1] : 0777;
- if (rslen == 0) {
+ if (rspara) {
do {
+ READ_CHECK(f);
TRAP_BEG;
c = getc(f);
TRAP_END;
@@ -290,51 +360,54 @@ io_gets(obj)
{
char buf[8192];
char *bp, *bpe = buf + sizeof buf - 3;
+ int cnt;
int append = 0;
again:
bp = buf;
- retry:
- TRAP_BEG;
- while ((c = getc(f)) != EOF && (*bp++ = c) != newline && bp < bpe)
- ;
- TRAP_END;
+ if (rslen) {
+ for (;;) {
+ READ_CHECK(f);
+ TRAP_BEG;
+ c = getc(f);
+ TRAP_END;
+ if (c == EOF) break;
+ if ((*bp++ = c) == newline) break;
+ if (bp == bpe) break;
+ }
+ cnt = bp - buf;
+ }
+ else {
+ cnt = fread(buf, 1, sizeof(buf), f);
+ c = cnt ? buf[cnt - 1]: EOF;
+ }
if (c == EOF) {
- if (!feof(f)) goto retry;
- if (!append && bp == buf) {
- str = Qnil;
+ if (!append && cnt == 0) {
+ str = RSTRING(Qnil);
goto return_gets;
}
}
if (append)
- str_cat(str, buf, bp - buf);
+ str_cat(str, buf, cnt);
else
- str = (struct RString*)str_new(buf, bp - buf);
-
- if (c != EOF
- &&
- (c != newline
- ||
- (rslen > 1
- &&
- (str->len < rslen
- ||
- memcmp(str->ptr+str->len-rslen, RSTRING(RS)->ptr, rslen)
- )
- )
- )
- ) {
+ str = (struct RString*)str_new(buf, cnt);
+
+ if (c != EOF &&
+ (!rslen ||
+ str->len < rslen ||
+ memcmp(str->ptr+str->len-rslen, rsptr, rslen))) {
append = 1;
goto again;
}
}
return_gets:
- if (rslen == 0) {
+ if (rspara) {
while (c != EOF) {
+ READ_CHECK(f);
TRAP_BEG;
c = getc(f);
TRAP_END;
@@ -349,82 +422,132 @@ io_gets(obj)
fptr->lineno++;
lineno = INT2FIX(fptr->lineno);
}
- return rb_lastline = (VALUE)str;
+ lastline_set(str);
+
+ return (VALUE)str;
+}
+
+VALUE
+io_gets(io)
+ VALUE io;
+{
+ return io_gets_method(0, 0, io);
}
static VALUE
-io_each_line(obj)
- VALUE obj;
+io_readline(argc, argv, io)
+ int argc;
+ VALUE argv;
+ VALUE io;
+{
+ VALUE line = io_gets_method(argc, argv, io);
+
+ if (NIL_P(line)) {
+ eof_error();
+ }
+ return line;
+}
+
+static VALUE
+io_each_line(argc, argv, io)
+ int argc;
+ VALUE argv;
+ VALUE io;
{
VALUE str;
- while (str = io_gets(obj)) {
+ while (!NIL_P(str = io_gets_method(argc, argv, io))) {
rb_yield(str);
}
return Qnil;
}
static VALUE
-io_each_byte(obj)
- VALUE obj;
+io_each_byte(io)
+ VALUE io;
{
OpenFile *fptr;
FILE *f;
int c;
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_READABLE)) {
- Fail("not opend for reading");
- }
+ GetOpenFile(io, fptr);
+ io_readable(fptr);
f = fptr->f;
- if (f == NULL) Fail("closed stream");
+ if (f == NULL) closed();
for (;;) {
+ READ_CHECK(f);
TRAP_BEG;
c = getc(f);
TRAP_END;
if (c == EOF) break;
rb_yield(INT2FIX(c & 0xff));
}
- if (ferror(f) != 0) rb_sys_fail(Qnil);
- return obj;
+ if (ferror(f) != 0) rb_sys_fail(fptr->path);
+ return Qnil;
}
-static VALUE
-io_getc(obj)
- VALUE obj;
+VALUE
+io_getc(io)
+ VALUE io;
{
OpenFile *fptr;
FILE *f;
int c;
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_READABLE)) {
- Fail("not opend for reading");
- }
+ GetOpenFile(io, fptr);
+ io_readable(fptr);
f = fptr->f;
- if (f == NULL) Fail("closed stream");
+ if (f == NULL) closed();
+ READ_CHECK(f);
TRAP_BEG;
c = getc(f);
TRAP_END;
if (c == EOF) {
- if (ferror(f) != 0) rb_sys_fail(Qnil);
+ if (ferror(f) != 0) rb_sys_fail(fptr->path);
return Qnil;
}
return INT2FIX(c & 0xff);
}
static VALUE
-io_isatty(obj)
- VALUE obj;
+io_readchar(io)
+ VALUE io;
+{
+ VALUE c = io_getc(io);
+
+ if (NIL_P(c)) {
+ eof_error();
+ }
+ return c;
+}
+
+VALUE
+io_ungetc(io, c)
+ VALUE io, c;
+{
+ OpenFile *fptr;
+
+ Check_Type(c, T_FIXNUM);
+ GetOpenFile(io, fptr);
+ io_readable(fptr);
+ if (fptr->f == NULL) closed();
+
+ if (ungetc(FIX2INT(c), fptr->f) == EOF)
+ rb_sys_fail(fptr->path);
+}
+
+static VALUE
+io_isatty(io)
+ VALUE io;
{
OpenFile *fptr;
#ifndef NT
- GetOpenFile(obj, fptr);
- if (fptr->f == NULL) Fail("closed stream");
+ GetOpenFile(io, fptr);
+ if (fptr->f == NULL) closed();
if (isatty(fileno(fptr->f)) == 0)
return FALSE;
#endif
@@ -466,30 +589,30 @@ io_fptr_finalize(fptr)
}
VALUE
-io_close(obj)
- VALUE obj;
+io_close(io)
+ VALUE io;
{
OpenFile *fptr;
- GetOpenFile(obj, fptr);
+ GetOpenFile(io, fptr);
io_fptr_finalize(fptr);
return Qnil;
}
static VALUE
-io_closed(obj)
- VALUE obj;
+io_closed(io)
+ VALUE io;
{
OpenFile *fptr;
- GetOpenFile(obj, fptr);
+ GetOpenFile(io, fptr);
return fptr->f?FALSE:TRUE;
}
static VALUE
-io_syswrite(obj, str)
- VALUE obj, str;
+io_syswrite(io, str)
+ VALUE io, str;
{
OpenFile *fptr;
FILE *f;
@@ -498,43 +621,45 @@ io_syswrite(obj, str)
if (TYPE(str) != T_STRING)
str = obj_as_string(str);
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_WRITABLE)) {
- Fail("not opend for writing");
- }
+ GetOpenFile(io, fptr);
+ io_writable(fptr);
f = (fptr->f2) ? fptr->f2 : fptr->f;
- if (f == NULL) Fail("closed stream");
+ if (f == NULL) closed();
+#ifdef THREAD
+ thread_fd_writable(fileno(f));
+#endif
n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len);
- if (n == -1) rb_sys_fail(Qnil);
+ if (n == -1) rb_sys_fail(fptr->path);
return INT2FIX(n);
}
static VALUE
-io_sysread(obj, len)
- VALUE obj, len;
+io_sysread(io, len)
+ VALUE io, len;
{
OpenFile *fptr;
int n, ilen;
VALUE str;
ilen = NUM2INT(len);
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_READABLE)) {
- Fail("not opend for reading");
- }
- if (fptr->f == NULL) Fail("closed stream");
+ GetOpenFile(io, fptr);
+ io_readable(fptr);
+ if (fptr->f == NULL) closed();
str = str_new(0, ilen);
+#ifdef THREAD
+ thread_wait_fd(fileno(fptr->f));
+#endif
TRAP_BEG;
n = read(fileno(fptr->f), RSTRING(str)->ptr, RSTRING(str)->len);
TRAP_END;
- if (n == -1) rb_sys_fail(Qnil);
- if (n == 0) return Qnil; /* EOF */
+ if (n == -1) rb_sys_fail(fptr->path);
+ if (n == 0) eof_error();
RSTRING(str)->len = n;
RSTRING(str)->ptr[n] = '\0';
@@ -542,21 +667,21 @@ io_sysread(obj, len)
}
static VALUE
-io_binmode(obj)
- VALUE obj;
+io_binmode(io)
+ VALUE io;
{
-#ifdef NT
+#if defined(NT) || defined(DJGPP)
OpenFile *fptr;
- GetOpenFile(obj, fptr);
- if (setmode(fileno(fptr), O_BINARY) == -1)
- rb_sys_fail(Qnil);
+ GetOpenFile(io, fptr);
+ if (fptr->f && setmode(fileno(fptr->f), O_BINARY) == -1)
+ rb_sys_fail(fptr->path);
+ if (fptr->f2 && setmode(fileno(fptr->f2), O_BINARY) == -1)
+ rb_sys_fail(fptr->path);
#endif
- return obj;
+ return io;
}
-VALUE obj_alloc();
-
int
io_mode_flags(mode)
char *mode;
@@ -574,7 +699,7 @@ io_mode_flags(mode)
flags |= FMODE_WRITABLE;
break;
default:
- Fail("illegal access mode");
+ ArgError("illegal access mode");
}
if (mode[1] == '+') {
flags |= FMODE_READABLE | FMODE_WRITABLE;
@@ -584,6 +709,26 @@ io_mode_flags(mode)
}
FILE *
+rb_fopen(fname, mode)
+ char *fname;
+ char *mode;
+{
+ FILE *f;
+
+ f = fopen(fname, mode);
+ if (f == NULL) {
+ if (errno == EMFILE || errno == ENFILE) {
+ gc();
+ f = fopen(fname, mode);
+ }
+ if (f == NULL) {
+ rb_sys_fail(fname);
+ }
+ }
+ return f;
+}
+
+FILE *
rb_fdopen(fd, mode)
int fd;
char *mode;
@@ -596,13 +741,13 @@ rb_fdopen(fd, mode)
f = fdopen(fd, mode);
}
if (f == NULL) {
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
}
}
return f;
}
-#ifdef NT
+#if defined (NT) || defined(DJGPP)
static void
pipe_finalize(fptr)
OpenFile *fptr;
@@ -619,29 +764,30 @@ pipe_open(pname, mode)
char *pname, *mode;
{
int modef = io_mode_flags(mode);
- VALUE port;
OpenFile *fptr;
-#ifdef NT
+#if defined(NT) || defined(DJGPP)
FILE *f = popen(pname, mode);
if (f == NULL) rb_sys_fail(pname);
+ else {
+ NEWOBJ(port, struct RFile);
+ OBJSETUP(port, cIO, T_FILE);
+ MakeOpenFile(port, fptr);
+ fptr->finalize = pipe_finalize;
- port = obj_alloc(cIO);
- MakeOpenFile(port, fptr);
- 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;
+ if (modef & FMODE_READABLE) fptr->f = f;
+ if (modef & FMODE_WRITABLE) fptr->f2 = f;
+ fptr->mode = modef | FMODE_SYNC;
+ return (VALUE)port;
+ }
#else
int pid, pr[2], pw[2];
volatile int doexec;
if (((modef & FMODE_READABLE) && pipe(pr) == -1) ||
((modef & FMODE_WRITABLE) && pipe(pw) == -1))
- rb_sys_fail(Qnil);
+ rb_sys_fail(pname);
doexec = (strcmp("-", pname) != 0);
if (!doexec) {
@@ -688,28 +834,52 @@ pipe_open(pname, mode)
break;
default: /* parent */
- 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;
+ {
+ NEWOBJ(port, struct RFile);
+ OBJSETUP(port, cIO, T_FILE);
+ 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 (modef & FMODE_READABLE) fptr->f = rb_fdopen(pr[0], "r");
+ if (modef & FMODE_WRITABLE) fptr->f2 = rb_fdopen(pw[1], "w");
+
+ return (VALUE)port;
+ }
}
+#endif
+}
- fptr->pid = pid;
- if (modef & FMODE_READABLE) fptr->f = rb_fdopen(pr[0], "r");
- if (modef & FMODE_WRITABLE) fptr->f2 = rb_fdopen(pw[1], "w");
+static VALUE
+io_popen(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ char *mode;
+ VALUE pname, pmode;
- return port;
-#endif
+ rb_scan_args(argc, argv, "11", &pname, &pmode);
+ Check_Type(pname, T_STRING);
+ if (NIL_P(pmode)) {
+ mode = "r";
+ }
+ else {
+ Check_Type(pmode, T_STRING);
+ if (RSTRING(pmode)->len == 0 || RSTRING(pmode)->len > 2)
+ ArgError("illegal access mode");
+ mode = RSTRING(pmode)->ptr;
+ }
+ return pipe_open(RSTRING(pname)->ptr, mode);
}
static VALUE
io_open(fname, mode)
char *fname, *mode;
{
- int pipe = 0;
-
if (fname[0] == '|') {
return pipe_open(fname+1, mode);
}
@@ -725,19 +895,17 @@ f_open(argc, argv, self)
VALUE self;
{
char *mode;
- VALUE port;
- int pipe = 0;
VALUE pname, pmode;
rb_scan_args(argc, argv, "11", &pname, &pmode);
Check_Type(pname, T_STRING);
- if (pmode == Qnil) {
+ if (NIL_P(pmode)) {
mode = "r";
}
else {
Check_Type(pmode, T_STRING);
if (RSTRING(pmode)->len == 0 || RSTRING(pmode)->len > 2)
- Fail("illegal access mode");
+ ArgError("illegal access mode");
mode = RSTRING(pmode)->ptr;
}
return io_open(RSTRING(pname)->ptr, mode);
@@ -765,13 +933,13 @@ f_printf(argc, argv)
if (TYPE(argv[0]) == T_STRING) {
out = rb_defout;
}
- else if (rb_responds_to(argv[0], id_write)) {
+ else if (rb_respond_to(argv[0], id_write)) {
out = argv[0];
argv++;
argc--;
}
else {
- Fail("output must responds to `write'");
+ NameError("output must responds to `write'");
}
rb_funcall(out, id_write, 1, f_sprintf(argc, argv));
@@ -790,30 +958,26 @@ io_print(argc, argv, out)
/* if no argument given, print `$_' */
if (argc == 0) {
argc = 1;
- if (rb_lastline)
- argv = &rb_lastline;
- else {
- line = str_new(0,0);
- argv = &line;
- }
+ line = lastline_get();
+ argv = &line;
}
for (i=0; i<argc; i++) {
- if (OFS && i>0) {
+ if (!NIL_P(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);
+ case T_NIL:
+ io_write(out, str_new2("nil"));
break;
default:
rb_funcall(argv[i], id_print_on, 1, out);
break;
}
}
- if (ORS) {
+ if (!NIL_P(ORS)) {
io_write(out, ORS);
}
@@ -829,6 +993,17 @@ f_print(argc, argv)
return Qnil;
}
+VALUE
+f_p(obj, val)
+{
+ VALUE str = rb_inspect(val);
+
+ Check_Type(str, T_STRING);
+ io_write(rb_defout, str);
+ io_write(rb_defout, str_new2("\n"));
+ return Qnil;
+}
+
static VALUE
io_defset(val, id)
VALUE val;
@@ -838,7 +1013,7 @@ io_defset(val, id)
val = io_open(RSTRING(val)->ptr, "w");
}
if (!obj_is_kind_of(val, cIO)) {
- Fail("$< must be a file, %s given", rb_class2name(CLASS_OF(val)));
+ TypeError("$< must be a file, %s given", rb_class2name(CLASS_OF(val)));
}
return rb_defout = val;
}
@@ -855,14 +1030,15 @@ prep_stdio(f, mode)
FILE *f;
int mode;
{
- VALUE obj = obj_alloc(cIO);
OpenFile *fp;
+ NEWOBJ(obj, struct RFile);
+ OBJSETUP(obj, cIO, T_FILE);
MakeOpenFile(obj, fp);
fp->f = f;
fp->mode = mode;
- return obj;
+ return (VALUE)obj;
}
static VALUE filename, file;
@@ -900,9 +1076,8 @@ next_argv()
}
}
else {
- FILE *fr = fopen(fn, "r");
+ FILE *fr = rb_fopen(fn, "r");
- if (!fr) rb_sys_fail(fn);
if (inplace) {
struct stat st, st2;
VALUE str;
@@ -919,25 +1094,40 @@ next_argv()
#else
str_cat(str, inplace, strlen(inplace));
#endif
+#if defined(MSDOS) || defined(__BOW__)
+ (void)fclose(fr);
+ (void)unlink(RSTRING(str)->ptr);
+ (void)rename(fn, RSTRING(str)->ptr);
+ fr = rb_fopen(RSTRING(str)->ptr, "r");
+#else
if (rename(fn, RSTRING(str)->ptr) < 0) {
Warning("Can't rename %s to %s: %s, skipping file",
fn, RSTRING(str)->ptr, strerror(errno));
fclose(fr);
goto retry;
}
+#endif
}
- else if (unlink(fn) < 0) {
- Warning("Can't remove %s: %s, skipping file",
+ else {
+#if !defined(MSDOS) && !defined(__BOW__)
+ if (unlink(fn) < 0) {
+ Warning("Can't remove %s: %s, skipping file",
fn, strerror(errno));
- fclose(fr);
- goto retry;
+ fclose(fr);
+ goto retry;
+ }
+#else
+ Fatal("Can't do inplace edit without backup");
+#endif
}
- fw = fopen(fn, "w");
+ fw = rb_fopen(fn, "w");
+#if !defined(DJGPP) && !defined(__CYGWIN32__)
fstat(fileno(fw), &st2);
fchmod(fileno(fw), st.st_mode);
if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
fchown(fileno(fw), st.st_uid, st.st_gid);
}
+#endif
rb_defout = prep_stdio(fw, FMODE_WRITABLE);
}
file = prep_stdio(fr, FMODE_READABLE);
@@ -952,25 +1142,48 @@ next_argv()
}
static VALUE
-f_gets()
+f_gets_method(argc, argv)
+ int argc;
+ VALUE argv;
{
VALUE line;
retry:
if (!next_argv()) return Qnil;
- line = io_gets(file);
- if (line == Qnil && next_p != -1) {
+ line = io_gets_method(argc, argv, file);
+ if (NIL_P(line) && next_p != -1) {
io_close(file);
next_p = 1;
goto retry;
}
-
gets_lineno++;
lineno = INT2FIX(gets_lineno);
return line;
}
+VALUE
+f_gets(argc, argv)
+ int argc;
+ VALUE argv;
+{
+ return f_gets_method(0,0);
+}
+
+static VALUE
+f_readline(argc, argv)
+ int argc;
+ VALUE argv;
+{
+ VALUE line = f_gets_method(argc, argv);
+
+ if (NIL_P(line)) {
+ eof_error();
+ }
+
+ return line;
+}
+
static VALUE
f_eof()
{
@@ -990,13 +1203,36 @@ f_getc()
}
static VALUE
-f_readlines(obj)
- VALUE obj;
+f_ungetc(obj, c)
+ VALUE obj, c;
+{
+ if (!next_argv()) {
+ ArgError("no stream to ungetc");
+ }
+
+ return io_ungetc(file, c);
+}
+
+static VALUE
+f_readchar()
+{
+ VALUE c = f_getc();
+
+ if (NIL_P(c)) {
+ eof_error();
+ }
+ return c;
+}
+
+static VALUE
+f_readlines(argc, argv)
+ int argc;
+ VALUE argv;
{
VALUE line, ary;
ary = ary_new();
- while (line = f_gets(obj)) {
+ while (RTEST(line = f_gets_method(argc, argv))) {
ary_push(ary, line);
}
@@ -1009,14 +1245,15 @@ rb_str_setter(val, id, var)
ID id;
VALUE *var;
{
- if (val && TYPE(val) != T_STRING) {
- Fail("value of %s must be String", rb_id2name(id));
+ if (!NIL_P(val) && TYPE(val) != T_STRING) {
+ TypeError("value of %s must be String", rb_id2name(id));
}
return *var = val;
}
-VALUE
-rb_xstring(str)
+static VALUE
+f_backquote(obj, str)
+ VALUE obj;
struct RString *str;
{
VALUE port, result;
@@ -1031,21 +1268,8 @@ rb_xstring(str)
return result;
}
-struct timeval *time_timeval();
-
-#ifdef _STDIO_USES_IOSTREAM /* GNU libc */
-# 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
-# ifdef FILE_COUNT
-# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
-# else
-extern int ReadDataPending();
-# define READ_DATA_PENDING(fp) ReadDataPending(fp)
-# endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
#endif
static VALUE
@@ -1063,28 +1287,31 @@ f_select(argc, argv, obj)
int interrupt = 0;
rb_scan_args(argc, argv, "13", &read, &write, &except, &timeout);
- if (timeout) {
- tp = time_timeval(timeout);
+ if (NIL_P(timeout)) {
+ tp = NULL;
}
else {
- tp = NULL;
+ timerec = time_timeval(timeout);
+ tp = &timerec;
}
FD_ZERO(&pset);
- if (read) {
+ if (!NIL_P(read)) {
int pending = 0;
Check_Type(read, T_ARRAY);
rp = &rset;
FD_ZERO(rp);
for (i=0; i<RARRAY(read)->len; i++) {
+ Check_Type(RARRAY(read)->ptr[i], T_FILE);
GetOpenFile(RARRAY(read)->ptr[i], fptr);
+ if (fptr->f == NULL) closed();
FD_SET(fileno(fptr->f), rp);
if (READ_DATA_PENDING(fptr->f)) { /* check for buffered data */
pending++;
FD_SET(fileno(fptr->f), &pset);
}
- if (max < (int)fileno(fptr->f)) max = fileno(fptr->f);
+ if (max < fileno(fptr->f)) max = fileno(fptr->f);
}
if (pending) { /* no blocking if there's buffered data */
timerec.tv_sec = timerec.tv_usec = 0;
@@ -1094,14 +1321,16 @@ f_select(argc, argv, obj)
else
rp = NULL;
- if (write) {
+ if (!NIL_P(write)) {
Check_Type(write, T_ARRAY);
wp = &wset;
FD_ZERO(wp);
for (i=0; i<RARRAY(write)->len; i++) {
+ Check_Type(RARRAY(write)->ptr[i], T_FILE);
GetOpenFile(RARRAY(write)->ptr[i], fptr);
+ if (fptr->f == NULL) closed();
FD_SET(fileno(fptr->f), wp);
- if (max > (int)fileno(fptr->f)) max = fileno(fptr->f);
+ if (max > fileno(fptr->f)) max = fileno(fptr->f);
if (fptr->f2) {
FD_SET(fileno(fptr->f2), wp);
if (max < (int)fileno(fptr->f2)) max = fileno(fptr->f2);
@@ -1111,14 +1340,16 @@ f_select(argc, argv, obj)
else
wp = NULL;
- if (except) {
+ if (!NIL_P(except)) {
Check_Type(except, T_ARRAY);
ep = &eset;
FD_ZERO(ep);
for (i=0; i<RARRAY(except)->len; i++) {
+ Check_Type(RARRAY(except)->ptr[i], T_FILE);
GetOpenFile(RARRAY(except)->ptr[i], fptr);
+ if (fptr->f == NULL) closed();
FD_SET(fileno(fptr->f), ep);
- if (max < (int)fileno(fptr->f)) max = fileno(fptr->f);
+ if (max < fileno(fptr->f)) max = fileno(fptr->f);
if (fptr->f2) {
FD_SET(fileno(fptr->f2), ep);
if (max > (int)fileno(fptr->f2)) max = fileno(fptr->f2);
@@ -1130,17 +1361,24 @@ f_select(argc, argv, obj)
max++;
+#ifdef THREAD
+ n = thread_select(max, rp, wp, ep, tp);
+ if (n < 0) {
+ rb_sys_fail(0);
+ }
+#else
retry:
TRAP_BEG;
n = select(max, rp, wp, ep, tp);
TRAP_END;
if (n < 0) {
if (errno != EINTR) {
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
}
if (tp == NULL) goto retry;
interrupt = 1;
}
+#endif
res = ary_new2(3);
ary_push(res, rp?ary_new():ary_new2(0));
@@ -1191,16 +1429,17 @@ f_select(argc, argv, obj)
}
void
-io_ctl(obj, req, arg, io_p)
- VALUE obj, req;
+io_ctl(io, req, arg, io_p)
+ VALUE io, req;
struct RString *arg;
int io_p;
{
+#if !defined(MSDOS)
int cmd = NUM2INT(req);
OpenFile *fptr;
int len, fd;
- GetOpenFile(obj, fptr);
+ GetOpenFile(io, fptr);
#ifdef IOCPARM_MASK
#ifndef IOCPARM_LEN
@@ -1216,9 +1455,7 @@ io_ctl(obj, req, arg, io_p)
Check_Type(arg, T_STRING);
str_modify(arg);
- if (arg->len < len) {
- str_grow(arg, len+1);
- }
+ str_resize(arg, len+1);
arg->ptr[len] = 17;
fd = fileno(fptr->f);
#ifdef HAVE_FCNTL
@@ -1227,22 +1464,25 @@ io_ctl(obj, req, arg, io_p)
}
#else
if (!io_p) {
- Bug("fcntl() not implemented");
+ rb_notimplement();
}
if (ioctl(fd, cmd, arg->ptr)<0) rb_sys_fail(fptr->path);
#endif
if (arg->ptr[len] != 17) {
- Fail("Return value overflowed string");
+ ArgError("Return value overflowed string");
}
+#else
+ rb_notimplement();
+#endif
}
static VALUE
-io_ioctl(obj, req, arg)
- VALUE obj, req;
+io_ioctl(io, req, arg)
+ VALUE io, req;
struct RString *arg;
{
- io_ctl(obj, req, arg, 1);
- return obj;
+ io_ctl(io, req, arg, 1);
+ return io;
}
static VALUE
@@ -1279,7 +1519,7 @@ f_syscall(argc, argv)
}
switch (argc) {
case 0:
- Fail("Too few args to syscall");
+ ArgError("Too few args to syscall");
case 1:
retval = syscall(arg[0]);
break;
@@ -1335,13 +1575,57 @@ f_syscall(argc, argv)
if (retval == -1) rb_sys_fail(0);
return INT2FIX(0);
#else
- Fail("syscall() unimplemented");
+ rb_notimplement();
#endif
}
static VALUE
-arg_read(obj)
- VALUE obj;
+io_pipe()
+{
+ int pipes[2];
+ VALUE r, w, ary;
+
+ if (pipe(pipes) == -1)
+ rb_sys_fail(0);
+ r = prep_stdio(fdopen(pipes[0], "r"), FMODE_READABLE);
+ w = prep_stdio(fdopen(pipes[1], "w"), FMODE_WRITABLE);
+
+ ary = ary_new2(2);
+ ary_push(ary, r);
+ ary_push(ary, w);
+
+ return ary;
+}
+
+
+static VALUE
+io_foreach_line(io)
+ VALUE io;
+{
+ VALUE str;
+
+ while (!NIL_P(str = io_gets(io))) {
+ rb_yield(str);
+ }
+ return Qnil;
+}
+
+static VALUE
+io_foreach(io, fname)
+ VALUE io;
+ struct RString *fname;
+{
+ VALUE f, v;
+
+ Check_Type(fname, T_STRING);
+ f = io_open(fname->ptr, "r");
+ return rb_ensure(io_foreach_line, f, io_close, f);
+}
+
+static VALUE
+arg_read(argc, argv)
+ int argc;
+ VALUE argv;
{
VALUE str, str2;
@@ -1349,13 +1633,13 @@ arg_read(obj)
for (;;) {
retry:
if (!next_argv()) return Qnil;
- str2 = io_read(0, Qnil, file);
- if (str2 == Qnil && next_p != -1) {
+ str2 = io_read(argc, argv, file);
+ if (NIL_P(str2) && next_p != -1) {
io_close(file);
next_p = 1;
goto retry;
}
- if (str2 == Qnil) break;
+ if (NIL_P(str2)) break;
str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
}
@@ -1370,7 +1654,7 @@ arg_getc()
retry:
if (!next_argv()) return Qnil;
byte = io_getc(file);
- if (byte == Qnil && next_p != -1) {
+ if (NIL_P(byte) && next_p != -1) {
io_close(file);
next_p = 1;
goto retry;
@@ -1380,11 +1664,13 @@ arg_getc()
}
static VALUE
-arg_each_line()
+arg_each_line(argc, argv)
+ int argc;
+ VALUE argv;
{
VALUE str;
- while (str = f_gets()) {
+ while (RTEST(str = f_gets_method(argc, argv))) {
rb_yield(str);
}
return Qnil;
@@ -1395,7 +1681,7 @@ arg_each_byte()
{
VALUE byte;
- while (byte = arg_getc()) {
+ while (!NIL_P(byte = arg_getc())) {
rb_yield(byte);
}
return Qnil;
@@ -1419,6 +1705,9 @@ void
Init_IO()
{
extern VALUE cKernel;
+ extern VALUE eException;
+
+ eEOFError = rb_define_class("EOFError", eException);
id_write = rb_intern("write");
id_fd = rb_intern("fd");
@@ -1429,32 +1718,46 @@ Init_IO()
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, "gets", f_gets_method, -1);
+ rb_define_private_method(cKernel, "readline", f_readline, -1);
rb_define_private_method(cKernel, "eof", f_eof, 0);
rb_define_private_method(cKernel, "getc", f_getc, 0);
+ rb_define_private_method(cKernel, "readchar", f_readchar, 0);
rb_define_private_method(cKernel, "select", f_select, -1);
+ rb_define_private_method(cKernel, "ungetc", f_ungetc, 1);
- rb_define_private_method(cKernel, "readlines", f_readlines, 0);
+ rb_define_private_method(cKernel, "readlines", f_readlines, -1);
rb_define_method(cKernel, "print_on", f_print_on, 1);
+ rb_define_private_method(cKernel, "`", f_backquote, 1);
+ rb_define_private_method(cKernel, "pipe", io_pipe, 0);
+
+ rb_define_private_method(cKernel, "p", f_p, 1);
+
cIO = rb_define_class("IO", cObject);
rb_include_module(cIO, mEnumerable);
+ rb_define_singleton_method(cIO, "popen", io_popen, -1);
+ rb_define_singleton_method(cIO, "foreach", io_foreach, 1);
+ rb_define_singleton_method(cIO, "select", f_select, -1);
+
+ FS = OFS = Qnil;
rb_define_hooked_variable("$;", &FS, 0, rb_str_setter);
rb_define_hooked_variable("$,", &OFS, 0, rb_str_setter);
- RS = str_new2("\n");
+ RS = RS_default = str_new2("\n"); ORS = Qnil;
+ rb_global_variable(&RS_default);
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_virtual_variable("$_", lastline_get, lastline_set);
rb_define_method(cIO, "print", io_print, -1);
+ rb_define_method(cIO, "printf", io_printf, -1);
- rb_define_method(cIO, "each", io_each_line, 0);
+ rb_define_method(cIO, "each", io_each_line, -1);
rb_define_method(cIO, "each_line", io_each_line, 0);
rb_define_method(cIO, "each_byte", io_each_byte, 0);
@@ -1469,11 +1772,13 @@ Init_IO()
rb_define_alias(cIO, "readlines", "to_a");
- rb_define_method(cIO, "read", io_read, -2);
+ rb_define_method(cIO, "read", io_read, -1);
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, "gets", io_gets_method, -1);
+ rb_define_method(cIO, "readline", io_readline, -1);
rb_define_method(cIO, "getc", io_getc, 0);
+ rb_define_method(cIO, "readchar", io_readchar, 0);
+ rb_define_method(cIO, "ungetc",io_ungetc, 1);
rb_define_method(cIO, "puts", io_puts, 1);
rb_define_method(cIO, "<<", io_puts, 1);
rb_define_method(cIO, "flush", io_flush, 0);
@@ -1497,27 +1802,29 @@ Init_IO()
rb_defout = rb_stdout;
rb_define_hooked_variable("$>", &rb_defout, 0, io_defset);
- rb_define_const(cObject, "STDIN", rb_stdin);
- rb_define_const(cObject, "STDOUT", rb_stdout);
- rb_define_const(cObject, "STDERR", rb_stderr);
+ rb_define_global_const("STDIN", rb_stdin);
+ rb_define_global_const("STDOUT", rb_stdout);
+ rb_define_global_const("STDERR", rb_stderr);
argf = obj_alloc(cObject);
rb_extend_object(argf, mEnumerable);
rb_define_readonly_variable("$<", &argf);
rb_define_readonly_variable("$ARGF", &argf);
+ rb_define_global_const("ARGF", argf);
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_line", arg_each_line, -1);
rb_define_singleton_method(argf, "each_byte", arg_each_byte, 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, "read", arg_read, -1);
+ rb_define_singleton_method(argf, "readlines", f_readlines, -1);
+ rb_define_singleton_method(argf, "gets", f_gets_method, -1);
+ rb_define_singleton_method(argf, "readline", f_readline, -1);
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_singleton_method(argf, "ungetc", f_ungetc, 1);
rb_define_singleton_method(argf, "to_s", arg_filename, 0);
rb_define_singleton_method(argf, "filename", arg_filename, 0);
diff --git a/io.h b/io.h
index b3772c9a2f..2817835ef3 100644
--- a/io.h
+++ b/io.h
@@ -7,7 +7,7 @@
$Date: 1994/08/12 11:06:42 $
created at: Fri Nov 12 16:47:09 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -18,7 +18,7 @@
#include <stdio.h>
#include <errno.h>
-typedef struct {
+typedef struct OpenFile {
FILE *f; /* stdio ptr for read/write */
FILE *f2; /* additional ptr for rw pipes */
int mode; /* mode flags */
@@ -33,14 +33,10 @@ typedef struct {
#define FMODE_READWRITE 3
#define FMODE_SYNC 4
-extern ID id_fd;
-
-#define GetOpenFile(obj,fp) Get_Data_Struct(obj, id_fd, OpenFile, fp)
-
-void io_fptr_finalize();
+#define GetOpenFile(obj,fp) fp = RFILE(obj)->fptr
#define MakeOpenFile(obj, fp) do {\
- Make_Data_Struct(obj, id_fd, OpenFile, 0, io_fptr_finalize, fp);\
+ fp = RFILE(obj)->fptr = ALLOC(OpenFile);\
fp->f = fp->f2 = NULL;\
fp->mode = 0;\
fp->pid = 0;\
@@ -49,4 +45,6 @@ void io_fptr_finalize();
fp->finalize = 0;\
} while (0)
+FILE *rb_fopen();
+
#endif
diff --git a/lib/base64.rb b/lib/base64.rb
index a6bf1adf92..9bb6487bee 100644
--- a/lib/base64.rb
+++ b/lib/base64.rb
@@ -46,7 +46,7 @@ def j2e(str)
end
def decode_b(str)
- str.gsub!(/=\?ISO-2022-JP\?B\?([!->@-~]+)\?=/) {
+ str.gsub!(/=\?ISO-2022-JP\?B\?([!->@-~]+)\?=/i) {
decode64($1)
}
str.gsub!(/\n/, ' ')
diff --git a/lib/cgi-lib.rb b/lib/cgi-lib.rb
new file mode 100644
index 0000000000..afadbff3b6
--- /dev/null
+++ b/lib/cgi-lib.rb
@@ -0,0 +1,56 @@
+#!/usr/local/bin/ruby
+#
+# Get CGI String
+#
+# EXAMPLE:
+# require "cgi-lib.rb"
+# foo = CGI.new
+# foo['field'] <== value of 'field'
+# foo.keys <== array of fields
+# foo.inputs <== hash of { <field> => <value> }
+
+class CGI
+ attr("inputs")
+
+ def initialize
+ str = if ENV['REQUEST_METHOD'] == "GET"
+ ENV['QUERY_STRING']
+ elsif ENV['REQUEST_METHOD'] == "POST"
+ $stdin.read ENV['CONTENT_LENGTH'].to_i
+ else
+ ""
+ end
+ arr = str.split(/&/)
+ @inputs = {}
+ arr.each do |x|
+ x.gsub!(/\+/, ' ')
+ key, val = x.split(/=/, 2)
+ val = "" unless val
+
+ key.gsub!(/%(..)/) { [$1.hex].pack("c") }
+ val.gsub!(/%(..)/) { [$1.hex].pack("c") }
+
+ @inputs[key] += "\0" if @inputs[key]
+ @inputs[key] += val
+ end
+ end
+
+ def keys
+ @inputs.keys
+ end
+
+ def [](key)
+ @inputs[key]
+ end
+
+ def CGI.message(msg, title = "")
+ print "Content-type: text/html\n\n"
+ print "<html><head><title>"
+ print title
+ print "</title></head><body>\n"
+ print msg
+ print "</body></html>\n"
+ TRUE
+ end
+
+end
diff --git a/lib/complex.rb b/lib/complex.rb
new file mode 100644
index 0000000000..aa5d219d2f
--- /dev/null
+++ b/lib/complex.rb
@@ -0,0 +1,490 @@
+#
+# complex.rb -
+# $Release Version: 0.5 $
+# $Revision: 1.1 $
+# $Date: 1996/11/11 04:25:19 $
+# by Keiju ISHITSUKA(SHL Japan Inc.)
+#
+# --
+# Usage:
+# class Complex < Numeric
+#
+# Complex(x, y) --> x + yi
+# y.im --> 0 + yi
+#
+# Complex::polar
+#
+# Complex::+
+# Complex::-
+# Complex::*
+# Complex::/
+# Complex::**
+# Complex::%
+# Complex::divmod
+# Complex::abs
+# Complex::abs2
+# Complex::arg
+# Complex::polar
+# Complex::conjugate
+# Complex::<=>
+# Complex::==
+# Complex::to_i
+# Complex::to_f
+# Complex::to_r
+# Complex::to_s
+#
+# Complex::I
+#
+# Numeric::im
+#
+# Math.sqrt
+# Math.exp
+# Math.cos
+# Math.sin
+# Math.tan
+# Math.log
+# Math.log10
+# Math.atan2
+#
+#
+
+def Complex(a, b = 0)
+ if a.kind_of?(Complex) and b == 0
+ a
+ elsif b == 0 and defined? Complex::Unify
+ a
+ else
+ Complex.new(a, b)
+ end
+end
+
+class Complex < Numeric
+
+ def Complex.generic?(other)
+ other.kind_of?(Integer) or
+ other.kind_of?(Float) or
+ (defined?(Rational) and other.kind_of?(Rational))
+ end
+
+ def Complex.polar(r, theta)
+ Complex(r*Math.cos(theta), r*Math.sin(theta))
+ end
+
+ def initialize(a, b = 0)
+ @real = a
+ @image = b
+ end
+
+ def + (other)
+ if other.kind_of?(Complex)
+ re = @real + other.real
+ im = @image + other.image
+ Complex(re, im)
+ elsif Complex.generic?(other)
+ Complex(@real + other, @image)
+ else
+ x , y = a.coerce(self)
+ x + y
+ end
+ end
+
+ def - (other)
+ if other.kind_of?(Complex)
+ re = @real - other.real
+ im = @image - other.image
+ Complex(re, im)
+ elsif Complex.generic?(other)
+ Complex(@real - other, @image)
+ else
+ x , y = a.coerce(self)
+ x - y
+ end
+ end
+
+ def * (other)
+ if other.kind_of?(Complex)
+ re = @real*other.real - @image*other.image
+ im = @real*other.image + @image*other.real
+ Complex(re, im)
+ elsif Complex.generic?(other)
+ Complex(@real * other, @image * other)
+ else
+ x , y = a.coerce(self)
+ x * y
+ end
+ end
+
+ def / (other)
+ if other.kind_of?(Complex)
+ self * other.conjugate / other.abs2
+ elsif Complex.generic?(other)
+ Complex(@real / other, @image / other)
+ else
+ x , y = a.coerce(self)
+ x / y
+ end
+ end
+
+ def ** (other)
+ if other == 0
+ return Complex(1)
+ end
+ if other.kind_of?(Complex)
+ r, theta = polar
+ ore = other.real
+ oim = other.image
+ nr = Math.exp!(ore*Math.log!(r) - oim * theta)
+ ntheta = theta*ore + oim*Math.log!(r)
+ Complex.polar(nr, ntheta)
+ elsif other.kind_of?(Integer)
+ if other > 0
+ x = self
+ z = x
+ n = other - 1
+ while n != 0
+ while (div, mod = n.divmod(2)
+ mod == 0)
+ x = Complex(x.real*x.real - x.image*x.image, 2*x.real*x.image)
+ n = div
+ end
+ z *= x
+ n -= 1
+ end
+ z
+ else
+ if defined? Rational
+ (Rational(1) / self) ** -other
+ else
+ self ** Float(other)
+ end
+ end
+ elsif Complex.generic?(other)
+ r, theta = polar
+ Complex.polar(r.power!(other), theta * other)
+ else
+ x , y = a.coerce(self)
+ x / y
+ end
+ end
+
+ def % (other)
+ if other.kind_of?(Complex)
+ Complex(@real % other.real, @image % other.image)
+ elsif Complex.generic?(other)
+ Complex(@real % other, @image % other)
+ else
+ x , y = a.coerce(self)
+ x % y
+ end
+ end
+
+ def divmod(other)
+ if other.kind_of?(Complex)
+ rdiv, rmod = @real.divmod(other.real)
+ idiv, imod = @image.divmod(other.image)
+ return Complex(rdiv, idiv), Complex(rmod, rdiv)
+ elsif Complex.generic?(other)
+ Complex(@real.divmod(other), @image.divmod(other))
+ else
+ x , y = a.coerce(self)
+ x.divmod(y)
+ end
+ end
+
+ def abs
+ Math.sqrt!((@real*@real + @image*@image).to_f)
+ end
+
+ def abs2
+ @real*@real + @image*@image
+ end
+
+ def arg
+ Math.atan2(@image.to_f, @real.to_f)
+ end
+
+ def polar
+ return abs, arg
+ end
+
+ def conjugate
+ Complex(@real, -@image)
+ end
+
+ def <=> (other)
+ self.abs <=> other.abs
+ end
+
+ def == (other)
+ if other.kind_of?(Complex)
+ @real == other.real and @image == other.image
+ elsif Complex.generic?(other)
+ @real == other and @image == 0
+ else
+ x , y = a.coerce(self)
+ x == y
+ end
+ end
+
+ def coerce(other)
+ if Complex.generic?(other)
+ return Complex.new(other), self
+ else
+ super
+ end
+ end
+
+ def to_i
+ Complex(@real.to_i, @image.to_i)
+ end
+
+ def to_f
+ Complex(@real.to_f, @image.to_f)
+ end
+
+ def to_r
+ Complex(@real.to_r, @image.to_r)
+ end
+
+ def denominator
+ @real.denominator.lcm(@image.denominator)
+ end
+
+ def numerator
+ cd = denominator
+ Complex(@real.numerator*(cd/@real.denominator),
+ @image.numerator*(cd/@image.denominator))
+ end
+
+ def to_s
+ if @real != 0
+ if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
+ if @image >= 0
+ @real.to_s+"+("+@image.to_s+")i"
+ else
+ @real.to_s+"-("+(-@image).to_s+")i"
+ end
+ else
+ if @image >= 0
+ @real.to_s+"+"+@image.to_s+"i"
+ else
+ @real.to_s+"-"+(-@image).to_s+"i"
+ end
+ end
+ else
+ if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
+ "("+@image.to_s+")i"
+ else
+ @image.to_s+"i"
+ end
+ end
+ end
+
+ def hash
+ @real ^ @image
+ end
+
+ I = Complex(0,1)
+
+ attr :real
+ attr :image
+
+end
+
+class Numeric
+ def im
+ Complex(0, self)
+ end
+
+ def real
+ self
+ end
+
+ def image
+ 0
+ end
+
+ def arg
+ if self >= 0
+ return 0
+ else
+ return Math.atan2(1,1)*4
+ end
+ end
+
+ def polar
+ return abs, arg
+ end
+
+ def conjugate
+ self
+ end
+end
+
+class Fixnum
+ if not defined? Rational
+ alias power! **
+ end
+
+ def ** (other)
+ if self < 0
+ Complex.new(self) ** other
+ else
+ if defined? Rational
+ if other >= 0
+ self.power!(other)
+ else
+ Rational.new!(self,1)**other
+ end
+ else
+ self.power!(other)
+ end
+ end
+ end
+end
+
+class Bignum
+ if not defined? Rational
+ alias power! **
+ end
+end
+
+class Float
+ alias power! **
+end
+
+module Math
+ alias sqrt! sqrt
+ alias exp! exp
+ alias cos! cos
+ alias sin! sin
+ alias tan! tan
+ alias log! log
+ alias log10! log10
+ alias atan2! atan2
+
+ def sqrt(z)
+ if Complex.generic?(z)
+ if z >= 0
+ sqrt!(z)
+ else
+ Complex(0,sqrt!(-z))
+ end
+ else
+ z**Rational(1,2)
+ end
+ end
+
+ def exp(z)
+ if Complex.generic?(z)
+ exp!(z)
+ else
+ Complex(exp!(z.real) * cos!(z.image), exp!(z.real) * sin!(z.image))
+ end
+ end
+
+ def cosh!(x)
+ (exp!(x) + exp!(-x))/2.0
+ end
+
+ def sinh!(x)
+ (exp!(x) - exp!(-x))/2.0
+ end
+
+ def cos(z)
+ if Complex.generic?(z)
+ cos!(z)
+ else
+ Complex(cos!(z.real)*cosh!(z.image),
+ sin!(z.real)*sinh!(z.image))
+ end
+ end
+
+ def sin(z)
+ if Complex.generic?(z)
+ sin!(z)
+ else
+ Complex(sin!(z.real)*cosh!(z.image),
+ -cos!(z.real)*sinh!(z.image))
+ end
+ end
+
+ def tan(z)
+ if Complex.generic?(z)
+ tan!(z)
+ else
+ sin(z)/cos(z)
+ end
+ end
+
+ def log(z)
+ if Complex.generic?(z) and z >= 0
+ log!(z)
+ else
+ r, theta = z.polar
+ Complex(log!(r.abs), theta)
+ end
+ end
+
+ def log10(z)
+ if Complex.generic?(z)
+ log10!(z)
+ else
+ log(z)/log!(10)
+ end
+ end
+
+ def atan2(x, y)
+ if Complex.generic?(x) and Complex.generic?(y)
+ atan2!(x, y)
+ else
+ fail "Not yet implemented."
+ end
+ end
+
+ def atanh!(x)
+ log((1.0 + x.to_f) / ( 1.0 - x.to_f)) / 2.0
+ end
+
+ def atan(z)
+ if Complex.generic?(z)
+ atan2!(z, 1)
+ elsif z.image == 0
+ atan2(z.real,1)
+ else
+ a = z.real
+ b = z.image
+
+ c = (a*a + b*b - 1.0)
+ d = (a*a + b*b + 1.0)
+
+ Complex(atan2!((c + sqrt(c*c + 4.0*a*a)), 2.0*a),
+ atanh!((-d + sqrt(d*d - 4.0*b*b))/(2.0*b)))
+ end
+ end
+
+ module_function :sqrt
+ module_function :sqrt!
+ module_function :exp!
+ module_function :exp
+ module_function :cosh!
+ module_function :cos!
+ module_function :cos
+ module_function :sinh!
+ module_function :sin!
+ module_function :sin
+ module_function :tan!
+ module_function :tan
+ module_function :log!
+ module_function :log
+ module_function :log10!
+ module_function :log
+ module_function :atan2!
+ module_function :atan2
+# module_function :atan!
+ module_function :atan
+ module_function :atanh!
+
+end
+
+
diff --git a/lib/find.rb b/lib/find.rb
index 340461c653..5ecc54329c 100644
--- a/lib/find.rb
+++ b/lib/find.rb
@@ -8,31 +8,32 @@
#
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
+ def find(*path)
+ while file = path.shift
+ catch(:prune) {
+ yield file
+ if File.directory? file and not File.symlink? file then
+ d = Dir.open(file)
+ begin
+ for f in d
+ next if f =~ /^\.\.?$/
+ if file == "/" then
+ f = "/" + f
+ else
+ f = file + "/" + f
+ end
+ path.unshift f
+ end
+ ensure
+ d.close
+ end
+ end
+ }
end
end
- private :findpath
- def find(*path)
- ary = []
- for p in path
- findpath(p, ary)
- for f in ary
- yield f
- end
- end
+ def prune
+ throw :prune
end
- module_function :find
+ module_function :find, :prune
end
diff --git a/lib/getopts.rb b/lib/getopts.rb
index 37fd3dc69d..d25437515d 100644
--- a/lib/getopts.rb
+++ b/lib/getopts.rb
@@ -1,117 +1,142 @@
+#!/usr/local/bin/ruby
#
-# getopts.rb - get options
+# getopts.rb -
# $Release Version: $
-# $Revision: 1.2 $
-# $Date: 1994/02/15 05:17:15 $
-# by Yasuo OHBA(STAFS Development Room)
+# $Revision: 1.1 $
+# $Date: 1996/11/10 05:01:15 $
+# by Yasuo OHBA(SHL Japan Inc. Technology Dept.)
#
# --
-# IvV̉͂, $OPT_?? ɒlZbg܂.
-# ŵȂIvVw肳ꂽ nil Ԃ܂.
-# Iꍇ, ZbgꂽIvV̐Ԃ܂.
#
-# getopts(single_opts, *opts)
-#
-# ex. sample [options] filename
-# options ...
-# -f -x --version --geometry 100x200 -d unix:0.0
-#
-# getopts("fx", "version", "geometry:", "d:")
-#
-# :
-# -f -x (= -fx) ̗lȈꕶ̃IvV̎w܂.
-# ňȂƂ nil ̎w肪Kvł.
-# ȍ~:
-# Ol[̃IvV, ̔IvV̎w܂.
-# --version , --geometry 300x400 , -d host:0.0 ł.
-# 𔺂w ":" KtĂ.
-#
-# IvV̎w肪ꍇ, ϐ $OPT_?? non-nil , ̃I
-# vV̈Zbg܂.
-# -f -> $OPT_f = TRUE
-# --geometry 300x400 -> $OPT_geometry = 300x400
-#
-# - -- , ȍ~, SăIvV̉͂܂.
+#
#
-$RCS_ID="$Header: /var/ohba/RCS/getopts.rb,v 1.2 1994/02/15 05:17:15 ohba Exp ohba $"
+$RCS_ID="$Header: /home/jammy/current/ruby/RCS/getopts.rb,v 1.1 1996/11/10 05:01:15 jammy Exp $"
+
+def isSingle(lopt)
+ if lopt.index(":")
+ if lopt.split(":")[0].length == 1
+ return TRUE
+ end
+ end
+ return nil
+end
+
+def getOptionName(lopt)
+ return lopt.split(":")[0]
+end
+
+def getDefaultOption(lopt)
+ od = lopt.split(":")[1]
+ if od
+ return od
+ end
+ return nil
+end
+
+def setOption(name, value)
+ eval("$OPT_" + name + " = " + 'value')
+end
+
+def setDefaultOption(lopt)
+ d = getDefaultOption(lopt)
+ if d
+ setOption(getOptionName(lopt), d)
+ end
+end
+
+def setNewArgv(newargv)
+ ARGV.clear
+ for na in newargv
+ ARGV << na
+ end
+end
-def getopts(single_opts, *opts)
- if (opts)
+
+def getopts(single_opts, *options)
+ if options
single_colon = ""
long_opts = []
sc = 0
- for option in opts
- if (option.length <= 2)
- single_colon[sc, 0] = option[0, 1]
+ for o in options
+ setDefaultOption(o)
+ if isSingle(o)
+ single_colon[sc, 0] = getOptionName(o)
sc += 1
else
- long_opts.push(option)
+ long_opts.push(o)
end
end
end
-
+
opts = {}
count = 0
- while ($ARGV.length != 0)
+ newargv = []
+ while ARGV.length != 0
compare = nil
- case $ARGV[0]
+ case ARGV[0]
when /^--?$/
- $ARGV.shift
+ ARGV.shift
+ newargv += ARGV
break
when /^--.*/
- compare = $ARGV[0][2, ($ARGV[0].length - 2)]
- if (long_opts != "")
- for option in long_opts
- if (option[(option.length - 1), 1] == ":" &&
- option[0, (option.length - 1)] == compare)
- if ($ARGV.length <= 1)
+ compare = ARGV[0][2, (ARGV[0].length - 2)]
+ if long_opts != ""
+ for lo in long_opts
+ if lo.index(":") && getOptionName(lo) == compare
+ if ARGV.length <= 1
return nil
- end
- eval("$OPT_" + compare + " = " + '$ARGV[1]')
- opts[compare] = TRUE
- $ARGV.shift
+ end
+ setOption(compare, ARGV[1])
+ opts[compare] = TRUE
+ ARGV.shift
count += 1
break
- elsif (option == compare)
- eval("$OPT_" + compare + " = TRUE")
- opts[compare] = TRUE
+ elsif lo == compare
+ setOption(compare, TRUE)
+ opts[compare] = TRUE
count += 1
- break
- end
- end
+ break
+ end
+ end
+ end
+ if compare.length <= 1
+ return nil
end
when /^-.*/
- for index in 1..($ARGV[0].length - 1)
- compare = $ARGV[0][index, 1]
- if (single_opts && compare =~ "[" + single_opts + "]")
- eval("$OPT_" + compare + " = TRUE")
- opts[compare] = TRUE
+ for idx in 1..(ARGV[0].length - 1)
+ compare = ARGV[0][idx, 1]
+ if single_opts && compare =~ "[" + single_opts + "]"
+ setOption(compare, TRUE)
+ opts[compare] = TRUE
count += 1
- elsif (single_colon != "" && compare =~ "[" + single_colon + "]")
- if ($ARGV[0][index..-1].length > 1)
- eval("$OPT_" + compare + " = " + '$ARGV[0][(index + 1)..-1]')
- opts[compare] = TRUE
+ elsif single_colon != "" && compare =~ "[" + single_colon + "]"
+ if ARGV[0][idx..-1].length > 1
+ setOption(compare, ARGV[0][(idx + 1)..-1])
+ opts[compare] = TRUE
count += 1
- elsif ($ARGV.length <= 1)
+ elsif ARGV.length <= 1
return nil
else
- eval("$OPT_" + compare + " = " + '$ARGV[1]')
- opts[compare] = TRUE
- $ARGV.shift
- count = count + 1
+ setOption(compare, ARGV[1])
+ opts[compare] = TRUE
+ ARGV.shift
+ count += 1
end
break
end
end
else
- break
+ compare = ARGV[0]
+ opts[compare] = TRUE
+ newargv << ARGV[0]
end
-
- $ARGV.shift
- if (!opts.includes(compare))
+
+ ARGV.shift
+ if !opts.has_key?(compare)
return nil
end
end
+ setNewArgv(newargv)
return count
end
diff --git a/lib/jcode.rb b/lib/jcode.rb
new file mode 100644
index 0000000000..5b2289932f
--- /dev/null
+++ b/lib/jcode.rb
@@ -0,0 +1,174 @@
+# jcode.rb - ruby code to handle japanese (EUC/SJIS) string
+
+class String
+ printf STDERR, "feel free for some warnings:\n" if $VERBOSE
+
+ alias original_succ succ
+ private :original_succ
+
+ def succ
+ if self[-2] && self[-2] & 0x80 != 0
+ s = self.dup
+ s[-1] += 1
+ return s
+ else
+ original_succ
+ end
+ end
+
+ def upto(to)
+ return if self > to
+
+ curr = self
+ tail = self[-2..-1]
+ if tail.length == 2 and tail =~ /^.$/ then
+ if self[0..-2] == to[0..-2]
+ for c in self[-1] .. to[-1]
+ yield self[0..-2]+c.chr
+ end
+ end
+ else
+ loop do
+ yield curr
+ return if curr == to
+ curr = curr.succ
+ return if curr.length > to.length
+ end
+ end
+ return nil
+ end
+
+ def _expand_ch
+ a = []
+ self.scan(/(.|\n)-(.|\n)|(.|\n)/) do |r|
+ if $3
+ a.push $3
+ elsif $1.length != $2.length
+ next
+ elsif $1.length == 1
+ $1[0].upto($2[0]) { |c| a.push c.chr }
+ else
+ $1.upto($2) { |c| a.push c }
+ end
+ end
+ a
+ end
+
+ def tr!(from, to)
+ return self.delete!(from) if to.length == 0
+
+ if from =~ /^\^/
+ comp=TRUE
+ from = $'
+ end
+ afrom = from._expand_ch
+ ato = to._expand_ch
+ i = 0
+ if comp
+ self.gsub!(/(.|\n)/) do |c|
+ unless afrom.include?(c)
+ ato[-1]
+ else
+ c
+ end
+ end
+ else
+ self.gsub!(/(.|\n)/) do |c|
+ if i = afrom.index(c)
+ if i < ato.size then ato[i] else ato[-1] end
+ else
+ c
+ end
+ end
+ end
+ end
+
+ def tr(from, to)
+ self.dup.tr!(from, to)
+ end
+
+ def delete!(del)
+ if del =~ /^\^/
+ comp=TRUE
+ del = $'
+ end
+ adel = del._expand_ch
+ if comp
+ self.gsub!(/(.|\n)/) do |c|
+ next unless adel.include?(c)
+ c
+ end
+ else
+ self.gsub!(/(.|\n)/) do |c|
+ next if adel.include?(c)
+ c
+ end
+ end
+ end
+
+ def delete(del)
+ self.dup.delete!(del)
+ end
+
+ def squeeze!(del=nil)
+ if del
+ if del =~ /^\^/
+ comp=TRUE
+ del = $'
+ end
+ adel = del._expand_ch
+ if comp
+ self.gsub!(/(.|\n)\1+/) do
+ next unless adel.include?($1)
+ $&
+ end
+ else
+ for c in adel
+ cq = Regexp.quote(c)
+ self.gsub!(/#{cq}(#{cq})+/, cq)
+ end
+ end
+ self
+ else
+ self.gsub!(/(.|\n)\1+/, '\1')
+ end
+ end
+
+ def squeeze(del=nil)
+ self.dup.squeeze!(del)
+ end
+
+ def tr_s!(from, to)
+ return self.delete!(from) if to.length == 0
+ if from =~ /^\^/
+ comp=TRUE
+ from = $'
+ end
+ afrom = from._expand_ch
+ ato = to._expand_ch
+ i = 0
+ c = nil
+ last = nil
+ self.gsub!(/(.|\n)/) do |c|
+ if comp
+ unless afrom.include?(c)
+ ato[-1]
+ else
+ c
+ end
+ elsif i = afrom.index(c)
+ c = if i < ato.size then ato[i] else ato[-1] end
+ next if c == last
+ last = c
+ else
+ last = nil
+ c
+ end
+ end
+ end
+
+ def tr_s(from, to)
+ self.dup.tr_s!(from,to)
+ end
+
+end
diff --git a/lib/mailread.rb b/lib/mailread.rb
index 4b04445beb..d9feffbb7a 100644
--- a/lib/mailread.rb
+++ b/lib/mailread.rb
@@ -1,9 +1,8 @@
class Mail
-
def Mail.new(f)
- if !f.is_kind_of?(IO)
+ unless f.kind_of?(IO)
f = open(f, "r")
- me = super
+ me = super(f)
f.close
else
me = super
@@ -16,17 +15,18 @@ class Mail
@body = []
while f.gets()
$_.chop!
- continue if /^From / # skip From-line
+ next if /^From / # skip From-line
break if /^$/ # end of header
+
if /^(\S+):\s*(.*)/
- @header[attr = $1.capitalize] = $2
+ @header[attr = $1.capitalize!] = $2
elsif attr
- sub(/^\s*/, '')
+ sub!(/^\s*/, '')
@header[attr] += "\n" + $_
end
end
-
- return if ! $_
+
+ return unless $_
while f.gets()
break if /^From /
@@ -42,4 +42,7 @@ class Mail
return @body
end
+ def [](field)
+ @header[field]
+ end
end
diff --git a/lib/mathn.rb b/lib/mathn.rb
new file mode 100644
index 0000000000..359cb45769
--- /dev/null
+++ b/lib/mathn.rb
@@ -0,0 +1,307 @@
+#
+# mathn.rb -
+# $Release Version: 0.5 $
+# $Revision: 1.1 $
+# $Date: 1996/11/11 04:25:24 $
+# by Keiju ISHITSUKA(SHL Japan Inc.)
+#
+# --
+#
+#
+#
+
+require "rational.rb"
+require "complex.rb"
+
+class Integer
+
+ def gcd2(int)
+ a = self.abs
+ b = int.abs
+ a, b = b, a if a < b
+
+ pd_a = a.prime_division
+ pd_b = b.prime_division
+
+ gcd = 1
+ for pair in pd_a
+ as = pd_b.assoc(pair[0])
+ if as
+ gcd *= as[0] ** [as[1], pair[1]].min
+ end
+ end
+ return gcd
+ end
+
+ def Integer.from_prime_division(pd)
+ value = 1
+ for prime, index in pd
+ value *= prime**index
+ end
+ value
+ end
+
+ def prime_division
+ ps = Prime.new
+ value = self
+ pv = []
+ for prime in ps
+ count = 0
+ while (value1, mod = value.divmod(prime)
+ mod) == 0
+ value = value1
+ count += 1
+ end
+ if count != 0
+ pv.push [prime, count]
+ end
+ break if prime * prime >= value
+ end
+ if value > 1
+ pv.push [value, 1]
+ end
+ return pv
+ end
+end
+
+class Prime
+ include Enumerable
+
+ def initialize
+ @seed = 1
+ @primes = []
+ @counts = []
+ end
+
+ def succ
+ i = -1
+ size = @primes.size
+ while i < size
+ if i == -1
+ @seed += 1
+ i += 1
+ else
+ while @seed > @counts[i]
+ @counts[i] += @primes[i]
+ end
+ if @seed != @counts[i]
+ i += 1
+ else
+ i = -1
+ end
+ end
+ end
+ @primes.push @seed
+ @counts.push @seed + @seed
+ return @seed
+ end
+
+ def each
+ loop do
+ yield succ
+ end
+ end
+end
+
+class Fixnum
+ alias divmod! divmod
+ alias / rdiv
+ def divmod(other)
+ a = self.div(other)
+ b = self % other
+ return a,b
+ end
+end
+
+class Bignum
+ alias divmod! divmod
+ alias / rdiv
+end
+
+class Rational
+ Unify = TRUE
+
+ alias power! **
+
+ def ** (other)
+ if other.kind_of?(Rational)
+ if self < 0
+ return Complex(self, 0) ** other
+ elsif other == 0
+ return Rational(1,1)
+ elsif self == 0
+ return Rational(0,1)
+ elsif self == 1
+ return Rational(1,1)
+ end
+
+ npd = @numerator.prime_division
+ dpd = @denominator.prime_division
+ if other < 0
+ other = -other
+ npd, dpd = dpd, npd
+ end
+
+ for elm in npd
+ elm[1] = elm[1] * other
+ if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
+ return Float(self) ** other
+ end
+ elm[1] = elm[1].to_i
+ end
+
+ for elm in dpd
+ elm[1] = elm[1] * other
+ if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
+ return Float(self) ** other
+ end
+ elm[1] = elm[1].to_i
+ end
+
+ num = Integer.from_prime_division(npd)
+ den = Integer.from_prime_division(dpd)
+
+ Rational(num,den)
+
+ elsif other.kind_of?(Integer)
+ if other > 0
+ num = @numerator ** other
+ den = @denominator ** other
+ elsif other < 0
+ num = @denominator ** -other
+ den = @numerator ** -other
+ elsif other == 0
+ num = 1
+ den = 1
+ end
+ Rational.new!(num, den)
+ elsif other.kind_of?(Float)
+ Float(self) ** other
+ else
+ x , y = other.coerce(self)
+ x ** y
+ end
+ end
+
+ def power2(other)
+ if other.kind_of?(Rational)
+ if self < 0
+ return Complex(self, 0) ** other
+ elsif other == 0
+ return Rational(1,1)
+ elsif self == 0
+ return Rational(0,1)
+ elsif self == 1
+ return Rational(1,1)
+ end
+
+ dem = nil
+ x = self.denominator.to_f.to_i
+ neard = self.denominator.to_f ** (1.0/other.denominator.to_f)
+ loop do
+ if (neard**other.denominator == self.denominator)
+ dem = neaed
+ break
+ end
+ end
+ nearn = self.numerator.to_f ** (1.0/other.denominator.to_f)
+ Rational(num,den)
+
+ elsif other.kind_of?(Integer)
+ if other > 0
+ num = @numerator ** other
+ den = @denominator ** other
+ elsif other < 0
+ num = @denominator ** -other
+ den = @numerator ** -other
+ elsif other == 0
+ num = 1
+ den = 1
+ end
+ Rational.new!(num, den)
+ elsif other.kind_of?(Float)
+ Float(self) ** other
+ else
+ x , y = other.coerce(self)
+ x ** y
+ end
+ end
+end
+
+module Math
+ def sqrt(a)
+ if a.kind_of?(Complex)
+ abs = sqrt(a.real*a.real + a.image*a.image)
+# if not abs.kind_of?(Rational)
+# return a**Rational(1,2)
+# end
+ x = sqrt((a.real + abs)/Rational(2))
+ y = sqrt((-a.real + abs)/Rational(2))
+# if !(x.kind_of?(Rational) and y.kind_of?(Rational))
+# return a**Rational(1,2)
+# end
+ if a.image >= 0
+ Complex(x, y)
+ else
+ Complex(x, -y)
+ end
+ elsif a >= 0
+ rsqrt(a)
+ else
+ Complex(0,rsqrt(-a))
+ end
+ end
+
+ def rsqrt(a)
+ if a.kind_of?(Float)
+ sqrt!(a)
+ elsif a.kind_of?(Rational)
+ rsqrt(a.numerator)/rsqrt(a.denominator)
+ else
+ src = a
+ max = 2 ** 32
+ byte_a = [src & 0xffffffff]
+ # ruby's bug
+ while (src >= max) and (src >>= 32)
+ byte_a.unshift src & 0xffffffff
+ end
+
+ answer = 0
+ main = 0
+ side = 0
+ for elm in byte_a
+ main = (main << 32) + elm
+ side <<= 16
+ if answer != 0
+ if main * 4 < side * side
+ applo = main.div(side)
+ else
+ applo = ((sqrt!(side * side + 4 * main) - side)/2.0).to_i + 1
+ end
+ else
+ applo = sqrt!(main).to_i + 1
+ end
+
+ while (x = (side + applo) * applo) > main
+ applo -= 1
+ end
+ main -= x
+ answer = (answer << 16) + applo
+ side += applo * 2
+ end
+ if main == 0
+ answer
+ else
+ sqrt!(a)
+ end
+ end
+ end
+
+ module_function :sqrt
+ module_function :rsqrt
+end
+
+class Complex
+ Unify = TRUE
+end
+
diff --git a/lib/observer.rb b/lib/observer.rb
new file mode 100644
index 0000000000..9a753939a2
--- /dev/null
+++ b/lib/observer.rb
@@ -0,0 +1,40 @@
+# Observable Mixin
+#
+# Observers must respond to update
+
+module Observable
+ def add_observer(observer)
+ @observer_peers = [] unless @observer_peers
+ unless defined? observer.update
+ raise NameError, "observer needs to respond to `update'"
+ end
+ @observer_peers.push observer
+ end
+ def delete_observer(observer)
+ @observer_peers.delete observer if @observer_peers
+ end
+ def delete_observers
+ @observer_peers.clear if @observer_peers
+ end
+ def count_observers
+ if @observer_peers
+ @observer_peers.size
+ else
+ 0
+ end
+ end
+ def changed(state=TRUE)
+ @observer_state = state
+ end
+ def changed?
+ @observer_state
+ end
+ def notify_observers(*arg)
+ if @observer_state
+ for i in @observer_peers
+ i.update(*arg)
+ end
+ @observer_state = FALSE
+ end
+ end
+end
diff --git a/lib/parsearg.rb b/lib/parsearg.rb
index e7e2b7a7f3..569ed260f7 100644
--- a/lib/parsearg.rb
+++ b/lib/parsearg.rb
@@ -1,68 +1,83 @@
+#!/usr/local/bin/ruby
#
-# parseargs.rb - parse arguments
+# parsearg.rb - parse arguments
# $Release Version: $
# $Revision: 1.3 $
-# $Date: 1994/02/15 05:16:21 $
-# by Yasuo OHBA(STAFS Development Room)
+# $Date: 1996/11/12 06:48:51 $
+# by Yasuo OHBA(SHL Japan Inc. Technology Dept.)
#
# --
-# ̉͂, $OPT_?? ɒlZbg܂.
-# Iꍇ, ZbgꂽIvV̐Ԃ܂.
#
-# parseArgs(argc, single_opts, *opts)
-#
-# ex. sample [options] filename
-# options ...
-# -f -x --version --geometry 100x200 -d unix:0.0
-#
-# parseArgs(1, nil, "fx", "version", "geometry:", "d:")
-#
-# :
-# IvVȊO̍Œ̐
-# :
-# IvV̕KvcKKvȂ %TRUE łȂ %FALSE.
-# O:
-# -f -x (= -fx) ̗lȈꕶ̃IvV̎w܂.
-# ňȂƂ nil ̎w肪Kvł.
-# lȍ~:
-# Ol[̃IvV, ̔IvV̎w܂.
-# --version , --geometry 300x400 , -d host:0.0 ł.
-# 𔺂w ":" KtĂ.
-#
-# IvV̎w肪ꍇ, ϐ $OPT_?? non-nil , ̃I
-# vV̈Zbg܂.
-# -f -> $OPT_f = %TRUE
-# --geometry 300x400 -> $OPT_geometry = 300x400
-#
-# usage gꍇ, $USAGE usage() w肵܂.
-# def usage()
-# c
-# end
-# $USAGE = 'usage'
-# usage , --help w肳ꂽ, Ԉwɕ\܂.
-#
-# - -- , ȍ~, SăIvV̉͂܂.
+#
#
-$RCS_ID="$Header: /var/ohba/RCS/parseargs.rb,v 1.3 1994/02/15 05:16:21 ohba Exp ohba $"
+$RCS_ID="$Header: /home/jammy/current/ruby/RCS/parsearg.rb,v 1.3 1996/11/12 06:48:51 jammy Exp $"
load("getopts.rb")
def printUsageAndExit()
if $USAGE
- apply($USAGE)
+ eval($USAGE)
end
exit()
end
+def setParenthesis(ex, opt, c)
+ if opt != ""
+ ex = sprintf("%s$OPT_%s%s", ex, opt, c)
+ else
+ ex = sprintf("%s%s", ex, c)
+ end
+ return ex
+end
+
+def setOrAnd(ex, opt, c)
+ if opt != ""
+ ex = sprintf("%s$OPT_%s %s%s ", ex, opt, c, c)
+ else
+ ex = sprintf("%s %s%s ", ex, c, c)
+ end
+ return ex
+end
+
+def setExpression(ex, opt, op)
+ if !op
+ ex = sprintf("%s$OPT_%s", ex, opt)
+ return ex
+ end
+ case op.chr
+ when "(", ")"
+ ex = setParenthesis(ex, opt, op.chr)
+ when "|", "&"
+ ex = setOrAnd(ex, opt, op.chr)
+ else
+ return nil
+ end
+ return ex
+end
+
def parseArgs(argc, nopt, single_opts, *opts)
- if ((noOptions = getopts(single_opts, *opts)) == nil)
+ if (noOptions = getopts(single_opts, *opts)) == nil
printUsageAndExit()
end
- if (nopt && noOptions == 0)
- printUsageAndExit()
+ if nopt
+ ex = nil
+ pos = 0
+ for o in nopt.split(/[()|&]/)
+ pos += o.length
+ ex = setExpression(ex, o, nopt[pos])
+ pos += 1
+ end
+ begin
+ if !eval(ex)
+ printUsageAndExit()
+ end
+ rescue
+ print "Format Error!! : \"" + nopt + "\"\t[parseArgs]\n"
+ exit! -1
+ end
end
- if ($ARGV.length < argc)
+ if ARGV.length < argc
printUsageAndExit()
end
return noOptions
diff --git a/lib/rational.rb b/lib/rational.rb
new file mode 100644
index 0000000000..d4112c2956
--- /dev/null
+++ b/lib/rational.rb
@@ -0,0 +1,361 @@
+#
+# rational.rb -
+# $Release Version: 0.5 $
+# $Revision: 1.1 $
+# $Date: 1996/11/11 04:25:14 $
+# by Keiju ISHITSUKA(SHL Japan Inc.)
+#
+# --
+# Usage:
+# class Rational < Numeric
+# (include Compareable)
+#
+# Rational(a, b) --> a/b
+#
+# Rational::+
+# Rational::-
+# Rational::*
+# Rational::/
+# Rational::**
+# Rational::%
+# Rational::divmod
+# Rational::abs
+# Rational::<=>
+# Rational::to_i
+# Rational::to_f
+# Rational::to_s
+#
+# Integer::gcd
+# Integer::lcm
+# Integer::gcdlcm
+# Integer::to_r
+#
+# Fixnum::**
+# Bignum::**
+#
+#
+
+def Rational(a, b = 1)
+ if a.kind_of?(Rational) && b == 1
+ a
+ else
+ Rational.reduce(a, b)
+ end
+end
+
+class Rational < Numeric
+ def Rational.reduce(num, den = 1)
+ if den < 0
+ num = -num
+ den = -den
+ end
+ gcd = num.gcd(den)
+ num = num.div(gcd)
+ den = den.div(gcd)
+ if den == 1 && defined?(Unify)
+ num
+ else
+ new!(num, den)
+ end
+ end
+
+ def Rational.new!(num, den = 1)
+ new(num, den)
+ end
+
+ def initialize(num, den)
+ if den < 0
+ num = -num
+ den = -den
+ end
+ if num.kind_of?(Integer) and den.kind_of?(Integer)
+ @numerator = num
+ @denominator = den
+ else
+ @numerator = num.to_i
+ @denoninator = den.to_i
+ end
+ end
+
+ def + (a)
+ if a.kind_of?(Rational)
+ num = @numerator * a.denominator
+ num_a = a.numerator * @denominator
+ Rational(num + num_a, @denominator * a.denominator)
+ elsif a.kind_of?(Integer)
+ self + Rational.new!(a, 1)
+ elsif a.kind_of?(Float)
+ Float(self) + a
+ else
+ x , y = a.coerce(self)
+ x + y
+ end
+ end
+
+ def - (a)
+ if a.kind_of?(Rational)
+ num = @numerator * a.denominator
+ num_a = a.numerator * @denominator
+ Rational(num - num_a, @denominator*a.denominator)
+ elsif a.kind_of?(Integer)
+ self - Rational.new!(a, 1)
+ elsif a.kind_of?(Float)
+ Float(self) - a
+ else
+ x , y = a.coerce(self)
+ x - y
+ end
+ end
+
+ def * (a)
+ if a.kind_of?(Rational)
+ num = @numerator * a.numerator
+ den = @denominator * a.denominator
+ Rational(num, den)
+ elsif a.kind_of?(Integer)
+ self * Rational.new!(a, 1)
+ elsif a.kind_of?(Float)
+ Float(self) * a
+ else
+ x , y = a.coerce(self)
+ x * y
+ end
+ end
+
+ def / (a)
+ if a.kind_of?(Rational)
+ num = @numerator * a.denominator
+ den = @denominator * a.numerator
+ Rational(num, den)
+ elsif a.kind_of?(Integer)
+ self / Rational.new!(a, 1)
+ elsif a.kind_of?(Float)
+ Float(self) / a
+ else
+ x , y = a.coerce(self)
+ x / y
+ end
+ end
+
+ def ** (other)
+ if other.kind_of?(Rational)
+ Float(self) ** other
+ elsif other.kind_of?(Integer)
+ if other > 0
+ num = @numerator ** other
+ den = @denominator ** other
+ elsif other < 0
+ num = @denominator ** -other
+ den = @numerator ** -other
+ elsif other == 0
+ num = 1
+ den = 1
+ end
+ Rational.new!(num, den)
+ elsif other.kind_of?(Float)
+ Float(self) ** other
+ else
+ x , y = other.coerce(self)
+ x ** y
+ end
+ end
+
+ def % (other)
+ value = (self / other).to_i
+ return self - other * value
+ end
+
+ def divmod(other)
+ value = (self / other).to_i
+ return value, self - other * value
+ end
+
+ def abs
+ if @numerator > 0
+ Rational.new!(@numerator, @denominator)
+ else
+ Rational.new!(-@numerator, @denominator)
+ end
+ end
+
+ def <=> (other)
+ if other.kind_of?(Rational)
+ num = @numerator * other.denominator
+ num_a = other.numerator * @denominator
+ v = num - num_a
+ if v > 0
+ return 1
+ elsif v < 0
+ return -1
+ else
+ return 0
+ end
+ elsif other.kind_of?(Integer)
+ return self <=> Rational.new!(other, 1)
+ elsif other.kind_of?(Float)
+ return Float(self) <=> other
+ else
+ x , y = other.coerce(self)
+ return x <=> y
+ end
+ end
+
+ def coerce(other)
+ if other.kind_of?(Float)
+ return other, self.to_f
+ elsif other.kind_of?(Integer)
+ return Rational.new!(other, 1), self
+ else
+ super
+ end
+ end
+
+ def to_i
+ Integer(@numerator.div(@denominator))
+ end
+
+ def to_f
+ @numerator.to_f/@denominator.to_f
+ end
+
+ def to_s
+ if @denominator == 1
+ @numerator.to_s
+ else
+ @numerator.to_s+"/"+@denominator.to_s
+ end
+ end
+
+ def to_r
+ self
+ end
+
+ def hash
+ @numerator ^ @denominator
+ end
+
+ attr :numerator
+ attr :denominator
+
+ private :initialize
+end
+
+class Integer
+ def numerator
+ self
+ end
+
+ def denomerator
+ 1
+ end
+
+ def to_r
+ Rational(self, 1)
+ end
+
+ def gcd(int)
+ a = self.abs
+ b = int.abs
+
+ a, b = b, a if a < b
+
+ while b != 0
+ void, a = a.divmod(b)
+ a, b = b, a
+ end
+ return a
+ end
+
+ def lcm(int)
+ a = self.abs
+ b = int.abs
+ gcd = a.gcd(b)
+ (a.div(gcd)) * b
+ end
+
+ def gcdlcm(int)
+ a = self.abs
+ b = int.abs
+ gcd = a.gcd(b)
+ return gcd, (a.div(gcd)) * b
+ end
+
+end
+
+class Fixnum
+ alias div! /;
+ def div(other)
+ if other.kind_of?(Fixnum)
+ self.div!(other)
+ elsif other.kind_of?(Bignum)
+ x, y = other.coerce(self)
+ x.div!(y)
+ else
+ x, y = other.coerce(self)
+ x / y
+ end
+ end
+
+# alias divmod! divmod
+
+ if not defined? Complex
+ alias power! **;
+ end
+
+# def rdiv(other)
+# if other.kind_of?(Fixnum)
+# Rational(self, other)
+# elsif
+# x, y = other.coerce(self)
+# if defined?(x.div())
+# x.div(y)
+# else
+# x / y
+# end
+# end
+ # end
+
+ def rdiv(other)
+ Rational.new!(self,1) / other
+ end
+
+ def rpower (other)
+ if other >= 0
+ self.power!(other)
+ else
+ Rational.new!(self,1)**other
+ end
+ end
+
+ if not defined? Complex
+ alias ** rpower
+ end
+end
+
+class Bignum
+ alias div! /;
+ alias div /;
+ alias divmod! divmod
+
+ if not defined? power!
+ alias power! **
+ end
+
+ def rdiv(other)
+ Rational.new!(self,1) / other
+ end
+
+ def rpower (other)
+ if other >= 0
+ self.power!(other)
+ else
+ Rational.new!(self, 1)**other
+ end
+ end
+
+ if not defined? Complex
+ alias ** rpower
+ end
+
+end
+
diff --git a/lib/safe.rb b/lib/safe.rb
new file mode 100644
index 0000000000..7c95555495
--- /dev/null
+++ b/lib/safe.rb
@@ -0,0 +1,78 @@
+# this is a safe-mode for ruby, which is still incomplete.
+
+unless defined? SecurityError
+ class SecurityError<Exception
+ end
+end
+
+module Restricted
+
+ printf STDERR, "feel free for some warnings:\n" if $VERBOSE
+ module Bastion
+ include Restricted
+ extend Restricted
+ BINDING = binding
+ def Bastion.to_s; "main" end
+ end
+
+ class R_File<File
+ NG_FILE_OP = []
+ def R_File.open(*args)
+ raise SecurityError, "can't use File.open() in safe mode" #'
+ end
+ end
+
+ IO = nil
+ File = R_File
+ FileTest = nil
+ Dir = nil
+ ObjectSpace = nil
+
+ def eval(string)
+ begin
+ super(string, Bastion::BINDING)
+ rescue
+ $@ = caller
+ raise
+ end
+ end
+ module_function :eval
+
+ DEFAULT_SECURITY_MANAGER = Object.new
+
+ def Restricted.set_securuty_manager(sec_man)
+ if @sec_man
+ raise SecurityError, "cannot change security manager"
+ end
+ @sec_man = sec_man
+ end
+
+ def Restricted.securuty_manager
+ return @sec_man if @sec_man
+ return DEFAULT_SECURITY_MANAGER
+ end
+
+ for cmd in ["test", "require", "load", "open", "system"]
+ eval format("def DEFAULT_SECURITY_MANAGER.%s(*args)
+ raise SecurityError, \"can't use %s() in safe mode\"
+ end", cmd, cmd) #'
+ eval format("def %s(*args)
+ Restricted.securuty_manager.%s(*args)
+ end", cmd, cmd)
+ end
+
+ def `(arg) #`
+ Restricted.securuty_manager.send(:`, arg) #`)
+ end
+
+ def DEFAULT_SECURITY_MANAGER.`(arg) #`
+ raise SecurityError, "can't use backquote(``) in safe mode"
+ end
+end
+
+if $DEBUG
+ p eval("File.open('/dev/null')")
+ p Restricted.eval("self")
+ p Restricted.eval("open('/dev/null')")
+ p Restricted.eval("File.open('/dev/null')")
+end
diff --git a/lib/thread.rb b/lib/thread.rb
new file mode 100644
index 0000000000..c3347b60b4
--- /dev/null
+++ b/lib/thread.rb
@@ -0,0 +1,153 @@
+#
+# thread.rb - thread support classes
+# $Date: 1996/05/21 09:29:21 $
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+#
+
+unless defined? Thread
+ fail "Thread not available for this ruby interpreter"
+end
+
+unless defined? ThreadError
+ class ThreadError<Exception
+ end
+end
+
+class Mutex
+ def initialize
+ @waiting = []
+ @locked = FALSE;
+ end
+
+ def locked?
+ @locked
+ end
+
+ def try_lock
+ Thread.exclusive do
+ if not @locked
+ @locked=TRUE
+ return TRUE
+ end
+ end
+ FALSE
+ end
+
+ def lock
+ while not try_lock
+ @waiting.push Thread.current
+ Thread.stop
+ end
+ end
+
+ def unlock
+ @locked = FALSE
+ if w = @waiting.shift
+ w.run
+ end
+ end
+
+ def synchronize
+ begin
+ lock
+ yield
+ ensure
+ unlock
+ end
+ end
+end
+
+class SharedMutex<Mutex
+ def initialize
+ @locking = nil
+ @num_locks = 0;
+ super
+ end
+ def try_lock
+ if @locking == Thread.current
+ @num_locks += 1
+ return TRUE
+ end
+ if super
+ @num_locks = 1
+ @locking = Thread.current
+ TRUE
+ else
+ FALSE
+ end
+ end
+ def unlock
+ unless @locking == Thread.current
+ raise ThreadError, "cannot release shared mutex"
+ end
+ @num_locks -= 1
+ if @num_locks == 0
+ @locking = nil
+ super
+ end
+ end
+end
+
+class Queue
+ def initialize
+ @que = []
+ @waiting = []
+ end
+
+ def push(obj)
+ @que.push obj
+ if t = @waiting.shift
+ t.run
+ end
+ end
+
+ def pop non_block=FALSE
+ if @que.length == 0
+ raise ThreadError, "queue empty" if non_block
+ @waiting.push Thread.current
+ Thread.stop
+ end
+ @que.shift
+ end
+
+ def empty?
+ @que.length == 0
+ end
+
+ def length
+ @que.length
+ end
+end
+
+class Condition
+ def initialize
+ @waiting = []
+ end
+
+ def wait(mut)
+ Thread.exclusive do
+ mut.unlock
+ @waiting.push Thread.current
+ end
+ Thread.sleep
+ mut.lock
+ end
+
+ def signal
+ th = nil
+ Thread.exclusive do
+ th = @waiting.pop
+ end
+ th.run
+ end
+
+ def broadcast
+ w = @waiting
+ Thread.exclusive do
+ th = []
+ end
+ for th in w
+ th.run
+ end
+ end
+end
diff --git a/lib/tk.rb b/lib/tk.rb
index 9c61269881..5a725aac11 100644
--- a/lib/tk.rb
+++ b/lib/tk.rb
@@ -3,477 +3,10 @@
# $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
+if defined? Thread and $tk_thread_safe
+ require "tkthcore"
+else
+ require "tkcore"
end
module TkSelection
@@ -550,11 +83,11 @@ module TkWinfo
def winfo_depth(window)
TkWinfo.depth self
end
- def TkWinfo.exists(window)
+ def TkWinfo.exist?(window)
bool(tk_call('winfo', 'exists', window.path))
end
- def winfo_exists(window)
- TkWinfo.exists self
+ def winfo_exist?(window)
+ TkWinfo.exist? self
end
def TkWinfo.fpixels(window, number)
number(tk_call('winfo', 'fpixels', window.path, number))
@@ -580,11 +113,11 @@ module TkWinfo
def winfo_id(window)
TkWinfo.id self
end
- def TkWinfo.ismapped(window)
+ def TkWinfo.mapped?(window)
bool(tk_call('winfo', 'ismapped', window.path))
end
- def winfo_ismapped(window)
- TkWinfo.ismapped self
+ def winfo_mapped?(window)
+ TkWinfo.mapped? self
end
def TkWinfo.parent(window)
window(tk_call('winfo', 'parent', window.path))
@@ -742,7 +275,7 @@ module TkPack
include Tk
extend Tk
def configure(win, *args)
- if args[-1].is_kind_of(Hash)
+ if args[-1].kind_of?(Hash)
keys = args.pop
end
wins = [win.epath]
@@ -780,7 +313,7 @@ module TkOption
module_function :add, :clear, :get, :readfile
end
-class TkObject:TkKernel
+class TkObject<TkKernel
include Tk
def path
@@ -822,16 +355,16 @@ class TkObject:TkKernel
configure slot, install_cmd(value)
end
- def bind(context, cmd=Proc.new)
- _bind path, context, cmd
+ def bind(context, cmd=Proc.new, args=nil)
+ _bind path, context, cmd, args
end
end
-class TkWindow:TkObject
+class TkWindow<TkObject
$tk_window_id = "w00000"
def initialize(parent=nil, keys=nil)
id = $tk_window_id
- $tk_window_id = $tk_window_id.next
+ $tk_window_id = $tk_window_id.succ
if !parent or parent == Tk.root
@path = format(".%s", id);
else
@@ -880,7 +413,7 @@ class TkWindow:TkObject
return val
end
else
- fail 'wrong # of args'
+ fail ArgumentError, 'wrong # of args'
end
end
@@ -913,7 +446,7 @@ class TkWindow:TkObject
end
end
-class TkRoot:TkWindow
+class TkRoot<TkWindow
include Wm
def TkRoot.new
return $tk_root if $tk_root
@@ -926,7 +459,7 @@ class TkRoot:TkWindow
$tk_window_list['.'] = $tk_root
end
-class TkToplevel:TkWindow
+class TkToplevel<TkWindow
include Wm
def initialize(parent=nil, screen=nil, classname=nil)
@screen = screen if screen
@@ -942,20 +475,21 @@ class TkToplevel:TkWindow
end
end
-class TkFrame:TkWindow
+class TkFrame<TkWindow
def create_self
tk_call 'frame', @path
end
end
-class TkLabel:TkWindow
+class TkLabel<TkWindow
def create_self
tk_call 'label', @path
end
def textvariable(v)
- vn = @path + v.id2name
+ v = v.id2name unless v.kind_of "String"
+ vn = @path + v
vset = format("global {%s}; set {%s}", vn, vn)
- tk_call vset, eval(v.id2name).inspect
+ tk_call vset, eval(v).inspect
trace_var v, proc{|val|
tk_call vset, val.inspect
}
@@ -963,7 +497,7 @@ class TkLabel:TkWindow
end
end
-class TkButton:TkLabel
+class TkButton<TkLabel
def create_self
tk_call 'button', @path
end
@@ -975,7 +509,7 @@ class TkButton:TkLabel
end
end
-class TkRadioButton:TkButton
+class TkRadioButton<TkButton
def create_self
tk_call 'radiobutton', @path
end
@@ -986,8 +520,13 @@ class TkRadioButton:TkButton
tk_send 'select'
end
def variable(v)
- vn = v.id2name; vn =~ /^./
- vn = 'btns_selected_' + $'
+ v = v.id2name unless v.kind_of "String"
+ if v =~ /^\$/
+ v = $'
+ else
+ fail ArgumentError, "variable must be global(%s)", v
+ end
+ vn = 'btns_selected_' + v
trace_var v, proc{|val|
tk_call 'set', vn, val
}
@@ -1004,7 +543,7 @@ class TkRadioButton:TkButton
end
end
-class TkCheckButton:TkRadioButton
+class TkCheckButton<TkRadioButton
def create_self
tk_call 'checkbutton', @path
end
@@ -1013,13 +552,13 @@ class TkCheckButton:TkRadioButton
end
end
-class TkMessage:TkLabel
+class TkMessage<TkLabel
def create_self
tk_call 'message', @path
end
end
-class TkScale:TkWindow
+class TkScale<TkWindow
def create_self
tk_call 'scale', path
end
@@ -1041,11 +580,23 @@ class TkScale:TkWindow
end
end
-class TkScrollbar:TkWindow
+class TkScrollbar<TkWindow
def create_self
tk_call 'scrollbar', path
end
+ def delta(deltax=None, deltay=None)
+ number(tk_send('delta', deltax, deltay))
+ end
+
+ def fraction(x=None, y=None)
+ number(tk_send('fraction', x, y))
+ end
+
+ def identify(x=None, y=None)
+ tk_send('fraction', x, y)
+ end
+
def get
ary1 = tk_send('get', path).split
ary2 = []
@@ -1061,7 +612,7 @@ class TkScrollbar:TkWindow
end
# abstract class for Text and Listbox
-class TkTextWin:TkWindow
+class TkTextWin<TkWindow
def bbox(index)
tk_send 'bbox', index
end
@@ -1091,7 +642,7 @@ class TkTextWin:TkWindow
end
end
-class TkListbox:TkTextWin
+class TkListbox<TkTextWin
def create_self
tk_call 'listbox', path
end
@@ -1119,7 +670,7 @@ class TkListbox:TkTextWin
end
end
-class TkMenu:TkWindow
+class TkMenu<TkWindow
def create_self
tk_call 'menu', path
end
@@ -1158,7 +709,7 @@ class TkMenu:TkWindow
end
end
-class TkMenubutton:TkLabel
+class TkMenubutton<TkLabel
def create_self
tk_call 'menubutton', path
end
@@ -1181,7 +732,7 @@ module TkComposite
def delegate(option, *wins)
@delegates = {} if not @delegates
@delegates['DEFAULT'] = @frame
- if option.is_kind_of? String
+ if option.kind_of? String
@delegates[option] = wins
else
for i in option
diff --git a/lib/tkcanvas.rb b/lib/tkcanvas.rb
index 33b28e3eff..b0ae8b1daa 100644
--- a/lib/tkcanvas.rb
+++ b/lib/tkcanvas.rb
@@ -5,12 +5,12 @@
require "tk"
-class TkCanvas:TkWindow
+class TkCanvas<TkWindow
def create_self
tk_call 'canvas', path
end
def tagid(tag)
- if tag.is_kind_of?(TkcItem)
+ if tag.kind_of?(TkcItem)
tag.id
else
tag
@@ -89,6 +89,9 @@ class TkCanvas:TkWindow
def move(tag, x, y)
tk_send 'move', tagid(tag), x, y
end
+ def itemtype(tag)
+ tk_send 'type', tagid(tag)
+ end
def postscript(keys=None)
tk_call "pack", *hash_kv(keys)
end
@@ -115,9 +118,9 @@ class TkCanvas:TkWindow
end
end
-class TkcItem:TkObject
+class TkcItem<TkObject
def initialize(parent, *args)
- if not parent.is_kind_of?(TkCanvas)
+ if not parent.kind_of?(TkCanvas)
fail format("%s need to be TkCanvas", parent.inspect)
end
@c = parent
@@ -137,7 +140,7 @@ class TkcItem:TkObject
end
def configure(slot, value)
- tk_call path, 'itemconfigure', id, "-#{slot}", value
+ tk_call path, 'itemconfigure', @id, "-#{slot}", value
end
def addtag(tag)
@@ -185,59 +188,59 @@ class TkcItem:TkObject
def scale(xorigin, yorigin, xscale, yscale)
@c.scale @id, xorigin, yorigin, xscale, yscale
end
- def type
- @c.type @id
+ def itemtype
+ @c.itemtype @id
end
def destroy
tk_call path, 'delete', @id
end
end
-class TkcArc:TkcItem
+class TkcArc<TkcItem
def create_self(*args)
tk_call(@path, 'create', 'arc', *args)
end
end
-class TkcBitmap:TkcItem
+class TkcBitmap<TkcItem
def create_self(*args)
tk_call(@path, 'create', 'bitmap', *args)
end
end
-class TkcImage:TkcItem
+class TkcImage<TkcItem
def create_self(*args)
tk_call(@path, 'create', 'image', *args)
end
end
-class TkcLine:TkcItem
+class TkcLine<TkcItem
def create_self(*args)
tk_call(@path, 'create', 'line', *args)
end
end
-class TkcOval:TkcItem
+class TkcOval<TkcItem
def create_self(*args)
tk_call(@path, 'create', 'oval', *args)
end
end
-class TkcPolygon:TkcItem
+class TkcPolygon<TkcItem
def create_self(*args)
tk_call(@path, 'create', 'polygon', *args)
end
end
-class TkcText:TkcItem
+class TkcText<TkcItem
def create_self(*args)
tk_call(@path, 'create', 'text', *args)
end
end
-class TkcWindow:TkcItem
+class TkcWindow<TkcItem
def create_self(*args)
tk_call(@path, 'create', 'window', *args)
end
end
-class TkcGroup:TkcItem
+class TkcGroup<TkcItem
$tk_group_id = 'tkg00000'
def create_self(*args)
@id = $tk_group_id
- $tk_group_id = $tk_group_id.next
+ $tk_group_id = $tk_group_id.succ
end
def add(*tags)
@@ -262,20 +265,20 @@ class TkcGroup:TkcItem
end
-class TkImage:TkObject
+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_image_id = $tk_image_id.succ
tk_call 'image', @type, @path, *hash_kv(keys)
end
def height
number(tk_call('image', 'height', @path))
end
- def type
+ def itemtype
tk_call('image', 'type', @path)
end
def width
@@ -290,14 +293,14 @@ class TkImage:TkObject
end
end
-class TkBitmapImage:TkImage
+class TkBitmapImage<TkImage
def initialize(*args)
@type = 'bitmap'
super
end
end
-class TkPhotoImage:TkImage
+class TkPhotoImage<TkImage
def initialize(*args)
@type = 'bitmap'
super
diff --git a/lib/tkcore.rb b/lib/tkcore.rb
new file mode 100644
index 0000000000..df4af669ba
--- /dev/null
+++ b/lib/tkcore.rb
@@ -0,0 +1,521 @@
+#
+# tkcore.rb - Tk interface modue without thread
+# $Date: 1996/11/09 22:51:15 $
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require "tkutil"
+if defined? Thread
+ require "thread"
+end
+
+module Tk
+ include TkUtil
+ extend Tk
+
+ wish_path = nil
+ ENV['PATH'].split(":").each {|path|
+ for wish in ['wish4.2', 'wish4.1', 'wish4.0', 'wish']
+ if File.exist? path+'/'+wish
+ wish_path = path+'/'+wish
+ break
+ end
+ break if wish_path
+ end
+ }
+ fail 'can\'t find wish' if not wish_path
+
+ def Tk.tk_exit
+ if not PORT.closed?
+ PORT.print "exit\n"
+ PORT.close
+ end
+ end
+
+ PORT = open(format("|%s -n %s", wish_path, File.basename($0)), "w+");
+ trap "EXIT", proc{Tk.tk_exit}
+ trap "PIPE", ""
+
+ 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 rb_ans args {
+ if [catch "$args" var] {puts "!$var"} {puts "=$var@@"}
+ 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)
+ if cmd == nil
+ READABLE.delete port
+ else
+ READABLE.push port
+ end
+ READ_CMD[port] = cmd
+ end
+
+ WRITABLE = []
+ WRITE_CMD = {}
+ def file_writable(port, cmd)
+ if cmd == nil
+ WRITABLE.delete port
+ else
+ WRITABLE.push port
+ end
+ WRITE_CMD[port] = cmd
+ end
+ module_function :file_readable, :file_writable
+
+ file_readable PORT, proc {
+ line = PORT.gets
+ exit if not line
+ Tk.dispatch(line.chop!)
+ }
+
+ 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|
+ next if s == None
+ if s.kind_of?(Hash)
+ s = hash_kv(s).join(" ")
+ else
+ if not s
+ s = "0"
+ elsif s == TRUE
+ s = "1"
+ elsif s.kind_of?(TkObject)
+ s = s.path
+ else
+ s = s.to_s
+ s.gsub!(/[{}]/, '\\\\\0')
+ end
+ "{#{s}}"
+ end
+ }
+ str = args.join(" ")
+ print str, "\n" if $DEBUG
+ tk_write 'rb_ans %s', str
+ while PORT.gets
+ print $_ if $DEBUG
+ $_.chop!
+ if /^=(.*)@@$/
+ val = $1
+ break
+ elsif /^=/
+ val = $' + "\n"
+ while TRUE
+ PORT.readline
+ if ~/@@$/
+ val += $'
+ return val
+ else
+ val += $_
+ end
+ end
+ elsif /^!/
+ $@ = error_at
+ msg = $'
+ if msg =~ /unknown option "-(.*)"/
+ fail NameError, 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 PORT.closed?
+# 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 = 0
+ def install_cmd(cmd)
+ return '' if cmd == '' # uninstall cmd
+ id = format("c%.4d", $tk_cmdid)
+ $tk_cmdid += 1
+ $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, args=nil)
+ if args
+ id = install_cmd(proc{|arg|
+ TkUtil.eval_cmd cmd, *arg
+ })
+ id + " " + args
+ else
+ id = install_cmd(proc{|arg|
+ TkUtil.eval_cmd cmd, Event.new(*arg)
+ })
+ id + " %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y"
+ end
+ end
+
+ def _bind(path, context, cmd, args=nil)
+ begin
+ id = install_bind(cmd, args)
+ 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, args=nil)
+ _bind 'all', context, cmd, args
+ end
+
+ def pack(*args)
+ TkPack.configure *args
+ end
+
+ $tk_cmdtbl = {}
+
+ def after(ms, cmd=Proc.new)
+ myid = format("c%.4d", $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
+ ensure
+ Tk.tk_exit
+ end
+ end
+
+ def root
+ $tk_root
+ end
+
+ def bell
+ tk_call 'bell'
+ end
+ module_function :after, :update, :dispatch, :mainloop, :root, :bell
+
+ 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
diff --git a/lib/tkentry.rb b/lib/tkentry.rb
index dbd848d0ca..9a03c34058 100644
--- a/lib/tkentry.rb
+++ b/lib/tkentry.rb
@@ -5,7 +5,7 @@
require 'tk.rb'
-class TkEntry:TkLabel
+class TkEntry<TkLabel
def create_self
tk_call 'entry', @path
end
diff --git a/lib/tkscrollbox.rb b/lib/tkscrollbox.rb
new file mode 100644
index 0000000000..b8dbe9b236
--- /dev/null
+++ b/lib/tkscrollbox.rb
@@ -0,0 +1,27 @@
+#
+# tkscrollbox.rb - Tk Listbox with Scrollbar
+# as an example of Composite Widget
+# $Date: 1995/12/12 18:21:01 $
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require 'tk.rb'
+
+class TkScrollbox<TkListbox
+ include TkComposite
+ def initialize_composite
+ list = TkListbox.new(@frame)
+ scroll = TkScrollbar.new(@frame)
+ @path = list.path
+
+ list.configure 'yscroll', scroll.path+" set"
+ list.pack 'side'=>'left','fill'=>'both','expand'=>'yes'
+ scroll.configure 'command', list.path+" yview"
+ scroll.pack 'side'=>'right','fill'=>'y'
+
+ delegate('DEFALUT', list)
+ delegate('foreground', list, scroll)
+ delegate('background', list, scroll)
+ delegate('borderwidth', @frame)
+ delegate('relief', @frame)
+ end
+end
diff --git a/lib/tktext.rb b/lib/tktext.rb
index e7a2be950f..55e396c497 100644
--- a/lib/tktext.rb
+++ b/lib/tktext.rb
@@ -5,7 +5,7 @@
require 'tk.rb'
-class TkText:TkTextWin
+class TkText<TkTextWin
include Scrollable
def create_self
tk_call 'text', @path
@@ -77,16 +77,16 @@ class TkText:TkTextWin
end
end
-class TkTextTag:TkObject
+class TkTextTag<TkObject
$tk_text_tag = 'tag0000'
def initialize(parent)
- if not parent.is_kind_of?(TkText)
+ if not parent.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
+ $tk_text_tag = $tk_text_tag.succ
@t._addtag id, self
end
def id
@@ -116,16 +116,16 @@ class TkTextTag:TkObject
end
end
-class TkTextMark:TkObject
+class TkTextMark<TkObject
$tk_text_mark = 'mark0000'
def initialize(parent, index)
- if not parent.is_kind_of?(TkText)
+ if not parent.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_text_mark = $tk_text_mark.succ
tk_call @t, 'set', @id, index
@t._addtag id, self
end
@@ -143,9 +143,9 @@ class TkTextMark:TkObject
alias destroy unset
end
-class TkTextWindow:TkObject
+class TkTextWindow<TkObject
def initialize(parent, index, *args)
- if not parent.is_kind_of?(TkText)
+ if not parent.kind_of?(TkText)
fail format("%s need to be TkText", parent.inspect)
end
@t = parent
diff --git a/lib/tkthcore.rb b/lib/tkthcore.rb
new file mode 100644
index 0000000000..adbad775d0
--- /dev/null
+++ b/lib/tkthcore.rb
@@ -0,0 +1,546 @@
+#
+# tkthcore.rb - Tk interface modue using thread
+# $Date: 1996/11/09 22:49:15 $
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require "tkutil"
+require "thread"
+
+module Tk
+ include TkUtil
+ extend Tk
+
+ def Tk.tk_exit
+ if not PORT.closed?
+ tk_write "exit"
+ PORT.close
+ end
+ end
+
+ trap "EXIT", proc{Tk.tk_exit}
+ trap "PIPE", ''
+
+ wish_path = nil
+ ENV['PATH'].split(":").each {|path|
+ for wish in ['wish4.2', 'wish4.1', 'wish4.0', 'wish']
+ if File.exist? path+'/'+wish
+ wish_path = path+'/'+wish
+ break
+ end
+ break if wish_path
+ end
+ }
+ fail 'can\'t find wish' if not wish_path
+
+ # mark for non-given arguments
+ None = Object.new
+ def None.to_s
+ 'None'
+ end
+
+ Qin = Queue.new
+ Qout = Queue.new
+ Qwish = Queue.new
+ Qcmd = Queue.new
+ PORT = open(format("|%s -n %s", wish_path, File.basename($0)), "w+");
+
+ $tk_not_init = TRUE
+
+ def Tk.init
+ $tk_not_init = FALSE
+ Thread.start do
+ loop do
+ while line = PORT.gets
+ line.chop!
+ if line =~ /^[=!]/
+ Qwish.push line
+ else
+ Qcmd.push line
+ end
+ end
+ exit
+ end
+ end
+
+ Thread.start do
+ ary = [PORT]
+ loop do
+ str = Qin.pop
+ print str, "\n" if $DEBUG
+ tk_write 'if [catch {%s} var] {puts "!$var"} {puts "=$var@@"};flush stdout', str
+ Qout.push(tk_recv)
+ end
+ end
+ end
+
+ $tk_event_queue = []
+ def tk_recv()
+ val = nil
+ $_ = Qwish.pop
+ loop do
+ if /^=(.*)@@$/
+ val = $1
+ break
+ elsif /^=/
+ val = $' + "\n"
+ while TRUE
+ PORT.readline
+ if ~/@@$/
+ val += $'
+ return val
+ else
+ v>al += $_
+ end
+ end
+ elsif /^!/
+ $@ = error_at
+ msg = $'
+ if msg =~ /unknown option "-(.*)"/
+ fail NameError, format("undefined method `%s' for %s(%s)", $1, self, self.type) #`'
+ else
+ fail format("%s - %s", self.type, msg)
+ end
+ end
+ Qcmd.push line
+ end
+
+ fail 'wish closed' if PORT.closed?
+# tk_split_list(val)
+ val
+ end
+
+ def tk_call(*args)
+ Tk.init if $tk_not_init
+ args = args.collect{|s|
+ next if s == None
+ if s.kind_of?(Hash)
+ s = hash_kv(s).join(" ")
+ else
+ if not s
+ s = "0"
+ elsif s == TRUE
+ s = "1"
+ elsif s.kind_of?(TkObject)
+ s = s.path
+ else
+ s = s.to_s
+ s.gsub!(/[{}]/, '\\\\\0')
+ end
+ "{#{s}}"
+ end
+ }
+ str = args.join(" ")
+ Qin.push str
+ return Qout.pop
+ end
+
+ def tk_write(*args)
+ PORT.printf *args; PORT.print "\n"
+ PORT.flush
+ end
+ module_function :tk_write, :tk_recv
+ 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'
+
+ READ_TH = {}
+ def file_readable(port, cmd)
+ if cmd == nil
+ if READ_TH[port].has_key?
+ READ_TH[port].exit
+ READ_TH[port] = nil
+ end
+ else
+ READ_TH[port] = Thread.start{
+ loop do
+ TkUtil.eval_cmd cmd
+ end
+ }
+ end
+ end
+
+ WRITE_TH = {}
+ def file_writable(port, cmd)
+ if cmd == nil
+ if WRITE_TH[port].has_key?
+ WRITE_TH[port].exit
+ end
+ else
+ WRITE_TH[port] = Thread.start{
+ loop do
+ TkUtil.eval_cmd cmd
+ end
+ }
+ end
+ end
+ module_function :file_readable, :file_writable
+
+ 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 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
+ module_function :dispatch
+
+ def error_at
+ n = 1
+ while c = caller(n)
+ break if c !~ /tk\.rb:/
+ n+=1
+ end
+ c
+ end
+
+ 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
+
+ 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 = 0
+ def install_cmd(cmd)
+ return '' if cmd == '' # uninstall cmd
+ id = format("c%.4d", $tk_cmdid)
+ $tk_cmdid += 1
+ $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, args=nil)
+ if args
+ id = install_cmd(proc{|arg|
+ TkUtil.eval_cmd cmd, *arg
+ })
+ id + " " + args
+ else
+ id = install_cmd(proc{|arg|
+ TkUtil.eval_cmd cmd, Event.new(*arg)
+ })
+ id + " %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y"
+ end
+ end
+
+ def _bind(path, context, cmd, args=nil)
+ begin
+ id = install_bind(cmd, args)
+ 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, args=nil)
+ _bind 'all', context, cmd, args
+ end
+
+ def pack(*args)
+ TkPack.configure *args
+ end
+
+ $tk_cmdtbl = {}
+
+ Qafter = Queue.new
+ def after(ms, cmd=Proc.new)
+ unless $tk_after_thread
+ $tk_after_thread = Thread.start{
+ loop do
+ cmd = Qafter.pop
+ TkUtil.eval_cmd cmd
+ end
+ }
+ end
+ Thread.start do
+ sleep Float(ms)/1000
+ Qafter.push cmd
+ end
+ end
+
+ def update(idle=nil)
+ if idle
+ tk_call 'update', 'idletasks'
+ else
+ tk_call 'update'
+ end
+ end
+
+ def root
+ $tk_root
+ end
+
+ def bell
+ tk_call 'bell'
+ end
+
+ def mainloop
+ begin
+ tk_call 'after', 'idle', 'wm deiconify .'
+ loop do
+ dispatch Qcmd.pop
+ end
+ ensure
+ Tk.tk_exit
+ end
+ end
+ module_function :after, :update, :dispatch, :mainloop, :root, :bell
+
+ 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
diff --git a/main.c b/main.c
index 3630f8aa7b..5bc0ecf62f 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,10 @@
************************************************/
+#ifdef DJGPP
+unsigned int _stklen = 0x100000;
+#endif
+
void
main(argc, argv, envp)
int argc;
diff --git a/math.c b/math.c
index 41a4232083..db4e4afc7e 100644
--- a/math.c
+++ b/math.c
@@ -6,7 +6,7 @@
$Date: 1994/11/01 08:28:03 $
created at: Tue Jan 25 14:12:56 JST 1994
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -15,12 +15,13 @@
VALUE mMath;
VALUE float_new();
+VALUE f_float();
#define Need_Float(x) \
if (FIXNUM_P(x)) {\
(x) = (struct RFloat*)float_new((double)FIX2INT(x));\
} else {\
- Check_Type(x, T_FLOAT);\
+ (x) = (struct RFloat*)f_float(x, x);\
}
#define Need_Float2(x,y) {\
@@ -34,7 +35,7 @@ math_atan2(obj, x, y)
struct RFloat *x, *y;
{
Need_Float2(x, y);
- return float_new(atan2(x->value, x->value));
+ return float_new(atan2(x->value, y->value));
}
static VALUE
@@ -101,7 +102,7 @@ math_sqrt(obj, x)
{
Need_Float(x);
- if (x->value < 0.0) Fail("square root for negative number");
+ if (x->value < 0.0) ArgError("square root for negative number");
return float_new(sqrt(x->value));
}
diff --git a/missing/flock.c b/missing/flock.c
new file mode 100644
index 0000000000..a4a9544b56
--- /dev/null
+++ b/missing/flock.c
@@ -0,0 +1,90 @@
+#include "config.h"
+
+#if defined(HAVE_LOCKF)
+
+#include <unistd.h>
+#include <errno.h>
+
+/* Emulate flock() with lockf() or fcntl(). This is just to increase
+ portability of scripts. The calls might not be completely
+ interchangeable. What's really needed is a good file
+ locking module.
+*/
+
+# ifndef F_ULOCK
+# define F_ULOCK 0 /* Unlock a previously locked region */
+# endif
+# ifndef F_LOCK
+# define F_LOCK 1 /* Lock a region for exclusive use */
+# endif
+# ifndef F_TLOCK
+# define F_TLOCK 2 /* Test and lock a region for exclusive use */
+# endif
+# ifndef F_TEST
+# define F_TEST 3 /* Test a region for other processes locks */
+# endif
+
+/* These are the flock() constants. Since this sytems doesn't have
+ flock(), the values of the constants are probably not available.
+*/
+# ifndef LOCK_SH
+# define LOCK_SH 1
+# endif
+# ifndef LOCK_EX
+# define LOCK_EX 2
+# endif
+# ifndef LOCK_NB
+# define LOCK_NB 4
+# endif
+# ifndef LOCK_UN
+# define LOCK_UN 8
+# endif
+
+int
+flock(fd, operation)
+ int fd;
+ int operation;
+{
+ int i;
+ switch (operation) {
+
+ /* LOCK_SH - get a shared lock */
+ case LOCK_SH:
+ /* LOCK_EX - get an exclusive lock */
+ case LOCK_EX:
+ i = lockf (fd, F_LOCK, 0);
+ break;
+
+ /* LOCK_SH|LOCK_NB - get a non-blocking shared lock */
+ case LOCK_SH|LOCK_NB:
+ /* LOCK_EX|LOCK_NB - get a non-blocking exclusive lock */
+ case LOCK_EX|LOCK_NB:
+ i = lockf (fd, F_TLOCK, 0);
+ if (i == -1)
+ if ((errno == EAGAIN) || (errno == EACCES))
+ errno = EWOULDBLOCK;
+ break;
+
+ /* LOCK_UN - unlock */
+ case LOCK_UN:
+ i = lockf (fd, F_ULOCK, 0);
+ break;
+
+ /* Default - can't decipher operation */
+ default:
+ i = -1;
+ errno = EINVAL;
+ break;
+ }
+ return i;
+}
+#else
+int
+flock(fd, operation)
+ int fd;
+ int operation;
+{
+ rb_notimplement();
+ return -1;
+}
+#endif
diff --git a/missing/mkdir.c b/missing/mkdir.c
index 5225e586d9..b581a5e467 100644
--- a/missing/mkdir.c
+++ b/missing/mkdir.c
@@ -1,4 +1,4 @@
-/*
+*
* Written by Robert Rother, Mariah Corporation, August 1985.
*
* If you want it, it's yours. All I ask in return is that if you
@@ -96,7 +96,7 @@ rmdir (dpath)
if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
{
errno = EIO; /* We don't know why, but */
- return -1; /* /bin/mkdir failed */
+ return -1; /* /bin/rmdir failed */
}
return 0;
diff --git a/missing/setenv.c b/missing/setenv.c
index 6211bcf02b..16ecbc6090 100644
--- a/missing/setenv.c
+++ b/missing/setenv.c
@@ -19,8 +19,8 @@ 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 */
+ if (memcmp(environ[i],nam,len) == 0 && environ[i][len] == '=')
+ break; /* memcmp must come first to avoid */
} /* potential SEGV's */
return i;
}
diff --git a/missing/strftime.c b/missing/strftime.c
index 1e668ef2ae..478471c37d 100644
--- a/missing/strftime.c
+++ b/missing/strftime.c
@@ -10,9 +10,12 @@
* For extensions from SunOS, add SUNOS_EXT.
* For stuff needed to implement the P1003.2 date command, add POSIX2_DATE.
* For VMS dates, add VMS_EXT.
+ * For a an RFC822 time format, add MAILHEADER_EXT.
+ * For ISO week years, add ISO_DATE_EXT.
* For complete POSIX semantics, add POSIX_SEMANTICS.
*
- * The code for %c, %x, and %X is my best guess as to what's "appropriate".
+ * The code for %c, %x, and %X now follows the 1003.2 specification for
+ * the POSIX locale.
* This version ignores LOCALE information.
* It also doesn't worry about multi-byte characters.
* So there.
@@ -26,6 +29,9 @@
* Updated April, 1993
* Updated February, 1994
* Updated May, 1994
+ * Updated January, 1995
+ * Updated September, 1995
+ * Updated January, 1996
*
* Fixes from ado@elsie.nci.nih.gov
* February 1991, May 1992
@@ -33,36 +39,46 @@
* May, 1993
* Further fixes from ado@elsie.nci.nih.gov
* February 1994
+ * %z code from chip@chinacat.unicom.com
+ * Applied September 1995
+ * %V code fixed (again) and %G, %g added,
+ * January 1996
*/
-#include "config.h"
-
+#ifndef GAWK
#include <stdio.h>
#include <ctype.h>
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else /* !HAVE_STRING_H */
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
+#include <string.h>
#include <time.h>
+#endif
+#if defined(TM_IN_SYS_TIME) || ! defined(GAWK)
#include <sys/types.h>
#include <sys/time.h>
+#endif
/* defaults: season to taste */
-#define SYSV_EXT 1 /* stuff in System V ascftime routine */
-#define SUNOS_EXT 1 /* stuff in SunOS strftime routine */
-#define POSIX2_DATE 1 /* stuff in Posix 1003.2 date command */
-#define VMS_EXT 1 /* include %v for VMS date format */
-#ifndef RUBY
-#define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */
+#define SYSV_EXT 1 /* stuff in System V ascftime routine */
+#define SUNOS_EXT 1 /* stuff in SunOS strftime routine */
+#define POSIX2_DATE 1 /* stuff in Posix 1003.2 date command */
+#define VMS_EXT 1 /* include %v for VMS date format */
+#define MAILHEADER_EXT 1 /* add %z for HHMM format */
+#define ISO_DATE_EXT 1 /* %G and %g for year of ISO week */
+#ifndef GAWK
+#define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */
+#endif
+
+#if defined(ISO_DATE_EXT)
+#if ! defined(POSIX2_DATE)
+#define POSIX2_DATE 1
+#endif
#endif
#if defined(POSIX2_DATE)
#if ! defined(SYSV_EXT)
-#define SYSV_EXT 1
+#define SYSV_EXT 1
#endif
#if ! defined(SUNOS_EXT)
-#define SUNOS_EXT 1
+#define SUNOS_EXT 1
#endif
#endif
@@ -103,11 +119,16 @@ adddecl(static int iso8601wknum(const struct tm *timeptr);)
#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
extern char *tzname[2];
-# ifdef HAVE_DAYLIGHT
extern int daylight;
-# endif
+#ifdef SOLARIS
+extern long timezone, altzone;
+#else
+extern int timezone, altzone;
+#endif
#endif
+#undef min /* just in case */
+
/* min --- return minimum of two numbers */
#ifndef __STDC__
@@ -119,9 +140,11 @@ static inline int
min(int a, int b)
#endif
{
- return (a < b ? a : b);
+ return (a < b ? a : b);
}
+#undef max /* also, just in case */
+
/* max --- return maximum of two numbers */
#ifndef __STDC__
@@ -133,7 +156,7 @@ static inline int
max(int a, int b)
#endif
{
- return (a > b ? a : b);
+ return (a > b ? a : b);
}
/* strftime --- produce formatted time */
@@ -150,360 +173,417 @@ size_t
strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
#endif
{
- char *endp = s + maxsize;
- char *start = s;
- auto char tbuf[100];
- int i;
- static short first = 1;
+ char *endp = s + maxsize;
+ char *start = s;
+ auto char tbuf[100];
+ long off;
+ int i, w, y;
+ static short first = 1;
#ifdef POSIX_SEMANTICS
- static char *savetz = NULL;
- static int savetzlen = 0;
- char *tz;
+ static char *savetz = NULL;
+ static int savetzlen = 0;
+ char *tz;
#endif /* POSIX_SEMANTICS */
#ifndef HAVE_TM_ZONE
- extern char *timezone();
- struct timeval tv;
- struct timezone zone;
+#ifndef HAVE_TM_NAME
+#ifndef HAVE_TZNAME
+ extern char *timezone();
+ struct timeval tv;
+ struct timezone zone;
+#endif /* HAVE_TZNAME */
+#endif /* HAVE_TM_NAME */
#endif /* HAVE_TM_ZONE */
- /* various tables, useful in North America */
- static const char *days_a[] = {
- "Sun", "Mon", "Tue", "Wed",
- "Thu", "Fri", "Sat",
- };
- static const char *days_l[] = {
- "Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday",
- };
- static const char *months_a[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
- };
- static const char *months_l[] = {
- "January", "February", "March", "April",
- "May", "June", "July", "August", "September",
- "October", "November", "December",
- };
- static const char *ampm[] = { "AM", "PM", };
-
- if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0)
- return 0;
-
- /* quick check if we even need to bother */
- if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize)
- return 0;
+ /* various tables, useful in North America */
+ static const char *days_a[] = {
+ "Sun", "Mon", "Tue", "Wed",
+ "Thu", "Fri", "Sat",
+ };
+ static const char *days_l[] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday",
+ };
+ static const char *months_a[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+ };
+ static const char *months_l[] = {
+ "January", "February", "March", "April",
+ "May", "June", "July", "August", "September",
+ "October", "November", "December",
+ };
+ static const char *ampm[] = { "AM", "PM", };
+
+ if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0)
+ return 0;
+
+ /* quick check if we even need to bother */
+ if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize)
+ return 0;
#ifndef POSIX_SEMANTICS
- if (first) {
- tzset();
- first = 0;
- }
+ if (first) {
+ tzset();
+ first = 0;
+ }
#else /* POSIX_SEMANTICS */
- tz = getenv("TZ");
- if (first) {
- if (tz != NULL) {
- int tzlen = strlen(tz);
-
- savetz = (char *) malloc(tzlen + 1);
- if (savetz != NULL) {
- savetzlen = tzlen + 1;
- strcpy(savetz, tz);
- }
+ tz = getenv("TZ");
+ if (first) {
+ if (tz != NULL) {
+ int tzlen = strlen(tz);
+
+ savetz = (char *) malloc(tzlen + 1);
+ if (savetz != NULL) {
+ savetzlen = tzlen + 1;
+ strcpy(savetz, tz);
+ }
+ }
+ tzset();
+ first = 0;
+ }
+ /* if we have a saved TZ, and it is different, recapture and reset */
+ if (tz && savetz && (tz[0] != savetz[0] || strcmp(tz, savetz) != 0)) {
+ i = strlen(tz) + 1;
+ if (i > savetzlen) {
+ savetz = (char *) realloc(savetz, i);
+ if (savetz) {
+ savetzlen = i;
+ strcpy(savetz, tz);
+ }
+ } else
+ strcpy(savetz, tz);
+ tzset();
}
- tzset();
- first = 0;
- }
- /* if we have a saved TZ, and it is different, recapture and reset */
- if (tz && savetz && (tz[0] != savetz[0] || strcmp(tz, savetz) != 0)) {
- i = strlen(tz) + 1;
- if (i > savetzlen) {
- savetz = (char *) realloc(savetz, i);
- if (savetz) {
- savetzlen = i;
- strcpy(savetz, tz);
- }
- } else
- strcpy(savetz, tz);
- tzset();
- }
#endif /* POSIX_SEMANTICS */
- for (; *format && s < endp - 1; format++) {
- tbuf[0] = '\0';
- if (*format != '%') {
- *s++ = *format;
- continue;
- }
- again:
- switch (*++format) {
- case '\0':
- *s++ = '%';
- goto out;
-
- case '%':
- *s++ = '%';
- continue;
-
- case 'a': /* abbreviated weekday name */
- if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
- strcpy(tbuf, "?");
- else
- strcpy(tbuf, days_a[timeptr->tm_wday]);
- break;
-
- case 'A': /* full weekday name */
- if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
- strcpy(tbuf, "?");
- else
- strcpy(tbuf, days_l[timeptr->tm_wday]);
- break;
+ for (; *format && s < endp - 1; format++) {
+ tbuf[0] = '\0';
+ if (*format != '%') {
+ *s++ = *format;
+ continue;
+ }
+ again:
+ switch (*++format) {
+ case '\0':
+ *s++ = '%';
+ goto out;
+
+ case '%':
+ *s++ = '%';
+ continue;
+
+ case 'a': /* abbreviated weekday name */
+ if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
+ strcpy(tbuf, "?");
+ else
+ strcpy(tbuf, days_a[timeptr->tm_wday]);
+ break;
+
+ case 'A': /* full weekday name */
+ if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
+ strcpy(tbuf, "?");
+ else
+ strcpy(tbuf, days_l[timeptr->tm_wday]);
+ break;
#ifdef SYSV_EXT
- case 'h': /* abbreviated month name */
+ case 'h': /* abbreviated month name */
#endif
- case 'b': /* abbreviated month name */
- if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
- strcpy(tbuf, "?");
- else
- strcpy(tbuf, months_a[timeptr->tm_mon]);
- break;
-
- case 'B': /* full month name */
- if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
- strcpy(tbuf, "?");
- else
- strcpy(tbuf, months_l[timeptr->tm_mon]);
- break;
-
- case 'c': /* appropriate date and time representation */
- sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d",
- days_a[range(0, timeptr->tm_wday, 6)],
- months_a[range(0, timeptr->tm_mon, 11)],
- range(1, timeptr->tm_mday, 31),
- range(0, timeptr->tm_hour, 23),
- range(0, timeptr->tm_min, 59),
- range(0, timeptr->tm_sec, 61),
- timeptr->tm_year + 1900);
- break;
-
- case 'd': /* day of the month, 01 - 31 */
- i = range(1, timeptr->tm_mday, 31);
- sprintf(tbuf, "%02d", i);
- break;
-
- case 'H': /* hour, 24-hour clock, 00 - 23 */
- i = range(0, timeptr->tm_hour, 23);
- sprintf(tbuf, "%02d", i);
- break;
-
- case 'I': /* hour, 12-hour clock, 01 - 12 */
- i = range(0, timeptr->tm_hour, 23);
- if (i == 0)
- i = 12;
- else if (i > 12)
- i -= 12;
- sprintf(tbuf, "%02d", i);
- break;
-
- case 'j': /* day of the year, 001 - 366 */
- sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
- break;
-
- case 'm': /* month, 01 - 12 */
- i = range(0, timeptr->tm_mon, 11);
- sprintf(tbuf, "%02d", i + 1);
- break;
-
- case 'M': /* minute, 00 - 59 */
- i = range(0, timeptr->tm_min, 59);
- sprintf(tbuf, "%02d", i);
- break;
-
- case 'p': /* am or pm based on 12-hour clock */
- i = range(0, timeptr->tm_hour, 23);
- if (i < 12)
- strcpy(tbuf, ampm[0]);
- else
- strcpy(tbuf, ampm[1]);
- break;
-
- case 'S': /* second, 00 - 61 */
- i = range(0, timeptr->tm_sec, 61);
- sprintf(tbuf, "%02d", i);
- break;
-
- case 'U': /* week of year, Sunday is first day of week */
- sprintf(tbuf, "%02d", weeknumber(timeptr, 0));
- break;
-
- case 'w': /* weekday, Sunday == 0, 0 - 6 */
- i = range(0, timeptr->tm_wday, 6);
- sprintf(tbuf, "%d", i);
- break;
-
- case 'W': /* week of year, Monday is first day of week */
- sprintf(tbuf, "%02d", weeknumber(timeptr, 1));
- break;
-
- case 'x': /* appropriate date representation */
- sprintf(tbuf, "%s %s %2d %d",
- days_a[range(0, timeptr->tm_wday, 6)],
- months_a[range(0, timeptr->tm_mon, 11)],
- range(1, timeptr->tm_mday, 31),
- timeptr->tm_year + 1900);
- break;
-
- case 'X': /* appropriate time representation */
- sprintf(tbuf, "%02d:%02d:%02d",
- range(0, timeptr->tm_hour, 23),
- range(0, timeptr->tm_min, 59),
- range(0, timeptr->tm_sec, 61));
- break;
-
- case 'y': /* year without a century, 00 - 99 */
- i = timeptr->tm_year % 100;
- sprintf(tbuf, "%02d", i);
- break;
-
- case 'Y': /* year with century */
- sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
- break;
-
- case 'Z': /* time zone name or abbrevation */
+ case 'b': /* abbreviated month name */
+ if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
+ strcpy(tbuf, "?");
+ else
+ strcpy(tbuf, months_a[timeptr->tm_mon]);
+ break;
+
+ case 'B': /* full month name */
+ if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
+ strcpy(tbuf, "?");
+ else
+ strcpy(tbuf, months_l[timeptr->tm_mon]);
+ break;
+
+ case 'c': /* appropriate date and time representation */
+ strftime(tbuf, sizeof tbuf, "%a %b %e %H:%M:%S %Y", timeptr);
+ break;
+
+ case 'd': /* day of the month, 01 - 31 */
+ i = range(1, timeptr->tm_mday, 31);
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'H': /* hour, 24-hour clock, 00 - 23 */
+ i = range(0, timeptr->tm_hour, 23);
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'I': /* hour, 12-hour clock, 01 - 12 */
+ i = range(0, timeptr->tm_hour, 23);
+ if (i == 0)
+ i = 12;
+ else if (i > 12)
+ i -= 12;
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'j': /* day of the year, 001 - 366 */
+ sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
+ break;
+
+ case 'm': /* month, 01 - 12 */
+ i = range(0, timeptr->tm_mon, 11);
+ sprintf(tbuf, "%02d", i + 1);
+ break;
+
+ case 'M': /* minute, 00 - 59 */
+ i = range(0, timeptr->tm_min, 59);
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'p': /* am or pm based on 12-hour clock */
+ i = range(0, timeptr->tm_hour, 23);
+ if (i < 12)
+ strcpy(tbuf, ampm[0]);
+ else
+ strcpy(tbuf, ampm[1]);
+ break;
+
+ case 'S': /* second, 00 - 61 */
+ i = range(0, timeptr->tm_sec, 61);
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'U': /* week of year, Sunday is first day of week */
+ sprintf(tbuf, "%02d", weeknumber(timeptr, 0));
+ break;
+
+ case 'w': /* weekday, Sunday == 0, 0 - 6 */
+ i = range(0, timeptr->tm_wday, 6);
+ sprintf(tbuf, "%d", i);
+ break;
+
+ case 'W': /* week of year, Monday is first day of week */
+ sprintf(tbuf, "%02d", weeknumber(timeptr, 1));
+ break;
+
+ case 'x': /* appropriate date representation */
+ strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
+ break;
+
+ case 'X': /* appropriate time representation */
+ strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
+ break;
+
+ case 'y': /* year without a century, 00 - 99 */
+ i = timeptr->tm_year % 100;
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'Y': /* year with century */
+ sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
+ break;
+
+#ifdef MAILHEADER_EXT
+ /*
+ * From: Chip Rosenthal <chip@chinacat.unicom.com>
+ * Date: Sun, 19 Mar 1995 00:33:29 -0600 (CST)
+ *
+ * Warning: the %z [code] is implemented by inspecting the
+ * timezone name conditional compile settings, and
+ * inferring a method to get timezone offsets. I've tried
+ * this code on a couple of machines, but I don't doubt
+ * there is some system out there that won't like it.
+ * Maybe the easiest thing to do would be to bracket this
+ * with an #ifdef that can turn it off. The %z feature
+ * would be an admittedly obscure one that most folks can
+ * live without, but it would be a great help to those of
+ * us that muck around with various message processors.
+ */
+ case 'z': /* time zone offset east of GMT e.g. -0600 */
+#ifdef HAVE_TM_NAME
+ /*
+ * Systems with tm_name probably have tm_tzadj as
+ * secs west of GMT. Convert to mins east of GMT.
+ */
+ off = -timeptr->tm_tzadj / 60;
+#else /* !HAVE_TM_NAME */
+#ifdef HAVE_TM_ZONE
+ /*
+ * Systems with tm_zone probably have tm_gmtoff as
+ * secs east of GMT. Convert to mins east of GMT.
+ */
+ off = timeptr->tm_gmtoff / 60;
+#else /* !HAVE_TM_ZONE */
+#if HAVE_TZNAME
+ /*
+ * Systems with tzname[] probably have timezone as
+ * secs west of GMT. Convert to mins east of GMT.
+ */
+ off = -(daylight ? timezone : altzone) / 60;
+#else /* !HAVE_TZNAME */
+ off = -zone.tz_minuteswest;
+#endif /* !HAVE_TZNAME */
+#endif /* !HAVE_TM_ZONE */
+#endif /* !HAVE_TM_NAME */
+ if (off < 0) {
+ tbuf[0] = '-';
+ off = -off;
+ } else {
+ tbuf[0] = '+';
+ }
+ sprintf(tbuf+1, "%02d%02d", off/60, off%60);
+ break;
+#endif /* MAILHEADER_EXT */
+
+ case 'Z': /* time zone name or abbrevation */
#ifdef HAVE_TZNAME
-#ifdef HAVE_DAYLIGHT
- i = (daylight && timeptr->tm_isdst); /* 0 or 1 */
-#else
- i = timeptr->tm_isdst;
-#endif
- strcpy(tbuf, tzname[i]);
+ i = (daylight && timeptr->tm_isdst > 0); /* 0 or 1 */
+ strcpy(tbuf, tzname[i]);
#else
#ifdef HAVE_TM_ZONE
- strcpy(tbuf, timeptr->tm_zone);
+ strcpy(tbuf, timeptr->tm_zone);
#else
- gettimeofday(& tv, & zone);
- strcpy(tbuf, timezone(zone.tz_minuteswest,
- timeptr->tm_isdst));
-#endif
-#endif
- break;
+#ifdef HAVE_TM_NAME
+ strcpy(tbuf, timeptr->tm_name);
+#else
+ gettimeofday(& tv, & zone);
+ strcpy(tbuf, timezone(zone.tz_minuteswest,
+ timeptr->tm_isdst > 0));
+#endif /* HAVE_TM_NAME */
+#endif /* HAVE_TM_ZONE */
+#endif /* HAVE_TZNAME */
+ break;
#ifdef SYSV_EXT
- case 'n': /* same as \n */
- tbuf[0] = '\n';
- tbuf[1] = '\0';
- break;
-
- case 't': /* same as \t */
- tbuf[0] = '\t';
- tbuf[1] = '\0';
- break;
-
- case 'D': /* date as %m/%d/%y */
- strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
- break;
-
- case 'e': /* day of month, blank padded */
- sprintf(tbuf, "%2d", range(1, timeptr->tm_mday, 31));
- break;
-
- case 'r': /* time as %I:%M:%S %p */
- strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);
- break;
-
- case 'R': /* time as %H:%M */
- strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);
- break;
-
- case 'T': /* time as %H:%M:%S */
- strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
- break;
+ case 'n': /* same as \n */
+ tbuf[0] = '\n';
+ tbuf[1] = '\0';
+ break;
+
+ case 't': /* same as \t */
+ tbuf[0] = '\t';
+ tbuf[1] = '\0';
+ break;
+
+ case 'D': /* date as %m/%d/%y */
+ strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
+ break;
+
+ case 'e': /* day of month, blank padded */
+ sprintf(tbuf, "%2d", range(1, timeptr->tm_mday, 31));
+ break;
+
+ case 'r': /* time as %I:%M:%S %p */
+ strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);
+ break;
+
+ case 'R': /* time as %H:%M */
+ strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);
+ break;
+
+ case 'T': /* time as %H:%M:%S */
+ strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
+ break;
#endif
#ifdef SUNOS_EXT
- case 'k': /* hour, 24-hour clock, blank pad */
- sprintf(tbuf, "%2d", range(0, timeptr->tm_hour, 23));
- break;
-
- case 'l': /* hour, 12-hour clock, 1 - 12, blank pad */
- i = range(0, timeptr->tm_hour, 23);
- if (i == 0)
- i = 12;
- else if (i > 12)
- i -= 12;
- sprintf(tbuf, "%2d", i);
- break;
+ case 'k': /* hour, 24-hour clock, blank pad */
+ sprintf(tbuf, "%2d", range(0, timeptr->tm_hour, 23));
+ break;
+
+ case 'l': /* hour, 12-hour clock, 1 - 12, blank pad */
+ i = range(0, timeptr->tm_hour, 23);
+ if (i == 0)
+ i = 12;
+ else if (i > 12)
+ i -= 12;
+ sprintf(tbuf, "%2d", i);
+ break;
#endif
#ifdef VMS_EXT
- case 'v': /* date as dd-bbb-YYYY */
- sprintf(tbuf, "%02d-%3.3s-%4d",
- range(1, timeptr->tm_mday, 31),
- months_a[range(0, timeptr->tm_mon, 11)],
- timeptr->tm_year + 1900);
- for (i = 3; i < 6; i++)
- if (islower(tbuf[i]))
- tbuf[i] = toupper(tbuf[i]);
- break;
+ case 'v': /* date as dd-bbb-YYYY */
+ sprintf(tbuf, "%02d-%3.3s-%4d",
+ range(1, timeptr->tm_mday, 31),
+ months_a[range(0, timeptr->tm_mon, 11)],
+ timeptr->tm_year + 1900);
+ for (i = 3; i < 6; i++)
+ if (islower(tbuf[i]))
+ tbuf[i] = toupper(tbuf[i]);
+ break;
#endif
#ifdef POSIX2_DATE
- case 'C':
- sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
- break;
-
-
- case 'E':
- case 'O':
- /* POSIX locale extensions, ignored for now */
- goto again;
-
- case 'V': /* week of year according ISO 8601 */
-#if defined(GAWK) && defined(VMS_EXT)
- {
- extern int do_lint;
- extern void warning();
- static int warned = 0;
-
- if (! warned && do_lint) {
- warned = 1;
- warning(
- "conversion %%V added in P1003.2; for VMS style date, use %%v");
- }
- }
-#endif
- sprintf(tbuf, "%02d", iso8601wknum(timeptr));
- break;
-
- case 'u':
- /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */
- sprintf(tbuf, "%d", timeptr->tm_wday == 0 ? 7 :
- timeptr->tm_wday);
- break;
+ case 'C':
+ sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
+ break;
+
+
+ case 'E':
+ case 'O':
+ /* POSIX locale extensions, ignored for now */
+ goto again;
+
+ case 'V': /* week of year according ISO 8601 */
+ sprintf(tbuf, "%02d", iso8601wknum(timeptr));
+ break;
+
+ case 'u':
+ /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */
+ sprintf(tbuf, "%d", timeptr->tm_wday == 0 ? 7 :
+ timeptr->tm_wday);
+ break;
#endif /* POSIX2_DATE */
- default:
- tbuf[0] = '%';
- tbuf[1] = *format;
- tbuf[2] = '\0';
- break;
- }
- i = strlen(tbuf);
- if (i) {
- if (s + i < endp - 1) {
- strcpy(s, tbuf);
- s += i;
- } else
- return 0;
+
+#ifdef ISO_DATE_EXT
+ case 'G':
+ case 'g':
+ /*
+ * Year of ISO week.
+ *
+ * If it's December but the ISO week number is one,
+ * that week is in next year.
+ * If it's January but the ISO week number is 52 or
+ * 53, that week is in last year.
+ * Otherwise, it's this year.
+ */
+ w = iso8601wknum(timeptr);
+ if (timeptr->tm_mon == 11 && w == 1)
+ y = 1900 + timeptr->tm_year + 1;
+ else if (timeptr->tm_mon == 0 && w >= 52)
+ y = 1900 + timeptr->tm_year - 1;
+ else
+ y = 1900 + timeptr->tm_year;
+
+ if (*format == 'G')
+ sprintf(tbuf, "%d", y);
+ else
+ sprintf(tbuf, "%02d", y % 100);
+ break;
+#endif ISO_DATE_EXT
+ default:
+ tbuf[0] = '%';
+ tbuf[1] = *format;
+ tbuf[2] = '\0';
+ break;
+ }
+ i = strlen(tbuf);
+ if (i) {
+ if (s + i < endp - 1) {
+ strcpy(s, tbuf);
+ s += i;
+ } else
+ return 0;
+ }
}
- }
out:
- if (s < endp && *format == '\0') {
- *s = '\0';
- return (s - start);
- } else
- return 0;
+ if (s < endp && *format == '\0') {
+ *s = '\0';
+ return (s - start);
+ } else
+ return 0;
}
/* isleap --- is a year a leap year? */
@@ -517,7 +597,7 @@ static int
isleap(int year)
#endif
{
- return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
+ return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
@@ -533,85 +613,108 @@ static int
iso8601wknum(const struct tm *timeptr)
#endif
{
- /*
- * From 1003.2:
- * If the week (Monday to Sunday) containing January 1
- * has four or more days in the new year, then it is week 1;
- * otherwise it is the highest numbered week of the previous
- * (52 or 53) year, and the next week is week 1.
- *
- * ADR: This means if Jan 1 was Monday through Thursday,
- * it was week 1, otherwise week 52 or 53.
- *
- * XPG4 erroneously included POSIX.2 rationale text in the
- * main body of the standard. Thus it requires week 53.
- */
-
- int weeknum, jan1day, diff;
-
- /* get week number, Monday as first day of the week */
- weeknum = weeknumber(timeptr, 1);
-
- /*
- * With thanks and tip of the hatlo to tml@tik.vtt.fi
- *
- * What day of the week does January 1 fall on?
- * We know that
- * (timeptr->tm_yday - jan1.tm_yday) MOD 7 ==
- * (timeptr->tm_wday - jan1.tm_wday) MOD 7
- * and that
- * jan1.tm_yday == 0
- * and that
- * timeptr->tm_wday MOD 7 == timeptr->tm_wday
- * from which it follows that. . .
- */
- jan1day = timeptr->tm_wday - (timeptr->tm_yday % 7);
- if (jan1day < 0)
- jan1day += 7;
-
- /*
- * If Jan 1 was a Monday through Thursday, it was in
- * week 1. Otherwise it was last year's highest week, which is
- * this year's week 0.
- *
- * What does that mean?
- * If Jan 1 was Monday, the week number is exactly right, it can
- * never be 0.
- * If it was Tuesday through Thursday, the weeknumber is one
- * less than it should be, so we add one.
- * Otherwise, Friday, Saturday or Sunday, the week number is
- * OK, but if it is 0, it needs to be 52 or 53.
- */
- switch (jan1day) {
- case 1: /* Monday */
- break;
- case 2: /* Tuesday */
- case 3: /* Wednedsday */
- case 4: /* Thursday */
- weeknum++;
- break;
- case 5: /* Friday */
- case 6: /* Saturday */
- case 0: /* Sunday */
- if (weeknum == 0) {
+ /*
+ * From 1003.2:
+ * If the week (Monday to Sunday) containing January 1
+ * has four or more days in the new year, then it is week 1;
+ * otherwise it is the highest numbered week of the previous
+ * year (52 or 53), and the next week is week 1.
+ *
+ * ADR: This means if Jan 1 was Monday through Thursday,
+ * it was week 1, otherwise week 52 or 53.
+ *
+ * XPG4 erroneously included POSIX.2 rationale text in the
+ * main body of the standard. Thus it requires week 53.
+ */
+
+ int weeknum, jan1day, diff;
+
+ /* get week number, Monday as first day of the week */
+ weeknum = weeknumber(timeptr, 1);
+
+ /*
+ * With thanks and tip of the hatlo to tml@tik.vtt.fi
+ *
+ * What day of the week does January 1 fall on?
+ * We know that
+ * (timeptr->tm_yday - jan1.tm_yday) MOD 7 ==
+ * (timeptr->tm_wday - jan1.tm_wday) MOD 7
+ * and that
+ * jan1.tm_yday == 0
+ * and that
+ * timeptr->tm_wday MOD 7 == timeptr->tm_wday
+ * from which it follows that. . .
+ */
+ jan1day = timeptr->tm_wday - (timeptr->tm_yday % 7);
+ if (jan1day < 0)
+ jan1day += 7;
+
+ /*
+ * If Jan 1 was a Monday through Thursday, it was in
+ * week 1. Otherwise it was last year's highest week, which is
+ * this year's week 0.
+ *
+ * What does that mean?
+ * If Jan 1 was Monday, the week number is exactly right, it can
+ * never be 0.
+ * If it was Tuesday through Thursday, the weeknumber is one
+ * less than it should be, so we add one.
+ * Otherwise, Friday, Saturday or Sunday, the week number is
+ * OK, but if it is 0, it needs to be 52 or 53.
+ */
+ switch (jan1day) {
+ case 1: /* Monday */
+ break;
+ case 2: /* Tuesday */
+ case 3: /* Wednesday */
+ case 4: /* Thursday */
+ weeknum++;
+ break;
+ case 5: /* Friday */
+ case 6: /* Saturday */
+ case 0: /* Sunday */
+ if (weeknum == 0) {
#ifdef USE_BROKEN_XPG4
- /* XPG4 (as of March 1994) says 53 unconditionally */
- weeknum = 53;
+ /* XPG4 (as of March 1994) says 53 unconditionally */
+ weeknum = 53;
#else
- /* get week number of last week of last year */
- struct tm dec31ly; /* 12/31 last year */
- dec31ly = *timeptr;
- dec31ly.tm_year--;
- dec31ly.tm_mon = 11;
- dec31ly.tm_mday = 31;
- dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1;
- dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900);
- weeknum = iso8601wknum(& dec31ly);
+ /* get week number of last week of last year */
+ struct tm dec31ly; /* 12/31 last year */
+ dec31ly = *timeptr;
+ dec31ly.tm_year--;
+ dec31ly.tm_mon = 11;
+ dec31ly.tm_mday = 31;
+ dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1;
+ dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900);
+ weeknum = iso8601wknum(& dec31ly);
#endif
+ }
+ break;
}
- break;
- }
- return weeknum;
+
+ if (timeptr->tm_mon == 11) {
+ /*
+ * The last week of the year
+ * can be in week 1 of next year.
+ * Sigh.
+ *
+ * This can only happen if
+ * M T W
+ * 29 30 31
+ * 30 31
+ * 31
+ */
+ int wday, mday;
+
+ wday = timeptr->tm_wday;
+ mday = timeptr->tm_mday;
+ if ( (wday == 1 && (mday >= 29 && mday <= 31))
+ || (wday == 2 && (mday == 30 || mday == 31))
+ || (wday == 3 && mday == 31))
+ weeknum = 1;
+ }
+
+ return weeknum;
}
#endif
@@ -629,25 +732,25 @@ static int
weeknumber(const struct tm *timeptr, int firstweekday)
#endif
{
- int wday = timeptr->tm_wday;
- int ret;
-
- if (firstweekday == 1) {
- if (wday == 0) /* sunday */
- wday = 6;
- else
- wday--;
- }
- ret = ((timeptr->tm_yday + 7 - wday) / 7);
- if (ret < 0)
- ret = 0;
- return ret;
+ int wday = timeptr->tm_wday;
+ int ret;
+
+ if (firstweekday == 1) {
+ if (wday == 0) /* sunday */
+ wday = 6;
+ else
+ wday--;
+ }
+ ret = ((timeptr->tm_yday + 7 - wday) / 7);
+ if (ret < 0)
+ ret = 0;
+ return ret;
}
#if 0
/* ADR --- I'm loathe to mess with ado's code ... */
-Date: Wed, 24 Apr 91 20:54:08 MDT
+Date: Wed, 24 Apr 91 20:54:08 MDT
From: Michal Jaegermann <audfax!emory!vm.ucs.UAlberta.CA!NTOMCZAK>
To: arnold@audiofax.com
@@ -661,7 +764,7 @@ in the following form:
*/
{
return (timeptr->tm_yday - timeptr->tm_wday +
- (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7;
+ (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7;
}
How nicer it depends on a compiler, of course, but always a tiny bit.
@@ -674,38 +777,38 @@ How nicer it depends on a compiler, of course, but always a tiny bit.
/*
* NAME:
- * tst
+ * tst
*
* SYNOPSIS:
- * tst
+ * tst
*
* DESCRIPTION:
- * "tst" is a test driver for the function "strftime".
+ * "tst" is a test driver for the function "strftime".
*
* OPTIONS:
- * None.
+ * None.
*
* AUTHOR:
- * Karl Vogel
- * Control Data Systems, Inc.
- * vogelke@c-17igp.wpafb.af.mil
+ * Karl Vogel
+ * Control Data Systems, Inc.
+ * vogelke@c-17igp.wpafb.af.mil
*
* BUGS:
- * None noticed yet.
+ * None noticed yet.
*
* COMPILE:
- * cc -o tst -DTEST_STRFTIME strftime.c
+ * cc -o tst -DTEST_STRFTIME strftime.c
*/
/* ADR: I reformatted this to my liking, and deleted some unneeded code. */
#ifndef NULL
-#include <stdio.h>
+#include <stdio.h>
#endif
-#include <sys/time.h>
-#include <string.h>
+#include <sys/time.h>
+#include <string.h>
-#define MAXTIME 132
+#define MAXTIME 132
/*
* Array of time formats.
@@ -713,42 +816,43 @@ How nicer it depends on a compiler, of course, but always a tiny bit.
static char *array[] =
{
- "(%%A) full weekday name, var length (Sunday..Saturday) %A",
- "(%%B) full month name, var length (January..December) %B",
- "(%%C) Century %C",
- "(%%D) date (%%m/%%d/%%y) %D",
- "(%%E) Locale extensions (ignored) %E",
- "(%%H) hour (24-hour clock, 00..23) %H",
- "(%%I) hour (12-hour clock, 01..12) %I",
- "(%%M) minute (00..59) %M",
- "(%%O) Locale extensions (ignored) %O",
- "(%%R) time, 24-hour (%%H:%%M) %R",
- "(%%S) second (00..61) %S",
- "(%%T) time, 24-hour (%%H:%%M:%%S) %T",
- "(%%U) week of year, Sunday as first day of week (00..53) %U",
- "(%%V) week of year according to ISO 8601 %V",
- "(%%W) week of year, Monday as first day of week (00..53) %W",
- "(%%X) appropriate locale time representation (%H:%M:%S) %X",
- "(%%Y) year with century (1970...) %Y",
- "(%%Z) timezone (EDT), or blank if timezone not determinable %Z",
- "(%%a) locale's abbreviated weekday name (Sun..Sat) %a",
- "(%%b) locale's abbreviated month name (Jan..Dec) %b",
- "(%%c) full date (Sat Nov 4 12:02:33 1989)%n%t%t%t %c",
- "(%%d) day of the month (01..31) %d",
- "(%%e) day of the month, blank-padded ( 1..31) %e",
- "(%%h) should be same as (%%b) %h",
- "(%%j) day of the year (001..366) %j",
- "(%%k) hour, 24-hour clock, blank pad ( 0..23) %k",
- "(%%l) hour, 12-hour clock, blank pad ( 0..12) %l",
- "(%%m) month (01..12) %m",
- "(%%p) locale's AM or PM based on 12-hour clock %p",
- "(%%r) time, 12-hour (same as %%I:%%M:%%S %%p) %r",
- "(%%u) ISO 8601: Weekday as decimal number [1 (Monday) - 7] %u",
- "(%%v) VAX date (dd-bbb-YYYY) %v",
- "(%%w) day of week (0..6, Sunday == 0) %w",
- "(%%x) appropriate locale date representation %x",
- "(%%y) last two digits of year (00..99) %y",
- (char *) NULL
+ "(%%A) full weekday name, var length (Sunday..Saturday) %A",
+ "(%%B) full month name, var length (January..December) %B",
+ "(%%C) Century %C",
+ "(%%D) date (%%m/%%d/%%y) %D",
+ "(%%E) Locale extensions (ignored) %E",
+ "(%%H) hour (24-hour clock, 00..23) %H",
+ "(%%I) hour (12-hour clock, 01..12) %I",
+ "(%%M) minute (00..59) %M",
+ "(%%O) Locale extensions (ignored) %O",
+ "(%%R) time, 24-hour (%%H:%%M) %R",
+ "(%%S) second (00..61) %S",
+ "(%%T) time, 24-hour (%%H:%%M:%%S) %T",
+ "(%%U) week of year, Sunday as first day of week (00..53) %U",
+ "(%%V) week of year according to ISO 8601 %V",
+ "(%%W) week of year, Monday as first day of week (00..53) %W",
+ "(%%X) appropriate locale time representation (%H:%M:%S) %X",
+ "(%%Y) year with century (1970...) %Y",
+ "(%%Z) timezone (EDT), or blank if timezone not determinable %Z",
+ "(%%a) locale's abbreviated weekday name (Sun..Sat) %a",
+ "(%%b) locale's abbreviated month name (Jan..Dec) %b",
+ "(%%c) full date (Sat Nov 4 12:02:33 1989)%n%t%t%t %c",
+ "(%%d) day of the month (01..31) %d",
+ "(%%e) day of the month, blank-padded ( 1..31) %e",
+ "(%%h) should be same as (%%b) %h",
+ "(%%j) day of the year (001..366) %j",
+ "(%%k) hour, 24-hour clock, blank pad ( 0..23) %k",
+ "(%%l) hour, 12-hour clock, blank pad ( 0..12) %l",
+ "(%%m) month (01..12) %m",
+ "(%%p) locale's AM or PM based on 12-hour clock %p",
+ "(%%r) time, 12-hour (same as %%I:%%M:%%S %%p) %r",
+ "(%%u) ISO 8601: Weekday as decimal number [1 (Monday) - 7] %u",
+ "(%%v) VMS date (dd-bbb-YYYY) %v",
+ "(%%w) day of week (0..6, Sunday == 0) %w",
+ "(%%x) appropriate locale date representation %x",
+ "(%%y) last two digits of year (00..99) %y",
+ "(%%z) timezone offset east of GMT as HHMM (e.g. -0500) %z",
+ (char *) NULL
};
/* main routine. */
@@ -758,28 +862,28 @@ main(argc, argv)
int argc;
char **argv;
{
- long time();
+ long time();
- char *next;
- char string[MAXTIME];
+ char *next;
+ char string[MAXTIME];
- int k;
- int length;
+ int k;
+ int length;
- struct tm *tm;
+ struct tm *tm;
- long clock;
+ long clock;
- /* Call the function. */
+ /* Call the function. */
- clock = time((long *) 0);
- tm = localtime(&clock);
+ clock = time((long *) 0);
+ tm = localtime(&clock);
- for (k = 0; next = array[k]; k++) {
- length = strftime(string, MAXTIME, next, tm);
- printf("%s\n", string);
- }
+ for (k = 0; next = array[k]; k++) {
+ length = strftime(string, MAXTIME, next, tm);
+ printf("%s\n", string);
+ }
- exit(0);
+ exit(0);
}
#endif /* TEST_STRFTIME */
diff --git a/node.h b/node.h
index f69258ab4c..eb91c01196 100644
--- a/node.h
+++ b/node.h
@@ -6,14 +6,14 @@
$Date: 1995/01/10 10:42:41 $
created at: Fri May 28 15:14:02 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
#ifndef NODE_H
#define NODE_H
-struct global_entry* rb_global_entry();
+struct global_entry *rb_global_entry();
enum node_type {
NODE_METHOD,
@@ -22,13 +22,18 @@ enum node_type {
NODE_SCOPE,
NODE_BLOCK,
NODE_IF,
+ NODE_UNLESS,
NODE_CASE,
NODE_WHEN,
+ NODE_OPT_N,
NODE_WHILE,
- NODE_WHILE2,
+ NODE_UNTIL,
NODE_ITER,
NODE_FOR,
NODE_BEGIN,
+ NODE_RESCUE,
+ NODE_RESBODY,
+ NODE_ENSURE,
NODE_AND,
NODE_OR,
NODE_NOT,
@@ -47,12 +52,7 @@ enum node_type {
NODE_ARRAY,
NODE_ZARRAY,
NODE_HASH,
- NODE_REDO,
- NODE_BREAK,
- NODE_CONTINUE,
NODE_RETURN,
- NODE_RETRY,
- NODE_FAIL,
NODE_YIELD,
NODE_LVAR,
NODE_DVAR,
@@ -62,12 +62,17 @@ enum node_type {
NODE_CONST,
NODE_NTH_REF,
NODE_BACK_REF,
+ NODE_MATCH_REF,
+ NODE_LASTLINE,
+ NODE_MATCH,
NODE_LIT,
NODE_STR,
- NODE_STR2,
+ NODE_DSTR,
NODE_XSTR,
- NODE_XSTR2,
+ NODE_DXSTR,
+ NODE_EVSTR,
NODE_DREGX,
+ NODE_DREGX_ONCE,
NODE_ARGS,
NODE_DEFN,
NODE_DEFS,
@@ -76,6 +81,7 @@ enum node_type {
NODE_CLASS,
NODE_MODULE,
NODE_COLON2,
+ NODE_CNAME,
NODE_CREF,
NODE_DOT2,
NODE_DOT3,
@@ -85,12 +91,12 @@ enum node_type {
NODE_SELF,
NODE_NIL,
NODE_DEFINED,
+ NODE_TAG,
};
typedef struct RNode {
UINT flags;
char *file;
- unsigned int line;
union {
struct RNode *node;
ID id;
@@ -102,6 +108,7 @@ typedef struct RNode {
struct RNode *node;
ID id;
int argc;
+ VALUE value;
} u2;
union {
struct RNode *node;
@@ -115,9 +122,13 @@ typedef struct RNode {
#define RNODE(obj) (R_CAST(RNode)(obj))
-#define nd_type(n) (((RNODE(n))->flags>>10)&0xff)
+#define nd_type(n) (((RNODE(n))->flags>>10)&0x7f)
#define nd_set_type(n,t) \
- RNODE(n)->flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<<10)&FL_UMASK))
+ RNODE(n)->flags=(RNODE(n)->flags&~FL_UMASK|(((t)<<10)&FL_UMASK))
+
+#define nd_line(n) (((RNODE(n))->flags>>17)&0x7fff)
+#define nd_set_line(n,l) \
+ RNODE(n)->flags=(RNODE(n)->flags&~(-1<<17)|(((l)&0x7fff)<<17))
#define nd_head u1.node
#define nd_alen u2.argc
@@ -126,7 +137,6 @@ typedef struct RNode {
#define nd_cond u1.node
#define nd_body u2.node
#define nd_else u3.node
-#define nd_break u3.state
#define nd_orig u3.value
@@ -181,40 +191,42 @@ typedef struct RNode {
#define nd_beg u1.node
#define nd_end u2.node
#define nd_state u3.state
-#define nd_rval u3.node
+#define nd_rval u3.value
#define nd_nth u2.argc
+#define nd_tag u1.id
+#define nd_tlev u3.cnt
+#define nd_tval u2.value
+
#define NEW_METHOD(n,x) newnode(NODE_METHOD,x,n,0)
#define NEW_FBODY(n,i,o) newnode(NODE_FBODY,n,i,o)
#define NEW_DEFN(i,a,d,p) newnode(NODE_DEFN,p,i,NEW_RFUNC(a,d))
#define NEW_DEFS(r,i,a,d) newnode(NODE_DEFS,r,i,NEW_RFUNC(a,d))
#define NEW_CFUNC(f,c) newnode(NODE_CFUNC,f,c,0)
#define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
-#define NEW_SCOPE(b) newnode(NODE_SCOPE,local_tbl(),(b),local_cnt(0))
+#define NEW_SCOPE(b) newnode(NODE_SCOPE,local_tbl(),(b),cur_cref)
#define NEW_BLOCK(a) newnode(NODE_BLOCK,a,1,0)
#define NEW_IF(c,t,e) newnode(NODE_IF,c,t,e)
+#define NEW_UNLESS(c,t,e) newnode(NODE_UNLESS,c,t,e)
#define NEW_EXNOT(c) newnode(NODE_EXNOT,c,0,0)
#define NEW_CASE(h,b) newnode(NODE_CASE,h,b,0)
#define NEW_WHEN(c,t,e) newnode(NODE_WHEN,c,t,e)
-#define NEW_WHILE(c,b) newnode(NODE_WHILE,c,b,0)
-#define NEW_WHILE2(c,b) newnode(NODE_WHILE2,c,b,0)
+#define NEW_OPT_N(b) newnode(NODE_OPT_N,0,b,0)
+#define NEW_WHILE(c,b,n) newnode(NODE_WHILE,c,b,n)
+#define NEW_UNTIL(c,b,n) newnode(NODE_UNTIL,c,b,n)
#define NEW_FOR(v,i,b) newnode(NODE_FOR,v,b,i)
#define NEW_ITER(v,i,b) newnode(NODE_ITER,v,b,i)
-#define NEW_BEGIN(b,ex,en) newnode(NODE_BEGIN,b,ex,en)
-#define NEW_REDO() newnode(NODE_REDO,0,0,0)
-#define NEW_BREAK() newnode(NODE_BREAK,0,0,0)
-#define NEW_CONT() newnode(NODE_CONTINUE,0,0,0)
-#define NEW_RETRY() newnode(NODE_RETRY,0,0,0)
+#define NEW_BEGIN(b) newnode(NODE_BEGIN,0,b,0)
+#define NEW_RESCUE(b,res) newnode(NODE_RESCUE,b,res,0)
+#define NEW_RESBODY(a,ex,n) newnode(NODE_RESBODY,n,ex,a)
+#define NEW_ENSURE(b,en) newnode(NODE_ENSURE,b,0,en)
#define NEW_RET(s) newnode(NODE_RETURN,s,0,0)
-#define NEW_FAIL(s) newnode(NODE_FAIL,s,0,0)
#define NEW_YIELD(a) newnode(NODE_YIELD,a,0,0)
#define NEW_LIST(a) NEW_ARRAY(a)
#define NEW_ARRAY(a) newnode(NODE_ARRAY,a,1,0)
#define NEW_ZARRAY() newnode(NODE_ZARRAY,0,0,0)
#define NEW_HASH(a) newnode(NODE_HASH,a,0,0)
-#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,0,r)
#define NEW_GASGN(v,val) newnode(NODE_GASGN,v,val,rb_global_entry(v))
@@ -223,19 +235,22 @@ typedef struct RNode {
#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_OP_ASGN2(r,i,o,val) newnode(NODE_OP_ASGN2,r,val,NEW_OP_ASGN3(i,o))
+#define NEW_OP_ASGN3(i,o) newnode(NODE_OP_ASGN2,i,o,0)
#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_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_CVAR(v) newnode(NODE_CVAR,v,0,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_MATCH(c) newnode(NODE_MATCH,c,0,0)
#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)
+#define NEW_DSTR(s) newnode(NODE_DSTR,s,0,0)
#define NEW_XSTR(s) newnode(NODE_XSTR,s,0,0)
-#define NEW_XSTR2(s) newnode(NODE_XSTR2,s,0,0)
+#define NEW_DXSTR(s) newnode(NODE_DXSTR,s,0,0)
+#define NEW_EVSTR(s,l) newnode(NODE_EVSTR,str_new(s,l),0,0)
#define NEW_CALL(r,m,a) newnode(NODE_CALL,r,m,a)
#define NEW_FCALL(m,a) newnode(NODE_FCALL,0,m,a)
#define NEW_SUPER(a) newnode(NODE_SUPER,0,0,a)
@@ -246,9 +261,9 @@ typedef struct RNode {
#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_CREF0() (cur_cref=newnode(NODE_CREF,RNODE(the_frame->cbase)->nd_clss,0,0))
+#define NEW_CREF() (cur_cref=newnode(NODE_CREF,0,0,cur_cref))
+#define NEW_CBODY(b) (cur_cref->nd_body=NEW_SCOPE(b),cur_cref)
#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)
@@ -262,4 +277,7 @@ VALUE rb_method_booundp();
#define NOEX_PUBLIC 0
#define NOEX_PRIVATE 1
+NODE *compile_string();
+NODE *compile_file();
+
#endif
diff --git a/numeric.c b/numeric.c
index ba91d0de21..0ff94dc046 100644
--- a/numeric.c
+++ b/numeric.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:42 $
created at: Fri Aug 13 18:33:09 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -21,114 +21,64 @@ VALUE cFloat;
VALUE cInteger;
VALUE cFixnum;
+VALUE eZeroDiv;
+
ID rb_frame_last_func();
+VALUE float_new();
double big2dbl();
-VALUE
-float_new(d)
- double d;
+void
+num_zerodiv()
{
- NEWOBJ(flt, struct RFloat);
- OBJSETUP(flt, cFloat, T_FLOAT);
-
- flt->value = d;
- return (VALUE)flt;
+ rb_raise(exc_new(eZeroDiv, "divided by 0"));
}
static VALUE
-num_coerce_bin(x, y)
+num_coerce(x, y)
VALUE x, y;
{
- return rb_funcall(rb_funcall(y, coerce, 1, x),
- rb_frame_last_func(), 1, y);
-}
-
-static VALUE
-num_uplus(num)
- VALUE num;
-{
- return num;
-}
-
-static VALUE
-num_uminus(num)
- VALUE num;
-{
- return rb_funcall(rb_funcall(num, coerce, 1, INT2FIX(0)), 1, num);
-}
-
-static VALUE
-num_next(num)
- VALUE num;
-{
- num = rb_funcall(num, rb_intern("to_i"), 0);
- return rb_funcall(num, '+', 1, INT2FIX(1));
+ return assoc_new(f_float(x,x),f_float(y,y));
}
VALUE
-num_upto(from, to)
- VALUE from, to;
+num_coerce_bin(x, y)
+ VALUE x, y;
{
- int i, end;
+ VALUE ary;
- end = NUM2INT(to);
- for (i = NUM2INT(from); i <= end; i++) {
- rb_yield(INT2FIX(i));
+ ary = rb_funcall(y, coerce, 1, x);
+ if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
+ TypeError("coerce must return [x, y]");
}
- return from;
-}
-
-static VALUE
-num_downto(from, to)
- VALUE from, to;
-{
- int i, end;
-
- end = NUM2INT(to);
- for (i=NUM2INT(from); i >= end; i--) {
- rb_yield(INT2FIX(i));
- }
+ x = RARRAY(ary)->ptr[0];
+ y = RARRAY(ary)->ptr[1];
- return from;
+ return rb_funcall(x, rb_frame_last_func(), 1, y);
}
static VALUE
-num_step(from, to, step)
- VALUE from, to, step;
+num_uplus(num)
+ VALUE num;
{
- int i, end, diff;
-
- end = NUM2INT(to);
- diff = NUM2INT(step);
-
- if (diff == 0) {
- Fail("step cannot be 0");
- }
- else if (diff > 0) {
- for (i=NUM2INT(from); i <= end; i+=diff) {
- rb_yield(INT2FIX(i));
- }
- }
- else {
- for (i=NUM2INT(from); i >= end; i+=diff) {
- rb_yield(INT2FIX(i));
- }
- }
- return from;
+ return num;
}
static VALUE
-num_dotimes(num)
+num_uminus(num)
VALUE num;
{
- int i, end;
+ VALUE ary, x, y;
- end = NUM2INT(num);
- for (i=0; i<end; i++) {
- rb_yield(INT2FIX(i));
+ ary = rb_funcall(num, coerce, 1, INT2FIX(0));
+ if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
+ TypeError("coerce must return [x, y]");
}
- return num;
+
+ x = RARRAY(ary)->ptr[0];
+ y = RARRAY(ary)->ptr[1];
+
+ return rb_funcall(x, '-', 1, y);
}
static VALUE
@@ -170,12 +120,45 @@ num_chr(num)
}
static VALUE
+num_abs(num)
+ VALUE num;
+{
+ if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) {
+ return rb_funcall(num, rb_intern("-@"), 0);
+ }
+ return num;
+}
+
+VALUE
+float_new(d)
+ double d;
+{
+ NEWOBJ(flt, struct RFloat);
+ OBJSETUP(flt, cFloat, T_FLOAT);
+
+ flt->value = d;
+ return (VALUE)flt;
+}
+
+static VALUE
flo_to_s(flt)
struct RFloat *flt;
{
char buf[32];
sprintf(buf, "%g", flt->value);
+ if (index(buf, '.') == 0) {
+ int len = strlen(buf);
+
+ if (len > 1 && buf[1] == 'e') {
+ memmove(buf+3, buf+1, len-1);
+ buf[1] = '.';
+ buf[2] = '0';
+ }
+ else {
+ strcat(buf, ".0");
+ }
+ }
return str_new2(buf);
}
@@ -184,18 +167,7 @@ static VALUE
flo_coerce(x, y)
VALUE x, y;
{
- switch (TYPE(y)) {
- case T_FIXNUM:
- return float_new((double)FIX2INT(y));
- case T_FLOAT:
- return y;
- case T_BIGNUM:
- return big_to_f(y);
- default:
- Fail("can't coerce %s to Float", rb_class2name(CLASS_OF(y)));
- }
- /* not reached */
- return Qnil;
+ return assoc_new(f_float(x, y), x);
}
static VALUE
@@ -267,14 +239,14 @@ flo_div(x, y)
switch (TYPE(y)) {
case T_FIXNUM:
f_y = FIX2INT(y);
- if (f_y == 0) Fail("devided by 0");
+ if (f_y == 0) num_zerodiv();
return float_new(x->value / (double)f_y);
case T_BIGNUM:
d = big2dbl(y);
- if (d == 0.0) Fail("devided by 0");
- return float_new(x->value + d);
+ if (d == 0.0) num_zerodiv();
+ return float_new(x->value / d);
case T_FLOAT:
- if (y->value == 0.0) Fail("devided by 0");
+ if (y->value == 0.0) num_zerodiv();
return float_new(x->value / y->value);
default:
return num_coerce_bin(x, y);
@@ -333,30 +305,21 @@ flo_pow(x, y)
}
}
-struct xy {
- VALUE x, y;
-};
-
static VALUE
-eq(arg)
- struct xy *arg;
+num_eql(x, y)
+ VALUE x, y;
{
- return rb_funcall(arg->y, rb_intern("=="), 1, arg->x);
-}
+ if (TYPE(x) != TYPE(y)) return FALSE;
-static VALUE
-eq_rescue()
-{
- return FALSE;
+ return rb_equal(x, y);
}
+
static VALUE
num_equal(x, y)
VALUE x, y;
{
- struct xy arg;
- arg.x = x; arg.y = y;
- return rb_rescue(eq, &arg, eq_rescue, Qnil);
+ return rb_equal(y, x);
}
static VALUE
@@ -364,13 +327,11 @@ flo_eq(x, y)
struct RFloat *x, *y;
{
switch (TYPE(y)) {
- case T_NIL:
- return Qnil;
case T_FIXNUM:
if (x->value == FIX2INT(y)) return TRUE;
return FALSE;
case T_BIGNUM:
- return float_new(x->value == big2dbl(y));
+ return (x->value == big2dbl(y))?TRUE:FALSE;
case T_FLOAT:
return (x->value == y->value)?TRUE:FALSE;
default:
@@ -463,14 +424,15 @@ static VALUE
fail_to_integer(val)
VALUE val;
{
- Fail("failed to convert %s into integer", rb_class2name(CLASS_OF(val)));
+ TypeError("failed to convert %s into Integer",
+ rb_class2name(CLASS_OF(val)));
}
int
num2int(val)
VALUE val;
{
- if (val == Qnil) return 0;
+ if (NIL_P(val)) return 0;
switch (TYPE(val)) {
case T_FIXNUM:
@@ -483,7 +445,6 @@ num2int(val)
}
else {
Fail("float %g out of rang of integer", RFLOAT(val)->value);
- return Qnil; /* not reached */
}
case T_BIGNUM:
@@ -501,7 +462,7 @@ num2fix(val)
{
int v;
- if (val == Qnil) return INT2FIX(0);
+ if (NIL_P(val)) return INT2FIX(0);
switch (TYPE(val)) {
case T_FIXNUM:
return val;
@@ -511,7 +472,7 @@ num2fix(val)
default:
v = num2int(val);
if (!FIXABLE(v))
- Fail("integer %d out of rang of Fixnum", v);
+ Fail("integer %d out of range of Fixnum", v);
return INT2FIX(v);
}
}
@@ -524,6 +485,13 @@ int_int_p(num)
}
static VALUE
+int_succ(num)
+ VALUE num;
+{
+ return rb_funcall(num, '+', 1, INT2FIX(1));
+}
+
+static VALUE
fix_uminus(num)
VALUE num;
{
@@ -541,7 +509,7 @@ fix2str(x, base)
if (base == 10) fmt[1] = 'd';
else if (base == 16) fmt[1] = 'x';
else if (base == 8) fmt[1] = 'o';
- else Fail("fixnum cannot treat base %d", base);
+ else Fatal("fixnum cannot treat base %d", base);
sprintf(buf, fmt, FIX2INT(x));
return str_new2(buf);
@@ -618,11 +586,17 @@ fix_mul(x, y)
switch (TYPE(y)) {
case T_FIXNUM:
{
- int a = FIX2INT(x), b = FIX2INT(y);
- int c = a * b;
- VALUE r = INT2FIX(c);
+ int a, b, c;
+ VALUE r;
- if (FIX2INT(r) != c) {
+ a = FIX2INT(x);
+ if (a == 0) return x;
+
+ b = FIX2INT(y);
+ c = a * b;
+ r = INT2FIX(c);
+
+ if (FIX2INT(r) != c || c/a != b) {
r = big_mul(int2big(a), int2big(b));
}
return r;
@@ -643,7 +617,7 @@ fix_div(x, y)
if (TYPE(y) == T_FIXNUM) {
i = FIX2INT(y);
- if (i == 0) Fail("devided by 0");
+ if (i == 0) num_zerodiv();
i = FIX2INT(x)/i;
return INT2FIX(i);
}
@@ -658,7 +632,7 @@ fix_mod(x, y)
if (TYPE(y) == T_FIXNUM) {
i = FIX2INT(y);
- if (i == 0) Fail("devided by 0");
+ if (i == 0) num_zerodiv();
i = FIX2INT(x)%i;
return INT2FIX(i);
}
@@ -669,8 +643,6 @@ static VALUE
fix_pow(x, y)
VALUE x, y;
{
- extern double pow();
-
if (FIXNUM_P(y)) {
int a, b;
@@ -695,9 +667,6 @@ fix_equal(x, y)
if (FIXNUM_P(y)) {
return (FIX2INT(x) == FIX2INT(y))?TRUE:FALSE;
}
- else if (NIL_P(y)) {
- return Qnil;
- }
else {
return num_equal(x, y);
}
@@ -837,7 +806,7 @@ fix_lshift(x, y)
val = NUM2INT(x);
width = NUM2INT(y);
if (width > (sizeof(VALUE)*CHAR_BIT-1)
- || (unsigned)val>>(sizeof(VALUE)*CHAR_BIT-width) > 0) {
+ || (unsigned)val>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {
return big_lshift(int2big(val), y);
}
val = val << width;
@@ -848,10 +817,15 @@ static VALUE
fix_rshift(x, y)
VALUE x, y;
{
- long val;
+ long i, val;
- val = RSHIFT(NUM2INT(x), NUM2INT(y));
- return INT2FIX(val);
+ i = NUM2INT(y);
+ if (y < 32) {
+ val = RSHIFT(FIX2INT(x), i);
+ return INT2FIX(val);
+ }
+
+ return INT2FIX(0);
}
static VALUE
@@ -890,7 +864,7 @@ static VALUE
fix_type(fix)
VALUE fix;
{
- return cFixnum;
+ return str_new2("Fixnum");
}
static VALUE
@@ -914,7 +888,7 @@ fix_id2name(fix)
}
static VALUE
-fix_next(fix)
+fix_succ(fix)
VALUE fix;
{
int i = FIX2INT(fix) + 1;
@@ -922,7 +896,153 @@ fix_next(fix)
return int2inum(i);
}
+static VALUE
+fix_size(fix)
+ VALUE fix;
+{
+ return INT2FIX(sizeof(VALUE));
+}
+
+VALUE
+num_upto(from, to)
+ VALUE from, to;
+{
+ VALUE i = from;
+
+ for (;;) {
+ if (RTEST(rb_funcall(i, '>', 1, to))) break;
+ rb_yield(i);
+ i = rb_funcall(i, '+', 1, INT2FIX(1));
+ }
+ return from;
+}
+
+static VALUE
+num_downto(from, to)
+ VALUE from, to;
+{
+ VALUE i = from;
+
+ for (;;) {
+ if (RTEST(rb_funcall(i, '<', 1, to))) break;
+ rb_yield(i);
+ i = rb_funcall(i, '-', 1, INT2FIX(1));
+ }
+ return from;
+}
+
+static VALUE
+num_step(from, to, step)
+ VALUE from, to, step;
+{
+ VALUE i = from;
+ ID cmp;
+
+ if (step == INT2FIX(0)) {
+ IndexError("step cannot be 0");
+ }
+
+ if (RTEST(rb_funcall(step, '>', 1, INT2FIX(0)))) {
+ cmp = '>';
+ }
+ else {
+ cmp = '<';
+ }
+ for (;;) {
+ if (RTEST(rb_funcall(i, cmp, 1, to))) break;
+ rb_yield(i);
+ i = rb_funcall(i, '+', 1, step);
+ }
+ return from;
+}
+
+static VALUE
+num_dotimes(num)
+ VALUE num;
+{
+ VALUE i = INT2FIX(0);
+
+ for (;;) {
+ if (!RTEST(rb_funcall(i, '<', 1, num))) break;
+ rb_yield(i);
+ i = rb_funcall(i, '+', 1, INT2FIX(1));
+ }
+ return num;
+}
+
+VALUE
+fix_upto(from, to)
+ VALUE from, to;
+{
+ int i, end;
+
+ if (!FIXNUM_P(to)) return num_upto(from, to);
+ end = FIX2INT(to);
+ for (i = FIX2INT(from); i <= end; i++) {
+ rb_yield(INT2FIX(i));
+ }
+
+ return from;
+}
+
+static VALUE
+fix_downto(from, to)
+ VALUE from, to;
+{
+ int i, end;
+
+ if (!FIXNUM_P(to)) return num_downto(from, to);
+ end = FIX2INT(to);
+ for (i=FIX2INT(from); i >= end; i--) {
+ rb_yield(INT2FIX(i));
+ }
+
+ return from;
+}
+
+static VALUE
+fix_step(from, to, step)
+ VALUE from, to, step;
+{
+ int i, end, diff;
+
+ if (!FIXNUM_P(to) || !FIXNUM_P(step))
+ return num_step(from, to, step);
+
+ end = FIX2INT(to);
+ diff = FIX2INT(step);
+
+ if (diff == 0) {
+ ArgError("step cannot be 0");
+ }
+ else if (diff > 0) {
+ for (i=FIX2INT(from); i <= end; i+=diff) {
+ rb_yield(INT2FIX(i));
+ }
+ }
+ else {
+ for (i=FIX2INT(from); i >= end; i+=diff) {
+ rb_yield(INT2FIX(i));
+ }
+ }
+ return from;
+}
+
+static VALUE
+fix_dotimes(num)
+ VALUE num;
+{
+ int i, end;
+
+ end = FIX2INT(num);
+ for (i=0; i<end; i++) {
+ rb_yield(INT2FIX(i));
+ }
+ return num;
+}
+
extern VALUE mComparable;
+extern VALUE eException;
void
Init_Numeric()
@@ -930,16 +1050,18 @@ Init_Numeric()
coerce = rb_intern("coerce");
to_i = rb_intern("to_i");
+ eZeroDiv = rb_define_class("ZeroDivisionError", eException);
cNumeric = rb_define_class("Numeric", cObject);
- rb_undef_method(CLASS_OF(cNumeric), "new");
-
rb_include_module(cNumeric, mComparable);
+ rb_define_method(cNumeric, "coerce", num_coerce, 1);
+
rb_define_method(cNumeric, "+@", num_uplus, 0);
rb_define_method(cNumeric, "-@", num_uminus, 0);
+ rb_define_method(cNumeric, "eql?", num_eql, 1);
rb_define_method(cNumeric, "divmod", num_divmod, 1);
+ rb_define_method(cNumeric, "abs", num_abs, 0);
- 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);
@@ -949,9 +1071,12 @@ Init_Numeric()
cInteger = rb_define_class("Integer", cNumeric);
rb_define_method(cInteger, "integer?", int_int_p, 0);
+ rb_define_method(cInteger, "succ", int_succ, 0);
cFixnum = rb_define_class("Fixnum", cInteger);
+ rb_undef_method(CLASS_OF(cFixnum), "new");
+
rb_define_method(cFixnum, "to_s", fix_to_s, 0);
rb_define_method(cFixnum, "type", fix_type, 0);
@@ -986,10 +1111,18 @@ Init_Numeric()
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);
+ rb_define_method(cFixnum, "succ", fix_succ, 0);
+ rb_define_method(cFixnum, "size", fix_size, 0);
+
+ rb_define_method(cFixnum, "upto", fix_upto, 1);
+ rb_define_method(cFixnum, "downto", fix_downto, 1);
+ rb_define_method(cFixnum, "step", fix_step, 2);
+ rb_define_method(cFixnum, "times", fix_dotimes, 0);
cFloat = rb_define_class("Float", cNumeric);
+ rb_undef_method(CLASS_OF(cFloat), "new");
+
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);
diff --git a/object.c b/object.c
index 74324b77e7..5b18835613 100644
--- a/object.c
+++ b/object.c
@@ -6,7 +6,7 @@
$Date: 1995/01/12 08:54:49 $
created at: Thu Jul 15 12:01:24 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -18,24 +18,39 @@ VALUE cKernel;
VALUE cObject;
VALUE cModule;
VALUE cClass;
-VALUE cNil;
+VALUE cFixnum;
VALUE cData;
+static VALUE cNil;
+static VALUE cTrue;
+static VALUE cFalse;
+
struct st_table *new_idhash();
VALUE f_sprintf();
VALUE obj_alloc();
-static ID eq;
-
-static ID init;
+static ID eq, eql;
+static ID inspect;
-VALUE
+int
rb_equal(obj1, obj2)
VALUE obj1, obj2;
{
- return rb_funcall(obj1, eq, 1, obj2);
+ VALUE result;
+
+ result = rb_funcall(obj1, eq, 1, obj2);
+ if (result == FALSE || NIL_P(result))
+ return FALSE;
+ return TRUE;
+}
+
+int
+rb_eql(obj1, obj2)
+ VALUE obj1, obj2;
+{
+ return rb_funcall(obj1, eql, 1, obj2);
}
static VALUE
@@ -67,11 +82,13 @@ krn_id(obj)
return obj | FIXNUM_FLAG;
}
+char *rb_class2path();
+
static VALUE
krn_type(obj)
struct RBasic *obj;
{
- return obj->class;
+ return rb_class_path(obj->class);
}
static VALUE
@@ -81,7 +98,7 @@ krn_clone(obj)
VALUE clone;
if (TYPE(obj) != T_OBJECT) {
- Fail("can't clone %s", rb_class2name(CLASS_OF(obj)));
+ TypeError("can't clone %s", rb_class2name(CLASS_OF(obj)));
}
clone = obj_alloc(RBASIC(obj)->class);
@@ -89,6 +106,7 @@ krn_clone(obj)
ROBJECT(clone)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl);
}
RBASIC(clone)->class = singleton_class_clone(RBASIC(obj)->class);
+ RBASIC(clone)->flags = RBASIC(obj)->flags;
return clone;
}
@@ -111,6 +129,13 @@ krn_to_s(obj)
}
VALUE
+rb_inspect(obj)
+ VALUE obj;
+{
+ return rb_funcall(obj, inspect, 0, 0);
+}
+
+static VALUE
krn_inspect(obj)
VALUE obj;
{
@@ -126,8 +151,11 @@ inspect_i(id, value, str)
VALUE str2;
char *ivname;
+ /* need not to show internal data */
+ if (TYPE(value) == T_DATA) return ST_CONTINUE;
if (str->ptr[0] == '-') {
str->ptr[0] = '#';
+ str_cat(str, ": ", 2);
}
else {
str_cat(str, ", ", 2);
@@ -135,7 +163,12 @@ inspect_i(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, 0);
+ if (TYPE(value) == T_OBJECT) {
+ str2 = krn_to_s(value);
+ }
+ else {
+ str2 = rb_inspect(value);
+ }
str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
return ST_CONTINUE;
@@ -145,25 +178,20 @@ static VALUE
obj_inspect(obj)
struct RObject *obj;
{
- VALUE str;
- char buf[256];
+ if (TYPE(obj) == T_OBJECT && obj->iv_tbl) {
+ VALUE str;
+ char buf[256];
- 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, inspect_i, str);
+ str_cat(str, ">", 1);
+ if (RSTRING(str)->ptr[0] == '-') /* no instance-var */
+ return krn_inspect(obj);
- sprintf(buf, "-<%s: ", rb_class2name(CLASS_OF(obj)));
- str = str_new2(buf);
- st_foreach(obj->iv_tbl, inspect_i, str);
- str_cat(str, ">", 1);
-
- return str;
+ return str;
+ }
+ return krn_inspect(obj);
}
VALUE
@@ -177,10 +205,10 @@ obj_is_instance_of(obj, c)
case T_CLASS:
break;
default:
- Fail("class or module required");
+ TypeError("class or module required");
}
- while (FL_TEST(class, FL_SINGLE)) {
+ while (FL_TEST(class, FL_SINGLETON)) {
class = class->super;
}
if (c == (VALUE)class) return TRUE;
@@ -198,7 +226,7 @@ obj_is_kind_of(obj, c)
case T_CLASS:
break;
default:
- Fail("class or module required");
+ TypeError("class or module required");
}
while (class) {
@@ -234,14 +262,21 @@ static VALUE
nil_to_s(obj)
VALUE obj;
{
+ return str_new2("");
+}
+
+static VALUE
+nil_inspect(obj)
+ VALUE obj;
+{
return str_new2("nil");
}
static VALUE
-nil_type(nil)
- VALUE nil;
+nil_type(obj)
+ VALUE obj;
{
- return cNil;
+ return str_new2("Nil");
}
static VALUE
@@ -256,10 +291,10 @@ nil_plus(x, y)
case T_ARRAY:
return y;
default:
- Fail("tried to add %s(%s) to nil",
- RSTRING(obj_as_string(y))->ptr, rb_class2name(CLASS_OF(y)));
+ TypeError("tried to add %s(%s) to nil",
+ RSTRING(obj_as_string(y))->ptr, rb_class2name(CLASS_OF(y)));
}
- return Qnil; /* not reached */
+ /* not reached */
}
static VALUE
@@ -273,29 +308,38 @@ static VALUE
true_to_s(obj)
VALUE obj;
{
- return str_new2("t");
+ return str_new2("TRUE");
}
-VALUE
-obj_alloc(class)
- VALUE class;
+static VALUE
+true_type(obj)
+ VALUE obj;
{
- NEWOBJ(obj, struct RObject);
- OBJSETUP(obj, class, T_OBJECT);
+ return str_new2("TRUE");
+}
- return (VALUE)obj;
+static VALUE
+false_to_s(obj)
+ VALUE obj;
+{
+ return str_new2("FALSE");
}
static VALUE
-mod_new(argc, argv, class)
- int argc;
- VALUE *argv;
+false_type(obj)
+ VALUE obj;
+{
+ return str_new2("FALSE");
+}
+
+VALUE
+obj_alloc(class)
VALUE class;
{
- VALUE obj = obj_alloc(class);
+ NEWOBJ(obj, struct RObject);
+ OBJSETUP(obj, class, T_OBJECT);
- rb_funcall2(obj, init, argc, argv);
- return obj;
+ return (VALUE)obj;
}
static VALUE
@@ -311,8 +355,6 @@ mod_clone(module)
return (VALUE)clone;
}
-char *rb_class2path();
-
static VALUE
mod_to_s(class)
VALUE class;
@@ -320,6 +362,20 @@ mod_to_s(class)
return rb_class_path(class);
}
+VALUE class_s_new(); /* moved to eval.c */
+
+static VALUE
+class_superclass(class)
+ struct RClass *class;
+{
+ struct RClass *super = class->super;
+
+ while (TYPE(super) == T_ICLASS)
+ super = super->super;
+
+ return (VALUE)super;
+}
+
ID
rb_to_id(name)
VALUE name;
@@ -327,7 +383,8 @@ rb_to_id(name)
if (TYPE(name) == T_STRING) {
return rb_intern(RSTRING(name)->ptr);
}
- return NUM2INT(name);
+ Check_Type(name, T_FIXNUM);
+ return FIX2INT(name);
}
static VALUE
@@ -360,8 +417,82 @@ mod_private_attr(class, name)
return Qnil;
}
-static
-VALUE boot_defclass(name, super)
+static VALUE
+f_integer(obj, arg)
+ VALUE obj, arg;
+{
+ int i;
+
+ switch (TYPE(arg)) {
+ case T_FLOAT:
+ if (RFLOAT(arg)->value <= (double)FIXNUM_MAX
+ && RFLOAT(arg)->value >= (double)FIXNUM_MIN) {
+ i = (int)RFLOAT(arg)->value;
+ break;
+ }
+ return dbl2big(RFLOAT(arg)->value);
+
+ case T_BIGNUM:
+ return arg;
+
+ case T_STRING:
+ return str2inum(RSTRING(arg)->ptr, 0);
+
+ default:
+ i = NUM2INT(arg);
+ }
+ return INT2NUM(i);
+}
+
+static VALUE
+to_flo(val)
+ VALUE val;
+{
+ return rb_funcall(val, rb_intern("to_f"), 0);
+}
+
+static VALUE
+fail_to_flo(val)
+ VALUE val;
+{
+ TypeError("failed to convert %s into Float", rb_class2name(CLASS_OF(val)));
+}
+
+double big2dbl();
+
+VALUE
+f_float(obj, arg)
+ VALUE obj, arg;
+{
+
+ switch (TYPE(arg)) {
+ case T_FLOAT:
+ return arg;
+
+ case T_BIGNUM:
+ return float_new(big2dbl(arg));
+
+ default:
+ return rb_rescue(to_flo, arg, fail_to_flo, arg);
+ }
+}
+
+static VALUE
+f_string(obj, arg)
+ VALUE obj, arg;
+{
+ return rb_funcall(arg, rb_intern("to_s"), 0);
+}
+
+static VALUE
+f_array(obj, arg)
+ VALUE obj, arg;
+{
+ return rb_funcall(arg, rb_intern("to_a"), 0);
+}
+
+static VALUE
+boot_defclass(name, super)
char *name;
VALUE super;
{
@@ -371,19 +502,53 @@ VALUE boot_defclass(name, super)
rb_name_class(obj, id);
st_add_direct(rb_class_tbl, id, obj);
- rb_set_class_path(obj, 0, name);
return (VALUE)obj;
}
+VALUE
+rb_class_of(obj)
+ VALUE obj;
+{
+ if (FIXNUM_P(obj)) return cFixnum;
+ if (obj == Qnil) return cNil;
+ if (obj == FALSE) return cFalse;
+ if (obj == TRUE) return cTrue;
+
+ return RBASIC(obj)->class;
+}
+
+int
+rb_type(obj)
+ VALUE obj;
+{
+ if (FIXNUM_P(obj)) return T_FIXNUM;
+ if (obj == Qnil) return T_NIL;
+ if (obj == FALSE) return T_FALSE;
+ if (obj == TRUE) return T_TRUE;
+
+ return BUILTIN_TYPE(obj);
+}
+
+int
+rb_special_const_p(obj)
+ VALUE obj;
+{
+ if (FIXNUM_P(obj)) return TRUE;
+ if (obj == Qnil) return TRUE;
+ if (obj == FALSE) return TRUE;
+ if (obj == TRUE) return TRUE;
+
+ return FALSE;
+}
+
VALUE TopSelf;
-VALUE TRUE = INT2FIX(1);
void
Init_Object()
{
VALUE metaclass;
- cKernel = boot_defclass("Kernel", Qnil);
+ cKernel = boot_defclass("kernel", 0);
cObject = boot_defclass("Object", cKernel);
cModule = boot_defclass("Module", cObject);
cClass = boot_defclass("Class", cModule);
@@ -396,39 +561,40 @@ Init_Object()
/*
* Ruby's Class Hierarchy Chart
*
- * +-------nil +---------------------+
- * | ^ | |
- * | | | |
- * | Kernel----->(Kernel) |
- * | ^ ^ ^ ^ |
- * | | | | | |
- * | +---+ +----+ | +---+ |
- * | | +-----|----+ | |
- * | | | | | |
- * +->Nil->(Nil) Object---->(Object) |
- * ^ ^ ^ ^ |
- * | | | | |
- * | | +-------+ | |
- * | | | | |
- * | +---------+ +------+ |
- * | | | | |
- * +---------+ | Module--->(Module) |
- * | | ^ ^ |
- * OtherClass-->(OtherClass) | | |
- * Class---->(Class) |
- * ^ |
- * | |
- * +----------------+
+ * +------------------------+
+ * | |
+ * kernel----->(kernel) |
+ * ^ ^ ^ ^ |
+ * | | | | |
+ * +---+ +----+ | +---+ |
+ * | +-----|----+ | |
+ * | | | | |
+ * Nil->(Nil) Object---->(Object) |
+ * ^ ^ ^ ^ |
+ * | | | | |
+ * | | +-----+ +---------+ |
+ * | | | | |
+ * | +-----------+ | |
+ * | | | | |
+ * +------+ | Module--->(Module) |
+ * | | ^ ^ |
+ * OtherClass-->(OtherClass) | | |
+ * Class---->(Class) |
+ * ^ |
+ * | |
+ * +----------------+
*
* + All metaclasses are instances of the class `Class'.
*/
-
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_alias(cKernel, "=~", "==");
+ rb_define_method(cKernel, "eql?", rb_equal, 1);
+
rb_define_method(cKernel, "hash", krn_id, 0);
rb_define_method(cKernel, "id", krn_id, 0);
rb_define_method(cKernel, "type", krn_type, 0);
@@ -440,14 +606,32 @@ Init_Object()
rb_define_method(cKernel, "to_s", krn_to_s, 0);
rb_define_method(cKernel, "inspect", krn_inspect, 0);
+ rb_define_method(cKernel, "instance_of?", obj_is_instance_of, 1);
+ rb_define_method(cKernel, "kind_of?", obj_is_kind_of, 1);
+ rb_define_method(cKernel, "is_a?", obj_is_kind_of, 1);
+
rb_define_private_method(cKernel, "sprintf", f_sprintf, -1);
rb_define_alias(cKernel, "format", "sprintf");
+ rb_define_private_method(cKernel, "Integer", f_integer, 1);
+ rb_define_private_method(cKernel, "Float", f_float, 1);
+
+ rb_define_private_method(cKernel, "String", f_string, 1);
+ rb_define_private_method(cKernel, "Array", f_array, 1);
+
+ cNil = rb_define_class("nil", cKernel);
+ rb_define_method(cNil, "type", nil_type, 0);
+ rb_define_method(cNil, "to_s", nil_to_s, 0);
+ rb_define_method(cNil, "inspect", nil_inspect, 0);
+
+ rb_define_method(cNil, "nil?", nil_nil_p, 0);
+
+ /* default addition */
+ rb_define_method(cNil, "+", nil_plus, 1);
+
rb_define_private_method(cObject, "initialize", obj_initialize, -1);
rb_define_private_method(cObject, "singleton_method_added", obj_s_added, 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(cModule, "to_s", mod_to_s, 0);
@@ -455,29 +639,27 @@ Init_Object()
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_private_method(cModule, "object_extended", obj_s_added, 1);
- rb_define_method(cClass, "new", mod_new, -1);
-
- 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(cNil, "nil?", nil_nil_p, 0);
-
- /* default addition */
- rb_define_method(cNil, "+", nil_plus, 1);
+ rb_define_method(cClass, "new", class_s_new, -1);
+ rb_define_method(cClass, "superclass", class_superclass, -1);
cData = rb_define_class("Data", cKernel);
- eq = rb_intern("==");
-
- Qself = TopSelf = obj_alloc(cObject);
+ TopSelf = obj_alloc(cObject);
rb_define_singleton_method(TopSelf, "to_s", main_to_s, 0);
- 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);
+ cTrue = rb_define_class("true", cKernel);
+ rb_define_method(cTrue, "to_s", true_to_s, 0);
+ rb_define_method(cTrue, "type", true_type, 0);
+ rb_define_global_const("TRUE", TRUE);
- init = rb_intern("initialize");
+ cFalse = rb_define_class("false", cKernel);
+ rb_define_method(cFalse, "to_s", false_to_s, 0);
+ rb_define_method(cFalse, "type", false_type, 0);
+ rb_define_global_const("FALSE", FALSE);
+
+ eq = rb_intern("==");
+ eql = rb_intern("eql?");
+ inspect = rb_intern("inspect");
}
diff --git a/pack.c b/pack.c
index ed98970d36..3e54b2ba3a 100644
--- a/pack.c
+++ b/pack.c
@@ -6,7 +6,7 @@
$Date: 1994/12/09 09:40:22 $
created at: Thu Feb 10 15:17:05 JST 1994
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -20,19 +20,23 @@
+(((x)&0x0000FF00)<<8) \
+(((x)&0x00FF0000)>>8) )
#ifdef WORDS_BIGENDIAN
+#ifndef ntohs
#define ntohs(x) (x)
#define ntohl(x) (x)
#define htons(x) (x)
#define htonl(x) (x)
+#endif
#define htovs(x) swaps(x)
#define htovl(x) swapl(x)
#define vtohs(x) swaps(x)
#define vtohl(x) swapl(x)
#else /* LITTLE ENDIAN */
+#ifndef ntohs
#define ntohs(x) swaps(x)
#define ntohl(x) swapl(x)
#define htons(x) swaps(x)
#define htonl(x) swapl(x)
+#endif
#define htovs(x) (x)
#define htovl(x) (x)
#define vtohs(x) (x)
@@ -70,7 +74,7 @@ pack_pack(ary, fmt)
items = ary->len;
idx = 0;
-#define NEXTFROM (items-- > 0 ? ary->ptr[idx++] : (Fail(toofew),0))
+#define NEXTFROM (items-- > 0 ? ary->ptr[idx++] : (ArgError(toofew),0))
while (p < pend) {
type = *p++; /* get data type */
@@ -91,7 +95,7 @@ pack_pack(ary, fmt)
case 'B': case 'b':
case 'H': case 'h':
from = NEXTFROM;
- if (from == Qnil) {
+ if (NIL_P(from)) {
ptr = 0;
plen = 0;
}
@@ -106,30 +110,20 @@ pack_pack(ary, fmt)
switch (type) {
case 'a':
- if (plen > len)
- str_cat(res, ptr, len);
- else {
- str_cat(res, ptr, plen);
- len = plen;
- while (len >= 10) {
- str_cat(res, nul10, 10);
- len -= 10;
- }
- str_cat(res, nul10, len);
- }
- break;
-
case 'A':
- if (plen > len)
+ if (plen >= len)
str_cat(res, ptr, len);
else {
str_cat(res, ptr, plen);
- len = plen;
+ len -= plen;
while (len >= 10) {
- str_cat(res, spc10, 10);
+ if (type == 'A')
+ str_cat(res, spc10, 10);
+ else
+ str_cat(res, nul10, 10);
len -= 10;
}
- str_cat(res, spc10, len);
+ str_cat(res, nul10, len);
}
break;
@@ -244,7 +238,7 @@ pack_pack(ary, fmt)
char c;
from = NEXTFROM;
- if (from == Qnil) c = 0;
+ if (NIL_P(from)) c = 0;
else {
c = NUM2INT(from);
}
@@ -258,7 +252,7 @@ pack_pack(ary, fmt)
short s;
from = NEXTFROM;
- if (from == Qnil) s = 0;
+ if (NIL_P(from)) s = 0;
else {
s = NUM2INT(from);
}
@@ -272,7 +266,7 @@ pack_pack(ary, fmt)
int i;
from = NEXTFROM;
- if (from == Qnil) i = 0;
+ if (NIL_P(from)) i = 0;
else {
i = NUM2INT(from);
}
@@ -286,7 +280,7 @@ pack_pack(ary, fmt)
long l;
from = NEXTFROM;
- if (from == Qnil) l = 0;
+ if (NIL_P(from)) l = 0;
else {
l = NUM2INT(from);
}
@@ -299,7 +293,7 @@ pack_pack(ary, fmt)
short s;
from = NEXTFROM;
- if (from == Qnil) s = 0;
+ if (NIL_P(from)) s = 0;
else {
s = NUM2INT(from);
}
@@ -313,7 +307,7 @@ pack_pack(ary, fmt)
long l;
from = NEXTFROM;
- if (from == Qnil) l = 0;
+ if (NIL_P(from)) l = 0;
else {
l = NUM2INT(from);
}
@@ -367,7 +361,7 @@ pack_pack(ary, fmt)
short s;
from = NEXTFROM;
- if (from == Qnil) s = 0;
+ if (NIL_P(from)) s = 0;
else {
s = NUM2INT(from);
}
@@ -381,7 +375,7 @@ pack_pack(ary, fmt)
long l;
from = NEXTFROM;
- if (from == Qnil) l = 0;
+ if (NIL_P(from)) l = 0;
else {
l = NUM2INT(from);
}
@@ -402,7 +396,7 @@ pack_pack(ary, fmt)
case 'X':
shrink:
if (RSTRING(res)->len < len)
- Fail("X outside of string");
+ ArgError("X outside of string");
RSTRING(res)->len -= len;
RSTRING(res)->ptr[RSTRING(res)->len] = '\0';
break;
@@ -415,7 +409,7 @@ pack_pack(ary, fmt)
break;
case '%':
- Fail("% may only be used in unpack");
+ ArgError("% may only be used in unpack");
break;
case 'u':
@@ -457,7 +451,6 @@ encodes(str, s, len)
char hunk[4];
char *p, *pend;
- p = str->ptr + str->len;
*hunk = len + ' ';
str_cat(str, hunk, 1);
while (len > 0) {
@@ -469,6 +462,7 @@ encodes(str, s, len)
s += 3;
len -= 3;
}
+ p = str->ptr;
pend = str->ptr + str->len;
while (p < pend) {
if (*p == ' ')
@@ -512,7 +506,7 @@ pack_unpack(str, fmt)
switch (type) {
case '%':
- Fail("% is not supported(yet)");
+ ArgError("% is not supported(yet)");
break;
case 'A':
@@ -616,7 +610,10 @@ pack_unpack(str, fmt)
if (len > send - s)
len = send - s;
while (len-- > 0) {
- char c = *s++;
+ int c = *s++;
+#ifdef __CHAR_UNSIGNED__
+ if (c > (char)127) c-=256;
+#endif
ary_push(ary, INT2FIX(c));
}
break;
@@ -781,6 +778,7 @@ pack_unpack(str, fmt)
hunk[3] = '\0';
len = (*s++ - ' ') & 077;
total += len;
+
while (len > 0) {
if (s < send && *s >= ' ')
a = (*s++ - ' ') & 077;
@@ -805,10 +803,10 @@ pack_unpack(str, fmt)
ptr += 3;
len -= 3;
}
- if (*s == '\n')
+ if (*s == '\n' || *s == '\r')
s++;
- else if (s[1] == '\n') /* possible checksum byte */
- s += 2;
+ else if (s+1 == send || s[1] == '\n' || s[1] == '\r')
+ s += 2; /* possible checksum byte */
}
RSTRING(str)->len = total;
ary_push(ary, str);
@@ -821,13 +819,13 @@ pack_unpack(str, fmt)
case 'X':
if (len > s - str->ptr)
- Fail("X outside of string");
+ ArgError("X outside of string");
s -= len;
break;
case 'x':
if (len > send - s)
- Fail("x outside of string");
+ ArgError("x outside of string");
s += len;
break;
diff --git a/parse.y b/parse.y
index cdecb958bc..741dd2573b 100644
--- a/parse.y
+++ b/parse.y
@@ -6,7 +6,7 @@
$Date: 1995/01/12 08:54:50 $
created at: Fri May 28 18:02:42 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -26,11 +26,11 @@
#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_LOCAL 0x01
+#define ID_INSTANCE 0x02
+#define ID_GLOBAL 0x03
+#define ID_ATTRSET 0x04
+#define ID_CONST 0x05
#define is_id_nonop(id) ((id)>LAST_TOKEN)
#define is_local_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
@@ -50,6 +50,7 @@ char *sourcefile; /* current source file */
int sourceline; /* current line no. */
static int yylex();
+static int yyerror();
static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */
@@ -65,6 +66,7 @@ static ID cur_mid = 0;
static int value_expr();
static NODE *cond();
+static NODE *logop();
static NODE *block_append();
static NODE *list_append();
@@ -90,12 +92,12 @@ 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)
+VALUE dyna_var_asgn();
+VALUE dyna_var_defined();
-#define cref_push() NEW_CREF(0)
+#define cref_push() NEW_CREF()
static void cref_pop();
-static NODE *cref_list;
+static NODE *cur_cref;
static void top_local_init();
static void top_local_setup();
@@ -118,46 +120,45 @@ static void top_local_setup();
ENSURE
END
IF
+ UNLESS
THEN
ELSIF
ELSE
CASE
WHEN
WHILE
+ UNTIL
FOR
IN
- REDO
- BREAK
- CONTINUE
+ DO
RETURN
- FAIL
YIELD
SUPER
- RETRY
SELF
NIL
AND
OR
NOT
- _FILE_
- _LINE_
IF_MOD
+ UNLESS_MOD
WHILE_MOD
+ UNTIL_MOD
ALIAS
DEFINED
%token <id> IDENTIFIER FID GVAR IVAR CONSTANT
%token <val> INTEGER FLOAT STRING XSTRING REGEXP
-%token <node> STRING2 XSTRING2 DREGEXP NTH_REF BACK_REF
+%token <node> DSTRING DXSTRING 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 rescue ensure
-%type <node> call_args call_args0 args args2 opt_args
+%type <node> compexpr exprs expr arg primary command_call method_call
+%type <node> if_tail opt_else case_body cases rescue ensure iterator
+%type <node> call_args call_args0 args args2 opt_args var_ref
%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 <node> iter_var opt_iter_var iter_block iter_do_block
+%type <node> mlhs mlhs_head mlhs_tail lhs backref
%type <id> variable symbol operation
%type <id> cname fname op rest_arg
%type <num> f_arg
@@ -166,6 +167,7 @@ static void top_local_setup();
%token POW /* ** */
%token CMP /* <=> */
%token EQ /* == */
+%token EQQ /* === */
%token NEQ /* != <> */
%token GEQ /* >= */
%token LEQ /* <= */
@@ -187,14 +189,15 @@ static void top_local_setup();
* precedence table
*/
-%left IF_MOD WHILE_MOD
-%right NOT
+%left IF_MOD UNLESS_MOD WHILE_MOD UNTIL_MOD
%left OR AND
+%right NOT
+%nonassoc DEFINED
%right '=' OP_ASGN
%nonassoc DOT2 DOT3
%left OROP
%left ANDOP
-%nonassoc CMP EQ NEQ MATCH NMATCH
+%nonassoc CMP EQ EQQ NEQ MATCH NMATCH
%left '>' GEQ '<' LEQ
%left '|' '^'
%left '&'
@@ -203,7 +206,6 @@ static void top_local_setup();
%left '*' '/' '%'
%right '!' '~' UPLUS UMINUS
%right POW
-%left COLON2
%token LAST_TOKEN
@@ -211,32 +213,29 @@ static void top_local_setup();
program : {
lex_state = EXPR_BEG;
top_local_init();
+ NEW_CREF0(); /* initialize constant c-ref */
}
compexpr
{
eval_tree = block_append(eval_tree, $2);
top_local_setup();
+ cur_cref = 0;
}
-compexpr : exprs opt_term
+compexpr : exprs opt_terms
exprs : /* none */
{
- $$ = Qnil;
+ $$ = 0;
}
| expr
- | exprs term expr
+ | exprs terms expr
{
$$ = block_append($1, $3);
}
- | exprs error
- {
- lex_state = EXPR_BEG;
- }
- expr
+ | error expr
{
- yyerrok;
- $$ = block_append($1, $4);
+ $$ = $2;
}
expr : mlhs '=' args2
@@ -253,41 +252,18 @@ expr : mlhs '=' args2
{
value_expr($2);
if (!cur_mid && !in_single)
- Error("return appeared outside of method");
+ yyerror("return appeared outside of method");
$$ = NEW_RET($2);
}
- | FAIL args2
- {
- value_expr($2);
- $$ = NEW_FAIL($2);
- }
| YIELD args2
{
value_expr($2);
$$ = NEW_YIELD($2);
}
- | DEFINED {in_defined = 1;} arg
- {
- in_defined = 0;
- $$ = NEW_DEFINED($3);
- }
- | operation call_args0
- {
- $$ = NEW_FCALL($1, $2);
- }
- | primary '.' operation call_args0
- {
- value_expr($1);
- $$ = NEW_CALL($1, $3, $4);
- }
- | SUPER call_args0
- {
- if (!cur_mid && !in_single && !in_defined)
- Error("super called outside of method");
- $$ = NEW_SUPER($2);
- }
- | UNDEF undef_list
+ | command_call
+ | iterator iter_do_block
{
+ $2->nd_iter = $1;
$$ = $2;
}
| ALIAS fname {lex_state = EXPR_FNAME;} fname
@@ -297,38 +273,76 @@ expr : mlhs '=' args2
| expr IF_MOD expr
{
value_expr($3);
- $$ = NEW_IF(cond($3), $1, Qnil);
+ $$ = NEW_IF(cond($3), $1, 0);
+ }
+ | expr UNLESS_MOD expr
+ {
+ value_expr($3);
+ $$ = NEW_UNLESS(cond($3), $1, 0);
}
| expr WHILE_MOD expr
{
value_expr($3);
if (nd_type($1) == NODE_BEGIN) {
- $$ = NEW_WHILE2(cond($3), $1);
+ $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
}
else {
- $$ = NEW_WHILE(cond($3), $1);
+ $$ = NEW_WHILE(cond($3), $1, 1);
+ }
+ }
+ | expr UNTIL_MOD expr
+ {
+ value_expr($3);
+ if (nd_type($1) == NODE_BEGIN) {
+ $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
+ }
+ else {
+ $$ = NEW_UNTIL(cond($3), $1, 1);
}
}
| expr AND expr
{
- value_expr($1);
- $$ = NEW_AND(cond($1), cond($3));
+ $$ = logop(NODE_AND, $1, $3);
}
| expr OR expr
{
- value_expr($1);
- $$ = NEW_OR(cond($1), cond($3));
+ $$ = logop(NODE_OR, $1, $3);
}
| NOT expr
{
value_expr($2);
$$ = NEW_NOT(cond($2));
}
+ | '!' command_call
+ {
+ value_expr($2);
+ $$ = NEW_NOT(cond($2));
+ }
| arg
+command_call : operation call_args0
+ {
+ $$ = NEW_FCALL($1, $2);
+ }
+ | primary '.' operation call_args0
+ {
+ value_expr($1);
+ $$ = NEW_CALL($1, $3, $4);
+ }
+ | SUPER call_args0
+ {
+ if (!cur_mid && !in_single && !in_defined)
+ yyerror("super called outside of method");
+ $$ = NEW_SUPER($2);
+ }
+ | UNDEF undef_list
+ {
+ $$ = $2;
+ }
+
mlhs : mlhs_head
{
- $$ = NEW_MASGN(NEW_LIST($1), Qnil);
+ $$ = NEW_MASGN(NEW_LIST($1), 0);
}
| mlhs_head STAR lhs
{
@@ -336,51 +350,55 @@ mlhs : mlhs_head
}
| mlhs_head mlhs_tail
{
- $$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),Qnil);
+ $$ = NEW_MASGN(list_concat(NEW_LIST($1),$2), 0);
}
- | mlhs_head mlhs_tail comma STAR lhs
+ | mlhs_head mlhs_tail ',' STAR lhs
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),$5);
}
+ | STAR lhs
+ {
+ $$ = NEW_MASGN(0, $2);
+ }
-mlhs_head : lhs comma
+mlhs_head : lhs ','
mlhs_tail : lhs
{
$$ = NEW_LIST($1);
}
- | mlhs_tail comma lhs
+ | mlhs_tail ',' lhs
{
$$ = list_append($1, $3);
}
lhs : variable
{
- $$ = asignable($1, Qnil);
+ $$ = asignable($1, 0);
}
- | primary '[' opt_args opt_nl rbracket
+ | primary '[' opt_args opt_nl ']'
{
- $$ = aryset($1, $3, Qnil);
+ $$ = aryset($1, $3, 0);
}
| primary '.' IDENTIFIER
{
- $$ = attrset($1, $3, Qnil);
+ $$ = attrset($1, $3, 0);
}
| backref
{
backref_error($1);
- $$ = Qnil;
+ $$ = 0;
}
cname : IDENTIFIER
{
- Error("class/module name must be CONSTANT");
+ yyerror("class/module name must be CONSTANT");
}
| CONSTANT
fname : IDENTIFIER
- | FID
| CONSTANT
+ | FID
| op
{
lex_state = EXPR_END;
@@ -391,9 +409,9 @@ undef_list : fname
{
$$ = NEW_UNDEF($1);
}
- | undef_list ',' fname
+ | undef_list ',' {lex_state = EXPR_FNAME;} fname
{
- $$ = block_append($1, NEW_UNDEF($3));
+ $$ = block_append($1, NEW_UNDEF($4));
}
op : DOT2 { $$ = DOT2; }
@@ -402,6 +420,7 @@ op : DOT2 { $$ = DOT2; }
| '&' { $$ = '&'; }
| CMP { $$ = CMP; }
| EQ { $$ = EQ; }
+ | EQQ { $$ = EQQ; }
| MATCH { $$ = MATCH; }
| '>' { $$ = '>'; }
| GEQ { $$ = GEQ; }
@@ -421,13 +440,14 @@ op : DOT2 { $$ = DOT2; }
| UMINUS { $$ = UPLUS; }
| AREF { $$ = AREF; }
| ASET { $$ = ASET; }
+ | '`' { $$ = '`'; }
arg : variable '=' arg
{
value_expr($3);
$$ = asignable($1, $3);
}
- | primary '[' opt_args opt_nl rbracket '=' arg
+ | primary '[' opt_args opt_nl ']' '=' arg
{
$$ = aryset($1, $3, $7);
}
@@ -439,29 +459,16 @@ arg : variable '=' arg
{
value_expr($3);
backref_error($1);
- $$ = Qnil;
+ $$ = 0;
}
| variable OP_ASGN arg
{
- NODE *val;
-
value_expr($3);
- if (is_local_id($1)) {
- if (local_id($1)) val = NEW_LVAR($1);
- else val = NEW_DVAR($1);
- }
- else if (is_global_id($1)) {
- val = NEW_GVAR($1);
- }
- else if (is_instance_id($1)) {
- val = NEW_IVAR($1);
- }
- else {
- val = NEW_CVAR($1);
- }
- $$ = asignable($1, call_op(val, $2, 1, $3));
+ if (is_local_id($1)&&!local_id($1)&&dyna_in_block())
+ dyna_var_asgn($1, TRUE);
+ $$ = asignable($1, call_op(gettable($1), $2, 1, $3));
}
- | primary '[' opt_args opt_nl rbracket OP_ASGN arg
+ | primary '[' opt_args opt_nl ']' OP_ASGN arg
{
NODE *args = NEW_LIST($7);
@@ -470,12 +477,12 @@ arg : variable '=' arg
}
| primary '.' IDENTIFIER OP_ASGN arg
{
- $$ = NEW_OP_ASGN2($1, $4, $5);
+ $$ = NEW_OP_ASGN2($1, $3, $4, $5);
}
| backref OP_ASGN arg
{
backref_error($1);
- $$ = Qnil;
+ $$ = 0;
}
| arg DOT2 arg
{
@@ -553,6 +560,10 @@ arg : variable '=' arg
{
$$ = call_op($1, EQ, 1, $3);
}
+ | arg EQQ arg
+ {
+ $$ = call_op($1, EQQ, 1, $3);
+ }
| arg NEQ arg
{
$$ = NEW_NOT(call_op($1, EQ, 1, $3));
@@ -582,19 +593,18 @@ arg : variable '=' arg
{
$$ = call_op($1, RSHFT, 1, $3);
}
- | arg COLON2 cname
- {
- $$ = NEW_COLON2($1, $3);
- }
| arg ANDOP arg
{
- value_expr($1);
- $$ = NEW_AND(cond($1), cond($3));
+ $$ = logop(NODE_AND, $1, $3);
}
| arg OROP arg
{
- value_expr($1);
- $$ = NEW_OR(cond($1), cond($3));
+ $$ = logop(NODE_OR, $1, $3);
+ }
+ | DEFINED {in_defined = 1;} arg
+ {
+ in_defined = 0;
+ $$ = NEW_DEFINED($3);
}
| primary
{
@@ -603,25 +613,34 @@ arg : variable '=' arg
call_args : /* none */
{
- $$ = Qnil;
+ $$ = 0;
}
| call_args0 opt_nl
call_args0 : args
+ | command_call
+ {
+ value_expr($1);
+ $$ = NEW_LIST($1);
+ }
| assocs
{
$$ = NEW_LIST(NEW_HASH($1));
}
- | args comma assocs
+ | args ',' command_call
+ {
+ $$ = list_append($1, $3);
+ }
+ | args ',' assocs
{
$$ = list_append($1, NEW_HASH($3));
}
- | args comma assocs comma STAR arg
+ | args ',' assocs ',' STAR arg
{
$$ = list_append($1, NEW_HASH($3));
$$ = call_op($$, '+', 1, $6);
}
- | args comma STAR arg
+ | args ',' STAR arg
{
$$ = call_op($1, '+', 1, $4);
}
@@ -632,7 +651,7 @@ call_args0 : args
opt_args : /* none */
{
- $$ = Qnil;
+ $$ = 0;
}
| args
@@ -641,7 +660,7 @@ args : arg
value_expr($1);
$$ = NEW_LIST($1);
}
- | args comma arg
+ | args ',' arg
{
value_expr($3);
$$ = list_append($1, $3);
@@ -649,7 +668,7 @@ args : arg
args2 : args
{
- if ($1 && $1->nd_next == Qnil) {
+ if ($1 && $1->nd_next == 0) {
$$ = $1->nd_head;
}
else {
@@ -659,7 +678,7 @@ args2 : args
array : /* none */
{
- $$ = Qnil;
+ $$ = 0;
}
| args trailer
@@ -667,85 +686,57 @@ primary : literal
{
$$ = NEW_LIT($1);
}
+ | primary COLON2 cname
+ {
+ $$ = NEW_COLON2($1, $3);
+ }
| STRING
{
$$ = NEW_STR($1);
}
- | STRING2
+ | DSTRING
| XSTRING
{
$$ = NEW_XSTR($1);
}
- | XSTRING2
+ | DXSTRING
| DREGEXP
| var_ref
| backref
- | SUPER '(' call_args rparen
+ | SUPER '(' call_args ')'
{
if (!cur_mid && !in_single && !in_defined)
- Error("super called outside of method");
+ yyerror("super called outside of method");
$$ = NEW_SUPER($3);
}
| SUPER
{
if (!cur_mid && !in_single && !in_defined)
- Error("super called outside of method");
+ yyerror("super called outside of method");
$$ = NEW_ZSUPER();
}
- | primary '[' opt_args opt_nl rbracket
+ | primary '[' opt_args opt_nl ']'
{
value_expr($1);
$$ = NEW_CALL($1, AREF, $3);
}
- | LBRACK array rbracket
+ | LBRACK array ']'
{
- if ($2 == Qnil)
+ if ($2 == 0)
$$ = NEW_ZARRAY(); /* zero length array*/
else {
$$ = $2;
}
}
- | LBRACE assoc_list rbrace
+ | LBRACE assoc_list '}'
{
$$ = NEW_HASH($2);
}
- | REDO
- {
- $$ = NEW_REDO();
- }
- | BREAK
- {
- $$ = NEW_BREAK();
- }
- | CONTINUE
- {
- $$ = NEW_CONT();
- }
- | RETRY
- {
- $$ = NEW_RETRY();
- }
| RETURN
{
if (!cur_mid && !in_single)
- Error("return appeared outside of method");
- $$ = NEW_RET(Qnil);
- }
- | FAIL '(' args2 ')'
- {
- if (nd_type($3) == NODE_ARRAY) {
- Error("wrong number of argument to fail(0 or 1)");
- }
- value_expr($3);
- $$ = NEW_FAIL($3);
- }
- | FAIL '(' ')'
- {
- $$ = NEW_FAIL(Qnil);
- }
- | FAIL
- {
- $$ = NEW_FAIL(Qnil);
+ yyerror("return appeared outside of method");
+ $$ = NEW_RET(0);
}
| YIELD '(' args2 ')'
{
@@ -754,48 +745,31 @@ primary : literal
}
| YIELD '(' ')'
{
- $$ = NEW_YIELD(Qnil);
+ $$ = NEW_YIELD(0);
}
| YIELD
{
- $$ = NEW_YIELD(Qnil);
- }
- | DEFINED '(' {in_defined = 1;} arg ')'
+ $$ = NEW_YIELD(0);
+ }
+ | DEFINED '(' {in_defined = 1;} expr ')'
{
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_CVAR) {
- $1 = NEW_FCALL($1->nd_vid, Qnil);
- }
- $$ = NEW_ITER($4, $1, $5);
- dyna_pop($<vars>3);
- }
| FID
{
- $$ = NEW_FCALL($1, Qnil);
- }
- | operation '(' call_args rparen
- {
- $$ = NEW_FCALL($1, $3);
+ $$ = NEW_FCALL($1, 0);
}
- | primary '.' operation '(' call_args rparen
+ | operation iter_block
{
- value_expr($1);
- $$ = NEW_CALL($1, $3, $5);
+ $2->nd_iter = NEW_FCALL($1, 0);
+ $$ = $2;
}
- | primary '.' operation
+ | method_call
+ | method_call iter_block
{
- value_expr($1);
- $$ = NEW_CALL($1, $3, Qnil);
+ $2->nd_iter = $1;
+ $$ = $2;
}
| IF expr then
compexpr
@@ -805,10 +779,23 @@ primary : literal
value_expr($2);
$$ = NEW_IF(cond($2), $4, $5);
}
+ | UNLESS expr then
+ compexpr
+ opt_else
+ END
+ {
+ value_expr($2);
+ $$ = NEW_UNLESS(cond($2), $4, $5);
+ }
| WHILE expr term compexpr END
{
value_expr($2);
- $$ = NEW_WHILE(cond($2), $4);
+ $$ = NEW_WHILE(cond($2), $4, 1);
+ }
+ | UNTIL expr term compexpr END
+ {
+ value_expr($2);
+ $$ = NEW_UNTIL(cond($2), $4, 1);
}
| CASE compexpr
case_body
@@ -828,16 +815,22 @@ primary : literal
ensure
END
{
- $$ = NEW_BEGIN($2, $3, $4);
+ if (!$3 && !$4)
+ $$ = NEW_BEGIN($2);
+ else {
+ if ($3) $2 = NEW_RESCUE($2, $3);
+ if ($4) $2 = NEW_ENSURE($2, $4);
+ $$ = $2;
+ }
}
- | LPAREN exprs opt_nl rparen
+ | LPAREN compexpr ')'
{
$$ = $2;
}
| CLASS cname superclass
{
if (cur_mid || in_single)
- Error("class definition in method body");
+ yyerror("class definition in method body");
class_nest++;
cref_push();
@@ -854,7 +847,7 @@ primary : literal
| MODULE cname
{
if (cur_mid || in_single)
- Error("module definition in method body");
+ yyerror("module definition in method body");
class_nest++;
cref_push();
local_push();
@@ -870,7 +863,7 @@ primary : literal
| DEF fname
{
if (cur_mid || in_single)
- Error("nested method definition");
+ yyerror("nested method definition");
cur_mid = $2;
local_push();
}
@@ -882,7 +875,7 @@ primary : literal
local_pop();
cur_mid = 0;
}
- | DEF singleton '.' fname
+ | DEF singleton '.' {lex_state = EXPR_FNAME;} fname
{
value_expr($2);
in_single++;
@@ -893,7 +886,7 @@ primary : literal
compexpr
END
{
- $$ = NEW_DEFS($2, $4, $6, $7);
+ $$ = NEW_DEFS($2, $5, $7, $8);
local_pop();
in_single--;
}
@@ -913,7 +906,7 @@ if_tail : opt_else
opt_else : /* none */
{
- $$ = Qnil;
+ $$ = 0;
}
| ELSE compexpr
{
@@ -925,21 +918,79 @@ iter_var : lhs
opt_iter_var : /* node */
{
- $$ = Qnil;
+ $$ = 0;
}
| '|' /* none */ '|'
{
- $$ = Qnil;
+ $$ = 0;
}
| OROP
{
- $$ = Qnil;
+ $$ = 0;
}
| '|' iter_var '|'
{
$$ = $2;
}
+iter_do_block : DO
+ {
+ $<vars>$ = dyna_push();
+ }
+ opt_iter_var
+ compexpr
+ END
+ {
+ $$ = NEW_ITER($3, 0, $4);
+ dyna_pop($<vars>2);
+ }
+
+iter_block : '{'
+ {
+ $<vars>$ = dyna_push();
+ }
+ opt_iter_var
+ compexpr '}'
+ {
+ $$ = NEW_ITER($3, 0, $4);
+ dyna_pop($<vars>2);
+ }
+
+iterator : IDENTIFIER
+ {
+ $$ = NEW_FCALL($1, 0);
+ }
+ | CONSTANT
+ {
+ $$ = NEW_FCALL($1, 0);
+ }
+ | FID
+ {
+ $$ = NEW_FCALL($1, 0);
+ }
+ | method_call
+ | command_call
+
+method_call : operation '(' call_args ')'
+ {
+ $$ = NEW_FCALL($1, $3);
+ }
+ | primary '.' operation '(' call_args ')'
+ {
+ value_expr($1);
+ $$ = NEW_CALL($1, $3, $5);
+ }
+ | primary '.' operation
+ {
+ value_expr($1);
+ $$ = NEW_CALL($1, $3, 0);
+ }
+ | primary COLON2 operation '(' call_args ')'
+ {
+ value_expr($1);
+ $$ = NEW_CALL($1, $3, $5);
+ }
+
case_body : WHEN args then
compexpr
cases
@@ -950,21 +1001,19 @@ case_body : WHEN args then
cases : opt_else
| case_body
-rescue : /* none */
+rescue : RESCUE opt_args term compexpr
+ rescue
{
- $$ = Qnil;
+ $$ = NEW_RESBODY($2, $4, $5);
}
- | RESCUE compexpr
+ | /* none */
{
- if ($2 == Qnil)
- $$ = (NODE*)1;
- else
- $$ = $2;
+ $$ = 0;
}
ensure : /* none */
{
- $$ = Qnil;
+ $$ = 0;
}
| ENSURE compexpr
{
@@ -972,9 +1021,9 @@ ensure : /* none */
}
literal : numeric
- | SYMBEG symbol
+ | SYMBEG {lex_state = EXPR_FNAME;} symbol
{
- $$ = INT2FIX($2);
+ $$ = INT2FIX($3);
}
| REGEXP
@@ -1008,9 +1057,9 @@ backref : NTH_REF
superclass : term
{
- $$ = Qnil;
+ $$ = 0;
}
- | colon
+ | '<'
{
lex_state = EXPR_BEG;
}
@@ -1018,10 +1067,12 @@ superclass : term
{
$$ = $3;
}
+ | error term {yyerrok;}
-f_arglist : '(' f_args rparen
+f_arglist : '(' f_args ')'
{
$$ = $2;
+ lex_state = EXPR_BEG;
}
| f_args term
{
@@ -1036,15 +1087,15 @@ f_args : /* no arg */
{
$$ = NEW_ARGS($1, 0, -1);
}
- | f_arg comma rest_arg
+ | f_arg ',' rest_arg
{
$$ = NEW_ARGS($1, 0, $3);
}
- | f_arg comma f_optarg
+ | f_arg ',' f_optarg
{
$$ = NEW_ARGS($1, $3, -1);
}
- | f_arg comma f_optarg comma rest_arg
+ | f_arg ',' f_optarg ',' rest_arg
{
$$ = NEW_ARGS($1, $3, $5);
}
@@ -1052,7 +1103,7 @@ f_args : /* no arg */
{
$$ = NEW_ARGS(0, $1, -1);
}
- | f_optarg comma rest_arg
+ | f_optarg ',' rest_arg
{
$$ = NEW_ARGS(0, $1, $3);
}
@@ -1060,23 +1111,18 @@ f_args : /* no arg */
{
$$ = NEW_ARGS(0, 0, $1);
}
- | error
- {
- lex_state = EXPR_BEG;
- $$ = NEW_ARGS(0, 0, -1);
- }
f_arg : IDENTIFIER
{
if (!is_local_id($1))
- Error("formal argument must be local variable");
+ yyerror("formal argument must be local variable");
local_cnt($1);
$$ = 1;
}
- | f_arg comma IDENTIFIER
+ | f_arg ',' IDENTIFIER
{
if (!is_local_id($3))
- Error("formal argument must be local variable");
+ yyerror("formal argument must be local variable");
local_cnt($3);
$$ += 1;
}
@@ -1084,7 +1130,7 @@ f_arg : IDENTIFIER
f_opt : IDENTIFIER '=' arg
{
if (!is_local_id($1))
- Error("formal argument must be local variable");
+ yyerror("formal argument must be local variable");
$$ = asignable($1, $3);
}
@@ -1092,7 +1138,7 @@ f_optarg : f_opt
{
$$ = NEW_BLOCK($1);
}
- | f_optarg comma f_opt
+ | f_optarg ',' f_opt
{
$$ = block_append($1, $3);
}
@@ -1100,7 +1146,7 @@ f_optarg : f_opt
rest_arg : STAR IDENTIFIER
{
if (!is_local_id($2))
- Error("rest argument must be local variable");
+ yyerror("rest argument must be local variable");
$$ = local_cnt($2);
}
@@ -1110,25 +1156,25 @@ singleton : var_ref
$$ = NEW_SELF();
}
else if (nd_type($1) == NODE_NIL) {
- Error("Can't define single method for nil.");
- $$ = Qnil;
+ yyerror("Can't define single method for nil.");
+ $$ = 0;
}
else {
$$ = $1;
}
}
- | LPAREN expr opt_nl rparen
+ | LPAREN expr opt_nl ')'
{
switch (nd_type($2)) {
case NODE_STR:
- case NODE_STR2:
+ case NODE_DSTR:
case NODE_XSTR:
- case NODE_XSTR2:
+ case NODE_DXSTR:
case NODE_DREGX:
case NODE_LIT:
case NODE_ARRAY:
case NODE_ZARRAY:
- Error("Can't define single method for literals.");
+ yyerror("Can't define single method for literals.");
default:
break;
}
@@ -1137,7 +1183,7 @@ singleton : var_ref
assoc_list : /* none */
{
- $$ = Qnil;
+ $$ = 0;
}
| assocs trailer
{
@@ -1146,13 +1192,13 @@ assoc_list : /* none */
| args trailer
{
if ($1->nd_alen%2 != 0) {
- Error("odd number list for Hash");
+ yyerror("odd number list for Hash");
}
$$ = $1;
}
assocs : assoc
- | assocs comma assoc
+ | assocs ',' assoc
{
$$ = list_concat($1, $3);
}
@@ -1163,32 +1209,24 @@ assoc : arg ASSOC arg
}
operation : IDENTIFIER
+ | CONSTANT
| FID
-opt_term : /* none */
- | term
+opt_terms : /* none */
+ | terms
opt_nl : /* none */
- | nl
+ | '\n'
trailer : /* none */
- | nl
- | comma
-
-term : sc
- | nl
+ | '\n'
+ | ','
-sc : ';' { yyerrok; }
-nl : '\n' { yyerrok; }
-
-colon : ':'
- | SYMBEG
-
-rparen : ')' { yyerrok; }
-rbracket : ']' { yyerrok; }
-rbrace : '}' { yyerrok; }
-comma : ',' { yyerrok; }
+term : ';' {yyerrok;}
+ | '\n'
+terms : term
+ | terms ';' {yyerrok;}
%%
#include <ctype.h>
#include <sys/types.h>
@@ -1206,51 +1244,138 @@ VALUE newfloat();
VALUE newinteger();
char *strdup();
-static NODE *var_extend();
+static NODE *str_extend();
#define LEAVE_BS 1
+static VALUE lex_input; /* non-nil if File */
+static char *lex_pbeg;
static char *lex_p;
-static int lex_len;
+static char *lex_pend;
-void
-lex_setsrc(src, ptr, len)
- char *src;
- char *ptr;
+static int
+yyerror(msg)
+ char *msg;
+{
+ char *p, *pe, *buf;
+ int len, i;
+
+ Error("%s", msg);
+ p = lex_p;
+ while (lex_pbeg <= p) {
+ if (*p == '\n') break;
+ p--;
+ }
+ p++;
+
+ pe = lex_p;
+ while (pe < lex_pend) {
+ if (*pe == '\n') break;
+ pe++;
+ }
+
+ len = pe - p;
+ if (len > 4) {
+ buf = ALLOCA_N(char, len+2);
+ MEMCPY(buf, p, char, len);
+ buf[len] = '\0';
+ Error_Append("%s", buf);
+
+ i = lex_p - p;
+ p = buf; pe = p + len;
+
+ while (p < pe) {
+ if (*p != '\t') *p = ' ';
+ p++;
+ }
+ buf[i] = '^';
+ buf[i+1] = '\0';
+ Error_Append("%s", buf);
+ }
+
+ return 0;
+}
+
+static int newline_seen;
+
+static NODE*
+yycompile(f)
+ char *f;
+{
+ int n;
+
+ newline_seen = 0;
+ sourcefile = strdup(f);
+ eval_tree = 0;
+ n = yyparse();
+ if (n == 0) return eval_tree;
+
+ return 0;
+}
+
+NODE*
+compile_string(f, s, len)
+ char *f, *s;
int len;
{
- sourcefile = strdup(src);
+ lex_pbeg = lex_p = s;
+ lex_pend = s + len;
+ lex_input = 0;
+ if (!sourcefile || strcmp(f, sourcefile)) /* not in eval() */
+ sourceline = 1;
- sourceline = 1;
- lex_p = ptr;
- lex_len = len;
+ return yycompile(f);
}
-#define nextc() ((--lex_len>=0)?(*lex_p++):-1)
-#define pushback() (lex_len++, lex_p--)
-
-#define SCAN_HEX(i) \
-do { \
- int numlen; \
- i=scan_hex(lex_p, 2, &numlen); \
- lex_p += numlen; \
- lex_len -= numlen; \
-} while (0)
-
-#define SCAN_OCT(i) \
-do { \
- int numlen; \
- i=scan_oct(lex_p, 3, &numlen); \
- lex_p += numlen; \
- lex_len -= numlen; \
-} while (0)
+NODE*
+compile_file(f, file, start)
+ char *f;
+ VALUE file;
+ int start;
+{
+ lex_input = file;
+ lex_pbeg = lex_p = lex_pend = 0;
+ sourceline = start;
+
+ return yycompile(f);
+}
+
+int
+nextc()
+{
+ int c;
+
+ if (lex_p == lex_pend) {
+ if (lex_input) {
+ VALUE v = io_gets(lex_input);
+
+ if (NIL_P(v)) return -1;
+ lex_pbeg = lex_p = RSTRING(v)->ptr;
+ lex_pend = lex_p + RSTRING(v)->len;
+ }
+ else {
+ return -1;
+ }
+ }
+ c = *lex_p++;
+
+ return c;
+}
+
+void
+pushback(c)
+ int c;
+{
+ if (c == -1) return;
+ lex_p--;
+}
#define tokfix() (tokenbuf[tokidx]='\0')
#define tok() tokenbuf
#define toklen() tokidx
#define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
-char *
+char*
newtok()
{
tokidx = 0;
@@ -1307,12 +1432,38 @@ read_escape()
case '0': case '1': case '2': case '3': /* octal constant */
case '4': case '5': case '6': case '7':
- pushback();
- SCAN_OCT(c);
+ pushback(c);
+ {
+ char buf[3];
+ int i;
+
+ for (i=0; i<3; i++) {
+ buf[i] = nextc();
+ if (buf[i] == -1) goto eof;
+ if (buf[i] < '0' || '7' < buf[i]) {
+ pushback(buf[i]);
+ break;
+ }
+ }
+ c = scan_oct(buf, i+1, &i);
+ }
return c;
case 'x': /* hex constant */
- SCAN_HEX(c);
+ {
+ char buf[2];
+ int i;
+
+ for (i=0; i<2; i++) {
+ buf[i] = nextc();
+ if (buf[i] == -1) goto eof;
+ if (!isxdigit(buf[i])) {
+ pushback(buf[i]);
+ break;
+ }
+ }
+ c = scan_hex(buf, i+1, &i);
+ }
return c;
case 'b': /* backspace */
@@ -1320,7 +1471,8 @@ read_escape()
case 'M':
if ((c = nextc()) != '-') {
- Error("Invalid escape character syntax");
+ yyerror("Invalid escape character syntax");
+ pushback(c);
return '\0';
}
if ((c = nextc()) == '\\') {
@@ -1333,7 +1485,8 @@ read_escape()
case 'C':
if ((c = nextc()) != '-') {
- Error("Invalid escape character syntax");
+ yyerror("Invalid escape character syntax");
+ pushback(c);
return '\0';
}
case 'c':
@@ -1348,8 +1501,7 @@ read_escape()
eof:
case -1:
- Error("Invalid escape character syntax");
- pushback();
+ yyerror("Invalid escape character syntax");
return '\0';
default:
@@ -1358,16 +1510,23 @@ read_escape()
}
static int
-parse_regx()
+parse_regx(term)
+ int term;
{
register int c;
int casefold = 0;
int in_brack = 0;
int re_start = sourceline;
- NODE *list = Qnil;
+ int once = 0;
+ int quote = 0;
+ NODE *list = 0;
newtok();
while ((c = nextc()) != -1) {
+ if (!in_brack && c == term) {
+ goto regx_end;
+ }
+
switch (c) {
case '[':
in_brack = 1;
@@ -1377,7 +1536,7 @@ parse_regx()
break;
case '#':
- list = var_extend(list, '/');
+ list = str_extend(list, term);
if (list == (NODE*)-1) return 0;
continue;
@@ -1405,6 +1564,11 @@ parse_regx()
tokadd(c);
break;
+ case '^': /* no \^ escape in regexp */
+ tokadd('\\');
+ tokadd('^');
+ break;
+
case 'b':
if (!in_brack) {
tokadd('\\');
@@ -1413,22 +1577,44 @@ parse_regx()
}
/* fall through */
default:
- pushback();
- tokadd('\\');
- tokadd(read_escape());
+ if (c == '\n') {
+ sourceline++;
+ }
+ else if (c == term) {
+ tokadd(c);
+ }
+ else {
+ pushback(c);
+ tokadd('\\');
+ tokadd(read_escape());
+ }
}
continue;
- case '/': /* end of the regexp */
- if (in_brack)
- break;
+ case -1:
+ Error("unterminated regexp");
+ return 0;
- if ('i' == nextc()) {
- casefold = 1;
+ default:
+ if (ismbchar(c)) {
+ tokadd(c);
+ c = nextc();
}
- else {
- casefold = 0;
- pushback();
+ break;
+
+ regx_end:
+ for (;;) {
+ c = nextc();
+ if (c == 'i') {
+ casefold = 1;
+ }
+ else if (c == 'o') {
+ once = 1;
+ }
+ else {
+ pushback(c);
+ break;
+ }
}
tokfix();
@@ -1438,8 +1624,8 @@ parse_regx()
VALUE ss = str_new(tok(), toklen());
list_append(list, NEW_STR(ss));
}
- nd_set_type(list, NODE_DREGX);
- if (casefold) list->nd_cflag = 1;
+ nd_set_type(list, once?NODE_DREGX_ONCE:NODE_DREGX);
+ list->nd_cflag = casefold;
yylval.node = list;
return DREGEXP;
}
@@ -1447,16 +1633,6 @@ parse_regx()
yylval.val = reg_new(tok(), toklen(), casefold);
return REGEXP;
}
- case -1:
- Error("unterminated regexp");
- return 0;
-
- default:
- if (ismbchar(c)) {
- tokadd(c);
- c = nextc();
- }
- break;
}
tokadd(c);
}
@@ -1465,16 +1641,18 @@ parse_regx()
}
static int
-parse_string(term)
- int term;
+parse_string(func,term)
+ int func, term;
{
int c;
- NODE *list = Qnil;
+ NODE *list = 0;
int strstart;
strstart = sourceline;
newtok();
+
while ((c = nextc()) != term) {
+ str_retry:
if (c == -1) {
unterm_str:
sourceline = strstart;
@@ -1489,7 +1667,7 @@ parse_string(term)
sourceline++;
}
else if (c == '#') {
- list = var_extend(list, term);
+ list = str_extend(list, term);
if (list == (NODE*)-1) goto unterm_str;
continue;
}
@@ -1502,34 +1680,89 @@ parse_string(term)
tokadd(c);
}
else {
- pushback();
- if (term != '"') tokadd('\\');
+ pushback(c);
+ if (func != '"') tokadd('\\');
tokadd(read_escape());
}
continue;
}
tokadd(c);
}
+
tokfix();
lex_state = EXPR_END;
- if (list == Qnil) {
- yylval.val = str_new(tok(), toklen());
- return (term == '`') ? XSTRING : STRING;
- }
- else {
+ if (list) {
if (toklen() > 0) {
VALUE ss = str_new(tok(), toklen());
list_append(list, NEW_STR(ss));
}
yylval.node = list;
- if (term == '`') {
- nd_set_type(list, NODE_XSTR2);
- return XSTRING2;
+ if (func == '`') {
+ nd_set_type(list, NODE_DXSTR);
+ return DXSTRING;
}
else {
- return STRING2;
+ return DSTRING;
}
}
+ else {
+ yylval.val = str_new(tok(), toklen());
+ return (func == '`') ? XSTRING : STRING;
+ }
+}
+
+static int
+parse_qstring(term)
+ int term;
+{
+ int quote = 0;
+ int strstart;
+ int c;
+
+ strstart = sourceline;
+ newtok();
+ while ((c = nextc()) != term) {
+ qstr_retry:
+ if (c == -1) {
+ sourceline = strstart;
+ Error("unterminated string meets end of file");
+ return 0;
+ }
+ if (ismbchar(c)) {
+ tokadd(c);
+ c = nextc();
+ }
+ else if (c == '\n') {
+ sourceline++;
+ }
+ else if (c == '\\') {
+ c = nextc();
+ switch (c) {
+ case '\n':
+ sourceline++;
+ continue;
+
+ case '\\':
+ c = '\\';
+ break;
+
+ case '\'':
+ if (term == '\'') {
+ c = '\'';
+ break;
+ }
+ /* fall through */
+ default:
+ tokadd('\\');
+ }
+ }
+ tokadd(c);
+ }
+
+ tokfix();
+ yylval.val = str_new(tok(), toklen());
+ lex_state = EXPR_END;
+ return STRING;
}
#define LAST(v) ((v)-1 + sizeof(v)/sizeof(v[0]))
@@ -1540,22 +1773,18 @@ static struct kwtable {
enum lex_state state;
} kwtable [] = {
"__END__", 0, EXPR_BEG,
- "__FILE__", _FILE_, EXPR_END,
- "__LINE__", _LINE_, EXPR_END,
"alias", ALIAS, EXPR_FNAME,
"and", AND, EXPR_BEG,
"begin", BEGIN, EXPR_BEG,
- "break", BREAK, EXPR_END,
"case", CASE, EXPR_BEG,
"class", CLASS, EXPR_BEG,
- "continue", CONTINUE, EXPR_END,
"def", DEF, EXPR_FNAME,
"defined?", DEFINED, EXPR_END,
+ "do", DO, EXPR_BEG,
"else", ELSE, EXPR_BEG,
"elsif", ELSIF, EXPR_BEG,
"end", END, EXPR_END,
"ensure", ENSURE, EXPR_BEG,
- "fail", FAIL, EXPR_END,
"for", FOR, EXPR_BEG,
"if", IF, EXPR_BEG,
"in", IN, EXPR_BEG,
@@ -1563,14 +1792,14 @@ static struct kwtable {
"nil", NIL, EXPR_END,
"not", NOT, EXPR_BEG,
"or", OR, EXPR_BEG,
- "redo", REDO, EXPR_END,
- "rescue", RESCUE, EXPR_BEG,
- "retry", RETRY, EXPR_END,
+ "rescue", RESCUE, EXPR_MID,
"return", RETURN, EXPR_MID,
"self", SELF, EXPR_END,
"super", SUPER, EXPR_END,
"then", THEN, EXPR_BEG,
"undef", UNDEF, EXPR_FNAME,
+ "unless", UNLESS, EXPR_BEG,
+ "until", UNTIL, EXPR_BEG,
"when", WHEN, EXPR_BEG,
"while", WHILE, EXPR_BEG,
"yield", YIELD, EXPR_END,
@@ -1589,6 +1818,11 @@ yylex()
int space_seen = 0;
struct kwtable *low = kwtable, *mid, *high = LAST(kwtable);
+ if (newline_seen) {
+ sourceline++;
+ newline_seen = 0;
+ }
+
retry:
switch (c = nextc()) {
case '\0': /* NUL */
@@ -1614,10 +1848,11 @@ retry:
}
/* fall through */
case '\n':
- sourceline++;
- if (lex_state == EXPR_BEG
- || lex_state == EXPR_FNAME)
+ if (lex_state == EXPR_BEG || lex_state == EXPR_FNAME) {
+ sourceline++;
goto retry;
+ }
+ newline_seen++;
lex_state = EXPR_BEG;
return '\n';
@@ -1628,7 +1863,7 @@ retry:
yylval.id = POW;
return OP_ASGN;
}
- pushback();
+ pushback(c);
return POW;
}
if (c == '=') {
@@ -1636,7 +1871,7 @@ retry:
lex_state = EXPR_BEG;
return OP_ASGN;
}
- pushback();
+ pushback(c);
if (lex_state == EXPR_ARG && space_seen && !isspace(c)){
arg_ambiguous();
lex_state = EXPR_BEG;
@@ -1656,12 +1891,16 @@ retry:
if (c == '~') {
return NMATCH;
}
- pushback();
+ pushback(c);
return '!';
case '=':
lex_state = EXPR_BEG;
if ((c = nextc()) == '=') {
+ if ((c = nextc()) == '=') {
+ return EQQ;
+ }
+ pushback(c);
return EQ;
}
if (c == '~') {
@@ -1670,7 +1909,7 @@ retry:
else if (c == '>') {
return ASSOC;
}
- pushback();
+ pushback(c);
return '=';
case '<':
@@ -1679,7 +1918,7 @@ retry:
if ((c = nextc()) == '>') {
return CMP;
}
- pushback();
+ pushback(c);
return LEQ;
}
if (c == '<') {
@@ -1687,10 +1926,10 @@ retry:
yylval.id = LSHFT;
return OP_ASGN;
}
- pushback();
+ pushback(c);
return LSHFT;
}
- pushback();
+ pushback(c);
return '<';
case '>':
@@ -1699,64 +1938,24 @@ retry:
return GEQ;
}
if (c == '>') {
- if (nextc() == '=') {
+ if ((c = nextc()) == '=') {
yylval.id = RSHFT;
return OP_ASGN;
}
- pushback();
+ pushback(c);
return RSHFT;
}
- pushback();
+ pushback(c);
return '>';
case '"':
+ return parse_string(c,c);
case '`':
- return parse_string(c);
+ if (lex_state == EXPR_FNAME) return c;
+ return parse_string(c,c);
case '\'':
- {
- int strstart;
-
- strstart = sourceline;
- newtok();
- while ((c = nextc()) != '\'') {
- if (c == -1) {
- sourceline = strstart;
- Error("unterminated string meets end of file");
- return 0;
- }
- if (ismbchar(c)) {
- tokadd(c);
- c = nextc();
- }
- else if (c == '\n') {
- sourceline++;
- }
- else if (c == '\\') {
- c = nextc();
- switch (c) {
- case '\n':
- sourceline++;
- continue;
-
- case '\'':
- c = '\'';
- break;
- case '\\':
- c = '\\';
- break;
-
- default:
- tokadd('\\');
- }
- }
- tokadd(c);
- }
- tokfix();
- yylval.val = str_new(tok(), toklen());
- lex_state = EXPR_END;
- return STRING;
- }
+ return parse_qstring(c);
case '?':
if ((c = nextc()) == '\\') {
@@ -1776,7 +1975,7 @@ retry:
yylval.id = '&';
return OP_ASGN;
}
- pushback();
+ pushback(c);
return '&';
case '|':
@@ -1788,7 +1987,7 @@ retry:
yylval.id = '|';
return OP_ASGN;
}
- pushback();
+ pushback(c);
return '|';
case '+':
@@ -1797,29 +1996,32 @@ retry:
if (c == '@') {
return UPLUS;
}
- pushback();
+ pushback(c);
return '+';
}
+ if (c == '=') {
+ lex_state = EXPR_BEG;
+ yylval.id = '+';
+ return OP_ASGN;
+ }
if (lex_state == EXPR_ARG) {
- if (!space_seen || c == '=' || isspace(c)) {
+ if (space_seen && !isspace(c)) {
arg_ambiguous();
+ }
+ else {
lex_state = EXPR_END;
}
}
if (lex_state != EXPR_END) {
- pushback();
- if (isdigit(c)) {
+ if (isdigit(c)) {
goto start_num;
}
+ pushback(c);
lex_state = EXPR_BEG;
return UPLUS;
}
lex_state = EXPR_BEG;
- if (c == '=') {
- yylval.id = '+';
- return OP_ASGN;
- }
- pushback();
+ pushback(c);
return '+';
case '-':
@@ -1828,31 +2030,34 @@ retry:
if (c == '@') {
return UMINUS;
}
- pushback();
+ pushback(c);
return '-';
}
+ if (c == '=') {
+ lex_state = EXPR_BEG;
+ yylval.id = '-';
+ return OP_ASGN;
+ }
if (lex_state == EXPR_ARG) {
- if (!space_seen || c == '=' || isspace(c)) {
+ if (space_seen && !isspace(c)) {
arg_ambiguous();
+ }
+ else {
lex_state = EXPR_END;
}
}
if (lex_state != EXPR_END) {
if (isdigit(c)) {
- pushback();
+ pushback(c);
c = '-';
goto start_num;
}
lex_state = EXPR_BEG;
- pushback();
+ pushback(c);
return UMINUS;
}
lex_state = EXPR_BEG;
- if (c == '=') {
- yylval.id = '-';
- return OP_ASGN;
- }
- pushback();
+ pushback(c);
return '-';
case '.':
@@ -1861,10 +2066,10 @@ retry:
if ((c = nextc()) == '.') {
return DOT3;
}
- pushback();
+ pushback(c);
return DOT2;
}
- pushback();
+ pushback(c);
if (!isdigit(c)) {
return '.';
}
@@ -1877,6 +2082,7 @@ retry:
{
int is_float, seen_point, seen_e;
+ is_float = seen_point = seen_e = 0;
lex_state = EXPR_END;
newtok();
if (c == '0') {
@@ -1887,30 +2093,39 @@ retry:
if (!isxdigit(c)) break;
tokadd(c);
}
- pushback();
+ pushback(c);
tokfix();
yylval.val = str2inum(tok(), 16);
return INTEGER;
}
- else if (c >= '0' && c <= '9') {
+ else if (c >= '0' && c <= '7') {
/* octal */
do {
tokadd(c);
c = nextc();
} while (c >= '0' && c <= '9');
- pushback();
+ pushback(c);
tokfix();
yylval.val = str2inum(tok(), 8);
return INTEGER;
}
+ else if (c > '7' && c <= '9') {
+ Error("Illegal octal digit");
+ }
+ else if (c == '.') {
+ tokadd('0');
+ }
+ else {
+ pushback(c);
+ yylval.val = INT2FIX(0);
+ return INTEGER;
+ }
}
if (c == '-' || c == '+') {
tokadd(c);
c = nextc();
}
- is_float = seen_point = seen_e = 0;
-
for (;;) {
switch (c) {
case '0': case '1': case '2': case '3': case '4':
@@ -1922,10 +2137,13 @@ retry:
if (seen_point) {
goto decode_num;
}
- c = nextc();
- if (!isdigit(c)) {
- pushback();
- goto decode_num;
+ else {
+ int c0 = nextc();
+ if (!isdigit(c0)) {
+ pushback(c0);
+ goto decode_num;
+ }
+ c = c0;
}
tokadd('.');
tokadd(c);
@@ -1957,7 +2175,7 @@ retry:
}
decode_num:
- pushback();
+ pushback(c);
tokfix();
if (is_float) {
double atof();
@@ -1981,30 +2199,29 @@ retry:
lex_state = EXPR_BEG;
return COLON2;
}
- pushback();
+ pushback(c);
if (isspace(c))
return ':';
return SYMBEG;
case '/':
- if (lex_state == EXPR_BEG
- || lex_state == EXPR_MID) {
- return parse_regx();
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+ return parse_regx('/');
+ }
+ if ((c = nextc()) == '=') {
+ lex_state = EXPR_BEG;
+ yylval.id = '/';
+ return OP_ASGN;
}
- c = nextc();
if (lex_state == EXPR_ARG) {
- if (space_seen && c != '=' && !isspace(c)) {
- pushback();
+ if (space_seen && !isspace(c)) {
+ pushback(c);
arg_ambiguous();
- return parse_regx();
+ return parse_regx('/');
}
}
lex_state = EXPR_BEG;
- if (c == '=') {
- yylval.id = '/';
- return OP_ASGN;
- }
- pushback();
+ pushback(c);
return '/';
case '^':
@@ -2013,7 +2230,7 @@ retry:
yylval.id = '^';
return OP_ASGN;
}
- pushback();
+ pushback(c);
return c;
case ',':
@@ -2027,15 +2244,14 @@ retry:
case '~':
if (lex_state == EXPR_FNAME) {
if ((c = nextc()) != '@') {
- pushback();
+ pushback(c);
}
}
lex_state = EXPR_BEG;
return c;
case '(':
- if (lex_state == EXPR_BEG
- || lex_state == EXPR_MID) {
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
c = LPAREN;
lex_state = EXPR_BEG;
}
@@ -2055,14 +2271,13 @@ retry:
if ((c = nextc()) == '=') {
return ASET;
}
- pushback();
+ pushback(c);
return AREF;
}
- pushback();
+ pushback(c);
return '[';
}
- else if (lex_state == EXPR_BEG
- || lex_state == EXPR_MID) {
+ else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
c = LBRACK;
}
else if (lex_state == EXPR_ARG && space_seen) {
@@ -2085,25 +2300,71 @@ retry:
space_seen = 1;
goto retry; /* skip \\n */
}
- pushback();
+ pushback(c);
return '\\';
case '%':
- lex_state = EXPR_BEG;
- if (nextc() == '=') {
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+ int term;
+
+ c = nextc();
+ quotation:
+ if (!isalnum(c)) {
+ term = c;
+ c = '"';
+ }
+ else {
+ term = nextc();
+ }
+ if (c == -1 || term == -1) {
+ Error("unterminated quoted string meets end of file");
+ return 0;
+ }
+ if (term == '(') term = ')';
+ else if (term == '[') term = ']';
+ else if (term == '{') term = '}';
+ else if (term == '<') term = '>';
+
+ switch (c) {
+ case 'Q':
+ return parse_string('"', term);
+
+ case 'q':
+ return parse_qstring(term);
+
+ case 'x':
+ return parse_string('`', term);
+
+ case 'r':
+ return parse_regx(term);
+
+ default:
+ Error("unknown type of string `%c'", c);
+ return 0;
+ }
+ }
+ if ((c = nextc()) == '=') {
yylval.id = '%';
return OP_ASGN;
}
- pushback();
- return c;
+ if (lex_state == EXPR_ARG) {
+ if (space_seen && !isspace(c)) {
+ arg_ambiguous();
+ goto quotation;
+ }
+ }
+ lex_state = EXPR_BEG;
+ pushback(c);
+ return '%';
case '$':
lex_state = EXPR_END;
newtok();
c = nextc();
switch (c) {
+ case '_': /* $_: last read line string */
case '~': /* $~: match-data */
- local_cnt('~');
+ local_cnt(c);
/* fall through */
case '*': /* $*: argv */
case '$': /* $$: pid */
@@ -2112,9 +2373,9 @@ retry:
case '@': /* $@: error position */
case '/': /* $/: input record separator */
case '\\': /* $\: output record separator */
+ case ';': /* $;: field separator */
case ',': /* $,: output field separator */
case '.': /* $.: last read line number */
- case '_': /* $_: last read line string */
case '=': /* $=: ignorecase */
case ':': /* $:: load path */
case '<': /* $<: reading filename */
@@ -2140,14 +2401,14 @@ retry:
tokadd(c);
c = nextc();
}
- pushback();
+ pushback(c);
tokfix();
yylval.node = NEW_NTH_REF(atoi(tok()));
return NTH_REF;
default:
if (!is_identchar(c)) {
- pushback();
+ pushback(c);
return '$';
}
case '0':
@@ -2158,7 +2419,7 @@ retry:
case '@':
c = nextc();
if (!is_identchar(c)) {
- pushback();
+ pushback(c);
return '@';
}
newtok();
@@ -2187,7 +2448,7 @@ retry:
tokadd(c);
}
else {
- pushback();
+ pushback(c);
}
tokfix();
@@ -2213,7 +2474,9 @@ retry:
if (state != EXPR_BEG
&& state != EXPR_BEG) {
if (mid->id == IF) return IF_MOD;
+ if (mid->id == UNLESS) return UNLESS_MOD;
if (mid->id == WHILE) return WHILE_MOD;
+ if (mid->id == UNTIL) return UNTIL_MOD;
}
return mid->id;
}
@@ -2231,7 +2494,7 @@ retry:
tokadd(c);
}
else {
- pushback();
+ pushback(c);
}
}
else if (lex_state == EXPR_BEG){
@@ -2255,68 +2518,43 @@ retry:
}
static NODE*
-var_extend(list, term)
+str_extend(list, term)
NODE *list;
char term;
{
- int c, t, brace;
+ int c;
VALUE ss;
NODE *node;
ID id;
+ int nest;
c = nextc();
switch (c) {
case '$':
+ case '@':
case '{':
break;
- case '@':
- t = nextc();
- pushback();
- if (!is_identchar(t)) {
- tokadd('#');
- tokadd(c);
- return list;
- }
default:
tokadd('#');
- pushback();
+ pushback(c);
return list;
}
ss = str_new(tok(), toklen());
- if (list == Qnil) {
- list = NEW_STR2(ss);
+ if (list == 0) {
+ list = NEW_DSTR(ss);
}
else if (toklen() > 0) {
list_append(list, NEW_STR(ss));
}
newtok();
- if (c == '{') {
- brace = 1;
- c = nextc();
- }
- else {
- brace = 0;
- }
switch (c) {
case '$':
+ tokadd('$');
c = nextc();
if (c == -1) return (NODE*)-1;
switch (c) {
- case '&':
- case '`':
- case '\'':
- case '+':
- node = NEW_BACK_REF(c);
- c = nextc();
- 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':
@@ -2324,55 +2562,108 @@ var_extend(list, term)
tokadd(c);
c = nextc();
}
- tokfix();
- node = NEW_NTH_REF(atoi(tok()));
- goto append_node;
- }
+ pushback(c);
+ goto fetch_id;
- tokadd('$');
- if (!is_identchar(c)) {
+ case '&': case '+':
+ case '_': case '~':
+ case '*': case '$': case '?':
+ case '!': case '@': case ',':
+ case '.': case '=': case ':':
+ case '<': case '>': case '\\':
+ refetch:
tokadd(c);
goto fetch_id;
+
+ default:
+ if (c == term) {
+ list_append(list, NEW_STR(str_new2("#$")));
+ pushback(c);
+ return list;
+ }
+ switch (c) {
+ case '\"':
+ case '/':
+ case '\'':
+ case '`':
+ goto refetch;
+ }
+ if (!is_identchar(c)) {
+ yyerror("bad global variable in string");
+ newtok();
+ return list;
+ }
}
/* through */
- case '@':
+
+ case '@':
tokadd(c);
c = nextc();
- break;
- }
- while (is_identchar(c)) {
- tokadd(c);
- if (ismbchar(c)) {
- c = nextc();
+ while (is_identchar(c)) {
tokadd(c);
+ if (ismbchar(c)) {
+ c = nextc();
+ tokadd(c);
+ }
+ c = nextc();
}
- c = nextc();
+ pushback(c);
+ break;
+
+ case '{':
+ nest = 0;
+ do {
+ loop_again:
+ c = nextc();
+ switch (c) {
+ case -1:
+ if (nest > 0) {
+ bad_sub:
+ Error("bad substitution in string");
+ newtok();
+ return list;
+ }
+ return (NODE*)-1;
+ case '}':
+ if (nest == 0) break;
+ nest--;
+ tokadd(c);
+ goto loop_again;
+ case '\\':
+ c = read_escape();
+ tokadd(c);
+ goto loop_again;
+ case '{':
+ nest++;
+ case '\"':
+ case '/':
+ case '`':
+ if (c == term) {
+ pushback(c);
+ list_append(list, NEW_STR(str_new2("#")));
+ Warning("bad substitution in string");
+ tokfix();
+ list_append(list, NEW_STR(str_new(tok(), toklen())));
+ newtok();
+ return list;
+ }
+ add_char:
+ default:
+ tokadd(c);
+ break;
+ }
+ } while (c != '}');
}
fetch_id:
tokfix();
- if (strcmp("__LINE__", tok()) == 0)
- id = _LINE_;
- else if (strcmp("__FILE__", tok()) == 0)
- id = _FILE_;
- else
- id = rb_intern(tok());
- id_node:
- node = gettable(id);
-
- append_node:
- if (brace) {
- if (c != '}')
- Error("Invalid variable name in string");
- }
- else pushback();
-
+ node = NEW_EVSTR(tok(),toklen());
list_append(list, node);
newtok();
+
return list;
}
-
NODE*
newnode(type, a0, a1, a2)
enum node_type type;
@@ -2382,7 +2673,7 @@ newnode(type, a0, a1, a2)
n->flags |= T_NODE;
nd_set_type(n, type);
- n->line = sourceline;
+ nd_set_line(n, sourceline);
n->file = sourcefile;
n->u1.node = a0;
@@ -2406,8 +2697,8 @@ block_append(head, tail)
extern int verbose;
NODE *last;
- if (tail == Qnil) return head;
- if (head == Qnil) return tail;
+ if (tail == 0) return head;
+ if (head == 0) return tail;
if (nd_type(head) != NODE_BLOCK)
head = last = NEW_BLOCK(head);
@@ -2420,11 +2711,7 @@ block_append(head, tail)
if (verbose) {
switch (nd_type(last->nd_head)) {
- case NODE_BREAK:
- case NODE_CONTINUE:
- case NODE_REDO:
case NODE_RETURN:
- case NODE_RETRY:
Warning("statement not reached");
break;
@@ -2447,7 +2734,7 @@ list_append(head, tail)
{
NODE *last;
- if (head == Qnil) return NEW_LIST(tail);
+ if (head == 0) return NEW_LIST(tail);
last = head;
while (last->nd_next) {
@@ -2465,11 +2752,6 @@ list_concat(head, tail)
{
NODE *last;
-#if 0
- if (nd_type(head) != NODE_ARRAY || nd_type(tail) != NODE_ARRAY)
- Bug("list_concat() called with non-list");
-#endif
-
last = head;
while (last->nd_next) {
last = last->nd_next;
@@ -2493,7 +2775,7 @@ call_op(recv, id, narg, arg1)
value_expr(arg1);
}
- return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):Qnil);
+ return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):0);
}
static NODE*
@@ -2506,19 +2788,11 @@ gettable(id)
else if (id == NIL) {
return NEW_NIL();
}
- else if (id == _LINE_) {
- return NEW_LIT(INT2FIX(sourceline));
- }
- else if (id == _FILE_) {
- VALUE s = str_new2(sourcefile);
-
- return NEW_STR(s);
- }
else if (is_local_id(id)) {
if (local_id(id)) return NEW_LVAR(id);
- if (dyna_id(id)) return NEW_DVAR(id);
+ if (dyna_var_defined(id)) return NEW_DVAR(id);
/* method call without arguments */
- return NEW_FCALL(id, Qnil);
+ return NEW_FCALL(id, 0);
}
else if (is_global_id(id)) {
return NEW_GVAR(id);
@@ -2530,7 +2804,7 @@ gettable(id)
return NEW_CVAR(id);
}
Bug("invalid id for gettable");
- return Qnil;
+ return 0;
}
static NODE*
@@ -2538,17 +2812,13 @@ asignable(id, val)
ID id;
NODE *val;
{
- extern VALUE dyna_var_asgn();
- NODE *lhs = Qnil;
+ NODE *lhs = 0;
if (id == SELF) {
- Error("Can't change the value of self");
+ yyerror("Can't change the value of self");
}
else if (id == NIL) {
- Error("Can't asign to nil");
- }
- else if (id == _LINE_ || id == _FILE_) {
- Error("Can't asign to special identifier");
+ yyerror("Can't asign to nil");
}
else if (is_local_id(id)) {
if (local_id(id) || !dyna_in_block())
@@ -2566,7 +2836,7 @@ asignable(id, val)
}
else if (is_const_id(id)) {
if (cur_mid || in_single)
- Error("class constant asigned in method body");
+ yyerror("dynamic constant asignment");
lhs = NEW_CASGN(id, val);
}
else {
@@ -2625,22 +2895,17 @@ static int
value_expr(node)
NODE *node;
{
- if (node == Qnil) return TRUE;
+ if (node == 0) return TRUE;
switch (nd_type(node)) {
case NODE_RETURN:
- case NODE_CONTINUE:
- case NODE_BREAK:
- case NODE_REDO:
- case NODE_RETRY:
- case NODE_FAIL:
case NODE_WHILE:
- case NODE_WHILE2:
+ case NODE_UNTIL:
case NODE_CLASS:
case NODE_MODULE:
case NODE_DEFN:
case NODE_DEFS:
- Error("void value expression");
+ yyerror("void value expression");
return FALSE;
break;
@@ -2666,19 +2931,26 @@ cond0(node)
{
enum node_type type = nd_type(node);
- if (type == NODE_STR || type == NODE_STR2 || type == NODE_DREGX) {
+ switch (type) {
+ case NODE_DREGX:
+ case NODE_DREGX_ONCE:
return call_op(NEW_GVAR(rb_intern("$_")),MATCH,1,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) {
+
+ case NODE_DOT2:
+ case 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;
+
+ case NODE_LIT:
+ if (TYPE(node->nd_lit) == T_REGEXP) {
+ return NEW_MATCH(node);
+ }
+ default:
+ return node;
}
- return node;
}
static NODE*
@@ -2700,7 +2972,7 @@ cond(node)
node = cond0(node);
if (type == NODE_CALL && node->nd_mid == '!') {
- if (node->nd_args || node->nd_recv == Qnil) {
+ if (node->nd_args || node->nd_recv == 0) {
Bug("method `!' called with wrong # of operand");
}
node->nd_recv = cond0(node->nd_recv);
@@ -2719,6 +2991,16 @@ cond2(node)
return node;
}
+static NODE*
+logop(type, left, right)
+ enum node_type type;
+ NODE *left, *right;
+{
+ value_expr(left);
+
+ return newnode(type, cond(left), cond(right));
+}
+
st_table *new_idhash();
static struct local_vars {
@@ -2797,10 +3079,8 @@ local_id(id)
static void
top_local_init()
{
- if (lvtbl == 0) {
- local_push();
- }
- else if (the_scope->local_tbl) {
+ local_push();
+ if (the_scope->local_tbl) {
lvtbl->cnt = the_scope->local_tbl[0];
}
else {
@@ -2813,7 +3093,6 @@ top_local_init()
else {
lvtbl->tbl = 0;
}
- NEW_CREF0(); /* initialize constant c-ref */
lvtbl->dlev = (the_dyna_vars?1:0);
}
@@ -2832,26 +3111,23 @@ top_local_setup()
the_scope->local_vars = ALLOC_N(VALUE, len);
if (vars) {
MEMCPY(the_scope->local_vars, vars, VALUE, i);
- MEMZERO(the_scope->local_vars+i, VALUE, len-i);
+ memclear(the_scope->local_vars+i, len-i);
}
else {
- MEMZERO(the_scope->local_vars, VALUE, len);
+ memclear(the_scope->local_vars, len);
}
the_scope->flag = SCOPE_MALLOC;
}
else {
REALLOC_N(the_scope->local_vars, VALUE, len);
- MEMZERO(the_scope->local_vars+i, VALUE, len-i);
+ memclear(the_scope->local_vars+i, len-i);
free(the_scope->local_tbl);
}
lvtbl->tbl[0] = len;
the_scope->local_tbl = lvtbl->tbl;
}
- else if (lvtbl->tbl) {
- free(lvtbl->tbl);
- }
}
- cref_list = Qnil;
+ local_pop();
}
static struct RVarmap*
@@ -2878,10 +3154,9 @@ dyna_in_block()
static void
cref_pop()
{
- NODE *cref = cref_list;
+ NODE *cref = cur_cref;
- cref_list = cref_list->nd_next;
- cref->nd_next = Qnil;
+ cur_cref = cur_cref->nd_next;
}
void
@@ -2893,22 +3168,22 @@ yyappend_print()
}
void
-yywhole_loop(chop, split)
+yywhile_loop(chop, split)
int chop, split;
{
if (split) {
eval_tree =
block_append(NEW_GASGN(rb_intern("$F"),
NEW_CALL(NEW_GVAR(rb_intern("$_")),
- rb_intern("split"), Qnil)),
+ rb_intern("split"), 0)),
eval_tree);
}
if (chop) {
eval_tree =
block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
- rb_intern("chop!"), Qnil), eval_tree);
+ rb_intern("chop!"), 0), eval_tree);
}
- eval_tree = NEW_WHILE(NEW_FCALL(rb_intern("gets"),0),eval_tree);
+ eval_tree = NEW_OPT_N(eval_tree);
}
static struct op_tbl rb_op_tbl[] = {
@@ -2934,6 +3209,7 @@ static struct op_tbl rb_op_tbl[] = {
'<', "<",
LEQ, "<=",
EQ, "==",
+ EQQ, "===",
NEQ, "!=",
MATCH, "=~",
NMATCH, "!~",
@@ -2948,7 +3224,8 @@ static struct op_tbl rb_op_tbl[] = {
LSHFT, "<<",
RSHFT, ">>",
COLON2, "::",
- Qnil, Qnil,
+ '`', "`",
+ 0, 0,
};
char *rb_id2name();
@@ -2963,8 +3240,8 @@ Init_sym()
{
int strcmp();
- sym_tbl = st_init_table(strcmp, st_strhash);
- rb_global_variable(&cref_list);
+ sym_tbl = st_init_strtable();
+ rb_global_variable(&cur_cref);
}
ID
@@ -3027,15 +3304,19 @@ rb_intern(name)
return id;
}
-static char *find_ok;
+struct find_ok {
+ ID id;
+ char *name;
+};
static int
-id_find(name, id1, id2)
+id_find(name, id1, ok)
char *name;
- ID id1, id2;
+ ID id1;
+ struct find_ok *ok;
{
- if (id1 == id2) {
- find_ok = name;
+ if (id1 == ok->id) {
+ ok->name = name;
return ST_STOP;
}
return ST_CONTINUE;
@@ -3045,7 +3326,7 @@ char *
rb_id2name(id)
ID id;
{
- find_ok = 0;
+ struct find_ok ok;
if (id < LAST_TOKEN) {
int i = 0;
@@ -3056,8 +3337,10 @@ rb_id2name(id)
}
}
- st_foreach(sym_tbl, id_find, id);
- if (!find_ok && is_attrset_id(id)) {
+ ok.name = 0;
+ ok.id = id;
+ st_foreach(sym_tbl, id_find, &ok);
+ if (!ok.name && is_attrset_id(id)) {
char *res;
ID id2;
@@ -3073,7 +3356,7 @@ rb_id2name(id)
return rb_id2name(id);
}
}
- return find_ok;
+ return ok.name;
}
static int
@@ -3095,3 +3378,84 @@ rb_const_check(class, module)
{
st_foreach(module->iv_tbl, const_check, class);
}
+
+void
+local_var_append(id)
+ ID id;
+{
+ struct local_vars tmp;
+ struct local_vars *save = lvtbl;
+
+ if (the_scope->local_tbl) {
+ tmp.cnt = the_scope->local_tbl[0];
+ tmp.tbl = the_scope->local_tbl;
+ lvtbl->dlev = 0;
+ }
+ lvtbl = &tmp;
+ local_cnt(id);
+ lvtbl = save;
+}
+
+static VALUE
+special_local_get(c)
+ char c;
+{
+ 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] == c) {
+ return the_scope->local_vars[cnt-1];
+ }
+ }
+ return Qnil;
+}
+
+static void
+special_local_set(c, val)
+ char c;
+ VALUE val;
+{
+ int cnt, max;
+
+ if (the_scope->local_tbl) {
+ for (cnt=1, max=the_scope->local_tbl[0]+1; cnt<max ;cnt++) {
+ if (the_scope->local_tbl[cnt] == c) {
+ the_scope->local_vars[cnt-1] = val;
+ return;
+ }
+ }
+ }
+ top_local_init();
+ cnt = local_cnt(c);
+ top_local_setup();
+ the_scope->local_vars[cnt] = val;
+}
+
+VALUE
+backref_get()
+{
+ return special_local_get('~');
+}
+
+void
+backref_set(val)
+ VALUE val;
+{
+ special_local_set('~', val);
+}
+
+VALUE
+lastline_get()
+{
+ VALUE v = special_local_get('_');
+ if (v == 1) return Qnil; /* $_ undefined */
+ return v;
+}
+
+void
+lastline_set(val)
+ VALUE val;
+{
+ special_local_set('_', val);
+}
diff --git a/process.c b/process.c
index 116a93f965..29f61ddd42 100644
--- a/process.c
+++ b/process.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:47 $
created at: Tue Aug 10 14:30:50 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -25,7 +25,12 @@ struct timeval {
};
#endif
-#include <sys/resource.h>
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifdef HAVE_GETPRIORITY
+# include <sys/resource.h>
+#endif
#ifdef HAVE_VFORK_H
#include <vfork.h>
#endif
@@ -51,7 +56,7 @@ get_ppid()
#define HAVE_WAITPID
#endif
-static VALUE status;
+VALUE last_status = Qnil;
#if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
static st_table *pid_tbl;
@@ -59,55 +64,72 @@ static st_table *pid_tbl;
# define WAIT_CALL
#endif
-int
-rb_waitpid(pid, flags)
+static int
+rb_waitpid(pid, flags, st)
int pid;
int flags;
+ int *st;
{
- int result, st;
+ int result;
#ifdef HAVE_WAITPID
- result = waitpid(pid, &st, flags);
+ retry:
+ result = waitpid(pid, st, flags);
+ if (result < 0) {
+ if (errno == EINTR) goto retry;
+ return -1;
+ }
#else
#ifdef HAVE_WAIT4
- result = wait4(pid, &st, flags, NULL);
+ retry:
+ result = wait4(pid, st, flags, NULL);
+ if (result < 0) {
+ if (errno == EINTR) goto retry;
+ return -1;
+ }
#else
- if (pid_tbl && st_lookup(pid_tbl, pid, &st)) {
- status = INT2FIX(st);
+ if (pid_tbl && st_lookup(pid_tbl, pid, st)) {
+ last_status = INT2FIX(*st);
st_delete(pid_tbl, &pid, NULL);
return pid;
}
if (flags)
- Fail("Can't do waitpid with flags");
+ Fatal("Can't do waitpid with flags");
for (;;) {
- result = wait(&st);
- if (result < 0) return -1;
+ result = wait(st);
+ if (result < 0) {
+ if (errno != EINTR) continue;
+ return -1;
+ }
if (result == pid) {
break;
}
if (!pid_tbl)
- pid_tbl = st_init_table(ST_NUMCMP, ST_NUMHASH);
+ pid_tbl = st_init_numtable();
st_insert(pid_tbl, pid, st);
}
#endif
#endif
- status = INT2FIX(st);
+ last_status = INT2FIX(*st);
return result;
}
#ifndef WAIT_CALL
-static int wait_pid;
-static int wait_status;
+struct wait_data {
+ int pid;
+ int status;
+}
-static wait_each(key, value)
+static wait_each(key, value, data)
int key, value;
+ struct wait_data *data;
{
- if (wait_status != -1) return ST_STOP;
+ if (data->status != -1) return ST_STOP;
- wait_pid = key;
- wait_status = value;
+ data->pid = key;
+ data->status = value;
return ST_DELETE;
}
#endif
@@ -116,21 +138,22 @@ static VALUE
f_wait()
{
int pid, state;
-
#ifndef WAIT_CALL
- wait_status = -1;
- st_foreach(pid_tbl, wait_each, NULL);
- if (wait_status != -1) {
- status = wait_status;
- return wait_pid;
+ struct wait_data data;
+
+ data.status = -1;
+ st_foreach(pid_tbl, wait_each, &data);
+ if (data.status != -1) {
+ status = data.status;
+ return data.pid;
}
#endif
if ((pid = wait(&state)) < 0) {
if (errno == ECHILD) return Qnil;
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
}
- status = INT2FIX(state);
+ last_status = INT2FIX(state);
return INT2FIX(pid);
}
@@ -138,18 +161,88 @@ static VALUE
f_waitpid(obj, vpid, vflags)
VALUE obj, vpid, vflags;
{
- int pid, flags;
+ int pid, flags, status;
- if (vflags == Qnil) flags = 0;
+ if (NIL_P(vflags)) flags = 0;
else flags = FIX2UINT(vflags);
- if ((pid = rb_waitpid(FIX2UINT(vpid), flags)) < 0)
- rb_sys_fail(Qnil);
+ if ((pid = rb_waitpid(FIX2UINT(vpid), flags, &status)) < 0)
+ rb_sys_fail(0);
return INT2FIX(pid);
}
char *strtok();
+#if defined(THREAD) && defined(HAVE_SETITIMER)
+static void
+before_exec()
+{
+ {
+ struct itimerval tval;
+
+ tval.it_interval.tv_sec = 0;
+ tval.it_interval.tv_usec = 0;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+ }
+}
+
+static void
+after_exec()
+{
+ {
+ struct itimerval tval;
+
+ tval.it_interval.tv_sec = 1;
+ tval.it_interval.tv_usec = 0;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+ }
+}
+#else
+#define before_exec()
+#define after_exec()
+#endif
+
+extern char *dln_find_exe();
+
+static int
+proc_exec_v(argv)
+ char **argv;
+{
+ char *prog;
+
+ prog = dln_find_exe(argv[0], 0);
+ if (!prog) {
+ errno = ENOENT;
+ return -1;
+ }
+ before_exec();
+ execv(prog, argv);
+ after_exec();
+ return -1;
+}
+
+static int
+proc_exec_n(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ char **args;
+ int i;
+
+ args = ALLOCA_N(char*, argc+1);
+ for (i=0; i<argc; i++) {
+ Check_Type(argv[i], T_STRING);
+ args[i] = RSTRING(argv[i])->ptr;
+ }
+ args[i] = 0;
+ if (args[0]) {
+ return proc_exec_v(args);
+ }
+ return -1;
+}
+
int
rb_proc_exec(str)
char *str;
@@ -159,7 +252,13 @@ rb_proc_exec(str)
for (s=str; *s; s++) {
if (*s != ' ' && !isalpha(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
+ before_exec();
+#if defined(MSDOS)
+ system(str);
+#else
execl("/bin/sh", "sh", "-c", str, (char *)NULL);
+#endif
+ after_exec();
return -1;
}
}
@@ -173,19 +272,25 @@ rb_proc_exec(str)
*a = NULL;
}
if (argv[0]) {
- execvp(argv[0], argv);
+ return proc_exec_v(argv);
}
+ errno = ENOENT;
return -1;
}
static VALUE
-f_exec(obj, str)
- VALUE obj;
- struct RString *str;
+f_exec(argc, argv)
+ int argc;
+ VALUE *argv;
{
- Check_Type(str, T_STRING);
- rb_proc_exec(str->ptr);
- rb_sys_fail(str->ptr);
+ if (argc == 1) {
+ Check_Type(argv[0], T_STRING);
+ rb_proc_exec(RSTRING(argv[0])->ptr);
+ }
+ else {
+ proc_exec_n(argc, argv);
+ }
+ rb_sys_fail(RSTRING(argv[0])->ptr);
}
static VALUE
@@ -224,7 +329,6 @@ f_exit_bang(obj, status)
_exit(code);
/* not reached */
- return Qnil;
}
void
@@ -232,12 +336,13 @@ rb_syswait(pid)
int pid;
{
RETSIGTYPE (*hfunc)(), (*ifunc)(), (*qfunc)();
+ int status;
hfunc = signal(SIGHUP, SIG_IGN);
ifunc = signal(SIGINT, SIG_IGN);
qfunc = signal(SIGQUIT, SIG_IGN);
- if (rb_waitpid(pid, 0) < 0) rb_sys_fail("wait");
+ if (rb_waitpid(pid, 0, &status) < 0) rb_sys_fail("wait");
signal(SIGHUP, hfunc);
signal(SIGINT, ifunc);
@@ -245,33 +350,58 @@ rb_syswait(pid)
}
static VALUE
-f_system(obj, str)
- VALUE obj;
- struct RString *str;
+f_system(argc, argv)
+ int argc;
+ VALUE *argv;
{
#ifdef NT
+ VALUE cmd;
+ int state;
+
+ cmd = ary_join(ary_new4(argc, argv), str_new2(" "));
+
+ state = do_spawn(RSTRING(cmd)->ptr);
+ last_status = INT2FIX(state);
+
+ if (state == 0) return TRUE;
+ return FALSE;
+#else
+#if defined(DJGPP)
+ VALUE cmd;
int state;
- Check_Type(str, T_STRING);
- state = do_spawn(str->ptr);
- status = INT2FIX(state);
+ cmd = ary_join(ary_new4(argc, argv), str_new2(" "));
+
+ state = system(RSTRING(cmd)->ptr);
+ last_status = INT2FIX(state);
if (state == 0) return TRUE;
return FALSE;
#else
+ int i;
int pid;
- Check_Type(str, T_STRING);
-
fflush(stdin); /* is it really needed? */
fflush(stdout);
fflush(stderr);
- if (*str->ptr == '\0') return INT2FIX(0);
+ if (argc == 0) {
+ last_status = INT2FIX(0);
+ return INT2FIX(0);
+ }
+
+ for (i=0; i<argc; i++) {
+ Check_Type(argv[i], T_STRING);
+ }
retry:
switch (pid = vfork()) {
case 0:
- rb_proc_exec(str->ptr);
+ if (argc == 1) {
+ rb_proc_exec(RSTRING(argv[0])->ptr);
+ }
+ else {
+ proc_exec_n(argc, argv);
+ }
_exit(127);
break; /* not reached */
@@ -280,62 +410,99 @@ f_system(obj, str)
sleep(5);
goto retry;
}
- rb_sys_fail(str->ptr);
+ rb_sys_fail(0);
break;
default:
rb_syswait(pid);
}
- if (status == INT2FIX(0)) return TRUE;
+ if (last_status == INT2FIX(0)) return TRUE;
return FALSE;
#endif
+#endif
}
+struct timeval time_timeval();
+
VALUE
f_sleep(argc, argv)
int argc;
VALUE *argv;
{
int beg, end;
+ int n;
beg = time(0);
+#ifdef THREAD
if (argc == 0) {
+ thread_sleep();
+ }
+ else if (argc == 1) {
+ thread_wait_for(time_timeval(argv[0]));
+ }
+#else
+ if (argc == 0) {
+ TRAP_BEG;
sleep((32767<<16)+32767);
+ TRAP_END;
}
else if (argc == 1) {
+ struct timeval tv;
+
+ tv = time_timeval(argv[0]);
TRAP_BEG;
- sleep(NUM2INT(argv[0]));
+ sleep(tv.tv_sec);
TRAP_END;
+ if (n<0) rb_sys_fail(0);
}
+#endif
else {
- Fail("wrong # of arguments");
+ ArgError("wrong # of arguments");
}
end = time(0) - beg;
- return int2inum(end);
+ return INT2FIX(end);
}
-#ifndef NT
+#if !defined(NT) && !defined(DJGPP)
+#ifdef _POSIX_SOURCE
+static VALUE
+proc_getpgrp()
+{
+ int pgrp;
+
+ pgrp = getpgrp();
+ if (pgrp < 0) rb_sys_fail(0);
+ return INT2FIX(pgrp);
+}
+
+static VALUE
+proc_setpgrp(obj)
+ VALUE obj;
+{
+ int pgrp;
+
+ if (setpgrp() < 0) rb_sys_fail(0);
+ return Qnil;
+}
+
+#else
+
static VALUE
-proc_getpgrp(argc, argv, obj)
+proc_getpgrp(argc, argv)
int argc;
VALUE *argv;
- VALUE obj;
{
VALUE vpid;
- int pid, pgrp;
+ int pgrp, pid;
rb_scan_args(argc, argv, "01", &vpid);
- if (vpid == Qnil) {
- pid = 0;
- }
- else {
- pid = NUM2INT(vpid);
- }
-
+ if (NIL_P(vpid)) pid = 0;
+ else pid = NUM2INT(vpid);
pgrp = getpgrp(pid);
+ if (pgrp < 0) rb_sys_fail(0);
return INT2FIX(pgrp);
}
@@ -347,11 +514,25 @@ proc_setpgrp(obj, pid, pgrp)
ipid = NUM2INT(pid);
ipgrp = NUM2INT(pgrp);
+ if (setpgrp(ipid, ipgrp) < 0) rb_sys_fail(0);
+ return Qnil;
+}
+#endif
- if (getpgrp(ipid, ipgrp) == -1) rb_sys_fail(Qnil);
+#ifdef HAVE_SETPGID
+static VALUE
+proc_setpgid(obj, pid, pgrp)
+ VALUE obj, pid, pgrp;
+{
+ int ipid, ipgrp;
- return INT2FIX(0);
+ ipid = NUM2INT(pid);
+ ipgrp = NUM2INT(pgrp);
+
+ if (setpgid(ipid, ipgrp) == -1) rb_sys_fail(0);
+ return Qnil;
}
+#endif
static VALUE
proc_getpriority(obj, which, who)
@@ -364,10 +545,10 @@ proc_getpriority(obj, which, who)
iwho = NUM2INT(who);
prio = getpriority(iwhich, iwho);
- if (prio == -1) rb_sys_fail(Qnil);
+ if (prio == -1) rb_sys_fail(0);
return INT2FIX(prio);
#else
- Fail("The getpriority() function is unimplemented on this machine");
+ rb_notimplement();
#endif
}
@@ -383,10 +564,10 @@ proc_setpriority(obj, which, who, prio)
iprio = NUM2INT(prio);
if (setpriority(iwhich, iwho, iprio) == -1)
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
return INT2FIX(0);
#else
- Fail("The setpriority() function is unimplemented on this machine");
+ rb_notimplement();
#endif
}
#endif
@@ -416,7 +597,7 @@ proc_setuid(obj, id)
if (geteuid() == uid)
setuid(uid);
else
- Fail("getruid not implemented");
+ rb_notimplement();
}
#endif
#endif
@@ -448,7 +629,7 @@ proc_setgid(obj, id)
if (getegid() == gid)
setgid(gid);
else
- Fail("getrgid not implemented");
+ rb_notimplement();
}
#endif
#endif
@@ -468,16 +649,16 @@ proc_seteuid(obj, euid)
VALUE obj, euid;
{
#ifdef HAVE_SETEUID
- if (seteuid(NUM2INT(euid)) == -1) rb_sys_fail(Qnil);
+ if (seteuid(NUM2INT(euid)) == -1) rb_sys_fail(0);
#else
#ifdef HAVE_SETREUID
- if (setreuid(-1, NUM2INT(euid)) == -1) rb_sys_fail(Qnil);
+ if (setreuid(-1, NUM2INT(euid)) == -1) rb_sys_fail(0);
#else
euid = NUM2INT(euid);
if (euid == getuid())
setuid(euid);
else
- Fail("seteuid() not implemented");
+ rb_notimplement();
#endif
#endif
return euid;
@@ -496,16 +677,16 @@ proc_setegid(obj, egid)
VALUE obj, egid;
{
#ifdef HAVE_SETEGID
- if (setegid(NUM2INT(egid)) == -1) rb_sys_fail(Qnil);
+ if (setegid(NUM2INT(egid)) == -1) rb_sys_fail(0);
#else
#ifdef HAVE_SETREGID
- if (setregid(-1, NUM2INT(egid)) == -1) rb_sys_fail(Qnil);
+ if (setregid(-1, NUM2INT(egid)) == -1) rb_sys_fail(0);
#else
egid = NUM2INT(egid);
if (egid == getgid())
setgid(egid);
else
- Fail("setegid() not implemented");
+ rb_notimplement();
#endif
#endif
return egid;
@@ -520,41 +701,60 @@ Init_process()
{
extern VALUE cKernel;
- rb_define_virtual_variable("$$", get_pid, Qnil);
- rb_define_readonly_variable("$?", &status);
+ rb_define_virtual_variable("$$", get_pid, 0);
+ rb_define_readonly_variable("$?", &last_status);
#ifndef NT
- rb_define_private_method(cKernel, "exec", f_exec, 1);
+ 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, "system", f_system, -1);
rb_define_private_method(cKernel, "sleep", f_sleep, -1);
mProcess = rb_define_module("Process");
+#ifdef WNOHANG
+ rb_define_const(mProcess, "WNOHANG", INT2FIX(WNOHANG));
+#else
+ rb_define_const(mProcess, "WNOHANG", INT2FIX(0));
+#endif
+#ifdef WUNTRACED
+ rb_define_const(mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
+#else
+ rb_define_const(mProcess, "WUNTRACED", INT2FIX(0));
+#endif
+#endif
+
#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, "kill", f_kill, -1);
+ rb_define_module_function(mProcess, "wait", f_wait, 0);
+ rb_define_module_function(mProcess, "waitpid", f_waitpid, 2);
rb_define_module_function(mProcess, "pid", get_pid, 0);
rb_define_module_function(mProcess, "ppid", get_ppid, 0);
-#ifndef NT
+#if !defined(NT) && !defined(DJGPP)
+#ifdef _POSIX_SOURCE
+ rb_define_module_function(mProcess, "getpgrp", proc_getpgrp, 0);
+ rb_define_module_function(mProcess, "setpgrp", proc_setpgrp, 0);
+#else
rb_define_module_function(mProcess, "getpgrp", proc_getpgrp, -1);
rb_define_module_function(mProcess, "setpgrp", proc_setpgrp, 2);
+#endif
+#ifdef HAVE_SETPGID
+ rb_define_module_function(mProcess, "setpgid", proc_setpgid, 2);
+#endif
+#ifdef HAVE_GETPRIORITY
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));
+#endif
rb_define_module_function(mProcess, "uid", proc_getuid, 0);
rb_define_module_function(mProcess, "uid=", proc_setuid, 1);
diff --git a/random.c b/random.c
index f7bc59569b..ebe5a35dee 100644
--- a/random.c
+++ b/random.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:48 $
created at: Fri Dec 24 16:39:21 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -54,19 +54,35 @@ f_srand(argc, argv, obj)
}
static VALUE
-f_rand(obj, max)
- VALUE obj, max;
+f_rand(obj, vmax)
+ VALUE obj, vmax;
{
- int val;
+ int val, max;
#ifdef HAVE_RANDOM
if (first == 1) {
initstate(1, state, sizeof state);
first = 0;
}
- val = random() % NUM2INT(max);
+#endif
+
+ switch (TYPE(vmax)) {
+ case T_BIGNUM:
+ return big_rand(vmax);
+
+ case T_FLOAT:
+ if (RFLOAT(vmax)->value > LONG_MAX || RFLOAT(vmax)->value < LONG_MIN)
+ return big_rand(dbl2big(RFLOAT(vmax)->value));
+ break;
+ }
+
+ max = NUM2INT(vmax);
+ if (max == 0) ArgError("rand(0)");
+
+#ifdef HAVE_RANDOM
+ val = random() % max;
#else
- val = rand() % NUM2INT(max);
+ val = rand() % max;
#endif
if (val < 0) val = -val;
diff --git a/range.c b/range.c
index 147c28ae7c..b7d2f3b75e 100644
--- a/range.c
+++ b/range.c
@@ -6,7 +6,7 @@
$Date: 1994/12/06 09:30:12 $
created at: Thu Aug 19 17:46:47 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -14,55 +14,58 @@
VALUE mComparable;
static VALUE cRange;
+extern VALUE cNumeric;
static ID upto;
static VALUE
-range_s_new(class, start, end)
- VALUE class, start, end;
+range_s_new(class, first, last)
+ VALUE class, first, last;
{
VALUE obj;
- 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");
+ if (!(FIXNUM_P(first) && FIXNUM_P(last))
+ && (TYPE(first) != TYPE(last)
+ || CLASS_OF(first) != CLASS_OF(last)
+ || !rb_respond_to(first, upto))
+ && !(obj_is_kind_of(first, cNumeric)
+ && obj_is_kind_of(last, cNumeric))) {
+ ArgError("bad value for range");
}
obj = obj_alloc(class);
- rb_iv_set(obj, "start", start);
- rb_iv_set(obj, "end", end);
+ rb_iv_set(obj, "first", first);
+ rb_iv_set(obj, "last", last);
return obj;
}
VALUE
-range_new(start, end)
- VALUE start, end;
+range_new(first, last)
+ VALUE first, last;
{
- return range_s_new(cRange, start, end);
+ return range_s_new(cRange, first, last);
}
static VALUE
range_match(rng, obj)
VALUE rng, obj;
{
- VALUE beg, end;
+ VALUE first, last;
- beg = rb_iv_get(rng, "start");
- end = rb_iv_get(rng, "end");
+ first = rb_iv_get(rng, "first");
+ last = rb_iv_get(rng, "last");
- if (FIXNUM_P(beg) && FIXNUM_P(obj)) {
- if (FIX2INT(beg) <= FIX2INT(obj) && FIX2INT(obj) <= FIX2INT(end)) {
+ if (FIXNUM_P(first) && FIXNUM_P(obj)) {
+ if (FIX2INT(first) <= FIX2INT(obj) && FIX2INT(obj) <= FIX2INT(last)) {
return TRUE;
}
return FALSE;
}
else {
- if (rb_funcall(beg, rb_intern("<="), 1, obj) &&
- rb_funcall(end, rb_intern(">="), 1, obj)) {
+ if (rb_funcall(first, rb_intern("<="), 1, obj) &&
+ rb_funcall(last, rb_intern(">="), 1, obj)) {
return TRUE;
}
return FALSE;
@@ -70,23 +73,15 @@ range_match(rng, obj)
}
struct upto_data {
- VALUE beg;
- VALUE end;
+ VALUE first;
+ VALUE last;
};
static VALUE
range_upto(data)
struct upto_data *data;
{
- return rb_funcall(data->beg, upto, 1, data->end);
-}
-
-static VALUE
-range_upto_yield(v)
- VALUE v;
-{
- rb_yield(v);
- return Qnil;
+ return rb_funcall(data->first, upto, 1, data->last);
}
static VALUE
@@ -95,73 +90,105 @@ range_each(obj)
{
VALUE b, e;
- b = rb_iv_get(obj, "start");
- e = rb_iv_get(obj, "end");
+ b = rb_iv_get(obj, "first");
+ e = rb_iv_get(obj, "last");
if (FIXNUM_P(b)) { /* fixnum is a special case(for performance) */
num_upto(b, e);
}
- else if (TYPE(b) == T_STRING) {
- str_upto(b, e);
- }
else {
struct upto_data data;
- data.beg = b;
- data.end = e;
+ data.first = b;
+ data.last = e;
- rb_iterate(range_upto, &data, range_upto_yield, Qnil);
+ rb_iterate(range_upto, &data, rb_yield, 0);
}
return Qnil;
}
static VALUE
-range_start(obj)
+range_first(obj)
VALUE obj;
{
VALUE b;
- b = rb_iv_get(obj, "start");
+ b = rb_iv_get(obj, "first");
return b;
}
static VALUE
-range_end(obj)
+range_last(obj)
VALUE obj;
{
VALUE e;
- e = rb_iv_get(obj, "end");
+ e = rb_iv_get(obj, "last");
return e;
}
-static VALUE
-range_to_s(obj)
- VALUE obj;
-{
- VALUE args[4];
-
- args[0] = str_new2("%d..%d");
- args[1] = rb_iv_get(obj, "start");
- args[2] = rb_iv_get(obj, "end");
- return f_sprintf(3, args);
-}
-
VALUE
range_beg_end(range, begp, endp)
VALUE range;
int *begp, *endp;
{
- int beg, end;
+ VALUE first, last;
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);
+ first = rb_iv_get(range, "first"); *begp = NUM2INT(first);
+ last = rb_iv_get(range, "last"); *endp = NUM2INT(last);
return TRUE;
}
+static VALUE
+range_to_s(range)
+ VALUE range;
+{
+ VALUE str, str2;
+
+ str = obj_as_string(rb_iv_get(range, "first"));
+ str2 = obj_as_string(rb_iv_get(range, "last"));
+ str_cat(str, "..", 2);
+ str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+
+ return str;
+}
+
+static VALUE
+range_inspect(range)
+ VALUE range;
+{
+ VALUE str, str2;
+
+ str = rb_inspect(rb_iv_get(range, "first"));
+ str2 = rb_inspect(rb_iv_get(range, "last"));
+ str_cat(str, "..", 2);
+ str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+
+ return str;
+}
+
+static VALUE
+range_length(rng)
+ VALUE rng;
+{
+ VALUE first, last;
+ VALUE size;
+
+ first = rb_iv_get(rng, "first");
+ last = rb_iv_get(rng, "last");
+
+ if (!obj_is_kind_of(first, cNumeric)) {
+ return enum_length(rng);
+ }
+ size = rb_funcall(last, '-', 1, first);
+ size = rb_funcall(size, '+', 1, INT2FIX(1));
+
+ return size;
+}
+
extern VALUE mEnumerable;
void
@@ -170,11 +197,15 @@ Init_Range()
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, "===", 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, "first", range_first, 0);
+ rb_define_method(cRange, "last", range_last, 0);
rb_define_method(cRange, "to_s", range_to_s, 0);
+ rb_define_method(cRange, "inspect", range_inspect, 0);
+
+ rb_define_method(cRange, "length", range_length, 0);
+ rb_define_method(cRange, "size", range_length, 0);
upto = rb_intern("upto");
}
diff --git a/re.c b/re.c
index f6dde5a4eb..bd6c2fb9b8 100644
--- a/re.c
+++ b/re.c
@@ -6,13 +6,15 @@
$Date: 1995/01/10 10:42:49 $
created at: Mon Aug 9 18:24:49 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "re.h"
+static VALUE eRegxpError;
+
#define BEG(no) regs->beg[no]
#define END(no) regs->end[no]
@@ -104,6 +106,73 @@ static int reg_kcode =
# endif
#endif
+extern int rb_in_eval;
+
+static VALUE
+reg_desc(s, len, re)
+ char *s;
+ int len;
+ VALUE re;
+{
+ VALUE str = str_new2("/");
+ char *p, *pend;
+ int slash = 0;
+
+ p = s; pend = p + len;
+ while (p<pend) {
+ if (*p == '/') {
+ slash = 1;
+ break;
+ }
+ p++;
+ }
+ if (!slash) {
+ str_cat(str, s, len);
+ }
+ else {
+ p = s;
+ while (p<pend) {
+ if (*p == '/') {
+ char c = '\\';
+ str_cat(str, &c, 1);
+ str_cat(str, p, 1);
+ }
+ else {
+ str_cat(str, p, 1);
+ }
+ p++;
+ }
+ }
+ str_cat(str, "/", 1);
+ if (re && FL_TEST(re, REG_IGNORECASE)) {
+ str_cat(str, "i", 1);
+ }
+ return str;
+}
+
+static VALUE
+reg_inspect(re)
+ struct RRegexp *re;
+{
+ return reg_desc(re->str, re->len, re);
+}
+
+static void
+reg_raise(s, len, err, compile, re)
+ char *s;
+ int len;
+ char *err;
+ int compile;
+ VALUE re;
+{
+ VALUE desc = reg_desc(s, len, re);
+
+ if (!compile)
+ Raise(eRegxpError, "%s: %s", err, RSTRING(desc)->ptr);
+ else
+ Error("%s: %s", err, RSTRING(desc)->ptr);
+}
+
static Regexp*
make_regexp(s, len)
char *s;
@@ -125,17 +194,52 @@ make_regexp(s, len)
rp->allocated = 16;
rp->fastmap = ALLOC_N(char, 256);
- if ((err = re_compile_pattern(s, (size_t)len, rp)) != NULL)
- Fail("%s: /%s/", err, s);
+ if ((err = re_compile_pattern(s, (size_t)len, rp)) != NULL) {
+ reg_raise(s, len, err, !rb_in_eval, 0);
+ }
return rp;
}
+extern VALUE cData;
+static VALUE cMatch;
+
+static VALUE
+match_to_a(match)
+ struct RMatch *match;
+{
+ struct re_registers *regs = match->regs;
+ VALUE ary = ary_new(regs->num_regs);
+ int i;
+
+ for (i=0; i<regs->num_regs; i++) {
+ if (regs->beg[0] == -1) ary_push(ary, Qnil);
+ else ary_push(ary, str_new(match->ptr+regs->beg[i],
+ regs->end[i]-regs->beg[i]));
+ }
+ return ary;
+}
+
+static VALUE
+match_to_s(match)
+ struct RMatch *match;
+{
+ int beg, len;
+
+ if (match->regs->allocated == 0) return Qnil;
+
+ beg = match->regs->beg[0];
+ if (beg == -1) return Qnil;
+
+ len = match->regs->end[0] - beg;
+ return str_new(match->ptr+beg, len);
+}
+
static VALUE
match_alloc()
{
NEWOBJ(match, struct RMatch);
- OBJSETUP(match, cData, T_MATCH);
+ OBJSETUP(match, cMatch, T_MATCH);
match->ptr = 0;
match->len = 0;
@@ -155,10 +259,12 @@ reg_search(reg, str, start, regs)
struct re_registers *regs;
{
int result;
- int casefold = ignorecase;
+ int casefold = RTEST(ignorecase);
VALUE match = 0;
struct re_registers *regs0 = 0;
+ if (start > str->len) return -1;
+
/* case-flag set for the object */
if (FL_TEST(reg, REG_IGNORECASE)) {
casefold = TRUE;
@@ -174,16 +280,11 @@ reg_search(reg, str, start, regs)
reg->ptr->fastmap_accurate = 0;
}
- if (start > str->len) return -1;
-
- if (regs == (struct re_registers *)-1) {
+ if (regs == (struct re_registers*)-1) {
regs = 0;
}
- else if (match = backref_get()) {
- if (match == 1) {
- match = match_alloc();
- backref_set(match);
- }
+ else {
+ match = match_alloc();
regs0 = RMATCH(match)->regs;
}
@@ -192,8 +293,9 @@ reg_search(reg, str, start, 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);
+ if ((err = re_compile_pattern(reg->str, reg->len, reg->ptr)) != NULL) {
+ reg_raise(reg->str, reg->len, err, reg);
+ }
RBASIC(reg)->flags = RBASIC(reg)->flags & ~KCODE_MASK;
RBASIC(reg)->flags |= reg_kcode;
}
@@ -201,11 +303,18 @@ reg_search(reg, str, start, regs)
result = re_search(reg->ptr, str->ptr, str->len,
start, str->len - start, regs0);
- if (match && result >= 0) {
+ if (start == -2) {
+ reg_raise(reg->str, reg->len, "Stack overfow in regexp matcher", reg);
+ }
+ if (result < 0) {
+ backref_set(Qnil);
+ }
+ else if (match) {
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';
+ backref_set(match);
}
if (regs && regs0 && regs0 != regs) re_copy_registers(regs, regs0);
@@ -217,7 +326,7 @@ reg_nth_defined(nth, match)
int nth;
struct RMatch *match;
{
- if (!match) return FALSE;
+ if (NIL_P(match)) return Qnil;
if (nth >= match->regs->num_regs) {
return FALSE;
}
@@ -232,7 +341,7 @@ reg_nth_match(nth, match)
{
int start, end, len;
- if (!match) return Qnil;
+ if (NIL_P(match)) return Qnil;
if (nth >= match->regs->num_regs) {
return Qnil;
}
@@ -254,7 +363,7 @@ VALUE
reg_match_pre(match)
struct RMatch *match;
{
- if (!match) return Qnil;
+ if (NIL_P(match)) return Qnil;
if (match->BEG(0) == -1) return Qnil;
return str_new(match->ptr, match->BEG(0));
}
@@ -263,7 +372,7 @@ VALUE
reg_match_post(match)
struct RMatch *match;
{
- if (!match) return Qnil;
+ if (NIL_P(match)) return Qnil;
if (match->BEG(0) == -1) return Qnil;
return str_new(match->ptr+match->END(0),
match->len-match->END(0));
@@ -275,7 +384,7 @@ reg_match_last(match)
{
int i;
- if (!match) return Qnil;
+ if (NIL_P(match)) return Qnil;
if (match->BEG(0) == -1) return Qnil;
for (i=match->regs->num_regs-1; match->BEG(i) == -1 && i > 0; i--)
@@ -293,13 +402,6 @@ Regexp *rp;
free(rp);
}
-void
-reg_error(s)
-const char *s;
-{
- Fail(s);
-}
-
VALUE cRegexp;
static VALUE
@@ -331,19 +433,22 @@ reg_new(s, len, ci)
return reg_new_1(cRegexp, s, len, ci);
}
-static VALUE reg_cache, ign_cache;
+int ign_cache;
+static VALUE reg_cache;
VALUE
reg_regcomp(str)
struct RString *str;
{
+ int ignc = RTEST(ignorecase);
+
if (reg_cache && RREGEXP(reg_cache)->len == str->len
- && ign_cache == ignorecase
+ && ign_cache == ignc
&& memcmp(RREGEXP(reg_cache)->str, str->ptr, str->len) == 0)
return reg_cache;
- ign_cache = ignorecase;
- return reg_cache = reg_new(str->ptr, str->len, ignorecase);
+ ign_cache = ignc;
+ return reg_cache = reg_new(str->ptr, str->len, ignc);
}
VALUE
@@ -356,7 +461,7 @@ reg_match(re, str)
if (TYPE(str) != T_STRING) return FALSE;
start = reg_search(re, str, 0, 0);
if (start < 0) {
- return Qnil;
+ return FALSE;
}
return INT2FIX(start);
}
@@ -365,15 +470,15 @@ VALUE
reg_match2(re)
struct RRegexp *re;
{
- extern VALUE rb_lastline;
int start;
+ VALUE line = lastline_get();
- if (TYPE(rb_lastline) != T_STRING)
- Fail("$_ is not a string");
+ if (TYPE(line) != T_STRING)
+ return FALSE;
- start = reg_search(re, rb_lastline, 0, 0);
- if (start == -1) {
- return Qnil;
+ start = reg_search(re, line, 0, 0);
+ if (start < 0) {
+ return FALSE;
}
return INT2FIX(start);
}
@@ -384,11 +489,11 @@ reg_s_new(argc, argv, self)
VALUE *argv;
VALUE self;
{
- VALUE src, reg;
+ VALUE src;
int ci = 0;
if (argc == 0 || argc > 2) {
- Fail("wrong # of argument");
+ ArgError("wrong # of argument");
}
if (argc == 2 && argv[1]) {
ci = 1;
@@ -397,10 +502,12 @@ reg_s_new(argc, argv, self)
src = argv[0];
switch (TYPE(src)) {
case T_STRING:
- reg = reg_new_1(self, RREGEXP(src)->ptr, RREGEXP(src)->len, ci);
+ return reg_new_1(self, RSTRING(src)->ptr, RSTRING(src)->len, ci);
+ break;
case T_REGEXP:
- reg = reg_new_1(self, RREGEXP(src)->str, RREGEXP(src)->len, ci);
+ return reg_new_1(self, RREGEXP(src)->str, RREGEXP(src)->len, ci);
+ break;
default:
Check_Type(src, T_STRING);
@@ -472,7 +579,7 @@ reg_regsub(str, src, regs)
no = -1;
if (no >= 0) {
- if (val == Qnil) {
+ if (NIL_P(val)) {
val = str_new(p, ss-p);
}
else {
@@ -490,7 +597,7 @@ reg_regsub(str, src, regs)
}
}
- if (val == Qnil) return (VALUE)str;
+ if (NIL_P(val)) return (VALUE)str;
if (p < e) {
str_cat(val, p, e-p);
}
@@ -501,20 +608,6 @@ reg_regsub(str, src, regs)
}
static VALUE
-reg_to_s(re)
- struct RRegexp *re;
-{
- 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) {
@@ -569,26 +662,7 @@ kcode_setter(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;
+ return backref_get();
}
static void
@@ -598,11 +672,16 @@ match_setter(val)
backref_set(val);
}
+VALUE krn_to_s();
+
void
Init_Regexp()
{
+ extern VALUE eException;
+
+ eRegxpError = rb_define_class("RegxpError", eException);
+
re_set_syntax(RE_NO_BK_PARENS | RE_NO_BK_VBAR
- | RE_AWK_CLASS_HACK
| RE_INTERVALS
| RE_NO_BK_BRACES
| RE_BACKSLASH_ESCAPE_IN_LISTS
@@ -623,8 +702,14 @@ Init_Regexp()
rb_define_method(cRegexp, "clone", reg_clone, 0);
rb_define_method(cRegexp, "=~", reg_match, 1);
+ 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_define_method(cRegexp, "inspect", reg_inspect, 0);
rb_global_variable(&reg_cache);
+
+ cMatch = rb_define_class("MatchingData", cData);
+ rb_define_method(cMatch, "to_a", match_to_a, 0);
+ rb_define_method(cMatch, "to_s", match_to_s, 0);
+ rb_define_method(cMatch, "inspect", krn_to_s, 0);
}
diff --git a/re.h b/re.h
index babbe413e5..ebbe0673f5 100644
--- a/re.h
+++ b/re.h
@@ -7,7 +7,7 @@
$Date: 1994/08/12 04:47:52 $
created at: Thu Sep 30 14:18:32 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
diff --git a/regex.c b/regex.c
index 4b4ff8a193..c6bbb3027f 100644
--- a/regex.c
+++ b/regex.c
@@ -62,6 +62,10 @@ char *alloca();
#endif
#endif /* __GNUC__ */
+#ifdef _AIX
+#pragma alloca
+#endif
+
#define RE_ALLOCATE alloca
#define FREE_VARIABLES() alloca(0)
@@ -144,6 +148,8 @@ init_syntax_once()
for (c = '0'; c <= '9'; c++)
re_syntax_table[c] = Sword;
+ re_syntax_table['_'] = Sword;
+
/* Add specific syntax for ISO Latin-1. */
for (c = 0300; c <= 0377; c++)
re_syntax_table[c] = Sword;
@@ -238,7 +244,7 @@ enum regexpcode
#define NFAILURES 80
#endif
-#ifdef CHAR_UNSIGNED
+#if defined(CHAR_UNSIGNED) || defined(__CHAR_UNSIGNED__)
#define SIGN_EXTEND_CHAR(c) ((c)>(char)127?(c)-256:(c)) /* for IBM RT */
#endif
#ifndef SIGN_EXTEND_CHAR
@@ -795,7 +801,7 @@ re_compile_pattern(pattern, size, bufp)
while (1)
{
int size;
- unsigned last = -1;
+ unsigned last = (unsigned)-1;
if ((size = EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH]))) {
/* Ensure the space is enough to hold another interval
@@ -830,8 +836,8 @@ re_compile_pattern(pattern, size, bufp)
PATFETCH(c);
switch (c) {
case 'w':
- for (c = 0; c < 256; c++)
- if (isalnum(c))
+ for (c = 0; c < (1 << BYTEWIDTH); c++)
+ if (SYNTAX(c) == Sword)
SET_LIST_BIT(c);
last = -1;
continue;
@@ -839,8 +845,8 @@ re_compile_pattern(pattern, size, bufp)
case 'W':
if (re_syntax_options & RE_MBCTYPE_MASK)
goto invalid_char;
- for (c = 0; c < 256; c++)
- if (!isalnum(c))
+ for (c = 0; c < (1 << BYTEWIDTH); c++)
+ if (SYNTAX(c) != Sword)
SET_LIST_BIT(c);
last = -1;
continue;
@@ -1072,7 +1078,9 @@ re_compile_pattern(pattern, size, bufp)
|| *laststart == charset
|| *laststart == charset_not
|| *laststart == start_memory
- || (*laststart == exactn && laststart[1] == 1)
+ || (*laststart == exactn
+ && (laststart[1] == 1
+ || laststart[1] == 2 && ismbchar(laststart[2])))
|| (! (re_syntax_options & RE_NO_BK_REFS)
&& *laststart == duplicate)))
{
@@ -1277,6 +1285,7 @@ re_compile_pattern(pattern, size, bufp)
c1 = 0;
GET_UNSIGNED_NUMBER(c1);
+ PATUNFETCH;
if (c1 >= regnum) {
if (c1 < RE_NREGS)
@@ -1722,27 +1731,27 @@ re_compile_fastmap(bufp)
-/* Using the compiled pattern in PBUFP->buffer, first tries to match
+/* Using the compiled pattern in BUFP->buffer, first tries to match
STRING, starting first at index STARTPOS, then at STARTPOS + 1, and
so on. RANGE is the number of places to try before giving up. If
RANGE is negative, it searches backwards, i.e., the starting
positions tried are STARTPOS, STARTPOS - 1, etc. STRING is of SIZE.
In REGS, return the indices of STRING that matched the entire
- PBUFP->buffer and its contained subexpressions.
+ BUFP->buffer and its contained subexpressions.
The value returned is the position in the strings at which the match
was found, or -1 if no match was found, or -2 if error (such as
failure stack overflow). */
int
-re_search(pbufp, string, size, startpos, range, regs)
- struct re_pattern_buffer *pbufp;
+re_search(bufp, string, size, startpos, range, regs)
+ struct re_pattern_buffer *bufp;
char *string;
int size, startpos, range;
struct re_registers *regs;
{
- register char *fastmap = pbufp->fastmap;
- register unsigned char *translate = (unsigned char *) pbufp->translate;
+ register char *fastmap = bufp->fastmap;
+ register unsigned char *translate = (unsigned char *) bufp->translate;
int val;
/* Check for out-of-range starting position. */
@@ -1750,8 +1759,8 @@ re_search(pbufp, string, size, startpos, range, regs)
return -1;
/* Update the fastmap now if not correct already. */
- if (fastmap && !pbufp->fastmap_accurate) {
- re_compile_fastmap (pbufp);
+ if (fastmap && !bufp->fastmap_accurate) {
+ re_compile_fastmap (bufp);
}
while (1)
@@ -1762,7 +1771,7 @@ re_search(pbufp, string, size, startpos, range, regs)
test it at each starting point so that we take the first null
string we get. */
- if (fastmap && startpos < size && pbufp->can_be_null != 1)
+ if (fastmap && startpos < size && bufp->can_be_null != 1)
{
if (range > 0) /* Searching forwards. */
{
@@ -1781,7 +1790,7 @@ re_search(pbufp, string, size, startpos, range, regs)
p++;
range--;
}
- else
+ else
if (fastmap[translate ? translate[c] : c])
break;
range--;
@@ -1799,11 +1808,12 @@ re_search(pbufp, string, size, startpos, range, regs)
}
}
- if (range >= 0 && startpos == size
- && fastmap && pbufp->can_be_null == 0)
- return -1;
+ if (range >= 0 && startpos == size && fastmap) {
+ if (bufp->can_be_null == 0 || (bufp->can_be_null == 2 && size > 0))
+ return -1;
+ }
- val = re_match(pbufp, string, size, startpos, regs);
+ val = re_match(bufp, string, size, startpos, regs);
if (val >= 0)
return startpos;
if (val == -2)
@@ -2006,12 +2016,12 @@ init_regs(regs, num_regs)
}
}
-/* Match the pattern described by PBUFP against STRING, which is of
+/* Match the pattern described by BUFP against STRING, which is of
SIZE. Start the match at index POS in STRING. In REGS, return the
- indices of STRING that matched the entire PBUFP->buffer and its
+ indices of STRING that matched the entire BUFP->buffer and its
contained subexpressions.
- If pbufp->fastmap is nonzero, then it had better be up to date.
+ If bufp->fastmap is nonzero, then it had better be up to date.
The reason that the data to match are specified as two components
which are to be regarded as concatenated is so this function can be
@@ -2022,24 +2032,24 @@ init_regs(regs, num_regs)
length of the substring which was matched. */
int
-re_match(pbufp, string_arg, size, pos, regs)
- struct re_pattern_buffer *pbufp;
+re_match(bufp, string_arg, size, pos, regs)
+ struct re_pattern_buffer *bufp;
char *string_arg;
int size, pos;
struct re_registers *regs;
{
- register unsigned char *p = (unsigned char *) pbufp->buffer;
+ register unsigned char *p = (unsigned char *) bufp->buffer;
/* Pointer to beyond end of buffer. */
- register unsigned char *pend = p + pbufp->used;
+ register unsigned char *pend = p + bufp->used;
- unsigned num_regs = pbufp->re_nsub + 1;
+ unsigned num_regs = bufp->re_nsub;
unsigned char *string = (unsigned char *) string_arg;
register unsigned char *d, *dend;
register int mcnt; /* Multipurpose. */
- unsigned char *translate = (unsigned char *) pbufp->translate;
+ unsigned char *translate = (unsigned char *) bufp->translate;
unsigned is_a_jump_n = 0;
/* Failure point stack. Each place that can handle a failure further
@@ -2133,7 +2143,7 @@ re_match(pbufp, string_arg, size, pos, regs)
#ifdef DEBUG_REGEX
fprintf(stderr,
"regex loop(%d): matching 0x%02d\n",
- p - (unsigned char *) pbufp->buffer,
+ p - (unsigned char *) bufp->buffer,
*p);
#endif
is_a_jump_n = 0;
@@ -2666,21 +2676,25 @@ re_copy_registers(regs1, regs2)
if (regs1->allocated == 0) {
regs1->beg = TMALLOC(regs2->num_regs, int);
regs1->end = TMALLOC(regs2->num_regs, int);
+ regs1->allocated = regs2->num_regs;
}
else if (regs1->allocated < regs2->num_regs) {
TREALLOC(regs1->beg, regs2->num_regs, int);
TREALLOC(regs1->end, regs2->num_regs, int);
+ regs1->allocated = regs2->num_regs;
}
for (i=0; i<regs2->num_regs; i++) {
regs1->beg[i] = regs2->beg[i];
regs1->end[i] = regs2->end[i];
}
+ regs1->num_regs = regs2->num_regs;
}
void
re_free_registers(regs)
struct re_registers *regs;
{
+ if (regs->allocated == 0) return;
if (regs->beg) free(regs->beg);
if (regs->end) free(regs->end);
}
diff --git a/regex.h b/regex.h
index 971c4e5c74..7b31b87b62 100644
--- a/regex.h
+++ b/regex.h
@@ -17,7 +17,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto)
Last change: May 21, 1993 by t^2 */
-
+/* modifis for Ruby by matz@caelum.co.jp */
#ifndef __REGEXP_LIBRARY
#define __REGEXP_LIBRARY
diff --git a/ruby.c b/ruby.c
index 9d437f8895..8e4ab30148 100644
--- a/ruby.c
+++ b/ruby.c
@@ -6,38 +6,39 @@
$Date: 1995/01/10 10:42:51 $
created at: Tue Aug 10 12:47:31 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "re.h"
+#include "dln.h"
#include <stdio.h>
-#include <fcntl.h>
#include <sys/types.h>
-#include <sys/stat.h>
-#include "dln.h"
+#include <fcntl.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
char *strchr();
+char *strrchr();
char *strstr();
#endif
static int version, copyright;
-int debug = 0;
-int verbose = 0;
+int debug = FALSE;
+int verbose = FALSE;
static int sflag = FALSE;
-char *inplace = 0;
+char *inplace = FALSE;
char *strdup();
extern int yydebug;
extern int nerrs;
-int xflag = FALSE;
+static int xflag = FALSE;
+extern VALUE RS, RS_default, ORS, FS;
static void load_stdin();
static void load_file();
@@ -49,10 +50,18 @@ static int do_split = FALSE;
static char *script;
#ifndef RUBY_LIB
-#define RUBY_LIB ".:/usr/local/lib/ruby"
+#if defined(MSDOS)
+#define RUBY_LIB "/usr/local/lib/ruby;."
+#else
+#define RUBY_LIB "/usr/local/lib/ruby:."
+#endif
#endif
+#if defined(MSDOS)
+#define RUBY_LIB_SEP ';'
+#else
#define RUBY_LIB_SEP ':'
+#endif
extern VALUE rb_load_path;
VALUE Frequire();
@@ -62,21 +71,24 @@ addpath(path)
char *path;
{
char *p, *s;
+ VALUE ary;
if (path == 0) return;
+ ary = ary_new();
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)));
+ if (s = strrchr(p, RUBY_LIB_SEP)) {
+ ary_push(ary, str_new(p, (int)(s-p)));
p = s + 1;
}
else {
- ary_push(rb_load_path, str_new2(p));
+ ary_push(ary, str_new2(p));
break;
}
}
+ rb_load_path = ary_plus(ary, rb_load_path);
}
static void
@@ -89,13 +101,11 @@ proc_options(argcp, argvp)
int script_given, do_search;
char *s;
- extern VALUE RS, ORS, FS;
-
if (argc == 0) return;
version = FALSE;
- script_given = FALSE;
do_search = FALSE;
+ script_given = 0;
for (argc--,argv++; argc > 0; argc--,argv++) {
if (argv[0][0] != '-' || !argv[0][1]) break;
@@ -127,8 +137,10 @@ proc_options(argcp, argvp)
goto reswitch;
case 'v':
- verbose = TRUE;
show_version();
+ verbose = 2;
+ case 'w':
+ verbose |= 1;
s++;
goto reswitch;
@@ -157,13 +169,12 @@ proc_options(argcp, argvp)
script_given++;
if (script == 0) script = "-e";
if (argv[1]) {
- lex_setsrc("-e", argv[1], strlen(argv[1]));
+ compile_string("-e", argv[1], strlen(argv[1]));
argc--,argv++;
}
else {
- lex_setsrc("-e", "", 0);
+ compile_string("-e", "", 0);
}
- yyparse();
break;
case 'r':
@@ -211,9 +222,9 @@ proc_options(argcp, argvp)
case 'I':
if (*++s)
- ary_push(rb_load_path, str_new2(s));
+ addpath(s);
else if (argv[1]) {
- ary_push(rb_load_path, str_new2(argv[1]));
+ addpath(argv[1]);
argc--,argv++;
}
break;
@@ -250,7 +261,7 @@ proc_options(argcp, argvp)
else if (strcmp("version", s) == 0)
version = 1;
else if (strcmp("verbose", s) == 0)
- verbose = 1;
+ verbose = 2;
else if (strcmp("yydebug", s) == 0)
yydebug = 1;
else {
@@ -277,22 +288,29 @@ proc_options(argcp, argvp)
show_copyright();
}
- if (script_given == 0) {
+ if (script_given == FALSE) {
if (argc == 0) { /* no more args */
- if (verbose) exit(0);
+ if (verbose == 3) exit(0);
script = "-";
load_stdin();
}
else {
script = argv[0];
- if (do_search) {
- script = dln_find_file(script, getenv("PATH"));
- if (!script) script = argv[0];
+ if (script[0] == '\0') {
+ script = "-";
+ load_stdin();
+ }
+ else {
+ if (do_search) {
+ script = dln_find_file(script, getenv("PATH"));
+ if (!script) script = argv[0];
+ }
+ load_file(script, 1);
}
- load_file(script, 1);
- argc--,argv++;
+ argc--; argv++;
}
}
+ if (verbose) verbose = TRUE;
xflag = FALSE;
*argvp = argv;
@@ -321,93 +339,85 @@ proc_options(argcp, argvp)
}
+static VALUE
+open_to_load(fname)
+ char *fname;
+{
+}
+
static void
-readin(fd, fname, script)
- int fd;
+load_file(fname, script)
char *fname;
int script;
{
- struct stat st;
- char *ptr, *p, *pend;
+ extern VALUE rb_stdin;
+ VALUE f;
+ int line_start = 1;
- if (fstat(fd, &st) < 0) rb_sys_fail(fname);
- if (!S_ISREG(st.st_mode))
- Fail("script is not a regular file - %s", fname);
-
- p = ptr = ALLOC_N(char, st.st_size+1);
- if (read(fd, ptr, st.st_size) != st.st_size) {
- free(ptr);
- rb_sys_fail(fname);
+ if (strcmp(fname, "-") == 0) {
+ f = rb_stdin;
+ }
+ else {
+ f = file_open(fname, "r");
}
- pend = p + st.st_size;
- *pend = '\0';
if (script) {
+ VALUE c;
+ VALUE line;
+ VALUE rs = RS;
+
+ RS = RS_default;
if (xflag) {
xflag = FALSE;
- while (p < pend) {
- if (p[0] == '#' && p[1] == '!') {
- char *s = p;
- while (s < pend && *s != '\n') s++;
- if (*s == '\n') {
- *s = '\0';
- if (strstr(p, "ruby")) {
- *s = '\n';
- goto start_read;
- }
+ while (!NIL_P(line = io_gets(f))) {
+ line_start++;
+ if (RSTRING(line)->len > 2
+ || RSTRING(line)->ptr[0] != '#'
+ || RSTRING(line)->ptr[1] != '!') {
+ if (strstr(RSTRING(line)->ptr, "ruby")) {
+ goto start_read;
}
- p = s + 1;
- }
- else {
- while (p < pend && *p++ != '\n')
- ;
- if (p >= pend) break;
}
}
- free(ptr);
- Fail("No Ruby script found in input");
+ RS = rs;
+ LoadError("No Ruby script found in input");
}
- start_read:
- if (p[0] == '#' && p[1] == '!') {
- char *s = p, *q;
+ c = io_getc(f);
+ if (c == INT2FIX('#')) {
+ line = io_gets(f);
+ line_start++;
+
+ if (RSTRING(line)->len > 2
+ || RSTRING(line)->ptr[0] != '#'
+ || RSTRING(line)->ptr[1] != '!') {
- while (s < pend && *s != '\n') s++;
- if (*s == '\n') {
- *s = '\0';
- if (q = strstr(p, "ruby -")) {
+ char *p;
+
+ start_read:
+ if (p = strstr(RSTRING(line)->ptr, "ruby -")) {
int argc; char *argv[2]; char **argvp = argv;
- argc = 2; argv[0] = Qnil; argv[1] = q + 5;
+ char *s;
+
+ s = RSTRING(line)->ptr;
+ while (isspace(*s++))
+ ;
+ *s = '\0';
+ RSTRING(line)->ptr[RSTRING(line)->len-1] = '\0';
+ if (RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
+ RSTRING(line)->ptr[RSTRING(line)->len-2] = '\0';
+ argc = 2; argv[0] = 0; argv[1] = p + 5;
proc_options(&argc, &argvp);
- p = s + 1;
- }
- else {
- *s = '\n';
}
}
}
+ else if (!NIL_P(c)) {
+ io_ungetc(f, c);
+ }
+ RS = rs;
}
- lex_setsrc(fname, p, pend - p);
- yyparse();
- free(ptr);
-}
-
-static void
-load_file(fname, script)
- char *fname;
- int script;
-{
- int fd;
-
- if (fname[0] == '\0') {
- load_stdin();
- return;
- }
-
- fd = open(fname, O_RDONLY, 0);
- if (fd < 0) rb_sys_fail(fname);
- readin(fd, fname, script);
- close(fd);
+ compile_file(fname, f, line_start);
+ if (f != rb_stdin) io_close(f);
}
void
@@ -420,21 +430,7 @@ rb_load_file(fname)
static void
load_stdin()
{
- char buf[32];
- FILE *f;
- char c;
- int fd;
-
- sprintf(buf, "/tmp/ruby-f%d", getpid());
- f = fopen(buf, "w");
- fd = open(buf, O_RDONLY, 0);
- if (fd < 0) rb_sys_fail(buf);
- unlink(buf);
- while ((c = getchar()) != EOF) {
- putc(c, f);
- }
- fclose(f);
- readin(fd, "-");
+ load_file("-", 1);
}
VALUE Progname;
@@ -500,16 +496,28 @@ ruby_options(argc, argv, envp)
origargc = argc; origargv = argv; origenvp = envp;
- rb_define_variable("$@", &errat);
errat = str_new2(argv[0]);
rb_define_variable("$VERBOSE", &verbose);
rb_define_variable("$DEBUG", &debug);
+ addpath(getenv("RUBYLIB"));
+ addpath(RUBY_LIB);
+#ifdef RUBY_ARCHLIB
+ addpath(RUBY_ARCHLIB);
+#endif
#if defined(USE_DLN_A_OUT)
dln_argv0 = argv[0];
#endif
+ rb_define_hooked_variable("$0", &Progname, 0, set_arg0);
+
+ Argv = ary_new2(argc);
+ rb_define_readonly_variable("$*", &Argv);
+ rb_define_global_const("ARGV", Argv);
+
proc_options(&argc, &argv);
+ ruby_script(script);
+
if (do_check && nerrs == 0) {
printf("Syntax OK\n");
exit(0);
@@ -518,18 +526,9 @@ ruby_options(argc, argv, envp)
yyappend_print();
}
if (do_loop) {
- yywhole_loop(do_line, do_split);
+ yywhile_loop(do_line, do_split);
}
- rb_define_hooked_variable("$0", &Progname, 0, set_arg0);
- ruby_script(script);
-
- 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 5ea5a237af..13c96e1a73 100644
--- a/ruby.h
+++ b/ruby.h
@@ -6,7 +6,7 @@
$Date: 1995/01/12 08:54:52 $
created at: Thu Jun 10 14:26:32 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
*************************************************/
@@ -26,12 +26,19 @@
# else
# define const
# endif
+# define _(args)
+#else
+# define _(args) args
#endif
#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
#include <alloca.h>
#endif
+#ifdef _AIX
+#pragma alloca
+#endif
+
typedef unsigned int UINT;
typedef UINT VALUE;
typedef UINT ID;
@@ -66,6 +73,7 @@ typedef unsigned short USHORT;
#define FIXNUM_FLAG 0x01
#define INT2FIX(i) (VALUE)(((int)(i))<<1 | FIXNUM_FLAG)
VALUE int2inum();
+#define INT2NUM(v) int2inum(v)
#if (-1==(((-1)<<1)&FIXNUM_FLAG)>>1)
# define RSHIFT(x,y) ((x)>>y)
@@ -80,19 +88,20 @@ VALUE int2inum();
#define NEGFIXABLE(f) ((f) >= FIXNUM_MIN)
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
-#define NIL_P(p) ((p) == Qnil)
-
+/* special contants - i.e. non-zero and non-fixnum constants */
+#define FALSE 0
#undef TRUE
-extern VALUE TRUE;
-#define FALSE Qnil
+#define TRUE 2
+#define Qnil 4
+
+int rb_test_false_or_nil();
+# define RTEST(v) rb_test_false_or_nil(v)
+#define NIL_P(v) ((VALUE)(v) == Qnil)
extern VALUE cObject;
-extern VALUE cNil;
-extern VALUE cFixnum;
-extern VALUE cData;
-#define CLASS_OF(obj) (FIXNUM_P(obj)?cFixnum: NIL_P(obj)?cNil:\
- RBASIC(obj)->class)
+VALUE rb_class_of();
+#define CLASS_OF(v) rb_class_of(v)
#define T_NIL 0x00
#define T_OBJECT 0x01
@@ -107,9 +116,12 @@ extern VALUE cData;
#define T_HASH 0x0a
#define T_STRUCT 0x0b
#define T_BIGNUM 0x0c
+#define T_FILE 0x0d
-#define T_DATA 0x10
-#define T_MATCH 0x11
+#define T_TRUE 0x20
+#define T_FALSE 0x21
+#define T_DATA 0x22
+#define T_MATCH 0x23
#define T_VARMAP 0xfd
#define T_SCOPE 0xfe
@@ -118,8 +130,11 @@ extern VALUE cData;
#define T_MASK 0xff
#define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
-#define TYPE(x) (FIXNUM_P(x)?T_FIXNUM:NIL_P(x)?T_NIL:BUILTIN_TYPE(x))
-#define Check_Type(x,t) {if (TYPE(x)!=(t)) WrongType(x,t);}
+
+int rb_type();
+#define TYPE(x) rb_type(x)
+
+void Check_Type();
#define Need_Fixnum(x) {if (!FIXNUM_P(x)) (x) = num2fix(x);}
#define NUM2INT(x) (FIXNUM_P(x)?FIX2INT(x):num2int(x))
VALUE num2fix();
@@ -180,6 +195,11 @@ struct RHash {
struct st_table *tbl;
};
+struct RFile {
+ struct RBasic basic;
+ struct OpenFile *fptr;
+};
+
struct RData {
struct RBasic basic;
void (*dmark)();
@@ -189,23 +209,16 @@ struct RData {
#define DATA_PTR(dta) (RDATA(dta)->data)
-VALUE data_new();
-VALUE rb_ivar_get();
-VALUE rb_ivar_set();
-
-#define Get_Data_Struct(obj, iv, type, sval) {\
- VALUE _data_;\
- _data_ = rb_ivar_get(obj, iv);\
- Check_Type(_data_, T_DATA);\
- sval = (type*)DATA_PTR(_data_);\
-}
+VALUE data_object_alloc();
+#define Make_Data_Struct(class,type,mark,free,sval) (\
+ sval = ALLOC(type),\
+ memset(sval, 0, sizeof(type)),\
+ data_object_alloc(class,sval,mark,free)\
+)
-#define Make_Data_Struct(obj, iv, type, mark, free, sval) {\
- VALUE _new_;\
- sval = ALLOC(type);\
- _new_ = data_new(sval,mark,free);\
- memset(sval, 0, sizeof(type));\
- rb_ivar_set(obj, iv, _new_);\
+#define Get_Data_Struct(obj,type,sval) {\
+ Check_Type(obj, T_DATA); \
+ sval = (type*)DATA_PTR(obj);\
}
struct RStruct {
@@ -233,28 +246,27 @@ struct RBignum {
#define RDATA(obj) (R_CAST(RData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
+#define RFILE(obj) (R_CAST(RFile)(obj))
-#define FL_SINGLE (1<<8)
-#define FL_MARK (1<<9)
+#define FL_SINGLETON (1<<8)
+#define FL_MARK (1<<9)
-#define FL_USER0 (1<<10)
-#define FL_USER1 (1<<11)
-#define FL_USER2 (1<<12)
-#define FL_USER3 (1<<13)
-#define FL_USER4 (1<<14)
-#define FL_USER5 (1<<15)
-#define FL_USER6 (1<<16)
-#define FL_USER7 (1<<17)
+#define FL_USER0 (1<<10)
+#define FL_USER1 (1<<11)
+#define FL_USER2 (1<<12)
+#define FL_USER3 (1<<13)
+#define FL_USER4 (1<<14)
+#define FL_USER5 (1<<15)
+#define FL_USER6 (1<<16)
-#define FL_UMASK (0xff<<10)
+#define FL_UMASK (0x7f<<10)
-#define FL_ABLE(x) (!(FIXNUM_P(x)||NIL_P(x)))
+int rb_special_const_p();
+#define FL_ABLE(x) (!(FIXNUM_P(x)||rb_special_const_p(x)))
#define FL_TEST(x,f) (FL_ABLE(x)?(RBASIC(x)->flags&(f)):0)
#define FL_SET(x,f) if (FL_ABLE(x)) {RBASIC(x)->flags |= (f);}
#define FL_UNSET(x,f) if(FL_ABLE(x)){RBASIC(x)->flags &= ~(f);}
-
-extern VALUE Qself;
-#define Qnil 0
+#define FL_REVERSE(x,f) if(FL_ABLE(x)){RBASIC(x)->flags ^= f;}
#define ALLOC_N(type,n) (type*)xmalloc(sizeof(type)*(n))
#define ALLOC(type) (type*)xmalloc(sizeof(type))
@@ -277,6 +289,7 @@ void rb_extend_object();
void rb_define_variable();
void rb_define_const();
+void rb_define_global_const();
void rb_define_method();
void rb_define_singleton_method();
@@ -289,26 +302,30 @@ char *rb_id2name();
ID rb_to_id();
char *rb_class2name();
-VALUE rb_method_boundp();
+int rb_method_boundp();
VALUE rb_eval_string();
VALUE rb_funcall();
VALUE rb_funcall2();
int rb_scan_args();
+VALUE rb_ivar_get();
+VALUE rb_ivar_set();
+
VALUE rb_iv_get();
VALUE rb_iv_set();
void rb_const_set();
VALUE rb_yield();
-VALUE iterator_p();
+int iterator_p();
-VALUE rb_equal();
+int rb_equal();
extern int verbose, debug;
#ifdef __GNUC__
typedef void voidfn ();
+volatile voidfn Raise;
volatile voidfn Fail;
volatile voidfn Fatal;
volatile voidfn Bug;
@@ -316,8 +333,11 @@ volatile voidfn WrongType;
volatile voidfn rb_sys_fail;
volatile voidfn rb_break;
volatile voidfn rb_exit;
-volatile voidfn rb_fail;
+volatile voidfn rb_fatal;
+volatile voidfn rb_raise;
+volatile voidfn rb_notimplement;
#else
+void Raise();
void Fail();
void Fatal();
void Bug();
@@ -325,9 +345,12 @@ void WrongType();
void rb_sys_fail();
void rb_break();
void rb_exit();
-void rb_fail();
+void rb_fatal();
+void rb_raise();
+void rb_notimplement();
#endif
+void Error();
void Warning();
#if defined(EXTLIB) && defined(USE_DLN_A_OUT)
diff --git a/ruby.texi b/ruby.texi
deleted file mode 100644
index 50ffb63a16..0000000000
--- a/ruby.texi
+++ /dev/null
@@ -1,5044 +0,0 @@
-\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/clnt.rb b/sample/clnt.rb
index c8c4b2db9f..7998379aa2 100644
--- a/sample/clnt.rb
+++ b/sample/clnt.rb
@@ -3,15 +3,15 @@
require "socket"
-host=(if $ARGV.length == 2; $ARGV.shift; else "localhost"; end)
+host=(if ARGV.length == 2; ARGV.shift; else "localhost"; end)
print("Trying ", host, " ...")
STDOUT.flush
-s = TCPsocket.open(host, $ARGV.shift)
+s = TCPsocket.open(host, ARGV.shift)
print(" done\n")
print("addr: ", s.addr.join(":"), "\n")
print("peer: ", s.peeraddr.join(":"), "\n")
while gets()
s.write($_)
- print(s.gets)
+ print(s.readline)
end
s.close
diff --git a/sample/dir.rb b/sample/dir.rb
index 3349dc7b6d..1fc0bb2aa8 100644
--- a/sample/dir.rb
+++ b/sample/dir.rb
@@ -1,9 +1,9 @@
# directory access
# list all files but .*/*~/*.o
dirp = Dir.open(".")
-dirp.rewind
for f in dirp
- if !(~/^\./ || ~/~$/ || ~/\.o/)
+ $_ = f
+ if (~/^\./ || ~/~$/ || ~/\.o/)
print f, "\n"
end
end
diff --git a/sample/eval.rb b/sample/eval.rb
new file mode 100644
index 0000000000..da31b77153
--- /dev/null
+++ b/sample/eval.rb
@@ -0,0 +1,41 @@
+line = ''
+indent=0
+print "ruby> "
+while TRUE
+ l = gets
+ if not l
+ break if line == ''
+ else
+ line = line + l
+ if l =~ /,\s*$/
+ print "ruby| "
+ next
+ end
+ if l =~ /^\s*(class|module|def|if|case|while|for|begin)\b[^_]/
+ indent += 1
+ end
+ if l =~ /^\s*end\b[^_]/
+ indent -= 1
+ end
+ if l =~ /{\s*(\|.*\|)?\s*$/
+ indent += 1
+ end
+ if l =~ /^\s*\}/
+ indent -= 1
+ end
+ if indent > 0
+ print "ruby| "
+ next
+ end
+ end
+ begin
+ print eval(line).inspect, "\n"
+ rescue
+ $! = 'exception raised' if not $!
+ print "ERR: ", $!, "\n"
+ end
+ break if not l
+ line = ''
+ print "ruby> "
+end
+print "\n"
diff --git a/sample/evaldef.rb b/sample/evaldef.rb
deleted file mode 100644
index 2cedd54999..0000000000
--- a/sample/evaldef.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# method definition by eval()
-# output:
-# bar
-# (eval):26: method `baz' not available for "#<foo: 0xbfc5c>"(foo)
-
-class Foo
- def foo
- eval("
-def baz
- print(\"bar\n\")
-end")
- end
-end
-
-class Bar : Foo
- def bar
- baz()
- end
-end
-
-f = Foo.new
-b = Bar.new
-
-b.foo
-b.bar
-f.baz
diff --git a/sample/export.rb b/sample/export.rb
index 2d05d8afd7..750b5c1948 100644
--- a/sample/export.rb
+++ b/sample/export.rb
@@ -28,7 +28,7 @@ f.printf "%s\n", Foo
f.quux
-class Bar : Foo
+class Bar<Foo
def quux
super
baz()
diff --git a/sample/fact.rb b/sample/fact.rb
new file mode 100644
index 0000000000..49678bc9d0
--- /dev/null
+++ b/sample/fact.rb
@@ -0,0 +1,8 @@
+def fact(n)
+ if n == 0
+ 1
+ else
+ n * fact(n-1)
+ end
+end
+print fact(ARGV[0].to_i), "\n"
diff --git a/sample/from.rb b/sample/from.rb
index 2f5fcebe12..2ef000face 100755
--- a/sample/from.rb
+++ b/sample/from.rb
@@ -5,15 +5,15 @@ require "base64"
include ParseDate
-if $ARGV[0] == '-w'
+if ARGV[0] == '-w'
wait = TRUE
- $ARGV.shift
+ ARGV.shift
end
class Mail
def Mail.new(f)
- if !f.is_kind_of?(IO)
+ if !f.kind_of?(IO)
f = open(f, "r")
me = super
f.close
@@ -28,7 +28,7 @@ class Mail
@body = []
while f.gets()
$_.chop!
- continue if /^From / # skip From-line
+ next if /^From / # skip From-line
break if /^$/ # end of header
if /^(\S+):\s*(.*)/
@header[attr = $1.capitalize] = $2
@@ -56,7 +56,7 @@ class Mail
end
-$ARGV[0] = '/usr/spool/mail/' + ENV['USER'] if $ARGV.length == 0
+ARGV[0] = '/usr/spool/mail/' + ENV['USER'] if ARGV.length == 0
$outcount = 0;
def fromout(date, from, subj)
@@ -72,8 +72,8 @@ def fromout(date, from, subj)
$outcount += 1
end
-for file in $ARGV
- continue if !File.exists?(file)
+for file in ARGV
+ next if !File.exist?(file)
f = open(file, "r")
while !f.eof
mail = Mail.new(f)
diff --git a/sample/fullpath.pl b/sample/fullpath.pl
deleted file mode 100644
index a07b90edd4..0000000000
--- a/sample/fullpath.pl
+++ /dev/null
@@ -1,22 +0,0 @@
-#! /usr/local/bin/perl
-# convert ls-lR filename into fullpath.
-
-$path = shift;
-if (!defined $path) {
- $path = "";
-}
-elsif ($path !~ /\/$/) {
- $path .= "/"
-}
-
-while (<>) {
- if (/:$/) {
- chop; chop;
- $path = $_ . "/";
- } elsif (/^total/ || /^d/) {
- next;
- } elsif (/^(.*\d )(.+)$/) {
- print $1, $path, $2, "\n";
- }
-}
-
diff --git a/sample/fullpath.rb b/sample/fullpath.rb
index 6c528f6f96..ce268e20b9 100644
--- a/sample/fullpath.rb
+++ b/sample/fullpath.rb
@@ -1,9 +1,9 @@
#! /usr/local/bin/ruby
# convert ls-lR filename into fullpath.
-if $ARGV[0] =~ /-p/
- $ARGV.shift
- path = $ARGV.shift
+if ARGV[0] =~ /-p/
+ ARGV.shift
+ path = ARGV.shift
end
if path == nil
diff --git a/sample/getopts.test b/sample/getopts.test
index adef7628db..2866bccea8 100755
--- a/sample/getopts.test
+++ b/sample/getopts.test
@@ -3,13 +3,16 @@
load("parsearg.rb")
def usage()
- printf("Usage:\n")
- printf("This is Getopt test program \n")
+ printf "Usage:\n"
+ printf "%s -d [-x x] [-y y] [--geometry geom] [--version] [string ...]\n", $0
end
$USAGE = 'usage'
-parseArgs(0, !nil, "d", "x:", "y:", "version", "geometry:")
+parseArgs(0, "d&(x|y)", "dfg", "x:", "y:", "geometry:800x600", "version")
if ($OPT_d)
+ if $OPT_version
+ printf "version 1.0\n"
+ end
if ($OPT_x)
printf("x = %d\n", $OPT_x.to_i)
end
@@ -19,13 +22,15 @@ if ($OPT_d)
if ($OPT_geometry)
printf("geometry = %s\n", $OPT_geometry)
end
+ if $OPT_f
+ printf "f = TRUE\n"
+ end
+ if $OPT_g
+ printf "g = TRUE\n"
+ end
end
-if ($OPT_version)
- printf("version 1.00\n")
-end
-
-while ($ARGV.length != 0)
- print ("other = ", $ARGV[0], "\n")
- $ARGV.shift
+while (ARGV.length != 0)
+ print "other = ", ARGV[0], "\n"
+ ARGV.shift
end
diff --git a/sample/io.rb b/sample/io.rb
index c12e4f4498..0b38d2112d 100644
--- a/sample/io.rb
+++ b/sample/io.rb
@@ -15,8 +15,8 @@ for i in "abc\n\ndef\nghi\n"
print("tt: ", i)
end
-printf("%s:(%d)%s\n", $0, $ARGV.length, $ARGV[0])
-passwd = open($ARGV[0], "r")
+printf("%s:(%d)%s\n", $0, ARGV.length, ARGV[0])
+passwd = open(ARGV[0], "r")
#printf("%s", passwd.find{i|i =~ /\*/})
n = 1
diff --git a/sample/less.rb b/sample/less.rb
index b0906d5d22..8be359108f 100755
--- a/sample/less.rb
+++ b/sample/less.rb
@@ -3,8 +3,8 @@
ZCAT = "/usr/local/bin/zcat"
LESS = "/usr/local/bin/less"
-FILE = $ARGV.pop
-OPTION = (if $ARGV.length == 0; "" else $ARGV.join(" "); end)
+FILE = ARGV.pop
+OPTION = (if ARGV.length == 0; "" else ARGV.join(" "); end)
if FILE =~ /\.(Z|gz)$/
exec(format("%s %s | %s %s", ZCAT, FILE, LESS, OPTION))
diff --git a/sample/list.rb b/sample/list.rb
index 93e3182f84..76035e67d6 100644
--- a/sample/list.rb
+++ b/sample/list.rb
@@ -4,20 +4,20 @@ class MyElem
def initialize(item)
# @ѿϥ󥹥ѿ(פʤ)
@data = item
- @next = nil
+ @succ = nil
end
def data
@data
end
- def next
- @next
+ def succ
+ @succ
end
# obj.data = valפȤȤ˰ۤ˸ƤФ᥽å
- def next=(new)
- @next = new
+ def succ=(new)
+ @succ = new
end
end
@@ -25,7 +25,7 @@ class MyList
def add_to_list(obj)
elt = MyElem.new(obj)
if @head
- @tail.next = elt
+ @tail.succ = elt
else
@head = elt
end
@@ -36,7 +36,7 @@ class MyList
elt = @head
while elt
yield elt
- elt = elt.next
+ elt = elt.succ
end
end
diff --git a/sample/mpart.rb b/sample/mpart.rb
index 2374ae0938..6c40d50e18 100755
--- a/sample/mpart.rb
+++ b/sample/mpart.rb
@@ -4,12 +4,12 @@
lines = 1000
-if ($ARGV[0] =~ /^-(\d+)$/ )
+if (ARGV[0] =~ /^-(\d+)$/ )
lines = $1.to_i;
- $ARGV.shift;
+ ARGV.shift;
end
-basename = $ARGV[0]
+basename = ARGV[0]
extname = "part"
part = 1
diff --git a/sample/observ.rb b/sample/observ.rb
new file mode 100644
index 0000000000..f7b1e73137
--- /dev/null
+++ b/sample/observ.rb
@@ -0,0 +1,31 @@
+#! /usr/local/bin/ruby
+
+require "thread"
+require "observer"
+
+class Tick
+ include Observable
+ def initialize
+ Thread.start do
+ while TRUE
+ sleep 0.999
+ changed
+ notify_observers(Time.now.strftime("%H:%M:%S"))
+ end
+ end
+ end
+end
+
+class Clock
+ def initialize
+ @tick = Tick.new
+ @tick.add_observer(self)
+ end
+ def update(time)
+ print "\e[8D", time
+ STDOUT.flush
+ end
+end
+
+clock = Clock.new
+sleep
diff --git a/sample/philos.rb b/sample/philos.rb
new file mode 100644
index 0000000000..ee0a8cd5fc
--- /dev/null
+++ b/sample/philos.rb
@@ -0,0 +1,54 @@
+#
+# The Dining Philosophers - thread example
+#
+require "thread"
+
+srand
+#srand
+N=9 # number of philosophers
+$forks = []
+for i in 0..N-1
+ $forks[i] = Mutex.new
+end
+$state = "-o"*N
+
+def wait
+ sleep rand(20)/10.0
+end
+
+def think(n)
+ wait
+end
+
+def eat(n)
+ wait
+end
+
+def philosopher(n)
+ while TRUE
+ think n
+ $forks[n].lock
+ if not $forks[(n+1)%N].try_lock
+ $forks[n].unlock # avoid deadlock
+ continue
+ end
+ $state[n*2] = ?|;
+ $state[(n+1)%N*2] = ?|;
+ $state[n*2+1] = ?*;
+ print $state, "\n"
+ eat(n)
+ $state[n*2] = ?-;
+ $state[(n+1)%N*2] = ?-;
+ $state[n*2+1] = ?o;
+ print $state, "\n"
+ $forks[n].unlock
+ $forks[(n+1)%N].unlock
+ end
+end
+
+for i in 0..N-1
+ Thread.start{philosopher(i)}
+ sleep 0.1
+end
+
+sleep
diff --git a/sample/pi.rb b/sample/pi.rb
new file mode 100644
index 0000000000..49067cc347
--- /dev/null
+++ b/sample/pi.rb
@@ -0,0 +1,18 @@
+#!/usr/local/bin/ruby
+
+k, a, b, a1, b1 = 2, 4, 1, 12, 4
+
+while TRUE
+ # Next approximation
+ p, q, k = k*k, 2*k+1, k+1
+ a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
+ # Print common digits
+ d = a / b
+ d1 = a1 / b1
+ while d == d1
+ print d
+ $stdout.flush
+ a, a1 = 10*(a%b), 10*(a1%b1)
+ d, d1 = a/b, a1/b1
+ end
+end
diff --git a/sample/rcs.rb b/sample/rcs.rb
index 13476267b2..3f74da9ef2 100644
--- a/sample/rcs.rb
+++ b/sample/rcs.rb
@@ -7,7 +7,7 @@ hdw = dw / 2.0
w = 20.0 # ̕
h =1.0 # ʂƊʂ̋
d = 0.2 # Pʓ̕オ
-ss="abcdefghijklmnopqrstuvwxyz0123456789!#$%^&*()-=\\[];'`,./"
+ss="abcdefghijklmnopqrstuvwxyz0123456789#!$%^&*()-=\\[];'`,./"
rnd = srand()
while gets()
diff --git a/sample/regx.rb b/sample/regx.rb
new file mode 100644
index 0000000000..b9d8ca6e14
--- /dev/null
+++ b/sample/regx.rb
@@ -0,0 +1,23 @@
+st = "\033[7m"
+en = "\033[m"
+#st = "<<"
+#en = ">>"
+
+while TRUE
+ print "str> "
+ STDOUT.flush
+ input = gets
+ break if not input
+ if input != ""
+ str = input
+ str.chop!
+ end
+ print "pat> "
+ STDOUT.flush
+ re = gets
+ break if not re
+ re.chop!
+ str.gsub! re, "#{st}&#{en}"
+ print str, "\n"
+end
+print "\n"
diff --git a/sample/ruby-mode.el b/sample/ruby-mode.el
index b555994fea..9dfde8588c 100644
--- a/sample/ruby-mode.el
+++ b/sample/ruby-mode.el
@@ -7,8 +7,18 @@
;;; created at: Fri Feb 4 14:49:13 JST 1994
;;;
+(defconst ruby-mode-version "1.0.2")
+
(defconst ruby-block-beg-re
- "class\\|module\\|def\\|if\\|case\\|while\\|for\\|begin"
+ "class\\|module\\|def\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin\\|do"
+ )
+
+(defconst ruby-indent-beg-re
+ "\\(\\s *\\(class\\|module\\|def\\)\\)\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin"
+ )
+
+(defconst ruby-modifier-re
+ "if\\|unless\\|while\\|until"
)
(defconst ruby-block-mid-re
@@ -18,13 +28,13 @@
(defconst ruby-block-end-re "end")
(defconst ruby-delimiter
- (concat "[?$/(){}#\"'`]\\|\\[\\|\\]\\|\\<\\("
- ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\>")
+ (concat "[?$/%(){}#\"'`]\\|\\[\\|\\]\\|\\<\\("
+ ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\>")
)
(defconst ruby-negative
- (concat "^[ \t]*\\(\\b\\(" ruby-block-mid-re "\\)\\|\\("
- ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)")
+ (concat "^[ \t]*\\(\\(" ruby-block-mid-re "\\)\\|\\("
+ ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)")
)
(defconst ruby-operator-chars "[,.+*/%-&|^~=<>:]")
@@ -44,6 +54,10 @@
(define-key ruby-mode-map "}" 'ruby-electric-brace)
(define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun)
(define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun)
+ (define-key ruby-mode-map "\e\C-b" 'ruby-beginning-of-block)
+ (define-key ruby-mode-map "\e\C-f" 'ruby-end-of-block)
+ (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block)
+ (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block)
(define-key ruby-mode-map "\t" 'ruby-indent-command)
(define-key ruby-mode-map "\C-m" 'ruby-reindent-then-newline-and-indent)
(define-key ruby-mode-map "\C-j" 'newline))
@@ -60,7 +74,7 @@
(modify-syntax-entry ?\n ">" 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)
@@ -121,17 +135,6 @@ The variable ruby-indent-level controls the amount of indentation.
(back-to-indentation)
(current-column)))
-(defun ruby-delete-indentation ()
- (let
- ((b nil)
- (m nil))
- (save-excursion
- (beginning-of-line)
- (setq b (point))
- (back-to-indentation)
- (setq m (point)))
- (delete-region b m)))
-
(defun ruby-indent-line (&optional flag)
"Correct indentation of the current ruby line."
(ruby-indent-to (ruby-calculate-indent)))
@@ -141,222 +144,294 @@ The variable ruby-indent-level controls the amount of indentation.
(ruby-indent-line t))
(defun ruby-indent-to (x)
- (let ((p nil) beg end)
- (if (null x)
- nil
- (setq p (- (current-column) (ruby-current-indentation)))
- (ruby-delete-indentation)
- (beginning-of-line)
- (save-excursion
+ (if x
+ (let (shift top beg)
+ (and (< x 0)
+ (error "invalid nest"))
+ (setq shift (current-column))
+ (beginning-of-line)
(setq beg (point))
- (forward-line 1)
- (setq end (point)))
- (indent-to x)
- (if (> p 0) (forward-char p)))))
+ (back-to-indentation)
+ (setq top (current-column))
+ (skip-chars-backward " \t")
+ (cond
+ ((>= x shift)
+ (setq shift 0))
+ ((>= shift top)
+ (setq shift (- shift top)))
+ (t (setq shift 0)))
+ (if (and (bolp)
+ (= x top))
+ (move-to-column (+ x shift))
+ (move-to-column top)
+ (delete-region beg (point))
+ (beginning-of-line)
+ (indent-to x)
+ (move-to-column (+ x shift))))))
(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))))))
+ (if (looking-at "\\?")
+ (progn
+ (or (bolp) (forward-char -1))
+ (not (looking-at "\\sw")))
+ (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)
- (in-string nil)
- (in-paren nil)
- (depth 0)
- (nest nil))
+ (indent 0)
+ (in-string nil)
+ (in-paren nil)
+ (depth 0)
+ (nest nil)
+ (pcol nil))
(save-excursion
- (if start
- (goto-char start)
- (ruby-beginning-of-defun))
- (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))))
- ((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
+ (if start
+ (goto-char start)
+ (ruby-beginning-of-indent))
+ (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
- ((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))
- (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
+ ((or (looking-at "\"") ;skip string
+ (looking-at "'")
+ (looking-at "`"))
+ (setq w (char-after (point)))
+ (cond
+ ((and (not (eobp))
+ (re-search-forward (format "[^\\]%c" w) indent-point t))
+ nil)
+ (t
+ (setq in-string (point))
+ (goto-char indent-point))))
+ ((looking-at "/")
+ (cond
+ ((and (not (eobp)) (ruby-expr-beg))
+ (if (re-search-forward "[^\\]/" indent-point t)
+ nil
+ (setq in-string (point))
+ (goto-char indent-point)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "%")
+ (cond
+ ((and (not (eobp)) (ruby-expr-beg)
+ (looking-at "%[Qq\"'Rr/Xx`]\\(.\\)"))
+ (setq w (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ (cond
+ ((string= w "[") (setq w "]"))
+ ((string= w "{") (setq w "}"))
+ ((string= w "(") (setq w ")"))
+ ((string= w "<") (setq w ">")))
+ (goto-char (match-end 0))
+ (if (search-forward w indent-point t)
+ nil
+ (setq in-string (point))
+ (goto-char indent-point)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "\\?") ;skip ?char
+ (cond
+ ((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 (point))
+ )
+ ((looking-at "(")
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
+ (setq pcol (cons (cons pnt depth) pcol))
+ (setq depth 0)
+ (goto-char pnt)
+ )
+ ((looking-at "[\\[{]")
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
+ (setq depth (1+ depth))
+ (goto-char pnt)
+ )
+ ((looking-at ")")
(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))))
+ (setq depth (cdr (car pcol)))
+ (setq pcol (cdr pcol))
+ (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)
+ (setq w (char-after (point)))
+ (and (not (eq ?_ w))
+ (not (eq ?! w))
+ (not (eq ?? w))))
+ (progn
+ (goto-char (match-beginning 0))
+ (if (looking-at ruby-modifier-re)
+ (ruby-expr-beg)
+ t))
+ (progn
+ (setq nest (cons (cons nil pnt) nest))
+ (setq depth (1+ depth))))
+ (if (looking-at "def\\s *[/`]")
+ (goto-char (match-end 0))
+ (goto-char pnt)))
+ (t
+ (error (format "bad string %s"
+ (buffer-substring (point) pnt)
+ )))))))
+ (list in-string (car nest) depth (car (car pcol))))))
(defun ruby-calculate-indent (&optional parse-start)
(save-excursion
(beginning-of-line)
(let ((indent-point (point))
- (case-fold-search nil)
- state bol eol
- (indent 0))
- (if parse-start
- (goto-char parse-start)
- (ruby-beginning-of-defun)
- (setq parse-start (point)))
- (setq state (ruby-parse-region parse-start indent-point))
- (cond
- ((nth 0 state) ; within string
- (setq indent nil)) ; do nothing
-
- ((nth 1 state) ; in paren
- (goto-char (cdr (nth 1 state)))
- (setq indent
- (if (and (eq (car (nth 1 state)) ?\( )
- (not (looking-at "(\\s *$")))
- (current-column)
- (+ (current-indentation) ruby-indent-level))))
-
- ((> (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)))
-
- (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))
+ (case-fold-search nil)
+ state bol eol
+ (indent 0))
+ (if parse-start
+ (goto-char parse-start)
+ (ruby-beginning-of-indent)
+ (setq parse-start (point)))
+ (back-to-indentation)
+ (setq indent (current-column))
+ (setq state (ruby-parse-region parse-start indent-point))
+ (cond
+ ((nth 0 state) ; within string
+ (setq indent nil)) ; do nothing
+
+ ((car (nth 1 state)) ; in paren
+ (goto-char (cdr (nth 1 state)))
+ (if (eq (car (nth 1 state)) ?\( )
+ (let ((column (current-column))
+ (s (ruby-parse-region (point) indent-point)))
+ (cond
+ ((> (nth 2 s) 0)
+ (goto-char (cdr (nth 1 s)))
+ (forward-word -1)
+ (setq indent (+ (current-column) ruby-indent-level)))
+ (t
+ (setq indent (current-column)))))
+ (cond
+ ((nth 3 state)
+ (goto-char (nth 3 state))
+ (setq indent (+ (current-column) ruby-indent-level)))
+ (t
+ (goto-char parse-start)
+ (back-to-indentation)
+ (setq indent (+ (current-column) (* (nth 2 state) ruby-indent-level)))))
+ ))
+
+ ((> (nth 2 state) 0) ; in nest
+ (goto-char (cdr (nth 1 state)))
+ (forward-word -1) ; skip back a keyword
+ (cond
+ ((looking-at "do") ; iter block is a special case
+ (cond
+ ((nth 3 state)
+ (goto-char (nth 3 state))
+ (setq indent (+ (current-column) ruby-indent-level)))
+ (t
+ (goto-char parse-start)
+ (back-to-indentation)
+ (setq indent (+ (current-column) (* (nth 2 state) ruby-indent-level))))))
+ (t
+ (setq indent (+ (current-column) ruby-indent-level)))))
+
+ ((< (nth 2 state) 0) ; in negative nest
+ (setq indent (+ (current-column) (* (nth 2 state) ruby-indent-level)))))
+
+ (cond
+ (indent
+ (goto-char indent-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)))
-
+ (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)
+ (skip-chars-backward " \t")
+ (or (bobp) (forward-char -1))
+ (and (looking-at ruby-operator-chars)
+ (or (not (or (eq ?/ (char-after (point)))))
+ (null (nth 0 (ruby-parse-region parse-start (point)))))
+ (save-excursion
+ (goto-char parse-start))
+ (not (eq (char-after (1- (point))) ?$))
+ (or (not (eq ?| (char-after (point))))
+ (save-excursion
+ (or (eolp) (forward-char -1))
+ (and (search-backward "|")
+ (skip-chars-backward " \t\n")
+ (and (not (eolp))
+ (progn
+ (forward-char -1)
+ (not (looking-at "\\{")))
+ (progn
+ (forward-word -1)
+ (not (looking-at "do\\>[^_]")))))))
+ (setq indent (+ indent ruby-indent-level)))))))
+ indent)))
+
(defun ruby-electric-brace (arg)
(interactive "P")
(self-insert-command (prefix-numeric-value arg))
(ruby-indent-line t))
(defun ruby-beginning-of-defun (&optional arg)
- "Move backward to next beginning-of-defun.
+ "Move backward to next beginning-of-defun.
With argument, do this that many times.
Returns t unless search stops due to end of buffer."
(interactive "p")
@@ -364,6 +439,13 @@ Returns t unless search stops due to end of buffer."
nil 'move (or arg 1))
(progn (beginning-of-line) t)))
+(defun ruby-beginning-of-indent ()
+ (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\b")
+ nil 'move)
+ (progn
+ (beginning-of-line)
+ t)))
+
(defun ruby-end-of-defun (&optional arg)
"Move forward to next end of defun.
An end of a defun is found by moving forward from the beginning of one."
@@ -373,6 +455,42 @@ An end of a defun is found by moving forward from the beginning of one."
(progn (beginning-of-line) t))
(forward-line 1))
+(defun ruby-move-to-block (n)
+ (let (start pos done down)
+ (setq start (ruby-calculate-indent))
+ (if (eobp)
+ nil
+ (while (and (not (bobp)) (not done))
+ (forward-line n)
+ (cond
+ ((looking-at "^$"))
+ ((looking-at "^\\s *#"))
+ (t
+ (setq pos (current-indentation))
+ (cond
+ ((< start pos)
+ (setq down t))
+ ((and down (= pos start))
+ (setq done t))
+ ((> start pos)
+ (setq done t)))))
+ (if done
+ (progn
+ (back-to-indentation)
+ (if (looking-at ruby-block-mid-re)
+ (setq done nil)))))))
+ (back-to-indentation))
+
+(defun ruby-beginning-of-block ()
+ "Move backward to next beginning-of-block"
+ (interactive)
+ (ruby-move-to-block -1))
+
+(defun ruby-end-of-block ()
+ "Move forward to next beginning-of-block"
+ (interactive)
+ (ruby-move-to-block 1))
+
(defun ruby-reindent-then-newline-and-indent ()
(interactive "*")
(save-excursion
@@ -383,39 +501,32 @@ An end of a defun is found by moving forward from the beginning of one."
(indent-according-to-mode))
(indent-according-to-mode))
-(defun ruby-encomment-region (beg end)
- (interactive "r")
- (save-excursion
- (goto-char beg)
- (while (re-search-forward "^" end t)
- (replace-match "#" nil nil))))
+(fset 'ruby-encomment-region (symbol-function 'comment-region))
(defun ruby-decomment-region (beg end)
(interactive "r")
(save-excursion
(goto-char beg)
(while (re-search-forward "^\\([ \t]*\\)#" end t)
- (replace-match "\\1" nil nil))))
+ (replace-match "\\1" nil nil)
+ (save-excursion
+ (ruby-indent-line)))))
(if (featurep 'hilit19)
(hilit-set-mode-patterns
'ruby-mode
- '(("\\s #.*$" nil comment)
- ("^#.*$" nil comment)
- ("\\$\\(.\\|\\sw+\\)" nil type)
- ("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string)
+ '(("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\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)
+ ("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string)
+ ("^\\s *#.*$" nil comment)
+ ("[^$@?\\]\\(#[^$@{].*$\\)" 1 comment)
+ ("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string)
+ ("^\\s *\\(require\\|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)
+ ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|unless\\|rescue\\|then\\|when\\|while\\|until\\|do\\)\\>[^_]" 1 defun)
+ ("[^_]\\<\\(and\\|break\\|next\\|raise\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\)\\>[^_]" 1 keyword)
+ ("[^_]\\<\\(self\\|nil\\|[A-Z][a-zA-Z_0-9]*\\)\\>[^_]" 1 define)
+ ("\\$\\(.\\|\\sw+\\)" nil type)
+ ("[$@].[a-zA-Z_0-9]*" nil struct)
("^__END__" nil label))))
diff --git a/sample/sieve.rb b/sample/sieve.rb
index a953784284..03ff8a67f4 100644
--- a/sample/sieve.rb
+++ b/sample/sieve.rb
@@ -1,6 +1,6 @@
# sieve of Eratosthenes
sieve = []
-if ! max = $ARGV.shift; max = 100; end
+if ! max = ARGV.shift; max = 100; end
max = max.to_i
print "1"
diff --git a/sample/svr.rb b/sample/svr.rb
index 460c16bedf..14aded8c3f 100644
--- a/sample/svr.rb
+++ b/sample/svr.rb
@@ -11,7 +11,7 @@ socks = [gs]
while TRUE
nsock = select(socks);
- if nsock == nil; continue end
+ next if nsock == nil
for s in nsock[0]
if s == gs
ns = s.accept
diff --git a/sample/test.rb b/sample/test.rb
index 7f26433181..aacddbc56a 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -1,6 +1,8 @@
#! /usr/local/bin/ruby
$testnum=0
+$ntest=0
+$failed = 0
def check(what)
printf "%s\n", what
@@ -8,15 +10,16 @@ def check(what)
$testnum = 0
end
-def ok
+def ok(cond)
$testnum+=1
- printf "ok %d\n", $testnum
-end
-
-def notok
- $testnum+=1
- printf "not ok %s %d\n", $what, $testnum
- $failed = TRUE
+ $ntest+=1
+ if cond
+ printf "ok %d\n", $testnum
+ else
+ where = caller[0]
+ printf "not ok %s %d -- %s\n", $what, $testnum, where
+ $failed+=1
+ end
end
# make sure conditional operators work
@@ -25,50 +28,62 @@ check "condition"
$x = '0';
-$x == $x && ok
-$x != $x && notok
-$x == $x || notok
-$x != $x || ok
+$x == $x && ok(TRUE)
+$x != $x && ok(FALSE)
+$x == $x || ok(FALSE)
+$x != $x || ok(TRUE)
# first test to see if we can run the tests.
-check "if";
+check "if/unless";
$x = 'test';
-if $x == $x then ok else notok end
-if $x != $x then notok else ok end
+ok(if $x == $x then TRUE else FALSE end)
+$bad = FALSE
+unless $x == $x
+ $bad = TRUE
+end
+ok(!$bad)
+ok(unless $x != $x then TRUE else FALSE end)
check "case"
case 5
when 1, 2, 3, 4, 6, 7, 8
- notok
+ ok(FALSE)
when 5
- ok
+ ok(TRUE)
end
case 5
when 5
- ok
+ ok(TRUE)
when 1..10
- notok
+ ok(FALSE)
+end
+
+case 5
+when 1..10
+ ok(TRUE)
+else
+ ok(FALSE)
end
case 5
when 5
- ok
+ ok(TRUE)
else
- notok
+ ok(FALSE)
end
case "foobar"
when /^f.*r$/
- ok
+ ok(TRUE)
else
- notok
+ ok(FALSE)
end
-check "while";
+check "while/until";
tmp = open("while_tmp", "w")
tmp.print "tvi925\n";
@@ -81,30 +96,23 @@ tmp.close
# test break
tmp = open("while_tmp", "r")
+ok(tmp.type == "File")
while tmp.gets()
break if /vt100/
end
-if !tmp.eof && /vt100/ then
- ok
-else
- notok
-end
+ok(!tmp.eof && /vt100/)
tmp.close
-# test continue
+# test next
$bad = FALSE
tmp = open("while_tmp", "r")
while tmp.gets()
- continue if /vt100/;
+ next if /vt100/;
$bad = 1 if /vt100/;
end
-if !tmp.eof || /vt100/ || $bad
- notok
-else
- ok
-end
+ok(!(!tmp.eof || /vt100/ || $bad))
tmp.close
# test redo
@@ -118,37 +126,39 @@ while tmp.gets()
$bad = 1 if /vt100/;
$bad = 1 if /VT100/;
end
-if !tmp.eof || $bad
- notok
-else
- ok
-end
+ok(tmp.eof && !$bad)
tmp.close
# test interval
$bad = FALSE
tmp = open("while_tmp", "r")
while tmp.gets()
- break if not 1..2
+ break unless 1..2
if /vt100/ || /Amiga/ || /paper/
$bad = TRUE
- notok
break
end
end
-ok if not $bad
+ok(!$bad)
tmp.close
File.unlink "while_tmp" or `/bin/rm -f "while_tmp"`
+ok(!File.exist?("while_tmp"))
+
+i = 0
+until i>4
+ i+=1
+end
+ok(i>4)
# exception handling
check "exception";
begin
fail "this must be handled"
- notok
+ ok(FALSE)
rescue
- ok
+ ok(TRUE)
end
$bad = TRUE
@@ -158,10 +168,10 @@ rescue
if $bad
$bad = FALSE
retry
- notok
+ ok(FALSE)
end
end
-ok
+ok(TRUE)
$bad = TRUE
$string = "this must be handled no.3"
@@ -170,9 +180,9 @@ begin
rescue
ensure
$bad = FALSE
- ok
+ ok(TRUE)
end
-notok if $bad || $! != $string
+ok(FALSE) if $bad || $! != $string
# exception in rescue clause
begin
@@ -181,164 +191,163 @@ begin
rescue
fail "exception in rescue clause"
end
- notok
+ ok(FALSE)
rescue
- ok
+ ok(TRUE)
end
-check "array"
-$x = [0, 1, 2, 3, 4, 5]
-if $x[2] == 2
- ok
-else
- notok
+# exception in ensure clause
+begin
+ begin
+ fail "this must be handled no.5"
+ ensure
+ fail "exception in ensure clause"
+ end
+ ok(FALSE)
+rescue
+ ok(TRUE)
end
-if $x[1..3] == [1, 2, 3]
- ok
-else
- notok
+$bad = TRUE
+begin
+ begin
+ fail "this must be handled no.5"
+ ensure
+ $bad = FALSE
+ end
+rescue
end
+ok(!$bad)
-if $x[1,3] == [1, 2, 3]
- ok
-else
- notok
+$bad = TRUE
+begin
+ begin
+ fail "this must be handled no.5"
+ ensure
+ $bad = FALSE
+ end
+rescue
end
+ok(!$bad)
-if [1, 2] + [3, 4] == [1, 2, 3, 4]
- ok
-else
- notok
+$bad = TRUE
+while TRUE
+ begin
+ break
+ ensure
+ $bad = FALSE
+ end
end
+ok(!$bad)
+
+check "array"
+ok([1, 2] + [3, 4] == [1, 2, 3, 4])
+ok([1, 2] * 2 == [1, 2, 1, 2])
+ok([1, 2] * ":" == "1:2")
+
+ok([1, 2].hash == [1, 2].hash)
+
+ok([1,2,3] & [2,3,4] == [2,3])
+ok([1,2,3] | [2,3,4] == [1,2,3,4])
+ok([1,2,3] - [2,3] == [1])
+
+$x = [0, 1, 2, 3, 4, 5]
+ok($x[2] == 2)
+ok($x[1..3] == [1, 2, 3])
+ok($x[1,3] == [1, 2, 3])
$x[0, 2] = 10
-if $x[0] == 10 && $x[1] == 2
- ok
-else
- notok
-end
+ok($x[0] == 10 && $x[1] == 2)
$x[0, 0] = -1
-if $x[0] == -1 && $x[1] == 10
- ok
-else
- notok
-end
+ok($x[0] == -1 && $x[1] == 10)
$x[-1, 1] = 20
-if $x[-1] == 20 && $x.pop == 20
- ok
-else
- notok
-end
+ok($x[-1] == 20 && $x.pop == 20)
+# compact
+$x = [nil, 1, nil, nil, 5, nil, nil]
+$x.compact!
+ok($x == [1, 5])
+
+# empty?
+ok(!$x.empty?)
+$x = []
+ok($x.empty?)
+
+# sort
$x = ["it", "came", "to", "pass", "that", "..."]
$x = $x.sort.join(" ")
-if $x == "... came it pass that to"
- ok
-else
- notok
-end
+ok($x == "... came it pass that to")
+$x = [2,5,3,1,7]
+$x.sort!{|a,b| a<=>b} # sort with condition
+ok($x == [1,2,3,5,7])
+$x.sort!{|a,b| b-a} # reverse sort
+ok($x == [7,5,3,2,1])
# 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 = "The Book of Mormon"
+ok($x.split(//).reverse!.join == "nomroM fo kooB ehT")
+ok("1 byte string".split(//).reverse.join(":") == "g:n:i:r:t:s: :e:t:y:b: :1")
+$x = "a b c d"
+ok($x.split == ['a', 'b', 'c', 'd'])
+ok($x.split(' ') == ['a', 'b', 'c', 'd'])
$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
+ok(($x * 5).join(":") == '1:1:1:1:1')
+ok(($x * 1).join(":") == '1')
+ok(($x * 0).join(":") == '')
+
+*$x = 1..7
+ok($x.size == 7)
+ok($x == [1, 2, 3, 4, 5, 6, 7])
check "hash"
$x = {1=>2, 2=>4, 3=>6}
$y = {1, 2, 2, 4, 3, 6}
-if $x[1] == 2
- ok
-else
- notok
-end
+ok($x[1] == 2)
-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
+ok(begin
+ for k,v in $y
+ fail if k*2 != v
+ end
+ TRUE
+ rescue
+ FALSE
+ end)
-if $x.indexes(2,3) == [4,6]
- ok
-else
- notok
-end
+ok($x.length == 3)
+ok($x.has_key?(1))
+ok($x.has_value?(4))
+ok($x.indexes(2,3) == [4,6])
+ok($x == (1=>2, 2=>4, 3=>6))
$z = $y.keys.join(":")
-if $z == "1:2:3"
- ok
-else
- notok
-end
+ok($z == "1:2:3")
$z = $y.values.join(":")
-if $z == "2:4:6"
- ok
-else
- notok
-end
-
-if $x == $y
- ok
-else
- notok
-end
+ok($z == "2:4:6")
+ok($x == $y)
$y.shift
-if $y.length == 2
- ok
-else
- notok
-end
+ok($y.length == 2)
+
+$z = [1,2]
+$y[$z] = 256
+ok($y[$z] == 256)
check "iterator"
-if iterator? then notok else ok end
+ok(!iterator?)
def ttt
- if iterator? then ok else notok end
+ ok(iterator?)
end
ttt{}
# yield at top level
-begin
- yield
- notok
-rescue
- ok
-end
+ok(!defined?(yield))
$x = [1, 2, 3, 4]
$y = []
@@ -347,11 +356,7 @@ $y = []
for i in $x
$y.push i
end
-if $x == $y
- ok
-else
- notok
-end
+ok($x == $y)
# nested iterator
def tt
@@ -361,59 +366,54 @@ def tt
end
tt{|i| break if i == 5}
-if i == 5
- ok
+ok(i == 5)
+
+# iterator break/redo/next/retry
+unless defined? loop
+ def loop
+ while TRUE
+ yield
+ end
+ end
+ ok(FALSE)
else
- notok
+ ok(TRUE)
end
-# iterator break/redo/continue/retry
done = TRUE
loop{
break
done = FALSE
- notok
}
-ok if done
+ok(done)
-done = TRUE
+done = FALSE
$bad = FALSE
loop {
- break if not done
- done = FALSE
- continue
+ break if done
+ done = TRUE
+ next
$bad = TRUE
}
-if $bad
- notok
-else
- ok
-end
+ok(!$bad)
-done = TRUE
+done = FALSE
$bad = FALSE
loop {
- break if not done
- done = FALSE
+ break if done
+ done = TRUE
redo
$bad = TRUE
}
-if $bad
- notok
-else
- ok
-end
+ok(!$bad)
$x = []
for i in 1 .. 7
- $x.push(i)
-end
-if $x.size == 7
- ok
-else
- notok
+ $x.push i
end
-# $x == [1, 2, 3, 4, 5, 6, 7]
+ok($x.size == 7)
+ok($x == [1, 2, 3, 4, 5, 6, 7])
+
$done = FALSE
$x = []
for i in 1 .. 7 # see how retry works in iterator loop
@@ -423,102 +423,56 @@ for i in 1 .. 7 # see how retry works in iterator loop
end
$x.push(i)
end
-# $x == [1, 2, 3, 1, 2, 3, 4, 5, 6, 7]
-if $x.size == 10
- ok
-else
- notok
-end
+ok($x.size == 10)
+ok($x == [1, 2, 3, 1, 2, 3, 4, 5, 6, 7])
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
+$x = fact(40)
+ok($x == $x)
+ok($x == fact(40))
+ok($x < $x+2)
+ok($x > $x-2)
+ok($x == 815915283247897734345611269596115894272000000000)
+ok($x != 815915283247897734345611269596115894272000000001)
+ok($x+1 == 815915283247897734345611269596115894272000000001)
+ok($x/fact(20) == 335367096786357081410764800000)
+$x = -$x
+ok($x == -815915283247897734345611269596115894272000000000)
+ok(2-(2**32) == -(2**32-2))
+ok(2**32 - 5 == (2**32-3)-2)
check "string & char"
-if "abcd" == "abcd"
- ok
-else
- notok
-end
-
-if "abcd" =~ "abcd"
- ok
-else
- notok
-end
+ok("abcd" == "abcd")
+ok("abcd" =~ "abcd")
+ok("abcd" === "abcd")
$foo = "abc"
-if "#$foo = abc" == "abc = abc"
- ok
-else
- notok
-end
-
-if "#{$foo} = abc" == "abc = abc"
- ok
-else
- notok
-end
+ok("#$foo = abc" == "abc = abc")
+ok("#{$foo} = abc" == "abc = abc")
foo = "abc"
-if "#{foo} = abc" == "abc = abc"
- ok
-else
- notok
-end
+ok("#{foo} = abc" == "abc = abc")
-if '-' * 5 == '-----' then ok else notok end
-if '-' * 1 == '-' then ok else notok end
-if '-' * 0 == '' then ok else notok end
+ok('-' * 5 == '-----')
+ok('-' * 1 == '-')
+ok('-' * 0 == '')
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
+ok(foo * 5 == '-----')
+ok(foo * 1 == '-')
+ok(foo * 0 == '')
# 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
+ok("a"[0] == ?a)
+ok(?a == ?a)
+ok(?\C-a == 1)
+ok(?\M-a == 225)
+ok(?\M-\C-a == 129)
$x = "abcdef"
$y = [ ?a, ?b, ?c, ?d, ?e, ?f ]
@@ -529,33 +483,28 @@ $x.each_byte {|i|
break
end
}
-if not $bad
- ok
-else
- notok
-end
+ok(!$bad)
check "asignment"
a = nil
-if a == nil
- ok
-else
- notok
-end
+ok(defined?(a))
+ok(a == nil)
+# multiple asignment
a, b = 1, 2
-if a == 1 and b == 2 then
- ok
-else
- notok
-end
+ok(a == 1 && b == 2)
+
+a, b = b, a
+ok(a == 2 && b == 1)
+
+a, = 1,2
+ok(a == 1)
a, *b = 1, 2, 3
-if a == 1 and b == [2, 3] then
- ok
-else
- notok
-end
+ok(a == 1 && b == [2, 3])
+
+*a = 1, 2, 3
+ok(a == [1, 2, 3])
check "call"
def aaa(a, b=100, *rest)
@@ -564,191 +513,167 @@ def aaa(a, b=100, *rest)
return res
end
+# not enough argument
begin
- aaa()
- notok
+ aaa() # need at least 1 arg
+ ok(FALSE)
rescue
- ok
+ ok(TRUE)
end
begin
- aaa
- notok
+ aaa # no arg given (exception raised)
+ ok(FALSE)
rescue
- ok
+ ok(TRUE)
end
begin
if aaa(1) == [1, 100]
- ok
+ ok(TRUE)
else
fail
end
rescue
- notok
+ ok(FALSE)
end
begin
if aaa(1, 2) == [1, 2]
- ok
+ ok(TRUE)
else
fail
end
rescue
- notok
+ ok(FALSE)
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
+ok(aaa(1, 2, 3, 4) == [1, 2, 3, 4])
+ok(aaa(1, *[2, 3, 4]) == [1, 2, 3, 4])
check "proc"
$proc = proc{|i| i}
-if $proc.call(2) == 2
- ok
-else
- notok
-end
+ok($proc.call(2) == 2)
+ok($proc.call(3) == 3)
$proc = proc{|i| i*2}
-if $proc.call(2) == 4
- ok
-else
- notok
-end
+ok($proc.call(2) == 4)
+ok($proc.call(3) == 6)
proc{
iii=5 # dynamic local variable
- $proc = proc{ |i|
+ $proc = proc{|i|
iii = i
}
$proc2 = proc {
$x = iii # dynamic variables shared by procs
}
- if defined?(iii) # dynamic variables' scope
- ok
- else
- notok
- end
+ # scope of dynamic variables
+ ok(defined?(iii))
}.call
-if defined?(iii) # out of scope
- notok
-else
- ok
-end
+ok(!defined?(iii)) # out of scope
+
$x=0
$proc.call(5)
$proc2.call
-if $x == 5
- ok
-else
- notok
-end
+ok($x == 5)
-check "signal"
-begin
- kill "SIGINT", $$
- sleep 1
- notok
-rescue
- ok
-end
+if defined? Process.kill
+ check "signal"
-$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 = 0
+ trap "SIGINT", proc{|sig| $x = sig}
+ Process.kill "SIGINT", $$
+ sleep 0.1
+ ok($x == 2)
-$x = FALSE
-trap "SIGINT", "$x = TRUE;fail"
-begin
- kill "SIGINT", $$
- sleep 1
- notok
-rescue
- if $x
- ok
- else
- notok
+ trap "SIGINT", proc{fail "Interrupt"}
+
+ x = FALSE
+ begin
+ Process.kill "SIGINT", $$
+ sleep 0.1
+ rescue
+ x = $!
end
+ ok(x =~ /Interrupt/)
+else
+ ok(FALSE)
end
check "eval"
$bad=FALSE
-eval 'while FALSE; $bad = TRUE; print "foo\n" end
-if not $bad then ok else notok end'
+eval 'while FALSE; $bad = TRUE; print "foo\n" end'
+ok(!$bad)
-$foo = 'ok'
+ok(eval('TRUE'))
+
+$foo = 'ok(TRUE)'
begin
eval $foo
rescue
- notok
+ ok(FALSE)
end
-check "system"
-if `echo foobar` == "foobar\n"
- ok
-else
- notok
+ok(eval("$foo") == 'ok(TRUE)')
+ok(eval("TRUE") == TRUE)
+i = 5
+ok(eval("i == 5"))
+ok(eval("i") == 5)
+ok(eval("defined? i"))
+
+# eval with binding
+def test_ev
+ local1 = "local1"
+ lambda {
+ local2 = "local2"
+ return binding
+ }.call
end
-if `./ruby -e 'print "foobar"'` == 'foobar'
- ok
-else
- notok
+$x = test_ev
+ok(eval("local1", $x) == "local1") # static local var
+ok(eval("local2", $x) == "local2") # dynamic local var
+$bad = TRUE
+begin
+ p eval("local1")
+rescue NameError # must raise error
+ $bad = FALSE
end
+ok(!$bad)
+
+module EvTest
+ EVTEST1 = 25
+ evtest2 = 125
+ $x = binding
+end
+ok(eval("EVTEST1", $x) == 25) # constant in module
+ok(eval("evtest2", $x) == 125) # local var in module
+$bad = TRUE
+begin
+ eval("EVTEST1")
+rescue NameError # must raise error
+ $bad = FALSE
+end
+ok(!$bad)
+
+check "system"
+ok(`echo foobar` == "foobar\n")
+ok(`./ruby -e 'print "foobar"'` == 'foobar')
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
+ok(`./ruby -s script_tmp -zzz` == 'TRUE')
+ok(`./ruby -s script_tmp -zzz=555` == '555')
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
+ok(`./ruby script_tmp -zzz=678` == '678')
tmp = open("script_tmp", "w")
tmp.print "this is a leading junk\n";
@@ -758,17 +683,8 @@ 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
+ok(`./ruby -x script_tmp` == 'nil')
+ok(`./ruby -x script_tmp -zzz=555` == '555')
tmp = open("script_tmp", "w")
for i in 1..5
@@ -780,13 +696,14 @@ tmp.close
done = TRUE
tmp = open("script_tmp", "r")
while tmp.gets
+ print "c: ", $_
if $_.to_i % 5 != 0
done = FALSE
- notok
break
end
end
-ok if done
+tmp.close
+ok(done)
File.unlink "script_tmp" or `/bin/rm -f "script_tmp"`
File.unlink "script_tmp.bak" or `/bin/rm -f "script_tmp.bak"`
@@ -807,19 +724,11 @@ end
include Const
-if [TEST1,TEST2,TEST3,TEST4] == [1,2,3,4]
- ok
-else
- notok
-end
+ok([TEST1,TEST2,TEST3,TEST4] == [1,2,3,4])
include Const2
-
-if [TEST1,TEST2,TEST3,TEST4] == [1,2,6,8]
- ok
-else
- notok
-end
+STDERR.print "intentionally redefines TEST3, TEST4\n" if $VERBOSE
+ok([TEST1,TEST2,TEST3,TEST4] == [1,2,6,8])
check "clone"
foo = Object.new
@@ -831,200 +740,124 @@ 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
+ok(bar.test2 == "test2")
+ok(bar.test == "test")
+ok(foo.test == "test")
begin
foo.test2
- notok
+ ok FALSE
rescue
- ok
+ ok TRUE
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.
+# test2 failing because ary2 goes str->numeric->str and ary does not.
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
+ok(ary.length == ary2.length)
+ok(ary.join(':') == ary2.join(':'))
+ok($x =~ /def/)
check "math"
-if Math.sqrt(4) == 2
- ok
-else
- notok
-end
+ok(Math.sqrt(4) == 2)
include Math
-if sqrt(4) == 2
- ok
-else
- notok
-end
+ok(sqrt(4) == 2)
check "struct"
struct_test = Struct.new("Test", :foo, :bar)
-if struct_test == Struct::Test
- ok
-else
- notok
-end
+ok(struct_test == Struct::Test)
+
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
+ok(test.foo == 1 && test.bar == 2)
+ok(test[0] == 1 && test[1] == 2)
+
a, b = test
-if a == 1 && b == 2
- ok
-else
- notok
-end
+ok(a == 1 && b == 2)
+
test[0] = 22
-if test.foo == 22
- ok
-else
- notok
-end
+ok(test.foo == 22)
+
test.bar = 47
-if test.bar == 47
- ok
-else
- notok
-end
+ok(test.bar == 47)
check "variable"
-if $$.is_instance_of? Fixnum
- ok
-else
- notok
-end
+ok($$.instance_of?(Fixnum))
+# read-only variable
begin
$$ = 5
- notok
+ ok FALSE
rescue
- ok
+ ok TRUE
end
foobar = "foobar"
$_ = foobar
-if $_ == foobar
- ok
-else
- notok
-end
+ok($_ == foobar)
check "trace"
$x = 1234
$y = 0
trace_var :$x, proc{$y = $x}
$x = 40414
-if $y == $x
- ok
-else
- notok
-end
+ok($y == $x)
untrace_var :$x
$x = 19660208
-if $y != $x
- ok
-else
- notok
-end
+ok($y != $x)
trace_var :$x, proc{$x *= 2}
$x = 5
-if $x == 10
- ok
-else
- notok
-end
+ok($x == 10)
+
untrace_var :$x
check "defined?"
-if defined? $x
- ok
-else
- notok
-end
+
+ok(defined?($x)) # global variable
+ok(defined?($x) == 'global-variable')# returns description
foo=5
-if defined? foo
- ok
-else
- notok
-end
+ok(defined?(foo)) # local variable
-if defined? Array
- ok
-else
- notok
-end
+ok(defined?(Array)) # constant
+ok(defined?(Object.new)) # method
+ok(!defined?(Object.print)) # private method
+ok(defined?(1 == 2)) # operator expression
-if defined? Object.new
- ok
-else
- notok
+def defined_test
+ return !defined?(yield)
end
-if defined? 1 == 2
- ok
-else
- notok
-end
+ok(defined_test) # not iterator
+ok(!defined_test{}) # called as iterator
-if defined? fail
- ok
-else
- notok
+check "alias"
+class Alias0
+ def foo; "foo" end
end
-
-def defined_test
- return defined?(yield)
+class Alias1<Alias0
+ alias bar foo
+ def foo; "foo+" + super end
end
-
-if defined_test
- notok
-else
- ok
+class Alias2<Alias1
+ alias baz foo
+ undef foo
end
-if defined_test{}
- ok
-else
- notok
-end
+x = Alias2.new
+ok(x.bar == "foo")
+ok(x.baz == "foo+foo")
+
+# check for cache
+ok(x.baz == "foo+foo")
check "gc"
begin
@@ -1032,9 +865,13 @@ begin
tmp = [0,1,2,3,4,5,6,7,8,9]
}
tmp = nil
- ok
+ ok TRUE
rescue
- notok
+ ok FALSE
end
-print "end of test\n" if not $failed
+if $failed > 0
+ printf "test: %d failed %d\n", $ntest, $failed
+else
+ printf "end of test(test: %d)\n", $ntest
+end
diff --git a/sample/time.rb b/sample/time.rb
index 715d98ac9e..f4f4ec4883 100755
--- a/sample/time.rb
+++ b/sample/time.rb
@@ -1,5 +1,5 @@
#! /usr/local/bin/ruby
-cmd = $ARGV.join(" ")
+cmd = ARGV.join(" ")
b = Time.now
system(cmd)
e = Time.now
diff --git a/sample/tkbiff.rb b/sample/tkbiff.rb
index 9b406010cb..24860c11a6 100644
--- a/sample/tkbiff.rb
+++ b/sample/tkbiff.rb
@@ -1,17 +1,23 @@
#! /usr/local/bin/ruby
-if $ARGV.length == 0
+if ARGV[0] != '-d'
+ unless $DEBUG
+ exit if fork
+ end
+else
+ ARGV.shift
+end
+
+if ARGV.length == 0
if ENV['MAIL']
$spool = ENV['MAIL']
else
$spool = '/usr/spool/mail/' + ENV['USER']
end
else
- $spool = $ARGV[0]
+ $spool = ARGV[0]
end
-exit if fork
-
require "parsedate"
require "base64"
@@ -19,7 +25,7 @@ include ParseDate
class Mail
def Mail.new(f)
- if !f.is_kind_of?(IO)
+ if !f.kind_of?(IO)
f = open(f, "r")
me = super
f.close
@@ -34,7 +40,7 @@ class Mail
@body = []
while f.gets()
$_.chop!
- continue if /^From / # skip From-line
+ next if /^From / # skip From-line
break if /^$/ # end of header
if /^(\S+):\s*(.*)/
@header[attr = $1.capitalize] = $2
@@ -83,23 +89,37 @@ $top.bind "Control-q", proc{exit}
$top.bind "space", proc{exit}
$spool_size = 0
+$check_time = Time.now
+
def check
+ $check_time = Time.now
size = File.size($spool)
if size and size != $spool_size
+ $spool_size = size
pop_up if size > 0
end
Tk.after 5000, proc{check}
end
+if defined? Thread
+ Thread.start do
+ loop do
+ sleep 600
+ if Time.now - $check_time > 200
+ Tk.after 5000, proc{check}
+ end
+ end
+ end
+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
+ next if !date
y = m = d = 0
y, m, d = parsedate(date) if date
from = "sombody@somewhere" if ! from
@@ -112,10 +132,18 @@ def pop_up
f.close
if outcount == 0
$list.insert 'end', "You have no mail."
+ else
+ $list.see 'end'
end
$top.deiconify
Tk.after 2000, proc{$top.withdraw}
end
+$list.insert 'end', "You have no mail."
check
-Tk.mainloop
+Tk.after 2000, proc{$top.withdraw}
+begin
+ Tk.mainloop
+rescue
+ `echo #$! > /tmp/tkbiff`
+end
diff --git a/sample/tkbrowse.rb b/sample/tkbrowse.rb
index dbaa132d1f..d127996173 100644
--- a/sample/tkbrowse.rb
+++ b/sample/tkbrowse.rb
@@ -25,10 +25,10 @@ list = TkScrollbox.new {
def browse (dir, file)
if dir != "."
file="#{dir}/#{file}"
- if File.isdirectory? file
+ if File.directory? file
system "browse #{file} &"
else
- if File.isfile? file
+ if File.file? file
if ENV['EDITOR']
system format("%s %s&", ENV['EDITOR'], file)
else
@@ -44,8 +44,8 @@ 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]
+if ARGV.length>0
+ dir = ARGV[0]
else
dir="."
end
diff --git a/sample/tkfrom.rb b/sample/tkfrom.rb
index 4a0d8c2b5d..9a53ea2d72 100644
--- a/sample/tkfrom.rb
+++ b/sample/tkfrom.rb
@@ -7,7 +7,7 @@ include ParseDate
class Mail
def Mail.new(f)
- if !f.is_kind_of?(IO)
+ if !f.kind_of?(IO)
f = open(f, "r")
me = super
f.close
@@ -22,7 +22,7 @@ class Mail
@body = []
while f.gets()
$_.chop!
- continue if /^From / # skip From-line
+ next if /^From / # skip From-line
break if /^$/ # end of header
if /^(\S+):\s*(.*)/
@header[attr = $1.capitalize] = $2
@@ -50,7 +50,7 @@ class Mail
end
-$ARGV[0] = '/usr/spool/mail/' + ENV['USER'] if $ARGV.length == 0
+ARGV[0] = '/usr/spool/mail/' + ENV['USER'] if ARGV.length == 0
require "tk"
list = scroll = nil
@@ -85,13 +85,13 @@ root.bind "Control-q", proc{exit}
root.bind "space", proc{exit}
$outcount = 0;
-for file in $ARGV
- continue if !File.exists?(file)
+for file in ARGV
+ next if !File.exist?(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
+ next if !date
y = m = d = 0
y, m, d = parsedate(date) if date
from = "sombody@somewhere" if ! from
@@ -102,6 +102,7 @@ for file in $ARGV
$outcount += 1
end
f.close
+ list.see 'end'
end
limit = 10000
diff --git a/sample/tkline.rb b/sample/tkline.rb
index 843893b5d9..63d763a680 100644
--- a/sample/tkline.rb
+++ b/sample/tkline.rb
@@ -1,5 +1,21 @@
+
+$tk_thread_safe = TRUE
require "tkclass"
+$tkline_init = FALSE
+def start_random
+ return if $tkline_init
+ $tkline_init = TRUE
+ if defined? Thread
+ Thread.start do
+ loop do
+ sleep 2
+ Line.new($c, rand(400), rand(200), rand(400), rand(200))
+ end
+ end
+ end
+end
+
$c = Canvas.new
$c.pack
$start_x = start_y = 0
@@ -7,7 +23,8 @@ $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')
+ $current_line = Line.new($c, x, y, x, y)
+ start_random
end
def do_motion(x, y)
if $current_line
@@ -23,7 +40,7 @@ def do_release(x, y)
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})
+$c.bind("1", proc{|e| do_press e.x, e.y})
+$c.bind("B1-Motion", proc{|x, y| do_motion x, y}, "%x %y")
+$c.bind("ButtonRelease-1", proc{|x, y| do_release x, y}, "%x %y")
Tk.mainloop
diff --git a/sample/trojan.pl b/sample/trojan.pl
deleted file mode 100644
index fe80786fa5..0000000000
--- a/sample/trojan.pl
+++ /dev/null
@@ -1,12 +0,0 @@
-#! /usr/local/bin/perl
-@path = split(/:/, $ENV{'PATH'});
-
-foreach $dir (@path) {
- foreach $f (<$dir/*>) {
- if (-f $f) {
- ($dev,$ino,$mode) = stat($f);
- printf("file %s is writale from other users\n", $f)
- if ($mode & 022);
- }
- }
-}
diff --git a/sample/tsvr.rb b/sample/tsvr.rb
new file mode 100644
index 0000000000..fbc6545bb5
--- /dev/null
+++ b/sample/tsvr.rb
@@ -0,0 +1,23 @@
+# socket example - server side using thread
+# usage: ruby tsvr.rb
+
+require "socket"
+require "thread"
+
+gs = TCPserver.open(0)
+addr = gs.addr
+addr.shift
+printf("server is on %d\n", addr.join(":"))
+
+while TRUE
+ ns = gs.accept
+ print(ns, " is accepted\n")
+ Thread.start do
+ s = ns # save to dynamic variable
+ while s.gets
+ s.write($_)
+ end
+ print(s, " is gone\n")
+ s.close
+ end
+end
diff --git a/sample/uumerge.rb b/sample/uumerge.rb
index ac6e1c6849..297b08f26a 100755
--- a/sample/uumerge.rb
+++ b/sample/uumerge.rb
@@ -1,8 +1,8 @@
#!/usr/local/bin/ruby
-if $ARGV[0] == "-c"
+if ARGV[0] == "-c"
out_stdout = 1;
- $ARGV.shift
+ ARGV.shift
end
while gets()
@@ -27,8 +27,8 @@ while gets()
break
end
sub(/[a-z]+$/, ""); # handle stupid trailing lowercase letters
- continue if /[a-z]/
- continue if !(((($_[0] - 32) & 077) + 2) / 3 == $_.length / 4)
+ next if /[a-z]/
+ next if !(((($_[0] - 32) & 077) + 2) / 3 == $_.length / 4)
out << $_.unpack("u");
end
diff --git a/sig.h b/sig.h
index da30956e12..5fc8abe1b6 100644
--- a/sig.h
+++ b/sig.h
@@ -2,7 +2,7 @@
sig.h -
- $Author$
+ $Author: matz $
$Date$
created at: Wed Aug 16 01:15:38 JST 1995
@@ -10,19 +10,43 @@
#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
+#define TRAP_BEG (trap_immediate=1)
+#define TRAP_END (trap_immediate=0)
-typedef RETSIGTYPE(*SIGHANDLE)();
-SIGHANDLE sig_beg();
-void sig_end();
+extern int prohibit_interrupt;
+#define DEFER_INTS {prohibit_interrupt++;}
+#define ALLOW_INTS {prohibit_interrupt--; CHECK_INTS;}
extern int trap_pending;
+#ifdef THREAD
+extern int thread_critical;
+#if defined(HAVE_SETITIMER) && !defined(__BOW__)
+extern int thread_pending;
+void thread_schedule();
+# define CHECK_INTS if (!prohibit_interrupt) {\
+ if (trap_pending) rb_trap_exec();\
+ if (thread_pending && !thread_critical) thread_schedule();\
+}
+# else
+/* pseudo preemptive thread switching */
+extern int thread_tick;
+#define THREAD_TICK 500
+void thread_schedule();
+# define CHECK_INTS if (!prohibit_interrupt) {\
+ if (trap_pending) rb_trap_exec();\
+ if (!thread_critical) {\
+ if (thread_tick-- <= 0) {\
+ thread_tick = THREAD_TICK;\
+ thread_schedule();\
+ }\
+ }\
+}
+# endif
+#else
+# define CHECK_INTS if (!prohibit_interrupt) {\
+ if (trap_pending) rb_trap_exec();\
+}
+#endif
#endif
diff --git a/signal.c b/signal.c
index a91facc831..a7a35f0a90 100644
--- a/signal.c
+++ b/signal.c
@@ -13,6 +13,10 @@
#include <signal.h>
#include <stdio.h>
+#ifndef NSIG
+#define NSIG (_SIGMAX + 1) /* For QNX */
+#endif
+
static struct signals {
char *signm;
int signo;
@@ -172,13 +176,13 @@ f_kill(argc, argv)
char *s;
if (argc < 2)
- Fail("wrong # of arguments -- kill(sig, pid...)");
+ ArgError("wrong # of arguments -- kill(sig, pid...)");
switch (TYPE(argv[0])) {
case T_FIXNUM:
sig = FIX2UINT(argv[0]);
if (sig >= NSIG) {
s = rb_id2name(sig);
- if (!s) Fail("Bad signal");
+ if (!s) ArgError("Bad signal");
goto str_signal;
}
break;
@@ -196,7 +200,7 @@ f_kill(argc, argv)
if (strncmp("SIG", s, 3) == 0)
s += 3;
if((sig = signm2signo(s)) == 0)
- Fail("Unrecognized signal name `%s'", s);
+ ArgError("Unrecognized signal name `%s'", s);
if (negative)
sig = -sig;
@@ -204,7 +208,7 @@ f_kill(argc, argv)
break;
default:
- Fail("bad signal type %s", rb_class2name(CLASS_OF(argv[0])));
+ ArgError("bad signal type %s", rb_class2name(CLASS_OF(argv[0])));
break;
}
@@ -217,25 +221,24 @@ f_kill(argc, argv)
#else
if (kill(-pid, sig) < 0)
#endif
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
}
}
else {
for (i=1; i<argc; i++) {
Check_Type(argv[i], T_FIXNUM);
if (kill(FIX2UINT(argv[i]), sig) < 0)
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
}
}
return INT2FIX(i-1);
}
static VALUE trap_list[NSIG];
-#ifdef SAFE_SIGHANDLE
static int trap_pending_list[NSIG];
int trap_pending;
int trap_immediate;
-#endif
+int prohibit_interrupt;
void
gc_mark_trap_list()
@@ -248,40 +251,75 @@ gc_mark_trap_list()
}
}
+#ifdef POSIX_SIGNAL
+void
+posix_signal(signum, handler)
+ int signum;
+ RETSIGTYPE (*handler)();
+{
+ struct sigaction sigact;
+
+ sigact.sa_handler = handler;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ sigaction(signum, &sigact, 0);
+}
+#endif
+
static RETSIGTYPE
sighandle(sig)
int sig;
{
- if (sig >= NSIG ||(sig != SIGINT && trap_list[sig] == Qnil))
- Fail("trap_handler: Bad signal %d", sig);
+ if (sig >= NSIG ||(sig != SIGINT && !trap_list[sig]))
+ Bug("trap_handler: Bad signal %d", sig);
-#ifndef HAVE_BSD_SIGNALS
+#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
signal(sig, sighandle);
#endif
-#ifdef SAFE_SIGHANDLE
if (trap_immediate) {
- if (sig == SIGINT && !trap_list[sig]) Fail("Interrupt");
+ trap_immediate = 0;
+ if (sig == SIGINT && !trap_list[SIGINT]) {
+#ifdef THREAD
+ thread_interrupt();
+#else
+ rb_interrupt();
+#endif
+ }
rb_trap_eval(trap_list[sig], sig);
+ trap_immediate = 1;
}
else {
trap_pending++;
trap_pending_list[sig]++;
}
-#else
- if (sig == SIGINT && !trap_list[sig]) Fail("Interrupt");
- rb_trap_eval(trap_list[sig], sig);
+}
+
+#ifdef SIGBUS
+static RETSIGTYPE
+sigbus(sig)
+ int sig;
+{
+ Bug("Bus Error");
+}
#endif
+
+#ifdef SIGSEGV
+static RETSIGTYPE
+sigsegv(sig)
+ int sig;
+{
+ Bug("Segmentation fault");
}
+#endif
void
rb_trap_exit()
{
if (trap_list[0])
- rb_trap_eval(trap_list[0], 0);
+ rb_eval_cmd(trap_list[0], ary_new3(1, INT2FIX(0)));
}
-#ifdef SAFE_SIGHANDLE
void
rb_trap_exec()
{
@@ -290,14 +328,18 @@ rb_trap_exec()
for (i=0; i<NSIG; i++) {
if (trap_pending_list[i]) {
trap_pending_list[i] = 0;
- if (i == SIGINT && trap_list[SIGINT] == 0)
- Fail("Interrupt");
+ if (i == SIGINT && trap_list[SIGINT] == 0) {
+#ifdef THREAD
+ thread_interrupt();
+#else
+ rb_interrupt();
+#endif
+ }
rb_trap_eval(trap_list[i], i);
}
}
trap_pending = 0;
}
-#endif
struct trap_arg {
#ifndef NT
@@ -313,7 +355,7 @@ struct trap_arg {
static RETSIGTYPE
sigexit()
{
- rb_exit(1);
+ rb_exit(0);
}
static VALUE
@@ -321,12 +363,12 @@ trap(arg)
struct trap_arg *arg;
{
RETSIGTYPE (*func)();
- VALUE command;
+ VALUE command, old;
int i, sig;
func = sighandle;
command = arg->cmd;
- if (command == Qnil) {
+ if (NIL_P(command)) {
func = SIG_IGN;
}
else if (TYPE(command) == T_STRING) {
@@ -356,7 +398,7 @@ trap(arg)
}
}
if (func == SIG_IGN || func == SIG_DFL) {
- command = Qnil;
+ command = 0;
}
if (TYPE(arg->sig) == T_STRING) {
@@ -366,15 +408,44 @@ trap(arg)
s += 3;
sig = signm2signo(s);
if (sig == 0 && strcmp(s, "EXIT") != 0)
- Fail("Invalid signal SIG%s", s);
+ ArgError("Invalid signal SIG%s", s);
}
else {
sig = NUM2INT(arg->sig);
}
if (sig < 0 || sig > NSIG) {
- Fail("Invalid signal no %d", sig);
+ ArgError("Invalid signal no %d", sig);
+ }
+#if defined(THREAD) && defined(HAVE_SETITIMER) && !defined(__BOW__)
+ if (sig == SIGVTALRM) {
+ ArgError("SIGVTALRM reserved for Thread; cannot set handler");
+ }
+#endif
+ if (func == SIG_DFL) {
+ switch (sig) {
+ case SIGINT:
+ func = sighandle;
+ break;
+#ifdef SIGBUS
+ case SIGBUS:
+ func = sigbus;
+ break;
+#endif
+#ifdef SIGSEGV
+ case SIGSEGV:
+ func = sigsegv;
+ break;
+#endif
+ }
}
+#ifdef POSIX_SIGNAL
+ posix_signal(sig, func);
+#else
signal(sig, func);
+#endif
+ old = trap_list[sig];
+ if (!old) old = Qnil;
+
trap_list[sig] = command;
/* enable at least specified signal. */
#ifdef HAVE_SIGPROCMASK
@@ -382,7 +453,7 @@ trap(arg)
#else
arg->mask &= ~sigmask(sig);
#endif
- return Qnil;
+ return old;
}
#ifndef NT
@@ -407,7 +478,7 @@ f_trap(argc, argv)
struct trap_arg arg;
if (argc == 0 || argc > 2) {
- Fail("wrong # of arguments -- trap(sig, cmd)/trap(sig){...}");
+ ArgError("wrong # of arguments -- trap(sig, cmd)/trap(sig){...}");
}
arg.sig = argv[0];
@@ -433,29 +504,21 @@ f_trap(argc, argv)
#endif
}
-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 cKernel;
- rb_define_method(cKernel, "kill", f_kill, -1);
- rb_define_method(cKernel, "trap", f_trap, -1);
+ rb_define_private_method(cKernel, "trap", f_trap, -1);
+#ifdef POSIX_SIGNAL
+ posix_signal(SIGINT, sighandle);
+#else
+ signal(SIGINT, sighandle);
+#endif
+#ifdef SIGBUS
+ signal(SIGBUS, sigbus);
+#endif
+#ifdef SIGSEGV
+ signal(SIGSEGV, sigsegv);
+#endif
}
diff --git a/sprintf.c b/sprintf.c
index 91ca246f8d..c845ecc0f4 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:59 $
created at: Fri Oct 15 10:39:26 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -51,7 +51,7 @@ f_sprintf(argc, argv)
}
#define GETARG() \
- ((argc == 0)?Fail("too few argument."),0:(argc--, (argv++)[0]))
+ ((argc == 0)?(ArgError("too few argument."),0):(argc--,((argv++)[0])))
fmt = (struct RString*)GETARG();
Check_Type(fmt, T_STRING);
@@ -77,9 +77,9 @@ f_sprintf(argc, argv)
switch (*p) {
default:
if (isprint(*p))
- Fail("malformed format string - %%%c", *p);
+ ArgError("malformed format string - %%%c", *p);
else
- Fail("malformed format string");
+ ArgError("malformed format string");
break;
case ' ':
@@ -114,13 +114,13 @@ f_sprintf(argc, argv)
width = 10 * width + (*p - '0');
}
if (p >= end) {
- Fail("malformed format string - %%[0-9]");
+ ArgError("malformed format string - %%[0-9]");
}
goto retry;
case '*':
if (flags & FWIDTH) {
- Fail("width given twice");
+ ArgError("width given twice");
}
flags |= FWIDTH;
@@ -135,7 +135,7 @@ f_sprintf(argc, argv)
case '.':
if (flags & FPREC) {
- Fail("precision given twice");
+ ArgError("precision given twice");
}
prec = 0;
@@ -154,12 +154,15 @@ f_sprintf(argc, argv)
prec = 10 * prec + (*p - '0');
}
if (p >= end) {
- Fail("malformed format string - %%.[0-9]");
+ ArgError("malformed format string - %%.[0-9]");
}
if (prec > 0)
flags |= FPREC;
goto retry;
+ case '\n':
+ p--;
+ case '\0':
case '%':
PUSH("%", 1);
break;
@@ -220,33 +223,61 @@ f_sprintf(argc, argv)
case 'x':
{
VALUE val = GETARG();
- char fbuf[32], *s, *t, *end;
- int v, base;
+ char fbuf[32], nbuf[64], *s, *t, *end;
+ int v, base, bignum = 0;
bin_retry:
switch (TYPE(val)) {
case T_FIXNUM:
v = FIX2INT(val);
- val = int2big(v);
break;
case T_FLOAT:
- v = RFLOAT(val)->value;
- val = int2big(v);
+ val = dbl2big(RFLOAT(val)->value);
+ bignum = 1;
break;
case T_STRING:
val = str2inum(RSTRING(val)->ptr, 0);
goto bin_retry;
case T_BIGNUM:
- val = big_clone(val);
+ bignum = 1;
break;
default:
- WrongType(val, T_FIXNUM);
+ Check_Type(val, T_FIXNUM);
break;
}
+
+ if (!bignum) {
+ if (*p == 'b' || *p == 'B') {
+ val = int2big(v);
+ }
+ else {
+ int len;
+
+ fmt_setup(fbuf, *p, flags, width, prec);
+ sprintf(nbuf, fbuf, v);
+ len = strlen(nbuf);
+
+ if (flags&FPREC) {
+ CHECK(prec);
+ }
+ else if ((flags&FWIDTH) && width > len) {
+ CHECK(width);
+ }
+ else {
+ CHECK(len);
+ }
+ memcpy(&buf[blen], nbuf, len);
+ blen += len;
+ break;
+ }
+ }
if (*p == 'x') base = 16;
else if (*p == 'o') base = 8;
else if (*p == 'b' || *p == 'B') base = 2;
- if (*p != 'B' && !RBIGNUM(val)->sign) big_2comp(val);
+ if (*p != 'B' && !RBIGNUM(val)->sign) {
+ val = big_clone(val);
+ big_2comp(val);
+ }
val = big2str(val, base);
fmt_setup(fbuf, 's', flags, width, prec);
@@ -285,6 +316,11 @@ f_sprintf(argc, argv)
while (t<end) *s++ = *t++;
*s = '\0';
}
+ else if (flags & FZERO) {
+ while (*s == ' ') {
+ *s++ = '0';
+ }
+ }
s = RSTRING(val)->ptr;
if (flags&FPREC) {
CHECK(prec);
@@ -387,7 +423,7 @@ f_sprintf(argc, argv)
fval = atof(RSTRING(val)->ptr);
break;
default:
- WrongType(val, T_FLOAT);
+ Check_Type(val, T_FLOAT);
break;
}
@@ -404,7 +440,7 @@ f_sprintf(argc, argv)
sprint_exit:
if (verbose && argc > 1) {
- Fail("too many argument for format string");
+ ArgError("too many argument for format string");
}
result = str_new(buf, blen);
free(buf);
diff --git a/st.c b/st.c
index d825a7d3c9..3efba70e22 100644
--- a/st.c
+++ b/st.c
@@ -1,21 +1,13 @@
/* This is a general purpose hash table package written by Peter Moore @ UCB. */
static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible";
-#ifndef lint
-static char *rcsid = "$Header: /usr/ext/cvsroot/ruby/st.c,v 1.3 1994/12/09 01:28:33 matz Exp $";
-#endif
#include "config.h"
#include <stdio.h>
#include "st.h"
-extern void *xmalloc();
-static void rehash();
-
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#define nil(type) ((type *) 0)
-#define alloc(type) (type *)xmalloc((unsigned)sizeof(type))
-#define Calloc(n,s) (char *)xcalloc((n),(s))
+#define ST_DEFAULT_MAX_DENSITY 5
+#define ST_DEFAULT_INIT_TABLE_SIZE 11
/*
* DEFAULT_MAX_DENSITY is the default for the largest we allow the
@@ -26,47 +18,98 @@ static void rehash();
* allocated initially
*
*/
+static int numcmp();
+static int numhash();
+struct st_hash_type type_numhash = {
+ numcmp,
+ numhash,
+};
+
+extern int strcmp();
+static int strhash();
+struct st_hash_type type_strhash = {
+ strcmp,
+ strhash,
+};
+
+#include "sig.h"
+
+extern void *xmalloc();
+static void rehash();
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define nil(type) ((type*)0)
+#define alloc(type) (type*)xmalloc((unsigned)sizeof(type))
+#define Calloc(n,s) (char*)xcalloc((n),(s))
+
+static int
+call_cmp_func(table, x, y)
+ st_table *table;
+ char *x, *y;
+{
+ int cmp;
+
+ DEFER_INTS;
+ cmp = (*table->type->compare)(x, y);
+ ALLOW_INTS;
+ return cmp;
+}
+
+#define EQUAL(table, x, y) (call_cmp_func((table),(x), (y)) == 0)
-#define EQUAL(func, x, y) \
- ((func == ST_NUMCMP) ? ((x) == (y)) : ((*func)((x), (y)) == 0))
+static int
+call_hash_func(key, table)
+ char *key;
+ st_table *table;
+{
+ int hash;
-/*#define do_hash(key, table) (*table->hash)(key, table->num_bins)*/
+ DEFER_INTS;
+ hash = (*table->type->hash)((key), table->num_bins);
+ ALLOW_INTS;
+ return hash;
+}
-#define do_hash(key, table)\
- ((table->hash == ST_PTRHASH) ? (((int) (key) >> 2) % table->num_bins) :\
- (table->hash == ST_NUMHASH) ? ((int) (key) % table->num_bins) :\
- (*table->hash)((key), table->num_bins))
+#define do_hash(key, table) call_hash_func((key), table)
st_table*
-st_init_table_with_params(compare, hash, size, density, reorder_flag)
- int (*compare)();
- int (*hash)();
+st_init_table_with_size(type, size)
+ struct st_hash_type *type;
int size;
- int density;
- int reorder_flag;
{
st_table *tbl;
+ if (size == 0) size = ST_DEFAULT_INIT_TABLE_SIZE;
+ else size /= ST_DEFAULT_MAX_DENSITY*0.87;
+
+ if (size < ST_DEFAULT_INIT_TABLE_SIZE)
+ size = ST_DEFAULT_INIT_TABLE_SIZE;
+
tbl = alloc(st_table);
- tbl->compare = compare;
- tbl->hash = hash;
+ tbl->type = type;
tbl->num_entries = 0;
- tbl->max_density = density;
- tbl->reorder_flag = reorder_flag;
tbl->num_bins = size;
- tbl->bins =
- (st_table_entry **) Calloc((unsigned)size, sizeof(st_table_entry *));
+ tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
return tbl;
}
st_table*
-st_init_table(compare, hash)
- int (*compare)();
- int (*hash)();
+st_init_table(type)
+ struct st_hash_type *type;
+{
+ return st_init_table_with_size(type, 0);
+}
+
+st_table*
+st_init_numtable()
{
- return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE,
- ST_DEFAULT_MAX_DENSITY,
- ST_DEFAULT_REORDER_FLAG);
+ return st_init_table(&type_numhash);
+}
+
+st_table*
+st_init_strtable()
+{
+ return st_init_table(&type_strhash);
}
int
@@ -80,32 +123,24 @@ st_free_table(table)
ptr = table->bins[i];
while (ptr != nil(st_table_entry)) {
next = ptr->next;
- free((char *) ptr);
+ free((char*)ptr);
ptr = next;
}
}
- free((char *) table->bins);
- free((char *) table);
+ free((char*)table->bins);
+ free((char*)table);
}
-#define PTR_NOT_EQUAL(table, ptr, key)\
-(ptr != nil(st_table_entry) && !EQUAL(table->compare, key, (ptr)->key))
+#define PTR_NOT_EQUAL(table, ptr, key) \
+(ptr != nil(st_table_entry) && !EQUAL(table, key, (ptr)->key))
-#define FIND_ENTRY(table, ptr, hash_val)\
+#define FIND_ENTRY(table, ptr, hash_val) \
ptr = (table)->bins[hash_val];\
if (PTR_NOT_EQUAL(table, ptr, key)) {\
while (PTR_NOT_EQUAL(table, ptr->next, key)) {\
ptr = ptr->next;\
}\
- if (ptr->next != nil(st_table_entry) && (table)->reorder_flag) {\
- st_table_entry *_tmp = (ptr)->next;\
- (ptr)->next = (ptr)->next->next;\
- _tmp->next = (table)->bins[hash_val];\
- (table)->bins[hash_val] = _tmp;\
- ptr = _tmp;\
- } else {\
- ptr = ptr->next;\
- }\
+ ptr = ptr->next;\
}
int
@@ -124,16 +159,16 @@ st_lookup(table, key, value)
if (ptr == nil(st_table_entry)) {
return 0;
} else {
- if (value != nil(char *)) *value = ptr->record;
+ if (value != nil(char*)) *value = ptr->record;
return 1;
}
}
#define ADD_DIRECT(table, key, value, hash_val, tbl)\
{\
- if (table->num_entries/table->num_bins > table->max_density) {\
+ if (table->num_entries/table->num_bins > ST_DEFAULT_MAX_DENSITY) {\
rehash(table);\
- hash_val = do_hash(key,table);\
+ hash_val = do_hash(key, table);\
}\
\
tbl = alloc(st_table_entry);\
@@ -195,11 +230,11 @@ st_find_or_add(table, key, slot)
FIND_ENTRY(table, ptr, hash_val);
if (ptr == nil(st_table_entry)) {
- ADD_DIRECT(table, key, (char *)0, hash_val, tbl)
- if (slot != nil(char **)) *slot = &tbl->record;
+ ADD_DIRECT(table, key, (char*)0, hash_val, tbl)
+ if (slot != nil(char**)) *slot = &tbl->record;
return 0;
} else {
- if (slot != nil(char **)) *slot = &ptr->record;
+ if (slot != nil(char**)) *slot = &ptr->record;
return 1;
}
}
@@ -211,16 +246,15 @@ rehash(table)
register st_table_entry *ptr, *next, **old_bins = table->bins;
int i, old_num_bins = table->num_bins, hash_val;
- table->num_bins = 2*old_num_bins;
+ table->num_bins = 1.79*old_num_bins;
if (table->num_bins%2 == 0) {
table->num_bins += 1;
}
table->num_entries = 0;
- table->bins =
- (st_table_entry **) Calloc((unsigned) table->num_bins,
- sizeof(st_table_entry *));
+ table->bins = (st_table_entry **)
+ Calloc((unsigned)table->num_bins, sizeof(st_table_entry*));
for(i = 0; i < old_num_bins ; i++) {
ptr = old_bins[i];
@@ -233,7 +267,7 @@ rehash(table)
ptr = next;
}
}
- free((char *) old_bins);
+ free((char*)old_bins);
}
st_table*
@@ -250,12 +284,11 @@ st_copy(old_table)
}
*new_table = *old_table;
- new_table->bins =
- (st_table_entry **) Calloc((unsigned) num_bins,
- sizeof(st_table_entry *));
+ new_table->bins = (st_table_entry**)
+ Calloc((unsigned)num_bins, sizeof(st_table_entry*));
- if (new_table->bins == nil(st_table_entry *)) {
- free((char *) new_table);
+ if (new_table->bins == nil(st_table_entry*)) {
+ free((char*)new_table);
return nil(st_table);
}
@@ -265,8 +298,8 @@ st_copy(old_table)
while (ptr != nil(st_table_entry)) {
tbl = alloc(st_table_entry);
if (tbl == nil(st_table_entry)) {
- free((char *) new_table->bins);
- free((char *) new_table);
+ free((char*)new_table->bins);
+ free((char*)new_table);
return nil(st_table);
}
*tbl = *ptr;
@@ -293,27 +326,27 @@ st_delete(table, key, value)
ptr = table->bins[hash_val];
if (ptr == nil(st_table_entry)) {
- if (value != nil(char *)) *value = nil(char);
+ if (value != nil(char*)) *value = nil(char);
return 0;
}
- if (EQUAL(table->compare, *key, ptr->key)) {
+ if (EQUAL(table, *key, ptr->key)) {
table->bins[hash_val] = ptr->next;
table->num_entries--;
- if (value != nil(char *)) *value = ptr->record;
+ if (value != nil(char*)) *value = ptr->record;
*key = ptr->key;
- free((char *) ptr);
+ free((char*)ptr);
return 1;
}
for(; ptr->next != nil(st_table_entry); ptr = ptr->next) {
- if (EQUAL(table->compare, ptr->next->key, *key)) {
+ if (EQUAL(table, ptr->next->key, *key)) {
tmp = ptr->next;
ptr->next = ptr->next->next;
table->num_entries--;
- if (value != nil(char *)) *value = tmp->record;
+ if (value != nil(char*)) *value = tmp->record;
*key = tmp->key;
- free((char *) tmp);
+ free((char*)tmp);
return 1;
}
}
@@ -350,15 +383,15 @@ st_foreach(table, func, arg)
last->next = ptr->next;
}
ptr = ptr->next;
- free((char *) tmp);
+ free((char*)tmp);
table->num_entries--;
}
}
}
}
-int
-st_strhash(string, modulus)
+static int
+strhash(string, modulus)
register char *string;
int modulus;
{
@@ -371,3 +404,18 @@ st_strhash(string, modulus)
return ((val < 0) ? -val : val)%modulus;
}
+
+static int
+numcmp(x, y)
+ int x, y;
+{
+ return x != y;
+}
+
+static int
+numhash(n, modulus)
+ int n;
+ int modulus;
+{
+ return n % modulus;
+}
diff --git a/st.h b/st.h
index 0caa85b1ad..9b25c944f7 100644
--- a/st.h
+++ b/st.h
@@ -16,13 +16,15 @@ struct st_table_entry {
typedef struct st_table st_table;
-struct st_table {
+struct st_hash_type {
int (*compare)();
int (*hash)();
+};
+
+struct st_table {
+ struct st_hash_type *type;
int num_bins;
int num_entries;
- int max_density;
- int reorder_flag;
st_table_entry **bins;
};
@@ -30,25 +32,19 @@ struct st_table {
enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
+st_table *st_init_table();
+st_table *st_init_table_with_size();
+st_table *st_init_numtable();
+st_table *st_init_strtable();
int st_delete(), st_insert(), st_foreach(), st_free_table();
int st_lookup(), st_find_or_add(), st_add_direct();
-st_table *st_init_table(), *st_init_table_with_params();
st_table *st_copy();
#define ST_NUMCMP ((int (*)()) 0)
#define ST_NUMHASH ((int (*)()) -2)
-#define ST_PTRCMP ((int (*)()) 0)
-#define ST_PTRHASH ((int (*)()) -1)
-
#define st_numcmp ST_NUMCMP
#define st_numhash ST_NUMHASH
-#define st_ptrcmp ST_PTRCMP
-#define st_ptrhash ST_PTRHASH
-
-#define ST_DEFAULT_MAX_DENSITY 5
-#define ST_DEFAULT_INIT_TABLE_SIZE 11
-#define ST_DEFAULT_REORDER_FLAG 0
int st_strhash();
diff --git a/string.c b/string.c
index 15c24738b8..73a57726fb 100644
--- a/string.c
+++ b/string.c
@@ -6,15 +6,15 @@
$Date: 1995/01/10 10:43:01 $
created at: Mon Aug 9 17:12:58 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "re.h"
-#define BEG(no) regs.beg[no]
-#define END(no) regs.end[no]
+#define BEG(no) regs->beg[no]
+#define END(no) regs->end[no]
#include <stdio.h>
#include <ctype.h>
@@ -32,7 +32,7 @@ str_new(ptr, len)
OBJSETUP(str, cString, T_STRING);
str->len = len;
- str->orig = Qnil;
+ str->orig = 0;
str->ptr = ALLOC_N(char,len+1);
if (ptr) {
memcpy(str->ptr, ptr, len);
@@ -117,7 +117,7 @@ str_s_new(class, str)
memcpy(str2->ptr, str->ptr, str->len);
}
str2->ptr[str->len] = '\0';
- str2->orig = Qnil;
+ str2->orig = 0;
return (VALUE)str2;
}
@@ -172,11 +172,11 @@ str_substr(str, start, len)
if (start < 0) {
start = str->len + start;
}
- if (str->len <= start) {
- Fail("index %d out of range [0..%d]", start, str->len-1);
+ if (str->len <= start || len < 0) {
+ return str_new(0,0);
}
- if (len < 0) {
- Fail("Negative length %d", len);
+ if (str->len < start + len) {
+ len = str->len - start;
}
str2 = (struct RString*)str_new(str->ptr+start, len);
@@ -191,21 +191,25 @@ str_subseq(str, beg, end)
{
int len;
+ if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
+ IndexError("end smaller than beg [%d..%d]", beg, end);
+ }
+
if (beg < 0) {
beg = str->len + beg;
if (beg < 0) beg = 0;
}
if (end < 0) {
end = str->len + end;
- if (end < 0) end = 0;
+ if (end < 0) end = -1;
+ else if (str->len < end) {
+ end = str->len;
+ }
}
if (beg >= str->len) {
return str_new(0, 0);
}
- if (str->len < end) {
- end = str->len;
- }
len = end - beg + 1;
if (len < 0) {
@@ -223,16 +227,21 @@ void
str_modify(str)
struct RString *str;
{
- if (FL_TEST(str, STR_FREEZE)) Fail("can't modify frozen string");
- if (str->orig == Qnil) return;
+ char *ptr;
+
+ if (FL_TEST(str, STR_FREEZE))
+ TypeError("can't modify frozen string");
+ if (!str->orig) return;
+ ptr = str->ptr;
str->ptr = ALLOC_N(char, str->len+1);
if (str->ptr) {
- memcpy(str->ptr, str->orig->ptr, str->len+1);
+ memcpy(str->ptr, ptr, str->len);
+ str->ptr[str->len] = 0;
}
- str->orig = Qnil;
+ str->orig = 0;
}
-static VALUE
+VALUE
str_freeze(str)
VALUE str;
{
@@ -259,13 +268,16 @@ str_dup_freezed(str)
}
VALUE
-str_grow(str, len)
+str_resize(str, len)
struct RString *str;
UINT len;
{
str_modify(str);
- if (len > 0) {
- REALLOC_N(str->ptr, char, len + 1);
+
+ if (len >= 0) {
+ if (str->len < len || str->len - len > 1024) {
+ REALLOC_N(str->ptr, char, len + 1);
+ }
str->len = len;
str->ptr[len] = '\0'; /* sentinel */
}
@@ -299,7 +311,7 @@ str_concat(str1, str2)
return (VALUE)str1;
}
-static int
+int
str_hash(str)
struct RString *str;
{
@@ -396,7 +408,7 @@ str_match(x, y)
return INT2FIX(start);
default:
- Fail("type mismatch");
+ TypeError("type mismatch");
break;
}
}
@@ -405,19 +417,7 @@ static VALUE
str_match2(str)
struct RString *str;
{
- extern VALUE rb_lastline;
- VALUE reg;
- int start;
-
- if (TYPE(rb_lastline) != T_STRING)
- Fail("$_ is not a string");
-
- reg = reg_regcomp(str);
- start = reg_search(reg, rb_lastline, 0, 0);
- if (start == -1) {
- return Qnil;
- }
- return INT2FIX(start);
+ return reg_match2(reg_regcomp(str));
}
static int
@@ -469,10 +469,10 @@ str_index_method(argc, argv, str)
break;
default:
- Fail("Type mismatch: %s given", rb_class2name(CLASS_OF(sub)));
+ TypeError("Type mismatch: %s given", rb_class2name(CLASS_OF(sub)));
}
- if (pos == -1) return Qnil;
+ if (pos == -1) return FALSE;
return INT2FIX(pos);
}
@@ -510,7 +510,7 @@ str_rindex(argc, argv, str)
}
static char
-str_next(s)
+succ_char(s)
char *s;
{
char c = *s;
@@ -535,7 +535,7 @@ str_next(s)
}
static VALUE
-str_next_method(orig)
+str_succ(orig)
struct RString *orig;
{
struct RString *str, *str2;
@@ -547,14 +547,19 @@ str_next_method(orig)
sbeg = str->ptr; s = sbeg + str->len - 1;
while (sbeg <= s) {
- if (isalnum(*s) && (c = str_next(s)) == Qnil) break;
+ if (isalnum(*s) && (c = succ_char(s)) == 0) break;
s--;
}
- if (s < sbeg && c != -1) {
- str2 = (struct RString*)str_new(0, str->len+1);
- str2->ptr[0] = c;
- memcpy(str2->ptr+1, str->ptr, str->len);
- str = str2;
+ if (s < sbeg) {
+ if (c == -1 && str->len > 0) {
+ str->ptr[str->len-1] += 1;
+ }
+ else {
+ str2 = (struct RString*)str_new(0, str->len+1);
+ str2->ptr[0] = c;
+ memcpy(str2->ptr+1, str->ptr, str->len);
+ str = str2;
+ }
}
return (VALUE)str;
@@ -566,11 +571,15 @@ str_upto(beg, end)
{
VALUE current;
+ Check_Type(end, T_STRING);
+ if (RTEST(rb_funcall(beg, '>', 1, end)))
+ return Qnil;
+
current = beg;
for (;;) {
rb_yield(current);
if (str_equal(current, end)) break;
- current = str_next_method(current);
+ current = str_succ(current);
if (RSTRING(current)->len > RSTRING(end)->len)
break;
}
@@ -587,13 +596,13 @@ str_aref(str, indx)
switch (TYPE(indx)) {
case T_FIXNUM:
- idx = FIX2UINT(indx);
+ idx = FIX2INT(indx);
if (idx < 0) {
idx = str->len + idx;
}
if (idx < 0 || str->len <= idx) {
- Fail("index %d out of range [0..%d]", idx, str->len-1);
+ return Qnil;
}
return (VALUE)INT2FIX(str->ptr[idx] & 0xff);
@@ -614,7 +623,7 @@ str_aref(str, indx)
return str_subseq(str, beg, end);
}
}
- Fail("Invalid index for string");
+ IndexError("Invalid index for string");
}
}
@@ -650,6 +659,7 @@ str_replace(str, beg, len, val)
str->ptr[str->len] = '\0';
}
+/* str_replace2() understands negatice offset */
static void
str_replace2(str, beg, end, val)
struct RString *str, *val;
@@ -657,35 +667,46 @@ str_replace2(str, beg, end, val)
{
int len;
+ if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
+ IndexError("end smaller than beg [%d..%d]", beg, end);
+ }
+
if (beg < 0) {
beg = str->len + beg;
+ if (beg < 0) {
+ beg = 0;
+ }
}
if (str->len <= beg) {
- Fail("start %d too big", beg);
+ beg = str->len;
}
if (end < 0) {
end = str->len + end;
+ if (end < 0) {
+ end = 0;
+ }
}
- if (end < 0 || str->len <= end) {
- Fail("end %d too big", end);
+ if (str->len <= end) {
+ end = str->len - 1;
}
len = end - beg + 1; /* length of substring */
if (len < 0) {
- Fail("end %d too small", end);
+ len = 0;
}
str_replace(str, beg, len, val);
}
static VALUE
-str_sub(str, pat, val, once)
+str_sub_s(str, pat, val, once)
struct RString *str;
struct RRegexp *pat;
VALUE val;
int once;
{
+ VALUE result, repl;
int beg, offset, n;
- struct re_registers regs;
+ struct re_registers *regs;
val = obj_as_string(val);
str_modify(str);
@@ -703,15 +724,126 @@ str_sub(str, pat, val, once)
Check_Type(pat, T_REGEXP);
}
- regs.allocated = 0;
- for (offset=0, n=0;
- (beg=reg_search(pat, str, offset, &regs)) >= 0;
- offset=END(0)+1) {
- str_replace2(str, beg, END(0)-1, reg_regsub(val, str, &regs));
+ result = str_new(0,0);
+ offset=0; n=0;
+ while ((beg=reg_search(pat, str, offset, 0)) >= 0) {
+ n++;
+
+ regs = RMATCH(backref_get())->regs;
+ str_cat(result, str->ptr+offset, beg-offset);
+
+ repl = reg_regsub(val, str, regs);
+ str_cat(result, RSTRING(repl)->ptr, RSTRING(repl)->len);
+ if (END(0) == offset) {
+ /*
+ * Always consume at least one character of the input string
+ * in order to prevent infinite loops.
+ */
+ str_cat(result, str->ptr+END(0), 1);
+ offset = END(0)+1;
+ }
+ else {
+ offset = END(0);
+ }
+
+ if (once) break;
+ if (offset >= STRLEN(str)) break;
+ }
+ if (n == 0) return Qnil;
+ str_cat(result, str->ptr+offset, str->len-offset);
+
+ return result;
+}
+
+static VALUE
+str_sub_f(str, pat, val, once)
+ struct RString *str;
+ VALUE pat;
+ VALUE val;
+ int once;
+{
+ VALUE result = str_sub_s(str, pat, val, once);
+
+ if (NIL_P(result)) return Qnil;
+ str_resize(str, RSTRING(result)->len);
+ memcpy(str->ptr, RSTRING(result)->ptr, RSTRING(result)->len);
+
+ return (VALUE)str;
+}
+
+static VALUE
+str_sub_iter_s(str, pat, once)
+ struct RString *str;
+ VALUE pat;
+ int once;
+{
+ VALUE val, result;
+ int beg, offset, n, null;
+ struct re_registers *regs;
+
+ if (!iterator_p()) {
+ ArgError("Wrong # of arguments(1 for 2)");
+ }
+
+ str_modify(str);
+ switch (TYPE(pat)) {
+ case T_REGEXP:
+ break;
+
+ case T_STRING:
+ pat = reg_regcomp(pat);
+ break;
+
+ default:
+ /* type failed */
+ Check_Type(pat, T_REGEXP);
+ }
+
+ result = str_new(0,0);
+ n = 0; offset = 0;
+ while ((beg=reg_search(pat, str, offset, 0)) >= 0) {
n++;
+
+ null = 0;
+ regs = RMATCH(backref_get())->regs;
+ str_cat(result, str->ptr+offset, beg-offset);
+
+ if (END(0) == offset) {
+ null = 1;
+ offset = END(0)+1;
+ }
+ else {
+ offset = END(0);
+ }
+
+ val = rb_yield(reg_nth_match(0, backref_get()));
+ val = obj_as_string(val);
+ str_cat(result, RSTRING(val)->ptr, RSTRING(val)->len);
+ if (null) {
+ str_cat(result, str->ptr+offset-1, 1);
+ }
+
if (once) break;
+ if (offset >= STRLEN(str)) break;
}
if (n == 0) return Qnil;
+ str_cat(result, str->ptr+offset, str->len-offset);
+
+ return result;
+}
+
+static VALUE
+str_sub_iter_f(str, pat, once)
+ struct RString *str;
+ VALUE pat;
+ int once;
+{
+ VALUE result = str_sub_iter_s(str, pat, once);
+
+ if (NIL_P(result)) return Qnil;
+ str_resize(str, RSTRING(result)->len);
+ memcpy(str->ptr, RSTRING(result)->ptr, RSTRING(result)->len);
+
return (VALUE)str;
}
@@ -729,13 +861,13 @@ str_aset(str, indx, val)
idx = str->len + idx;
}
if (idx < 0 || str->len <= idx) {
- Fail("index %d out of range [0..%d]", idx, str->len-1);
+ IndexError("index %d out of range [0..%d]", idx, str->len-1);
}
- str->ptr[idx] = FIX2UINT(val) & 0xff;
+ str->ptr[idx] = FIX2INT(val) & 0xff;
return val;
case T_REGEXP:
- str_sub(str, indx, val, 0);
+ str_sub_f(str, indx, val, 0);
return val;
case T_STRING:
@@ -745,7 +877,7 @@ str_aset(str, indx, val)
end = beg + STRLEN(indx) - 1;
str_replace2(str, beg, end, val);
}
- if (offset == 0) Fail("Not a substring");
+ if (offset == 0) return Qnil;
return val;
default:
@@ -757,7 +889,7 @@ str_aset(str, indx, val)
return val;
}
}
- Fail("Invalid index for string");
+ IndexError("Invalid index for string");
}
}
@@ -779,10 +911,10 @@ str_aset_method(argc, argv, str)
beg = NUM2INT(arg1);
if (beg < 0) {
beg = str->len + beg;
- if (beg < 0) Fail("start %d too small", beg);
+ if (beg < 0) beg = 0;
}
len = NUM2INT(arg2);
- if (len < 0) Fail("length %d too small", len);
+ if (len < 0) IndexError("negative length %d", len);
if (beg + len > str->len) {
len = str->len - beg;
}
@@ -793,46 +925,6 @@ str_aset_method(argc, argv, str)
}
static VALUE
-str_sub_iter(str, pat, once)
- VALUE str, pat;
- int once;
-{
- VALUE val;
- int beg, offset;
- struct re_registers regs;
-
- if (!iterator_p()) {
- Fail("Wrong # of arguments(1 for 2)");
- }
-
- str_modify(str);
- switch (TYPE(pat)) {
- case T_REGEXP:
- break;
-
- case T_STRING:
- pat = reg_regcomp(pat);
- break;
-
- default:
- /* type failed */
- Check_Type(pat, T_REGEXP);
- }
-
- offset=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
str_sub_bang(argc, argv, str)
int argc;
VALUE *argv;
@@ -841,18 +933,27 @@ str_sub_bang(argc, argv, str)
VALUE pat, val;
if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- return str_sub_iter(str, pat, 1);
+ return str_sub_iter_f(str, pat, 1);
}
- return str_sub(str, pat, val, 1);
+ return str_sub_f(str, pat, val, 1);
}
static VALUE
-str_sub_method(argc, argv, str)
+str_sub(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
- return str_sub_bang(argc, argv, str_dup(str));
+ VALUE pat, val, v;
+
+ if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
+ v = str_sub_iter_s(str, pat, 1);
+ }
+ else {
+ v = str_sub_s(str, pat, val, 1);
+ }
+ if (NIL_P(v)) return str;
+ return v;
}
static VALUE
@@ -864,9 +965,9 @@ str_gsub_bang(argc, argv, str)
VALUE pat, val;
if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- return str_sub_iter(str, pat, 0);
+ return str_sub_iter_f(str, pat, 0);
}
- return str_sub(str, pat, val, 0);
+ return str_sub_f(str, pat, val, 0);
}
static VALUE
@@ -875,25 +976,31 @@ str_gsub(argc, argv, str)
VALUE *argv;
VALUE str;
{
- VALUE v = str_gsub_bang(argc, argv, str_dup(str));
- if (v) return v;
- return str;
-}
+ VALUE pat, val, v;
-extern VALUE rb_lastline;
+ if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
+ v = str_sub_iter_s(str, pat, 0);
+ }
+ else {
+ v = str_sub_s(str, pat, val, 0);
+ }
+ if (NIL_P(v)) return str;
+ return v;
+}
static VALUE
f_sub_bang(argc, argv)
int argc;
VALUE *argv;
{
- VALUE pat, val;
+ VALUE pat, val, line;
- Check_Type(rb_lastline, T_STRING);
+ line = lastline_get();
+ Check_Type(line, T_STRING);
if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- return str_sub_iter(rb_lastline, pat, 1);
+ return str_sub_iter_f(line, pat, 1);
}
- return str_sub(rb_lastline, pat, val, 1);
+ return str_sub_f(line, pat, val, 1);
}
static VALUE
@@ -901,15 +1008,21 @@ f_sub(argc, argv)
int argc;
VALUE *argv;
{
- VALUE v;
+ VALUE pat, val, line, v;
- Check_Type(rb_lastline, T_STRING);
- v = f_sub_bang(argc, argv, str_dup(rb_lastline));
- if (v) {
- rb_lastline = v;
+ line = lastline_get();
+ Check_Type(line, T_STRING);
+ if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
+ v = str_sub_iter_s(line, pat, 1);
+ }
+ else {
+ v = str_sub_s(line, pat, val, 1);
+ }
+ if (!NIL_P(v)) {
+ lastline_set(v);
return v;
}
- return rb_lastline;
+ return line;
}
static VALUE
@@ -917,13 +1030,14 @@ f_gsub_bang(argc, argv)
int argc;
VALUE *argv;
{
- VALUE pat, val;
+ VALUE pat, val, line;
- Check_Type(rb_lastline, T_STRING);
+ line = lastline_get();
+ Check_Type(line, T_STRING);
if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
- return str_sub_iter(rb_lastline, pat, 0);
+ return str_sub_iter_f(line, pat, 0);
}
- return str_sub(rb_lastline, pat, val, 0);
+ return str_sub_f(line, pat, val, 0);
}
static VALUE
@@ -931,15 +1045,21 @@ f_gsub(argc, argv)
int argc;
VALUE *argv;
{
- VALUE v;
+ VALUE pat, val, line, v;
- Check_Type(rb_lastline, T_STRING);
- v = f_gsub_bang(argc, argv, str_dup(rb_lastline));
- if (v) {
- rb_lastline = v;
+ line = lastline_get();
+ Check_Type(line, T_STRING);
+ if (rb_scan_args(argc, argv, "11", &pat, &val) == 1) {
+ v = str_sub_iter_s(line, pat, 0);
+ }
+ else {
+ v = str_sub_s(line, pat, val, 0);
+ }
+ if (!NIL_P(v)) {
+ lastline_set(v);
return v;
}
- return rb_lastline;
+ return line;
}
static VALUE
@@ -1005,23 +1125,27 @@ static VALUE
str_inspect(str)
struct RString *str;
{
- struct RString *str0;
+#define STRMAX 80
+ char buf[STRMAX];
char *p, *pend;
char *b;
int offset;
- 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;
+ *b++ = '"';
+
+#define CHECK(n) {\
+ if (b - buf + n > STRMAX - 4) {\
+ strcpy(b, "...");\
+ b += 3;\
+ break;\
+ }\
+}
+
while (p < pend) {
- char c = *p++;
- if (ismbchar(c) && p+1 < pend) {
+ unsigned char c = *p++;
+ if (ismbchar(c) && p < pend) {
CHECK(2);
*b++ = c;
*b++ = *p++;
@@ -1082,8 +1206,8 @@ str_inspect(str)
b += 3;
}
}
- str_cat(str0, "\"", 1);
- return (VALUE)str0;
+ *b++ = '"';
+ return str_new(buf, b - buf);
}
static VALUE
@@ -1227,14 +1351,17 @@ trnext(t)
}
}
+static VALUE str_delete_bang();
+
static VALUE
-str_tr_bang(str, src, repl)
+tr_trans(str, src, repl, sflag)
struct RString *str, *src, *repl;
+ int sflag;
{
struct tr trsrc, trrepl;
int cflag = 0;
char trans[256];
- int i, c;
+ int i, c, c0;
char *s, *send, *t;
Check_Type(src, T_STRING);
@@ -1244,6 +1371,7 @@ str_tr_bang(str, src, repl)
trsrc.p++;
}
Check_Type(repl, T_STRING);
+ if (repl->len == 0) return str_delete_bang(str, src);
trrepl.p = repl->ptr; trrepl.pend = trrepl.p + repl->len;
trsrc.gen = trrepl.gen = 0;
trsrc.now = trrepl.now = 0;
@@ -1286,21 +1414,40 @@ str_tr_bang(str, src, repl)
str_modify(str);
t = s = str->ptr; send = s + str->len;
- while (s < send) {
- c = *s++ & 0xff;
- c = trans[c] & 0xff;
- *t++ = c;
+ c0 = -1;
+ if (sflag) {
+ while (s < send) {
+ c = trans[*s++ & 0xff] & 0xff;
+ if (s[-1] == c || c != c0) {
+ c0 = (s[-1] == c)?-1:c;
+ *t++ = c;
+ }
+ }
+ }
+ else {
+ while (s < send) {
+ c = trans[*s++ & 0xff] & 0xff;
+ *t++ = c;
+ }
}
*t = '\0';
+ if (sflag) str->len = (t - str->ptr);
return (VALUE)str;
}
static VALUE
+str_tr_bang(str, src, repl)
+ VALUE str, src, repl;
+{
+ return tr_trans(str, src, repl, 0);
+}
+
+static VALUE
str_tr(str, src, repl)
- struct RString *str, *src, *repl;
+ VALUE str, src, repl;
{
- return str_tr_bang(str_dup(str), src, repl);
+ return tr_trans(str_dup(str), src, repl, 0);
}
static void
@@ -1314,7 +1461,7 @@ tr_setup_table(str, table)
tr.p = str->ptr; tr.pend = tr.p + str->len;
tr.gen = tr.now = tr.max = 0;
- if (str->len > 2 && str->ptr[0] == '^') {
+ if (str->len > 1 && str->ptr[0] == '^') {
cflag++;
tr.p++;
}
@@ -1426,9 +1573,8 @@ str_tr_s_bang(str, src, repl)
{
Check_Type(src, T_STRING);
Check_Type(repl, T_STRING);
- str_tr(str, src, repl);
- tr_squeeze(str, repl);
- return str;
+
+ return tr_trans(str, src, repl, 1);
}
static VALUE
@@ -1452,13 +1598,13 @@ str_split_method(argc, argv, str)
VALUE result, tmp;
rb_scan_args(argc, argv, "02", &spat, &limit);
- if (limit) {
+ if (!NIL_P(limit)) {
lim = NUM2INT(limit);
i = 1;
}
- if (spat == Qnil) {
- if (FS) {
+ if (NIL_P(spat)) {
+ if (!NIL_P(FS)) {
spat = (struct RRegexp*)FS;
goto fs_set;
}
@@ -1478,7 +1624,7 @@ str_split_method(argc, argv, str)
case T_REGEXP:
break;
default:
- Fail("split(): bad separator");
+ ArgError("split(): bad separator");
}
}
@@ -1505,7 +1651,7 @@ str_split_method(argc, argv, str)
else {
if (isspace(*ptr)) {
ary_push(result, str_substr(str, beg, end-beg));
- if (limit && lim <= ++i) break;
+ if (!NIL_P(limit) && lim <= ++i) break;
skip = 1;
beg = end + 1;
}
@@ -1519,7 +1665,7 @@ str_split_method(argc, argv, str)
for (end = beg = 0; ptr<eptr; ptr++) {
if (*ptr == char_sep) {
ary_push(result, str_substr(str, beg, end-beg));
- if (limit && lim <= ++i) break;
+ if (!NIL_P(limit) && lim <= ++i) break;
beg = end + 1;
}
end++;
@@ -1530,18 +1676,18 @@ str_split_method(argc, argv, str)
int start = beg;
int last_null = 0;
int idx;
- struct re_registers regs;
+ struct re_registers *regs;
- regs.allocated = 0;
- while ((end = reg_search(spat, str, start, &regs)) >= 0) {
- if (start == end && regs.beg[0] == regs.end[0]) {
+ while ((end = reg_search(spat, str, start, 0)) >= 0) {
+ regs = RMATCH(backref_get())->regs;
+ if (start == end && BEG(0) == END(0)) {
if (last_null == 1) {
if (ismbchar(str->ptr[beg]))
ary_push(result, str_substr(str, beg, 2));
else
ary_push(result, str_substr(str, beg, 1));
beg = start;
- if (limit && lim <= ++i) break;
+ if (!NIL_P(limit) && lim <= ++i) break;
}
else {
start += ismbchar(str->ptr[start])?2:1;
@@ -1551,23 +1697,20 @@ str_split_method(argc, argv, str)
}
else {
ary_push(result, str_substr(str, beg, end-beg));
- beg = start = regs.end[0];
- if (limit && lim <= ++i) break;
+ beg = start = END(0);
}
last_null = 0;
- for (idx=1; idx < 10; idx++) {
- if (regs.beg[idx] == -1) break;
- if (regs.beg[idx] == regs.end[idx])
+ for (idx=1; idx < regs->num_regs; idx++) {
+ if (BEG(idx) == -1) continue;
+ if (BEG(idx) == END(idx))
tmp = str_new(0, 0);
else
- tmp = str_subseq(str, regs.beg[idx], regs.end[idx]-1);
+ tmp = str_subseq(str, BEG(idx), END(idx)-1);
ary_push(result, tmp);
- if (limit && lim <= ++i) break;
}
-
+ if (!NIL_P(limit) && lim <= ++i) break;
}
- re_free_registers(&regs);
}
if (str->len > beg) {
ary_push(result, str_subseq(str, beg, -1));
@@ -1583,32 +1726,56 @@ str_split(str, sep0)
{
VALUE sep;
+ Check_Type(str, T_STRING);
sep = str_new2(sep0);
return str_split_method(1, &sep, str);
}
static VALUE
-str_each_line(str)
+f_split(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE line;
+
+ line = lastline_get();
+ Check_Type(line, T_STRING);
+ return str_split_method(argc, argv, line);
+}
+
+static VALUE
+str_each_line(argc, argv, str)
+ int argc;
+ VALUE *argv;
struct RString* str;
{
extern VALUE RS;
+ VALUE rs;
int newline;
int rslen;
char *p = str->ptr, *pend = p + str->len, *s;
char *ptr = p;
int len = str->len;
+ VALUE line;
- if (RS == Qnil) {
+ if (rb_scan_args(argc, argv, "01", &rs) == 1) {
+ if (!NIL_P(rs)) Check_Type(rs, T_STRING);
+ }
+ else {
+ rs = RS;
+ }
+
+ if (NIL_P(rs)) {
rb_yield(str);
- return (VALUE)str;
+ return Qnil;
}
- rslen = RSTRING(RS)->len;
+ rslen = RSTRING(rs)->len;
if (rslen == 0) {
newline = '\n';
}
else {
- newline = RSTRING(RS)->ptr[rslen-1];
+ newline = RSTRING(rs)->ptr[rslen-1];
}
for (s = p, p += rslen; p < pend; p++) {
@@ -1619,9 +1786,10 @@ str_each_line(str)
}
if (*p == newline &&
(rslen <= 1 ||
- memcmp(RSTRING(RS)->ptr, p-rslen+1, rslen) == 0)) {
- rb_lastline = str_new(s, p - s + 1);
- rb_yield(rb_lastline);
+ memcmp(RSTRING(rs)->ptr, p-rslen+1, rslen) == 0)) {
+ line = str_new(s, p - s + 1);
+ lastline_set(line);
+ rb_yield(line);
if (str->ptr != ptr || str->len != len)
Fail("string modified");
s = p + 1;
@@ -1629,11 +1797,12 @@ str_each_line(str)
}
if (s != pend) {
- rb_lastline = str_new(s, p - s);
- rb_yield(rb_lastline);
+ line = str_new(s, p - s);
+ lastline_set(line);
+ rb_yield(line);
}
- return (VALUE)str;
+ return Qnil;
}
static VALUE
@@ -1645,7 +1814,7 @@ str_each_byte(str)
for (i=0; i<str->len; i++) {
rb_yield(INT2FIX(str->ptr[i] & 0xff));
}
- return (VALUE)str;
+ return Qnil;
}
static VALUE
@@ -1656,6 +1825,10 @@ str_chop_bang(str)
str->len--;
str->ptr[str->len] = '\0';
+ if (str->len > 1 && str->ptr[str->len-1] == '\r') {
+ str->len--;
+ str->ptr[str->len] = '\0';
+ }
return (VALUE)str;
}
@@ -1668,6 +1841,27 @@ str_chop(str)
}
static VALUE
+f_chop_bang(str)
+ struct RString *str;
+{
+ VALUE line;
+
+ line = lastline_get();
+ Check_Type(line, T_STRING);
+ return str_chop_bang(line);
+}
+
+static VALUE
+f_chop()
+{
+ VALUE line;
+
+ line = lastline_get();
+ Check_Type(line, T_STRING);
+ return str_chop_bang(str_dup(line));
+}
+
+static VALUE
str_strip_bang(str)
struct RString *str;
{
@@ -1702,6 +1896,70 @@ str_strip_bang(str)
}
static VALUE
+scan_once(str, pat, start)
+ struct RString *str;
+ struct RRegexp *pat;
+ int *start;
+{
+ VALUE result;
+ struct re_registers *regs;
+ int idx;
+
+ if (reg_search(pat, str, *start, 0) >= 0) {
+ regs = RMATCH(backref_get())->regs;
+ result = ary_new2(regs->num_regs);
+ for (idx=1; idx < regs->num_regs; idx++) {
+ if (BEG(idx) == -1) {
+ ary_push(result, Qnil);
+ }
+ else if (BEG(idx) == END(idx)) {
+ ary_push(result, str_new(0, 0));
+ }
+ else {
+ ary_push(result, str_subseq(str, BEG(idx), END(idx)-1));
+ }
+ }
+ if (END(0) == *start) {
+ *start = END(0)+1;
+ }
+ else {
+ *start = END(0);
+ }
+
+ return result;
+ }
+ return Qnil;
+}
+
+static VALUE
+str_scan(str, pat)
+ struct RString *str;
+ struct RRegexp *pat;
+{
+ VALUE result;
+ int start = 0;
+
+ switch (TYPE(pat)) {
+ case T_STRING:
+ pat = (struct RRegexp*)reg_regcomp(pat);
+ break;
+ case T_REGEXP:
+ break;
+ default:
+ Check_Type(pat, T_REGEXP);
+ }
+
+ if (!iterator_p()) {
+ return scan_once(str, pat, &start);
+ }
+
+ while (!NIL_P(result = scan_once(str, pat, &start))) {
+ rb_yield(result);
+ }
+ return Qnil;
+}
+
+static VALUE
str_strip(str)
struct RString *str;
{
@@ -1728,7 +1986,7 @@ str_crypt(str, salt)
{
salt = as_str(salt);
if (salt->len < 2)
- Fail("salt too short(need >2 bytes)");
+ ArgError("salt too short(need >2 bytes)");
return str_new2(crypt(str->ptr, salt->ptr));
}
@@ -1737,7 +1995,7 @@ str_intern(str)
struct RString *str;
{
if (strlen(str->ptr) != str->len)
- Fail("string contains `\0'");
+ ArgError("string contains `\0'");
return rb_intern(str->ptr)|FIXNUM_FLAG;
}
@@ -1753,7 +2011,7 @@ str_sum(argc, argv, str)
char *p, *pend;
rb_scan_args(argc, argv, "01", &vbits);
- if (vbits == Qnil) bits = 16;
+ if (NIL_P(vbits)) bits = 16;
else bits = NUM2INT(vbits);
p = str->ptr; pend = p + str->len;
@@ -1862,6 +2120,7 @@ Init_String()
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, "===", 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);
@@ -1871,8 +2130,8 @@ Init_String()
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, "succ", str_succ, 0);
+ rb_define_method(cString, "upto", str_upto, 1);
rb_define_method(cString, "index", str_index_method, -1);
rb_define_method(cString, "rindex", str_rindex, -1);
@@ -1903,11 +2162,13 @@ Init_String()
rb_define_method(cString, "crypt", str_crypt, 1);
rb_define_method(cString, "intern", str_intern, 0);
+ rb_define_method(cString, "scan", str_scan, 1);
+
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, "sub", str_sub, -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);
@@ -1927,9 +2188,9 @@ Init_String()
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_line", str_each_line, -1);
+ rb_define_method(cString, "each", str_each_line, -1);
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);
@@ -1939,5 +2200,10 @@ Init_String()
rb_define_private_method(cKernel, "sub!", f_sub_bang, -1);
rb_define_private_method(cKernel, "gsub!", f_gsub_bang, -1);
+ rb_define_private_method(cKernel, "chop", f_chop, 0);
+ rb_define_private_method(cKernel, "chop!", f_chop_bang, 0);
+
+ rb_define_private_method(cKernel, "split", f_split, -1);
+
pr_str = rb_intern("to_s");
}
diff --git a/struct.c b/struct.c
index 2f4c35f397..bf8a468787 100644
--- a/struct.c
+++ b/struct.c
@@ -15,6 +15,34 @@ VALUE cStruct;
extern VALUE mEnumerable;
static VALUE
+struct_s_members(obj)
+ VALUE obj;
+{
+ struct RArray *member;
+ VALUE ary, *p, *pend;
+
+ member = RARRAY(rb_ivar_get(obj, rb_intern("__member__")));
+ if (NIL_P(member)) {
+ Fatal("non-initialized struct");
+ }
+ ary = ary_new2(member->len);
+ p = member->ptr; pend = p + member->len;
+ while (p < pend) {
+ ary_push(ary, str_new2(rb_id2name(FIX2INT(*p))));
+ p++;
+ }
+
+ return ary;
+}
+
+static VALUE
+struct_members(obj)
+ VALUE obj;
+{
+ return struct_s_members(CLASS_OF(obj));
+}
+
+static VALUE
struct_ref(obj)
struct RStruct *obj;
{
@@ -23,8 +51,8 @@ struct_ref(obj)
nstr = CLASS_OF(obj);
member = rb_ivar_get(nstr, rb_intern("__member__"));
- if (member == Qnil) {
- Fail("non-initialized struct");
+ if (NIL_P(member)) {
+ Fatal("non-initialized struct");
}
slot = INT2FIX(rb_frame_last_func());
for (i=0; i<RARRAY(member)->len; i++) {
@@ -32,8 +60,8 @@ struct_ref(obj)
return obj->ptr[i];
}
}
- Fail("not struct member");
- return Qnil; /* not reached */
+ NameError("not struct member");
+ /* not reached */
}
static VALUE struct_ref0(obj) struct RStruct *obj; {return obj->ptr[0];}
@@ -70,8 +98,8 @@ struct_set(obj, val)
nstr = CLASS_OF(obj);
member = rb_ivar_get(nstr, rb_intern("__member__"));
- if (member == Qnil) {
- Fail("non-initialized struct");
+ if (NIL_P(member)) {
+ Fatal("non-initialized struct");
}
for (i=0; i<RARRAY(member)->len; i++) {
slot = RARRAY(member)->ptr[i];
@@ -79,11 +107,11 @@ struct_set(obj, val)
return obj->ptr[i] = val;
}
}
- Fail("not struct member");
- return Qnil; /* not reached */
+ NameError("not struct member");
+ /* not reached */
}
-static VALUE struct_s_new();
+VALUE struct_alloc();
static VALUE
make_struct(name, member)
@@ -97,7 +125,8 @@ make_struct(name, member)
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);
+ rb_define_singleton_method(nstr, "new", struct_alloc, -2);
+ rb_define_singleton_method(nstr, "members", struct_s_members, 0);
for (i=0; i< member->len; i++) {
ID id = FIX2INT(member->ptr[i]);
if (i<10) {
@@ -149,7 +178,8 @@ struct_s_def(argc, argv)
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);
+ ID id = rb_to_id(rest->ptr[i]);
+ rest->ptr[i] = INT2FIX(id);
}
return make_struct(name, rest);
}
@@ -165,7 +195,7 @@ struct_alloc(class, values)
size = rb_ivar_get(class, rb_intern("__size__"));
n = FIX2INT(size);
if (n < values->len) {
- Fail("struct size differs");
+ ArgError("struct size differs");
}
else {
NEWOBJ(st, struct RStruct);
@@ -173,11 +203,11 @@ struct_alloc(class, values)
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);
+ memclear(st->ptr+values->len, n - values->len);
return (VALUE)st;
}
- return Qnil; /* not reached */
+ /* not reached */
}
VALUE
@@ -186,11 +216,15 @@ struct_new(class, va_alist)
va_dcl
{
VALUE val, mem;
+ int size;
va_list args;
+ val = rb_ivar_get(class, rb_intern("__size__"));
+ size = FIX2INT(val);
mem = ary_new();
va_start(args);
- while (val = va_arg(args, VALUE)) {
+ while (size--) {
+ val = va_arg(args, VALUE);
ary_push(mem, val);
}
va_end(args);
@@ -199,17 +233,6 @@ struct_new(class, va_alist)
}
static VALUE
-struct_s_new(argc, argv, obj)
- int argc;
- VALUE *argv;
-{
- VALUE member, slot;
-
- member = ary_new4(argc, argv);
- return struct_alloc(obj, member);
-}
-
-static VALUE
struct_each(s)
struct RStruct *s;
{
@@ -241,14 +264,13 @@ struct_inspect(s)
struct RStruct *s;
{
char *name = rb_class2name(CLASS_OF(s));
- ID inspect = rb_intern("inspect");
VALUE str, member;
char buf[256];
int i;
member = rb_ivar_get(CLASS_OF(s), rb_intern("__member__"));
- if (member == Qnil) {
- Fail("non-initialized struct");
+ if (NIL_P(member)) {
+ Fatal("non-initialized struct");
}
sprintf(buf, "#<%s%s: ", HDR, name);
@@ -264,7 +286,7 @@ struct_inspect(s)
p = rb_id2name(FIX2INT(slot));
str_cat(str, p, strlen(p));
str_cat(str, "=", 1);
- str2 = rb_funcall(s->ptr[i], inspect, 0, 0);
+ str2 = rb_inspect(s->ptr[i]);
str2 = obj_as_string(str2);
str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
}
@@ -303,9 +325,9 @@ struct_aref(s, idx)
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);
+ IndexError("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);
+ IndexError("offset %d too large for struct(size:%d)", i, s->len);
return s->ptr[i];
}
@@ -319,9 +341,9 @@ struct_aset(s, idx, val)
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);
+ IndexError("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);
+ IndexError("offset %d too large for struct(size:%d)", i, s->len);
return s->ptr[i] = val;
}
@@ -334,7 +356,7 @@ struct_equal(s, s2)
if (TYPE(s2) != T_STRUCT) return FALSE;
if (CLASS_OF(s) != CLASS_OF(s2)) return FALSE;
if (s->len != s2->len) {
- Fail("incomsistent struct");
+ Bug("inconsistent struct"); /* should never happen */
}
for (i=0; i<s->len; i++) {
@@ -364,6 +386,7 @@ Init_Struct()
rb_include_module(cStruct, mEnumerable);
rb_define_singleton_method(cStruct, "new", struct_s_def, -1);
+ rb_define_singleton_method(cStruct, "members", struct_s_members, 0);
rb_define_method(cStruct, "clone", struct_clone, 0);
@@ -378,4 +401,6 @@ Init_Struct()
rb_define_method(cStruct, "each", struct_each, 0);
rb_define_method(cStruct, "[]", struct_aref, 1);
rb_define_method(cStruct, "[]=", struct_aset, 2);
+
+ rb_define_method(cStruct, "members", struct_members, 0);
}
diff --git a/time.c b/time.c
index b8ebe05230..1cfac22160 100644
--- a/time.c
+++ b/time.c
@@ -6,7 +6,7 @@
$Date: 1994/12/06 09:30:28 $
created at: Tue Dec 28 14:31:59 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -43,27 +43,19 @@ struct time_object {
int tm_got;
};
-static ID id_tv;
-
#define GetTimeval(obj, tobj) {\
- if (!id_tv) id_tv = rb_intern("tv");\
- Get_Data_Struct(obj, id_tv, struct time_object, tobj);\
-}
-
-#define MakeTimeval(obj,tobj) {\
- if (!id_tv) id_tv = rb_intern("tv");\
- Make_Data_Struct(obj, id_tv, struct time_object, 0, 0, tobj);\
- tobj->tm_got=0;\
+ Get_Data_Struct(obj, struct time_object, tobj);\
}
static VALUE
time_s_now(class)
VALUE class;
{
- VALUE obj = obj_alloc(class);
+ VALUE obj;
struct time_object *tobj;
- MakeTimeval(obj, tobj);
+ obj = Make_Data_Struct(class, struct time_object, 0, 0, tobj);
+ tobj->tm_got=0;
if (gettimeofday(&(tobj->tv), 0) == -1) {
rb_sys_fail("gettimeofday");
@@ -77,10 +69,11 @@ time_new_internal(class, sec, usec)
VALUE class;
int sec, usec;
{
- VALUE obj = obj_alloc(class);
+ VALUE obj;
struct time_object *tobj;
- MakeTimeval(obj, tobj);
+ obj = Make_Data_Struct(class, struct time_object, 0, 0, tobj);
+ tobj->tm_got=0;
tobj->tv.tv_sec = sec;
tobj->tv.tv_usec = usec;
@@ -94,18 +87,18 @@ time_new(sec, usec)
return time_new_internal(cTime, sec, usec);
}
-struct timeval*
+struct timeval
time_timeval(time)
VALUE time;
{
struct time_object *tobj;
- static struct timeval t;
+ struct timeval t;
switch (TYPE(time)) {
case T_FIXNUM:
t.tv_sec = FIX2UINT(time);
if (t.tv_sec < 0)
- Fail("time must be positive");
+ ArgError("time must be positive");
t.tv_usec = 0;
break;
@@ -114,7 +107,7 @@ time_timeval(time)
double seconds, microseconds;
if (RFLOAT(time)->value < 0.0)
- Fail("time must be positive");
+ ArgError("time must be positive");
seconds = floor(RFLOAT(time)->value);
microseconds = (RFLOAT(time)->value - seconds) * 1000000.0;
t.tv_sec = seconds;
@@ -122,26 +115,153 @@ time_timeval(time)
}
break;
+ case T_BIGNUM:
+ t.tv_sec = NUM2INT(time);
+ t.tv_usec = 0;
+ break;
+
default:
if (!obj_is_kind_of(time, cTime)) {
- Fail("Can't convert %s into Time", rb_class2name(CLASS_OF(time)));
+ TypeError("Can't convert %s into Time",
+ rb_class2name(CLASS_OF(time)));
}
GetTimeval(time, tobj);
t = tobj->tv;
break;
}
- return &t;
+ return t;
}
static VALUE
time_s_at(class, time)
VALUE class, time;
{
- struct timeval *tp;
+ struct timeval tv;
+
+ tv = time_timeval(time);
+ return time_new_internal(class, tv.tv_sec, tv.tv_usec);
+}
+
+static char *months [12] = {
+ "jan", "feb", "mar", "apr", "may", "jun",
+ "jul", "aug", "sep", "oct", "nov", "dec",
+};
+
+static void
+time_arg(argc, argv, args)
+ int argc;
+ VALUE *argv;
+ int *args;
+{
+ VALUE v[6];
+ int i;
+
+ rb_scan_args(argc, argv, "15", &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
+
+ args[0] = NUM2INT(v[0]);
+ if (args[0] < 70) args[0] += 100;
+ if (args[0] > 1900) args[0] -= 1900;
+ if (v[1] == Qnil) {
+ args[1] = 0;
+ }
+ else if (TYPE(v[1]) == T_STRING) {
+ args[1] = -1;
+ for (i=0; i<12; i++) {
+ if (strcasecmp(months[i], RSTRING(v[1])->ptr) == 0) {
+ args[1] = i;
+ break;
+ }
+ }
+ }
+ else {
+ args[1] = NUM2INT(v[1]) - 1;
+ }
+ if (v[2] == Qnil) {
+ args[2] = 1;
+ }
+ else {
+ args[2] = NUM2INT(v[2]);
+ }
+ for (i=3;i<6;i++) {
+ if (v[i] == Qnil) {
+ args[i] = 0;
+ }
+ else {
+ args[i] = NUM2INT(v[i]);
+ }
+ }
+
+ /* value validation */
+ if ( args[0] < 70|| args[1] > 137
+ || args[1] < 0 || args[1] > 11
+ || args[2] < 1 || args[2] > 31
+ || args[3] < 0 || args[3] > 23
+ || args[4] < 0 || args[4] > 60
+ || args[5] < 0 || args[5] > 61)
+ ArgError("argument out of range");
+}
+
+static VALUE
+time_gm_or_local(argc, argv, gm_or_local)
+ int argc;
+ VALUE *argv;
+ int gm_or_local;
+{
+ int args[6];
+ struct timeval tv;
+ struct tm *tm;
+ time_t guess, t;
+ int diff;
+ struct tm *(*fn)();
+
+ fn = (gm_or_local) ? gmtime : localtime;
+ time_arg(argc, argv, args);
+
+ gettimeofday(&tv, 0);
+ guess = tv.tv_sec;
+
+ tm = (*fn)(&guess);
+ if (!tm) goto error;
+ t = args[0];
+ while (diff = t - tm->tm_year) {
+ guess += diff * 364 * 24 * 3600;
+ if (guess < 0) ArgError("too far future");
+ tm = (*fn)(&guess);
+ if (!tm) goto error;
+ }
+ t = args[1];
+ while (diff = t - tm->tm_mon) {
+ guess += diff * 27 * 24 * 3600;
+ tm = (*fn)(&guess);
+ if (!tm) goto error;
+ }
+ guess += (args[2] - tm->tm_mday) * 3600 * 24;
+ guess += (args[3] - tm->tm_hour) * 3600;
+ guess += (args[4] - tm->tm_min) * 60;
+ guess += args[5] - tm->tm_sec;
+
+ return time_new_internal(cTime, guess, 0);
- tp = time_timeval(time);
- return time_new_internal(class, tp->tv_sec, tp->tv_usec);
+ error:
+ ArgError("gmtime error");
+}
+static VALUE
+time_s_timegm(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ return time_gm_or_local(argc, argv, 1);
+}
+
+static VALUE
+time_s_timelocal(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ return time_gm_or_local(argc, argv, 0);
}
static VALUE
@@ -182,6 +302,25 @@ time_cmp(time1, time2)
int i;
GetTimeval(time1, tobj1);
+ switch (TYPE(time2)) {
+ case T_FIXNUM:
+ i = FIX2INT(time2);
+ if (tobj1->tv.tv_sec == i) return INT2FIX(0);
+ if (tobj1->tv.tv_sec > i) return INT2FIX(1);
+ return FIX2INT(-1);
+
+ case T_FLOAT:
+ {
+ double t;
+
+ if (tobj1->tv.tv_sec == (int)RFLOAT(time2)->value) return INT2FIX(0);
+ t = (double)tobj1->tv.tv_sec + (double)tobj1->tv.tv_usec*1e-6;
+ if (tobj1->tv.tv_sec == RFLOAT(time2)->value) return INT2FIX(0);
+ if (tobj1->tv.tv_sec > RFLOAT(time2)->value) return INT2FIX(1);
+ return FIX2INT(-1);
+ }
+ }
+
if (obj_is_instance_of(time2, cTime)) {
GetTimeval(time2, tobj2);
if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) {
@@ -271,6 +410,13 @@ static VALUE
time_coerce(time1, time2)
VALUE time1, time2;
{
+ if (TYPE(time2) == T_FLOAT) {
+ double d = RFLOAT(time2)->value;
+ unsigned int i = (unsigned int) d;
+
+ return time_new_internal(i, (int)(d - (double)i)*1e6);
+ }
+
return time_new(CLASS_OF(time1), NUM2INT(time2), 0);
}
@@ -282,7 +428,11 @@ time_plus(time1, time2)
int sec, usec;
GetTimeval(time1, tobj1);
- if (obj_is_instance_of(time2, cTime)) {
+ if (TYPE(time2) == T_FLOAT) {
+ sec = tobj1->tv.tv_sec + (unsigned int)RFLOAT(time2)->value;
+ usec = tobj1->tv.tv_usec + (RFLOAT(time2)->value - (double)sec)*1e6;
+ }
+ else 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;
@@ -290,10 +440,11 @@ time_plus(time1, time2)
else {
sec = tobj1->tv.tv_sec + NUM2INT(time2);
usec = tobj1->tv.tv_usec;
- if (usec >= 1000000) {
- sec++;
- usec -= 1000000;
- }
+ }
+
+ if (usec >= 1000000) { /* usec overflow */
+ sec++;
+ usec -= 1000000;
}
return time_new(sec, usec);
}
@@ -307,18 +458,28 @@ time_minus(time1, time2)
GetTimeval(time1, tobj1);
if (obj_is_instance_of(time2, cTime)) {
+ double f;
+
GetTimeval(time2, tobj2);
- sec = tobj1->tv.tv_sec - tobj2->tv.tv_sec;
- usec = tobj1->tv.tv_usec - tobj2->tv.tv_usec;
- if (usec < 0) {
- sec--;
- usec += 1000000;
- }
+ f = tobj1->tv.tv_sec - tobj2->tv.tv_sec;
+
+ f += (tobj1->tv.tv_usec - tobj2->tv.tv_usec)*1e-6;
+
+ return float_new(f);
+ }
+ else if (TYPE(time2) == T_FLOAT) {
+ sec = tobj1->tv.tv_sec - (int)RFLOAT(time2)->value;
+ usec = tobj1->tv.tv_usec - (RFLOAT(time2)->value - (double)sec)*1e6;
}
else {
sec = tobj1->tv.tv_sec - NUM2INT(time2);
usec = tobj1->tv.tv_usec;
}
+
+ if (usec < 0) { /* usec underflow */
+ sec--;
+ usec += 1000000;
+ }
return time_new(sec, usec);
}
@@ -522,13 +683,12 @@ time_s_times(obj)
#endif /* HZ */
struct tms buf;
- if (times(&buf) == -1) rb_sys_fail(Qnil);
+ if (times(&buf) == -1) rb_sys_fail(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);
+ float_new((double)buf.tms_cstime / HZ));
#else
#ifdef NT
FILETIME create, exit, kernel, user;
@@ -537,14 +697,12 @@ time_s_times(obj)
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)(kernel.dwHighDateTime*2e32+kernel.dwLowDateTime)/2e6),
+ float_new((double)(user.dwHighDateTime*2e32+user.dwLowDateTime)/2e6),
float_new((double)0),
- Qnil);
+ float_new((double)0));
#else
- Fail("can't call times");
- return Qnil;
+ rb_notimplement();
#endif
#endif
}
@@ -558,6 +716,9 @@ Init_Time()
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, "gm", time_s_timegm, -1);
+ rb_define_singleton_method(cTime, "local", time_s_timelocal, -1);
+ rb_define_singleton_method(cTime, "mktime", time_s_timelocal, -1);
rb_define_singleton_method(cTime, "times", time_s_times, 0);
@@ -596,6 +757,6 @@ Init_Time()
rb_define_method(cTime, "strftime", time_strftime, 1);
#if defined(HAVE_TIMES) || defined(NT)
- S_Tms = struct_define("Tms", "utime", "stime", "cutime", "cstime", Qnil);
+ S_Tms = struct_define("Tms", "utime", "stime", "cutime", "cstime", 0);
#endif
}
diff --git a/top.sed b/top.sed
new file mode 100644
index 0000000000..371190875a
--- /dev/null
+++ b/top.sed
@@ -0,0 +1,37 @@
+s/@srcdir@/./
+s/@CC@/gcc/
+s/@CPP@/gcc -E/
+s/@CPPFLAGS@//
+s/@YACC@/bison -y/
+s/@INSTALL@/ginstall -c/
+s/@INSTALL_PROGRAM@/${INSTALL}/
+s/@INSTALL_DATA@/${INSTALL} -m 644/
+s/@SET_MAKE@//
+s/@CFLAGS@/-g -O -I./
+s/@STATIC@//
+s/@LDFLAGS@//
+s/@LIBS@//
+s/@LIBOBJS@/crypt.o/
+s/@ALLOCA@//
+s!@prefix@!/usr/local!
+s/@exec_prefix@/${prefix}/
+s/@STRIP@/strip/
+s!/bin/rm!rm!
+s/@LDEXT@/so/
+s/@CCDLFLAGS@/-fpic/
+s!@arclib@!/usr/local/lib/ruby/i386-msdos!
+/\/dev\/null/s,/dev/null 2>&1, nul,
+/if older/s/"ruby"/"ruby.exe"/g
+/`rm -f ruby`/s//`rm -f ruby.exe`/
+/`cp miniruby ruby`/s//`cp miniruby.exe ruby.exe`/
+/^extruby:/ {
+ n;N;N;N;c\
+ cd ext\
+ ../miniruby ./extmk.rb\
+ cd ..
+}
+/^clean:;/ {
+ n;n;s!cd.*!cd ext\
+ ../miniruby ./extmk.rb clean\
+ cd ..!
+}
diff --git a/util.c b/util.c
index 19a0416794..717e0beed9 100644
--- a/util.c
+++ b/util.c
@@ -6,7 +6,7 @@
$Date$
created at: Fri Mar 10 17:22:34 JST 1995
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
diff --git a/util.h b/util.h
index 91805d99c5..570d894ccb 100644
--- a/util.h
+++ b/util.h
@@ -6,7 +6,7 @@
$Date$
created at: Thu Mar 9 11:55:53 JST 1995
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
#ifndef UTIL_H
diff --git a/variable.c b/variable.c
index 9721c1c2d4..1d6449bcab 100644
--- a/variable.c
+++ b/variable.c
@@ -10,20 +10,21 @@
#include "ruby.h"
#include "env.h"
+#include "node.h"
#include "st.h"
-st_table *rb_global_tbl;
+static st_table *rb_global_tbl;
st_table *rb_class_tbl;
#define global_tbl rb_global_tbl
#define class_tbl rb_class_tbl
-VALUE rb_const_defined();
+int rb_const_defined();
VALUE rb_const_get();
st_table *
new_idhash()
{
- return st_init_table(ST_NUMCMP, ST_NUMHASH);
+ return st_init_numtable();
}
void
@@ -39,10 +40,13 @@ rb_class2path(class)
{
VALUE path;
- while (TYPE(class) == T_ICLASS) {
+ while (TYPE(class) == T_ICLASS || FL_TEST(class, FL_SINGLETON)) {
class = (VALUE)RCLASS(class)->super;
}
path = rb_ivar_get(class, rb_intern("__classpath__"));
+ if (NIL_P(path)) {
+ return rb_class2name(class);
+ }
if (TYPE(path) != T_STRING) Bug("class path does not set properly");
return RSTRING(path)->ptr;
}
@@ -55,7 +59,6 @@ rb_class_path(class)
if (strchr(name, ':')) {
VALUE ary = str_split(str_new2(name), ":");
- ary_pop(ary);
ary = ary_reverse(ary);
return ary_join(ary, str_new2("::"));
}
@@ -70,6 +73,7 @@ rb_set_class_path(class, under, name)
VALUE str;
char *s;
+ if (cObject == under) return;
str = str_new2(name);
if (under) {
str_cat(str, ":", 1);
@@ -93,8 +97,9 @@ rb_path2class(path)
*p++;
}
if (*p == '\0') { /* pre-defined class */
- if (!st_lookup(class_tbl, rb_intern(path), &class)) {
- Fail("Undefined class -- %s", path);
+ if (!st_lookup(RCLASS(cObject)->iv_tbl, rb_intern(path), &class)
+ && !st_lookup(class_tbl, rb_intern(path), &class)) {
+ NameError("Undefined class -- %s", path);
}
return class;
}
@@ -107,14 +112,14 @@ rb_path2class(path)
*s = '\0';
id = rb_intern(name);
if (!rb_const_defined(class, id))
- Fail("%s not defined", name);
+ Fatal("%s not defined", name);
class = rb_const_get(class, id);
switch (TYPE(class)) {
case T_CLASS:
case T_MODULE:
break;
default:
- Fail("%s not a module/class");
+ Fatal("0x%x is not a class/module", class);
}
return class;
}
@@ -124,7 +129,7 @@ rb_name_class(class, id)
VALUE class;
ID id;
{
- rb_ivar_set(class, rb_intern("__classname__"), INT2FIX(id));
+ rb_ivar_set(class, rb_intern("__classname__"), id);
}
static st_table *autoload_tbl = 0;
@@ -173,16 +178,15 @@ rb_class2name(class)
case T_MODULE:
break;
default:
- Fail("0x%x is not a class/module", class);
+ Fatal("0x%x is not a class/module", class);
}
- while (FL_TEST(class, FL_SINGLE) || TYPE(class) == T_ICLASS) {
+ while (FL_TEST(class, FL_SINGLETON) || TYPE(class) == T_ICLASS) {
class = (struct RClass*)class->super;
}
name = rb_ivar_get(class, rb_intern("__classname__"));
- if (name) {
- name = FIX2INT(name);
+ if (!NIL_P(name)) {
return rb_id2name((ID)name);
}
Bug("class 0x%x not named", class);
@@ -194,6 +198,8 @@ struct trace_var {
struct trace_var *next;
};
+VALUE f_untrace_var();
+
struct global_entry {
ID id;
void *data;
@@ -241,7 +247,7 @@ static VALUE
undef_getter(id)
ID id;
{
- Warning("global var %s not initialized", rb_id2name(id));
+ Warning("global variable `%s' not initialized", rb_id2name(id));
return Qnil;
}
@@ -315,12 +321,12 @@ var_marker(var)
}
static void
-readonly_setter(id, var, val)
+readonly_setter(val, id, var)
ID id;
void *var;
VALUE val;
{
- Fail("Can't set variable %s", rb_id2name(id));
+ NameError("Can't set variable %s", rb_id2name(id));
}
static int
@@ -405,8 +411,6 @@ rb_define_virtual_variable(name, getter, setter)
rb_define_hooked_variable(name, 0, getter, setter);
}
-void rb_trace_eval();
-
void
rb_trace_eval(cmd, val)
VALUE cmd, val;
@@ -427,9 +431,12 @@ f_trace_var(argc, argv)
if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
cmd = f_lambda();
}
+ if (NIL_P(cmd)) {
+ return f_untrace_var(argc, argv, Qnil);
+ }
id = rb_to_id(var);
if (!st_lookup(global_tbl, id, &entry)) {
- Fail("undefined global variable %s", rb_id2name(id));
+ NameError("undefined global variable %s", rb_id2name(id));
}
trace = ALLOC(struct trace_var);
trace->next = entry->trace;
@@ -441,29 +448,52 @@ f_trace_var(argc, argv)
}
VALUE
-f_untrace_var(obj, var)
- VALUE obj, var;
+f_untrace_var(argc, argv)
+ int argc;
+ VALUE *argv;
{
+ VALUE var, cmd;
ID id;
struct global_entry *entry;
struct trace_var *trace;
- VALUE ary;
+ rb_scan_args(argc, argv, "11", &var, &cmd);
id = rb_to_id(var);
if (!st_lookup(global_tbl, id, &entry)) {
- Fail("undefined global variable %s", rb_id2name(id));
+ NameError("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;
+ if (NIL_P(cmd)) {
+ VALUE 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;
+ return ary;
+ }
+ else {
+ struct trace_var t;
+ struct trace_var *next;
+
+ t.next = entry->trace;
+ trace = &t;
+ while (trace->next) {
+ next = trace->next;
+ if (next->data == (void*)cmd) {
+ trace->next = next->next;
+ free(next);
+ entry->trace = t.next;
+ return ary_new3(1, cmd);
+ }
+ trace = next;
+ }
+ }
+ return Qnil;
}
VALUE
@@ -549,8 +579,8 @@ rb_ivar_get(obj, id)
return val;
return Qnil;
default:
- Fail("class %s can not have instance variables",
- rb_class2name(CLASS_OF(obj)));
+ Fatal("class %s can not have instance variables",
+ rb_class2name(CLASS_OF(obj)));
break;
}
Warning("instance var %s not initialized", rb_id2name(id));
@@ -571,8 +601,8 @@ rb_ivar_set(obj, id, val)
st_insert(obj->iv_tbl, id, val);
break;
default:
- Fail("class %s can not have instance variables",
- rb_class2name(CLASS_OF(obj)));
+ Fatal("class %s can not have instance variables",
+ rb_class2name(CLASS_OF(obj)));
break;
}
return val;
@@ -595,6 +625,22 @@ rb_ivar_defined(obj, id)
}
VALUE
+rb_const_get_at(class, id)
+ struct RClass *class;
+ ID id;
+{
+ VALUE value;
+
+ if (class->iv_tbl && st_lookup(class->iv_tbl, id, &value)) {
+ return value;
+ }
+ NameError("Uninitialized constant %s::%s",
+ RSTRING(rb_class_path(class))->ptr,
+ rb_id2name(id));
+ /* not reached */
+}
+
+VALUE
rb_const_get(class, id)
struct RClass *class;
ID id;
@@ -624,21 +670,32 @@ rb_const_get(class, id)
st_delete(autoload_tbl, &id, &modname);
module = str_new2(modname);
free(modname);
- f_require(Qnil, module);
+ f_require(0, 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));
+ NameError("Uninitialized constant %s::%s",
+ RSTRING(rb_class_path(class))->ptr,
+ rb_id2name(id));
else
- Fail("Uninitialized constant %s",rb_id2name(id));
+ NameError("Uninitialized constant %s",rb_id2name(id));
/* not reached */
}
-VALUE
+int
+rb_const_defined_at(class, id)
+ struct RClass *class;
+ ID id;
+{
+ if (class->iv_tbl && st_lookup(class->iv_tbl, id, 0)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
rb_const_defined(class, id)
struct RClass *class;
ID id;
@@ -656,16 +713,31 @@ rb_const_defined(class, id)
return FALSE;
}
+int
+rb_autoload_defined(id)
+ ID id;
+{
+ if (autoload_tbl && st_lookup(autoload_tbl, id, 0))
+ return TRUE;
+ return FALSE;
+}
+
void
rb_const_set(class, id, val)
struct RClass *class;
ID id;
VALUE val;
{
- if (rb_const_defined(class, id))
- Fail("already initialized constnant %s", rb_id2name(id));
+ if (!class->iv_tbl) {
+ class->iv_tbl = new_idhash();
+ }
+ else if (st_lookup(class->iv_tbl, id, 0)) {
+ NameError("already initialized constnant %s", rb_id2name(id));
+ }
+ if (!rb_autoload_defined(id) && rb_const_defined(class, id)) {
+ Warning("already initialized constnant %s", rb_id2name(id));
+ }
- if (!class->iv_tbl) class->iv_tbl = new_idhash();
st_insert(class->iv_tbl, id, val);
}
@@ -678,6 +750,16 @@ rb_define_const(class, name, val)
rb_const_set(class, rb_intern(name), val);
}
+extern VALUE cKernel;
+
+void
+rb_define_global_const(name, val)
+ char *name;
+ VALUE val;
+{
+ rb_define_const(cKernel, name, val);
+}
+
VALUE
rb_iv_get(obj, name)
VALUE obj;
@@ -698,33 +780,3 @@ rb_iv_set(obj, name, 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 dba5f6c8b5..26ef8d054f 100644
--- a/version.c
+++ b/version.c
@@ -7,7 +7,7 @@
$Date: 1995/01/12 08:54:54 $
created at: Thu Sep 30 20:08:01 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -20,18 +20,18 @@ extern VALUE cKernel;
void
Init_version()
{
- rb_define_const(cKernel, "VERSION", str_new2(RUBY_VERSION));
+ rb_define_global_const("VERSION", str_new2(RUBY_VERSION));
}
void
show_version()
{
- fprintf(stderr, "ruby - version %s (%s)\n", RUBY_VERSION, VERSION_DATE);
+ fprintf(stderr, "ruby - version %s\n", RUBY_VERSION, VERSION_DATE);
}
void
show_copyright()
{
- fprintf(stderr, "ruby - Copyright (C) 1993-1995 Yukihiro Matsumoto\n");
+ fprintf(stderr, "ruby - Copyright (C) 1993-1996 Yukihiro Matsumoto\n");
exit(0);
}
diff --git a/version.h b/version.h
index f019bbdae3..3ed36e70e2 100644
--- a/version.h
+++ b/version.h
@@ -1,2 +1,2 @@
-#define RUBY_VERSION "0.95"
-#define VERSION_DATE "95/12/21"
+#define RUBY_VERSION "0.99.4-961224"
+#define VERSION_DATE "96/12/24"