[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:126

From: ko1 atdot.net
Date: 27 Oct 2005 23:53:46 -0000
Subject: [yarv-diff:126] r282 - in trunk: . benchmark lib rb yarvtest

Author: ko1
Date: 2005-10-28 08:53:45 +0900 (Fri, 28 Oct 2005)
New Revision: 282

Added:
   trunk/lib/getoptlong.rb
   trunk/lib/getopts.rb
   trunk/lib/mkmf.rb
   trunk/lib/rational.rb
Modified:
   trunk/ChangeLog
   trunk/benchmark/bmx_temp.rb
   trunk/benchmark/run_rite.rb
   trunk/common.mk
   trunk/compile.c
   trunk/error.c
   trunk/eval.c
   trunk/eval_load.c
   trunk/eval_method.h
   trunk/eval_proc.c
   trunk/insns.def
   trunk/lib/fileutils.rb
   trunk/parse.y
   trunk/rb/yasm.rb
   trunk/test.rb
   trunk/vm.c
   trunk/vm.h
   trunk/vm_dump.c
   trunk/vm_macro.def
   trunk/yarvcore.c
   trunk/yarvtest/test_massign.rb
   trunk/yarvtest/test_method.rb
Log:
	* benchmark/run_rite.rb : add -I options to run benchmark

	* common.mk : pass options to some rules with RUNOPT
	and add -I options

	* compile.c : fix massign with constant

	* yarvtest/test_massign.rb : add tests for above

	* eval_load.c : fix load_wait()

	* eval_method.h : support ruby_cbase()

	* lib/*.rb : add or modify libraries to run on yarv
	* parse.y : change to ANSI C style

	* vm.c : fix making proc process under cfunc/ifunc environment

	* vm_macro.def : fix block pass

	* yarvtest/test_method.rb : add tests for above

	* yarvcore.c : add yarv_obj_is_proc()

	* eval.c : fix rb_obj_is_proc to use yarv_obj_is_proc()



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/ChangeLog	2005-10-27 23:53:45 UTC (rev 282)
@@ -4,6 +4,35 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2005-10-28(Fri) 08:43:29 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* benchmark/run_rite.rb : add -I options to run benchmark
+
+	* common.mk : pass options to some rules with RUNOPT
+	and add -I options
+
+	* compile.c : fix massign with constant
+
+	* yarvtest/test_massign.rb : add tests for above
+
+	* eval_load.c : fix load_wait()
+
+	* eval_method.h : support ruby_cbase()
+
+	* lib/*.rb : add or modify libraries to run on yarv
+	* parse.y : change to ANSI C style
+
+	* vm.c : fix making proc process under cfunc/ifunc environment
+
+	* vm_macro.def : fix block pass
+
+	* yarvtest/test_method.rb : add tests for above
+
+	* yarvcore.c : add yarv_obj_is_proc()
+
+	* eval.c : fix rb_obj_is_proc to use yarv_obj_is_proc()
+
+
 2005-10-27(Thu) 11:50:15 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* some files : import from ruby 1.9.0 (2005-10-12)

Modified: trunk/benchmark/bmx_temp.rb
===================================================================
--- trunk/benchmark/bmx_temp.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/benchmark/bmx_temp.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -1,7 +1,10 @@
-Array.new(100000000).each{}
-__END__
+require 'rational'
 
-10000000.times{
-}
+a = Rational(1, 2)
+b = Rational(3, 4)
+i = 0
+while i<100000
+  i+=1
+  a-b
+end
 
-

Modified: trunk/benchmark/run_rite.rb
===================================================================
--- trunk/benchmark/run_rite.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/benchmark/run_rite.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -45,7 +45,7 @@
 
 def benchmark file, bin
   m = Benchmark.measure{
-    `#{bin} #{file}`
+    `#{bin} #{$opts} #{file}`
   }
   sec = '%.3f' % m.real
   puts " #{sec}"
@@ -69,6 +69,8 @@
       $yarv_program = $1
     when /\A--ruby-program=(.+)/
       $ruby_program = $1
+    when /\A--opts=(.+)/
+      $opts = $1
     when /\A(--yarv)|(-y)/
       $yarvonly = true
     when /\A(--ruby)|(-r)/

Modified: trunk/common.mk
===================================================================
--- trunk/common.mk	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/common.mk	2005-10-27 23:53:45 UTC (rev 282)
@@ -429,7 +429,7 @@
 	$(BASERUBY) -I$(srcdir)/lib $(srcdir)/test.rb $(MINIRUBY) $(BASERUBY) $(RUNOPT)
 
 run: all
-	$(MINIRUBY) $(srcdir)/test.rb
+	$(MINIRUBY) -I$(srcdir)/lib $(srcdir)/test.rb $(RUNOPT)
 
 parse: all
 	$(MINIRUBY) $(srcdir)/rb/parse.rb $(srcdir)/test.rb
@@ -442,10 +442,10 @@
 	$(MINIRUBY) $(srcdir)/sample/test.rb
 
 benchmark: all
-	$(BASERUBY) -I$(srcdir) $(srcdir)/benchmark/run_rite.rb $(OPT) $(ITEMS) --yarv-program=$(MINIRUBY) --ruby-program=$(BASERUBY)
+	$(BASERUBY) -I$(srcdir) -I$(srcdir)/lib $(srcdir)/benchmark/run_rite.rb $(OPT) $(ITEMS) --yarv-program=$(MINIRUBY) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib
 
 tbench: all
-	$(BASERUBY) -I$(srcdir) $(srcdir)/benchmark/run_rite.rb bmx $(OPT) --yarv-program=$(MINIRUBY) --ruby-program=$(BASERUBY)
+	$(BASERUBY) -I$(srcdir) -I$(srcdir)/lib $(srcdir)/benchmark/run_rite.rb bmx $(OPT) --yarv-program=$(MINIRUBY) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib
 
 bench-item: all
 	$(BASERUBY) -I$(srcdir) $(srcdir)/benchmark/run_rite.rb bm_$(ITEM) $(OPT) --yarv-program=$(MINIRUBY) --ruby-program=$(BASERUBY)
@@ -461,4 +461,4 @@
 	echo run > run.gdb
 
 gdb: all run.gdb
-	gdb -x run.gdb --quiet --args $(MINIRUBY) -I$(srcdir) $(srcdir)/test.rb
+	gdb -x run.gdb --quiet --args $(MINIRUBY) -I$(srcdir)/lib $(srcdir)/test.rb

Modified: trunk/compile.c
===================================================================
--- trunk/compile.c	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/compile.c	2005-10-27 23:53:45 UTC (rev 282)
@@ -331,8 +331,9 @@
 {
 #if CPDEBUG > 0
   int flag = 0;
-  LINK_ELEMENT* list = anchor->anchor.next,
-                   * plist= &anchor->anchor;
+  LINK_ELEMENT* list  =  anchor->anchor.next,
+              * plist = &anchor->anchor;
+
   while(list){
     if(plist != list->prev){
       flag += 1;
@@ -1903,9 +1904,12 @@
 
   default:{
     DECL_ANCHOR(anchor);
-    
     COMPILE_POPED(anchor, "masgn lhs", node);
-    ADD_ELEM(ret, LAST_ELEMENT(anchor));
+    // dump_disasm_list(FIRST_ELEMENT(anchor));
+    REMOVE_ELEM(FIRST_ELEMENT(anchor));
+    // dump_disasm_list(FIRST_ELEMENT(anchor));
+    ADD_SEQ(ret, anchor);
+    // ADD_ELEM(ret, LAST_ELEMENT(anchor));
   }
   }
   
@@ -2069,6 +2073,7 @@
     estr = "false";
     break;
   case NODE_STR:
+  case NODE_LIT:
     estr = "expression";
     break;
     
@@ -3062,6 +3067,8 @@
     VALUE parent_block = iseqobj->compile_data->current_block;
     iseqobj->compile_data->current_block = Qfalse;
 
+    
+#if SUPPORT_JOKE
     if(nd_type(node) == NODE_VCALL){
       if(node->nd_mid ==idBitblt){
         ADD_INSN(ret, nd_line(node), bitblt);
@@ -3072,8 +3079,6 @@
         break;
       }
     }
-    
-#if SUPPORT_GOTO
     /* only joke */
     {
       static ID goto_id;
@@ -3130,10 +3135,16 @@
         flag |= VM_CALL_ARGS_SPLAT_BIT;
       }
       else if(nd_type(node->nd_args) == NODE_ARGSCAT){
+        NODE *t = node->nd_args->nd_head;
+        for(argc = 0; t; argc++, t = t->nd_next){
+          /* */
+        }
+        argc = I2F(argc+1);
+        
         compile_array(self, iseqobj, args, node->nd_args->nd_head, Qfalse);
         POP_ELEMENT(args);
         
-        argc = I2F(LIST_SIZE(args) + 1);
+        // argc = I2F(LIST_SIZE(args) + 1);
         COMPILE(args, "args(cat: splat)", node->nd_args->nd_body);
 
         flag |= VM_CALL_ARGS_SPLAT_BIT;

Modified: trunk/error.c
===================================================================
--- trunk/error.c	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/error.c	2005-10-27 23:53:45 UTC (rev 282)
@@ -147,24 +147,27 @@
     return Qnil;
 }
 
+void yarv_bug();
+
 void
 rb_bug(const char *fmt, ...)
 {
-    char buf[BUFSIZ];
-    va_list args;
-    FILE *out = stderr;
-    int len = err_position(buf, BUFSIZ);
-
-    if (fwrite(buf, 1, len, out) == len ||
-	fwrite(buf, 1, len, (out = stdout)) == len) {
-	fputs("[BUG] ", out);
-	va_start(args, fmt);
-	vfprintf(out, fmt, args);
-	va_end(args);
-	fprintf(out, "\nruby %s (%s) [%s]\n\n",
-		ruby_version, ruby_release_date, ruby_platform);
-    }
-    abort();
+  char buf[BUFSIZ];
+  va_list args;
+  FILE *out = stderr;
+  int len = err_position(buf, BUFSIZ);
+  
+  if (fwrite(buf, 1, len, out) == len ||
+      fwrite(buf, 1, len, (out = stdout)) == len) {
+    yarv_bug();
+    fputs("[BUG] ", out);
+    va_start(args, fmt);
+    vfprintf(out, fmt, args);
+    va_end(args);
+    fprintf(out, "\nruby %s (%s) [%s]\n\n",
+            ruby_version, ruby_release_date, ruby_platform);
+  }
+  abort();
 }
 
 static struct types {

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/eval.c	2005-10-27 23:53:45 UTC (rev 282)
@@ -487,8 +487,7 @@
 rb_obj_is_proc(proc)
     VALUE proc;
 {
-  // TODO: fix me
-  return Qtrue;
+  return yarv_obj_is_proc(proc);
 }
 
 void

Modified: trunk/eval_load.c
===================================================================
--- trunk/eval_load.c	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/eval_load.c	2005-10-27 23:53:45 UTC (rev 282)
@@ -208,11 +208,22 @@
 }
 
 static int
-load_wait(ftptr)
-    char *ftptr;
+load_wait(char *ftptr)
 {
   // TODO: fix me
+  return Qfalse;
+  /*
+  st_data_t th;
+
+  if (!loading_tbl) return Qfalse;
+  if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return Qfalse;
+  if ((rb_thread_t)th == curr_thread) return Qtrue;
+  do {
+    CHECK_INTS;
+    rb_thread_schedule();
+  } while (st_lookup(loading_tbl, (st_data_t)ftptr, &th));
   return Qtrue;
+   */
 }
 
 /*
@@ -331,82 +342,80 @@
 }
 
 VALUE
-rb_require_safe(fname, safe)
-    VALUE fname;
-    int safe;
+rb_require_safe(VALUE fname, int safe)
 {
-    VALUE result = Qnil;
-    volatile VALUE errinfo = GET_THREAD()->errinfo;
-    int state;
-    struct {
-	NODE *node;
-	ID this_func, callee;
-	int vmode, safe;
-    } volatile saved;
-    char *volatile ftptr = 0;
+  VALUE result = Qnil;
+  volatile VALUE errinfo = GET_THREAD()->errinfo;
+  int state;
+  struct {
+    NODE *node;
+    ID this_func, callee;
+    int vmode, safe;
+  } volatile saved;
+  char *volatile ftptr = 0;
 
-    saved.vmode = scope_vmode;
-    saved.node = ruby_current_node;
-    saved.safe = ruby_safe_level;
-    PUSH_TAG(PROT_NONE);
-    if ((state = EXEC_TAG()) == 0) {
-	VALUE path;
-	long handle;
-	int found;
+  saved.vmode = scope_vmode;
+  saved.node = ruby_current_node;
+  saved.safe = ruby_safe_level;
+  PUSH_TAG(PROT_NONE);
+  if ((state = EXEC_TAG()) == 0) {
+    VALUE path;
+    long handle;
+    int found;
 
-	ruby_safe_level = safe;
-	FilePathValue(fname);
-	*(volatile VALUE *)&fname = rb_str_new4(fname);
-	found = search_required(fname, &path);
-	if (found) {
-	    if (!path || load_wait(RSTRING(path)->ptr)) {
-		result = Qfalse;
-	    }
-	    else {
-		ruby_safe_level = 0;
-		switch (found) {
-		  case 'r':
-		    /* loading ruby library should be serialized. */
-		    if (!loading_tbl) {
-			loading_tbl = st_init_strtable();
-		    }
-		    /* partial state */
-		    ftptr = ruby_strdup(RSTRING(path)->ptr);
-		    st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)rb_vm_curr_thread());
-		    rb_load(path, 0);
-		    break;
+    ruby_safe_level = safe;
+    FilePathValue(fname);
+    *(volatile VALUE *)&fname = rb_str_new4(fname);
+    found = search_required(fname, &path);
+    if (found) {
+      if (!path || load_wait(RSTRING(path)->ptr)) {
+        result = Qfalse;
+      }
+      else {
+        ruby_safe_level = 0;
+        switch (found) {
+        case 'r':
+          /* loading ruby library should be serialized. */
+          if (!loading_tbl) {
+            loading_tbl = st_init_strtable();
+          }
+          /* partial state */
+          ftptr = ruby_strdup(RSTRING(path)->ptr);
+          st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)rb_vm_curr_thread());
+          rb_load(path, 0);
+          break;
 
-		  case 's':
-		    ruby_current_node = 0;
-		    ruby_sourcefile = rb_source_filename(RSTRING(path)->ptr);
-		    ruby_sourceline = 0;
-		    SCOPE_SET(SCOPE_PUBLIC);
-		    handle = (long)dln_load(RSTRING(path)->ptr);
-		    rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
-		    break;
-		}
-		rb_provide_feature(path);
-		result = Qtrue;
-	    }
-	}
+        case 's':
+          ruby_current_node = 0;
+          ruby_sourcefile = rb_source_filename(RSTRING(path)->ptr);
+          ruby_sourceline = 0;
+          SCOPE_SET(SCOPE_PUBLIC);
+          handle = (long)dln_load(RSTRING(path)->ptr);
+          rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
+          break;
+        }
+        rb_provide_feature(path);
+        result = Qtrue;
+      }
     }
