ip_rbUpdateCommand(clientData, interp, objc, objv)
    ClientData clientData;
    Tcl_Interp *interp;
    int objc;
    char *objv[];
#endif
{
    int  flags = 0;
    static CONST char *updateOptions[] = {"idletasks", (char *) NULL};
    enum updateOptions {REGEXP_IDLETASKS};

    DUMP1("Ruby's 'update' is called");
    if (interp == (Tcl_Interp*)NULL) {
        rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
                                             "IP is deleted");
        return TCL_ERROR;
    }
#ifdef HAVE_NATIVETHREAD
#ifndef RUBY_USE_NATIVE_THREAD
    if (!ruby_native_thread_p()) {
        rb_bug("cross-thread violation on ip_ruby_eval()");
    }
#endif
#endif

    Tcl_ResetResult(interp);

    if (objc == 1) {
        flags = TCL_DONT_WAIT;

    } else if (objc == 2) {
#if TCL_MAJOR_VERSION >= 8
        int  optionIndex;
        if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)updateOptions,
                "option", 0, &optionIndex) != TCL_OK) {
            return TCL_ERROR;
        }
        switch ((enum updateOptions) optionIndex) {
            case REGEXP_IDLETASKS: {
                flags = TCL_IDLE_EVENTS;
                break;
            }
            default: {
                rb_bug("ip_rbUpdateObjCmd: bad option index to UpdateOptions");
            }
        }
#else
        if (strncmp(objv[1], "idletasks", strlen(objv[1])) != 0) {
            Tcl_AppendResult(interp, "bad option \"", objv[1],
                    "\": must be idletasks", (char *) NULL);
            return TCL_ERROR;
        }
        flags = TCL_IDLE_EVENTS;
#endif
    } else {
#ifdef Tcl_WrongNumArgs
        Tcl_WrongNumArgs(interp, 1, objv, "[ idletasks ]");
#else
# if TCL_MAJOR_VERSION >= 8
        int  dummy;
        Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
                         Tcl_GetStringFromObj(objv[0], &dummy),
                         " [ idletasks ]\"",
                         (char *) NULL);
# else /* TCL_MAJOR_VERSION < 8 */
        Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
                         objv[0], " [ idletasks ]\"", (char *) NULL);
# endif
#endif
        return TCL_ERROR;
    }

    Tcl_Preserve(interp);

    /* call eventloop */
    /* ret = lib_eventloop_core(0, flags, (int *)NULL);*/ /* ignore result */
    lib_eventloop_launcher(0, flags, (int *)NULL, interp); /* ignore result */

    /* exception check */
    if (!NIL_P(rbtk_pending_exception)) {
        Tcl_Release(interp);

        /*
        if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)) {
        */
        if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)
            || rb_obj_is_kind_of(rbtk_pending_exception, rb_eInterrupt)) {
            return TCL_RETURN;
        } else{
            return TCL_ERROR;
        }
    }

    /* trap check */
    if (rb_thread_check_trap_pending()) {
        Tcl_Release(interp);

        return TCL_RETURN;
    }

    /*
     * Must clear the interpreter's result because event handlers could
     * have executed commands.
     */

    DUMP2("last result '%s'", Tcl_GetStringResult(interp));
    Tcl_ResetResult(interp);
    Tcl_Release(interp);

    DUMP1("finish Ruby's 'update'");
    return TCL_OK;
}
ip_rbUpdateCommand(clientData, interp, objc, objv)
    ClientData clientData;
    Tcl_Interp *interp;
    int objc;
    char *objv[];
#endif
{
    int  flags = 0;
    static CONST char *updateOptions[] = {"idletasks", (char *) NULL};
    enum updateOptions {REGEXP_IDLETASKS};

    DUMP1("Ruby's 'update' is called");
    if (interp == (Tcl_Interp*)NULL) {
        rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
                                             "IP is deleted");
        return TCL_ERROR;
    }
#ifdef HAVE_NATIVETHREAD
#ifndef RUBY_USE_NATIVE_THREAD
    if (!ruby_native_thread_p()) {
        rb_bug("cross-thread violation on ip_ruby_eval()");
    }
#endif
#endif

    Tcl_ResetResult(interp);

    if (objc == 1) {
        flags = TCL_DONT_WAIT;

    } else if (objc == 2) {
#if TCL_MAJOR_VERSION >= 8
        int  optionIndex;
        if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)updateOptions,
                "option", 0, &optionIndex) != TCL_OK) {
            return TCL_ERROR;
        }
        switch ((enum updateOptions) optionIndex) {
            case REGEXP_IDLETASKS: {
                flags = TCL_IDLE_EVENTS;
                break;
            }
            default: {
                rb_bug("ip_rbUpdateObjCmd: bad option index to UpdateOptions");
            }
        }
#else
        if (strncmp(objv[1], "idletasks", strlen(objv[1])) != 0) {
            Tcl_AppendResult(interp, "bad option \"", objv[1],
                    "\": must be idletasks", (char *) NULL);
            return TCL_ERROR;
        }
        flags = TCL_IDLE_EVENTS;
#endif
    } else {
#ifdef Tcl_WrongNumArgs
        Tcl_WrongNumArgs(interp, 1, objv, "[ idletasks ]");
#else
# if TCL_MAJOR_VERSION >= 8
        int  dummy;
        Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
                         Tcl_GetStringFromObj(objv[0], &dummy),
                         " [ idletasks ]\"",
                         (char *) NULL);
# else  
        Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
                         objv[0], " [ idletasks ]\"", (char *) NULL);
# endif
#endif
        return TCL_ERROR;
    }

    Tcl_Preserve(interp);

     
       
    lib_eventloop_launcher(0, flags, (int *)NULL, interp);  

     
    if (!NIL_P(rbtk_pending_exception)) {
        Tcl_Release(interp);

         
        if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)
            || rb_obj_is_kind_of(rbtk_pending_exception, rb_eInterrupt)) {
            return TCL_RETURN;
        } else{
            return TCL_ERROR;
        }
    }

     
    if (rb_thread_check_trap_pending()) {
        Tcl_Release(interp);

        return TCL_RETURN;
    }

     

    DUMP2("last result '%s'", Tcl_GetStringResult(interp));
    Tcl_ResetResult(interp);
    Tcl_Release(interp);

    DUMP1("finish Ruby's 'update'");
    return TCL_OK;
}