/*
 *  call-seq:
 *     callcc {|cont| block }   =>  obj
 *  
 *  Generates a <code>Continuation</code> object, which it passes to the
 *  associated block. Performing a <em>cont</em><code>.call</code> will
 *  cause the <code>callcc</code> to return (as will falling through the
 *  end of the block). The value returned by the <code>callcc</code> is
 *  the value of the block, or the value passed to
 *  <em>cont</em><code>.call</code>. See class <code>Continuation</code> 
 *  for more details. Also see <code>Kernel::throw</code> for
 *  an alternative mechanism for unwinding a call stack.
 */

static VALUE
rb_callcc(self)
    VALUE self;
{
    volatile VALUE cont;
    rb_thread_t th;
    volatile rb_thread_t th_save;
    struct tag *tag;
    struct RVarmap *vars;

    THREAD_ALLOC(th);
    /* must finish th initialization before any possible gc.
     * brent@mbari.org */
    th->thread = curr_thread->thread;
    th->thgroup = cont_protect;
    cont = Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th);

    scope_dup(ruby_scope);
    for (tag=prot_tag; tag; tag=tag->prev) {
        scope_dup(tag->scope);
    }

    for (vars = ruby_dyna_vars; vars; vars = vars->next) {
        if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
        FL_SET(vars, DVAR_DONT_RECYCLE);
    }
    th_save = th;
    if (THREAD_SAVE_CONTEXT(th)) {
        return th_save->result;
    }
    else {
        return rb_yield(cont);
    }
}