-    POP_TAG();
-    ruby_current_node = saved.node;
-    ruby_set_current_source();
-    SCOPE_SET(saved.vmode);
-    ruby_safe_level = saved.safe;
-    if (ftptr) {
-	if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */
-	    free(ftptr);
-	}
+  }
+  POP_TAG();
+  ruby_current_node = saved.node;
+  ruby_set_current_source();
+  SCOPE_SET(saved.vmode);
+  ruby_safe_level = saved.safe;
+  if (ftptr) {
+    if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */
+      free(ftptr);
     }
-    if (state) JUMP_TAG(state);
-    if (NIL_P(result)) {
-	load_failed(fname);
-    }
-    GET_THREAD()->errinfo = errinfo;
+  }
+  if (state) JUMP_TAG(state);
+  if (NIL_P(result)) {
+    load_failed(fname);
+  }
+  GET_THREAD()->errinfo = errinfo;
 
-    return result;
+  return result;
 }
 
 VALUE

Modified: trunk/eval_method.h
===================================================================
--- trunk/eval_method.h	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/eval_method.h	2005-10-27 23:53:45 UTC (rev 282)
@@ -413,8 +413,17 @@
 
 static VALUE
 ruby_cbase(){
-  UNSUPPORTED(ruby_cbase);
-  return Qnil;
+  yarv_thread_t *th = GET_THREAD();
+  yarv_iseq_t *iseq = th->cfp->iseq;
+  VALUE cref;
+  
+  if(iseq->klass_nest_stack){
+    cref = iseq->klass_nest_stack;
+  }
+  else{
+    cref = th->klass_nest_stack;
+  }
+  return rb_ary_entry(cref, -1);
 }
 
 static NODE *
@@ -424,52 +433,50 @@
 }
 
 void
