Hey guys!

I'm embedding Ruby in my most recent application, and using it as a glue to to 
piece all my C/C++ modules together.  

I've found the default implementation of rb_protect() usefull, but somewhat 
lacking.  I frequently call handlers written in ruby from my C/C++ code using the 
rb_funcall functions.  Of course, the problem with that is that when there is a 
problem with the ruby script, my application exits out rather ungracefully, hence 
the need for rb_protect.  My application will potentially have MANY MANY callbacks 
implemented in it by the time it is done, and it is very inconvenient to write C 
wrapper functions for each callback and pass those wrapper functions to rb_protect.

Because of this, I've modified eval.c and ruby.h to add a couple extra functions.  
These funtions work like a combination of rb_protect combined with rb_load_file, 
rb_require, rb_funcall2, or rb_funcall3 (I did not implement a version of 
rb_funcall since I did not want to create a duplicate of the functionality in that 
function).  I've found these functions very usefull, and they will save me a lot of 
uneccessary coding effort.  I feel they are worth including in the next version of 
Ruby, so I'm submitting them here with the hopes that they will be included and 
hopefully help somebody else out in the future.

Thanks,
Bryan


---SNIP-- add these to eval.c and definitions to ruby.h --SNIP--

VALUE
rb_protect_funcall2(recv, id, argc, args, state)
        VALUE recv;
        ID id;
        int argc;
        VALUE *args;
        int *state;
{
        VALUE result;
        int status;

        PUSH_TAG(PROT_NONE);
        if ((status = EXEC_TAG()) == 0) {
                result = rb_funcall2(recv, id, argc, args);
        }
        POP_TAG();
        if (state) {
                *state = status;
        }
        if (status != 0) {
                return Qnil;
        }

        return result;
}

VALUE
rb_protect_funcall3(recv, id, argc, args, state)
        VALUE recv;
        ID id;
        int argc;
        VALUE *args;
        int *state;
{
        VALUE result;
        int status;

        PUSH_TAG(PROT_NONE);
        if ((status = EXEC_TAG()) == 0) {
                result = rb_funcall3(recv, id, argc, args);
        }
        POP_TAG();
        if (state) {
                *state = status;
        }
        if (status != 0) {
                return Qnil;
        }

        return result;
}

VALUE
rb_protect_require(name, state)
       char *name;
       int *state;
{
        VALUE result;
        int status;

        PUSH_TAG(PROT_NONE);
        if ((status = EXEC_TAG()) == 0) {
                result = rb_require(name);
        }
        POP_TAG();
        if (state) {
                *state = status;
        }
        if (status != 0) {
                return Qfalse;
        }

        return result;
}

void
rb_protect_load_file(name, state)
       char *name;
       int *state;
{
        VALUE result;
        int status;

        PUSH_TAG(PROT_NONE);
        if ((status = EXEC_TAG()) == 0) {
                rb_load_file(name);
        }
        POP_TAG();
        if (state) {
                *state = status;
        }
}