近藤と申します。

Mac OS X(Darwin)ではLinuxのようにスタックが自動伸長しないので、racc等で
スタックが溢れてしまうことがあります。
今まではシェルでlimitなりulimitなりして対応していましたが、せっかくなので
ある程度スタックを使ったら自動的にsetrlimitするようにしてみました。
eval.cの変更はスタックサイズが1MBのとき、以下のメソッドでruby_stack_check
を通るタイミングが、スタックの伸びに追いつくようにしただけです。
 def fact(n) if n < 2 then 1 else n * fact(n - 1) end end

$ /usr/bin/ruby -v fact.rb 99
ruby 1.6.8 (2002-12-24) [powerpc-darwin7.0]
(省略)
$ ruby-1.8.1 -v fact.rb 85
ruby 1.8.1 (2003-12-25) [powerpc-darwin]
(省略)
$ ruby-current -v fact.rb 5524
ruby 1.9.0 (2004-10-02) [powerpc-darwin7.5.0]
(省略)

以下パッチです。
--- eval.c.orig Sun Oct  3 01:34:33 2004
+++ eval.c      Sun Oct  3 01:37:17 2004
@@ -5464,5 +5464,9 @@ rb_call0(klass, recv, id, oid, argc, arg
      }

+#ifdef __APPLE__
+    if ((++tick & 0x7f) == 0) {
+#else
      if ((++tick & 0xff) == 0) {
+#endif
         CHECK_INTS;             /* better than nothing */
         stack_check();

--- gc.c.orig   Sun Oct  3 01:34:33 2004
+++ gc.c        Sun Oct  3 01:38:16 2004
@@ -492,4 +492,21 @@ ruby_stack_check()
      int ret;

+#ifdef __APPLE__
+    SET_STACK_END;
+    if (STACK_LENGTH < 2 * STACK_LEVEL_MAX + GC_WATER_MARK) {
+        struct rlimit rlim;
+       if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
+           rlim.rlim_cur = (rlim.rlim_cur * 3) / 2;
+           if (rlim.rlim_max < rlim.rlim_cur)
+                rlim.rlim_cur = rlim.rlim_max;
+           if (setrlimit(RLIMIT_STACK, &rlim) == 0) {
+               unsigned int space = rlim.rlim_cur/5;
+
+               if (space > 1024*1024) space = 1024*1024;
+               STACK_LEVEL_MAX = (rlim.rlim_cur - space) / 
sizeof(VALUE);
+           }
+       }
+    }
+#endif
      CHECK_STACK(ret);
      return ret;

---
近藤充弘