From e299d511db939232c628d6880e61c32e83937d66 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 16 Dec 1998 07:30:36 +0000 Subject: first public release of 1.1d (pre1.2) series git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1dev@354 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 81 +++++- MANIFEST | 9 +- README.EXT | 327 +++++++++++-------------- README.EXT.jp | 48 ++-- ToDo | 39 ++- config.guess | 15 ++ configure.in | 40 +-- dln.c | 17 +- enum.c | 4 + error.c | 10 +- eval.c | 115 ++++----- ext/extmk.rb.in | 15 +- ext/gtk/gtk.c | 10 +- gc.c | 16 +- hash.c | 8 +- intern.h | 12 +- io.c | 2 +- lib/debug.rb | 4 +- lib/delegate.rb | 50 ++-- lib/mailread.rb | 2 +- lib/mkmf.rb | 10 +- lib/pstore.rb | 1 + misc/README | 5 + misc/inf-ruby.el | 313 ++++++++++++++++++++++++ misc/ruby-mode.el | 691 ++++++++++++++++++++++++++++++++++++++++++++++++++++ misc/rubydb2x.el | 104 ++++++++ misc/rubydb3x.el | 104 ++++++++ missing/nt.c | 17 +- numeric.c | 2 +- object.c | 22 +- pack.c | 157 ++++++++++-- parse.y | 48 +++- process.c | 44 ++-- re.h | 1 - regex.c | 1 + ruby.c | 22 ++ ruby.h | 16 +- rubyio.h | 1 + sample/cal.rb | 4 +- sample/inf-ruby.el | 310 ----------------------- sample/ruby-mode.el | 683 --------------------------------------------------- sample/rubydb2x.el | 104 -------- sample/rubydb3x.el | 104 -------- st.c | 9 +- string.c | 6 +- top.sed | 2 +- variable.c | 168 +++++++++++-- version.h | 2 +- 48 files changed, 2108 insertions(+), 1667 deletions(-) create mode 100644 misc/README create mode 100644 misc/inf-ruby.el create mode 100644 misc/ruby-mode.el create mode 100644 misc/rubydb2x.el create mode 100644 misc/rubydb3x.el delete mode 100644 sample/inf-ruby.el delete mode 100644 sample/ruby-mode.el delete mode 100644 sample/rubydb2x.el delete mode 100644 sample/rubydb3x.el diff --git a/ChangeLog b/ChangeLog index 45aa37915a..b08a28f836 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,68 @@ +Wed Dec 16 16:28:31 1998 Yukihiro Matsumoto + + * experimental version 1.1d0 (pre1.2) released. + +Wed Dec 16 10:43:34 1998 Yukihiro Matsumoto + + * regex.c (re_search): bound check before calling re_match(). + +Tue Dec 15 13:59:01 1998 Yukihiro Matsumoto + + * error.c (exc_to_s): returns class name for unset mesg. + + * error.c (exc_initialize): do not initialize @mesg by "". + + * parse.y (nextc): __END__ should handle CR+LF newlines. + +Wed Dec 9 13:37:12 1998 MAEDA shugo + + * pack.c (encodes): use buffering for B-encoding. + + * pack.c (pack_pack): Q-encoding by 'M'. + +Tue Dec 8 14:10:00 1998 Yukihiro Matsumoto + + * variable.c (generic_ivar_get): any object can have instance + variables now. great improvement. + + * variable.c (rb_name_class): do not set __classpath__ by default, + use __classid__ instead. + +Mon Dec 7 22:08:22 1998 Yukihiro Matsumoto + + * ruby.h (struct RFile): IO objects can have instance variables now. + + * parse.y (primary): allows `def obj::foo; .. end'. + +Mon Dec 7 18:24:50 1998 WATANABE Tetsuya + + * ruby.c (set_arg0): $0 supprt for HP-UX. + +Mon Dec 7 01:30:28 1998 WATANABE Hirofumi + + * dln.c (dln_strerror): better error messages on win32. + +Sat Dec 5 23:27:23 1998 Yukihiro Matsumoto + + * parse.y (here_document): indentable here-doc delimiter by + `<<-'. Proposed by Clemens . Thanks. + +Thu Dec 3 16:50:17 1998 Yukihiro Matsumoto + + * ext/extmk.rb.in (realclean): trouble on install. + +Sun Nov 29 22:25:39 1998 Takaaki Tateishi + + * process.c (f_exec): check number of argument. + +Wed Nov 25 13:07:12 1998 Yukihiro Matsumoto + + * parse.y (yycompile): reduce known memory leak (hard to remove). + +Thu Nov 26 17:27:30 1998 Yukihiro Matsumoto + + * version 1.1c9 released. + Wed Nov 25 03:41:21 1998 Yukihiro Matsumoto * st.c (st_init_table_with_size): round size up to prime number. @@ -20,6 +85,14 @@ Sat Nov 21 23:27:23 1998 Yukihiro Matsumoto * string.c (rb_str_dup): do not copy additional data (STR_NO_ORIG). +Sat Nov 21 18:44:06 1998 Masaki Fukushima + + * time.c (time_s_now): had memory leak. + + * ext/md5/md5init.c (md5_new): had memory leak. + + * ext/md5/md5init.c (md5_clone): ditto. + Fri Nov 20 23:23:23 1998 Yukihiro Matsumoto * lib/delegate.rb: do not propagate hash and eql?. @@ -34,15 +107,15 @@ Thu Nov 19 01:40:52 1998 Yukihiro Matsumoto * eval.c (rb_eval): actual rest arguments extended arrays too much. -Wed Nov 18 10:48:09 1998 Yukihiro Matsumoto - - * io.c (read_all): SEGV on large files. - Wed Nov 18 14:30:24 1998 Yukihiro Matsumoto * class.c (rb_define_global_function): global functions now be module function of the Kernel. +Wed Nov 18 10:48:09 1998 Yukihiro Matsumoto + + * io.c (read_all): SEGV on large files. + Tue Nov 17 18:11:20 1998 Yukihiro Matsumoto * version 1.1c8 released. diff --git a/MANIFEST b/MANIFEST index 51931493ae..131906d4d7 100644 --- a/MANIFEST +++ b/MANIFEST @@ -131,6 +131,11 @@ lib/thwait.rb lib/timeout.rb lib/tracer.rb lib/weakref.rb +misc/README +misc/inf-ruby.el +misc/ruby-mode.el +misc/rubydb2x.el +mics/rubydb3x.el missing/alloca.c missing/crypt.c missing/dir.h @@ -174,7 +179,6 @@ sample/from.rb sample/fullpath.rb sample/getopts.test sample/goodfriday.rb -sample/inf-ruby.el sample/less.rb sample/list.rb sample/list2.rb @@ -194,9 +198,6 @@ sample/rcs.awk sample/rcs.dat sample/rcs.rb sample/regx.rb -sample/ruby-mode.el -sample/rubydb2x.el -sample/rubydb3x.el sample/sieve.rb sample/svr.rb sample/test.rb diff --git a/README.EXT b/README.EXT index a6d6cdbc33..f169e54995 100644 --- a/README.EXT +++ b/README.EXT @@ -84,37 +84,28 @@ There are faster check-macros for fixnums and nil. 1.3 Convert VALUE into C data -データタイプがT_NIL, T_FALSE, T_TRUEである時,データはそれぞ -れnil, false, trueです.このデータタイプのオブジェクトはひと -つずつしか存在しません. - -データタイプがT_FIXNUMの時,これは31bitのサイズを持つ整数で -す.FIXNUMをCの整数に変換するためにはマクロ「FIX2INT()」を使 -います.それから,FIXNUMに限らずRubyのデータを整数に変換する -「NUM2INT()」というマクロがあります.このマクロはデータタイ -プのチェック無しで使えます(整数に変換できない場合には例外が -発生する). - -それ以外のデータタイプは対応するCの構造体があります.対応す -る構造体のあるVALUEはそのままキャスト(型変換)すれば構造体の -ポインタに変換できます. - -構造体は「struct RXxxxx」という名前でruby.hで定義されていま -す.例えば文字列は「struct RString」です.実際に使う可能性が -あるのは文字列と配列くらいだと思います. - -ruby.hでは構造体へキャストするマクロも「RXXXXX()」(全部大文 -字にしたもの)という名前で提供されています(例: RSTRING()). - -例えば,文字列strの長さを得るためには「RSTRING(str)->len」と -し,文字列strをchar*として得るためには「RSTRING(str)->ptr」 -とします.配列の場合には,それぞれ「RARRAT(str)->len」, -「RARRAT(str)->ptr」となります. - -Rubyの構造体を直接アクセスする時に気をつけなければならないこ -とは,配列や文字列の構造体の中身は参照するだけで,直接変更し -ないことです.直接変更した場合,オブジェクトの内容の整合性が -とれなくなって,思わぬバグの原因になります. +The data for type T_NIL, T_FALSE, T_TRUE are nil, true, false +respectively. They are singletons for the data type. + +The T_FIXNUM data is the 31bit length fixed integer (63bit length on +some machines), which can be conver to the C integer by using +FIX2INT() macro. There also be NUM2INT() which converts any Ruby +numbers into C integer. The NUM2INT() macro includes type check, so +the exception will be raised if conversion failed. + +Other data types have corresponding C structures, e.g. struct RArray +for T_ARRAY etc. VALUE of the type which has corresponding structure +can be cast to retrieve the pointer to the struct. The casting macro +RXXXX for each data type like RARRAY(obj). see "ruby.h". + +For example, `RSTRING(size)->len' is the way to get the size of the +Ruby String object. The allocated region can be accessed by +`RSTRING(str)->ptr'. For arrays, `RARRAY(ary)->len' and +`RARRAY(ary)->ptr' respectively. + +Notice: Do not change the value of the structure directly, unless you +are responsible about the result. It will be the cause of interesting +bugs. 1.4 Convert C data into VALUE @@ -150,12 +141,9 @@ INT2NUM() 1.5 Manipulate Ruby data -先程も述べた通り,Rubyの構造体をアクセスする時に内容の更新を -行うことは勧められません.で,Rubyのデータを操作する時には -Rubyが用意している関数を用いてください. - -ここではもっとも使われるであろう文字列と配列の生成/操作を行 -い関数をあげます(全部ではないです). +As I already told, it is not recommended to modify object's internal +structure. To manipulate objects, use functions supplied by Ruby +interpreter. Useful functions are listed below (not all): String funtions @@ -213,160 +201,148 @@ Ruby を追加することができます.Rubyでは以下の機能を追加する関数が 提供されています. - * クラス,モジュール - * メソッド,特異メソッドなど - * 定数 + * Classes, Modules + * Methods, Singleton Methods + * Constants では順に紹介します. 2.1.1 Class/module definition -クラスやモジュールを定義するためには,以下の関数を使います. +To define class or module, use functions below: VALUE rb_define_class(char *name, VALUE super) VALUE rb_define_module(char *name) -これらの関数は新しく定義されたクラスやモジュールを返します. -メソッドや定数の定義にこれらの値が必要なので,ほとんどの場合 -は戻り値を変数に格納しておく必要があるでしょう. +These functions return the newly created class ot module. You may +want to save this reference into the variable to use later. 2.1.2 Method/singleton method definition -メソッドや特異メソッドを定義するには以下の関数を使います. +To define methods or singleton methods, use functions below: void rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc) void rb_define_singleton_method(VALUE object, char *name, - VALUE (*func)(), int argc) + VALUE (*func)(), int argc) +The `argc' represents the number of the arguments to the C function, +which must be less than 17. But I believe you don't need that much. :-) -念のため説明すると「特異メソッド」とは,その特定のオブジェク -トに対してだけ有効なメソッドです.RubyではよくSmalltalkにお -けるクラスメソッドとして,クラスに対する特異メソッドが使われ -ます. +If `argc' is negative, it specifies calling sequence, not number of +the arguments. -これらの関数の argcという引数はCの関数へ渡される引数の数(と -形式)を決めます.argcが正の時は関数に引き渡す引数の数を意味 -します.16個以上の引数は使えません(が,要りませんよね,そん -なに). +If argc is -1, the function will be called like: -argcが負の時は引数の数ではなく,形式を指定したことになります. -argcが-1の時は引数を配列に入れて渡されます.argcが-2の時は引 -数はRubyの配列として渡されます. + VALUE func(int argc, VALUE *argv, VALUE obj) -メソッドを定義する関数はもう二つあります.ひとつはprivateメ -ソッドを定義する関数で,引数はrb_define_method()と同じです. +where argc is the actual number of arguments, argv is the C array of +the arguments, and obj is the receiver. + +if argc is -2, the arguments are passed in Ruby array. The function +will be called like: + + VALUE func(VALUE obj, VALUE args) + +where obj is the receiver, and args is the Ruby array containing +actual arguments. + +There're two more functions to define method. One is to define +private method: void rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc) -privateメソッドとは関数形式でしか呼び出すことの出来ないメソッ -ドです. - -もうひとつはモジュール関数を定義するものです.モジュール関数 -とはモジュールの特異メソッドであり,同時にprivateメソッドで -もあるものです.例をあげるとMathモジュールのsqrt()などがあげ -られます.このメソッドは +The other is to define module function, which is private AND singleton +method of the module. For example, sqrt is the module function +defined in Math module. It can be call in the form like: Math.sqrt(4) -という形式でも +or include Math sqrt(4) -という形式でも使えます.モジュール関数を定義する関数は以下の -通りです. +To define module function void rb_define_module_function(VALUE module, char *name, VALUE (*func)(), int argc) -関数的メソッド(Kernelモジュールのprivaet method)を定義するた -めの関数は以下の通りです. +Oh, in addition, function-like method, which is private method defined +in Kernel module, can be defined using: void rb_define_global_function(char *name, VALUE (*func)(), int argc) 2.1.3 Constant definition -拡張モジュールが必要な定数はあらかじめ定義しておいた方が良い -でしょう.定数を定義する関数は二つあります. +We have 2 functions to define constants: void rb_define_const(VALUE class, char *name, VALUE val) void rb_define_global_const(char *name, VALUE val) -前者は特定のクラス/モジュールに属する定数を定義するもの,後 -者はグローバルな定数を定義するものです. +The former is to define constant under specified class/module. The +latter is to define global constant. 2.2 Use Ruby features from C -既に『1.5 Rubyのデータを操作する』で一部紹介したような関数を -使えば,Rubyの機能を実現している関数を直接呼び出すことが出来 -ます. - -# このような関数の一覧表はいまのところありません.ソースを見 -# るしかないですね. - -それ以外にもRubyの機能を呼び出す方法はいくつかあります. +There are several ways to invoke Ruby's features from C code. -2.2.1 Rubyのプログラムをevalする +2.2.1 Evaluate Ruby Program in String -CからRubyの機能を呼び出すもっとも簡単な方法として,文字列で -与えられたRubyのプログラムを評価する関数があります. +Easiest way to call Ruby's function from C program is to evaluate the +string as Ruby program. This function will do the job. VALUE rb_eval_string(char *str) -この評価は現在の環境で行われます.つまり,現在のローカル変数 -などを受け継ぎます. +Evaluation is done under current context, thus current local variables +of the innermost method (which is defined by Ruby) can be accessed. 2.2.2 ID or Symbol -Cから文字列を経由せずにRubyのメソッドを呼び出すこともできま -す.その前に,Rubyインタプリタ内でメソッドや変数名を指定する -時に使われているIDについて説明しておきましょう. - -IDとは変数名,メソッド名を表す整数です.Rubyの中では +You can invoke methods directly, without parsing the string. First I +need to explain about symbols (which data type is ID). ID is the +integer number to represent Ruby's identifiers such as variable names. +It can be accessed from Ruby in the form like: - :識別子 + :Identifier -でアクセスできます.Cからこの整数を得るためには関数 +You can get the symbol value from string within C code, by using rb_intern(char *name) -を使います.また一文字の演算子はその文字コードがそのままシン -ボルになっています. +In addition, the symbols for one character operators (e.g +) is the +code for that character. 2.2.3 Invoke Ruby method from C -Cから文字列を経由せずにRubyのメソッドを呼び出すためには以下 -の関数を使います. +To invoke methods directly, you can use the function below VALUE rb_funcall(VALUE recv, ID mid, int argc, ...) -この関数はオブジェクトrecvのmidで指定されるメソッドを呼び出 -します. +This function invokes the method of the recv, which name is specified +by the symbol mid. -2.2.4 変数/定数を参照/更新する +2.2.4 Accessing the variables and constants Cから関数を使って参照・更新できるのは,クラス定数,インスタ ンス変数です.大域変数は一部のものはCの大域変数としてアクセ スできます.ローカル変数を参照する方法は公開していません. -オブジェクトのインスタンス変数を参照・更新する関数は以下の通 -りです. +The functions to access/modify instance variables are below: VALUE rb_ivar_get(VALUE obj, ID id) VALUE rb_ivar_set(VALUE obj, ID id, VALUE val) -idはrb_intern()で得られるものを使ってください. +id must be the symbol, which can be retrieved by rb_intern(). -クラス定数を参照するには以下の関数を使ってください. +To access the constants of the class/module: VALUE rb_const_get(VALUE obj, ID id) -クラス定数を新しく定義するためには『2.1.3 定数定義』で紹介さ -れている関数を使ってください. +See 2.1.3 for defining new constant. 3. Informatin sharing between Ruby and C @@ -477,7 +453,7 @@ C 4.Example - Create dbm module -ここまでの説明でとりあえず拡張モジュールは作れるはずです. +ここまでの説明でとりあえず拡張ライブラリは作れるはずです. Rubyのextディレクトリにすでに含まれているdbmモジュールを例に して段階的に説明します. @@ -485,39 +461,30 @@ Ruby % mkdir ext/dbm -Rubyを展開したディレクトリの下,extディレクトリの中に拡張モ -ジュール用のディレクトリを作ります.名前は適当に選んで構いま -せん. +Make a directory for the extension library under ext directory. (2) create MANIFEST file % cd ext/dbm % touch MANIFEST -拡張モジュールのディレクトリの下にはMANIFESTというファイルが -必要なので,とりあえず空のファイルを作っておきます.後でこの -ファイルには必要なファイル一覧が入ることになります. - -MANIFESTというファイルは,makeの時にディレクトリが拡張モジュー -ルを含んでいるかどうか判定するために使われれています. +There should be MANIFEST file in the directory for the extension +library. Make empty file now. (3) design the library -まあ,当然なんですけど,どういう機能を実現するかどうかまず設 -計する必要があります.どんなクラスをつくるか,そのクラスには -どんなメソッドがあるか,クラスが提供する定数などについて設計 -します.dbmクラスについてはext/dbm.docを参照してください. +You need to design the library features, before making it. (4) write C code. -拡張モジュール本体となるC言語のソースを書きます.C言語のソー +拡張ライブラリ本体となるC言語のソースを書きます.C言語のソー スがひとつの時には「モジュール名.c」を選ぶと良いでしょう.C 言語のソースが複数の場合には逆に「モジュール名.c」というファ イル名は避ける必要があります.オブジェクトファイルとモジュー ル生成時に中間的に生成される「モジュール名.o」というファイル とが衝突するからです. -Rubyは拡張モジュールをロードする時に「Init_モジュール名」と +Rubyは拡張ライブラリをロードする時に「Init_モジュール名」と いう関数を自動的に実行します.dbmモジュールの場合「Init_dbm」 です.この関数の中でクラス,モジュール,メソッド,定数などの 定義を行います.dbm.cから一部引用します. @@ -525,22 +492,20 @@ Ruby -- Init_dbm() { - /* DBMクラスを定義する */ + /* define DBM class */ cDBM = rb_define_class("DBM", rb_cObject); - /* DBMはEnumerateモジュールをインクルードする */ + /* DBM includes Enumerate module */ rb_include_module(cDBM, rb_mEnumerable); - /* DBMクラスのクラスメソッドopen(): 引数はCの配列で受ける */ + /* DBM has class method open(): arguments are received as C array */ rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1); - /* DBMクラスのメソッドclose(): 引数はなし */ + /* DBM instance method close(): no args */ rb_define_method(cDBM, "close", fdbm_close, 0); - /* DBMクラスのメソッド[]: 引数は1個 */ + /* DBM instance method []: 1 argument */ rb_define_method(cDBM, "[]", fdbm_fetch, 1); : - /* DBMデータを格納するインスタンス変数名のためのID */ - id_dbm = rb_intern("dbm"); } -- @@ -646,11 +611,10 @@ fdbm_indexes(obj, args) らすため struct RArray* で受けていますが,VALUEでも同じこと です. -** 注意事項 +** Notice -Rubyと共有はしないがRubyのオブジェクトを格納する可能性のある -Cの大域変数は以下の関数を使ってRubyインタプリタに変数の存在 -を教えてあげてください.でないとGCでトラブルを起こします. +GC should know about global variables which refers Ruby's objects, but +not exported to the Ruby world. You need to protect them by void rb_global_variable(VALUE *var) @@ -704,22 +668,22 @@ Ruby してくれます.extconf.rbを書き換えるなどしてMakefileの再生成 が必要な時はまたRubyディレクトリでmakeしてください. -(9) rb_debug +(9) debug You may need to rb_debug the module. The modules can be linked statically by adding directory name in the ext/Setup file, so that you can inspect the module by the debugger. -(10) done, now you have the extension module +(10) done, now you have the extension library 後はこっそり使うなり,広く公開するなり,売るなり,ご自由にお -使いください.Rubyの作者は拡張モジュールに関して一切の権利を +使いください.Rubyの作者は拡張ライブラリに関して一切の権利を 主張しません. Appendix A. Rubyのソースコードの分類 Rubyのソースはいくつかに分類することが出来ます.このうちクラ -スライブラリの部分は基本的に拡張モジュールと同じ作り方になっ +スライブラリの部分は基本的に拡張ライブラリと同じ作り方になっ ています.これらのソースは今までの説明でほとんど理解できると 思います. @@ -847,54 +811,63 @@ super オブジェクトをモジュール(で定義されているメソッド)で拡張する. -** 大域変数定義 +** Defining Global Variables void rb_define_variable(char *name, VALUE *var) -RubyとCとで共有するグローバル変数を定義する.変数名が`$'で始 -まらない時には自動的に追加される.nameとしてRubyの識別子とし -て許されない文字(例えば` ')を含む場合にはRubyプログラムから -は見えなくなる. +Defines a global variable which is shared between C and Ruby. If name +contains the character which is not allowed to be part of the symbol, +it can't be seen from Ruby programs. void rb_define_readonly_variable(char *name, VALUE *var) -RubyとCとで共有するread onlyのグローバル変数を定義する.read -onlyであること以外はrb_define_variable()と同じ. +Defines a read-only global variable. Works just like +rb_define_variable(), except defined variable is read-only. void rb_define_virtual_variable(char *name, VALUE (*getter)(), VALUE (*setter)()) -関数によって実現されるRuby変数を定義する.変数が参照された時 -にはgetterが,変数に値がセットされた時にはsetterが呼ばれる. +Defines a virtual variable, whose behavior is defined by pair of C +functions. The getter function is called when the variable is +referred. The setter function is called when the value is set to the +variable. The prototype for getter/setter functions are: + + VALUE getter(ID id) + void setter(VALUE val, ID id) + +The getter function must return the value for the access. void rb_define_hooked_variable(char *name, VALUE *var, VALUE (*getter)(), VALUE (*setter)()) -関数によってhookのつけられたグローバル変数を定義する.変数が -参照された時にはgetterが,関数に値がセットされた時にはsetter -が呼ばれる.getterやsetterに0を指定した時にはhookを指定しな -いのと同じ事になる. +Defines hooked variable. It's virtual variable with C variable. The +getter is called as + + VALUE getter(ID id, VALUE *var) + +returning new value. The setter is called as + + void setter(VALUE val, ID id, VALUE *var) + +GC requires to mark the C global variables which hold Ruby values. void rb_global_variable(VALUE *var) -GCのため,Rubyプログラムからはアクセスされないが, Rubyオブジェ -クトを含む大域変数をマークする. +Tells GC to protect these variables. -** クラス定数 +** Constant Definition - void rb_define_const(VALUE class, char *name, VALUE val) + void rb_define_const(VALUE klass, char *name, VALUE val) -クラス定数を定義する. +Defines a new constant under the class/module. void rb_define_global_const(char *name, VALUE val) -大域定数を定義する. +Defines global contant. This is just work as rb_define_const(cKernal, name, val) -と同じ意味. - -** メソッド定義 +** Method Definition rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc) @@ -1008,50 +981,46 @@ rb_verbose 況の時呼ぶ.インタープリタはコアダンプし直ちに終了する.例外 処理は一切行なわれない. -** Rubyの初期化・実行 +** Initialize and Starts the Interpreter -Rubyをアプリケーションに埋め込む場合には以下のインタフェース -を使う.通常の拡張モジュールには必要ない. +The embedding API are below (not needed for extension libraries): void ruby_init(int argc, char **argv, char **envp) -Rubyインタプリタの初期化を行なう. +Initializes the interpreter. void ruby_run() -Rubyインタプリタを実行する. +Starts execution of the interpreter. void ruby_script(char *name) -Rubyのスクリプト名($0)を設定する. - +Specifies the name of the script ($0). -Appendix B. extconf.rbで使える関数たち +Appendix B. Functions Available in extconf.rb extconf.rbの中では利用可能なコンパイル条件チェックの関数は以 下の通りである. have_library(lib, func) -関数funcを定義しているライブラリlibの存在をチェックする.ラ -イブラリが存在する時,Qtrueを返す. +Checks whether library which contains specified function exists. +Returns true if the library exists. have_func(func) -関数funcの存在をチェックする.funcが標準ではリンクされないラ -イブラリ内のものである時には先にhave_libraryでそのライブラリ -をチェックしておく事.関数が存在する時TRUEを返す. +Checks whether func exists. Returns true if the function exists. To +check functions in the additional library, you need to check that +library first using have_library(). have_header(header) -ヘッダファイルの存在をチェックする.ヘッダファイルが存在する -時TRUEを返す. +Checks for the header files. Returns true if the header file exists. create_makefile(target) -拡張モジュール用のMakefileを生成する.この関数を呼ばなければ -そのモジュールはコンパイルされない.targetはモジュール名を表 -す. +Generates the Makefile for the extension library. If you don't invoke +this method, the compilation will not be done. /* * Local variables: diff --git a/README.EXT.jp b/README.EXT.jp index 9dbd845fa7..87175be853 100644 --- a/README.EXT.jp +++ b/README.EXT.jp @@ -1,6 +1,6 @@ .\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995 -Rubyの拡張モジュールの作り方を説明します. +Rubyの拡張ライブラリの作り方を説明します. 1.基礎知識 @@ -120,8 +120,8 @@ ruby.h 例えば,文字列strの長さを得るためには「RSTRING(str)->len」と し,文字列strをchar*として得るためには「RSTRING(str)->ptr」 -とします.配列の場合には,それぞれ「RARRAY(str)->len」, -「RARRAY(str)->ptr」となります. +とします.配列の場合には,それぞれ「RARRAY(ary)->len」, +「RARRAY(ary)->ptr」となります. Rubyの構造体を直接アクセスする時に気をつけなければならないこ とは,配列や文字列の構造体の中身は参照するだけで,直接変更し @@ -309,7 +309,7 @@ private 2.1.3 定数定義 -拡張モジュールが必要な定数はあらかじめ定義しておいた方が良い +拡張ライブラリが必要な定数はあらかじめ定義しておいた方が良い でしょう.定数を定義する関数は二つあります. void rb_define_const(VALUE class, char *name, VALUE val) @@ -376,9 +376,9 @@ apply 2.2.4 変数/定数を参照/更新する -Cから関数を使って参照・更新できるのは,クラス定数,インスタ -ンス変数です.大域変数は一部のものはCの大域変数としてアクセ -スできます.ローカル変数を参照する方法は公開していません. +Cから関数を使って参照・更新できるのは,定数,インスタンス変 +数です.大域変数は一部のものはCの大域変数としてアクセスでき +ます.ローカル変数を参照する方法は公開していません. オブジェクトのインスタンス変数を参照・更新する関数は以下の通 りです. @@ -388,11 +388,11 @@ C idはrb_intern()で得られるものを使ってください. -クラス定数を参照するには以下の関数を使ってください. +定数を参照するには以下の関数を使ってください. VALUE rb_const_get(VALUE obj, ID id) -クラス定数を新しく定義するためには『2.1.3 定数定義』で紹介さ +定数を新しく定義するためには『2.1.3 定数定義』で紹介さ れている関数を使ってください. 3.RubyとCとの情報共有 @@ -504,7 +504,7 @@ C 4.例題 - dbmパッケージを作る -ここまでの説明でとりあえず拡張モジュールは作れるはずです. +ここまでの説明でとりあえず拡張ライブラリは作れるはずです. Rubyのextディレクトリにすでに含まれているdbmモジュールを例に して段階的に説明します. @@ -523,12 +523,12 @@ Ruby 1.1 % cd ext/dbm % touch MANIFEST -拡張モジュールのディレクトリの下にはMANIFESTというファイルが +拡張ライブラリのディレクトリの下にはMANIFESTというファイルが 必要なので,とりあえず空のファイルを作っておきます.後でこの ファイルには必要なファイル一覧が入ることになります. MANIFESTというファイルは,静的リンクのmakeの時にディレクトリ -が拡張モジュールを含んでいるかどうか判定するために使われれて +が拡張ライブラリを含んでいるかどうか判定するために使われれて います.ダイナミックライブラリを作る場合には必ずしも必要では ありません. @@ -541,14 +541,14 @@ MANIFEST (4) Cコードを書く -拡張モジュール本体となるC言語のソースを書きます.C言語のソー +拡張ライブラリ本体となるC言語のソースを書きます.C言語のソー スがひとつの時には「モジュール名.c」を選ぶと良いでしょう.C 言語のソースが複数の場合には逆に「モジュール名.c」というファ イル名は避ける必要があります.オブジェクトファイルとモジュー ル生成時に中間的に生成される「モジュール名.o」というファイル とが衝突するからです. -Rubyは拡張モジュールをロードする時に「Init_モジュール名」と +Rubyは拡張ライブラリをロードする時に「Init_モジュール名」と いう関数を自動的に実行します.dbmモジュールの場合「Init_dbm」 です.この関数の中でクラス,モジュール,メソッド,定数などの 定義を行います.dbm.cから一部引用します. @@ -762,7 +762,7 @@ extconf.rb 動的リンクライブラリはmake installでRubyライブラリのディレク トリの下にコピーされます.もしモジュールと協調して使うRubyで 記述されたプログラムがあり,Rubyライブラリに置きたい場合には, -拡張モジュール用のディレクトリの下に lib というディレクトリ +拡張ライブラリ用のディレクトリの下に lib というディレクトリ を作り,そこに 拡張子 .rb のファイルを置いておけば同時にイン ストールされます. @@ -775,13 +775,13 @@ extconf.rb (11) できあがり 後はこっそり使うなり,広く公開するなり,売るなり,ご自由にお -使いください.Rubyの作者は拡張モジュールに関して一切の権利を +使いください.Rubyの作者は拡張ライブラリに関して一切の権利を 主張しません. Appendix A. Rubyのソースコードの分類 Rubyのソースはいくつかに分類することが出来ます.このうちクラ -スライブラリの部分は基本的に拡張モジュールと同じ作り方になっ +スライブラリの部分は基本的に拡張ライブラリと同じ作り方になっ ています.これらのソースは今までの説明でほとんど理解できると 思います. @@ -962,11 +962,11 @@ only GCのため,Rubyプログラムからはアクセスされないが, Rubyオブジェ クトを含む大域変数をマークする. -** クラス定数 +** 定数 - void rb_define_const(VALUE class, char *name, VALUE val) + void rb_define_const(VALUE klass, char *name, VALUE val) -クラス定数を定義する. +定数を定義する. void rb_define_global_const(char *name, VALUE val) @@ -1098,7 +1098,7 @@ exception ** Rubyの初期化・実行 Rubyをアプリケーションに埋め込む場合には以下のインタフェース -を使う.通常の拡張モジュールには必要ない. +を使う.通常の拡張ライブラリには必要ない. void ruby_init(int argc, char **argv, char **envp) @@ -1121,7 +1121,7 @@ extconf.rb have_library(lib, func) 関数funcを定義しているライブラリlibの存在をチェックする.ラ -イブラリが存在する時,Qtrueを返す. +イブラリが存在する時,trueを返す. have_func(func) @@ -1132,11 +1132,11 @@ extconf.rb have_header(header) ヘッダファイルの存在をチェックする.ヘッダファイルが存在する -時TRUEを返す. +時trueを返す. create_makefile(target) -拡張モジュール用のMakefileを生成する.この関数を呼ばなければ +拡張ライブラリ用のMakefileを生成する.この関数を呼ばなければ そのモジュールはコンパイルされない.targetはモジュール名を表 す. diff --git a/ToDo b/ToDo index edb238997c..87fd542424 100644 --- a/ToDo +++ b/ToDo @@ -1,5 +1,36 @@ -* non-blocking open/write for thread -* avoid blocking with gethostbyname/gethostbyaddr +Language Spec. + * package or access control for global variables -* format -* freeze or undump to bundle everything in birary format. +* named arguments like foo(nation:="german"). +* multiple return values, yield values. maybe imcompatible + +Hacking Interpreter + +* non-blocking open (e.g. named pipe) for thread +* avoid blocking with gethostbyname/gethostbyaddr +* objectify interpreters +* remove rb_eval() recursions +* syntax tree -> bytecode ??? +* scrambled script, or script filter + +Extension Libraries + +* mod_ruby, FastCGI ruby +* InterBase module +* ptk.rb pTk wrapper that is compatible to tk.rb + +Ruby Libraries + +* CGI.rb +* httplib.rb, urllib.rb, nttplib.rb, etc. +* format like perl's + +Tools + +* extension library maker like XS or SWIG +* freeze or undump to bundle everything + +Misc + +* translate README.EXT fully into English +* publish Ruby books diff --git a/config.guess b/config.guess index d62857905a..d1eb24fcc1 100644 --- a/config.guess +++ b/config.guess @@ -740,6 +740,21 @@ EOF BePC:BeOS:*:*) echo i586-pc-beos exit 0 ;; + + *:Rhapsody:*:*) + arch=`/usr/bin/arch` + case "$arch" in + ppc) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + ;; + i[3456]86) + echo i386-apple-rhapsody${UNAME_RELEASE} + ;; + *) + echo $arch-apple-rhapsody${UNAME_RELEASE} + ;; + esac + exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 diff --git a/configure.in b/configure.in index 6aa2254633..33b43deed2 100644 --- a/configure.in +++ b/configure.in @@ -34,25 +34,37 @@ fat_binary=no AC_ARG_ENABLE( fat-binary, [--enable-fat-binary build a NeXT/Apple Multi Architecture Binary. ], [ fat_binary=$enableval ] ) - if test "$fat_binary" = yes ; then + if test "$fat_binary" = yes ; then AC_MSG_CHECKING( target architecture ) - if test "$host_os" = "rhapsody" ; then - echo -n "Rhapsody: " - if test "$TARGET_ARCHS" = "" ; then - TARGET_ARCHS="ppc i486" + case "$host_os" in + rhapsody*) + echo -n "MacOS X Server: " + if test "$TARGET_ARCHS" = "" ; then + TARGET_ARCHS="ppc i386" fi - else + ;; + nextstep*|openstep*) echo -n "NeXTSTEP/OPENSTEP: " - if test "$TARGET_ARCHS" = "" ; then - if test `/usr/bin/arch` = "m68k" ; then - TARGET_ARCHS="m68k i486" - else - TARGET_ARCHS="m68k `/usr/bin/arch`" - fi + + if test "$host_os" = "rhapsody" ; then + echo -n "Rhapsody: " + if test "$TARGET_ARCHS" = "" ; then + TARGET_ARCHS="ppc i486" + fi + else + echo -n "NeXTSTEP/OPENSTEP: " + if test "$TARGET_ARCHS" = "" ; then + if test `/usr/bin/arch` = "m68k" ; then + TARGET_ARCHS="m68k i486" + else # Black and Native one + TARGET_ARCHS="m68k `/usr/bin/arch`" + fi + fi fi - fi + ;; + esac # /usr/lib/arch_tool -archify_list $TARGET_ARCHS for archs in $TARGET_ARCHS do @@ -163,7 +175,7 @@ AC_REPLACE_FUNCS(dup2 setenv memmove mkdir strcasecmp strerror strftime\ AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall getcwd\ truncate chsize times utimes fcntl lockf setitimer\ setruid seteuid setreuid setrgid setegid setregid\ - setpgrp2 getpgid getgroups getpriority\ + setpgrp2 getpgid setpgid getgroups getpriority\ dlopen sigprocmask sigaction _setjmp setpgrp setsid) if test "$ac_cv_func_strftime" = no; then AC_STRUCT_TIMEZONE diff --git a/dln.c b/dln.c index 0c06a03b12..418bb6b76e 100644 --- a/dln.c +++ b/dln.c @@ -1129,15 +1129,22 @@ dln_strerror() #ifdef _WIN32 static char message[1024]; + int error = GetLastError(); + char *p = message; + p += sprintf(message, "%d: ", error); FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, - GetLastError(), - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - message, - sizeof message, + error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + p, + sizeof message - strlen(message), NULL); + for (p = message; *p; p++) { + if (*p == '\n' || *p == '\r') + *p = ' '; + } return message; #endif } @@ -1213,7 +1220,7 @@ dln_load(file) /* Load file */ if ((handle = LoadLibraryExA(winfile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL) { - printf("LoadLibraryExA\n"); + printf("LoadLibraryExA: %s\n", winfile); goto failed; } diff --git a/enum.c b/enum.c index 61d47613f5..7dd1842126 100644 --- a/enum.c +++ b/enum.c @@ -343,7 +343,11 @@ each_with_index_i(val, indexp) VALUE val; int *indexp; { +#if 0 rb_yield(rb_assoc_new(val, INT2FIX(*indexp))); +#else + rb_yield(rb_ary_concat(val, INT2FIX(*indexp))); +#endif (*indexp)++; return Qnil; } diff --git a/error.c b/error.c index bec8febff0..44ca067472 100644 --- a/error.c +++ b/error.c @@ -274,10 +274,7 @@ exc_initialize(argc, argv, exc) { VALUE mesg; - if (rb_scan_args(argc, argv, "01", &mesg) == 0) { - mesg = rb_str_new(0, 0); - } - else { + if (rb_scan_args(argc, argv, "01", &mesg) == 1) { STR2CSTR(mesg); /* ensure mesg can be converted to String */ } rb_iv_set(exc, "mesg", mesg); @@ -308,7 +305,10 @@ static VALUE exc_to_s(exc) VALUE exc; { - return rb_iv_get(exc, "mesg"); + VALUE mesg = rb_iv_get(exc, "mesg"); + + if (NIL_P(mesg)) return rb_class_path(CLASS_OF(exc)); + return mesg; } static VALUE diff --git a/eval.c b/eval.c index 79ce7abed7..9679eeb102 100644 --- a/eval.c +++ b/eval.c @@ -97,41 +97,6 @@ rb_clear_cache() } } -static int cache_conflict; -static int eval_called; - -static int -count_cent() -{ - struct cache_entry *ent, *end; - int n = 0, n2 = 0; - int p = 0; - - fprintf(stderr, "\n|"); - ent = cache; end = ent + CACHE_SIZE; - while (ent < end) { - fprintf(stderr, (ent->klass != 0)?"*":" "); - p++; - if (p % 80 == 0) { - break; - } - ent++; - } - fprintf(stderr, "|\n|"); - p = 0; ent = cache; - while (ent < end) { - if (ent->klass != 0) {n++; n2++;} - p++; - if (p % 24 == 0) { - fprintf(stderr, "%c", n2?(n2+'0'):' '); - n2 = 0; - } - ent++; - } - fprintf(stderr, "|\n"); - return n; -} - static void rb_clear_cache_by_id(id) ID id; @@ -433,7 +398,10 @@ static struct SCOPE *top_scope; _frame.argc = 0; \ ruby_frame = &_frame; \ -#define POP_FRAME() ruby_frame = _frame.prev; } +#define POP_FRAME() \ + ruby_sourcefile = _frame.file; \ + ruby_sourceline = _frame.line; \ + ruby_frame = _frame.prev; } struct BLOCK { NODE *var; @@ -873,7 +841,9 @@ error_print() ep = RARRAY(errat); for (i=1; ilen; i++) { - fprintf(stderr, "\tfrom %s\n", RSTRING(ep->ptr[i])->ptr); + if (TYPE(ep->ptr[i]) == T_STRING) { + 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); @@ -1016,11 +986,6 @@ ruby_run() #endif exec_end_proc(); rb_gc_call_finalizer_at_exit(); -#if 1 - fprintf(stderr, "%d/%d(%d)\n", count_cent(), CACHE_SIZE, cache_conflict); -#else - fprintf(stderr, "rb_eval() called %d times\n", eval_called); -#endif } else { ex = state; @@ -1666,8 +1631,6 @@ rb_eval(self, node) #define RETURN(v) { result = (v); goto finish; } - eval_called++; - again: if (!node) RETURN(Qnil); @@ -3030,12 +2993,12 @@ rb_f_raise(argc, argv) } if (!NIL_P(mesg)) { - if (n >= 2) { - mesg = rb_funcall(etype, rb_intern("new"), 1, mesg); - } - else if (TYPE(mesg) == T_STRING) { + if (n == 1 && TYPE(mesg) == T_STRING) { mesg = rb_exc_new3(rb_eRuntimeError, mesg); } + else if (n == 1 || n == 2) { + mesg = rb_funcall(etype, rb_intern("new"), n-1, mesg); + } if (!rb_obj_is_kind_of(mesg, rb_eException)) { rb_raise(rb_eTypeError, "exception object expected"); } @@ -3835,22 +3798,13 @@ rb_call(klass, recv, mid, argc, argv, scope) noex = ent->noex; body = ent->method; } - else { - if (ent->mid) { - fprintf(stderr, "%s#%s -> %s#%s (%d)\n", rb_class2name(ent->klass), - rb_id2name(ent->mid), - rb_class2name(klass), - rb_id2name(id), ent-cache); - cache_conflict++; - } - if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { + else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { if (scope == 3) { rb_raise(rb_eNameError, "super: no superclass method `%s'", rb_id2name(mid)); } return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0); } - } /* receiver specified form for private method */ if ((noex & NOEX_PRIVATE) && scope == 0) @@ -4537,7 +4491,7 @@ rb_f_require(obj, fname) VALUE obj, fname; { char *ext, *file, *feature, *buf; /* OK */ - VALUE load; + volatile VALUE load; rb_secure(4); Check_SafeStr(fname); @@ -5510,7 +5464,7 @@ method_call(argc, argv, method) Data_Get_Struct(method, struct METHOD, data); PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT); PUSH_TAG(PROT_NONE); - if (FL_TEST(data->recv, FL_TAINT)) { + if (FL_TEST(data->recv, FL_TAINT) || FL_TEST(method, FL_TAINT)) { FL_SET(method, FL_TAINT); if (safe_level < 4) safe_level = 4; } @@ -6543,6 +6497,34 @@ static VALUE rb_thread_raise _((int, VALUE*, VALUE)); #define SCOPE_SHARED FL_USER1 +#if defined(HAVE_SETITIMER) && !defined(__BOW__) +static int thread_init = 0; + +void +thread_start_timer() +{ + struct itimerval tval; + + if (!thread_init) return; + tval.it_interval.tv_sec = 0; + tval.it_interval.tv_usec = 100000; + tval.it_value = tval.it_interval; + setitimer(ITIMER_VIRTUAL, &tval, NULL); +} + +void +thread_stop_timer() +{ + struct itimerval tval; + + if (!thread_init) return; + tval.it_interval.tv_sec = 0; + tval.it_interval.tv_usec = 0; + tval.it_value = tval.it_interval; + setitimer(ITIMER_VIRTUAL, &tval, NULL); +} +#endif + static VALUE rb_thread_create_0(fn, arg, klass) VALUE (*fn)(); @@ -6554,11 +6536,7 @@ rb_thread_create_0(fn, arg, klass) int state; #if defined(HAVE_SETITIMER) && !defined(__BOW__) - static init = 0; - - if (!init) { - struct itimerval tval; - + if (!thread_init) { #ifdef POSIX_SIGNAL posix_signal(SIGVTALRM, catch_timer); posix_signal(SIGALRM, catch_timer); @@ -6567,11 +6545,8 @@ rb_thread_create_0(fn, arg, klass) signal(SIGALRM, catch_timer); #endif - tval.it_interval.tv_sec = 0; - tval.it_interval.tv_usec = 100000; - tval.it_value = tval.it_interval; - setitimer(ITIMER_VIRTUAL, &tval, NULL); - init = 1; + thread_init = 1; + thread_start_timer(); } #endif diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index b60951538d..e1623529b6 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -313,11 +313,11 @@ archdir = $(pkglibdir)/@arch@ mfile.printf $objs.join(" ") mfile.printf "\n" - mfile.printf "\ -TARGET = %s.%s + mfile.printf << EOS +TARGET = #{target}.#{$static ? "a" : "@DLEXT@"} -INSTALL = %s@INSTALL@ -INSTALL_DATA = %s@INSTALL_DATA@ +INSTALL = #{$dots}@INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ binsuffix = @binsuffix@ @@ -328,16 +328,15 @@ clean:; @rm -f *.o *.a *.so *.sl @rm -f core ruby$(binsuffix) *~ realclean: clean -", target, - if $static then "a" else "@DLEXT@" end, $dots, $dots +EOS - mfile.printf "\ + mfile.printf <as.basic.flags |= FL_MARK; + if (FL_TEST(obj, FL_EXIVAR)) { + return rb_mark_generic_ivar((VALUE)obj); + } + switch (obj->as.basic.flags & T_MASK) { case T_NIL: case T_FIXNUM: @@ -616,7 +620,7 @@ rb_gc_mark(ptr) #define MIN_FREE_OBJ 512 -static void obj_free(); +static void obj_free _((VALUE)); static void gc_sweep() @@ -693,6 +697,10 @@ obj_free(obj) if (need_call_final && FL_TEST(obj, FL_FINALIZE)) { run_final(obj); } + if (FL_TEST(obj, FL_EXIVAR)) { + rb_free_generic_ivar((VALUE)obj); + } + switch (RANY(obj)->as.basic.flags & T_MASK) { case T_OBJECT: if (RANY(obj)->as.object.iv_tbl) { @@ -871,11 +879,14 @@ rb_gc() for (list = Global_List; list; list = list->next) { rb_gc_mark(*list->varptr); } - rb_gc_mark_global_tbl(); + mark_tbl(rb_class_tbl); rb_gc_mark_trap_list(); + /* mark generic instance variables for special constants */ + rb_mark_generic_ivar_tbl(); + gc_sweep(); dont_gc--; } @@ -1070,6 +1081,7 @@ id2ref(obj, id) { unsigned long ptr = NUM2UINT(id); + rb_secure(4); if (FIXNUM_P(ptr)) return (VALUE)ptr; if (ptr == Qtrue) return Qtrue; if (ptr == Qfalse) return Qfalse; diff --git a/hash.c b/hash.c index d7d6f4de2c..6ce5313202 100644 --- a/hash.c +++ b/hash.c @@ -1027,7 +1027,7 @@ static VALUE env_each(hash) VALUE hash; { - VALUE ary = env_keys(); + volatile VALUE ary = env_keys(); VALUE *ptr = RARRAY(ary)->ptr; int len = RARRAY(ary)->len; @@ -1044,7 +1044,7 @@ env_each(hash) static VALUE env_delete_if() { - VALUE ary; + volatile VALUE ary; VALUE *ptr; int len; @@ -1124,7 +1124,7 @@ env_has_value(dmy, value) VALUE dmy, value; { char **env; - VALUE ary; + volatile VALUE ary; if (TYPE(value) != T_STRING) return Qfalse; ary = rb_ary_new(); @@ -1168,7 +1168,7 @@ env_to_hash(obj) VALUE obj; { VALUE hash = rb_hash_new(); - VALUE ary = env_keys(); + volatile VALUE ary = env_keys(); VALUE *ptr = RARRAY(ary)->ptr; int len = RARRAY(ary)->len; diff --git a/intern.h b/intern.h index 86a74b844e..364e97e0d7 100644 --- a/intern.h +++ b/intern.h @@ -67,6 +67,7 @@ VALUE rb_define_module_id _((ID)); VALUE rb_mod_included_modules _((VALUE)); VALUE rb_mod_ancestors _((VALUE)); VALUE rb_class_instance_methods _((int, VALUE*, VALUE)); +VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE)); VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE)); VALUE rb_obj_singleton_methods _((VALUE)); void rb_define_method_id _((VALUE, ID, VALUE (*)(), int)); @@ -100,9 +101,6 @@ VALUE rb_dvar_defined _((ID)); VALUE rb_dvar_ref _((ID)); void rb_dvar_asgn _((ID, VALUE)); void rb_dvar_push _((ID, VALUE)); -void ruby_init _((void)); -void ruby_options _((int, char**)); -void ruby_run _((void)); VALUE rb_eval_cmd _((VALUE, VALUE)); VALUE rb_trap_eval _((VALUE, int)); int rb_respond_to _((VALUE, ID)); @@ -119,6 +117,8 @@ VALUE rb_class_new_instance _((int, VALUE*, VALUE)); VALUE rb_f_lambda _((void)); void rb_set_end_proc _((void (*)(),VALUE)); void rb_gc_mark_threads _((void)); +void thread_start_timer _((void)); +void thread_stop_timer _((void)); void rb_thread_schedule _((void)); void rb_thread_wait_fd _((int)); void rb_thread_fd_writable _((int)); @@ -175,9 +175,7 @@ VALUE rb_num2fix _((VALUE)); VALUE rb_fix2str _((VALUE, int)); VALUE rb_fix_upto _((VALUE, VALUE)); /* object.c */ -VALUE rb_equal _((VALUE, VALUE)); int rb_eql _((VALUE, VALUE)); -VALUE rb_obj_equal _((VALUE, VALUE)); VALUE rb_any_to_s _((VALUE)); VALUE rb_inspect _((VALUE)); VALUE rb_obj_is_instance_of _((VALUE, VALUE)); @@ -191,7 +189,6 @@ VALUE rb_Integer _((VALUE)); VALUE rb_Float _((VALUE)); VALUE rb_String _((VALUE)); VALUE rb_Array _((VALUE)); -double rb_num2dbl _((VALUE)); /* parse.y */ extern int ruby_sourceline; extern char *ruby_sourcefile; @@ -291,6 +288,9 @@ VALUE rb_f_untrace_var _((int, VALUE*)); VALUE rb_gvar_set2 _((char*, VALUE)); VALUE rb_f_global_variables _((void)); void rb_alias_variable _((ID, ID)); +void rb_mark_generic_ivar _((VALUE)); +void rb_mark_generic_ivar_tbl _((void)); +void rb_free_generic_ivar _((VALUE)); VALUE rb_ivar_get _((VALUE, ID)); VALUE rb_ivar_set _((VALUE, ID, VALUE)); VALUE rb_ivar_defined _((VALUE, ID)); diff --git a/io.c b/io.c index 1da75b6411..7144f59fa8 100644 --- a/io.c +++ b/io.c @@ -2544,7 +2544,7 @@ arg_read(argc, argv) next_p = 1; goto retry; } - if (NIL_P(tmp)) return str; + if (NIL_P(tmp) || RSTRING(tmp)->len == 0) return str; else if (NIL_P(str)) str = tmp; else rb_str_cat(str, RSTRING(tmp)->ptr, RSTRING(tmp)->len); if (argc == 0) { diff --git a/lib/debug.rb b/lib/debug.rb index 497d163024..90270a3fe7 100644 --- a/lib/debug.rb +++ b/lib/debug.rb @@ -267,6 +267,6 @@ class DEBUGGER__ CONTEXT = new end -set_trace_func proc{|event, file, line, id, binding, klass| - DEBUGGER__::CONTEXT.trace_func event, file, line, id, binding, klass +set_trace_func proc{|event, file, line, id, binding| + DEBUGGER__::CONTEXT.trace_func event, file, line, id, binding } diff --git a/lib/delegate.rb b/lib/delegate.rb index d784586702..594c500cab 100644 --- a/lib/delegate.rb +++ b/lib/delegate.rb @@ -20,24 +20,32 @@ class Delegator def initialize(obj) preserved = ::Kernel.instance_methods + preserved -= ["to_s","to_a","inspect","==","=~","==="] for t in self.type.ancestors preserved |= t.instance_methods + preserved |= t.private_instance_methods + preserved |= t.protected_instance_methods break if t == Delegator end - preserved -= ["to_s","to_a","inspect","==","=~","==="] for method in obj.methods next if preserved.include? method - eval < true - foo.test # raise error! - + p foo.test == foo2.test # => true + foo2.error # raise error! end diff --git a/lib/mailread.rb b/lib/mailread.rb index 8ec951e754..5e46606c09 100644 --- a/lib/mailread.rb +++ b/lib/mailread.rb @@ -1,7 +1,7 @@ class Mail def initialize(f) - unless f.kind_of?(IO) + unless defined? f.gets f = open(f, "r") opened = true end diff --git a/lib/mkmf.rb b/lib/mkmf.rb index 0aa9d98b9c..218b3b19f6 100644 --- a/lib/mkmf.rb +++ b/lib/mkmf.rb @@ -289,7 +289,8 @@ LDSHARED = #{CONFIG["LDSHARED"]} prefix = #{CONFIG["prefix"]} exec_prefix = #{CONFIG["exec_prefix"]} -libdir = #{$archdir} +libdir = #{$libdir} +archdir = #{$archdir} #### End of system configuration section. #### @@ -312,11 +313,12 @@ clean:; @rm -f *.o *.so *.sl realclean: clean -install: $(libdir)/$(TARGET) +install: $(archdir)/$(TARGET) -$(libdir)/$(TARGET): $(TARGET) +$(archdir)/$(TARGET): $(TARGET) @test -d $(libdir) || mkdir $(libdir) - $(INSTALL) $(TARGET) $(libdir)/$(TARGET) + @test -d $(archdir) || mkdir $(archdir) + $(INSTALL) $(TARGET) $(archdir)/$(TARGET) EOMF install_rb(mfile) mfile.printf "\n" diff --git a/lib/pstore.rb b/lib/pstore.rb index f075dbc8bb..2aa9864b58 100644 --- a/lib/pstore.rb +++ b/lib/pstore.rb @@ -110,6 +110,7 @@ class PStore @abort = false end ensure + @table = nil @transaction = false end value diff --git a/misc/README b/misc/README new file mode 100644 index 0000000000..adc119d02e --- /dev/null +++ b/misc/README @@ -0,0 +1,5 @@ +README this file +inf-ruby.el program to run ruby under emacs +ruby-mode.el ruby mode for emacs +rubydb2x.el ruby debugger support for emacs 19.2x or before +rubydb3x.el ruby debugger support for emacs 19.3x or later diff --git a/misc/inf-ruby.el b/misc/inf-ruby.el new file mode 100644 index 0000000000..8668f1d217 --- /dev/null +++ b/misc/inf-ruby.el @@ -0,0 +1,313 @@ +(J;;;(B (J-*-Emacs-Lisp-*-(B +;;; +;;; $Id$ +;;; $Author$ +;;; $Date$ +;;; +;;; Inferior Ruby Mode - ruby process in a buffer. +;;; adapted from cmuscheme.el +;;; +;;; Usage: +;;; +;;; (0) check ruby-program-name variable that can run your environment. +;;; +;;; (1) modify .emacs to use ruby-mode +;;; for example : +;;; +;;; (autoload 'ruby-mode "ruby-mode" +;;; "Mode for editing ruby source files") +;;; (setq auto-mode-alist +;;; (append '(("\\.rb$" . ruby-mode)) auto-mode-alist)) +;;; (setq interpreter-mode-alist (append '(("^#!.*ruby" . ruby-mode)) +;;; interpreter-mode-alist)) +;;; +;;; (2) set to road inf-ruby and set inf-ruby key definition in ruby-mode. +;;; +;;; (autoload 'run-ruby "inf-ruby" +;;; "Run an inferior Ruby process") +;;; (autoload 'inf-ruby-keys "inf-ruby" +;;; "Set local key defs for inf-ruby in ruby-mode") +;;; (add-hook 'ruby-mode-hook +;;; '(lambda () +;;; (inf-ruby-keys) +;;; )) +;;; +;;; HISTORY +;;; senda - 8 Apr 1998: Created. +;;; $Log$ +;;; Revision 1.1.2.1 1998/12/16 07:30:36 matz +;;; first public release of 1.1d (pre1.2) series +;;; +;;; Revision 1.4 1998/05/20 02:45:58 senda +;;; default program to irb +;;; +;;; Revision 1.3 1998/04/10 04:11:30 senda +;;; modification by Matsumoto san (1.1b9_09) +;;; remove-in-string defined +;;; global variable : +;;; inferior-ruby-first-prompt-pattern +;;; inferior-ruby-prompt-pattern +;;; defined +;;; +;;; Revision 1.2 1998/04/09 07:53:42 senda +;;; remove M-C-x in inferior-ruby-mode +;;; +;;; Revision 1.1 1998/04/09 07:28:36 senda +;;; Initial revision +;;; +;;; + +(require 'comint) +(require 'ruby-mode) + +;; +;; you may change these variables +;; +;(defvar ruby-program-name "rbc --noreadline" +; "*Program invoked by the run-ruby command") +; +;(defvar inferior-ruby-first-prompt-pattern "^rbc0> *" +; "first prompt regex pattern of ruby interpreter.") +; +;(defvar inferior-ruby-prompt-pattern "^\\(rbc.[>*\"'] *\\)+" +; "prompt regex pattern of ruby interpreter.") + +;;;; for irb +(defvar ruby-program-name "irb --inf-ruby-mode" + "*Program invoked by the run-ruby command") + +(defvar inferior-ruby-first-prompt-pattern "^irb(.*)[0-9:]+0> *" + "first prompt regex pattern of ruby interpreter.") + +(defvar inferior-ruby-prompt-pattern "^\\(irb(.*)[0-9:]+[>*\"'] *\\)+" + "prompt regex pattern of ruby interpreter.") + +;; +;; mode variables +;; +(defvar inferior-ruby-mode-hook nil + "*Hook for customising inferior-ruby mode.") +(defvar inferior-ruby-mode-map nil + "*Mode map for inferior-ruby-mode") + +(cond ((not inferior-ruby-mode-map) + (setq inferior-ruby-mode-map + (copy-keymap comint-mode-map)) +; (define-key inferior-ruby-mode-map "\M-\C-x" ;gnu convention +; 'ruby-send-definition) +; (define-key inferior-ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp) + (define-key inferior-ruby-mode-map "\C-c\C-l" 'ruby-load-file) +)) + +(defun inf-ruby-keys () + "Set local key defs for inf-ruby in ruby-mode" + (define-key ruby-mode-map "\M-\C-x" 'ruby-send-definition) +; (define-key ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp) + (define-key ruby-mode-map "\C-c\C-e" 'ruby-send-definition) + (define-key ruby-mode-map "\C-c\M-e" 'ruby-send-definition-and-go) + (define-key ruby-mode-map "\C-c\C-r" 'ruby-send-region) + (define-key ruby-mode-map "\C-c\M-r" 'ruby-send-region-and-go) + (define-key ruby-mode-map "\C-c\C-z" 'switch-to-ruby) + (define-key ruby-mode-map "\C-c\C-l" 'ruby-load-file) + (define-key ruby-mode-map "\C-c\C-s" 'run-ruby) +) + +(defvar ruby-buffer nil "current ruby (actually irb) process buffer.") + +(defun inferior-ruby-mode () + "Major mode for interacting with an inferior ruby (irb) process. + +The following commands are available: +\\{inferior-ruby-mode-map} + +A ruby process can be fired up with M-x run-ruby. + +Customisation: Entry to this mode runs the hooks on comint-mode-hook and +inferior-ruby-mode-hook (in that order). + +You can send text to the inferior ruby process from other buffers containing +Ruby source. + switch-to-ruby switches the current buffer to the ruby process buffer. + ruby-send-definition sends the current definition to the ruby process. + ruby-send-region sends the current region to the ruby process. + + ruby-send-definition-and-go, ruby-send-region-and-go, + switch to the ruby process buffer after sending their text. +For information on running multiple processes in multiple buffers, see +documentation for variable ruby-buffer. + +Commands: +Return after the end of the process' output sends the text from the + end of process to point. +Return before the end of the process' output copies the sexp ending at point + to the end of the process' output, and sends it. +Delete converts tabs to spaces as it moves back. +Tab indents for ruby; with argument, shifts rest + of expression rigidly with the current line. +C-M-q does Tab on each line starting within following expression. +Paragraphs are separated only by blank lines. # start comments. +If you accidentally suspend your process, use \\[comint-continue-subjob] +to continue it." + (interactive) + (comint-mode) + ;; Customise in inferior-ruby-mode-hook + ;(setq comint-prompt-regexp "^[^>\n]*>+ *") + (setq comint-prompt-regexp inferior-ruby-prompt-pattern) + ;;(scheme-mode-variables) + (ruby-mode-variables) + (setq major-mode 'inferior-ruby-mode) + (setq mode-name "Inferior Ruby") + (setq mode-line-process '(":%s")) + (use-local-map inferior-ruby-mode-map) + (setq comint-input-filter (function ruby-input-filter)) + (setq comint-get-old-input (function ruby-get-old-input)) + (run-hooks 'inferior-ruby-mode-hook)) + +(defvar inferior-ruby-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'" + "*Input matching this regexp are not saved on the history list. +Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.") + +(defun ruby-input-filter (str) + "Don't save anything matching inferior-ruby-filter-regexp" + (not (string-match inferior-ruby-filter-regexp str))) + +;; adapted from replace-in-string in XEmacs (subr.el) +(defun remove-in-string (str regexp) + "Remove all matches in STR for REGEXP and returns the new string." + (let ((rtn-str "") (start 0) match prev-start) + (while (setq match (string-match regexp str start)) + (setq prev-start start + start (match-end 0) + rtn-str (concat rtn-str (substring str prev-start match)))) + (concat rtn-str (substring str start)))) + +(defun ruby-get-old-input () + "Snarf the sexp ending at point" + (save-excursion + (let ((end (point))) + (re-search-backward inferior-ruby-first-prompt-pattern) + (remove-in-string (buffer-substring (point) end) + inferior-ruby-prompt-pattern) + ))) + +(defun ruby-args-to-list (string) + (let ((where (string-match "[ \t]" string))) + (cond ((null where) (list string)) + ((not (= where 0)) + (cons (substring string 0 where) + (ruby-args-to-list (substring string (+ 1 where) + (length string))))) + (t (let ((pos (string-match "[^ \t]" string))) + (if (null pos) + nil + (ruby-args-to-list (substring string pos + (length string))))))))) + +(defun run-ruby (cmd) + "Run an inferior Ruby process, input and output via buffer *ruby*. +If there is a process already running in `*ruby*', switch to that buffer. +With argument, allows you to edit the command line (default is value +of `ruby-program-name'). Runs the hooks `inferior-ruby-mode-hook' +\(after the `comint-mode-hook' is run). +\(Type \\[describe-mode] in the process buffer for a list of commands.)" + + (interactive (list (if current-prefix-arg + (read-string "Run Ruby: " ruby-program-name) + ruby-program-name))) + (if (not (comint-check-proc "*ruby*")) + (let ((cmdlist (ruby-args-to-list cmd))) + (set-buffer (apply 'make-comint "ruby" (car cmdlist) + nil (cdr cmdlist))) + (inferior-ruby-mode))) + (setq ruby-program-name cmd) + (setq ruby-buffer "*ruby*") + (pop-to-buffer "*ruby*")) + +(defun ruby-send-region (start end) + "Send the current region to the inferior Ruby process." + (interactive "r") + (comint-send-region (ruby-proc) start end) + (comint-send-string (ruby-proc) "\n")) + +(defun ruby-send-definition () + "Send the current definition to the inferior Ruby process." + (interactive) + (save-excursion + (ruby-end-of-defun) + (let ((end (point))) + (ruby-beginning-of-defun) + (ruby-send-region (point) end)))) + +;(defun ruby-send-last-sexp () +; "Send the previous sexp to the inferior Ruby process." +; (interactive) +; (ruby-send-region (save-excursion (backward-sexp) (point)) (point))) + +(defun switch-to-ruby (eob-p) + "Switch to the ruby process buffer. +With argument, positions cursor at end of buffer." + (interactive "P") + (if (get-buffer ruby-buffer) + (pop-to-buffer ruby-buffer) + (error "No current process buffer. See variable ruby-buffer.")) + (cond (eob-p + (push-mark) + (goto-char (point-max))))) + +(defun ruby-send-region-and-go (start end) + "Send the current region to the inferior Ruby process. +Then switch to the process buffer." + (interactive "r") + (ruby-send-region start end) + (switch-to-ruby t)) + +(defun ruby-send-definition-and-go () + "Send the current definition to the inferior Ruby. +Then switch to the process buffer." + (interactive) + (ruby-send-definition) + (switch-to-ruby t)) + +(defvar ruby-source-modes '(ruby-mode) + "*Used to determine if a buffer contains Ruby source code. +If it's loaded into a buffer that is in one of these major modes, it's +considered a ruby source file by ruby-load-file. +Used by these commands to determine defaults.") + +(defvar ruby-prev-l/c-dir/file nil + "Caches the last (directory . file) pair. +Caches the last pair used in the last ruby-load-file command. +Used for determining the default in the +next one.") + +(defun ruby-load-file (file-name) + "Load a Ruby file into the inferior Ruby process." + (interactive (comint-get-source "Load Ruby file: " ruby-prev-l/c-dir/file + ruby-source-modes t)) ; T because LOAD + ; needs an exact name + (comint-check-source file-name) ; Check to see if buffer needs saved. + (setq ruby-prev-l/c-dir/file (cons (file-name-directory file-name) + (file-name-nondirectory file-name))) + (comint-send-string (ruby-proc) (concat "(load \"" + file-name + "\"\)\n"))) + +(defun ruby-proc () + "Returns the current ruby process. See variable ruby-buffer." + (let ((proc (get-buffer-process (if (eq major-mode 'inferior-ruby-mode) + (current-buffer) + ruby-buffer)))) + (or proc + (error "No current process. See variable ruby-buffer")))) + +;;; Do the user's customisation... + +(defvar inf-ruby-load-hook nil + "This hook is run when inf-ruby is loaded in. +This is a good place to put keybindings.") + +(run-hooks 'inf-ruby-load-hook) + +(provide 'inf-ruby) + +;;; inf-ruby.el ends here diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el new file mode 100644 index 0000000000..d202561402 --- /dev/null +++ b/misc/ruby-mode.el @@ -0,0 +1,691 @@ +;;; +;;; ruby-mode.el - +;;; +;;; $Author$ +<<<<<<< ruby-mode.el +;;; $Date$ +======= +;;; $Date$ +>>>>>>> 1.1.1.2.2.23 +;;; created at: Fri Feb 4 14:49:13 JST 1994 +;;; + +<<<<<<< ruby-mode.el +(defconst ruby-mode-revision "$Revision$") +======= +(defconst ruby-mode-revision "$Revision$") +>>>>>>> 1.1.1.2.2.23 + +(defconst ruby-mode-version + (progn + (string-match "[0-9.]+" ruby-mode-revision) + (substring ruby-mode-revision (match-beginning 0) (match-end 0)))) + +(defconst ruby-block-beg-re + "class\\|module\\|def\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin\\|do" + ) + +(defconst ruby-indent-beg-re + "\\(\\s *\\(class\\|module\\|def\\)\\)\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin" + ) + +(defconst ruby-modifier-re + "if\\|unless\\|while\\|until" + ) + +(defconst ruby-block-mid-re + "then\\|else\\|elsif\\|when\\|rescue\\|ensure" + ) + +(defconst ruby-block-op-re + "and\\|or\\|not" + ) + +(defconst ruby-block-end-re "end") + +(defconst ruby-delimiter + (concat "[?$/%(){}#\"'`.:]\\|\\[\\|\\]\\|\\<\\(" + ruby-block-beg-re + "\\|" ruby-block-end-re + "\\)\\>\\|^=begin") + ) + +(defconst ruby-negative + (concat "^[ \t]*\\(\\(" ruby-block-mid-re "\\)\\>\\|\\(" + ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)") + ) + +(defconst ruby-operator-chars ",.+*/%-&|^~=<>:") +(defconst ruby-operator-re (concat "[" ruby-operator-chars "]")) + +(defconst ruby-symbol-chars "a-zA-Z0-9_") +(defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]")) + +(defvar ruby-mode-abbrev-table nil + "Abbrev table in use in ruby-mode buffers.") + +(define-abbrev-table 'ruby-mode-abbrev-table ()) + +(defvar ruby-mode-map nil "Keymap used in ruby mode.") + +(if ruby-mode-map + nil + (setq ruby-mode-map (make-sparse-keymap)) + (define-key ruby-mode-map "{" 'ruby-electric-brace) + (define-key ruby-mode-map "}" 'ruby-electric-brace) + (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun) + (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun) + (define-key ruby-mode-map "\e\C-b" 'ruby-beginning-of-block) + (define-key ruby-mode-map "\e\C-f" 'ruby-end-of-block) + (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block) + (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block) + (define-key ruby-mode-map "\t" 'ruby-indent-command) + (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end) + (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent) + (define-key ruby-mode-map "\C-m" 'newline)) + +(defvar ruby-mode-syntax-table nil + "Syntax table in use in ruby-mode buffers.") + +(if ruby-mode-syntax-table + () + (setq ruby-mode-syntax-table (make-syntax-table)) + (modify-syntax-entry ?\' "\"" ruby-mode-syntax-table) + (modify-syntax-entry ?\" "\"" ruby-mode-syntax-table) + (modify-syntax-entry ?\` "\"" ruby-mode-syntax-table) + (modify-syntax-entry ?# "<" ruby-mode-syntax-table) + (modify-syntax-entry ?\n ">" ruby-mode-syntax-table) + (modify-syntax-entry ?\\ "\\" ruby-mode-syntax-table) + (modify-syntax-entry ?$ "/" ruby-mode-syntax-table) + (modify-syntax-entry ?? "_" ruby-mode-syntax-table) + (modify-syntax-entry ?_ "_" ruby-mode-syntax-table) + (modify-syntax-entry ?< "." ruby-mode-syntax-table) + (modify-syntax-entry ?> "." ruby-mode-syntax-table) + (modify-syntax-entry ?& "." ruby-mode-syntax-table) + (modify-syntax-entry ?| "." ruby-mode-syntax-table) + (modify-syntax-entry ?% "." ruby-mode-syntax-table) + (modify-syntax-entry ?= "." ruby-mode-syntax-table) + (modify-syntax-entry ?/ "." ruby-mode-syntax-table) + (modify-syntax-entry ?+ "." ruby-mode-syntax-table) + (modify-syntax-entry ?* "." ruby-mode-syntax-table) + (modify-syntax-entry ?- "." ruby-mode-syntax-table) + (modify-syntax-entry ?\; "." ruby-mode-syntax-table) + (modify-syntax-entry ?\( "()" ruby-mode-syntax-table) + (modify-syntax-entry ?\) ")(" ruby-mode-syntax-table) + (modify-syntax-entry ?\{ "(}" ruby-mode-syntax-table) + (modify-syntax-entry ?\} "){" ruby-mode-syntax-table) + (modify-syntax-entry ?\[ "(]" ruby-mode-syntax-table) + (modify-syntax-entry ?\] ")[" ruby-mode-syntax-table) + ) + +(defvar ruby-indent-level 2 + "*Indentation of ruby statements.") + +(defun ruby-mode-variables () + (set-syntax-table ruby-mode-syntax-table) + (setq local-abbrev-table ruby-mode-abbrev-table) + (make-local-variable 'indent-line-function) + (setq indent-line-function 'ruby-indent-line) + (make-local-variable 'require-final-newline) + (setq require-final-newline t) + (make-variable-buffer-local 'comment-start) + (setq comment-start "# ") + (make-variable-buffer-local 'comment-end) + (setq comment-end "") + (make-variable-buffer-local 'comment-column) + (setq comment-column 32) + (make-variable-buffer-local 'comment-start-skip) + (setq comment-start-skip "\\(^\\|\\s-\\);?#+ *") + (make-local-variable 'parse-sexp-ignore-comments) + (setq parse-sexp-ignore-comments t)) + +(defun ruby-mode () + "Major mode for editing ruby scripts. +\\[ruby-indent-command] properly indents subexpressions of multi-line +class, module, def, if, while, for, do, and case statements, taking +nesting into account. + +The variable ruby-indent-level controls the amount of indentation. +\\{ruby-mode-map}" + (interactive) + (kill-all-local-variables) + (use-local-map ruby-mode-map) + (setq mode-name "Ruby") + (setq major-mode 'ruby-mode) + (ruby-mode-variables) + (run-hooks 'ruby-mode-hook)) + +(defun ruby-current-indentation () + (save-excursion + (beginning-of-line) + (back-to-indentation) + (current-column))) + +(defun ruby-indent-line (&optional flag) + "Correct indentation of the current ruby line." + (ruby-indent-to (ruby-calculate-indent))) + +(defun ruby-indent-command () + (interactive) + (ruby-indent-line t)) + +(defun ruby-indent-to (x) + (if x + (let (shift top beg) + (and (< x 0) + (error "invalid nest")) + (setq shift (current-column)) + (beginning-of-line) + (setq beg (point)) + (back-to-indentation) + (setq top (current-column)) + (skip-chars-backward " \t") + (cond + ((>= x shift) + (setq shift 0)) + ((>= shift top) + (setq shift (- shift top))) + (t (setq shift 0))) + (if (and (bolp) + (= x top)) + (move-to-column (+ x shift)) + (move-to-column top) + (delete-region beg (point)) + (beginning-of-line) + (indent-to x) + (move-to-column (+ x shift)))))) + +(defun ruby-expr-beg (&optional modifier pnt) + (save-excursion + (if (looking-at "\\?") + (progn + (or (bolp) (forward-char -1)) + (not (looking-at "\\sw"))) + (store-match-data nil) + (skip-chars-backward " \t") + (or (bolp) (forward-char -1)) + (or (bolp) + (looking-at ruby-operator-re) + (looking-at "[\\[({]") + (and (not modifier) (looking-at "[!?]")) + (and (looking-at ruby-symbol-re) + (forward-word -1) + (if (and (not modifier) (bolp)) + t + (if (or (looking-at ruby-block-beg-re) + (looking-at ruby-block-op-re) + (looking-at ruby-block-mid-re)) + (progn + (goto-char (match-end 0)) + (looking-at "\\>"))))))))) + +(defun ruby-parse-region (start end) + (let ((indent-point end) + (indent 0) + (in-string nil) + (in-paren nil) + (depth 0) + (nest nil) + (pcol nil)) + (save-excursion + (if start + (goto-char start) + (ruby-beginning-of-indent)) + (save-restriction + (narrow-to-region (point) end) + (while (and (> indent-point (point)) + (re-search-forward ruby-delimiter indent-point t)) + (let ((pnt (point)) w) + (goto-char (match-beginning 0)) + (cond + ((or (looking-at "\"") ;skip string + (looking-at "'") + (looking-at "`")) + (setq w (char-after (point))) + (cond + ((and (not (eobp)) + (re-search-forward (format "[^\\]\\(\\\\\\\\\\)*%c" w) indent-point t)) + nil) + (t + (setq in-string (point)) + (goto-char indent-point)))) + ((looking-at "/") + (cond + ((and (not (eobp)) (ruby-expr-beg)) + (if (re-search-forward "[^\\]/" indent-point t) + nil + (setq in-string (point)) + (goto-char indent-point))) + (t + (goto-char pnt)))) + ((looking-at "%") + (cond + ((and (not (eobp)) (ruby-expr-beg) + (looking-at "%[Qqrxw]?\\(.\\)")) + (setq w (buffer-substring (match-beginning 1) + (match-end 1))) + (cond + ((string= w "[") (setq w "]")) + ((string= w "{") (setq w "}")) + ((string= w "(") (setq w ")")) + ((string= w "<") (setq w ">"))) + (goto-char (match-end 0)) + (if (search-forward w indent-point t) + nil + (setq in-string (point)) + (goto-char indent-point))) + (t + (goto-char pnt)))) + ((looking-at "\\?") ;skip ?char + (cond + ((ruby-expr-beg) + (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.") + (goto-char (match-end 0))) + (t + (goto-char pnt)))) + ((looking-at "\\$") ;skip $char + (goto-char pnt) + (forward-char 1)) + ((looking-at "#") ;skip comment + (forward-line 1) + (goto-char (point)) + ) + ((looking-at "(") + (setq nest (cons (cons (char-after (point)) pnt) nest)) + (setq pcol (cons (cons pnt depth) pcol)) + (setq depth 0) + (goto-char pnt) + ) + ((looking-at "[\\[{]") + (setq nest (cons (cons (char-after (point)) pnt) nest)) + (setq depth (1+ depth)) + (goto-char pnt) + ) + ((looking-at ")") + (setq nest (cdr nest)) + (setq depth (cdr (car pcol))) + (setq pcol (cdr pcol)) + (goto-char pnt)) + ((looking-at "[])}]") + (setq nest (cdr nest)) + (setq depth (1- depth)) + (goto-char pnt)) + ((looking-at ruby-block-end-re) + (if (or (and (not (bolp)) + (progn + (forward-char -1) + (eq ?_ (char-after (point))))) + (progn + (goto-char pnt) + (setq w (char-after (point))) + (or (eq ?_ w) + (eq ?! w) + (eq ?? w)))) + nil + (setq nest (cdr nest)) + (setq depth (1- depth))) + (goto-char pnt)) + ((looking-at "def\\s +[^(\n;]*") + (if (or (bolp) + (progn + (forward-char -1) + (not (eq ?_ (char-after (point)))))) + (progn + (setq nest (cons (cons nil pnt) nest)) + (setq depth (1+ depth)))) + (goto-char (match-end 0))) + ((looking-at ruby-block-beg-re) + (and + (or (bolp) + (progn + (forward-char -1) + (not (eq ?_ (char-after (point)))))) + (goto-char pnt) + (setq w (char-after (point))) + (not (eq ?_ w)) + (not (eq ?! w)) + (not (eq ?? w)) + (skip-chars-forward " \t") + (if (not (eolp)) + (progn + (goto-char (match-beginning 0)) + (if (looking-at ruby-modifier-re) + (ruby-expr-beg t) + t)) + t) + (goto-char pnt) + (setq nest (cons (cons nil pnt) nest)) + (setq depth (1+ depth))) + (goto-char pnt)) + ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?") + (goto-char (match-end 0))) + ((or (looking-at "\\.") + (looking-at "\\.\\.\\.?") + (looking-at "\\.[0-9]+") + (looking-at "\\.[a-zA-Z_0-9]+")) + (goto-char (match-end 0))) + ((looking-at "^=begin") + (if (re-search-forward "^=end" indent-point t) + (forward-line 1) + (setq in-string (match-end 0)) + (goto-char indent-point))) + (t + (error (format "bad string %s" + (buffer-substring (point) pnt) + ))))))) + (list in-string (car nest) depth (car (car pcol)))))) + +(defun ruby-indent-size (pos nest) + (+ pos (* (if nest nest 1) ruby-indent-level))) + +(defun ruby-calculate-indent (&optional parse-start) + (save-excursion + (beginning-of-line) + (let ((indent-point (point)) + (case-fold-search nil) + state bol eol + (indent 0)) + (if parse-start + (goto-char parse-start) + (ruby-beginning-of-indent) + (setq parse-start (point))) + (back-to-indentation) + (setq indent (current-column)) + (setq state (ruby-parse-region parse-start indent-point)) + (cond + ((nth 0 state) ; within string + (setq indent nil)) ; do nothing + + ((car (nth 1 state)) ; in paren + (goto-char (cdr (nth 1 state))) + (if (eq (car (nth 1 state)) ?\( ) + (let ((column (current-column)) + (s (ruby-parse-region (point) indent-point))) + (cond + ((and (nth 2 s) (> (nth 2 s) 0)) + (goto-char (cdr (nth 1 s))) + (forward-word -1) + (setq indent (ruby-indent-size (current-column) (nth 2 state)))) + (t + (setq indent (current-column))))) + (cond + ((nth 3 state) + (goto-char (nth 3 state)) + (setq indent (ruby-indent-size (current-column) (nth 2 state)))) + (t + (goto-char parse-start) + (back-to-indentation) + (setq indent (ruby-indent-size (current-column) (nth 2 state))))) + )) + + ((and (nth 2 state)(> (nth 2 state) 0)) ; in nest + (if (null (cdr (nth 1 state))) + (error "invalid nest")) + (goto-char (cdr (nth 1 state))) + (forward-word -1) ; skip back a keyword + (cond + ((looking-at "do") ; iter block is a special case + (cond + ((nth 3 state) + (goto-char (nth 3 state)) + (setq indent (ruby-indent-size (current-column) (nth 2 state)))) + (t + (goto-char parse-start) + (back-to-indentation) + (setq indent (ruby-indent-size (current-column) (nth 2 state)))))) + (t + (setq indent (+ (current-column) ruby-indent-level))))) + + ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest + (setq indent (ruby-indent-size (current-column) (nth 2 state))))) + + (cond + (indent + (goto-char indent-point) + (end-of-line) + (setq eol (point)) + (beginning-of-line) + (cond + ((re-search-forward ruby-negative eol t) + (and (not (eq ?_ (char-after (match-end 0)))) + (setq indent (- indent ruby-indent-level)))) + ;;operator terminated lines + ((and + (save-excursion + (beginning-of-line) + (not (bobp))) + (or (null (car (nth 1 state))) ;not in parens + (and (eq (car (nth 1 state)) ?\{) + (save-excursion ;except non-block braces + (goto-char (cdr (nth 1 state))) + (or (bobp) (forward-char -1)) + (not (ruby-expr-beg)))))) + ;; goto beginning of non-empty no-comment line + (let (end done) + (while (not done) + (skip-chars-backward " \t\n") + (setq end (point)) + (beginning-of-line) + (if (re-search-forward "^\\s *#" end t) + (beginning-of-line) + (setq done t)))) + (setq bol (point)) + (end-of-line) + (skip-chars-backward " \t") + (and (re-search-backward "#" (save-excursion + (beginning-of-line) + (point)) t) + (setq state (ruby-parse-region parse-start (point))) + (nth 0 state) + (goto-char (nth 0 state))) + (or (bobp) (forward-char -1)) + (and + (or (and (looking-at ruby-symbol-re) + (skip-chars-backward ruby-symbol-chars) + (looking-at ruby-block-op-re) + (save-excursion + (goto-char (match-end 0)) + (not (looking-at "[a-z_]")))) + (and (looking-at ruby-operator-re) + (or (not (eq ?/ (char-after (point)))) + (null (nth 0 (ruby-parse-region parse-start (point))))) + (not (eq (char-after (1- (point))) ?$)) + (or (not (eq ?| (char-after (point)))) + (save-excursion + (or (eolp) (forward-char -1)) + (and (search-backward "|") + (skip-chars-backward " \t\n") + (and (not (eolp)) + (progn + (forward-char -1) + (not (looking-at "\\{"))) + (progn + (forward-word -1) + (not (looking-at "do\\>[^_]"))))))))) + (setq indent (+ indent ruby-indent-level))))))) + indent))) + +(defun ruby-electric-brace (arg) + (interactive "P") + (self-insert-command (prefix-numeric-value arg)) + (ruby-indent-line t)) + +(defun ruby-beginning-of-defun (&optional arg) + "Move backward to next beginning-of-defun. +With argument, do this that many times. +Returns t unless search stops due to end of buffer." + (interactive "p") + (and (re-search-backward (concat "^\\(" ruby-block-beg-re "\\)\\b") + nil 'move (or arg 1)) + (progn (beginning-of-line) t))) + +(defun ruby-beginning-of-indent () + (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\b") + nil 'move) + (progn + (beginning-of-line) + t))) + +(defun ruby-end-of-defun (&optional arg) + "Move forward to next end of defun. +An end of a defun is found by moving forward from the beginning of one." + (interactive "p") + (and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\b[^_]") + nil 'move (or arg 1)) + (progn (beginning-of-line) t)) + (forward-line 1)) + +(defun ruby-move-to-block (n) + (let (start pos done down) + (setq start (ruby-calculate-indent)) + (if (eobp) + nil + (while (and (not (bobp)) (not done)) + (forward-line n) + (cond + ((looking-at "^$")) + ((looking-at "^\\s *#")) + (t + (setq pos (current-indentation)) + (cond + ((< start pos) + (setq down t)) + ((and down (= pos start)) + (setq done t)) + ((> start pos) + (setq done t))))) + (if done + (progn + (back-to-indentation) + (if (looking-at ruby-block-mid-re) + (setq done nil))))))) + (back-to-indentation)) + +(defun ruby-beginning-of-block () + "Move backward to next beginning-of-block" + (interactive) + (ruby-move-to-block -1)) + +(defun ruby-end-of-block () + "Move forward to next beginning-of-block" + (interactive) + (ruby-move-to-block 1)) + +(defun ruby-reindent-then-newline-and-indent () + (interactive "*") + (save-excursion + (delete-region (point) (progn (skip-chars-backward " \t") (point)))) + (newline) + (save-excursion + (forward-line -1) + (indent-according-to-mode)) + (indent-according-to-mode)) + +(fset 'ruby-encomment-region (symbol-function 'comment-region)) + +(defun ruby-decomment-region (beg end) + (interactive "r") + (save-excursion + (goto-char beg) + (while (re-search-forward "^\\([ \t]*\\)#" end t) + (replace-match "\\1" nil nil) + (save-excursion + (ruby-indent-line))))) + +(defun ruby-insert-end () + (interactive) + (insert "end") + (ruby-indent-line t) + (end-of-line)) + +(cond + ((featurep 'hilit19) + (hilit-set-mode-patterns + 'ruby-mode + '(("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string) + ("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string) + ("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string) + ("^\\s *#.*$" nil comment) + ("[^$@?\\]\\(#[^$@{\n].*$\\)" 1 comment) + ("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string) + ("^\\s *\\(require\\|load\\).*$" nil include) + ("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl) + ("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun) + ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|unless\\|rescue\\|then\\|when\\|while\\|until\\|do\\)\\>[^_]" 1 defun) + ("[^_]\\<\\(and\\|break\\|next\\|raise\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\|self\\|nil\\)\\>[^_]" 1 keyword) + ("\\$\\(.\\|\\sw+\\)" nil type) + ("[$@].[a-zA-Z_0-9]*" nil struct) + ("^__END__" nil label)))) + + ((featurep 'font-lock) + (or (boundp 'font-lock-variable-name-face) + (setq font-lock-variable-name-face font-lock-type-face)) + (defvar ruby-font-lock-keywords + (list + (cons (concat + "\\(^\\|[^_:.]\\|\\.\\.\\)\\b\\(" + (mapconcat + 'identity + '("alias" + "and" + "begin" + "break" + "case" + "class" + "def" + "do" + "elsif" + "else" + "fail" + "ensure" + "for" + "end" + "if" + "in" + "module" + "next" + "not" + "or" + "raise" + "redo" + "rescue" + "retry" + "return" + "then" + "self" + "super" + "unless" + "undef" + "until" + "when" + "while" + ) + "\\|") + "\\)\\b") + 2) + ;; variables + '("\\(^\\|[^_]\\)\\b\\(nil\\|self\\|true\\|false\\)\\b\\([^_]\\|$\\)" + 2 font-lock-variable-name-face) + ;; variables + '("[$@].[a-zA-Z0-9_]*" + 0 font-lock-variable-name-face) + ;; constants + '("\\(^\\|[^_]\\)\\b\\([A-Z]+[a-zA-Z0-9_]*\\)" + 2 font-lock-type-face) + ;; functions + '("^\\s *def[ \t]+\\([^ \t(]*\\)" + 1 font-lock-function-name-face t)) + "*Additional expressions to highlight in ruby mode.") + (if (and (>= (string-to-int emacs-version) 19) + (not (featurep 'xemacs))) + (add-hook + 'ruby-mode-hook + (lambda () + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults + '((ruby-font-lock-keywords) nil nil ((?\_ . "w")))))) + (add-hook 'ruby-mode-hook + (lambda () + (setq font-lock-keywords ruby-font-lock-keywords)))))) + +(provide 'ruby-mode) diff --git a/misc/rubydb2x.el b/misc/rubydb2x.el new file mode 100644 index 0000000000..a74265fb0e --- /dev/null +++ b/misc/rubydb2x.el @@ -0,0 +1,104 @@ +(require 'gud) +(provide 'rubydb) + +;; ====================================================================== +;; rubydb functions + +;;; History of argument lists passed to rubydb. +(defvar gud-rubydb-history nil) + +(defun gud-rubydb-massage-args (file args) + (cons "-I" (cons "." (cons "-r" (cons "debug" (cons file args)))))) + +;; There's no guarantee that Emacs will hand the filter the entire +;; marker at once; it could be broken up across several strings. We +;; might even receive a big chunk with several markers in it. If we +;; receive a chunk of text which looks like it might contain the +;; beginning of a marker, we save it here between calls to the +;; filter. +(defvar gud-rubydb-marker-acc "") + +(defun gud-rubydb-marker-filter (string) + (save-match-data + (setq gud-marker-acc (concat gud-marker-acc string)) + (let ((output "")) + + ;; Process all the complete markers in this chunk. + (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" + gud-marker-acc) + (setq + + ;; Extract the frame position from the marker. + gud-last-frame + (cons (substring gud-marker-acc (match-beginning 1) (match-end 1)) + (string-to-int (substring gud-marker-acc + (match-beginning 2) + (match-end 2)))) + + ;; Append any text before the marker to the output we're going + ;; to return - we don't include the marker in this text. + output (concat output + (substring gud-marker-acc 0 (match-beginning 0))) + + ;; Set the accumulator to the remaining text. + gud-marker-acc (substring gud-marker-acc (match-end 0)))) + + ;; Does the remaining text look like it might end with the + ;; beginning of another marker? If it does, then keep it in + ;; gud-marker-acc until we receive the rest of it. Since we + ;; know the full marker regexp above failed, it's pretty simple to + ;; test for marker starts. + (if (string-match "\032.*\\'" gud-marker-acc) + (progn + ;; Everything before the potential marker start can be output. + (setq output (concat output (substring gud-marker-acc + 0 (match-beginning 0)))) + + ;; Everything after, we save, to combine with later input. + (setq gud-marker-acc + (substring gud-marker-acc (match-beginning 0)))) + + (setq output (concat output gud-marker-acc) + gud-marker-acc "")) + + output))) + +(defun gud-rubydb-find-file (f) + (find-file-noselect f)) + +(defvar rubydb-command-name "ruby" + "File name for executing ruby.") + +;;;###autoload +(defun rubydb (command-line) + "Run rubydb on program FILE in buffer *gud-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger." + (interactive + (list (read-from-minibuffer "Run rubydb (like this): " + (if (consp gud-rubydb-history) + (car gud-rubydb-history) + (concat rubydb-command-name " ")) + nil nil + '(gud-rubydb-history . 1)))) + + (gud-overload-functions '((gud-massage-args . gud-rubydb-massage-args) + (gud-marker-filter . gud-rubydb-marker-filter) + (gud-find-file . gud-rubydb-find-file) + )) + (gud-common-init command-line) + + (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.") +; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") + (gud-def gud-step "s" "\C-s" "Step one source line with display.") + (gud-def gud-next "n" "\C-n" "Step one line (skip functions).") + (gud-def gud-cont "c" "\C-r" "Continue with display.") + (gud-def gud-finish "finish" "\C-f" "Finish executing current function.") + (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") + (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") + (gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.") + + (setq comint-prompt-regexp "^(rdb:-) ") + (setq paragraph-start comint-prompt-regexp) + (run-hooks 'rubydb-mode-hook) + ) diff --git a/misc/rubydb3x.el b/misc/rubydb3x.el new file mode 100644 index 0000000000..9d4e31f90e --- /dev/null +++ b/misc/rubydb3x.el @@ -0,0 +1,104 @@ +(require 'gud) +(provide 'rubydb) + +;; ====================================================================== +;; rubydb functions + +;;; History of argument lists passed to rubydb. +(defvar gud-rubydb-history nil) + +(defun gud-rubydb-massage-args (file args) + (cons "-r" (cons "debug" args))) + +;; There's no guarantee that Emacs will hand the filter the entire +;; marker at once; it could be broken up across several strings. We +;; might even receive a big chunk with several markers in it. If we +;; receive a chunk of text which looks like it might contain the +;; beginning of a marker, we save it here between calls to the +;; filter. +(defvar gud-rubydb-marker-acc "") + +(defun gud-rubydb-marker-filter (string) + (setq gud-marker-acc (concat gud-marker-acc string)) + (let ((output "")) + + ;; Process all the complete markers in this chunk. + (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" + gud-marker-acc) + (setq + + ;; Extract the frame position from the marker. + gud-last-frame + (cons (substring gud-marker-acc (match-beginning 1) (match-end 1)) + (string-to-int (substring gud-marker-acc + (match-beginning 2) + (match-end 2)))) + + ;; Append any text before the marker to the output we're going + ;; to return - we don't include the marker in this text. + output (concat output + (substring gud-marker-acc 0 (match-beginning 0))) + + ;; Set the accumulator to the remaining text. + gud-marker-acc (substring gud-marker-acc (match-end 0)))) + + ;; Does the remaining text look like it might end with the + ;; beginning of another marker? If it does, then keep it in + ;; gud-marker-acc until we receive the rest of it. Since we + ;; know the full marker regexp above failed, it's pretty simple to + ;; test for marker starts. + (if (string-match "\032.*\\'" gud-marker-acc) + (progn + ;; Everything before the potential marker start can be output. + (setq output (concat output (substring gud-marker-acc + 0 (match-beginning 0)))) + + ;; Everything after, we save, to combine with later input. + (setq gud-marker-acc + (substring gud-marker-acc (match-beginning 0)))) + + (setq output (concat output gud-marker-acc) + gud-marker-acc "")) + + output)) + +(defun gud-rubydb-find-file (f) + (save-excursion + (let ((buf (find-file-noselect f))) + (set-buffer buf) + (gud-make-debug-menu) + buf))) + +(defvar rubydb-command-name "ruby" + "File name for executing ruby.") + +;;;###autoload +(defun rubydb (command-line) + "Run rubydb on program FILE in buffer *gud-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger." + (interactive + (list (read-from-minibuffer "Run rubydb (like this): " + (if (consp gud-rubydb-history) + (car gud-rubydb-history) + (concat rubydb-command-name " ")) + nil nil + '(gud-rubydb-history . 1)))) + + (gud-common-init command-line 'gud-rubydb-massage-args + 'gud-rubydb-marker-filter 'gud-rubydb-find-file) + + (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.") +; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") + (gud-def gud-step "s" "\C-s" "Step one source line with display.") + (gud-def gud-next "n" "\C-n" "Step one line (skip functions).") + (gud-def gud-cont "c" "\C-r" "Continue with display.") + (gud-def gud-finish "finish" "\C-f" "Finish executing current function.") + (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") + (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") + (gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.") + + (setq comint-prompt-regexp "^(rdb:-) ") + (setq paragraph-start comint-prompt-regexp) + (run-hooks 'rubydb-mode-hook) + ) diff --git a/missing/nt.c b/missing/nt.c index a78d82e1ef..3f25c81cd4 100644 --- a/missing/nt.c +++ b/missing/nt.c @@ -251,6 +251,9 @@ int SafeFree(char **vec, int vecc) static char *szInternalCmds[] = { + "append", + "break", + "call", "cd", "chdir", "cls", @@ -264,6 +267,7 @@ static char *szInternalCmds[] = { "md", "mkdir", "path", + "pause", "rd", "rem", "ren", @@ -280,13 +284,18 @@ static char *szInternalCmds[] = { int isInternalCmd(char *cmd) { - int fRet; + int i, fRet; char **vec; - int vecc = NtMakeCmdVector(cmd, &vec, FALSE); - + for( i = 0; szInternalCmds[i] ; i++){ + if(!strcmp(szInternalCmds[i], vec[0])){ + fRet = 1; + break; + } + } + SafeFree (vec, vecc); - return 0; + return fRet; } diff --git a/numeric.c b/numeric.c index d1921f3898..74350d579f 100644 --- a/numeric.c +++ b/numeric.c @@ -1044,7 +1044,7 @@ static VALUE fix_rev(num) VALUE num; { - unsigned long val = FIX2UINT(num); + unsigned long val = FIX2ULONG(num); val = ~val; return rb_int2inum(val); diff --git a/object.c b/object.c index 033539f159..5abf4db5ab 100644 --- a/object.c +++ b/object.c @@ -49,7 +49,7 @@ rb_eql(obj1, obj2) return rb_funcall(obj1, eql, 1, obj2); } -VALUE +static VALUE rb_obj_equal(obj1, obj2) VALUE obj1, obj2; { @@ -598,13 +598,6 @@ rb_class_s_inherited() rb_raise(rb_eTypeError, "can't make subclass of Class"); } -VALUE rb_mod_name(); -VALUE rb_mod_included_modules(); -VALUE rb_mod_ancestors(); -VALUE rb_class_instance_methods(); -VALUE rb_class_protected_instance_methods(); -VALUE rb_class_private_instance_methods(); - static VALUE rb_class_superclass(klass) VALUE klass; @@ -624,11 +617,16 @@ ID rb_to_id(name) VALUE name; { + ID id; + if (TYPE(name) == T_STRING) { return rb_intern(RSTRING(name)->ptr); } - Check_Type(name, T_FIXNUM); - return FIX2UINT(name); + id = NUM2UINT(name); + if (!rb_id2name(id)) { + rb_raise(rb_eArgError, "%d is not a symbol", id); + } + return id; } static VALUE @@ -686,8 +684,6 @@ rb_mod_attr_accessor(argc, argv, klass) return Qnil; } -VALUE rb_mod_constants(); - static VALUE rb_mod_const_get(mod, name) VALUE mod, name; @@ -935,6 +931,7 @@ Init_Object() rb_mKernel = rb_define_module("Kernel"); rb_include_module(rb_cObject, rb_mKernel); + rb_define_private_method(rb_cObject, "initialize", rb_obj_dummy, -1); rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1); /* @@ -1022,7 +1019,6 @@ Init_Object() rb_define_method(rb_cNilClass, "+", nil_plus, 1); #endif - rb_define_global_function("initialize", rb_obj_dummy, -1); rb_define_global_function("singleton_method_added", rb_obj_dummy, 1); rb_define_method(rb_cModule, "===", rb_mod_eqq, 1); diff --git a/pack.c b/pack.c index cfe4b8bad2..6b29857734 100644 --- a/pack.c +++ b/pack.c @@ -77,6 +77,7 @@ endian() static char *toofew = "too few arguments"; static void encodes _((VALUE,char*,int,int)); +static void qpencode _((VALUE,VALUE,int)); static void pack_add_ptr(str, add) @@ -104,7 +105,7 @@ pack_pack(ary, fmt) int plen; - p = str2cstr(fmt, &plen); + p = rb_str2cstr(fmt, &plen); pend = p + plen; res = rb_str_new(0, 0); @@ -469,6 +470,13 @@ pack_pack(ary, fmt) } break; + case 'M': + from = rb_obj_as_string(NEXTFROM); + if (len <= 1) + len = 72; + qpencode(res, from, len); + break; + case 'P': len = 1; /* FALL THROUGH */ @@ -505,38 +513,121 @@ encodes(str, s, len, type) int len; int type; { - char hunk[4]; + char *buff = ALLOCA_N(char, len * 4 / 3 + 6); + int i = 0; char *p, *pend; char *trans = type == 'u' ? uu_table : b64_table; int padding; if (type == 'u') { - *hunk = len + ' '; - rb_str_cat(str, hunk, 1); + buff[i++] = len + ' '; padding = '`'; } else { padding = '='; } - while (len > 0) { - hunk[0] = trans[077 & (*s >> 2)]; - hunk[1] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))]; - hunk[2] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))]; - hunk[3] = trans[077 & s[2]]; - rb_str_cat(str, hunk, 4); + while (len >= 3) { + buff[i++] = trans[077 & (*s >> 2)]; + buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))]; + buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))]; + buff[i++] = trans[077 & s[2]]; s += 3; len -= 3; } - p = RSTRING(str)->ptr; - pend = RSTRING(str)->ptr + RSTRING(str)->len; - if (len == -1) { - pend[-1] = padding; + if (len == 2) { + buff[i++] = trans[077 & (*s >> 2)]; + buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))]; + buff[i++] = trans[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))]; + buff[i++] = padding; } - else if (len == -2) { - pend[-2] = padding; - pend[-1] = padding; + else if (len == 1) { + buff[i++] = trans[077 & (*s >> 2)]; + buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))]; + buff[i++] = padding; + buff[i++] = padding; + } + buff[i++] = '\n'; + rb_str_cat(str, buff, i); +} + +static char hex_table[] = "0123456789ABCDEF"; + +static void +qpencode(str, from, len) + VALUE str, from; + int len; +{ + char buff[1024]; + int i = 0, n = 0, prev = EOF; + unsigned char *s = RSTRING(from)->ptr; + unsigned char *send = s + RSTRING(from)->len; + + while (s < send) { + if ((*s > 126) || + (*s < 32 && *s != '\n' && *s != '\t') || + (*s == '=')) { + buff[i++] = '='; + buff[i++] = hex_table[*s >> 4]; + buff[i++] = hex_table[*s & 0x0f]; + n += 3; + prev = EOF; + } + else if (*s == '\n') { + if (prev == ' ' || prev == '\t') { + buff[i++] = '='; + buff[i++] = *s; + } + buff[i++] = *s; + n = 0; + prev = *s; + } + else { + buff[i++] = *s; + n++; + prev = *s; + } + if (n > len) { + buff[i++] = '='; + buff[i++] = '\n'; + n = 0; + prev = '\n'; + } + if (i > 1024 - 5) { + rb_str_cat(str, buff, i); + i = 0; + } + s++; + } + if (n > 0) { + buff[i++] = '='; + buff[i++] = '\n'; + } + if (i > 0) { + rb_str_cat(str, buff, i); + } +} + +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE) +static __inline__ int +#else +static int +#endif +hex2num(c) + char c; +{ + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return c - '0'; + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + return c - 'a' + 10; + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + return c - 'A' + 10; + default: + return -1; } - rb_str_cat(str, "\n", 1); } static VALUE @@ -550,9 +641,9 @@ pack_unpack(str, fmt) char type; int len; - s = str2cstr(str, &len); + s = rb_str2cstr(str, &len); send = s + len; - p = str2cstr(fmt, &len); + p = rb_str2cstr(fmt, &len); pend = p + len; ary = rb_ary_new(); @@ -929,6 +1020,32 @@ pack_unpack(str, fmt) } break; + case 'M': + { + VALUE str = rb_str_new(0, send - s); + char *ptr = RSTRING(str)->ptr; + int c1, c2; + + while (s < send) { + if (*s == '=') { + if (++s == send) break; + if (*s != '\n' && s < send - 1) { + if ((c1 = hex2num(*s)) == -1) break; + if (++s == send) break; + if ((c2 = hex2num(*s)) == -1) break; + *ptr++ = c1 << 4 | c2; + } + } + else { + *ptr++ = *s; + } + s++; + } + RSTRING(str)->len = ptr - RSTRING(str)->ptr; + rb_ary_push(ary, str); + } + break; + case '@': s = RSTRING(str)->ptr + len; break; diff --git a/parse.y b/parse.y index 9e8cfad2bb..2fc4de40e9 100644 --- a/parse.y +++ b/parse.y @@ -1150,7 +1150,7 @@ primary : literal local_pop(); cur_mid = 0; } - | kDEF singleton '.' {lex_state = EXPR_FNAME;} fname + | kDEF singleton dot_or_colon {lex_state = EXPR_FNAME;} fname { value_expr($2); in_single++; @@ -1284,6 +1284,7 @@ method_call : operation '(' opt_call_args ')' { value_expr($1); $$ = new_call($1, $3, 0); + fixpos($$, $1); } | primary tCOLON2 operation '(' opt_call_args ')' { @@ -1557,6 +1558,9 @@ operation : tIDENTIFIER | tCONSTANT | tFID +dot_or_colon : '.' + | tCOLON2 + opt_terms : /* none */ | terms @@ -1723,6 +1727,20 @@ rb_compile_file(f, file, start) return yycompile(strdup(f)); } + +static void +normalize_newline(line) + VALUE line; +{ + if (RSTRING(line)->len >= 2 && + RSTRING(line)->ptr[RSTRING(line)->len-1] == '\n' && + RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r') + { + RSTRING(line)->ptr[RSTRING(line)->len-2] = '\n'; + RSTRING(line)->len--; + } +} + static int nextc() { @@ -1737,19 +1755,20 @@ nextc() ruby_sourceline = heredoc_end+1; heredoc_end = 0; } + normalize_newline(v); while (RSTRING(v)->len >= 2 && RSTRING(v)->ptr[RSTRING(v)->len-1] == '\n' && RSTRING(v)->ptr[RSTRING(v)->len-2] == '\\') { VALUE v2 = (*lex_gets)(lex_input); if (!NIL_P(v2)) { + normalize_newline(v2); rb_str_cat(v, RSTRING(v2)->ptr, RSTRING(v2)->len); } } lex_pbeg = lex_p = RSTRING(v)->ptr; lex_pend = lex_p + RSTRING(v)->len; - if (RSTRING(v)->len == 8 && - strncmp(lex_pbeg, "__END__", 7) == 0) { + if (strncmp(lex_pbeg, "__END__", 7) == 0 && lex_pbeg[7] == '\n') { lex_lastline = 0; return -1; } @@ -2220,11 +2239,12 @@ parse_quotedword(term, paren) char *strdup(); static int -here_document(term) +here_document(term, indent) char term; + int indent; { int c; - char *eos; + char *eos, *p; int len; VALUE str, line; char *save_beg, *save_end, *save_lexp; @@ -2273,10 +2293,15 @@ here_document(term) free(eos); return 0; } + normalize_newline(line); ruby_sourceline++; - if (strncmp(eos, RSTRING(line)->ptr, len) == 0 && - (RSTRING(line)->ptr[len] == '\n' || - RSTRING(line)->ptr[len] == '\r')) { + p = RSTRING(line)->ptr; + if (indent) { + while (*p && (*p == ' ' || *p == '\t')) { + p++; + } + } + if (strncmp(eos, p, len) == 0 && p[len] == '\n') { break; } @@ -2486,8 +2511,13 @@ retry: lex_state != EXPR_END && lex_state != EXPR_CLASS && (lex_state != EXPR_ARG || space_seen)) { int c2 = nextc(); + int indent = 0; + if (c2 == '-') { + indent = 1; + c2 = nextc(); + } if (!ISSPACE(c2) && (strchr("\"'`", c2) || is_identchar(c2))) { - return here_document(c2); + return here_document(c2, indent); } pushback(c2); } diff --git a/process.c b/process.c index e4d0d0ab82..79d30c8139 100644 --- a/process.c +++ b/process.c @@ -212,28 +212,9 @@ rb_f_waitpid(obj, vpid, vflags) char *strtok(); -#if defined(USE_THREAD) && defined(HAVE_SETITIMER) -static void -before_exec() -{ - struct itimerval tval; - - tval.it_interval.tv_sec = 0; - tval.it_interval.tv_usec = 0; - tval.it_value = tval.it_interval; - setitimer(ITIMER_VIRTUAL, &tval, NULL); -} - -static void -after_exec() -{ - struct itimerval tval; - - tval.it_interval.tv_sec = 0; - tval.it_interval.tv_usec = 100000; - tval.it_value = tval.it_interval; - setitimer(ITIMER_VIRTUAL, &tval, NULL); -} +#if defined(THREAD) && defined(HAVE_SETITIMER) +#define before_exec() thread_stop_timer() +#define after_exec() thread_start_timer() #else #define before_exec() #define after_exec() @@ -503,6 +484,9 @@ rb_f_exec(argc, argv) VALUE prog = 0; int i; + if (argc == 0) { + rb_raise(rb_eArgError, "wrong # of arguments"); + } if (TYPE(argv[0]) == T_ARRAY) { if (RARRAY(argv[0])->len != 2) { rb_raise(rb_eArgError, "wrong first argument"); @@ -834,6 +818,20 @@ proc_setpgrp(argc, argv) #endif } +static VALUE +proc_getpgid(obj, pid) + VALUE obj, pid; +{ +#ifdef HAVE_GETPGID + int i; + + i = getpgid(NUM2INT(pid)); + return INT2NUM(i); +#else + rb_notimplement(); +#endif +} + static VALUE proc_setpgid(obj, pid, pgrp) VALUE obj, pid, pgrp; @@ -1085,7 +1083,7 @@ Init_process() rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2); rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3); -#ifdef PRIO_PROCESS +#ifdef HAVE_GETPRIORITY rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS)); rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP)); rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER)); diff --git a/re.h b/re.h index 8aeb4e3980..3bbbd91f07 100644 --- a/re.h +++ b/re.h @@ -3,7 +3,6 @@ re.h - $Author$ - $Revision$ $Date$ created at: Thu Sep 30 14:18:32 JST 1993 diff --git a/regex.c b/regex.c index b3cbb77f2c..c5a903e721 100644 --- a/regex.c +++ b/regex.c @@ -2812,6 +2812,7 @@ re_search(bufp, string, size, startpos, range, regs) } } + if (startpos > size) return -1; if (fastmap && startpos == size && range >= 0 && (bufp->can_be_null == 0 || (bufp->can_be_null && size > 0 diff --git a/ruby.c b/ruby.c index 289798ab9c..fb78235d92 100644 --- a/ruby.c +++ b/ruby.c @@ -20,6 +20,10 @@ #include #include +#ifdef __hpux +#include +#endif + #ifdef HAVE_UNISTD_H #include #endif @@ -607,6 +611,7 @@ set_arg0(val, id) static int len; if (origargv == 0) rb_raise(rb_eRuntimeError, "$0 not initialized"); +#ifndef __hpux if (len == 0) { s = origargv[0]; s += strlen(s); @@ -617,7 +622,9 @@ set_arg0(val, id) } len = s - origargv[0]; } +#endif s = str2cstr(val, &i); +#ifndef __hpux if (i > len) { memcpy(origargv[0], s, len); origargv[0][len] = '\0'; @@ -630,6 +637,21 @@ set_arg0(val, id) *s++ = ' '; } rb_progname = rb_tainted_str_new2(origargv[0]); +#else + if (i >= PST_CLEN) { + union pstun j; + j.pst_command = s; + i = PST_CLEN; + RSTRING(val)->len = i; + *(s + i) = '\0'; + pstat(PSTAT_SETCMD, j, PST_CLEN, 0, 0); + } else { + union pstun j; + j.pst_command = s; + pstat(PSTAT_SETCMD, j, i, 0, 0); + } + rb_progname = str_taint(str_new(s, i)); +#endif } void diff --git a/ruby.h b/ruby.h index 174cfd68a8..f0978baccd 100644 --- a/ruby.h +++ b/ruby.h @@ -163,11 +163,11 @@ VALUE rb_int2inum _((long)); #define T_DATA 0x22 #define T_MATCH 0x23 -#define T_VARMAP 0xfd -#define T_SCOPE 0xfe -#define T_NODE 0xff +#define T_VARMAP 0x7d +#define T_SCOPE 0x7e +#define T_NODE 0x7f -#define T_MASK 0xff +#define T_MASK 0x7f #define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK) @@ -271,6 +271,7 @@ struct RHash { struct RFile { struct RBasic basic; + struct st_table *iv_tbl; struct OpenFile *fptr; }; @@ -329,9 +330,10 @@ struct RBignum { #define RFILE(obj) (R_CAST(RFile)(obj)) #define FL_SINGLETON FL_USER0 -#define FL_MARK (1<<8) -#define FL_FINALIZE (1<<9) -#define FL_TAINT (1<<10) +#define FL_MARK (1<<7) +#define FL_FINALIZE (1<<8) +#define FL_TAINT (1<<9) +#define FL_EXIVAR (1<<10) #define FL_USHIFT 11 diff --git a/rubyio.h b/rubyio.h index 9fc4ec8a70..5b8baf0f15 100644 --- a/rubyio.h +++ b/rubyio.h @@ -45,6 +45,7 @@ typedef struct OpenFile { fp->finalize = 0;\ } while (0) +#define GetReadFile(fptr) ((fptr)->f) #define GetWriteFile(fptr) (((fptr)->f2) ? (fptr)->f2 : (fptr)->f) FILE *rb_fopen _((char *, char *)); diff --git a/sample/cal.rb b/sample/cal.rb index b0f5d88335..a5f4b4db18 100644 --- a/sample/cal.rb +++ b/sample/cal.rb @@ -1,7 +1,7 @@ #! /usr/local/bin/ruby # cal.rb (bsd compatible version): Written by Tadayoshi Funaba 1998 -# $Id: bsdcal.rb,v 1.1 1998/06/01 12:53:01 tadf Exp $ +# $Id: bsdcal.rb,v 1.2 1998/12/01 13:47:40 tadf Exp $ require 'date2' @@ -59,7 +59,7 @@ def zip(xs) until xs.empty? ln = (if $jd then l, r, *xs = xs; [l, r] else l, c, r, *xs = xs; [l, c, r] end). - collect{|x| x.split(/\n/no)} + collect{|x| x.split(/\n/no, -1)} 8.times do yr << ln.collect{|x| x.shift.ljust((($w + 1) * 7) - 1)}.join(' ') << "\n" diff --git a/sample/inf-ruby.el b/sample/inf-ruby.el deleted file mode 100644 index 504aff2db7..0000000000 --- a/sample/inf-ruby.el +++ /dev/null @@ -1,310 +0,0 @@ -(J;;;(B (J-*-Emacs-Lisp-*-(B -;;; -;;; $Id: inf-ruby.el,v 1.4 1998/05/20 02:45:58 senda Exp $ -;;; $Author: senda $ -;;; $Date: 1998/05/20 02:45:58 $ -;;; -;;; Inferior Ruby Mode - ruby process in a buffer. -;;; adapted from cmuscheme.el -;;; -;;; Usage: -;;; -;;; (0) check ruby-program-name variable that can run your environment. -;;; -;;; (1) modify .emacs to use ruby-mode -;;; for example : -;;; -;;; (autoload 'ruby-mode "ruby-mode" -;;; "Mode for editing ruby source files") -;;; (setq auto-mode-alist -;;; (append '(("\\.rb$" . ruby-mode)) auto-mode-alist)) -;;; (setq interpreter-mode-alist (append '(("^#!.*ruby" . ruby-mode)) -;;; interpreter-mode-alist)) -;;; -;;; (2) set to road inf-ruby and set inf-ruby key definition in ruby-mode. -;;; -;;; (autoload 'run-ruby "inf-ruby" -;;; "Run an inferior Ruby process") -;;; (autoload 'inf-ruby-keys "inf-ruby" -;;; "Set local key defs for inf-ruby in ruby-mode") -;;; (add-hook 'ruby-mode-hook -;;; '(lambda () -;;; (inf-ruby-keys) -;;; )) -;;; -;;; HISTORY -;;; senda - 8 Apr 1998: Created. -;;; $Log: inf-ruby.el,v $ -;;; Revision 1.4 1998/05/20 02:45:58 senda -;;; default program to irb -;;; -;;; Revision 1.3 1998/04/10 04:11:30 senda -;;; modification by Matsumoto san (1.1b9_09) -;;; remove-in-string defined -;;; global variable : -;;; inferior-ruby-first-prompt-pattern -;;; inferior-ruby-prompt-pattern -;;; defined -;;; -;;; Revision 1.2 1998/04/09 07:53:42 senda -;;; remove M-C-x in inferior-ruby-mode -;;; -;;; Revision 1.1 1998/04/09 07:28:36 senda -;;; Initial revision -;;; -;;; - -(require 'comint) -(require 'ruby-mode) - -;; -;; you may change these variables -;; -;(defvar ruby-program-name "rbc --noreadline" -; "*Program invoked by the run-ruby command") -; -;(defvar inferior-ruby-first-prompt-pattern "^rbc0> *" -; "first prompt regex pattern of ruby interpreter.") -; -;(defvar inferior-ruby-prompt-pattern "^\\(rbc.[>*\"'] *\\)+" -; "prompt regex pattern of ruby interpreter.") - -;;;; for irb -(defvar ruby-program-name "irb --inf-ruby-mode" - "*Program invoked by the run-ruby command") - -(defvar inferior-ruby-first-prompt-pattern "^irb(.*)[0-9:]+0> *" - "first prompt regex pattern of ruby interpreter.") - -(defvar inferior-ruby-prompt-pattern "^\\(irb(.*)[0-9:]+[>*\"'] *\\)+" - "prompt regex pattern of ruby interpreter.") - -;; -;; mode variables -;; -(defvar inferior-ruby-mode-hook nil - "*Hook for customising inferior-ruby mode.") -(defvar inferior-ruby-mode-map nil - "*Mode map for inferior-ruby-mode") - -(cond ((not inferior-ruby-mode-map) - (setq inferior-ruby-mode-map - (copy-keymap comint-mode-map)) -; (define-key inferior-ruby-mode-map "\M-\C-x" ;gnu convention -; 'ruby-send-definition) -; (define-key inferior-ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp) - (define-key inferior-ruby-mode-map "\C-c\C-l" 'ruby-load-file) -)) - -(defun inf-ruby-keys () - "Set local key defs for inf-ruby in ruby-mode" - (define-key ruby-mode-map "\M-\C-x" 'ruby-send-definition) -; (define-key ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp) - (define-key ruby-mode-map "\C-c\C-e" 'ruby-send-definition) - (define-key ruby-mode-map "\C-c\M-e" 'ruby-send-definition-and-go) - (define-key ruby-mode-map "\C-c\C-r" 'ruby-send-region) - (define-key ruby-mode-map "\C-c\M-r" 'ruby-send-region-and-go) - (define-key ruby-mode-map "\C-c\C-z" 'switch-to-ruby) - (define-key ruby-mode-map "\C-c\C-l" 'ruby-load-file) - (define-key ruby-mode-map "\C-c\C-s" 'run-ruby) -) - -(defvar ruby-buffer nil "current ruby (actually irb) process buffer.") - -(defun inferior-ruby-mode () - "Major mode for interacting with an inferior ruby (irb) process. - -The following commands are available: -\\{inferior-ruby-mode-map} - -A ruby process can be fired up with M-x run-ruby. - -Customisation: Entry to this mode runs the hooks on comint-mode-hook and -inferior-ruby-mode-hook (in that order). - -You can send text to the inferior ruby process from other buffers containing -Ruby source. - switch-to-ruby switches the current buffer to the ruby process buffer. - ruby-send-definition sends the current definition to the ruby process. - ruby-send-region sends the current region to the ruby process. - - ruby-send-definition-and-go, ruby-send-region-and-go, - switch to the ruby process buffer after sending their text. -For information on running multiple processes in multiple buffers, see -documentation for variable ruby-buffer. - -Commands: -Return after the end of the process' output sends the text from the - end of process to point. -Return before the end of the process' output copies the sexp ending at point - to the end of the process' output, and sends it. -Delete converts tabs to spaces as it moves back. -Tab indents for ruby; with argument, shifts rest - of expression rigidly with the current line. -C-M-q does Tab on each line starting within following expression. -Paragraphs are separated only by blank lines. # start comments. -If you accidentally suspend your process, use \\[comint-continue-subjob] -to continue it." - (interactive) - (comint-mode) - ;; Customise in inferior-ruby-mode-hook - ;(setq comint-prompt-regexp "^[^>\n]*>+ *") - (setq comint-prompt-regexp inferior-ruby-prompt-pattern) - ;;(scheme-mode-variables) - (ruby-mode-variables) - (setq major-mode 'inferior-ruby-mode) - (setq mode-name "Inferior Ruby") - (setq mode-line-process '(":%s")) - (use-local-map inferior-ruby-mode-map) - (setq comint-input-filter (function ruby-input-filter)) - (setq comint-get-old-input (function ruby-get-old-input)) - (run-hooks 'inferior-ruby-mode-hook)) - -(defvar inferior-ruby-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'" - "*Input matching this regexp are not saved on the history list. -Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.") - -(defun ruby-input-filter (str) - "Don't save anything matching inferior-ruby-filter-regexp" - (not (string-match inferior-ruby-filter-regexp str))) - -;; adapted from replace-in-string in XEmacs (subr.el) -(defun remove-in-string (str regexp) - "Remove all matches in STR for REGEXP and returns the new string." - (let ((rtn-str "") (start 0) match prev-start) - (while (setq match (string-match regexp str start)) - (setq prev-start start - start (match-end 0) - rtn-str (concat rtn-str (substring str prev-start match)))) - (concat rtn-str (substring str start)))) - -(defun ruby-get-old-input () - "Snarf the sexp ending at point" - (save-excursion - (let ((end (point))) - (re-search-backward inferior-ruby-first-prompt-pattern) - (remove-in-string (buffer-substring (point) end) - inferior-ruby-prompt-pattern) - ))) - -(defun ruby-args-to-list (string) - (let ((where (string-match "[ \t]" string))) - (cond ((null where) (list string)) - ((not (= where 0)) - (cons (substring string 0 where) - (ruby-args-to-list (substring string (+ 1 where) - (length string))))) - (t (let ((pos (string-match "[^ \t]" string))) - (if (null pos) - nil - (ruby-args-to-list (substring string pos - (length string))))))))) - -(defun run-ruby (cmd) - "Run an inferior Ruby process, input and output via buffer *ruby*. -If there is a process already running in `*ruby*', switch to that buffer. -With argument, allows you to edit the command line (default is value -of `ruby-program-name'). Runs the hooks `inferior-ruby-mode-hook' -\(after the `comint-mode-hook' is run). -\(Type \\[describe-mode] in the process buffer for a list of commands.)" - - (interactive (list (if current-prefix-arg - (read-string "Run Ruby: " ruby-program-name) - ruby-program-name))) - (if (not (comint-check-proc "*ruby*")) - (let ((cmdlist (ruby-args-to-list cmd))) - (set-buffer (apply 'make-comint "ruby" (car cmdlist) - nil (cdr cmdlist))) - (inferior-ruby-mode))) - (setq ruby-program-name cmd) - (setq ruby-buffer "*ruby*") - (pop-to-buffer "*ruby*")) - -(defun ruby-send-region (start end) - "Send the current region to the inferior Ruby process." - (interactive "r") - (comint-send-region (ruby-proc) start end) - (comint-send-string (ruby-proc) "\n")) - -(defun ruby-send-definition () - "Send the current definition to the inferior Ruby process." - (interactive) - (save-excursion - (ruby-end-of-defun) - (let ((end (point))) - (ruby-beginning-of-defun) - (ruby-send-region (point) end)))) - -;(defun ruby-send-last-sexp () -; "Send the previous sexp to the inferior Ruby process." -; (interactive) -; (ruby-send-region (save-excursion (backward-sexp) (point)) (point))) - -(defun switch-to-ruby (eob-p) - "Switch to the ruby process buffer. -With argument, positions cursor at end of buffer." - (interactive "P") - (if (get-buffer ruby-buffer) - (pop-to-buffer ruby-buffer) - (error "No current process buffer. See variable ruby-buffer.")) - (cond (eob-p - (push-mark) - (goto-char (point-max))))) - -(defun ruby-send-region-and-go (start end) - "Send the current region to the inferior Ruby process. -Then switch to the process buffer." - (interactive "r") - (ruby-send-region start end) - (switch-to-ruby t)) - -(defun ruby-send-definition-and-go () - "Send the current definition to the inferior Ruby. -Then switch to the process buffer." - (interactive) - (ruby-send-definition) - (switch-to-ruby t)) - -(defvar ruby-source-modes '(ruby-mode) - "*Used to determine if a buffer contains Ruby source code. -If it's loaded into a buffer that is in one of these major modes, it's -considered a ruby source file by ruby-load-file. -Used by these commands to determine defaults.") - -(defvar ruby-prev-l/c-dir/file nil - "Caches the last (directory . file) pair. -Caches the last pair used in the last ruby-load-file command. -Used for determining the default in the -next one.") - -(defun ruby-load-file (file-name) - "Load a Ruby file into the inferior Ruby process." - (interactive (comint-get-source "Load Ruby file: " ruby-prev-l/c-dir/file - ruby-source-modes t)) ; T because LOAD - ; needs an exact name - (comint-check-source file-name) ; Check to see if buffer needs saved. - (setq ruby-prev-l/c-dir/file (cons (file-name-directory file-name) - (file-name-nondirectory file-name))) - (comint-send-string (ruby-proc) (concat "(load \"" - file-name - "\"\)\n"))) - -(defun ruby-proc () - "Returns the current ruby process. See variable ruby-buffer." - (let ((proc (get-buffer-process (if (eq major-mode 'inferior-ruby-mode) - (current-buffer) - ruby-buffer)))) - (or proc - (error "No current process. See variable ruby-buffer")))) - -;;; Do the user's customisation... - -(defvar inf-ruby-load-hook nil - "This hook is run when inf-ruby is loaded in. -This is a good place to put keybindings.") - -(run-hooks 'inf-ruby-load-hook) - -(provide 'inf-ruby) - -;;; inf-ruby.el ends here diff --git a/sample/ruby-mode.el b/sample/ruby-mode.el deleted file mode 100644 index 8bf843c1ea..0000000000 --- a/sample/ruby-mode.el +++ /dev/null @@ -1,683 +0,0 @@ -;;; -;;; ruby-mode.el - -;;; -;;; $Author$ -;;; $Date$ -;;; created at: Fri Feb 4 14:49:13 JST 1994 -;;; - -(defconst ruby-mode-revision "$Revision$") - -(defconst ruby-mode-version - (progn - (string-match "[0-9.]+" ruby-mode-revision) - (substring ruby-mode-revision (match-beginning 0) (match-end 0)))) - -(defconst ruby-block-beg-re - "class\\|module\\|def\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin\\|do" - ) - -(defconst ruby-indent-beg-re - "\\(\\s *\\(class\\|module\\|def\\)\\)\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin" - ) - -(defconst ruby-modifier-re - "if\\|unless\\|while\\|until" - ) - -(defconst ruby-block-mid-re - "then\\|else\\|elsif\\|when\\|rescue\\|ensure" - ) - -(defconst ruby-block-op-re - "and\\|or\\|not" - ) - -(defconst ruby-block-end-re "end") - -(defconst ruby-delimiter - (concat "[?$/%(){}#\"'`.:]\\|\\[\\|\\]\\|\\<\\(" - ruby-block-beg-re - "\\|" ruby-block-end-re - "\\)\\>\\|^=begin") - ) - -(defconst ruby-negative - (concat "^[ \t]*\\(\\(" ruby-block-mid-re "\\)\\>\\|\\(" - ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)") - ) - -(defconst ruby-operator-chars ",.+*/%-&|^~=<>:") -(defconst ruby-operator-re (concat "[" ruby-operator-chars "]")) - -(defconst ruby-symbol-chars "a-zA-Z0-9_") -(defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]")) - -(defvar ruby-mode-abbrev-table nil - "Abbrev table in use in ruby-mode buffers.") - -(define-abbrev-table 'ruby-mode-abbrev-table ()) - -(defvar ruby-mode-map nil "Keymap used in ruby mode.") - -(if ruby-mode-map - nil - (setq ruby-mode-map (make-sparse-keymap)) - (define-key ruby-mode-map "{" 'ruby-electric-brace) - (define-key ruby-mode-map "}" 'ruby-electric-brace) - (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun) - (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun) - (define-key ruby-mode-map "\e\C-b" 'ruby-beginning-of-block) - (define-key ruby-mode-map "\e\C-f" 'ruby-end-of-block) - (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block) - (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block) - (define-key ruby-mode-map "\t" 'ruby-indent-command) - (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end) - (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent) - (define-key ruby-mode-map "\C-m" 'newline)) - -(defvar ruby-mode-syntax-table nil - "Syntax table in use in ruby-mode buffers.") - -(if ruby-mode-syntax-table - () - (setq ruby-mode-syntax-table (make-syntax-table)) - (modify-syntax-entry ?\' "\"" ruby-mode-syntax-table) - (modify-syntax-entry ?\" "\"" ruby-mode-syntax-table) - (modify-syntax-entry ?\` "\"" ruby-mode-syntax-table) - (modify-syntax-entry ?# "<" ruby-mode-syntax-table) - (modify-syntax-entry ?\n ">" ruby-mode-syntax-table) - (modify-syntax-entry ?\\ "\\" ruby-mode-syntax-table) - (modify-syntax-entry ?$ "/" ruby-mode-syntax-table) - (modify-syntax-entry ?? "_" ruby-mode-syntax-table) - (modify-syntax-entry ?_ "_" ruby-mode-syntax-table) - (modify-syntax-entry ?< "." ruby-mode-syntax-table) - (modify-syntax-entry ?> "." ruby-mode-syntax-table) - (modify-syntax-entry ?& "." ruby-mode-syntax-table) - (modify-syntax-entry ?| "." ruby-mode-syntax-table) - (modify-syntax-entry ?% "." ruby-mode-syntax-table) - (modify-syntax-entry ?= "." ruby-mode-syntax-table) - (modify-syntax-entry ?/ "." ruby-mode-syntax-table) - (modify-syntax-entry ?+ "." ruby-mode-syntax-table) - (modify-syntax-entry ?* "." ruby-mode-syntax-table) - (modify-syntax-entry ?- "." ruby-mode-syntax-table) - (modify-syntax-entry ?\; "." ruby-mode-syntax-table) - (modify-syntax-entry ?\( "()" ruby-mode-syntax-table) - (modify-syntax-entry ?\) ")(" ruby-mode-syntax-table) - (modify-syntax-entry ?\{ "(}" ruby-mode-syntax-table) - (modify-syntax-entry ?\} "){" ruby-mode-syntax-table) - (modify-syntax-entry ?\[ "(]" ruby-mode-syntax-table) - (modify-syntax-entry ?\] ")[" ruby-mode-syntax-table) - ) - -(defvar ruby-indent-level 2 - "*Indentation of ruby statements.") - -(defun ruby-mode-variables () - (set-syntax-table ruby-mode-syntax-table) - (setq local-abbrev-table ruby-mode-abbrev-table) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'ruby-indent-line) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-variable-buffer-local 'comment-start) - (setq comment-start "# ") - (make-variable-buffer-local 'comment-end) - (setq comment-end "") - (make-variable-buffer-local 'comment-column) - (setq comment-column 32) - (make-variable-buffer-local 'comment-start-skip) - (setq comment-start-skip "\\(^\\|\\s-\\);?#+ *") - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments t)) - -(defun ruby-mode () - "Major mode for editing ruby scripts. -\\[ruby-indent-command] properly indents subexpressions of multi-line -class, module, def, if, while, for, do, and case statements, taking -nesting into account. - -The variable ruby-indent-level controls the amount of indentation. -\\{ruby-mode-map}" - (interactive) - (kill-all-local-variables) - (use-local-map ruby-mode-map) - (setq mode-name "Ruby") - (setq major-mode 'ruby-mode) - (ruby-mode-variables) - (run-hooks 'ruby-mode-hook)) - -(defun ruby-current-indentation () - (save-excursion - (beginning-of-line) - (back-to-indentation) - (current-column))) - -(defun ruby-indent-line (&optional flag) - "Correct indentation of the current ruby line." - (ruby-indent-to (ruby-calculate-indent))) - -(defun ruby-indent-command () - (interactive) - (ruby-indent-line t)) - -(defun ruby-indent-to (x) - (if x - (let (shift top beg) - (and (< x 0) - (error "invalid nest")) - (setq shift (current-column)) - (beginning-of-line) - (setq beg (point)) - (back-to-indentation) - (setq top (current-column)) - (skip-chars-backward " \t") - (cond - ((>= x shift) - (setq shift 0)) - ((>= shift top) - (setq shift (- shift top))) - (t (setq shift 0))) - (if (and (bolp) - (= x top)) - (move-to-column (+ x shift)) - (move-to-column top) - (delete-region beg (point)) - (beginning-of-line) - (indent-to x) - (move-to-column (+ x shift)))))) - -(defun ruby-expr-beg (&optional modifier pnt) - (save-excursion - (if (looking-at "\\?") - (progn - (or (bolp) (forward-char -1)) - (not (looking-at "\\sw"))) - (store-match-data nil) - (skip-chars-backward " \t") - (or (bolp) (forward-char -1)) - (or (bolp) - (looking-at ruby-operator-re) - (looking-at "[\\[({]") - (and (not modifier) (looking-at "[!?]")) - (and (looking-at ruby-symbol-re) - (forward-word -1) - (if (and (not modifier) (bolp)) - t - (if (or (looking-at ruby-block-beg-re) - (looking-at ruby-block-op-re) - (looking-at ruby-block-mid-re)) - (progn - (goto-char (match-end 0)) - (looking-at "\\>"))))))))) - -(defun ruby-parse-region (start end) - (let ((indent-point end) - (indent 0) - (in-string nil) - (in-paren nil) - (depth 0) - (nest nil) - (pcol nil)) - (save-excursion - (if start - (goto-char start) - (ruby-beginning-of-indent)) - (save-restriction - (narrow-to-region (point) end) - (while (and (> indent-point (point)) - (re-search-forward ruby-delimiter indent-point t)) - (let ((pnt (point)) w) - (goto-char (match-beginning 0)) - (cond - ((or (looking-at "\"") ;skip string - (looking-at "'") - (looking-at "`")) - (setq w (char-after (point))) - (cond - ((and (not (eobp)) - (re-search-forward (format "[^\\]\\(\\\\\\\\\\)*%c" w) indent-point t)) - nil) - (t - (setq in-string (point)) - (goto-char indent-point)))) - ((looking-at "/") - (cond - ((and (not (eobp)) (ruby-expr-beg)) - (if (re-search-forward "[^\\]/" indent-point t) - nil - (setq in-string (point)) - (goto-char indent-point))) - (t - (goto-char pnt)))) - ((looking-at "%") - (cond - ((and (not (eobp)) (ruby-expr-beg) - (looking-at "%[Qqrxw]?\\(.\\)")) - (setq w (buffer-substring (match-beginning 1) - (match-end 1))) - (cond - ((string= w "[") (setq w "]")) - ((string= w "{") (setq w "}")) - ((string= w "(") (setq w ")")) - ((string= w "<") (setq w ">"))) - (goto-char (match-end 0)) - (if (search-forward w indent-point t) - nil - (setq in-string (point)) - (goto-char indent-point))) - (t - (goto-char pnt)))) - ((looking-at "\\?") ;skip ?char - (cond - ((ruby-expr-beg) - (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.") - (goto-char (match-end 0))) - (t - (goto-char pnt)))) - ((looking-at "\\$") ;skip $char - (goto-char pnt) - (forward-char 1)) - ((looking-at "#") ;skip comment - (forward-line 1) - (goto-char (point)) - ) - ((looking-at "(") - (setq nest (cons (cons (char-after (point)) pnt) nest)) - (setq pcol (cons (cons pnt depth) pcol)) - (setq depth 0) - (goto-char pnt) - ) - ((looking-at "[\\[{]") - (setq nest (cons (cons (char-after (point)) pnt) nest)) - (setq depth (1+ depth)) - (goto-char pnt) - ) - ((looking-at ")") - (setq nest (cdr nest)) - (setq depth (cdr (car pcol))) - (setq pcol (cdr pcol)) - (goto-char pnt)) - ((looking-at "[])}]") - (setq nest (cdr nest)) - (setq depth (1- depth)) - (goto-char pnt)) - ((looking-at ruby-block-end-re) - (if (or (and (not (bolp)) - (progn - (forward-char -1) - (eq ?_ (char-after (point))))) - (progn - (goto-char pnt) - (setq w (char-after (point))) - (or (eq ?_ w) - (eq ?! w) - (eq ?? w)))) - nil - (setq nest (cdr nest)) - (setq depth (1- depth))) - (goto-char pnt)) - ((looking-at "def\\s +[^(\n;]*") - (if (or (bolp) - (progn - (forward-char -1) - (not (eq ?_ (char-after (point)))))) - (progn - (setq nest (cons (cons nil pnt) nest)) - (setq depth (1+ depth)))) - (goto-char (match-end 0))) - ((looking-at ruby-block-beg-re) - (and - (or (bolp) - (progn - (forward-char -1) - (not (eq ?_ (char-after (point)))))) - (goto-char pnt) - (setq w (char-after (point))) - (not (eq ?_ w)) - (not (eq ?! w)) - (not (eq ?? w)) - (skip-chars-forward " \t") - (if (not (eolp)) - (progn - (goto-char (match-beginning 0)) - (if (looking-at ruby-modifier-re) - (ruby-expr-beg t) - t)) - t) - (goto-char pnt) - (setq nest (cons (cons nil pnt) nest)) - (setq depth (1+ depth))) - (goto-char pnt)) - ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?") - (goto-char (match-end 0))) - ((or (looking-at "\\.") - (looking-at "\\.\\.\\.?") - (looking-at "\\.[0-9]+") - (looking-at "\\.[a-zA-Z_0-9]+")) - (goto-char (match-end 0))) - ((looking-at "^=begin") - (if (re-search-forward "^=end" indent-point t) - (forward-line 1) - (setq in-string (match-end 0)) - (goto-char indent-point))) - (t - (error (format "bad string %s" - (buffer-substring (point) pnt) - ))))))) - (list in-string (car nest) depth (car (car pcol)))))) - -(defun ruby-indent-size (pos nest) - (+ pos (* (if nest nest 1) ruby-indent-level))) - -(defun ruby-calculate-indent (&optional parse-start) - (save-excursion - (beginning-of-line) - (let ((indent-point (point)) - (case-fold-search nil) - state bol eol - (indent 0)) - (if parse-start - (goto-char parse-start) - (ruby-beginning-of-indent) - (setq parse-start (point))) - (back-to-indentation) - (setq indent (current-column)) - (setq state (ruby-parse-region parse-start indent-point)) - (cond - ((nth 0 state) ; within string - (setq indent nil)) ; do nothing - - ((car (nth 1 state)) ; in paren - (goto-char (cdr (nth 1 state))) - (if (eq (car (nth 1 state)) ?\( ) - (let ((column (current-column)) - (s (ruby-parse-region (point) indent-point))) - (cond - ((and (nth 2 s) (> (nth 2 s) 0)) - (goto-char (cdr (nth 1 s))) - (forward-word -1) - (setq indent (ruby-indent-size (current-column) (nth 2 state)))) - (t - (setq indent (current-column))))) - (cond - ((nth 3 state) - (goto-char (nth 3 state)) - (setq indent (ruby-indent-size (current-column) (nth 2 state)))) - (t - (goto-char parse-start) - (back-to-indentation) - (setq indent (ruby-indent-size (current-column) (nth 2 state))))) - )) - - ((and (nth 2 state)(> (nth 2 state) 0)) ; in nest - (if (null (cdr (nth 1 state))) - (error "invalid nest")) - (goto-char (cdr (nth 1 state))) - (forward-word -1) ; skip back a keyword - (cond - ((looking-at "do") ; iter block is a special case - (cond - ((nth 3 state) - (goto-char (nth 3 state)) - (setq indent (ruby-indent-size (current-column) (nth 2 state)))) - (t - (goto-char parse-start) - (back-to-indentation) - (setq indent (ruby-indent-size (current-column) (nth 2 state)))))) - (t - (setq indent (+ (current-column) ruby-indent-level))))) - - ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest - (setq indent (ruby-indent-size (current-column) (nth 2 state))))) - - (cond - (indent - (goto-char indent-point) - (end-of-line) - (setq eol (point)) - (beginning-of-line) - (cond - ((re-search-forward ruby-negative eol t) - (and (not (eq ?_ (char-after (match-end 0)))) - (setq indent (- indent ruby-indent-level)))) - ;;operator terminated lines - ((and - (save-excursion - (beginning-of-line) - (not (bobp))) - (or (null (car (nth 1 state))) ;not in parens - (and (eq (car (nth 1 state)) ?\{) - (save-excursion ;except non-block braces - (goto-char (cdr (nth 1 state))) - (or (bobp) (forward-char -1)) - (not (ruby-expr-beg)))))) - ;; goto beginning of non-empty no-comment line - (let (end done) - (while (not done) - (skip-chars-backward " \t\n") - (setq end (point)) - (beginning-of-line) - (if (re-search-forward "^\\s *#" end t) - (beginning-of-line) - (setq done t)))) - (setq bol (point)) - (end-of-line) - (skip-chars-backward " \t") - (and (re-search-backward "#" (save-excursion - (beginning-of-line) - (point)) t) - (setq state (ruby-parse-region parse-start (point))) - (nth 0 state) - (goto-char (nth 0 state))) - (or (bobp) (forward-char -1)) - (and - (or (and (looking-at ruby-symbol-re) - (skip-chars-backward ruby-symbol-chars) - (looking-at ruby-block-op-re) - (save-excursion - (goto-char (match-end 0)) - (not (looking-at "[a-z_]")))) - (and (looking-at ruby-operator-re) - (or (not (eq ?/ (char-after (point)))) - (null (nth 0 (ruby-parse-region parse-start (point))))) - (not (eq (char-after (1- (point))) ?$)) - (or (not (eq ?| (char-after (point)))) - (save-excursion - (or (eolp) (forward-char -1)) - (and (search-backward "|") - (skip-chars-backward " \t\n") - (and (not (eolp)) - (progn - (forward-char -1) - (not (looking-at "\\{"))) - (progn - (forward-word -1) - (not (looking-at "do\\>[^_]"))))))))) - (setq indent (+ indent ruby-indent-level))))))) - indent))) - -(defun ruby-electric-brace (arg) - (interactive "P") - (self-insert-command (prefix-numeric-value arg)) - (ruby-indent-line t)) - -(defun ruby-beginning-of-defun (&optional arg) - "Move backward to next beginning-of-defun. -With argument, do this that many times. -Returns t unless search stops due to end of buffer." - (interactive "p") - (and (re-search-backward (concat "^\\(" ruby-block-beg-re "\\)\\b") - nil 'move (or arg 1)) - (progn (beginning-of-line) t))) - -(defun ruby-beginning-of-indent () - (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\b") - nil 'move) - (progn - (beginning-of-line) - t))) - -(defun ruby-end-of-defun (&optional arg) - "Move forward to next end of defun. -An end of a defun is found by moving forward from the beginning of one." - (interactive "p") - (and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\b[^_]") - nil 'move (or arg 1)) - (progn (beginning-of-line) t)) - (forward-line 1)) - -(defun ruby-move-to-block (n) - (let (start pos done down) - (setq start (ruby-calculate-indent)) - (if (eobp) - nil - (while (and (not (bobp)) (not done)) - (forward-line n) - (cond - ((looking-at "^$")) - ((looking-at "^\\s *#")) - (t - (setq pos (current-indentation)) - (cond - ((< start pos) - (setq down t)) - ((and down (= pos start)) - (setq done t)) - ((> start pos) - (setq done t))))) - (if done - (progn - (back-to-indentation) - (if (looking-at ruby-block-mid-re) - (setq done nil))))))) - (back-to-indentation)) - -(defun ruby-beginning-of-block () - "Move backward to next beginning-of-block" - (interactive) - (ruby-move-to-block -1)) - -(defun ruby-end-of-block () - "Move forward to next beginning-of-block" - (interactive) - (ruby-move-to-block 1)) - -(defun ruby-reindent-then-newline-and-indent () - (interactive "*") - (save-excursion - (delete-region (point) (progn (skip-chars-backward " \t") (point)))) - (newline) - (save-excursion - (forward-line -1) - (indent-according-to-mode)) - (indent-according-to-mode)) - -(fset 'ruby-encomment-region (symbol-function 'comment-region)) - -(defun ruby-decomment-region (beg end) - (interactive "r") - (save-excursion - (goto-char beg) - (while (re-search-forward "^\\([ \t]*\\)#" end t) - (replace-match "\\1" nil nil) - (save-excursion - (ruby-indent-line))))) - -(defun ruby-insert-end () - (interactive) - (insert "end") - (ruby-indent-line t) - (end-of-line)) - -(cond - ((featurep 'hilit19) - (hilit-set-mode-patterns - 'ruby-mode - '(("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string) - ("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string) - ("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string) - ("^\\s *#.*$" nil comment) - ("[^$@?\\]\\(#[^$@{\n].*$\\)" 1 comment) - ("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string) - ("^\\s *\\(require\\|load\\).*$" nil include) - ("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl) - ("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun) - ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|unless\\|rescue\\|then\\|when\\|while\\|until\\|do\\)\\>[^_]" 1 defun) - ("[^_]\\<\\(and\\|break\\|next\\|raise\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\|self\\|nil\\)\\>[^_]" 1 keyword) - ("\\$\\(.\\|\\sw+\\)" nil type) - ("[$@].[a-zA-Z_0-9]*" nil struct) - ("^__END__" nil label)))) - - ((featurep 'font-lock) - (or (boundp 'font-lock-variable-name-face) - (setq font-lock-variable-name-face font-lock-type-face)) - (defvar ruby-font-lock-keywords - (list - (cons (concat - "\\(^\\|[^_:.]\\|\\.\\.\\)\\b\\(" - (mapconcat - 'identity - '("alias" - "and" - "begin" - "break" - "case" - "class" - "def" - "do" - "elsif" - "else" - "fail" - "ensure" - "for" - "end" - "if" - "in" - "module" - "next" - "not" - "or" - "raise" - "redo" - "rescue" - "retry" - "return" - "then" - "self" - "super" - "unless" - "undef" - "until" - "when" - "while" - ) - "\\|") - "\\)\\b") - 2) - ;; variables - '("\\(^\\|[^_]\\)\\b\\(nil\\|self\\|true\\|false\\)\\b\\([^_]\\|$\\)" - 2 font-lock-variable-name-face) - ;; variables - '("[$@].[a-zA-Z0-9_]*" - 0 font-lock-variable-name-face) - ;; constants - '("\\(^\\|[^_]\\)\\b\\([A-Z]+[a-zA-Z0-9_]*\\)" - 2 font-lock-type-face) - ;; functions - '("^\\s *def[ \t]+\\([^ \t(]*\\)" - 1 font-lock-function-name-face t)) - "*Additional expressions to highlight in ruby mode.") - (if (and (>= (string-to-int emacs-version) 19) - (not (featurep 'xemacs))) - (add-hook - 'ruby-mode-hook - (lambda () - (make-local-variable 'font-lock-defaults) - (setq font-lock-defaults - '((ruby-font-lock-keywords) nil nil ((?\_ . "w")))))) - (add-hook 'ruby-mode-hook - (lambda () - (setq font-lock-keywords ruby-font-lock-keywords)))))) - -(provide 'ruby-mode) diff --git a/sample/rubydb2x.el b/sample/rubydb2x.el deleted file mode 100644 index a74265fb0e..0000000000 --- a/sample/rubydb2x.el +++ /dev/null @@ -1,104 +0,0 @@ -(require 'gud) -(provide 'rubydb) - -;; ====================================================================== -;; rubydb functions - -;;; History of argument lists passed to rubydb. -(defvar gud-rubydb-history nil) - -(defun gud-rubydb-massage-args (file args) - (cons "-I" (cons "." (cons "-r" (cons "debug" (cons file args)))))) - -;; There's no guarantee that Emacs will hand the filter the entire -;; marker at once; it could be broken up across several strings. We -;; might even receive a big chunk with several markers in it. If we -;; receive a chunk of text which looks like it might contain the -;; beginning of a marker, we save it here between calls to the -;; filter. -(defvar gud-rubydb-marker-acc "") - -(defun gud-rubydb-marker-filter (string) - (save-match-data - (setq gud-marker-acc (concat gud-marker-acc string)) - (let ((output "")) - - ;; Process all the complete markers in this chunk. - (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" - gud-marker-acc) - (setq - - ;; Extract the frame position from the marker. - gud-last-frame - (cons (substring gud-marker-acc (match-beginning 1) (match-end 1)) - (string-to-int (substring gud-marker-acc - (match-beginning 2) - (match-end 2)))) - - ;; Append any text before the marker to the output we're going - ;; to return - we don't include the marker in this text. - output (concat output - (substring gud-marker-acc 0 (match-beginning 0))) - - ;; Set the accumulator to the remaining text. - gud-marker-acc (substring gud-marker-acc (match-end 0)))) - - ;; Does the remaining text look like it might end with the - ;; beginning of another marker? If it does, then keep it in - ;; gud-marker-acc until we receive the rest of it. Since we - ;; know the full marker regexp above failed, it's pretty simple to - ;; test for marker starts. - (if (string-match "\032.*\\'" gud-marker-acc) - (progn - ;; Everything before the potential marker start can be output. - (setq output (concat output (substring gud-marker-acc - 0 (match-beginning 0)))) - - ;; Everything after, we save, to combine with later input. - (setq gud-marker-acc - (substring gud-marker-acc (match-beginning 0)))) - - (setq output (concat output gud-marker-acc) - gud-marker-acc "")) - - output))) - -(defun gud-rubydb-find-file (f) - (find-file-noselect f)) - -(defvar rubydb-command-name "ruby" - "File name for executing ruby.") - -;;;###autoload -(defun rubydb (command-line) - "Run rubydb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run rubydb (like this): " - (if (consp gud-rubydb-history) - (car gud-rubydb-history) - (concat rubydb-command-name " ")) - nil nil - '(gud-rubydb-history . 1)))) - - (gud-overload-functions '((gud-massage-args . gud-rubydb-massage-args) - (gud-marker-filter . gud-rubydb-marker-filter) - (gud-find-file . gud-rubydb-find-file) - )) - (gud-common-init command-line) - - (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.") -; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") - (gud-def gud-step "s" "\C-s" "Step one source line with display.") - (gud-def gud-next "n" "\C-n" "Step one line (skip functions).") - (gud-def gud-cont "c" "\C-r" "Continue with display.") - (gud-def gud-finish "finish" "\C-f" "Finish executing current function.") - (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") - (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") - (gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.") - - (setq comint-prompt-regexp "^(rdb:-) ") - (setq paragraph-start comint-prompt-regexp) - (run-hooks 'rubydb-mode-hook) - ) diff --git a/sample/rubydb3x.el b/sample/rubydb3x.el deleted file mode 100644 index 9d4e31f90e..0000000000 --- a/sample/rubydb3x.el +++ /dev/null @@ -1,104 +0,0 @@ -(require 'gud) -(provide 'rubydb) - -;; ====================================================================== -;; rubydb functions - -;;; History of argument lists passed to rubydb. -(defvar gud-rubydb-history nil) - -(defun gud-rubydb-massage-args (file args) - (cons "-r" (cons "debug" args))) - -;; There's no guarantee that Emacs will hand the filter the entire -;; marker at once; it could be broken up across several strings. We -;; might even receive a big chunk with several markers in it. If we -;; receive a chunk of text which looks like it might contain the -;; beginning of a marker, we save it here between calls to the -;; filter. -(defvar gud-rubydb-marker-acc "") - -(defun gud-rubydb-marker-filter (string) - (setq gud-marker-acc (concat gud-marker-acc string)) - (let ((output "")) - - ;; Process all the complete markers in this chunk. - (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" - gud-marker-acc) - (setq - - ;; Extract the frame position from the marker. - gud-last-frame - (cons (substring gud-marker-acc (match-beginning 1) (match-end 1)) - (string-to-int (substring gud-marker-acc - (match-beginning 2) - (match-end 2)))) - - ;; Append any text before the marker to the output we're going - ;; to return - we don't include the marker in this text. - output (concat output - (substring gud-marker-acc 0 (match-beginning 0))) - - ;; Set the accumulator to the remaining text. - gud-marker-acc (substring gud-marker-acc (match-end 0)))) - - ;; Does the remaining text look like it might end with the - ;; beginning of another marker? If it does, then keep it in - ;; gud-marker-acc until we receive the rest of it. Since we - ;; know the full marker regexp above failed, it's pretty simple to - ;; test for marker starts. - (if (string-match "\032.*\\'" gud-marker-acc) - (progn - ;; Everything before the potential marker start can be output. - (setq output (concat output (substring gud-marker-acc - 0 (match-beginning 0)))) - - ;; Everything after, we save, to combine with later input. - (setq gud-marker-acc - (substring gud-marker-acc (match-beginning 0)))) - - (setq output (concat output gud-marker-acc) - gud-marker-acc "")) - - output)) - -(defun gud-rubydb-find-file (f) - (save-excursion - (let ((buf (find-file-noselect f))) - (set-buffer buf) - (gud-make-debug-menu) - buf))) - -(defvar rubydb-command-name "ruby" - "File name for executing ruby.") - -;;;###autoload -(defun rubydb (command-line) - "Run rubydb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run rubydb (like this): " - (if (consp gud-rubydb-history) - (car gud-rubydb-history) - (concat rubydb-command-name " ")) - nil nil - '(gud-rubydb-history . 1)))) - - (gud-common-init command-line 'gud-rubydb-massage-args - 'gud-rubydb-marker-filter 'gud-rubydb-find-file) - - (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.") -; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") - (gud-def gud-step "s" "\C-s" "Step one source line with display.") - (gud-def gud-next "n" "\C-n" "Step one line (skip functions).") - (gud-def gud-cont "c" "\C-r" "Continue with display.") - (gud-def gud-finish "finish" "\C-f" "Finish executing current function.") - (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") - (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") - (gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.") - - (setq comint-prompt-regexp "^(rdb:-) ") - (setq paragraph-start comint-prompt-regexp) - (run-hooks 'rubydb-mode-hook) - ) diff --git a/st.c b/st.c index a48d11e9aa..a4bee22c61 100644 --- a/st.c +++ b/st.c @@ -66,10 +66,9 @@ static void rehash(); #define MINSIZE 8 /* -Table of irreducible polynomials to efficiently cycle through -GF(2^n)-{0}, 2<=n<=30. +Table of prime numbers 2^n+a, 2<=n<=30. */ -static long polys[] = { +static long primes[] = { 8 + 3, 16 + 3, 32 + 5, @@ -108,10 +107,10 @@ new_size(size) int i, newsize; for (i = 0, newsize = MINSIZE; - i < sizeof(polys)/sizeof(polys[0]); + i < sizeof(primes)/sizeof(primes[0]); i++, newsize <<= 1) { - if (newsize > size) return polys[i]; + if (newsize > size) return primes[i]; } /* Ran out of polynomials */ return -1; /* should raise exception */ diff --git a/string.c b/string.c index 710de1aa48..a97319e5c7 100644 --- a/string.c +++ b/string.c @@ -1345,7 +1345,7 @@ rb_str_inspect(str) CHECK(1); *b++ = c; } - else if (c == '"' || c == '\''|| c == '\\') { + else if (c == '"'|| c == '\\') { CHECK(2); *b++ = '\\'; *b++ = c; @@ -1414,7 +1414,7 @@ rb_str_dump(str) while (p < pend) { char c = *p++; switch (c) { - case '"': case '\'': case '\\': + case '"': case '\\': case '\n': case '\r': case '\t': case '\f': case '\013': case '\007': case '\033': @@ -1440,7 +1440,7 @@ rb_str_dump(str) while (p < pend) { char c = *p++; - if (c == '"' || c == '\'' || c == '\\') { + if (c == '"' || c == '\\') { *q++ = '\\'; *q++ = c; } diff --git a/top.sed b/top.sed index bb9a96c146..a9ec12f7b6 100644 --- a/top.sed +++ b/top.sed @@ -33,7 +33,7 @@ s%@AR@%ar%g s%@INSTALL_PROGRAM@%${INSTALL}%g s%@INSTALL_DATA@%${INSTALL} -m 644%g s%@SET_MAKE@%%g -s%@LIBOBJS@% crypt.o flock.o snprintf.o%g +s%@LIBOBJS@% crypt.o flock.o vsnprintf.o%g s%@ALLOCA@%%g s%@DLDFLAGS@%%g s%@STATIC@%%g diff --git a/variable.c b/variable.c index 85d6eafdaa..a0502315bb 100644 --- a/variable.c +++ b/variable.c @@ -129,7 +129,7 @@ classname(klass) path = rb_ivar_get(klass, classid); if (!NIL_P(path)) { path = rb_str_new2(rb_id2name(FIX2INT(path))); - rb_ivar_set(klass, classid, path); + rb_ivar_set(klass, rb_intern("__classpath__"), path); st_delete(RCLASS(klass)->iv_tbl, &classid, 0); } } @@ -205,12 +205,7 @@ rb_name_class(klass, id) VALUE klass; ID id; { - if (rb_cString) { - rb_iv_set(klass, "__classpath__", rb_str_new2(rb_id2name(id))); - } - else { - rb_iv_set(klass, "__classid__", INT2FIX(id)); - } + rb_iv_set(klass, "__classid__", INT2FIX(id)); } static st_table *autoload_tbl = 0; @@ -690,6 +685,133 @@ rb_alias_variable(name1, name2) entry1->marker = entry2->marker; } +static int special_generic_ivar = 0; +static st_table *generic_iv_tbl; + +static VALUE +generic_ivar_get(obj, id) + VALUE obj; + ID id; +{ + st_table *tbl; + VALUE val; + + if (!generic_iv_tbl) return Qnil; + if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qnil; + if (st_lookup(tbl, id, &val)) { + return val; + } + return Qnil; +} + +static void +generic_ivar_set(obj, id, val) + VALUE obj; + ID id; + VALUE val; +{ + st_table *tbl; + + if (rb_special_const_p(obj)) { + special_generic_ivar = 1; + } + if (!generic_iv_tbl) { + generic_iv_tbl = st_init_numtable(); + } + + if (!st_lookup(generic_iv_tbl, obj, &tbl)) { + FL_SET(obj, FL_EXIVAR); + tbl = st_init_numtable(); + st_add_direct(generic_iv_tbl, obj, tbl); + st_add_direct(tbl, id, val); + return; + } + st_insert(tbl, id, val); +} + +static VALUE +generic_ivar_defined(obj, id) + VALUE obj; + ID id; +{ + st_table *tbl; + VALUE val; + + if (!generic_iv_tbl) return Qfalse; + if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qfalse; + if (st_lookup(tbl, id, &val)) { + return Qtrue; + } + return Qfalse; +} + +static VALUE +generic_ivar_remove(obj, id) + VALUE obj; + ID id; +{ + st_table *tbl; + VALUE val; + + if (!generic_iv_tbl) return Qnil; + if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qnil; + st_delete(tbl, &id, &val); + if (tbl->num_entries == 0) { + st_delete(generic_iv_tbl, &obj, &tbl); + st_free_table(tbl); + } + return val; +} + +static int +givar_mark_i(key, value) + ID key; + VALUE value; +{ + rb_gc_mark(value); + return ST_CONTINUE; +} + +void +rb_mark_generic_ivar(obj) + VALUE obj; +{ + st_table *tbl; + + if (st_lookup(generic_iv_tbl, obj, &tbl)) { + st_foreach(tbl, givar_mark_i, 0); + } +} + +static int +givar_i(obj, tbl) + VALUE obj; + st_table *tbl; +{ + if (rb_special_const_p(obj)) { + st_foreach(tbl, givar_mark_i, 0); + } + return ST_CONTINUE; +} + +void +rb_mark_generic_ivar_tbl() +{ + if (special_generic_ivar == 0) return; + if (!generic_iv_tbl) return; + st_foreach(generic_iv_tbl, givar_i, 0); +} + +void +rb_free_generic_ivar(obj) + VALUE obj; +{ + st_table *tbl; + + if (st_delete(generic_iv_tbl, &obj, &tbl)) + st_free_table(tbl); +} + VALUE rb_ivar_get(obj, id) VALUE obj; @@ -701,12 +823,13 @@ rb_ivar_get(obj, id) case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val)) return val; - return Qnil; + break; default: - rb_raise(rb_eTypeError, "class %s can not have instance variables", - rb_class2name(CLASS_OF(obj))); + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) + return generic_ivar_get(obj, id); break; } if (rb_verbose) { @@ -725,14 +848,14 @@ rb_ivar_set(obj, id, val) case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: if (rb_safe_level() >= 4 && !FL_TEST(obj, FL_TAINT)) rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable(); st_insert(ROBJECT(obj)->iv_tbl, id, val); break; default: - rb_raise(rb_eTypeError, "class %s can not have instance variables", - rb_class2name(CLASS_OF(obj))); + generic_ivar_set(obj, id, val); break; } return val; @@ -749,9 +872,14 @@ rb_ivar_defined(obj, id) case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0)) return Qtrue; break; + default: + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) + return generic_ivar_defined(obj, id); + break; } return Qfalse; } @@ -778,11 +906,22 @@ rb_obj_instance_variables(obj) case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: ary = rb_ary_new(); if (ROBJECT(obj)->iv_tbl) { st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary); } return ary; + default: + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { + st_table *tbl; + + if (st_lookup(generic_iv_tbl, obj, &tbl)) { + ary = rb_ary_new(); + st_foreach(tbl, ivar_i, ary); + return ary; + } + } } return Qnil; } @@ -803,13 +942,14 @@ rb_obj_remove_instance_variable(obj, name) case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: if (ROBJECT(obj)->iv_tbl) { st_delete(ROBJECT(obj)->iv_tbl, &id, &val); } break; default: - rb_raise(rb_eTypeError, "object %s can not have instance variables", - rb_class2name(CLASS_OF(obj))); + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) + return generic_ivar_remove(obj, id); break; } return val; diff --git a/version.h b/version.h index 8f49f67368..18f352c9cf 100644 --- a/version.h +++ b/version.h @@ -1,2 +1,2 @@ #define RUBY_VERSION "1.1d0" -#define VERSION_DATE "98/09/08" +#define VERSION_DATE "98/12/16" -- cgit v1.2.3