-rb_undef(klass, id)
-    VALUE klass;
-    ID id;
+rb_undef(VALUE klass, ID id)
 {
-    VALUE origin;
-    NODE *body;
+  VALUE origin;
+  NODE *body;
 
-    if (ruby_cbase() == rb_cObject && klass == rb_cObject) {
-	rb_secure(4);
-    }
-    if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id));
-    }
-    rb_frozen_class_p(klass);
-    if (id == __id__ || id == __send__ || id == init) {
-	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
-    }
-    body = search_method(klass, id, &origin);
-    if (!body || !body->nd_body) {
-	char *s0 = " class";
-	VALUE c = klass;
+  if (ruby_cbase() == rb_cObject && klass == rb_cObject) {
+    rb_secure(4);
+  }
+  if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) {
+    rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id));
+  }
+  rb_frozen_class_p(klass);
+  if (id == __id__ || id == __send__ || id == init) {
+    rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
+  }
+  body = search_method(klass, id, &origin);
+  if (!body || !body->nd_body) {
+    char *s0 = " class";
+    VALUE c = klass;
 
-	if (FL_TEST(c, FL_SINGLETON)) {
-	    VALUE obj = rb_iv_get(klass, "__attached__");
+    if (FL_TEST(c, FL_SINGLETON)) {
+      VALUE obj = rb_iv_get(klass, "__attached__");
 
-	    switch (TYPE(obj)) {
-	      case T_MODULE:
-	      case T_CLASS:
-		c = obj;
-		s0 = "";
-	    }
-	}
-	else if (TYPE(c) == T_MODULE) {
-	    s0 = " module";
-	}
-	rb_name_error(id, "undefined method `%s' for%s `%s'",
-		      rb_id2name(id),s0,rb_class2name(c));
+      switch (TYPE(obj)) {
+      case T_MODULE:
+      case T_CLASS:
+        c = obj;
+        s0 = "";
+      }
     }
-    rb_add_method(klass, id, 0, NOEX_PUBLIC);
-    if (FL_TEST(klass, FL_SINGLETON)) {
-	rb_funcall(rb_iv_get(klass, "__attached__"),
-		   singleton_undefined, 1, ID2SYM(id));
+    else if (TYPE(c) == T_MODULE) {
+      s0 = " module";
     }
-    else {
-	rb_funcall(klass, undefined, 1, ID2SYM(id));
-    }
+    rb_name_error(id, "undefined method `%s' for%s `%s'",
+                  rb_id2name(id),s0,rb_class2name(c));
+  }
+  rb_add_method(klass, id, 0, NOEX_PUBLIC);
+  if (FL_TEST(klass, FL_SINGLETON)) {
+    rb_funcall(rb_iv_get(klass, "__attached__"),
+               singleton_undefined, 1, ID2SYM(id));
+  }
+  else {
+    rb_funcall(klass, undefined, 1, ID2SYM(id));
+  }
 }
 
 /*

Modified: trunk/eval_proc.c
===================================================================
--- trunk/eval_proc.c	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/eval_proc.c	2005-10-27 23:53:45 UTC (rev 282)
@@ -151,7 +151,6 @@
   }
   cfp = YARV_PREVIOUS_CONTROL_FRAME(cfp);
   procval = th_make_proc(th, cfp, block);
-
   if(is_lambda){
     // TODO: lambda or proc
   }

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/insns.def	2005-10-27 23:53:45 UTC (rev 282)
@@ -1354,7 +1354,6 @@
   }
 }
 
-
 /**
   @c method/iterator
   @e return from this scope.

Modified: trunk/lib/fileutils.rb
===================================================================
--- trunk/lib/fileutils.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/lib/fileutils.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -1488,7 +1488,7 @@
 
   METHODS = singleton_methods() - %w( private_module_function
       commands options have_option? options_of collect_method )
-
+if false
   # 
   # This module has all methods of FileUtils module, but it outputs messages
   # before acting.  This equates to passing the <tt>:verbose</tt> flag to
@@ -1564,5 +1564,5 @@
       end
     end
   end
-
 end
+end

Added: trunk/lib/getoptlong.rb
===================================================================
--- trunk/lib/getoptlong.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/lib/getoptlong.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -0,0 +1,481 @@
+#                                                         -*- Ruby -*-
+# Copyright (C) 1998, 1999, 2000  Motoyuki Kasahara
+#
+# You may redistribute it and/or modify it under the same license
+# terms as Ruby.
+#
+
+#
+# Documents and latest version of `getoptlong.rb' are found at:
+#    http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
+#
+
+#
+# Parse command line options just like GNU getopt_long().
+#
+class GetoptLong
+  #
+  # Orderings.
+  #
+  ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
+
+  #
+  # Argument flags.
+  #
+  ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
+    OPTIONAL_ARGUMENT = 2]
+
+  #
+  # Status codes.
+  #
+  STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
+
+  #
+  # Error types.
+  #
+  class Error  < StandardError; end
+  class AmbiguousOption   < Error; end
+  class NeedlessArgument < Error; end
+  class MissingArgument  < Error; end
+  class InvalidOption    < Error; end
+
+  #
+  # The arguments are passed to new() as an array of arrays. Each
+  # subarray has a number of option names which carry the same
+  # meaning, and a ARGUMENT_FLAG, being one of
+  # GetoptLong::NO_ARGUMENT, GetoptLong::REQUIRED_ARGUMENT or
+  # GetoptLong::OPTIONAL_ARGUMENT.  These determine whether the
+  # option takes an argument or not, or whether it is optional The
+  # actual processing is done later with #each().
+  #
+  def initialize(*arguments)
+    #
+    # Current ordering.
+    #
+    if ENV.include?('POSIXLY_CORRECT')
+      @ordering = REQUIRE_ORDER
+    else
+      @ordering = PERMUTE
+    end
+
+    #
+    # Hash table of option names.
+    # Keys of the table are option names, and their values are canonical
+    # names of the options.
+    #
+    @canonical_names = Hash.new
+
+    #
+    # Hash table of argument flags.
+    # Keys of the table are option names, and their values are argument
+    # flags of the options.
+    #
+    @argument_flags = Hash.new
+
+    #
+    # Whether error messages are output to $deferr.
+    #
+    @quiet = FALSE
+
+    #
+    # Status code.
+    #
+    @status = STATUS_YET
+
+    #
+    # Error code.
+    #
+    @error = nil
+
+    #
+    # Error message.
+    #
+    @error_message = nil
+
+    #
+    # Rest of catenated short options.
+    #
+    @rest_singles = ''
+
+    #
+    # List of non-option-arguments.
+    # Append them to ARGV when option processing is terminated.
+    #
+    @non_option_arguments = Array.new
+
+    if 0 < arguments.length
+      set_options(*arguments)
+    end
+  end
+
+  #
+  # Set the handling of the ordering of options.  The supplied
+  # argument ordering must be a member of ORDERINGS, i.e one of
+  # GetoptLong::REQUIRE_ORDER, GetoptLong::PERMUTE,
+  # GetoptLong::RETURN_IN_ORDER.  A RuntimeError is raised if
+  # option processing has already started.
+  #
+  def ordering=(ordering)
+    #
+    # The method is failed if option processing has already started.
+    #
+    if @status != STATUS_YET
+      set_error(ArgumentError, "argument error")
+      raise RuntimeError,
+	"invoke ordering=, but option processing has already started"
+    end
+
+    #
+    # Check ordering.
+    #
+    if !ORDERINGS.include?(ordering)
+      raise ArgumentError, "invalid ordering `#{ordering}'"
+    end
+    if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
+      @ordering = REQUIRE_ORDER
+    else
+      @ordering = ordering
+    end
+  end
+
+  #
+  # Return ordering.
+  #
+  attr_reader :ordering
+
+  #
+  # Set options
+  #
+  def set_options(*arguments)
+    #
+    # The method is failed if option processing has already started.
+    #
+    if @status != STATUS_YET
+      raise RuntimeError, 
+	"invoke set_options, but option processing has already started"
+    end
+
+    #
+    # Clear tables of option names and argument flags.
+    #
+    @canonical_names.clear
+    @argument_flags.clear
+
+    arguments.each do |arg|
+      #
+      # Each argument must be an Array.
+      #
+      if !arg.is_a?(Array)
+	raise ArgumentError, "the option list contains non-Array argument"
+      end
+
+      #
+      # Find an argument flag and it set to `argument_flag'.
+      #
+      argument_flag = nil
+      arg.each do |i|
+	if ARGUMENT_FLAGS.include?(i)
+	  if argument_flag != nil
+	    raise ArgumentError, "too many argument-flags"
+	  end
+	  argument_flag = i
+	end
+      end
+      raise ArgumentError, "no argument-flag" if argument_flag == nil
+
+      canonical_name = nil
+      arg.each do |i|
+	#
+	# Check an option name.
+	#
+	next if i == argument_flag
+	begin
+	  if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
+	    raise ArgumentError, "an invalid option `#{i}'"
+	  end
+	  if ( canonical_names.include?(i))
+	    raise ArgumentError, "option redefined `#{i}'"
+	  end
+	rescue
+	  @canonical_names.clear
+	  @argument_flags.clear
+	  raise
+	end
+
+	#
+	# Register the option (`i') to the `@canonical_names' and 
+	# `@canonical_names' Hashes.
+	#
+	if canonical_name == nil
+	  canonical_name = i
+	end
+	@canonical_names[i] = canonical_name
+	@argument_flags[i] = argument_flag
+      end
+      raise ArgumentError, "no option name" if canonical_name == nil
+    end
+    return self
+  end
+
+  #
+  # Set/Unset `quiet' mode.
+  #
+  attr_writer :quiet
+
+  #
+  # Return the flag of `quiet' mode.
+  #
+  attr_reader :quiet
+
+  #
+  # `quiet?' is an alias of `quiet'.
+  #
+  alias quiet? quiet
+
+  #
+  # Terminate option processing.
+  #
+  def terminate
+    return nil if @status == STATUS_TERMINATED
+    raise RuntimeError, "an error has occured" if @error != nil
+
+    @status = STATUS_TERMINATED
+    @non_option_arguments.reverse_each do |argument|
+      ARGV.unshift(argument)
+    end
+
+    @canonical_names = nil
+    @argument_flags = nil
+    @rest_singles = nil
+    @non_option_arguments = nil
+
+    return self
+  end
+
+  #
+  # Examine whether option processing is terminated or not.
+  #
+  def terminated?
+    return @status == STATUS_TERMINATED
+  end
+
+  #
+  # Set an error (a protected method).
+  #
+  def set_error(type, message)
+    $deferr.print("#{$0}: #{message}\n") if !@quiet
+
+    @error = type
+    @error_message = message
+    @canonical_names = nil
+    @argument_flags = nil
+    @rest_singles = nil
+    @non_option_arguments = nil
+
+    raise type, message
+  end
+  protected :set_error
+
+  #
+  # Examine whether an option processing is failed.
+  #
+  attr_reader :error
+
+  #
+  # `error?' is an alias of `error'.
+  #
+  alias error? error
+
+  #
+  # Return an error message.
+  #
+  def error_message
+    return @error_message
+  end
+
+  #
+  # Get next option name and its argument as an array.
+  # Return nil if the processing is complete (as determined by
+  # STATUS_TERMINATED).
+  #
+  def get
+    option_name, option_argument = nil, ''
+
+    #
+    # Check status.
+    #
+    return nil if @error != nil
+    case @status
+    when STATUS_YET
+      @status = STATUS_STARTED
+    when STATUS_TERMINATED
+      return nil
+    end
+
+    #
+    # Get next option argument.
+    #
+    if 0 < @rest_singles.length
+      argument = '-' + @rest_singles
+    elsif (ARGV.length == 0)
+      terminate
+      return nil
+    elsif @ordering == PERMUTE
+      while 0 < ARGV.length && ARGV[0] !~ /^-./
+	@non_option_arguments.push(ARGV.shift)
+      end
+      if ARGV.length == 0
+	terminate
+	return nil
+      end
+      argument = ARGV.shift
+    elsif @ordering == REQUIRE_ORDER 
+      if (ARGV[0] !~ /^-./)
+	terminate
+	return nil
+      end
+      argument = ARGV.shift
+    else
+      argument = ARGV.shift
+    end
+
+    #
+    # Check the special argument `--'.
+    # `--' indicates the end of the option list.
+    #
+    if argument == '--' && @rest_singles.length == 0
+      terminate
+      return nil
+    end
+
+    #
+    # Check for long and short options.
+    #
+    if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0
+      #
+      # This is a long style option, which start with `--'.
+      #
+      pattern = $1
+      if @canonical_names.include?(pattern)
+	option_name = pattern
+      else
+	#
+	# The option `option_name' is not registered in `@canonical_names'.
+	# It may be an abbreviated.
+	#
+	matches = []
+	@canonical_names.each_key do |key|
+	  if key.index(pattern) == 0
+	    option_name = key
+	    matches << key
+	  end
+	end
+	if 2 <= matches.length
+	  set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}")
+	elsif matches.length == 0
+	  set_error(InvalidOption, "unrecognized option `#{argument}'")
+	end
+      end
+
+      #
+      # Check an argument to the option.
+      #
+      if @argument_flags[option_name] == REQUIRED_ARGUMENT
+	if argument =~ /=(.*)$/
+	  option_argument = $1
+	elsif 0 < ARGV.length
+	  option_argument = ARGV.shift
+	else
+	  set_error(MissingArgument,
+	            "option `#{argument}' requires an argument")
+	end
+      elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
+	if argument =~ /=(.*)$/
+	  option_argument = $1
+	elsif 0 < ARGV.length && ARGV[0] !~ /^-./
+	  option_argument = ARGV.shift
+	else
+	  option_argument = ''
+	end
+      elsif argument =~ /=(.*)$/
+	set_error(NeedlessArgument,
+		  "option `#{option_name}' doesn't allow an argument")
+      end
+
+    elsif argument =~ /^(-(.))(.*)/
+      #
+      # This is a short style option, which start with `-' (not `--').
+      # Short options may be catenated (e.g. `-l -g' is equivalent to
+      # `-lg').
+      #
+      option_name, ch, @rest_singles = $1, $2, $3
+
+      if @canonical_names.include?(option_name)
+	#
+	# The option `option_name' is found in `@canonical_names'.
+	# Check its argument.
+	#
+	if @argument_flags[option_name] == REQUIRED_ARGUMENT
+	  if 0 < @rest_singles.length
+	    option_argument = @rest_singles
+	    @rest_singles = ''
+	  elsif 0 < ARGV.length
+	    option_argument = ARGV.shift
+	  else
+	    # 1003.2 specifies the format of this message.
+	    set_error(MissingArgument, "option requires an argument -- #{ch}")
+	  end
+	elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
+	  if 0 < @rest_singles.length
+	    option_argument = @rest_singles
+	    @rest_singles = ''
+	  elsif 0 < ARGV.length && ARGV[0] !~ /^-./
+	    option_argument = ARGV.shift
+	  else
+	    option_argument = ''
+	  end
+	end
+      else
+	#
+	# This is an invalid option.
+	# 1003.2 specifies the format of this message.
+	#
+	if ENV.include?('POSIXLY_CORRECT')
+	  set_error(InvalidOption, "illegal option -- #{ch}")
+	else
+	  set_error(InvalidOption, "invalid option -- #{ch}")
+	end
+      end
+    else
+      #
+      # This is a non-option argument.
+      # Only RETURN_IN_ORDER falled into here.
+      #
+      return '', argument
+    end
+
+    return @canonical_names[option_name], option_argument
+  end
+
+  #
+  # `get_option' is an alias of `get'.
+  #
+  alias get_option get
+
+  #
+  # Iterator version of `get', passes the option and the
+  # corresponding argument to the supplied block for processing.
+  #
+  def each
+    loop do
+      option_name, option_argument = get_option
+      break if option_name == nil
+      yield option_name, option_argument
+    end
+  end
+
+  #
+  # `each_option' is an alias of `each'.
+  #
+  alias each_option each
+end

Added: trunk/lib/getopts.rb
===================================================================
--- trunk/lib/getopts.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/lib/getopts.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -0,0 +1,126 @@
+#
+#               getopts.rb - 
+#                       $Release Version: $
+#                       $Revision: 1.11 $
+#                       $Date: 2004/11/04 23:43:39 $
+#                       by Yasuo OHBA(SHL Japan Inc. Technology Dept.)
+#
+# --
+# this is obsolete; use getoptlong
+#
+# 2000-03-21
+# modified by Minero Aoki <aamine dp.u-netsurf.ne.jp>
+#
+# 2002-03-05
+# rewritten by Akinori MUSHA <knu ruby-lang.org>
+#
+
+warn "Warning:#{caller[0].sub(/:in `.*'\z/, '')}: getopts is deprecated after Ruby 1.8.1; use optparse instead" if caller[0]
+
+$RCS_ID=%q$Header: /src/ruby/lib/getopts.rb,v 1.11 2004/11/04 23:43:39 matz Exp $
+
+
+def getopts(single_options, *options)
+  boolopts = {}
+  valopts = {}
+
+  #
+  # set defaults
+  #
+  single_options.scan(/.:?/) do |opt|
+    if opt.size == 1
+      boolopts[opt] = false
+    else
+      valopts[opt[0, 1]] = nil
+    end
+  end if single_options
+
+  options.each do |arg|
+    opt, val = arg.split(':', 2)
+
+    if val
+      valopts[opt] = val.empty? ? nil : val
+    else
+      boolopts[opt] = false
+    end
+  end
+
+  #
+  # scan
+  #
+  c = 0
+  argv = ARGV
+
+  while arg = argv.shift
+    case arg
+    when /\A--(.*)/
+      if $1.empty?			# xinit -- -bpp 24
+	break
+      end
+
+      opt, val = $1.split('=', 2)
+
+      if opt.size == 1
+	argv.unshift arg
+	return nil
+      elsif valopts.key? opt		# imclean --src +trash
+	valopts[opt] = val || argv.shift or return nil
+      elsif boolopts.key? opt		# ruby --verbose
+	boolopts[opt] = true
+      else
+	argv.unshift arg
+	return nil
+      end
+
+      c += 1
+    when /\A-(.+)/
+      opts = $1
+
+      until opts.empty?
+	opt = opts.slice!(0, 1)
+
+	if valopts.key? opt
+	  val = opts
+
+	  if val.empty?			# ruby -e 'p $:'
+	    valopts[opt] = argv.shift or return nil
+	  else				# cc -ohello ...
+	    valopts[opt] = val
+	  end
+
+	  c += 1
+	  break
+	elsif boolopts.key? opt
+	  boolopts[opt] = true		# ruby -h
+	  c += 1
+	else
+	  argv.unshift arg
+	  return nil
+	end
+      end
+    else
+      argv.unshift arg
+      break
+    end
+  end
+
+  #
+  # set
+  #
+  $OPT = {}
+
+  boolopts.each do |opt, val|
+    $OPT[opt] = val
+
+    sopt = opt.gsub(/[^A-Za-z0-9_]/, '_')
+    eval "$OPT_#{sopt} = val"
+  end
+  valopts.each do |opt, val|
+    $OPT[opt] = val
+
+    sopt = opt.gsub(/[^A-Za-z0-9_]/, '_')
+    eval "$OPT_#{sopt} = val"
+  end
+
+  c
+end

Added: trunk/lib/mkmf.rb
===================================================================
--- trunk/lib/mkmf.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/lib/mkmf.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -0,0 +1,1386 @@
+# module to create Makefile for extension modules
+# invoke like: ruby -r mkmf extconf.rb
+
+require 'rbconfig'
+require 'fileutils'
+require 'shellwords'
+
+CONFIG = Config::MAKEFILE_CONFIG
+ORIG_LIBPATH = ENV['LIB']
+
+CXX_EXT = %w[cc cxx cpp]
+if /mswin|bccwin|mingw|msdosdjgpp|human|os2/ !~ CONFIG['build_os']
+  CXX_EXT.concat(%w[C])
+end
+SRC_EXT = %w[c m] << CXX_EXT
+$static = $config_h = nil
+
+unless defined? $configure_args
+  $configure_args = {}
+  args = CONFIG["configure_args"]
+  if ENV["CONFIGURE_ARGS"]
+    args << " " << ENV["CONFIGURE_ARGS"]
+  end
+  for arg in Shellwords::shellwords(args)
+    arg, val = arg.split('=', 2)
+    next unless arg
+    arg.tr!('_', '-')
+    if arg.sub!(/^(?!--)/, '--')
+      val or next
+      arg.downcase!
+    end
+    next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg
+    $configure_args[arg] = val || true
+  end
+  for arg in ARGV
+    arg, val = arg.split('=', 2)
+    next unless arg
+    arg.tr!('_', '-')
+    if arg.sub!(/^(?!--)/, '--')
+      val or next
+      arg.downcase!
+    end
+    $configure_args[arg] = val || true
+  end
+end
+
+$libdir = CONFIG["libdir"]
+$rubylibdir = CONFIG["rubylibdir"]
+$archdir = CONFIG["archdir"]
+$sitedir = CONFIG["sitedir"]
+$sitelibdir = CONFIG["sitelibdir"]
+$sitearchdir = CONFIG["sitearchdir"]
+
+$mswin = /mswin/ =~ RUBY_PLATFORM
+$bccwin = /bccwin/ =~ RUBY_PLATFORM
+$mingw = /mingw/ =~ RUBY_PLATFORM
+$cygwin = /cygwin/ =~ RUBY_PLATFORM
+$human = /human/ =~ RUBY_PLATFORM
+$netbsd = /netbsd/ =~ RUBY_PLATFORM
+$os2 = /os2/ =~ RUBY_PLATFORM
+$beos = /beos/ =~ RUBY_PLATFORM
+$solaris = /solaris/ =~ RUBY_PLATFORM
+
+def config_string(key, config = CONFIG)
+  s = config[key] and !s.empty? and block_given? ? yield(s) : s
+end
+
+def dir_re(dir)
+  Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$\(target_prefix\)|\{target_prefix\})?')
+end
+
+INSTALL_DIRS = [
+  [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
+  [dir_re("sitedir"), "$(RUBYCOMMONDIR)"],
+  [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
+  [dir_re('archdir'), "$(RUBYARCHDIR)"],
+  [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
+  [dir_re('sitearchdir'), "$(RUBYARCHDIR)"]
+]
+
+def install_dirs(target_prefix = nil)
+  if $extout
+    dirs = [
+      ['RUBYCOMMONDIR', '$(extout)'],
+      ['RUBYLIBDIR',    '$(extout)$(target_prefix)'],
+      ['RUBYARCHDIR',   '$(extout)/$(arch)$(target_prefix)'],
+      ['extout',        "#$extout"],
+      ['extout_prefix', "#$extout_prefix"],
+    ]
+  elsif $extmk
+    dirs = [
+      ['RUBYCOMMONDIR', '$(rubylibdir)'],
+      ['RUBYLIBDIR',    '$(rubylibdir)$(target_prefix)'],
+      ['RUBYARCHDIR',   '$(archdir)$(target_prefix)'],
+    ]
+  else
+    dirs = [
+      ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
+      ['RUBYLIBDIR',    '$(sitelibdir)$(target_prefix)'],
+      ['RUBYARCHDIR',   '$(sitearchdir)$(target_prefix)'],
+    ]
+  end
+  dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
+  dirs
+end
+
+def map_dir(dir, map = nil)
+  map ||= INSTALL_DIRS
+  map.inject(dir) {|dir, (orig, new)| dir.gsub(orig, new)}
+end
+
+topdir = File.dirname(libdir = File.dirname(__FILE__))
+extdir = File.expand_path("ext", topdir)
+$extmk = File.expand_path($0)[0, extdir.size+1] == extdir+"/"
+if not $extmk and File.exist?(Config::CONFIG["archdir"] + "/ruby.h")
+  $hdrdir = $topdir = Config::CONFIG["archdir"]
+elsif File.exist?(($top_srcdir ||= topdir)  + "/ruby.h") and
+    File.exist?(($topdir ||= Config::CONFIG["topdir"]) + "/config.h")
+  $hdrdir = $top_srcdir
+else
+  abort "can't find header files for ruby."
+end
+
+OUTFLAG = CONFIG['OUTFLAG']
+CPPOUTFILE = CONFIG['CPPOUTFILE']
+
+CONFTEST_C = "conftest.c"
+
+class String
+  def quote
+    /\s/ =~ self ? "\"#{self}\"" : self
+  end
+end
+class Array
+  def quote
+    map {|s| s.quote}
+  end
+end
+
+def rm_f(*files)
+  FileUtils.rm_f(Dir[files.join("\0")])
+end
+
+def modified?(target, times)
+  (t = File.mtime(target)) rescue return nil
+  Array === times or times = [times]
+  t if times.all? {|n| n <= t}
+end
+
+def merge_libs(*libs)
+  libs.inject([]) do |x, y|
+    xy = x & y
+    xn = yn = 0
+    y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
+    y.each_with_index do |v, yi|
+      if xy.include?(v)
+        xi = [x.index(v), xn].max()
+        x[xi, 1] = y[yn..yi]
+        xn, yn = xi + (yi - yn + 1), yi + 1
+      end
+    end
+    x.concat(y[yn..-1] || [])
+  end
+end
+
+module Logging
+  @log = nil
+  @logfile = 'mkmf.log'
+  @orgerr = $stderr.dup
+  @orgout = $stdout.dup
+  @postpone = 0
+
+  def self::open
+    @log ||= File::open(@logfile, 'w')
+    @log.sync = true
+    $stderr.reopen(@log)
+    $stdout.reopen(@log)
+    yield
+  ensure
+    $stderr.reopen(@orgerr)
+    $stdout.reopen(@orgout)
+  end
+
+  def self::message(*s)
+    @log ||= File::open(@logfile, 'w')
+    @log.sync = true
+    @log.printf(*s)
+  end
+
+  def self::logfile file
+    @logfile = file
+    if @log and not @log.closed?
+      @log.flush
+      @log.close
+      @log = nil
+    end
+  end
+  
+  def self::postpone
+    tmplog = "mkmftmp#{@postpone += 1}.log"
+    open do
+      log, *save = @log, @logfile, @orgout, @orgerr
+      @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
+      begin
+        log.print(open {yield})
+        @log.close
+        File::open(tmplog) {|t| FileUtils.copy_stream(t, log)}
+      ensure
+        @log, @logfile, @orgout, @orgerr = log, *save
+        @postpone -= 1
+        rm_f tmplog
+      end
+    end
+  end
+end
+
+def xsystem command
+  Logging::open do
+    puts command.quote
+    system(command)
+  end
+end
+
+def xpopen command, *mode, &block
+  Logging::open do
+    case mode[0]
+    when nil, /^r/
+      puts "#{command} |"
+    else
+      puts "| #{command}"
+    end
+    IO.popen(command, *mode, &block)
+  end
+end
+
+def log_src(src)
+  Logging::message <<"EOM", src
+checked program was:
+/* begin */
+%s/* end */
+
+EOM
+end
+
+def create_tmpsrc(src)
+  src = yield(src) if block_given?
+  src = src.sub(/[^\n]\z/, "\\&\n")
+  open(CONFTEST_C, "wb") do |cfile|
+    cfile.print src
+  end
+  src
+end
+
+def try_do(src, command, &b)
+  src = create_tmpsrc(src, &b)
+  xsystem(command)
+ensure
+  log_src(src)
+end
+
+def link_command(ldflags, opt="", libpath=$LIBPATH)
+  Config::expand(TRY_LINK.dup,
+                 CONFIG.merge('hdrdir' => $hdrdir.quote,
+		 'src' => CONFTEST_C,
+		 'INCFLAGS' => $INCFLAGS,
+		 'CPPFLAGS' => $CPPFLAGS,
+		 'CFLAGS' => "#$CFLAGS",
+		 'ARCH_FLAG' => "#$ARCH_FLAG",
+		 'LDFLAGS' => "#$LDFLAGS #{ldflags}",
+		 'LIBPATH' => libpathflag(libpath),
+		 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
+                              'LIBS' => "#$LIBRUBYARG_STATIC #{opt} #$LIBS"))
+end
+
+def cc_command(opt="")
+  Config::expand("$(CC) -c #$INCFLAGS -I$(hdrdir) " \
+                 "#$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} #{CONFTEST_C}",
+		 CONFIG.merge('hdrdir' => $hdrdir.quote))
+end
+
+def cpp_command(outfile, opt="")
+  Config::expand("$(CPP) #$INCFLAGS -I$(hdrdir) " \
+                 "#$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
+		 CONFIG.merge('hdrdir' => $hdrdir.quote))
+end
+
+def libpathflag(libpath=$LIBPATH)
+  libpath.map{|x|
+    (x == "$(topdir)" ? LIBPATHFLAG : LIBPATHFLAG+RPATHFLAG) % x.quote
+  }.join
+end
+
+def try_link0(src, opt="", &b)
+  try_do(src, link_command("", opt), &b)
+end
+
+def try_link(src, opt="", &b)
+  try_link0(src, opt, &b)
+ensure
+  rm_f "conftest*", "c0x32*"
+end
+
+def try_compile(src, opt="", &b)
+  try_do(src, cc_command(opt), &b)
+ensure
+  rm_f "conftest*"
+end
+
+def try_cpp(src, opt="", &b)
+  try_do(src, cpp_command(CPPOUTFILE, opt), &b)
+ensure
+  rm_f "conftest*"
+end
+
+def cpp_include(header)
+  if header
+    header = [header] unless header.kind_of? Array
+    header.map {|h| "#include <#{h}>\n"}.join
+  else
+    ""
+  end
+end
+
+def with_cppflags(flags)
+  cppflags = $CPPFLAGS
+  $CPPFLAGS = flags
+  ret = yield
+ensure
+  $CPPFLAGS = cppflags unless ret
+end
+
+def with_cflags(flags)
+  cflags = $CFLAGS
+  $CFLAGS = flags
+  ret = yield
+ensure
+  $CFLAGS = cflags unless ret
+end
+
+def with_ldflags(flags)
+  ldflags = $LDFLAGS
+  $LDFLAGS = flags
+  ret = yield
+ensure
+  $LDFLAGS = ldflags unless ret
+end
+
+def try_static_assert(expr, headers = nil, opt = "", &b)
+  headers = cpp_include(headers)
+  try_compile(<<SRC, opt, &b)
+#{COMMON_HEADERS}
+#{headers}
+/*top*/
+int conftest_const[(#{expr}) ? 1 : -1];
+SRC
+end
+
+def try_constant(const, headers = nil, opt = "", &b)
+  includes = cpp_include(headers)
+  if CROSS_COMPILING
+    if try_static_assert("#{const} > 0", headers, opt)
+      # positive constant
+    elsif try_static_assert("#{const} < 0", headers, opt)
+      neg = true
+      const = "-(#{const})"
+    elsif try_static_assert("#{const} == 0", headers, opt)
+      return 0
+    else
+      # not a constant
+      return nil
+    end
+    upper = 1
+    until try_static_assert("#{const} <= #{upper}", headers, opt)
+      lower = upper
+      upper <<= 1
+    end
+    return nil unless lower
+    while upper > lower + 1
+      mid = (upper + lower) / 2
+      if try_static_assert("#{const} > #{mid}", headers, opt)
+        lower = mid
+      else
+        upper = mid
+      end
+    end
+    unless upper == lower
+      if try_static_assert("#{const} == #{lower}", headers, opt)
+        upper = lower
+      end
+    end
+    upper = -upper if neg
+    return upper
+  else
+    src = %{#{COMMON_HEADERS}
+#{includes}
+#include <stdio.h>
+/*top*/
+int conftest_const = (int)(#{const});
+int main() {printf("%d\\n", conftest_const); return 0;}
+}
+    if try_link0(src, opt, &b)
+      xpopen("./conftest") do |f|
+        return Integer(f.gets)
+      end
+    end
+  end
+  nil
+end
+
+def try_func(func, libs, headers = nil, &b)
+  headers = cpp_include(headers)
+  try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b)
+#{headers}
+/*top*/
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+#{COMMON_HEADERS}
+#{headers}
+/*top*/
+int main() { return 0; }
+int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; }
+SRC
+end
+
+def try_var(var, headers = nil, &b)
+  headers = cpp_include(headers)
+  try_compile(<<"SRC", &b)
+#{COMMON_HEADERS}
+#{headers}
+/*top*/
+int main() { return 0; }
+int t() { void *volatile p; p = (void *)&#{var}; return 0; }
+SRC
+end
+
+def egrep_cpp(pat, src, opt = "", &b)
+  src = create_tmpsrc(src, &b)
+  xpopen(cpp_command('', opt)) do |f|
+    if Regexp === pat
+      puts("    ruby -ne 'print if #{pat.inspect}'")
+      f.grep(pat) {|l|
+	puts "#{f.lineno}: #{l}"
+	return true
+      }
+      false
+    else
+      puts("    egrep '#{pat}'")
+      begin
+	stdin = $stdin.dup
+	$stdin.reopen(f)
+	system("egrep", pat)
+      ensure
+	$stdin.reopen(stdin)
+      end
+    end
+  end
+ensure
+  rm_f "conftest*"
+  log_src(src)
+end
+
+def macro_defined?(macro, src, opt = "", &b)
+  src = src.sub(/[^\n]\z/, "\\&\n")
+  try_compile(src + <<"SRC", opt, &b)
+/*top*/
+#ifndef #{macro}
+# error
+>>>>>> #{macro} undefined <<<<<<
+#endif
+SRC
+end
+
+def try_run(src, opt = "", &b)
+  if try_link0(src, opt, &b)
+    xsystem("./conftest")
+  else
+    nil
+  end
+ensure
+  rm_f "conftest*"
+end
+
+def install_files(mfile, ifiles, map = nil, srcprefix = nil)
+  ifiles or return
+  srcprefix ||= '$(srcdir)'
+  Config::expand(srcdir = srcprefix.dup)
+  dirs = []
+  path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
+  ifiles.each do |files, dir, prefix|
+    dir = map_dir(dir, map)
+    prefix = %r|\A#{Regexp.quote(prefix)}/?| if prefix
+    if /\A\.\// =~ files
+      # install files which are in current working directory.
+      files = files[2..-1]
+      len = nil
+    else
+      # install files which are under the $(srcdir).
+      files = File.join(srcdir, files)
+      len = srcdir.size
+    end
+    f = nil
+    Dir.glob(files) do |f|
+      f[0..len] = "" if len
+      d = File.dirname(f)
+      d.sub!(prefix, "") if prefix
+      d = (d.empty? || d == ".") ? dir : File.join(dir, d)
+      f = File.join(srcprefix, f) if len
+      path[d] << f
+    end
+    unless len or f
+      d = File.dirname(files)
+      d.sub!(prefix, "") if prefix
+      d = (d.empty? || d == ".") ? dir : File.join(dir, d)
+      path[d] << files
+    end
+  end
+  dirs
+end
+
+def install_rb(mfile, dest, srcdir = nil)
+  install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
+end
+
+def append_library(libs, lib)
+  format(LIBARG, lib) + " " + libs
+end
+
+def message(*s)
+  unless $extmk and not $VERBOSE
+    printf(*s)
+    $stdout.flush
+  end
+end
+
+def checking_for(m, fmt = nil)
+  f = caller[0][/in `(.*)'$/, 1] and f << ": " #` for vim, ' for xyzzy
+  m = "checking for #{m}... "
+  message "%s", m
+  a = r = nil
+  Logging::postpone do
+    r = yield
+    a = (fmt ? fmt % r : r ? "yes" : "no") << "\n"
+    "#{f}#{m}-------------------- #{a}\n"
+  end
+  message(a)
+  Logging::message "--------------------\n\n"
+  r
+end
+
+def have_macro(macro, headers = nil, opt = "", &b)
+  m = "#{macro}"
+  m << " in #{headers.inspect}" if headers
+  checking_for m do
+    macro_defined?(macro, cpp_include(headers), opt, &b)
+  end
+end
+
+def have_library(lib, func = nil, header=nil, &b)
+  func = "main" if !func or func.empty?
+  lib = with_config(lib+'lib', lib)
+  checking_for "#{func}() in #{LIBARG%lib}" do
+    if COMMON_LIBS.include?(lib)
+      true
+    else
+      libs = append_library($libs, lib)
+      if try_func(func, libs, header, &b)
+        $libs = libs
+        true
+      else
+        false
+      end
+    end
+  end
+end
+
+def find_library(lib, func, *paths, &b)
+  func = "main" if !func or func.empty?
+  lib = with_config(lib+'lib', lib)
+  paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
+  checking_for "#{func}() in #{LIBARG%lib}" do
+    libpath = $LIBPATH
+    libs = append_library($libs, lib)
+    begin
+      until r = try_func(func, libs, &b) or paths.empty?
+	$LIBPATH = libpath | [paths.shift]
+      end
+      if r
+	$libs = libs
+	libpath = nil
+      end
+    ensure
+      $LIBPATH = libpath if libpath
+    end
+    r
+  end
+end
+
+def have_func(func, headers = nil, &b)
+  checking_for "#{func}()" do
+    if try_func(func, $libs, headers, &b)
+      $defs.push(format("-DHAVE_%s", func.upcase))
+      true
+    else
+      false
+    end
+  end
+end
+
+def have_var(var, headers = nil, &b)
+  checking_for "#{var}" do
+    if try_var(var, headers, &b)
+      $defs.push(format("-DHAVE_%s", var.upcase))
+      true
+    else
+      false
+    end
+  end
+end
+
+def have_header(header, &b)
+  checking_for header do
+    if try_cpp(cpp_include(header), &b)
+      $defs.push(format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___")))
+      true
+    else
+      false
+    end
+  end
+end
+
+def find_header(header, *paths)
+  checking_for header do
+    if try_cpp(cpp_include(header))
+      true
+    else
+      found = false
+      paths.each do |dir|
+        opt = "-I#{dir}".quote
+        if try_cpp(cpp_include(header), opt)
+          $INCFLAGS << " " << opt
+          found = true
+          break
+        end
+      end
+      found
+    end
+  end
+end
+
+def have_struct_member(type, member, header = nil, &b)
+  checking_for "#{type}.#{member}" do
+    if try_compile(<<"SRC", &b)
+#{COMMON_HEADERS}
+#{cpp_include(header)}
+/*top*/
+int main() { return 0; }
+int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
+SRC
+      $defs.push(format("-DHAVE_ST_%s", member.upcase))
+      true
+    else
+      false
+    end
+  end
+end
+
+def have_type(type, header = nil, opt = "", &b)
+  checking_for type do
+    header = cpp_include(header)
+    if try_compile(<<"SRC", opt, &b) or (/\A\w+\z/n =~ type && try_compile(<<"SRC", opt, &b))
+#{COMMON_HEADERS}
+#{header}
+/*top*/
+static #{type} t;
+SRC
+#{COMMON_HEADERS}
+#{header}
+/*top*/
+static #{type} *t;
+SRC
+      $defs.push(format("-DHAVE_TYPE_%s", type.strip.upcase.tr_s("^A-Z0-9_", "_")))
+      true
+    else
+      false
+    end
+  end
+end
+
+def check_sizeof(type, header = nil, &b)
+  expr = "sizeof(#{type})"
+  m = "checking size of #{type}... "
+  message "%s", m
+  a = size = nil
+  Logging::postpone do
+    if size = try_constant(expr, header, &b)
+      $defs.push(format("-DSIZEOF_%s=%d", type.upcase.tr_s("^A-Z0-9_", "_"), size))
+      a = "#{size}\n"
+    else
+      a = "failed\n"
+    end
+    "check_sizeof: #{m}-------------------- #{a}\n"
+  end
+  message(a)
+  Logging::message "--------------------\n\n"
+  size
+end
+
+def scalar_ptr_type?(type, member = nil, headers = nil, &b)
+  try_compile(<<"SRC", &b)   # pointer
+#{COMMON_HEADERS}
+#{cpp_include(headers)}
+/*top*/
+volatile #{type} conftestval;
+int main() { return 0; }
+int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
+SRC
+end
+
+def scalar_type?(type, member = nil, headers = nil, &b)
+  try_compile(<<"SRC", &b)   # pointer
+#{COMMON_HEADERS}
+#{cpp_include(headers)}
+/*top*/
+volatile #{type} conftestval;
+int main() { return 0; }
+int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
+SRC
+end
+
+def what_type?(type, member = nil, headers = nil, &b)
+  m = "#{type}"
+  name = type
+  if member
+    m << "." << member
+    name = "(((#{type} *)0)->#{member})"
+  end
+  m << " in #{headers.inspect}" if headers
+  fmt = "seems %s"
+  def fmt.%(x)
+    x ? super : "unknown"
+  end
+  checking_for m, fmt do
+    if scalar_ptr_type?(type, member, headers, &b)
+      if try_static_assert("sizeof(*#{name}) == 1", headers)
+        "string"
+      end
+    elsif scalar_type?(type, member, headers, &b)
+      if try_static_assert("sizeof(#{name}) > sizeof(long)", headers)
+        "long long"
+      elsif try_static_assert("sizeof(#{name}) > sizeof(int)", headers)
+        "long"
+      elsif try_static_assert("sizeof(#{name}) > sizeof(short)", headers)
+        "int"
+      elsif try_static_assert("sizeof(#{name}) > 1", headers)
+        "short"
+      else
+        "char"
+      end
+    end
+  end
+end
+
+def find_executable0(bin, path = nil)
+  ext = config_string('EXEEXT')
+  if File.expand_path(bin) == bin
+    return bin if File.executable?(bin)
+    return file if ext and File.executable?(file = bin + ext)
+    return nil
+  end
+  if path ||= ENV['PATH']
+    path = path.split(File::PATH_SEPARATOR)
+  else
+    path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
+  end
+  file = nil
+  path.each do |dir|
+    return file if File.executable?(file = File.join(dir, bin))
+    return file if ext and File.executable?(file << ext)
+  end
+  nil
+end
+
+def find_executable(bin, path = nil)
+  checking_for bin do
+    find_executable0(bin, path)
+  end
+end
+
+def arg_config(config, *defaults, &block)
+  $arg_config << [config, *defaults]
+  defaults << nil if !block and defaults.empty?
+  $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
+end
+
+def with_config(config, *defaults, &block)
+  unless /^--with[-_]/ =~ config
+    config = '--with-' + config
+  end
+  arg_config(config, *defaults, &block)
+end
+
+def enable_config(config, *defaults)
+  if arg_config("--enable-"+config)
+    true
+  elsif arg_config("--disable-"+config)
+    false
+  elsif block_given?
+    yield(config, *defaults)
+  else
+    return *defaults
+  end
+end
+
+def create_header(header = "extconf.h")
+  message "creating %s\n", header
+  if $defs.length > 0
+    sym = header.tr("a-z./\055", "A-Z___")
+    open(header, "w") do |hfile|
+      hfile.print "#ifndef #{sym}\n#define #{sym}\n"
+      for line in $defs
+	case line
+	when /^-D([^=]+)(?:=(.*))?/
+	  hfile.print "#define #$1 #{$2 || 1}\n"
+	when /^-U(.*)/
+	  hfile.print "#undef #$1\n"
+	end
+      end
+      hfile.print "#endif\n"
+    end
+  end
+end
+
+def dir_config(target, idefault=nil, ldefault=nil)
+  if dir = with_config(target + "-dir", (idefault unless ldefault))
+    defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
+    idefault = ldefault = nil
+  end
+
+  idir = with_config(target + "-include", idefault)
+  $arg_config.last[1] ||= "${#{target}-dir}/include"
+  ldir = with_config(target + "-lib", ldefault)
+  $arg_config.last[1] ||= "${#{target}-dir}/lib"
+
+  idirs = idir ? Array === idir ? idir : idir.split(File::PATH_SEPARATOR) : []
+  if defaults
+    idirs.concat(defaults.collect {|dir| dir + "/include"})
+    idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
+  end
+  unless idirs.empty?
+    idirs.collect! {|dir| "-I" + dir}
+    idirs -= Shellwords.shellwords($CPPFLAGS)
+    unless idirs.empty?
+      $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
+    end
+  end
+
+  ldirs = ldir ? Array === ldir ? ldir : ldir.split(File::PATH_SEPARATOR) : []
+  if defaults
+    ldirs.concat(defaults.collect {|dir| dir + "/lib"})
+    ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
+  end
+  $LIBPATH = ldirs | $LIBPATH
+
+  [idir, ldir]
+end
+
+def pkg_config(pkg)
+  unless defined?($PKGCONFIG)
+    if pkgconfig = with_config("pkg-config", !CROSS_COMPILING && "pkg-config")
+      find_executable0(pkgconfig) or pkgconfig = nil
+    end
+    $PKGCONFIG = pkgconfig
+  end
+  if $PKGCONFIG and system("#{$PKGCONFIG} --exists #{pkg}")
+    cflags = `#{$PKGCONFIG} --cflags #{pkg}`.chomp
+    ldflags = `#{$PKGCONFIG} --libs #{pkg}`.chomp
+    libs = `#{$PKGCONFIG} --libs-only-l #{pkg}`.chomp
+    ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
+    $CFLAGS += " " << cflags
+    $LDFLAGS += " " << ldflags
+    $libs += " " << libs
+    Logging::message "package configuration for %s\n", pkg
+    Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
+                     cflags, ldflags, libs
+    [cflags, ldflags, libs]
+  end
+end
+
+def with_destdir(dir)
+  /^\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
+end
+
+def winsep(s)
+  s.tr('/', '\\')
+end
+
+def configuration(srcdir)
+  mk = []
+  vpath = %w[$(srcdir) $(topdir) $(hdrdir)]
+  if !CROSS_COMPILING
+    case CONFIG['build_os']
+    when 'cygwin'
+      if CONFIG['target_os'] != 'cygwin'
+        vpath.each {|p| p.sub!(/.*/, '$(shell cygpath -u \&)')}
+      end
+    when 'msdosdjgpp', 'mingw32'
+      CONFIG['PATH_SEPARATOR'] = ';'
+    end
+  end
+  mk << %{
+SHELL = /bin/sh
+
+#### Start of system configuration section. ####
+
+srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {CONFIG[$1||$2]}.quote}
+topdir = #{($extmk ? CONFIG["topdir"] : $topdir).quote}
+hdrdir = #{$extmk ? CONFIG["hdrdir"].quote : '$(topdir)'}
+VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
+}
+  drive = File::PATH_SEPARATOR == ';' ? /\A\w:/ : /\A/
+  if destdir = CONFIG["prefix"].scan(drive)[0] and !destdir.empty?
+    mk << "\nDESTDIR = #{destdir}\n"
+  end
+  CONFIG.each do |key, var|
+    next unless /prefix$/ =~ key
+    mk << "#{key} = #{with_destdir(var.sub(drive, ''))}\n"
+  end
+  CONFIG.each do |key, var|
+    next if /^abs_/ =~ key
+    next unless /^(?:src|top|hdr|(.*))dir$/ =~ key and $1
+    mk << "#{key} = #{with_destdir(var.sub(drive, ''))}\n"
+  end
+  if !$extmk and !$configure_args.has_key?('--ruby') and
+      sep = config_string('BUILD_FILE_SEPARATOR')
+    sep = ":/=#{sep}"
+  else
+    sep = ""
+  end
+  mk << %{
+CC = #{CONFIG['CC']}
+CXX = #{CONFIG['CXX']}
+LIBRUBY = #{CONFIG['LIBRUBY']}
+LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
+LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
+LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
+
+CFLAGS   = #{CONFIG['CCDLFLAGS'] unless $static} #$CFLAGS #$ARCH_FLAG
+CPPFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir) #{$defs.join(" ")} #{$CPPFLAGS}
+CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']}
+DLDFLAGS = #$LDFLAGS #$DLDFLAGS #$ARCH_FLAG
+LDSHARED = #{CONFIG['LDSHARED']}
+LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'}
+AR = #{CONFIG['AR']}
+EXEEXT = #{CONFIG['EXEEXT']}
+
+RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
+RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
+arch = #{CONFIG['arch']}
+sitearch = #{CONFIG['sitearch']}
+ruby_version = #{Config::CONFIG['ruby_version']}
+ruby = #{$ruby}
+RUBY = $(ruby#{sep})
+RM = #{config_string('RM') || '$(RUBY) -run -e rm -- -f'}
+MAKEDIRS = #{config_string('MAKEDIRS') || '@$(RUBY) -run -e mkdir -- -p'}
+INSTALL = #{config_string('INSTALL') || '@$(RUBY) -run -e install -- -vp'}
+INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
+INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
+COPY = #{config_string('CP') || '@$(RUBY) -run -e cp -- -v'}
+
+#### End of system configuration section. ####
+
+preload = #{$preload.join(" ") if $preload}
+}
+  if $nmake == ?b
+    mk.each do |x|
+      x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
+        "!ifndef " + $1 + "\n" +
+        $& +
+	"!endif\n"
+      end
+    end
+  end
+  mk
+end
+
+def dummy_makefile(srcdir)
+  configuration(srcdir) << <<RULES << CLEANINGS
+CLEANFILES = #{$cleanfiles.join(' ')}
+DISTCLEANFILES = #{$distcleanfiles.join(' ')}
+
+all install static install-so install-rb: Makefile
+
+RULES
+end
+
+def create_makefile(target, srcprefix = nil)
+  $target = target
+  libpath = $LIBPATH
+  message "creating Makefile\n"
+  rm_f "conftest*"
+  if CONFIG["DLEXT"] == $OBJEXT
+    for lib in libs = $libs.split
+      lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
+    end
+    $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
+  end
+
+  if target.include?('/')
+    target_prefix, target = File.split(target)
+    target_prefix[0,0] = '/'
+  else
+    target_prefix = ""
+  end
+
+  srcprefix ||= '$(srcdir)'
+  Config::expand(srcdir = srcprefix.dup)
+
+  if not $objs
+    $objs = []
+    srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
+    for f in srcs
+      obj = File.basename(f, ".*") << ".o"
+      $objs.push(obj) unless $objs.index(obj)
+    end
+  elsif !(srcs = $srcs)
+    srcs = $objs.collect {|obj| obj.sub(/\.o\z/, '.c')}
+  end
+  for i in $objs
+    i.sub!(/\.o\z/, ".#{$OBJEXT}")
+  end
+  $objs = $objs.join(" ")
+
+  target = nil if $objs == ""
+
+  if target and EXPORT_PREFIX
+    if File.exist?(File.join(srcdir, target + '.def'))
+      deffile = "$(srcdir)/$(TARGET).def"
+      unless EXPORT_PREFIX.empty?
+        makedef = %{-pe "sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"}
+      end
+    else
+      makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}Init_$(TARGET)'"}
+    end
+    if makedef
+      $distcleanfiles << '$(DEFFILE)'
+      origdef = deffile
+      deffile = "$(TARGET)-$(arch).def"
+    end
+  end
+
+  libpath = libpathflag(libpath)
+
+  dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
+  staticlib = target ? "$(TARGET).#$LIBEXT" : ""
+  mfile = open("Makefile", "wb")
+  mfile.print configuration(srcprefix)
+  mfile.print %{
+libpath = #{$LIBPATH.join(" ")}
+LIBPATH = #{libpath}
+DEFFILE = #{deffile}
+
+CLEANFILES = #{$cleanfiles.join(' ')}
+DISTCLEANFILES = #{$distcleanfiles.join(' ')}
+
+extout = #{$extout}
+extout_prefix = #{$extout_prefix}
+target_prefix = #{target_prefix}
+LOCAL_LIBS = #{$LOCAL_LIBS}
+LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
+SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
+OBJS = #{$objs}
+TARGET = #{target}
+DLLIB = #{dllib}
+STATIC_LIB = #{staticlib unless $static.nil?}
+
+}
+  install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
+  n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET).'
+  mfile.print %{
+TARGET_SO     = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
+CLEANLIBS     = #{n}#{CONFIG['DLEXT']} #{n}il? #{n}tds #{n}map
+CLEANOBJS     = *.#{$OBJEXT} *.#{$LIBEXT} *.s[ol] *.pdb *.exp *.bak
+
+all:		#{target ? $extout ? "install" : "$(DLLIB)" : "Makefile"}
+static:		$(STATIC_LIB)#{$extout ? " install-rb" : ""}
+}
+  mfile.print CLEANINGS
+  dirs = []
+  mfile.print "install: install-so install-rb\n\n"
+  sodir = dir = "$(RUBYARCHDIR)"
+  mfile.print("install-so: #{dir}\n")
+  if target
+    f = "$(DLLIB)"
+    dest = "#{dir}/#{f}"
+    mfile.print "install-so: #{dest}\n"
+    unless $extout
+      mfile.print "#{dest}: #{f}\n"
+      if (sep = config_string('BUILD_FILE_SEPARATOR'))
+        f.gsub!("/", sep)
+        dir.gsub!("/", sep)
+        sep = ":/="+sep
+        f.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
+        f.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
+        dir.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
+        dir.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
+      end
+      mfile.print "\t$(INSTALL_PROG) #{f} #{dir}\n"
+    end
+  end
+  dirs << (dir = "$(RUBYLIBDIR)")
+  mfile.print("install-rb: pre-install-rb install-rb-default\n")
+  mfile.print("install-rb-default: pre-install-rb-default\n")
+  mfile.print("pre-install-rb pre-install-rb-default: #{dir}\n")
+  for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
+    files = install_files(mfile, i, nil, srcprefix) or next
+    for dir, *files in files
+      unless dirs.include?(dir)
+	dirs << dir
+	mfile.print "pre-install-rb#{sfx}: #{dir}\n"
+      end
+      files.each do |f|
+	dest = "#{dir}/#{File.basename(f)}"
+	mfile.print("install-rb#{sfx}: #{dest}\n")
+	mfile.print("#{dest}: #{f}\n\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) ")
+	sep = config_string('BUILD_FILE_SEPARATOR')
+	if sep
+	  f = f.gsub("/", sep)
+	  sep = ":/="+sep
+	  f = f.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
+	  f = f.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
+	else
+	  sep = ""
+	end
+	mfile.print("#{f} $(@D#{sep})\n")
+      end
+    end
+  end
+  dirs.unshift(sodir) if target and !dirs.include?(sodir)
+  dirs.each {|dir| mfile.print "#{dir}:\n\t$(MAKEDIRS) $@\n"}
+
+  mfile.print <<-SITEINSTALL
+
+site-install: site-install-so site-install-rb
+site-install-so: install-so
+site-install-rb: install-rb
+
+  SITEINSTALL
+
+  return unless target
+
+  mfile.puts SRC_EXT.collect {|ext| ".path.#{ext} = $(VPATH)"} if $nmake == ?b
+  mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n"
+  mfile.print "\n"
+
+  CXX_EXT.each do |ext|
+    COMPILE_RULES.each do |rule|
+      mfile.printf(rule, ext, $OBJEXT)
+      mfile.printf("\n\t%s\n\n", COMPILE_CXX)
+    end
+  end
+  %w[c].each do |ext|
+    COMPILE_RULES.each do |rule|
+      mfile.printf(rule, ext, $OBJEXT)
+      mfile.printf("\n\t%s\n\n", COMPILE_C)
+    end
+  end
+
+  mfile.print "$(RUBYARCHDIR)/" if $extout
+  mfile.print "$(DLLIB): ", (makedef ? "$(DEFFILE) " : ""), "$(OBJS)\n\t"
+  mfile.print "@-$(RM) $@\n\t"
+  mfile.print "@-$(MAKEDIRS) $(@D)\n\t" if $extout
+  link_so = LINK_SO
+  if srcs.any?(&%r"\.(?:#{CXX_EXT.join('|')})\z".method(:===))
+    link_so = link_so.sub(/\bLDSHARED\b/, '\&XX')
+  end
+  mfile.print link_so, "\n\n"
+  unless $static.nil?
+    mfile.print "$(STATIC_LIB): $(OBJS)\n\t"
+    mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
+    config_string('RANLIB') do |ranlib|
+      mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
+    end
+  end
+  mfile.print "\n\n"
+  if makedef
+    mfile.print "$(DEFFILE): #{origdef}\n"
+    mfile.print "\t$(RUBY) #{makedef} #{origdef} > $@\n\n"
+  end
+
+  depend = File.join(srcdir, "depend")
+  if File.exist?(depend)
+    suffixes = []
+    depout = []
+    open(depend, "r") do |dfile|
+      mfile.printf "###\n"
+      cont = implicit = nil
+      impconv = proc do
+	COMPILE_RULES.each {|rule| depout << (rule % implicit[0]) << implicit[1]}
+	implicit = nil
+      end
+      ruleconv = proc do |line|
+	if implicit
+	  if /\A\t/ =~ line
+	    implicit[1] << line
+	    next
+	  else
+	    impconv[]
+	  end
+	end
+	if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
+          suffixes << m[1] << m[2]
+	  implicit = [[m[1], m[2]], [m.post_match]]
+	  next
+	elsif RULE_SUBST and /\A[$\w][^#]*:/ =~ line
+	  line.gsub!(%r"(?<=\s)(?!\.)([^$(){}+=:\s\/\\,]+)(?=\s|\z)") {|*m| RULE_SUBST % m}
+	end
+	depout << line
+      end
+      while line = dfile.gets()
+	line.gsub!(/\.o\b/, ".#{$OBJEXT}")
+	line.gsub!(/\$\(hdrdir\)\/config.h/, $config_h) if $config_h
+	if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
+	  (cont ||= []) << line
+	  next
+	elsif cont
+	  line = (cont << line).join
+	  cont = nil
+	end
+	ruleconv.call(line)
+      end
+      if cont
+	ruleconv.call(cont.join)
+      elsif implicit
+	impconv.call
+      end
+    end
+    unless suffixes.empty?
+      mfile.print ".SUFFIXES: .", suffixes.uniq.join(" ."), "\n\n"
+    end
+    mfile.print depout
+  else
+    headers = %w[ruby.h defines.h]
+    if RULE_SUBST
+      headers.each {|h| h.sub!(/.*/) {|*m| RULE_SUBST % m}}
+    end
+    headers << $config_h if $config_h
+    mfile.print "$(OBJS): ", headers.join(' '), "\n"
+  end
+
+  $makefile_created = true
+ensure
+  mfile.close if mfile
+end
+
+def init_mkmf(config = CONFIG)
+  $makefile_created = false
+  $arg_config = []
+  $enable_shared = config['ENABLE_SHARED'] == 'yes'
+  $defs = []
+  $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
+  $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
+  $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
+  $LDFLAGS = (with_config("ldflags") || "").dup
+  $INCFLAGS = "-I$(topdir)"
+  $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
+  $LIBEXT = config['LIBEXT'].dup
+  $OBJEXT = config["OBJEXT"].dup
+  $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
+  $LIBRUBYARG = ""
+  $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
+  $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
+  $LIBPATH = $extmk ? ["$(topdir)"] : CROSS_COMPILING ? [] : ["$(libdir)"]
+  $INSTALLFILES = nil
+
+  $objs = nil
+  $srcs = nil
+  $libs = ""
+  if $enable_shared or Config.expand(config["LIBRUBY"].dup) != Config.expand(config["LIBRUBY_A"].dup)
+    $LIBRUBYARG = config['LIBRUBYARG']
+  end
+
+  $LOCAL_LIBS = ""
+
+  $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
+  $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
+
+  $extout ||= nil
+  $extout_prefix ||= nil
+
+  $arg_config.clear
+  dir_config("opt")
+end
+
+FailedMessage = <<MESSAGE
+Could not create Makefile due to some reason, probably lack of
+necessary libraries and/or headers.  Check the mkmf.log file for more
+details.  You may need configuration options.
+
+Provided configuration options:
+MESSAGE
+
+def mkmf_failed(path)
+  unless $makefile_created or File.exist?("Makefile")
+    opts = $arg_config.collect {|t, n| "\t#{t}#{"=#{n}" if n}\n"}
+    abort "*** #{path} failed ***\n" + FailedMessage + opts.join
+  end
+end
+
+init_mkmf
+
+$make = with_config("make-prog", ENV["MAKE"] || "make")
+make, = Shellwords.shellwords($make)
+$nmake = nil
+case
+when $mswin
+  $nmake = ?m if /nmake/i =~ make
+when $bccwin
+  $nmake = ?b if /Borland/i =~ `#{make} -h`
+end
+
+Config::CONFIG["srcdir"] = CONFIG["srcdir"] =
+  $srcdir = arg_config("--srcdir", File.dirname($0))
+$configure_args["--topsrcdir"] ||= $srcdir
+if $curdir = arg_config("--curdir")
+  Config.expand(curdir = $curdir.dup)
+else
+  curdir = $curdir = "."
+end
+unless File.expand_path(Config::CONFIG["topdir"]) == File.expand_path(curdir)
+  CONFIG["topdir"] = $curdir
+  Config::CONFIG["topdir"] = curdir
+end
+$configure_args["--topdir"] ||= $curdir
+$ruby = arg_config("--ruby", File.join(Config::CONFIG["bindir"], CONFIG["ruby_install_name"]))
+
+split = Shellwords.method(:shellwords).to_proc
+
+EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
+
+hdr = []
+config_string('COMMON_MACROS') do |s|
+  Shellwords.shellwords(s).each do |s|
+    /(.*?)(?:=(.*))/ =~ s
+    hdr << "#define #$1 #$2"
+  end
+end
+config_string('COMMON_HEADERS') do |s|
+  Shellwords.shellwords(s).each {|s| hdr << "#include <#{s}>"}
+end
+COMMON_HEADERS = (hdr.join("\n") unless hdr.empty?)
+COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
+
+COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
+RULE_SUBST = config_string('RULE_SUBST')
+COMPILE_C = config_string('COMPILE_C') || '$(CC) $(CFLAGS) $(CPPFLAGS) -c $<'
+COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<'
+TRY_LINK = config_string('TRY_LINK') ||
+  "$(CC) #{OUTFLAG}conftest $(INCFLAGS) -I$(hdrdir) $(CPPFLAGS) " \
+  "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
+LINK_SO = config_string('LINK_SO') ||
+  if CONFIG["DLEXT"] == $OBJEXT
+    "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
+  else
+    "$(LDSHARED) $(DLDFLAGS) $(LIBPATH) #{OUTFLAG}$@ " \
+    "$(OBJS) $(LOCAL_LIBS) $(LIBS)"
+  end
+LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
+RPATHFLAG = config_string('RPATHFLAG') || ''
+LIBARG = config_string('LIBARG') || '-l%s'
+
+sep = File::ALT_SEPARATOR ? ":/=#{File::ALT_SEPARATOR}" : ''
+CLEANINGS = "
+clean:
+		@-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
+
+distclean:	clean
+		@-$(RM) Makefile extconf.h conftest.* mkmf.log
+		@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
+
+realclean:	distclean
+"
+
+if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
+  # END {mkmf_failed($0)}
+end

Added: trunk/lib/rational.rb
===================================================================
--- trunk/lib/rational.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/lib/rational.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -0,0 +1,376 @@
+#
+#   rational.rb - 
+#   	$Release Version: 0.5 $
+#   	$Revision: 1.7 $
+#   	$Date: 1999/08/24 12:49:28 $
+#   	by Keiju ISHITSUKA(SHL Japan Inc.)
+#
+# --
+#   Usage:
+#   class Rational < Numeric
+#      (include Comparable)
+#
+#   Rational(a, b) --> a/b
+#
+#   Rational::+
+#   Rational::-
+#   Rational::*
+#   Rational::/
+#   Rational::**
+#   Rational::%
+#   Rational::divmod
+#   Rational::abs
+#   Rational::<=>
+#   Rational::to_i
+#   Rational::to_f
+#   Rational::to_s
+#
+#   Integer::gcd
+#   Integer::lcm
+#   Integer::gcdlcm
+#   Integer::to_r
+#
+#   Fixnum::**
+#   Fixnum::quo
+#   Bignum::**
+#   Bignum::quo
+#
+
+def Rational(a, b = 1)
+  if a.kind_of?(Rational) && b == 1
+    a
+  else
+    Rational.reduce(a, b)
+  end
+end
+  
+class Rational < Numeric
+  @RCS_ID='-$Id: rational.rb,v 1.7 1999/08/24 12:49:28 keiju Exp keiju $-'
+
+  def Rational.reduce(num, den = 1)
+    raise ZeroDivisionError, "denominator is zero" if den == 0
+
+    if den < 0
+      num = -num
+      den = -den
+    end
+    gcd = num.gcd(den)
+    num = num.div(gcd)
+    den = den.div(gcd)
+    if den == 1 && defined?(Unify)
+      num
+    else
+      new!(num, den)
+    end
+  end
+  
+  def Rational.new!(num, den = 1)
+    new(num, den)
+  end
+
+  # private_class_method :new
+
+  def initialize(num, den)
+    if den < 0
+      num = -num
+      den = -den
+    end
+    if num.kind_of?(Integer) and den.kind_of?(Integer)
+      @numerator = num
+      @denominator = den
+    else
+      @numerator = num.to_i
+      @denominator = den.to_i
+    end
+  end
+  
+  def + (a)
+    if a.kind_of?(Rational)
+      num = @numerator * a.denominator
+      num_a = a.numerator * @denominator
+      Rational(num + num_a, @denominator * a.denominator)
+    elsif a.kind_of?(Integer)
+      self + Rational.new!(a, 1)
+    elsif a.kind_of?(Float)
+      Float(self) + a
+    else
+      x, y = a.coerce(self)
+      x + y
+    end
+  end
+  
+  def - (a)
+    if a.kind_of?(Rational)
+      num = @numerator * a.denominator
+      num_a = a.numerator * @denominator
+      Rational(num - num_a, @denominator*a.denominator)
+    elsif a.kind_of?(Integer)
+      self - Rational.new!(a, 1)
+    elsif a.kind_of?(Float)
+      Float(self) - a
+    else
+      x, y = a.coerce(self)
+      x - y
+    end
+  end
+  
+  def * (a)
+    if a.kind_of?(Rational)
+      num = @numerator * a.numerator
+      den = @denominator * a.denominator
+      Rational(num, den)
+    elsif a.kind_of?(Integer)
+      self * Rational.new!(a, 1)
+    elsif a.kind_of?(Float)
+      Float(self) * a
+    else
+      x, y = a.coerce(self)
+      x * y
+    end
+  end
+  
+  def / (a)
+    if a.kind_of?(Rational)
+      num = @numerator * a.denominator
+      den = @denominator * a.numerator
+      Rational(num, den)
+    elsif a.kind_of?(Integer)
+      raise ZeroDivisionError, "division by zero" if a == 0
+      self / Rational.new!(a, 1)
+    elsif a.kind_of?(Float)
+      Float(self) / a
+    else
+      x, y = a.coerce(self)
+      x / y
+    end
+  end
+  
+  def ** (other)
+    if other.kind_of?(Rational)
+      Float(self) ** other
+    elsif other.kind_of?(Integer)
+      if other > 0
+	num = @numerator ** other
+	den = @denominator ** other
+      elsif other < 0
+	num = @denominator ** -other
+	den = @numerator ** -other
+      elsif other == 0
+	num = 1
+	den = 1
+      end
+      Rational.new!(num, den)
+    elsif other.kind_of?(Float)
+      Float(self) ** other
+    else
+      x, y = other.coerce(self)
+      x ** y
+    end
+  end
+  
+  def % (other)
+    value = (self / other).to_i
+    return self - other * value
+  end
+  
+  def divmod(other)
+    value = (self / other).to_i
+    return value, self - other * value
+  end
+  
+  def abs
+    if @numerator > 0
+      Rational.new!(@numerator, @denominator)
+    else
+      Rational.new!(-@numerator, @denominator)
+    end
+  end
+
+  def == (other)
+    if other.kind_of?(Rational)
+      @numerator == other.numerator and @denominator == other.denominator
+    elsif other.kind_of?(Integer)
+      self == Rational.new!(other, 1)
+    elsif other.kind_of?(Float)
+      Float(self) == other
+    else
+      other == self
+    end
+  end
+
+  def <=> (other)
+    if other.kind_of?(Rational)
+      num = @numerator * other.denominator
+      num_a = other.numerator * @denominator
+      v = num - num_a
+      if v > 0
+	return 1
+      elsif v < 0
+	return  -1
+      else
+	return 0
+      end
+    elsif other.kind_of?(Integer)
+      return self <=> Rational.new!(other, 1)
+    elsif other.kind_of?(Float)
+      return Float(self) <=> other
+    elsif defined? other.coerce
+      x, y = other.coerce(self)
+      return x <=> y
+    else
+      return nil
+    end
+  end
+
+  def coerce(other)
+    if other.kind_of?(Float)
+      return other, self.to_f
+    elsif other.kind_of?(Integer)
+      return Rational.new!(other, 1), self
+    else
+      super
+    end
+  end
+
+  def to_i
+    Integer( numerator.div( denominator))
+  end
+  
+  def to_f
+    @numerator.to_f/ denominator.to_f
+  end
+  
+  def to_s
+    if @denominator == 1
+      @numerator.to_s
+    else
+      @numerator.to_s+"/"+ denominator.to_s
+    end
+  end
+  
+  def to_r
+    self
+  end
+  
+  def inspect
+    sprintf("Rational(%s, %s)", @numerator.inspect, @denominator.inspect)
+  end
+  
+  def hash
+    @numerator.hash ^ @denominator.hash
+  end
+  
+  attr :numerator
+  attr :denominator
+  
+  private :initialize
+end
+
+class Integer
+  def numerator
+    self
+  end
+  
+  def denominator
+    1
+  end
+  
+  def to_r
+    Rational(self, 1)
+  end
+  
+  def gcd(n)
+    m = self.abs
+    n = n.abs
+
+    return n if m == 0
+    return m if n == 0
+
+    b = 0
+    while n[0] == 0 && m[0] == 0
+      b += 1; n >>= 1; m >>= 1
+    end
+    m >>= 1 while m[0] == 0
+    n >>= 1 while n[0] == 0
+    while m != n
+      m, n = n, m if n > m
+      m -= n; m >>= 1 while m[0] == 0
+    end
+    m << b
+  end
+  
+  def gcd2(int)
+    a = self.abs
+    b = int.abs
+  
+    a, b = b, a if a < b
+  
+    while b != 0
+      void, a = a.divmod(b)
+      a, b = b, a
+    end
+    return a
+  end
+
+  def lcm(other)
+    if self.zero? or other.zero?
+      0
+    else
+      (self.div(self.gcd(other)) * other).abs
+    end
+  end
+  
+  def gcdlcm(other)
+    gcd = self.gcd(other)
+    if self.zero? or other.zero?
+      [gcd, 0]
+    else
+      [gcd, (self.div(gcd) * other).abs]
+    end
+  end
+end
+
+class Fixnum
+  undef quo
+  def quo(other)
+    Rational.new!(self,1) / other
+  end
+  alias rdiv quo
+  
+  def rpower (other)
+    if other >= 0
+      self.power!(other)
+    else
+      Rational.new!(self,1)**other
+    end
+  end
+
+  unless defined? 1.power!
+    alias power! ** 
+    alias ** rpower
+  end
+end
+
+class Bignum
+  unless defined? Complex
+    alias power! **
+  end
+
+  undef quo
+  def quo(other)
+    Rational.new!(self,1) / other
+  end
+  alias rdiv quo
+  
+  def rpower (other)
+    if other >= 0
+      self.power!(other)
+    else
+      Rational.new!(self, 1)**other
+    end
+  end
+  
+  unless defined? Complex
+    alias ** rpower
+  end
+end

Modified: trunk/parse.y
===================================================================
--- trunk/parse.y	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/parse.y	2005-10-27 23:53:45 UTC (rev 282)
@@ -4648,9 +4648,7 @@
 
 static VALUE lex_get_str(struct parser_params *, VALUE);
 static VALUE
-lex_get_str(parser, s)
-    struct parser_params *parser;
-    VALUE s;
+lex_get_str(struct parser_params *parser, VALUE s)
 {
     char *beg, *end, *pend;
 
@@ -7978,10 +7976,7 @@
 }
 
 static NODE*
-new_call(r,m,a)
-    NODE *r;
-    ID m;
-    NODE *a;
+new_call(NODE *r,ID m, NODE *a)
 {
     if (a && nd_type(a) == NODE_BLOCK_PASS) {
 	a->nd_iter = NEW_CALL(r,m,a->nd_head);
@@ -7991,10 +7986,7 @@
 }
 
 static NODE*
-new_fcall_gen(parser, m, a)
-    struct parser_params *parser;
-    ID m;
-    NODE *a;
+new_fcall_gen(struct parser_params *parser, ID m, NODE *a)
 {
     if (a && nd_type(a) == NODE_BLOCK_PASS) {
 	a->nd_iter = NEW_FCALL(m,a->nd_head);
@@ -8004,8 +7996,7 @@
 }
 
 static NODE*
-new_super(a)
-    NODE *a;
+new_super(NODE *a)
 {
     if (a && nd_type(a) == NODE_BLOCK_PASS) {
 	a->nd_iter = NEW_SUPER(a->nd_head);
@@ -8173,17 +8164,14 @@
 }
 
 static int
-dyna_push_gen(parser)
-    struct parser_params *parser;
+dyna_push_gen(struct parser_params *parser)
 {
     lvtbl->dvars = vtable_alloc(lvtbl->dvars);
     return 0;
 }
 
 static void
-dyna_pop_gen(parser, vars)
-    struct parser_params *parser;
-    struct RVarmap* vars;
+dyna_pop_gen(struct parser_params *parser, struct RVarmap* vars)
 {
     struct vtable *tmp = lvtbl->dvars;
     lvtbl->dvars = lvtbl->dvars->prev;
@@ -8191,17 +8179,13 @@
 }
 
 static int
-dyna_in_block_gen(parser)
-    struct parser_params *parser;
+dyna_in_block_gen(struct parser_params *parser)
 {
     return lvtbl->dvars != 0;
 }
 
 static NODE *
-dyna_init_gen(parser, node, pre_cnt)
-    struct parser_params *parser;
-    NODE *node;
-    int pre_cnt;
+dyna_init_gen(struct parser_params *parser, NODE *node, int pre_cnt)
 {
     NODE *var;
     int post_cnt = vtable_size(lvtbl->dvars);
@@ -8214,9 +8198,7 @@
 }
 
 static int
-dvar_defined_gen(parser, id)
-     struct parser_params *parser;
-     ID id;
+dvar_defined_gen(struct parser_params *parser, ID id)
 {
     struct vtable *dvars = lvtbl->dvars;
     while((VALUE)dvars & ~3){
@@ -8232,21 +8214,18 @@
 }
 
 static int
-dvar_curr_gen(parser, id)
-     struct parser_params *parser;
-     ID id;
+dvar_curr_gen(struct parser_params *parser, ID id)
 {
     return vtable_included(lvtbl->dvars, id);
 }
 
 void
-rb_gc_mark_parser()
+rb_gc_mark_parser(void)
 {
 }
 
 NODE*
-rb_parser_append_print(node)
-    NODE *node;
+rb_parser_append_print(NODE *node)
 {
     NODE *prelude = 0;
 
@@ -8502,40 +8481,35 @@
 }
 
 int
-rb_is_const_id(id)
-    ID id;
+rb_is_const_id(ID id)
 {
     if (is_const_id(id)) return Qtrue;
     return Qfalse;
 }
 
 int
-rb_is_class_id(id)
-    ID id;
+rb_is_class_id(ID id)
 {
     if (is_class_id(id)) return Qtrue;
     return Qfalse;
 }
 
 int
-rb_is_instance_id(id)
-    ID id;
+rb_is_instance_id(ID id)
 {
     if (is_instance_id(id)) return Qtrue;
     return Qfalse;
 }
 
 int
-rb_is_local_id(id)
-    ID id;
+rb_is_local_id(ID id)
 {
     if (is_local_id(id)) return Qtrue;
     return Qfalse;
 }
 
 int
-rb_is_junk_id(id)
-    ID id;
+rb_is_junk_id(ID id)
 {
     if (is_junk_id(id)) return Qtrue;
     return Qfalse;
@@ -8544,8 +8518,7 @@
 #endif /* !RIPPER */
 
 static void
-parser_initialize(parser)
-    struct parser_params *parser;
+parser_initialize(struct parser_params *parser)
 {
     parser->eofp = Qfalse;
 

Modified: trunk/rb/yasm.rb
===================================================================
--- trunk/rb/yasm.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/rb/yasm.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -310,3 +310,7 @@
   end
 end
 
+hoge.each{|i|
+  
+}
+

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/test.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -1,6 +1,3 @@
-p 0*1
 
-__END__
-p bitblt
-p the_answer_to_life_the_universe_and_everything
-
+require 'mkmf'
+create_makefile('hoge')

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/vm.c	2005-10-27 23:53:45 UTC (rev 282)
@@ -195,13 +195,16 @@
   env->local_size = local_size;
   env->env = ALLOC_N(VALUE, env->env_size);
   env->prev_envval = penvval;
-  
+
   for(i=0; i<=local_size; i++){
     env->env[i] = envptr[-local_size + i];
-    envptr[-local_size + i] = 0;
+    if(cfp->iseq != 0 && !CMETHOD_INFO_P(cfp->iseq)){
+      /* clear value stack for GC */
+      envptr[-local_size + i] = 0;
+    }
   }
+
   *envptr = envval; /* GC mark */
-
   nenvptr = &env->env[i-1];
   nenvptr[1] = Qfalse; /* frame is not orphan */
   nenvptr[2] = Qundef; /* frame is in heap    */
@@ -331,9 +334,7 @@
     GetProcVal(proc->blockprocval, p);
     *cfp->lfp = GC_GUARDED_PTR(&p->block);
   }
-
   envval = th_make_env_object(th, cfp);
-
   proc->block.self = block->self;
   proc->block.lfp  = block->lfp;
   proc->block.dfp  = block->dfp;

Modified: trunk/vm.h
===================================================================
--- trunk/vm.h	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/vm.h	2005-10-27 23:53:45 UTC (rev 282)
@@ -33,7 +33,7 @@
 
 #if 0
 #undef  VMDEBUG
-#define VMDEBUG 10
+#define VMDEBUG 3
 #endif
 
 // #define COLLECT_USAGE_ANALYSIS

Modified: trunk/vm_dump.c
===================================================================
--- trunk/vm_dump.c	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/vm_dump.c	2005-10-27 23:53:45 UTC (rev 282)
@@ -53,7 +53,7 @@
     }
     else{
       pc = cfp->pc - cfp->iseq->iseq_encoded;
-      iseq_name = "";//RSTRING(cfp->iseq->name)->ptr;
+      iseq_name = RSTRING(cfp->iseq->name)->ptr;
     }
   }
   
@@ -186,7 +186,10 @@
      cfp->magic == FRAME_MAGIC_TOP    ||
      cfp->magic == FRAME_MAGIC_BLOCK  ||
      cfp->magic == FRAME_MAGIC_CLASS  ||
-     cfp->magic == FRAME_MAGIC_PROC){
+     cfp->magic == FRAME_MAGIC_PROC   ||
+     cfp->magic == FRAME_MAGIC_CFUNC  ||
+     cfp->magic == FRAME_MAGIC_IFUNC  ||
+     cfp->magic == FRAME_MAGIC_EVAL){
 
     if(cfp->pc){
       stack_dump_each(th, cfp+1);
@@ -299,6 +302,7 @@
     printf("  sc reg B: %s\n", StringValueCStr(rstr));
   }
 #endif
+  printf("--------------------------------------------------------------\n");
 #endif
 
 #if VMDEBUG > 9
@@ -478,3 +482,9 @@
   return Qnil;
 }
 
+void
+yarv_bug(){
+  yarv_thread_t *th = GET_THREAD();
+  dp(th_backtrace(th, 0));
+  SDR();
+}

Modified: trunk/vm_macro.def
===================================================================
--- trunk/vm_macro.def	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/vm_macro.def	2005-10-27 23:53:45 UTC (rev 282)
@@ -10,8 +10,17 @@
     VALUE proc;
     
     proc = TOPN(0);
-    GetProcVal(proc, po);
-    blockptr = &po->block;
+    if(proc != Qnil){
+      if(!yarv_obj_is_proc(proc)){
+        proc = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
+        if(!yarv_obj_is_proc(proc)){
+          rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc)",
+                   rb_obj_classname(proc));
+        }
+      }
+      GetProcVal(proc, po);
+      blockptr = &po->block;
+    }
     INC_SP(-1);
   }
   else if(blockval){
@@ -239,11 +248,18 @@
     case NODE_SCOPE:{
       dpi(id);
       SDR();
-      rb_bug("eval_invoke_method: NODE_SCOPE");
+      rb_bug("eval_invoke_method: NODE_SCOPE should not be appear");
       /* unreachable */
       break;
     }
+    case NODE_ZSUPER:{
+      int *a = 0;
+      dpi(id);
+      SDR();
+      *a = 0;
+    }
     default:{
+      printf("node: %s\n", node_name(nd_type(mn)));
       rb_bug("eval_invoke_method: unreachable");
       /* unreachable */
       break;

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/yarvcore.c	2005-10-27 23:53:45 UTC (rev 282)
@@ -797,10 +797,15 @@
   return th_invoke_proc(GET_THREAD(), proc, argc, argv);
 }
 
-static VALUE akr(VALUE self){
-  volatile int *a = 0;
-  *a = 0;
-  return 0;
+VALUE
+yarv_obj_is_proc(VALUE proc){
+  if (TYPE(proc) == T_DATA &&
+      RDATA(proc)->dfree == (RUBY_DATA_FUNC)proc_free){
+    return Qtrue;
+  }
+  else{
+    return Qfalse;
+  }
 }
 
 /********************************************************************/
@@ -923,7 +928,6 @@
   rb_define_global_function("once", yarv_once, 0);
   rb_define_global_function("cfunc", cfunc, 0);
   rb_define_global_function("yarv_caller", yarv_caller, 1);
-  rb_define_global_function("akr", akr, 0);
   
   /* Integer#times */
   rb_define_method(rb_cInteger, "times", yarv_Integer_times, 0);

Modified: trunk/yarvtest/test_massign.rb
===================================================================
--- trunk/yarvtest/test_massign.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/yarvtest/test_massign.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -360,28 +360,39 @@
 
   # ignore
   def _test_massign_value
-   # Value of this massign statement should be [1, 2, 3]
-   ae %q{
-     a, b, c = [1, 2, 3]
-   }
- end
-
- def test_nested_splat
-   # Somewhat obscure nested splat
-   ae %q{
-     a = *[*[1]]
-     a
-   }
- end
- 
- def test_calls_to_a
-   # Should be result of calling to_a on arg, ie [[1, 2], [3, 4]]
-   ae %q{
-     x=*{1=>2,3=>4}
-     x
-   }
- end
-
+    # Value of this massign statement should be [1, 2, 3]
+    ae %q{
+      a, b, c = [1, 2, 3]
+    }
+  end
+  
+  def test_nested_splat
+    # Somewhat obscure nested splat
+    ae %q{
+      a = *[*[1]]
+      a
+    }
+  end
+  
+  def test_calls_to_a
+    # Should be result of calling to_a on arg, ie [[1, 2], [3, 4]]
+    ae %q{
+      x=*{1=>2,3=>4}
+      x
+    }
+  end
+  
+  def test_const_massign
+    ae %q{
+      class C
+        class D
+        end
+      end
+      
+      X, Y = 1, 2
+      Z, C::Const, C::D::Const, ::C::Const2 = 3, 4, 5, 6
+      [X, Y, Z, C::Const, C::D::Const, ::C::Const2]
+    }
+  end
 end
 
-

Modified: trunk/yarvtest/test_method.rb
===================================================================
--- trunk/yarvtest/test_method.rb	2005-10-27 02:54:30 UTC (rev 281)
+++ trunk/yarvtest/test_method.rb	2005-10-27 23:53:45 UTC (rev 282)
@@ -363,6 +363,24 @@
         [x+y, x*y]
       }
     }
+    ae %q{
+      def m &b
+        b
+      end
+      m(&nil)
+    }
+    ae %q{
+      def m a, &b
+        [a, b]
+      end
+      m(1, &nil)
+    }
+    ae %q{
+      def m
+        [a, block_given?]
+      end
+      m(&nil)
+    }
   end
 
   def test_method_missing


--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]