diff options
author | Yukihiro Matsumoto <matz@ruby-lang.org> | 1996-12-24 15:20:58 +0900 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2019-08-17 22:09:32 +0900 |
commit | 554b989ba1623b9f6a0b76f00824c83a23fbcbc1 (patch) | |
tree | 71f06227fe259bebaa5ca4bf05cc398184bced68 | |
parent | fca49a8a69a0f6bb4feae74c6cd0e93d7fac8b36 (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-- | ChangeLog | 1799 | ||||
-rw-r--r-- | MANIFEST | 30 | ||||
-rw-r--r-- | Makefile.in | 30 | ||||
-rw-r--r-- | README | 182 | ||||
-rw-r--r-- | README.EXT | 973 | ||||
-rw-r--r-- | README.jp | 159 | ||||
-rw-r--r-- | ToDo | 8 | ||||
-rw-r--r-- | array.c | 459 | ||||
-rw-r--r-- | bignum.c | 440 | ||||
-rw-r--r-- | class.c | 45 | ||||
-rw-r--r-- | compar.c | 10 | ||||
-rw-r--r-- | config.dj | 35 | ||||
-rwxr-xr-x | config.guess | 139 | ||||
-rwxr-xr-x | config.sub | 177 | ||||
-rw-r--r-- | configure.bat | 5 | ||||
-rw-r--r-- | configure.in | 242 | ||||
-rw-r--r-- | defines.h | 13 | ||||
-rw-r--r-- | dir.c | 64 | ||||
-rw-r--r-- | dln.c | 161 | ||||
-rw-r--r-- | enum.c | 100 | ||||
-rw-r--r-- | env.h | 7 | ||||
-rw-r--r-- | error.c | 714 | ||||
-rw-r--r-- | eval.c | 3252 | ||||
-rw-r--r-- | ext/Setup | 4 | ||||
-rw-r--r-- | ext/Setup.dj | 8 | ||||
-rw-r--r-- | ext/dbm/MANIFEST | 1 | ||||
-rw-r--r-- | ext/dbm/dbm.c | 188 | ||||
-rw-r--r-- | ext/dbm/dbm.doc | 107 | ||||
-rw-r--r-- | ext/dbm/extconf.rb | 2 | ||||
-rw-r--r-- | ext/etc/etc.c | 36 | ||||
-rw-r--r-- | ext/extmk.rb.in | 148 | ||||
-rw-r--r-- | ext/kconv/MANIFEST | 2 | ||||
-rw-r--r-- | ext/kconv/kconv.c | 1934 | ||||
-rw-r--r-- | ext/marshal/MANIFEST | 1 | ||||
-rw-r--r-- | ext/marshal/extconf.rb | 2 | ||||
-rw-r--r-- | ext/marshal/marshal.c | 519 | ||||
-rw-r--r-- | ext/marshal/marshal.doc | 5 | ||||
-rw-r--r-- | ext/md5/MANIFEST | 6 | ||||
-rw-r--r-- | ext/md5/depend | 2 | ||||
-rw-r--r-- | ext/md5/md5.doc | 36 | ||||
-rw-r--r-- | ext/md5/md5.h | 86 | ||||
-rw-r--r-- | ext/md5/md5c.c | 337 | ||||
-rw-r--r-- | ext/md5/md5init.c | 90 | ||||
-rw-r--r-- | ext/socket/MANIFEST | 1 | ||||
-rw-r--r-- | ext/socket/extconf.rb | 7 | ||||
-rw-r--r-- | ext/socket/socket.c | 426 | ||||
-rw-r--r-- | ext/socket/socket.doc | 227 | ||||
-rw-r--r-- | ext/tkutil/MANIFEST | 2 | ||||
-rw-r--r-- | ext/tkutil/depend | 1 | ||||
-rw-r--r-- | ext/tkutil/extconf.rb | 11 | ||||
-rw-r--r-- | ext/tkutil/tkutil.c | 1 | ||||
-rw-r--r-- | file.c | 403 | ||||
-rw-r--r-- | gc.c | 171 | ||||
-rw-r--r-- | glob.c | 8 | ||||
-rw-r--r-- | hash.c | 137 | ||||
-rw-r--r-- | inits.c | 8 | ||||
-rw-r--r-- | io.c | 885 | ||||
-rw-r--r-- | io.h | 14 | ||||
-rw-r--r-- | lib/base64.rb | 2 | ||||
-rw-r--r-- | lib/cgi-lib.rb | 56 | ||||
-rw-r--r-- | lib/complex.rb | 490 | ||||
-rw-r--r-- | lib/find.rb | 47 | ||||
-rw-r--r-- | lib/getopts.rb | 173 | ||||
-rw-r--r-- | lib/jcode.rb | 174 | ||||
-rw-r--r-- | lib/mailread.rb | 19 | ||||
-rw-r--r-- | lib/mathn.rb | 307 | ||||
-rw-r--r-- | lib/observer.rb | 40 | ||||
-rw-r--r-- | lib/parsearg.rb | 103 | ||||
-rw-r--r-- | lib/rational.rb | 361 | ||||
-rw-r--r-- | lib/safe.rb | 78 | ||||
-rw-r--r-- | lib/thread.rb | 153 | ||||
-rw-r--r-- | lib/tk.rb | 557 | ||||
-rw-r--r-- | lib/tkcanvas.rb | 47 | ||||
-rw-r--r-- | lib/tkcore.rb | 521 | ||||
-rw-r--r-- | lib/tkentry.rb | 2 | ||||
-rw-r--r-- | lib/tkscrollbox.rb | 27 | ||||
-rw-r--r-- | lib/tktext.rb | 18 | ||||
-rw-r--r-- | lib/tkthcore.rb | 546 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | math.c | 9 | ||||
-rw-r--r-- | missing/flock.c | 90 | ||||
-rw-r--r-- | missing/mkdir.c | 4 | ||||
-rw-r--r-- | missing/setenv.c | 4 | ||||
-rw-r--r-- | missing/strftime.c | 1094 | ||||
-rw-r--r-- | node.h | 84 | ||||
-rw-r--r-- | numeric.c | 417 | ||||
-rw-r--r-- | object.c | 384 | ||||
-rw-r--r-- | pack.c | 74 | ||||
-rw-r--r-- | parse.y | 1586 | ||||
-rw-r--r-- | process.c | 386 | ||||
-rw-r--r-- | random.c | 28 | ||||
-rw-r--r-- | range.c | 153 | ||||
-rw-r--r-- | re.c | 247 | ||||
-rw-r--r-- | re.h | 2 | ||||
-rw-r--r-- | regex.c | 76 | ||||
-rw-r--r-- | regex.h | 2 | ||||
-rw-r--r-- | ruby.c | 239 | ||||
-rw-r--r-- | ruby.h | 123 | ||||
-rw-r--r-- | ruby.texi | 5044 | ||||
-rw-r--r-- | sample/clnt.rb | 6 | ||||
-rw-r--r-- | sample/dir.rb | 4 | ||||
-rw-r--r-- | sample/eval.rb | 41 | ||||
-rw-r--r-- | sample/evaldef.rb | 26 | ||||
-rw-r--r-- | sample/export.rb | 2 | ||||
-rw-r--r-- | sample/fact.rb | 8 | ||||
-rwxr-xr-x | sample/from.rb | 14 | ||||
-rw-r--r-- | sample/fullpath.pl | 22 | ||||
-rw-r--r-- | sample/fullpath.rb | 6 | ||||
-rwxr-xr-x | sample/getopts.test | 25 | ||||
-rw-r--r-- | sample/io.rb | 4 | ||||
-rwxr-xr-x | sample/less.rb | 4 | ||||
-rw-r--r-- | sample/list.rb | 14 | ||||
-rwxr-xr-x | sample/mpart.rb | 6 | ||||
-rw-r--r-- | sample/observ.rb | 31 | ||||
-rw-r--r-- | sample/philos.rb | 54 | ||||
-rw-r--r-- | sample/pi.rb | 18 | ||||
-rw-r--r-- | sample/rcs.rb | 2 | ||||
-rw-r--r-- | sample/regx.rb | 23 | ||||
-rw-r--r-- | sample/ruby-mode.el | 575 | ||||
-rw-r--r-- | sample/sieve.rb | 2 | ||||
-rw-r--r-- | sample/svr.rb | 2 | ||||
-rw-r--r-- | sample/test.rb | 981 | ||||
-rwxr-xr-x | sample/time.rb | 2 | ||||
-rw-r--r-- | sample/tkbiff.rb | 46 | ||||
-rw-r--r-- | sample/tkbrowse.rb | 8 | ||||
-rw-r--r-- | sample/tkfrom.rb | 13 | ||||
-rw-r--r-- | sample/tkline.rb | 25 | ||||
-rw-r--r-- | sample/trojan.pl | 12 | ||||
-rw-r--r-- | sample/tsvr.rb | 23 | ||||
-rwxr-xr-x | sample/uumerge.rb | 8 | ||||
-rw-r--r-- | sig.h | 46 | ||||
-rw-r--r-- | signal.c | 161 | ||||
-rw-r--r-- | sprintf.c | 72 | ||||
-rw-r--r-- | st.c | 202 | ||||
-rw-r--r-- | st.h | 22 | ||||
-rw-r--r-- | string.c | 674 | ||||
-rw-r--r-- | struct.c | 95 | ||||
-rw-r--r-- | time.c | 251 | ||||
-rw-r--r-- | top.sed | 37 | ||||
-rw-r--r-- | util.c | 2 | ||||
-rw-r--r-- | util.h | 2 | ||||
-rw-r--r-- | variable.c | 206 | ||||
-rw-r--r-- | version.c | 8 | ||||
-rw-r--r-- | version.h | 4 |
144 files changed, 20373 insertions, 12047 deletions
@@ -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åɤƤФ褦 @@ -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 @@ -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: @@ -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 @@ -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("<=>"); } @@ -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); } @@ -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; } @@ -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 @@ -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 @@ -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); @@ -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); @@ -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("<=>"); } @@ -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; @@ -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 } @@ -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 @@ -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); @@ -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("W |