/*
 *  call-seq:
 *     binding -> a_binding
 *  
 *  Returns a +Binding+ object, describing the variable and
 *  method bindings at the point of call. This object can be used when
 *  calling +eval+ to execute the evaluated command in this
 *  environment. Also see the description of class +Binding+.
 *     
 *     def getBinding(param)
 *       return binding
 *     end
 *     b = getBinding("hello")
 *     eval("param", b)   #=> "hello"
 */

static VALUE
rb_f_binding(self)
    VALUE self;
{
    struct BLOCK *data, *p;
    struct RVarmap *vars;
    VALUE bind;

    PUSH_BLOCK(0,0);
    bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
    *data = *ruby_block;

    data->orig_thread = rb_thread_current();
    data->wrapper = ruby_wrapper;
    data->iter = rb_f_block_given_p();
    frame_dup(&data->frame);
    if (ruby_frame->prev) {
        data->frame.last_func = ruby_frame->prev->last_func;
        data->frame.last_class = ruby_frame->prev->last_class;
        data->frame.orig_func = ruby_frame->prev->orig_func;
    }

    if (data->iter) {
        blk_copy_prev(data);
    }
    else {
        data->prev = 0;
    }

    for (p = data; p; p = p->prev) {
        for (vars = p->dyna_vars; vars; vars = vars->next) {
            if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
            FL_SET(vars, DVAR_DONT_RECYCLE);
        }
    }
    scope_dup(data->scope);
    POP_BLOCK();

    return bind;
}