aboutsummaryrefslogtreecommitdiffstats
path: root/ext/tcltklib/tcltklib.c
diff options
context:
space:
mode:
authornagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-01-25 14:31:45 +0000
committernagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-01-25 14:31:45 +0000
commit4116b8b0f5e04347782dfbce5b1ee35134e2a31a (patch)
treed9a3897ffd5f5b93a814e71ad460d654c14684c6 /ext/tcltklib/tcltklib.c
parent5ff5e1c91d436e44b6ecd2a8c74c191252af2ed6 (diff)
downloadruby-4116b8b0f5e04347782dfbce5b1ee35134e2a31a.tar.gz
* ext/tk: merge tcltklib for Ruby/Tk installation control
* ext/tcltklib: remove git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7826 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/tcltklib/tcltklib.c')
-rw-r--r--ext/tcltklib/tcltklib.c6541
1 files changed, 0 insertions, 6541 deletions
diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c
deleted file mode 100644
index c9a72ed4bd..0000000000
--- a/ext/tcltklib/tcltklib.c
+++ /dev/null
@@ -1,6541 +0,0 @@
-/*
- * tcltklib.c
- * Aug. 27, 1997 Y. Shigehiro
- * Oct. 24, 1997 Y. Matsumoto
- */
-
-#define TCLTKLIB_RELEASE_DATE "2005-01-25"
-
-#include "ruby.h"
-#include "rubysig.h"
-#include "version.h"
-#undef EXTERN /* avoid conflict with tcl.h of tcl8.2 or before */
-#include <stdio.h>
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-#include <string.h>
-#include <tcl.h>
-#include <tk.h>
-
-#ifdef __MACOS__
-# include <tkMac.h>
-# include <Quickdraw.h>
-#endif
-
-#if TCL_MAJOR_VERSION >= 8
-# ifndef CONST84
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 4 /* Tcl8.0.x -- 8.4b1 */
-# define CONST84
-# else /* unknown (maybe TCL_VERSION >= 8.5) */
-# ifdef CONST
-# define CONST84 CONST
-# else
-# define CONST84
-# endif
-# endif
-# endif
-#else /* TCL_MAJOR_VERSION < 8 */
-# ifdef CONST
-# define CONST84 CONST
-# else
-# define CONST
-# define CONST84
-# endif
-#endif
-
-/* copied from eval.c */
-#define TAG_RETURN 0x1
-#define TAG_BREAK 0x2
-#define TAG_NEXT 0x3
-#define TAG_RETRY 0x4
-#define TAG_REDO 0x5
-#define TAG_RAISE 0x6
-#define TAG_THROW 0x7
-#define TAG_FATAL 0x8
-
-/* for ruby_debug */
-#define DUMP1(ARG1) if (ruby_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1); fflush(stderr); }
-#define DUMP2(ARG1, ARG2) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
-fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); fflush(stderr); }
-/*
-#define DUMP1(ARG1)
-#define DUMP2(ARG1, ARG2)
-*/
-
-/* release date */
-const char tcltklib_release_date[] = TCLTKLIB_RELEASE_DATE;
-
-/* finalize_proc_name */
-static char *finalize_hook_name = "INTERP_FINALIZE_HOOK";
-
-/* to cancel remained after-scripts when deleting IP */
-#define CANCEL_AFTER_SCRIPTS "__ruby_tcltklib_cancel_after_scripts__"
-#define DEF_CANCEL_AFTER_SCRIPTS_PROC "proc __ruby_tcltklib_cancel_after_scripts__ {} {foreach id [after info] {after cancel $id}}"
-
-/* for callback break & continue */
-static VALUE eTkCallbackReturn;
-static VALUE eTkCallbackBreak;
-static VALUE eTkCallbackContinue;
-
-static VALUE eLocalJumpError;
-
-static ID ID_at_enc;
-static ID ID_at_interp;
-
-static ID ID_stop_p;
-static ID ID_kill;
-static ID ID_join;
-
-static ID ID_call;
-static ID ID_backtrace;
-static ID ID_message;
-
-static ID ID_at_reason;
-static ID ID_return;
-static ID ID_break;
-static ID ID_next;
-
-static ID ID_to_s;
-static ID ID_inspect;
-
-static VALUE ip_invoke_real _((int, VALUE*, VALUE));
-static VALUE ip_invoke _((int, VALUE*, VALUE));
-
-/* from tkAppInit.c */
-
-#if TCL_MAJOR_VERSION < 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 4)
-# if !defined __MINGW32__ && !defined __BORLANDC__
-/*
- * The following variable is a special hack that is needed in order for
- * Sun shared libraries to be used for Tcl.
- */
-
-extern int matherr();
-int *tclDummyMathPtr = (int *) matherr;
-# endif
-#endif
-
-/*---- module TclTkLib ----*/
-
-struct invoke_queue {
- Tcl_Event ev;
- int argc;
-#if TCL_MAJOR_VERSION >= 8
- Tcl_Obj **argv;
-#else /* TCL_MAJOR_VERSION < 8 */
- char **argv;
-#endif
- VALUE interp;
- int *done;
- int safe_level;
- VALUE result;
- VALUE thread;
-};
-
-struct eval_queue {
- Tcl_Event ev;
- char *str;
- int len;
- VALUE interp;
- int *done;
- int safe_level;
- VALUE result;
- VALUE thread;
-};
-
-void
-invoke_queue_mark(struct invoke_queue *q)
-{
- rb_gc_mark(q->interp);
- rb_gc_mark(q->result);
- rb_gc_mark(q->thread);
-}
-
-void
-eval_queue_mark(struct eval_queue *q)
-{
- rb_gc_mark(q->interp);
- rb_gc_mark(q->result);
- rb_gc_mark(q->thread);
-}
-
-
-static VALUE eventloop_thread;
-static VALUE watchdog_thread;
-Tcl_Interp *current_interp;
-
-/*
- * 'event_loop_max' is a maximum events which the eventloop processes in one
- * term of thread scheduling. 'no_event_tick' is the count-up value when
- * there are no event for processing.
- * 'timer_tick' is a limit of one term of thread scheduling.
- * If 'timer_tick' == 0, then not use the timer for thread scheduling.
- */
-#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
-#define DEFAULT_NO_EVENT_TICK 10/*counts*/
-#define DEFAULT_NO_EVENT_WAIT 20/*milliseconds ( 1 -- 999 ) */
-#define WATCHDOG_INTERVAL 10/*milliseconds ( 1 -- 999 ) */
-#define DEFAULT_TIMER_TICK 0/*milliseconds ( 0 -- 999 ) */
-#define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */
-
-static int event_loop_max = DEFAULT_EVENT_LOOP_MAX;
-static int no_event_tick = DEFAULT_NO_EVENT_TICK;
-static int no_event_wait = DEFAULT_NO_EVENT_WAIT;
-static int timer_tick = DEFAULT_TIMER_TICK;
-static int req_timer_tick = DEFAULT_TIMER_TICK;
-static int run_timer_flag = 0;
-
-static int event_loop_wait_event = 0;
-static int event_loop_abort_on_exc = 1;
-static int loop_counter = 0;
-
-static int check_rootwidget_flag = 0;
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_ruby_eval _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
-static int ip_ruby_cmd _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
-#else /* TCL_MAJOR_VERSION < 8 */
-static int ip_ruby_eval _((ClientData, Tcl_Interp *, int, char **));
-static int ip_ruby_cmd _((ClientData, Tcl_Interp *, int, char **));
-#endif
-
-static int ip_null_namespace _((Tcl_Interp *));
-#if TCL_MAJOR_VERSION >= 8
-#ifndef Tcl_GetCurrentNamespace
-EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _((Tcl_Interp *));
-#endif
-#endif
-
-
-/*---- class TclTkIp ----*/
-struct tcltkip {
- Tcl_Interp *ip; /* the interpreter */
- int has_orig_exit; /* has original 'exit' command ? */
- Tcl_CmdInfo orig_exit_info; /* command info of original 'exit' command */
- int ref_count; /* reference count of rbtk_preserve_ip call */
- int allow_ruby_exit; /* allow exiting ruby by 'exit' function */
- int return_value; /* return value */
-};
-
-static struct tcltkip *
-get_ip(self)
- VALUE self;
-{
- struct tcltkip *ptr;
-
- Data_Get_Struct(self, struct tcltkip, ptr);
- if (ptr == 0) {
- rb_raise(rb_eTypeError, "uninitialized TclTkIp");
- }
- return ptr;
-}
-
-/* increment/decrement reference count of tcltkip */
-static int
-rbtk_preserve_ip(ptr)
- struct tcltkip *ptr;
-{
- ptr->ref_count++;
- Tcl_Preserve((ClientData)ptr->ip);
- return(ptr->ref_count);
-}
-
-static int
-rbtk_release_ip(ptr)
- struct tcltkip *ptr;
-{
- ptr->ref_count--;
- if (ptr->ref_count < 0) {
- ptr->ref_count = 0;
- } else {
- Tcl_Release((ClientData)ptr->ip);
- }
- return(ptr->ref_count);
-}
-
-/* call original 'exit' command */
-static void
-call_original_exit(ptr, state)
- struct tcltkip *ptr;
- int state;
-{
- int thr_crit_bup;
- Tcl_CmdInfo *info;
-#if TCL_MAJOR_VERSION >= 8
- Tcl_Obj *state_obj;
-#endif
-
- if (!(ptr->has_orig_exit)) return;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- Tcl_ResetResult(ptr->ip);
-
- info = &(ptr->orig_exit_info);
-
- /* memory allocation for arguments of this command */
-#if TCL_MAJOR_VERSION >= 8
- state_obj = Tcl_NewIntObj(state);
- Tcl_IncrRefCount(state_obj);
-
- if (info->isNativeObjectProc) {
- Tcl_Obj **argv;
- argv = (Tcl_Obj **)ALLOC_N(Tcl_Obj *, 3);
- argv[0] = Tcl_NewStringObj("exit", 4);
- argv[1] = state_obj;
- argv[2] = (Tcl_Obj *)NULL;
-
- ptr->return_value
- = (*(info->objProc))(info->objClientData, ptr->ip, 2, argv);
-
- free(argv);
-
- } else {
- /* string interface */
- char **argv;
- argv = (char **)ALLOC_N(char *, 3);
- argv[0] = "exit";
- argv[1] = Tcl_GetString(state_obj);
- argv[2] = (char *)NULL;
-
- ptr->return_value = (*(info->proc))(info->clientData, ptr->ip,
- 2, (CONST84 char **)argv);
-
- free(argv);
- }
-
- Tcl_DecrRefCount(state_obj);
-
-#else /* TCL_MAJOR_VERSION < 8 */
- {
- /* string interface */
- char **argv;
- argv = (char **)ALLOC_N(char *, 3);
- argv[0] = "exit";
- argv[1] = RSTRING(rb_fix2str(INT2NUM(state), 10))->ptr;
- argv[2] = (char *)NULL;
-
- ptr->return_value = (*(info->proc))(info->clientData, ptr->ip,
- 2, argv);
-
- free(argv);
- }
-#endif
-
- rb_thread_critical = thr_crit_bup;
-}
-
-/* Tk_ThreadTimer */
-static Tcl_TimerToken timer_token = (Tcl_TimerToken)NULL;
-
-/* timer callback */
-static void _timer_for_tcl _((ClientData));
-static void
-_timer_for_tcl(clientData)
- ClientData clientData;
-{
- int thr_crit_bup;
-
- /* struct invoke_queue *q, *tmp; */
- /* VALUE thread; */
-
- DUMP1("called timer_for_tcl");
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- Tk_DeleteTimerHandler(timer_token);
-
- run_timer_flag = 1;
-
- if (timer_tick > 0) {
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
- } else {
- timer_token = (Tcl_TimerToken)NULL;
- }
-
- rb_thread_critical = thr_crit_bup;
-
- /* rb_thread_schedule(); */
- /* tick_counter += event_loop_max; */
-}
-
-static VALUE
-set_eventloop_tick(self, tick)
- VALUE self;
- VALUE tick;
-{
- int ttick = NUM2INT(tick);
- int thr_crit_bup;
-
- rb_secure(4);
-
- if (ttick < 0) {
- rb_raise(rb_eArgError,
- "timer-tick parameter must be 0 or positive number");
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* delete old timer callback */
- Tk_DeleteTimerHandler(timer_token);
-
- timer_tick = req_timer_tick = ttick;
- if (timer_tick > 0) {
- /* start timer callback */
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
- } else {
- timer_token = (Tcl_TimerToken)NULL;
- }
-
- rb_thread_critical = thr_crit_bup;
-
- return tick;
-}
-
-static VALUE
-get_eventloop_tick(self)
- VALUE self;
-{
- return INT2NUM(timer_tick);
-}
-
-static VALUE
-ip_set_eventloop_tick(self, tick)
- VALUE self;
- VALUE tick;
-{
- struct tcltkip *ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return get_eventloop_tick(self);
- }
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return get_eventloop_tick(self);
- }
- return set_eventloop_tick(self, tick);
-}
-
-static VALUE
-ip_get_eventloop_tick(self)
- VALUE self;
-{
- return get_eventloop_tick(self);
-}
-
-static VALUE
-set_no_event_wait(self, wait)
- VALUE self;
- VALUE wait;
-{
- int t_wait = NUM2INT(wait);
-
- rb_secure(4);
-
- if (t_wait <= 0) {
- rb_raise(rb_eArgError,
- "no_event_wait parameter must be positive number");
- }
-
- no_event_wait = t_wait;
-
- return wait;
-}
-
-static VALUE
-get_no_event_wait(self)
- VALUE self;
-{
- return INT2NUM(no_event_wait);
-}
-
-static VALUE
-ip_set_no_event_wait(self, wait)
- VALUE self;
- VALUE wait;
-{
- struct tcltkip *ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return get_no_event_wait(self);
- }
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return get_no_event_wait(self);
- }
- return set_no_event_wait(self, wait);
-}
-
-static VALUE
-ip_get_no_event_wait(self)
- VALUE self;
-{
- return get_no_event_wait(self);
-}
-
-static VALUE
-set_eventloop_weight(self, loop_max, no_event)
- VALUE self;
- VALUE loop_max;
- VALUE no_event;
-{
- int lpmax = NUM2INT(loop_max);
- int no_ev = NUM2INT(no_event);
-
- rb_secure(4);
-
- if (lpmax <= 0 || no_ev <= 0) {
- rb_raise(rb_eArgError, "weight parameters must be positive numbers");
- }
-
- event_loop_max = lpmax;
- no_event_tick = no_ev;
-
- return rb_ary_new3(2, loop_max, no_event);
-}
-
-static VALUE
-get_eventloop_weight(self)
- VALUE self;
-{
- return rb_ary_new3(2, INT2NUM(event_loop_max), INT2NUM(no_event_tick));
-}
-
-static VALUE
-ip_set_eventloop_weight(self, loop_max, no_event)
- VALUE self;
- VALUE loop_max;
- VALUE no_event;
-{
- struct tcltkip *ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return get_eventloop_weight(self);
- }
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return get_eventloop_weight(self);
- }
- return set_eventloop_weight(self, loop_max, no_event);
-}
-
-static VALUE
-ip_get_eventloop_weight(self)
- VALUE self;
-{
- return get_eventloop_weight(self);
-}
-
-static VALUE
-set_max_block_time(self, time)
- VALUE self;
- VALUE time;
-{
- struct Tcl_Time tcl_time;
- VALUE divmod;
-
- switch(TYPE(time)) {
- case T_FIXNUM:
- case T_BIGNUM:
- /* time is micro-second value */
- divmod = rb_funcall(time, rb_intern("divmod"), 1, LONG2NUM(1000000));
- tcl_time.sec = NUM2LONG(RARRAY(divmod)->ptr[0]);
- tcl_time.usec = NUM2LONG(RARRAY(divmod)->ptr[1]);
- break;
-
- case T_FLOAT:
- /* time is second value */
- divmod = rb_funcall(time, rb_intern("divmod"), 1, INT2FIX(1));
- tcl_time.sec = NUM2LONG(RARRAY(divmod)->ptr[0]);
- tcl_time.usec = (long)(NUM2DBL(RARRAY(divmod)->ptr[1]) * 1000000);
-
- default:
- rb_raise(rb_eArgError, "invalid value for time: '%s'",
- RSTRING(rb_funcall(time, ID_inspect, 0, 0))->ptr);
- }
-
- Tcl_SetMaxBlockTime(&tcl_time);
-
- return Qnil;
-}
-
-static VALUE
-lib_evloop_abort_on_exc(self)
- VALUE self;
-{
- if (event_loop_abort_on_exc > 0) {
- return Qtrue;
- } else if (event_loop_abort_on_exc == 0) {
- return Qfalse;
- } else {
- return Qnil;
- }
-}
-
-static VALUE
-ip_evloop_abort_on_exc(self)
- VALUE self;
-{
- return lib_evloop_abort_on_exc(self);
-}
-
-static VALUE
-lib_evloop_abort_on_exc_set(self, val)
- VALUE self, val;
-{
- rb_secure(4);
- if (RTEST(val)) {
- event_loop_abort_on_exc = 1;
- } else if (NIL_P(val)) {
- event_loop_abort_on_exc = -1;
- } else {
- event_loop_abort_on_exc = 0;
- }
- return lib_evloop_abort_on_exc(self);
-}
-
-static VALUE
-ip_evloop_abort_on_exc_set(self, val)
- VALUE self, val;
-{
- struct tcltkip *ptr = get_ip(self);
-
- rb_secure(4);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return lib_evloop_abort_on_exc(self);
- }
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return lib_evloop_abort_on_exc(self);
- }
- return lib_evloop_abort_on_exc_set(self, val);
-}
-
-static VALUE
-lib_num_of_mainwindows(self)
- VALUE self;
-{
- return INT2FIX(Tk_GetNumMainWindows());
-}
-
-static int
-lib_eventloop_core(check_root, update_flag, check_var)
- int check_root;
- int update_flag;
- int *check_var;
-{
- volatile VALUE current = eventloop_thread;
- int found_event = 1;
- int event_flag;
- struct timeval t;
- int thr_crit_bup;
-
-
- if (update_flag) DUMP1("update loop start!!");
-
- t.tv_sec = (time_t)0;
- t.tv_usec = (time_t)(no_event_wait*1000.0);
-
- Tk_DeleteTimerHandler(timer_token);
- run_timer_flag = 0;
- if (timer_tick > 0) {
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
- rb_thread_critical = thr_crit_bup;
- } else {
- timer_token = (Tcl_TimerToken)NULL;
- }
-
- for(;;) {
- if (rb_thread_alone()) {
- DUMP1("no other thread");
- event_loop_wait_event = 0;
-
- if (update_flag) {
- event_flag = update_flag | TCL_DONT_WAIT; /* for safety */
- } else {
- event_flag = TCL_ALL_EVENTS;
- }
-
- if (timer_tick == 0 && update_flag == 0) {
- timer_tick = NO_THREAD_INTERRUPT_TIME;
- timer_token = Tk_CreateTimerHandler(timer_tick,
- _timer_for_tcl,
- (ClientData)0);
- }
-
- if (check_var != (int *)NULL) {
- if (*check_var || !found_event) {
- return found_event;
- }
- }
-
- found_event = Tcl_DoOneEvent(event_flag);
-
- if (update_flag != 0) {
- if (found_event) {
- DUMP1("next update loop");
- continue;
- } else {
- DUMP1("update complete");
- return 0;
- }
- }
-
- DUMP1("check Root Widget");
- if (check_root && Tk_GetNumMainWindows() == 0) {
- run_timer_flag = 0;
- if (!rb_prohibit_interrupt) {
- if (rb_trap_pending) rb_trap_exec();
- }
- return 1;
- }
-
- if (loop_counter++ > 30000) {
- /* fprintf(stderr, "loop_counter > 30000\n"); */
- loop_counter = 0;
- }
-
- } else {
- int tick_counter;
-
- DUMP1("there are other threads");
- event_loop_wait_event = 1;
-
- found_event = 1;
-
- if (update_flag) {
- event_flag = update_flag | TCL_DONT_WAIT; /* for safety */
- } else {
- event_flag = TCL_ALL_EVENTS | TCL_DONT_WAIT;
- }
-
- timer_tick = req_timer_tick;
- tick_counter = 0;
- while(tick_counter < event_loop_max) {
- if (check_var != (int *)NULL) {
- if (*check_var || !found_event) {
- return found_event;
- }
- }
-
- if (Tcl_DoOneEvent(event_flag)) {
- tick_counter++;
- } else {
- if (update_flag != 0) {
- DUMP1("update complete");
- return 0;
- }
- tick_counter += no_event_tick;
- rb_thread_wait_for(t);
- }
-
- if (watchdog_thread != 0 && eventloop_thread != current) {
- return 1;
- }
-
- DUMP1("check Root Widget");
- if (check_root && Tk_GetNumMainWindows() == 0) {
- run_timer_flag = 0;
- if (!rb_prohibit_interrupt) {
- if (rb_trap_pending) rb_trap_exec();
- }
- return 1;
- }
-
- DUMP1("trap check");
- if (!rb_prohibit_interrupt) {
- if (rb_trap_pending) rb_trap_exec();
- }
-
- if (loop_counter++ > 30000) {
- /* fprintf(stderr, "loop_counter > 30000\n"); */
- loop_counter = 0;
- }
-
- if (run_timer_flag) {
- /*
- DUMP1("timer interrupt");
- run_timer_flag = 0;
- */
- break; /* switch to other thread */
- }
- }
- }
-
- DUMP1("trap check & thread scheduling");
- if (update_flag == 0) CHECK_INTS;
-
- }
- return 1;
-}
-
-VALUE
-lib_eventloop_main(check_rootwidget)
- VALUE check_rootwidget;
-{
- check_rootwidget_flag = RTEST(check_rootwidget);
-
- if (lib_eventloop_core(check_rootwidget_flag, 0, (int *)NULL)) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-VALUE
-lib_eventloop_ensure(parent_evloop)
- VALUE parent_evloop;
-{
- Tk_DeleteTimerHandler(timer_token);
- timer_token = (Tcl_TimerToken)NULL;
- DUMP2("eventloop-ensure: current-thread : %lx\n", rb_thread_current());
- DUMP2("eventloop-ensure: eventloop-thread : %lx\n", eventloop_thread);
- if (eventloop_thread == rb_thread_current()) {
- DUMP2("eventloop-thread -> %lx\n", parent_evloop);
- eventloop_thread = parent_evloop;
- }
- return Qnil;
-}
-
-static VALUE
-lib_eventloop_launcher(check_rootwidget)
- VALUE check_rootwidget;
-{
- VALUE parent_evloop = eventloop_thread;
-
- eventloop_thread = rb_thread_current();
-
- if (ruby_debug) {
- fprintf(stderr, "tcltklib: eventloop-thread : %lx -> %lx\n",
- parent_evloop, eventloop_thread);
- }
-
- return rb_ensure(lib_eventloop_main, check_rootwidget,
- lib_eventloop_ensure, parent_evloop);
-}
-
-/* execute Tk_MainLoop */
-static VALUE
-lib_mainloop(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE check_rootwidget;
-
- if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
- check_rootwidget = Qtrue;
- } else if (RTEST(check_rootwidget)) {
- check_rootwidget = Qtrue;
- } else {
- check_rootwidget = Qfalse;
- }
-
- return lib_eventloop_launcher(check_rootwidget);
-}
-
-static VALUE
-ip_mainloop(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return Qnil;
- }
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return Qnil;
- }
- return lib_mainloop(argc, argv, self);
-}
-
-VALUE
-lib_watchdog_core(check_rootwidget)
- VALUE check_rootwidget;
-{
- VALUE evloop;
- int prev_val = -1;
- int chance = 0;
- int check = RTEST(check_rootwidget);
- struct timeval t0, t1;
-
- t0.tv_sec = (time_t)0;
- t0.tv_usec = (time_t)((NO_THREAD_INTERRUPT_TIME)*1000.0);
- t1.tv_sec = (time_t)0;
- t1.tv_usec = (time_t)((WATCHDOG_INTERVAL)*1000.0);
-
- /* check other watchdog thread */
- if (watchdog_thread != 0) {
- if (RTEST(rb_funcall(watchdog_thread, ID_stop_p, 0))) {
- rb_funcall(watchdog_thread, ID_kill, 0);
- } else {
- return Qnil;
- }
- }
- watchdog_thread = rb_thread_current();
-
- /* watchdog start */
- do {
- if (eventloop_thread == 0
- || (loop_counter == prev_val
- && RTEST(rb_funcall(eventloop_thread, ID_stop_p, 0))
- && ++chance >= 3 )
- ) {
- /* start new eventloop thread */
- DUMP2("eventloop thread %lx is sleeping or dead",
- eventloop_thread);
- evloop = rb_thread_create(lib_eventloop_launcher,
- (void*)&check_rootwidget);
- DUMP2("create new eventloop thread %lx", evloop);
- loop_counter = -1;
- chance = 0;
- rb_thread_run(evloop);
- } else {
- loop_counter = prev_val;
- chance = 0;
- if (event_loop_wait_event) {
- rb_thread_wait_for(t0);
- } else {
- rb_thread_wait_for(t1);
- }
- /* rb_thread_schedule(); */
- }
- } while(!check || Tk_GetNumMainWindows() != 0);
-
- return Qnil;
-}
-
-VALUE
-lib_watchdog_ensure(arg)
- VALUE arg;
-{
- eventloop_thread = 0; /* stop eventloops */
- return Qnil;
-}
-
-static VALUE
-lib_mainloop_watchdog(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE check_rootwidget;
-
- if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
- check_rootwidget = Qtrue;
- } else if (RTEST(check_rootwidget)) {
- check_rootwidget = Qtrue;
- } else {
- check_rootwidget = Qfalse;
- }
-
- return rb_ensure(lib_watchdog_core, check_rootwidget,
- lib_watchdog_ensure, Qnil);
-}
-
-static VALUE
-ip_mainloop_watchdog(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return Qnil;
- }
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return Qnil;
- }
- return lib_mainloop_watchdog(argc, argv, self);
-}
-
-static VALUE
-lib_do_one_event_core(argc, argv, self, is_ip)
- int argc;
- VALUE *argv;
- VALUE self;
- int is_ip;
-{
- volatile VALUE vflags;
- int flags;
- int found_event;
-
- if (rb_scan_args(argc, argv, "01", &vflags) == 0) {
- flags = TCL_ALL_EVENTS | TCL_DONT_WAIT;
- } else {
- Check_Type(vflags, T_FIXNUM);
- flags = FIX2INT(vflags);
- }
-
- if (rb_safe_level() >= 4 || (rb_safe_level() >=1 && OBJ_TAINTED(vflags))) {
- flags |= TCL_DONT_WAIT;
- }
-
- if (is_ip) {
- /* check IP */
- struct tcltkip *ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return Qfalse;
- }
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- flags |= TCL_DONT_WAIT;
- }
- }
-
- /* found_event = Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT); */
- found_event = Tcl_DoOneEvent(flags);
-
- if (found_event) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-static VALUE
-lib_do_one_event(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- return lib_do_one_event_core(argc, argv, self, 0);
-}
-
-static VALUE
-ip_do_one_event(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- return lib_do_one_event_core(argc, argv, self, 0);
-}
-
-
-static void
-ip_set_exc_message(interp, exc)
- Tcl_Interp *interp;
- VALUE exc;
-{
- char *buf;
- Tcl_DString dstr;
- volatile VALUE msg;
- int thr_crit_bup;
-
-#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
- volatile VALUE enc;
- Tcl_Encoding encoding;
-#endif
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- msg = rb_funcall(exc, ID_message, 0, 0);
-
-#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
- enc = Qnil;
- if (RTEST(rb_ivar_defined(exc, ID_at_enc))) {
- enc = rb_ivar_get(exc, ID_at_enc);
- }
- if (NIL_P(enc) && RTEST(rb_ivar_defined(msg, ID_at_enc))) {
- enc = rb_ivar_get(msg, ID_at_enc);
- }
- if (NIL_P(enc)) {
- encoding = (Tcl_Encoding)NULL;
- } else if (TYPE(enc) == T_STRING) {
- encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr);
- } else {
- enc = rb_funcall(enc, ID_to_s, 0, 0);
- encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr);
- }
-
- /* to avoid a garbled error message dialog */
- buf = ALLOC_N(char, (RSTRING(msg)->len)+1);
- strncpy(buf, RSTRING(msg)->ptr, RSTRING(msg)->len);
- buf[RSTRING(msg)->len] = 0;
-
- Tcl_DStringInit(&dstr);
- Tcl_DStringFree(&dstr);
- Tcl_ExternalToUtfDString(encoding, buf, RSTRING(msg)->len, &dstr);
-
- Tcl_AppendResult(interp, Tcl_DStringValue(&dstr), (char*)NULL);
- DUMP2("error message:%s", Tcl_DStringValue(&dstr));
- free(buf);
-
-#else /* TCL_VERSION <= 8.0 */
- Tcl_AppendResult(interp, RSTRING(msg)->ptr, (char*)NULL);
-#endif
-
- rb_thread_critical = thr_crit_bup;
-}
-
-static VALUE
-TkStringValue(obj)
- VALUE obj;
-{
- switch(TYPE(obj)) {
- case T_STRING:
- return obj;
-
- case T_NIL:
- return rb_str_new2("");
-
- case T_TRUE:
- return rb_str_new2("1");
-
- case T_FALSE:
- return rb_str_new2("0");
-
- case T_ARRAY:
- return rb_funcall(obj, ID_join, 1, rb_str_new2(" "));
-
- default:
- if (rb_respond_to(obj, ID_to_s)) {
- return rb_funcall(obj, ID_to_s, 0, 0);
- }
- }
-
- return rb_funcall(obj, ID_inspect, 0, 0);
-}
-
-/* Tcl command `ruby'|`ruby_eval' */
-static VALUE
-ip_ruby_eval_rescue(failed, einfo)
- VALUE failed;
- VALUE einfo;
-{
- DUMP1("call ip_ruby_eval_rescue");
- RARRAY(failed)->ptr[0] = einfo;
- return Qnil;
-}
-
-struct eval_body_arg {
- char *string;
- VALUE failed;
-};
-
-static VALUE
-ip_ruby_eval_body(arg)
- struct eval_body_arg *arg;
-{
- volatile VALUE ret;
- int status = 0;
- int thr_crit_bup;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- DUMP1("call ip_ruby_eval_body");
- rb_trap_immediate = 0;
-
-#if 0
- ret = rb_rescue2(rb_eval_string, (VALUE)arg->string,
- ip_ruby_eval_rescue, arg->failed,
- rb_eStandardError, rb_eScriptError, rb_eSystemExit,
- (VALUE)0);
-#else
-
- rb_thread_critical = Qfalse;
- ret = rb_eval_string_protect(arg->string, &status);
- rb_thread_critical = Qtrue;
- if (status) {
- char *errtype, *buf;
- int errtype_len, len;
- VALUE old_gc;
-
- old_gc = rb_gc_disable();
-
- switch(status) {
- case TAG_RETURN:
- errtype = "LocalJumpError: ";
- errtype_len = strlen(errtype);
- len = errtype_len + RSTRING(rb_obj_as_string(ruby_errinfo))->len;
- buf = ALLOC_N(char, len + 1);
- strncpy(buf, errtype, errtype_len);
- strncpy(buf + errtype_len,
- RSTRING(rb_obj_as_string(ruby_errinfo))->ptr,
- RSTRING(rb_obj_as_string(ruby_errinfo))->len);
- *(buf + len) = 0;
-
- RARRAY(arg->failed)->ptr[0] = rb_exc_new2(eTkCallbackReturn, buf);
- free(buf);
- break;
-
- case TAG_BREAK:
- errtype = "LocalJumpError: ";
- errtype_len = strlen(errtype);
- len = errtype_len + RSTRING(rb_obj_as_string(ruby_errinfo))->len;
- buf = ALLOC_N(char, len + 1);
- strncpy(buf, errtype, errtype_len);
- strncpy(buf + errtype_len,
- RSTRING(rb_obj_as_string(ruby_errinfo))->ptr,
- RSTRING(rb_obj_as_string(ruby_errinfo))->len);
- *(buf + len) = 0;
-
- RARRAY(arg->failed)->ptr[0] = rb_exc_new2(eTkCallbackBreak, buf);
- free(buf);
- break;
-
- case TAG_NEXT:
- errtype = "LocalJumpError: ";
- errtype_len = strlen(errtype);
- len = errtype_len + RSTRING(rb_obj_as_string(ruby_errinfo))->len;
- buf = ALLOC_N(char, len + 1);
- strncpy(buf, errtype, errtype_len);
- strncpy(buf + errtype_len,
- RSTRING(rb_obj_as_string(ruby_errinfo))->ptr,
- RSTRING(rb_obj_as_string(ruby_errinfo))->len);
- *(buf + len) = 0;
-
- RARRAY(arg->failed)->ptr[0] = rb_exc_new2(eTkCallbackContinue,buf);
- free(buf);
- break;
-
- case TAG_RETRY:
- case TAG_REDO:
- if (NIL_P(ruby_errinfo)) {
- rb_jump_tag(status);
- } else {
- RARRAY(arg->failed)->ptr[0] = ruby_errinfo;
- }
- break;
-
- case TAG_RAISE:
- case TAG_FATAL:
- if (NIL_P(ruby_errinfo)) {
- RARRAY(arg->failed)->ptr[0]
- = rb_exc_new2(rb_eException, "unknown exception");
- } else {
- RARRAY(arg->failed)->ptr[0] = ruby_errinfo;
- }
- break;
-
- case TAG_THROW:
- if (NIL_P(ruby_errinfo)) {
- rb_jump_tag(TAG_THROW);
- } else {
- RARRAY(arg->failed)->ptr[0] = ruby_errinfo;
- }
- break;
-
- default:
- buf = ALLOC_N(char, 256);
- sprintf(buf, "unknown loncaljmp status %d", status);
- RARRAY(arg->failed)->ptr[0] = rb_exc_new2(rb_eException, buf);
- free(buf);
- break;
- }
-
- if (old_gc == Qfalse) rb_gc_enable();
-
- ret = Qnil;
- }
-#endif
-
- rb_thread_critical = thr_crit_bup;
-
- return ret;
-}
-
-static VALUE
-ip_ruby_eval_ensure(trapflag)
- VALUE trapflag;
-{
- rb_trap_immediate = NUM2INT(trapflag);
- return Qnil;
-}
-
-
-static int
-#if TCL_MAJOR_VERSION >= 8
-ip_ruby_eval(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- Tcl_Obj *CONST argv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-ip_ruby_eval(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
-#endif
-{
- volatile VALUE res;
- volatile VALUE exception = rb_ary_new2(1);
- int old_trapflag;
- struct eval_body_arg *arg;
- int thr_crit_bup;
-
- /* ruby command has 1 arg. */
- if (argc != 2) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)",
- argc - 1);
- }
-
- /* allocate */
- arg = ALLOC(struct eval_body_arg);
-
- /* get C string from Tcl object */
-#if TCL_MAJOR_VERSION >= 8
- {
- char *str;
- int len;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- str = Tcl_GetStringFromObj(argv[1], &len);
- arg->string = ALLOC_N(char, len + 1);
- strncpy(arg->string, str, len);
- arg->string[len] = 0;
-
- rb_thread_critical = thr_crit_bup;
-
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- arg->string = argv[1];
-#endif
- /* arg.failed = 0; */
- RARRAY(exception)->ptr[0] = Qnil;
- RARRAY(exception)->len = 1;
- arg->failed = exception;
-
- /* evaluate the argument string by ruby */
- DUMP2("rb_eval_string(%s)", arg->string);
- old_trapflag = rb_trap_immediate;
-#ifdef HAVE_NATIVETHREAD
- if (!is_ruby_native_thread()) {
- rb_bug("cross-thread violation on ip_ruby_eval()");
- }
-#endif
- res = rb_ensure(ip_ruby_eval_body, (VALUE)arg,
- ip_ruby_eval_ensure, INT2FIX(old_trapflag));
-
-#if TCL_MAJOR_VERSION >= 8
- free(arg->string);
-#endif
-
- free(arg);
-
- /* status check */
- /* if (arg.failed) { */
- if (!NIL_P(RARRAY(exception)->ptr[0])) {
- VALUE eclass;
- volatile VALUE bt_ary;
- volatile VALUE backtrace;
-
- DUMP1("(rb_eval_string result) failed");
-
- Tcl_ResetResult(interp);
-
- res = RARRAY(exception)->ptr[0];
- eclass = rb_obj_class(res);
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- DUMP1("set backtrace");
- if (!NIL_P(bt_ary = rb_funcall(res, ID_backtrace, 0, 0))) {
- backtrace = rb_ary_join(bt_ary, rb_str_new2("\n"));
- StringValue(backtrace);
- Tcl_AddErrorInfo(interp, RSTRING(backtrace)->ptr);
- }
-
- rb_thread_critical = thr_crit_bup;
-
- if (eclass == eTkCallbackReturn) {
- ip_set_exc_message(interp, res);
- return TCL_RETURN;
-
- } else if (eclass == eTkCallbackBreak) {
- ip_set_exc_message(interp, res);
- return TCL_BREAK;
-
- } else if (eclass == eTkCallbackContinue) {
- ip_set_exc_message(interp, res);
- return TCL_CONTINUE;
-
- } else if (eclass == rb_eSystemExit) {
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* Tcl_Eval(interp, "destroy ."); */
- if (Tk_GetNumMainWindows() > 0) {
- Tk_Window main_win = Tk_MainWindow(interp);
- if (main_win != (Tk_Window)NULL) {
- Tk_DestroyWindow(main_win);
- }
- }
-
- /* StringValue(res); */
- res = rb_funcall(res, ID_message, 0, 0);
-
- Tcl_AppendResult(interp, RSTRING(res)->ptr, (char*)NULL);
-
- rb_thread_critical = thr_crit_bup;
-
- rb_raise(rb_eSystemExit, RSTRING(res)->ptr);
-
- } else if (rb_obj_is_kind_of(res, eLocalJumpError)) {
- VALUE reason = rb_ivar_get(res, ID_at_reason);
-
- if (TYPE(reason) != T_SYMBOL) {
- ip_set_exc_message(interp, res);
- return TCL_ERROR;
- }
-
- if (SYM2ID(reason) == ID_return) {
- ip_set_exc_message(interp, res);
- return TCL_RETURN;
-
- } else if (SYM2ID(reason) == ID_break) {
- ip_set_exc_message(interp, res);
- return TCL_BREAK;
-
- } else if (SYM2ID(reason) == ID_next) {
- ip_set_exc_message(interp, res);
- return TCL_CONTINUE;
-
- } else {
- ip_set_exc_message(interp, res);
- return TCL_ERROR;
- }
- } else {
- ip_set_exc_message(interp, res);
- return TCL_ERROR;
- }
- }
-
- /* result must be string or nil */
- if (NIL_P(res)) {
- DUMP1("(rb_eval_string result) nil");
- Tcl_ResetResult(interp);
- return TCL_OK;
- }
-
- /* copy result to the tcl interpreter */
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- res = TkStringValue(res);
- DUMP2("(rb_eval_string result) %s", RSTRING(res)->ptr);
- DUMP1("Tcl_AppendResult");
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, RSTRING(res)->ptr, (char *)NULL);
-
- rb_thread_critical = thr_crit_bup;
-
- return TCL_OK;
-}
-
-
-/* Tcl command `ruby_cmd' */
-struct cmd_body_arg {
- VALUE receiver;
- ID method;
- VALUE args;
- VALUE failed;
-};
-
-static VALUE
-ip_ruby_cmd_core(arg)
- struct cmd_body_arg *arg;
-{
- volatile VALUE ret;
- int thr_crit_bup;
-
- DUMP1("call ip_ruby_cmd_core");
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qfalse;
- ret = rb_apply(arg->receiver, arg->method, arg->args);
- rb_thread_critical = thr_crit_bup;
- DUMP1("finish ip_ruby_cmd_core");
-
- return ret;
-}
-
-static VALUE
-ip_ruby_cmd_rescue(failed, einfo)
- VALUE failed;
- VALUE einfo;
-{
- DUMP1("call ip_ruby_cmd_rescue");
- RARRAY(failed)->ptr[0] = einfo;
- return Qnil;
-}
-
-static VALUE
-ip_ruby_cmd_body(arg)
- struct cmd_body_arg *arg;
-{
- volatile VALUE ret;
- int status = 0;
- int thr_crit_bup;
- VALUE old_gc;
-
- volatile VALUE receiver = arg->receiver;
- volatile VALUE args = arg->args;
- volatile VALUE failed = arg->failed;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- DUMP1("call ip_ruby_cmd_body");
- rb_trap_immediate = 0;
-
-#if 0
- ret = rb_rescue2(ip_ruby_cmd_core, (VALUE)arg,
- ip_ruby_cmd_rescue, arg->failed,
- rb_eStandardError, rb_eScriptError, rb_eSystemExit,
- (VALUE)0);
-#else
- ret = rb_protect(ip_ruby_cmd_core, (VALUE)arg, &status);
-
- if (status) {
- char *errtype, *buf;
- int errtype_len, len;
-
- old_gc = rb_gc_disable();
-
- switch(status) {
- case TAG_RETURN:
- errtype = "LocalJumpError: ";
- errtype_len = strlen(errtype);
- len = errtype_len + RSTRING(rb_obj_as_string(ruby_errinfo))->len;
- buf = ALLOC_N(char, len + 1);
- strncpy(buf, errtype, errtype_len);
- strncpy(buf + errtype_len,
- RSTRING(rb_obj_as_string(ruby_errinfo))->ptr,
- RSTRING(rb_obj_as_string(ruby_errinfo))->len);
- *(buf + len) = 0;
-
- RARRAY(arg->failed)->ptr[0] = rb_exc_new2(eTkCallbackReturn, buf);
- free(buf);
- break;
-
- case TAG_BREAK:
- errtype = "LocalJumpError: ";
- errtype_len = strlen(errtype);
- len = errtype_len + RSTRING(rb_obj_as_string(ruby_errinfo))->len;
- buf = ALLOC_N(char, len + 1);
- strncpy(buf, errtype, errtype_len);
- strncpy(buf + errtype_len,
- RSTRING(rb_obj_as_string(ruby_errinfo))->ptr,
- RSTRING(rb_obj_as_string(ruby_errinfo))->len);
- *(buf + len) = 0;
-
- RARRAY(arg->failed)->ptr[0] = rb_exc_new2(eTkCallbackBreak, buf);
- free(buf);
- break;
-
- case TAG_NEXT:
- errtype = "LocalJumpError: ";
- errtype_len = strlen(errtype);
- len = errtype_len + RSTRING(rb_obj_as_string(ruby_errinfo))->len;
- buf = ALLOC_N(char, len + 1);
- strncpy(buf, errtype, errtype_len);
- strncpy(buf + errtype_len,
- RSTRING(rb_obj_as_string(ruby_errinfo))->ptr,
- RSTRING(rb_obj_as_string(ruby_errinfo))->len);
- *(buf + len) = 0;
-
- RARRAY(arg->failed)->ptr[0] = rb_exc_new2(eTkCallbackContinue,buf);
- free(buf);
- break;
-
- case TAG_RETRY:
- case TAG_REDO:
- if (NIL_P(ruby_errinfo)) {
- rb_jump_tag(status);
- } else {
- RARRAY(arg->failed)->ptr[0] = ruby_errinfo;
- }
- break;
-
- case TAG_RAISE:
- case TAG_FATAL:
- if (NIL_P(ruby_errinfo)) {
- RARRAY(arg->failed)->ptr[0]
- = rb_exc_new2(rb_eException, "unknown exception");
- } else {
- RARRAY(arg->failed)->ptr[0] = ruby_errinfo;
- }
- break;
-
- case TAG_THROW:
- if (NIL_P(ruby_errinfo)) {
- rb_jump_tag(TAG_THROW);
- } else {
- RARRAY(arg->failed)->ptr[0] = ruby_errinfo;
- }
- break;
-
- default:
- buf = ALLOC_N(char, 256);
- rb_warn(buf, "unknown loncaljmp status %d", status);
- RARRAY(arg->failed)->ptr[0] = rb_exc_new2(rb_eException, buf);
- free(buf);
- break;
- }
-
- if (old_gc == Qfalse) rb_gc_enable();
-
- ret = Qnil;
- }
-#endif
-
- rb_thread_critical = thr_crit_bup;
- DUMP1("finish ip_ruby_cmd_body");
-
- return ret;
-}
-
-static VALUE
-ip_ruby_cmd_ensure(trapflag)
- VALUE trapflag;
-{
- rb_trap_immediate = NUM2INT(trapflag);
- return Qnil;
-}
-
-/* ruby_cmd receiver method arg ... */
-static int
-#if TCL_MAJOR_VERSION >= 8
-ip_ruby_cmd(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- Tcl_Obj *CONST argv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-ip_ruby_cmd(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
-#endif
-{
- volatile VALUE res;
- volatile VALUE receiver;
- volatile ID method;
- volatile VALUE args = rb_ary_new2(argc - 2);
- volatile VALUE exception = rb_ary_new2(1);
- char *str;
- int i;
- int len;
- int old_trapflag;
- struct cmd_body_arg *arg;
- int thr_crit_bup;
- VALUE old_gc;
-
- if (argc < 3) {
- rb_raise(rb_eArgError, "too few arguments");
- }
-
- /* allocate */
- arg = ALLOC(struct cmd_body_arg);
-
- /* get arguments from Tcl objects */
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
- old_gc = rb_gc_disable();
-
- /* get receiver */
-#if TCL_MAJOR_VERSION >= 8
- str = Tcl_GetStringFromObj(argv[1], &len);
-#else /* TCL_MAJOR_VERSION < 8 */
- str = argv[1];
-#endif
- DUMP2("receiver:%s",str);
- if (str[0] == ':' || ('A' <= str[0] && str[0] <= 'Z')) {
- /* class | module | constant */
- receiver = rb_const_get(rb_cObject, rb_intern(str));
- } else if (str[0] == '$') {
- /* global variable */
- receiver = rb_gv_get(str);
- } else {
- /* global variable omitted '$' */
- char *buf;
-
- len = strlen(str);
- buf = ALLOC_N(char, len + 2);
- buf[0] = '$';
- strncpy(buf + 1, str, len);
- buf[len + 1] = 0;
- receiver = rb_gv_get(buf);
- free(buf);
- }
- if (NIL_P(receiver)) {
- rb_raise(rb_eArgError, "unknown class/module/global-variable '%s'",
- str);
- }
-
- /* get metrhod */
-#if TCL_MAJOR_VERSION >= 8
- str = Tcl_GetStringFromObj(argv[2], &len);
-#else /* TCL_MAJOR_VERSION < 8 */
- str = argv[2];
-#endif
- method = rb_intern(str);
-
- /* get args */
- RARRAY(args)->len = 0;
- for(i = 3; i < argc; i++) {
-#if TCL_MAJOR_VERSION >= 8
- str = Tcl_GetStringFromObj(argv[i], &len);
- DUMP2("arg:%s",str);
- RARRAY(args)->ptr[RARRAY(args)->len++] = rb_tainted_str_new(str, len);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP2("arg:%s",argv[i]);
- RARRAY(args)->ptr[RARRAY(args)->len++] = rb_tainted_str_new2(argv[i]);
-#endif
- }
-
- if (old_gc == Qfalse) rb_gc_enable();
- rb_thread_critical = thr_crit_bup;
-
- RARRAY(exception)->ptr[0] = Qnil;
- RARRAY(exception)->len = 1;
-
- arg->receiver = receiver;
- arg->method = method;
- arg->args = args;
- arg->failed = exception;
-
- /* evaluate the argument string by ruby */
- old_trapflag = rb_trap_immediate;
-#ifdef HAVE_NATIVETHREAD
- if (!is_ruby_native_thread()) {
- rb_bug("cross-thread violation on ip_ruby_cmd()");
- }
-#endif
-
- res = rb_ensure(ip_ruby_cmd_body, (VALUE)arg,
- ip_ruby_cmd_ensure, INT2FIX(old_trapflag));
-
- free(arg);
-
- /* status check */
- /* if (arg.failed) { */
- if (!NIL_P(RARRAY(exception)->ptr[0])) {
- VALUE eclass;
- volatile VALUE bt_ary;
- volatile VALUE backtrace;
-
- DUMP1("(rb_eval_cmd result) failed");
-
- Tcl_ResetResult(interp);
-
- res = RARRAY(exception)->ptr[0];
- eclass = rb_obj_class(res);
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- DUMP1("set backtrace");
- if (!NIL_P(bt_ary = rb_funcall(res, ID_backtrace, 0, 0))) {
- backtrace = rb_ary_join(bt_ary, rb_str_new2("\n"));
- StringValue(backtrace);
- Tcl_AddErrorInfo(interp, RSTRING(backtrace)->ptr);
- }
-
- rb_thread_critical = thr_crit_bup;
-
- if (eclass == eTkCallbackReturn) {
- ip_set_exc_message(interp, res);
- return TCL_RETURN;
-
- } else if (eclass == eTkCallbackBreak) {
- ip_set_exc_message(interp, res);
- return TCL_BREAK;
-
- } else if (eclass == eTkCallbackContinue) {
- ip_set_exc_message(interp, res);
- return TCL_CONTINUE;
-
- } else if (eclass == rb_eSystemExit) {
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* Tcl_Eval(interp, "destroy ."); */
- if (Tk_GetNumMainWindows() > 0) {
- Tk_Window main_win = Tk_MainWindow(interp);
- if (main_win != (Tk_Window)NULL) {
- Tk_DestroyWindow(main_win);
- }
- }
-
- /* StringValue(res); */
- res = rb_funcall(res, ID_message, 0, 0);
-
- Tcl_AppendResult(interp, RSTRING(res)->ptr, (char*)NULL);
-
- rb_thread_critical = thr_crit_bup;
-
- rb_raise(rb_eSystemExit, RSTRING(res)->ptr);
-
- } else if (rb_obj_is_kind_of(res, eLocalJumpError)) {
- VALUE reason = rb_ivar_get(res, ID_at_reason);
-
- if (TYPE(reason) != T_SYMBOL) {
- ip_set_exc_message(interp, res);
- return TCL_ERROR;
- }
-
- if (SYM2ID(reason) == ID_return) {
- ip_set_exc_message(interp, res);
- return TCL_RETURN;
-
- } else if (SYM2ID(reason) == ID_break) {
- ip_set_exc_message(interp, res);
- return TCL_BREAK;
-
- } else if (SYM2ID(reason) == ID_next) {
- ip_set_exc_message(interp, res);
- return TCL_CONTINUE;
-
- } else {
- ip_set_exc_message(interp, res);
- return TCL_ERROR;
- }
- } else {
- ip_set_exc_message(interp, res);
- return TCL_ERROR;
- }
- }
-
- /* result must be string or nil */
- if (NIL_P(res)) {
- DUMP1("(rb_eval_cmd result) nil");
- Tcl_ResetResult(interp);
- return TCL_OK;
- }
-
-
- /* copy result to the tcl interpreter */
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- old_gc = rb_gc_disable();
-
- res = TkStringValue(res);
-
- if (old_gc == Qfalse) rb_gc_enable();
- DUMP2("(rb_eval_cmd result) '%s'", RSTRING(res)->ptr);
- DUMP1("Tcl_AppendResult");
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, RSTRING(res)->ptr, (char *)NULL);
-
- rb_thread_critical = thr_crit_bup;
-
- DUMP1("end of ip_ruby_cmd");
- return TCL_OK;
-}
-
-
-static int
-#if TCL_MAJOR_VERSION >= 8
-ip_InterpExitObjCmd(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- Tcl_Obj *CONST argv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-ip_InterpExitCommand(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
-#endif
-{
- if (!Tcl_InterpDeleted(interp) && !ip_null_namespace(interp)) {
- Tcl_Preserve(interp);
- Tcl_Eval(interp, "interp eval {} {destroy .}; interp delete {}");
- Tcl_Release(interp);
- }
- return TCL_OK;
-}
-
-static int
-#if TCL_MAJOR_VERSION >= 8
-ip_RubyExitObjCmd(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- Tcl_Obj *CONST argv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-ip_RubyExitCommand(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
-#endif
-{
- int state;
- char *cmd, *param;
-
-#if TCL_MAJOR_VERSION >= 8
- cmd = Tcl_GetString(argv[0]);
-
-#else /* TCL_MAJOR_VERSION < 8 */
- char *endptr;
- cmd = argv[0];
-#endif
-
- if (rb_safe_level() >= 4) {
- rb_raise(rb_eSecurityError,
- "Insecure operation `exit' at level %d",
- rb_safe_level());
- } else if (Tcl_IsSafe(interp)) {
- rb_raise(rb_eSecurityError,
- "Insecure operation `exit' on a safe interpreter");
-#if 0
- } else if (Tcl_GetMaster(interp) != (Tcl_Interp *)NULL) {
- Tcl_Preserve(interp);
- Tcl_Eval(interp, "interp eval {} {destroy .}");
- Tcl_Eval(interp, "interp delete {}");
- Tcl_Release(interp);
- return TCL_OK;
-#endif
- }
-
- Tcl_ResetResult(interp);
-
- switch(argc) {
- case 1:
- rb_exit(0); /* not return if succeed */
-
- Tcl_AppendResult(interp,
- "fail to call \"", cmd, "\"", (char *)NULL);
- return TCL_ERROR;
-
- case 2:
-#if TCL_MAJOR_VERSION >= 8
- if (!Tcl_GetIntFromObj(interp, argv[1], &state)) {
- return TCL_ERROR;
- }
- param = Tcl_GetString(argv[1]);
-#else /* TCL_MAJOR_VERSION < 8 */
- state = (int)strtol(argv[1], &endptr, 0);
- if (endptr) {
- Tcl_AppendResult(interp,
- "expected integer but got \"",
- argv[1], "\"", (char *)NULL);
- }
- param = argv[1];
-#endif
- rb_exit(state); /* not return if succeed */
-
- Tcl_AppendResult(interp, "fail to call \"", cmd, " ",
- param, "\"", (char *)NULL);
- return TCL_ERROR;
- default:
- /* arguemnt error */
- Tcl_AppendResult(interp,
- "wrong number of arguments: should be \"",
- cmd, " ?returnCode?\"", (char *)NULL);
- return TCL_ERROR;
- }
-}
-
-
-/**************************/
-/* based on tclEvent.c */
-/**************************/
-
-#if 0 /*
- Disable the following "update" and "thread_update". Bcause,
- they don't work in a callback-proc. After calling update in
- a callback-proc, the callback proc never be worked.
- If the problem will be fixed in the future, may enable the
- functions.
- */
-/*********************/
-/* replace of update */
-/*********************/
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rbUpdateObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rbUpdateObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-static int ip_rbUpdateCommand _((ClientData, Tcl_Interp *, int, char *[]));
-static int
-ip_rbUpdateCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- int optionIndex;
- int ret, done;
- int flags = 0;
- static CONST char *updateOptions[] = {"idletasks", (char *) NULL};
- enum updateOptions {REGEXP_IDLETASKS};
- char *nameString;
- int dummy;
-
- DUMP1("Ruby's 'update' is called");
- if (objc == 1) {
- flags = TCL_ALL_EVENTS|TCL_DONT_WAIT;
-
- } else if (objc == 2) {
- if (Tcl_GetIndexFromObj(interp, objv[1], updateOptions,
- "option", 0, &optionIndex) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum updateOptions) optionIndex) {
- case REGEXP_IDLETASKS: {
- flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT;
- break;
- }
- default: {
- Tcl_Panic("ip_rbUpdateObjCmd: bad option index to UpdateOptions");
- }
- }
- } else {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "[ idletasks ]");
-#else
-# if TCL_MAJOR_VERSION >= 8
- 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;
- }
-
- /* call eventloop */
-#if 1
- ret = lib_eventloop_core(0, flags, (int *)NULL); /* ignore result */
-#else
- Tcl_UpdateObjCmd(clientData, interp, objc, objv);
-#endif
-
- /*
- * Must clear the interpreter's result because event handlers could
- * have executed commands.
- */
-
- DUMP2("last result '%s'", Tcl_GetStringResult(interp));
- Tcl_ResetResult(interp);
- DUMP1("finish Ruby's 'update'");
- return TCL_OK;
-}
-
-
-/**********************/
-/* update with thread */
-/**********************/
-struct th_update_param {
- VALUE thread;
- int done;
-};
-
-static void rb_threadUpdateProc _((ClientData));
-static void
-rb_threadUpdateProc(clientData)
- ClientData clientData; /* Pointer to integer to set to 1. */
-{
- struct th_update_param *param = (struct th_update_param *) clientData;
-
- DUMP1("threadUpdateProc is called");
- param->done = 1;
- rb_thread_wakeup(param->thread);
-
- return;
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rb_threadUpdateObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rb_threadUpdateObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-static int ip_rb_threadUpdateCommand _((ClientData, Tcl_Interp *, int,
- char *[]));
-static int
-ip_rb_threadUpdateCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- int optionIndex;
- int ret, done;
- int flags = 0;
- int dummy;
- struct th_update_param *param;
- static CONST char *updateOptions[] = {"idletasks", (char *) NULL};
- enum updateOptions {REGEXP_IDLETASKS};
- volatile VALUE current_thread = rb_thread_current();
-
- DUMP1("Ruby's 'thread_update' is called");
-
- if (rb_thread_alone() || eventloop_thread == current_thread) {
-#define USE_TCL_UPDATE 0
-#if TCL_MAJOR_VERSION >= 8
-# if USE_TCL_UPDATE
- DUMP1("call Tcl_UpdateObjCmd");
- return Tcl_UpdateObjCmd(clientData, interp, objc, objv);
-# else
- DUMP1("call ip_rbUpdateObjCmd");
- return ip_rbUpdateObjCmd(clientData, interp, objc, objv);
-# endif
-#else /* TCL_MAJOR_VERSION < 8 */
-# if USE_TCL_UPDATE
- DUMP1("call ip_rbUpdateCommand");
- return Tcl_UpdateCommand(clientData, interp, objc, objv);
-# else
- DUMP1("call ip_rbUpdateCommand");
- return ip_rbUpdateCommand(clientData, interp, objc, objv);
-# endif
-#endif
- }
-
- DUMP1("start Ruby's 'thread_update' body");
-
- if (objc == 1) {
- flags = TCL_ALL_EVENTS|TCL_DONT_WAIT;
-
- } else if (objc == 2) {
- if (Tcl_GetIndexFromObj(interp, objv[1], updateOptions,
- "option", 0, &optionIndex) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum updateOptions) optionIndex) {
- case REGEXP_IDLETASKS: {
- flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT;
- break;
- }
- default: {
- Tcl_Panic("ip_rb_threadUpdateObjCmd: bad option index to UpdateOptions");
- }
- }
- } else {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "[ idletasks ]");
-#else
-# if TCL_MAJOR_VERSION >= 8
- 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;
- }
-
- DUMP1("pass argument check");
-
- param = (struct th_update_param *)Tcl_Alloc(sizeof(struct th_update_param));
- Tcl_Preserve(param);
- param->thread = current_thread;
- param->done = 0;
-
- DUMP1("set idle proc");
- Tcl_DoWhenIdle(rb_threadUpdateProc, (ClientData) param);
-
- while(!param->done) {
- DUMP1("wait for complete idle proc");
- rb_thread_stop();
- }
-
- Tcl_Release(param);
- Tcl_Free((char *)param);
-
- DUMP1("finish Ruby's 'thread_update'");
- return TCL_OK;
-}
-#endif /* update and thread_update don't work */
-
-
-/***************************/
-/* replace of vwait/tkwait */
-/***************************/
-#if TCL_MAJOR_VERSION >= 8
-static char *VwaitVarProc _((ClientData, Tcl_Interp *,
- CONST84 char *,CONST84 char *, int));
-static char *
-VwaitVarProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST84 char *name1; /* Name of variable. */
- CONST84 char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-#else /* TCL_MAJOR_VERSION < 8 */
-static char *VwaitVarProc _((ClientData, Tcl_Interp *, char *, char *, int));
-static char *
-VwaitVarProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- char *name1; /* Name of variable. */
- char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-#endif
-{
- int *donePtr = (int *) clientData;
-
- *donePtr = 1;
- return (char *) NULL;
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rbVwaitObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rbVwaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-static int ip_rbVwaitCommand _((ClientData, Tcl_Interp *, int, char *[]));
-static int
-ip_rbVwaitCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- int ret, done, foundEvent;
- char *nameString;
- int dummy;
- int thr_crit_bup;
-
- DUMP1("Ruby's 'vwait' is called");
- Tcl_Preserve(interp);
-
- if (objc != 2) {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "name");
-#else
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
-#if TCL_MAJOR_VERSION >= 8
- /* nameString = Tcl_GetString(objv[0]); */
- nameString = Tcl_GetStringFromObj(objv[0], &dummy);
-#else /* TCL_MAJOR_VERSION < 8 */
- nameString = objv[0];
-#endif
- Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
- nameString, " name\"", (char *) NULL);
-
- rb_thread_critical = thr_crit_bup;
-#endif
-
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_IncrRefCount(objv[1]);
- /* nameString = Tcl_GetString(objv[1]); */
- nameString = Tcl_GetStringFromObj(objv[1], &dummy);
-#else /* TCL_MAJOR_VERSION < 8 */
- nameString = objv[1];
-#endif
-
- /*
- if (Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- VwaitVarProc, (ClientData) &done) != TCL_OK) {
- return TCL_ERROR;
- }
- */
- ret = Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- VwaitVarProc, (ClientData) &done);
-
- rb_thread_critical = thr_crit_bup;
-
- if (ret != TCL_OK) {
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[1]);
-#endif
- Tcl_Release(interp);
- return TCL_ERROR;
- }
- done = 0;
- foundEvent = lib_eventloop_core(/* not check root-widget */0, 0, &done);
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- Tcl_UntraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- VwaitVarProc, (ClientData) &done);
-
- rb_thread_critical = thr_crit_bup;
-
- /*
- * Clear out the interpreter's result, since it may have been set
- * by event handlers.
- */
-
- Tcl_ResetResult(interp);
- if (!foundEvent) {
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- Tcl_AppendResult(interp, "can't wait for variable \"", nameString,
- "\": would wait forever", (char *) NULL);
-
- rb_thread_critical = thr_crit_bup;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[1]);
-#endif
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[1]);
-#endif
- Tcl_Release(interp);
- return TCL_OK;
-}
-
-
-/**************************/
-/* based on tkCmd.c */
-/**************************/
-#if TCL_MAJOR_VERSION >= 8
-static char *WaitVariableProc _((ClientData, Tcl_Interp *,
- CONST84 char *,CONST84 char *, int));
-static char *
-WaitVariableProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST84 char *name1; /* Name of variable. */
- CONST84 char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-#else /* TCL_MAJOR_VERSION < 8 */
-static char *WaitVariableProc _((ClientData, Tcl_Interp *,
- char *, char *, int));
-static char *
-WaitVariableProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- char *name1; /* Name of variable. */
- char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-#endif
-{
- int *donePtr = (int *) clientData;
-
- *donePtr = 1;
- return (char *) NULL;
-}
-
-static void WaitVisibilityProc _((ClientData, XEvent *));
-static void
-WaitVisibilityProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to integer to set to 1. */
- XEvent *eventPtr; /* Information about event (not used). */
-{
- int *donePtr = (int *) clientData;
-
- if (eventPtr->type == VisibilityNotify) {
- *donePtr = 1;
- }
- if (eventPtr->type == DestroyNotify) {
- *donePtr = 2;
- }
-}
-
-static void WaitWindowProc _((ClientData, XEvent *));
-static void
-WaitWindowProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to integer to set to 1. */
- XEvent *eventPtr; /* Information about event. */
-{
- int *donePtr = (int *) clientData;
-
- if (eventPtr->type == DestroyNotify) {
- *donePtr = 1;
- }
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rbTkWaitObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rbTkWaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-static int ip_rbTkWaitCommand _((ClientData, Tcl_Interp *, int, char *[]));
-static int
-ip_rbTkWaitCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- Tk_Window tkwin = (Tk_Window) clientData;
- Tk_Window window;
- int done, index;
- static CONST char *optionStrings[] = { "variable", "visibility", "window",
- (char *) NULL };
- enum options { TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW };
- char *nameString;
- int ret, dummy;
- int thr_crit_bup;
-
- DUMP1("Ruby's 'tkwait' is called");
-
- Tcl_Preserve(interp);
-
- if (objc != 3) {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name");
-#else
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
- Tcl_GetStringFromObj(objv[0], &dummy),
- " variable|visibility|window name\"",
- (char *) NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
- objv[0], " variable|visibility|window name\"",
- (char *) NULL);
-#endif
-
- rb_thread_critical = thr_crit_bup;
-#endif
-
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
-#if TCL_MAJOR_VERSION >= 8
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /*
- if (Tcl_GetIndexFromObj(interp, objv[1],
- (CONST84 char **)optionStrings,
- "option", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- */
- ret = Tcl_GetIndexFromObj(interp, objv[1],
- (CONST84 char **)optionStrings,
- "option", 0, &index);
-
- rb_thread_critical = thr_crit_bup;
-
- if (ret != TCL_OK) {
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- {
- int c = objv[1][0];
- size_t length = strlen(objv[1]);
-
- if ((c == 'v') && (strncmp(objv[1], "variable", length) == 0)
- && (length >= 2)) {
- index = TKWAIT_VARIABLE;
- } else if ((c == 'v') && (strncmp(objv[1], "visibility", length) == 0)
- && (length >= 2)) {
- index = TKWAIT_VISIBILITY;
- } else if ((c == 'w') && (strncmp(objv[1], "window", length) == 0)) {
- index = TKWAIT_WINDOW;
- } else {
- Tcl_AppendResult(interp, "bad option \"", objv[1],
- "\": must be variable, visibility, or window",
- (char *) NULL);
- Tcl_Release(interp);
- return TCL_ERROR;
- }
- }
-#endif
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_IncrRefCount(objv[2]);
- /* nameString = Tcl_GetString(objv[2]); */
- nameString = Tcl_GetStringFromObj(objv[2], &dummy);
-#else /* TCL_MAJOR_VERSION < 8 */
- nameString = objv[2];
-#endif
-
- rb_thread_critical = thr_crit_bup;
-
- switch ((enum options) index) {
- case TKWAIT_VARIABLE:
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
- /*
- if (Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- WaitVariableProc, (ClientData) &done) != TCL_OK) {
- return TCL_ERROR;
- }
- */
- ret = Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- WaitVariableProc, (ClientData) &done);
-
- rb_thread_critical = thr_crit_bup;
-
- if (ret != TCL_OK) {
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
- Tcl_Release(interp);
- return TCL_ERROR;
- }
- done = 0;
- lib_eventloop_core(check_rootwidget_flag, 0, &done);
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- Tcl_UntraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- WaitVariableProc, (ClientData) &done);
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
-
- rb_thread_critical = thr_crit_bup;
-
- break;
-
- case TKWAIT_VISIBILITY:
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (Tk_MainWindow(interp) == (Tk_Window)NULL) {
- window = NULL;
- } else {
- window = Tk_NameToWindow(interp, nameString, tkwin);
- }
-
- if (window == NULL) {
- rb_thread_critical = thr_crit_bup;
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
- Tk_CreateEventHandler(window,
- VisibilityChangeMask|StructureNotifyMask,
- WaitVisibilityProc, (ClientData) &done);
-
- rb_thread_critical = thr_crit_bup;
-
- done = 0;
- lib_eventloop_core(check_rootwidget_flag, 0, &done);
- if (done != 1) {
- /*
- * Note that we do not delete the event handler because it
- * was deleted automatically when the window was destroyed.
- */
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "window \"", nameString,
- "\" was deleted before its visibility changed",
- (char *) NULL);
-
- rb_thread_critical = thr_crit_bup;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
-
- Tk_DeleteEventHandler(window,
- VisibilityChangeMask|StructureNotifyMask,
- WaitVisibilityProc, (ClientData) &done);
-
- rb_thread_critical = thr_crit_bup;
-
- break;
-
- case TKWAIT_WINDOW:
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (Tk_MainWindow(interp) == (Tk_Window)NULL) {
- window = NULL;
- } else {
- window = Tk_NameToWindow(interp, nameString, tkwin);
- }
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
-
- if (window == NULL) {
- rb_thread_critical = thr_crit_bup;
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
- Tk_CreateEventHandler(window, StructureNotifyMask,
- WaitWindowProc, (ClientData) &done);
-
- rb_thread_critical = thr_crit_bup;
-
- done = 0;
- lib_eventloop_core(check_rootwidget_flag, 0, &done);
- /*
- * Note: there's no need to delete the event handler. It was
- * deleted automatically when the window was destroyed.
- */
- break;
- }
-
- /*
- * Clear out the interpreter's result, since it may have been set
- * by event handlers.
- */
-
- Tcl_ResetResult(interp);
- Tcl_Release(interp);
- return TCL_OK;
-}
-
-/****************************/
-/* vwait/tkwait with thread */
-/****************************/
-struct th_vwait_param {
- VALUE thread;
- int done;
-};
-
-#if TCL_MAJOR_VERSION >= 8
-static char *rb_threadVwaitProc _((ClientData, Tcl_Interp *,
- CONST84 char *,CONST84 char *, int));
-static char *
-rb_threadVwaitProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST84 char *name1; /* Name of variable. */
- CONST84 char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-#else /* TCL_MAJOR_VERSION < 8 */
-static char *rb_threadVwaitProc _((ClientData, Tcl_Interp *,
- char *, char *, int));
-static char *
-rb_threadVwaitProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- char *name1; /* Name of variable. */
- char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-#endif
-{
- struct th_vwait_param *param = (struct th_vwait_param *) clientData;
-
- if (flags & (TCL_INTERP_DESTROYED | TCL_TRACE_DESTROYED)) {
- param->done = -1;
- } else {
- param->done = 1;
- }
- rb_thread_wakeup(param->thread);
-
- return (char *)NULL;
-}
-
-#define TKWAIT_MODE_VISIBILITY 1
-#define TKWAIT_MODE_DESTROY 2
-
-static void rb_threadWaitVisibilityProc _((ClientData, XEvent *));
-static void
-rb_threadWaitVisibilityProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to integer to set to 1. */
- XEvent *eventPtr; /* Information about event (not used). */
-{
- struct th_vwait_param *param = (struct th_vwait_param *) clientData;
-
- if (eventPtr->type == VisibilityNotify) {
- param->done = TKWAIT_MODE_VISIBILITY;
- }
- if (eventPtr->type == DestroyNotify) {
- param->done = TKWAIT_MODE_DESTROY;
- }
- rb_thread_wakeup(param->thread);
-}
-
-static void rb_threadWaitWindowProc _((ClientData, XEvent *));
-static void
-rb_threadWaitWindowProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to integer to set to 1. */
- XEvent *eventPtr; /* Information about event. */
-{
- struct th_vwait_param *param = (struct th_vwait_param *) clientData;
-
- if (eventPtr->type == DestroyNotify) {
- param->done = TKWAIT_MODE_DESTROY;
- }
- rb_thread_wakeup(param->thread);
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rb_threadVwaitObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rb_threadVwaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-static int ip_rb_threadVwaitCommand _((ClientData, Tcl_Interp *, int,
- char *[]));
-static int
-ip_rb_threadVwaitCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- struct th_vwait_param *param;
- char *nameString;
- int ret, dummy;
- int thr_crit_bup;
- volatile VALUE current_thread = rb_thread_current();
-
- DUMP1("Ruby's 'thread_vwait' is called");
-
- if (rb_thread_alone() || eventloop_thread == current_thread) {
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("call ip_rbVwaitObjCmd");
- return ip_rbVwaitObjCmd(clientData, interp, objc, objv);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("call ip_rbVwaitCommand");
- return ip_rbVwaitCommand(clientData, interp, objc, objv);
-#endif
- }
-
- Tcl_Preserve(interp);
-
- if (objc != 2) {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "name");
-#else
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
-#if TCL_MAJOR_VERSION >= 8
- /* nameString = Tcl_GetString(objv[0]); */
- nameString = Tcl_GetStringFromObj(objv[0], &dummy);
-#else /* TCL_MAJOR_VERSION < 8 */
- nameString = objv[0];
-#endif
- Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
- nameString, " name\"", (char *) NULL);
-
- rb_thread_critical = thr_crit_bup;
-#endif
-
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_IncrRefCount(objv[1]);
- /* nameString = Tcl_GetString(objv[1]); */
- nameString = Tcl_GetStringFromObj(objv[1], &dummy);
-#else /* TCL_MAJOR_VERSION < 8 */
- nameString = objv[1];
-#endif
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param));
- Tcl_Preserve(param);
- param->thread = current_thread;
- param->done = 0;
-
- /*
- if (Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param) != TCL_OK) {
- return TCL_ERROR;
- }
- */
- ret = Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param);
-
- rb_thread_critical = thr_crit_bup;
-
- if (ret != TCL_OK) {
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[1]);
-#endif
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
- /* if (!param->done) { */
- while(!param->done) {
- rb_thread_stop();
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (param->done > 0) {
- Tcl_UntraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param);
- }
-
- Tcl_Release(param);
- Tcl_Free((char *)param);
-
- rb_thread_critical = thr_crit_bup;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[1]);
-#endif
- Tcl_Release(interp);
- return TCL_OK;
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rb_threadTkWaitObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rb_threadTkWaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else /* TCL_MAJOR_VERSION < 8 */
-static int ip_rb_threadTkWaitCommand _((ClientData, Tcl_Interp *, int,
- char *[]));
-static int
-ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- struct th_vwait_param *param;
- Tk_Window tkwin = (Tk_Window) clientData;
- Tk_Window window;
- int index;
- static CONST char *optionStrings[] = { "variable", "visibility", "window",
- (char *) NULL };
- enum options { TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW };
- char *nameString;
- int ret, dummy;
- int thr_crit_bup;
- volatile VALUE current_thread = rb_thread_current();
-
- DUMP1("Ruby's 'thread_tkwait' is called");
-
- if (rb_thread_alone() || eventloop_thread == current_thread) {
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("call ip_rbTkWaitObjCmd");
- return ip_rbTkWaitObjCmd(clientData, interp, objc, objv);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("call rb_VwaitCommand");
- return ip_rbTkWaitCommand(clientData, interp, objc, objv);
-#endif
- }
-
- Tcl_Preserve(interp);
- Tcl_Preserve(tkwin);
-
- if (objc != 3) {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name");
-#else
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
- Tcl_GetStringFromObj(objv[0], &dummy),
- " variable|visibility|window name\"",
- (char *) NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
- objv[0], " variable|visibility|window name\"",
- (char *) NULL);
-#endif
-
- rb_thread_critical = thr_crit_bup;
-#endif
-
- Tcl_Release(tkwin);
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
-#if TCL_MAJOR_VERSION >= 8
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
- /*
- if (Tcl_GetIndexFromObj(interp, objv[1],
- (CONST84 char **)optionStrings,
- "option", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- */
- ret = Tcl_GetIndexFromObj(interp, objv[1],
- (CONST84 char **)optionStrings,
- "option", 0, &index);
-
- rb_thread_critical = thr_crit_bup;
-
- if (ret != TCL_OK) {
- Tcl_Release(tkwin);
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- {
- int c = objv[1][0];
- size_t length = strlen(objv[1]);
-
- if ((c == 'v') && (strncmp(objv[1], "variable", length) == 0)
- && (length >= 2)) {
- index = TKWAIT_VARIABLE;
- } else if ((c == 'v') && (strncmp(objv[1], "visibility", length) == 0)
- && (length >= 2)) {
- index = TKWAIT_VISIBILITY;
- } else if ((c == 'w') && (strncmp(objv[1], "window", length) == 0)) {
- index = TKWAIT_WINDOW;
- } else {
- Tcl_AppendResult(interp, "bad option \"", objv[1],
- "\": must be variable, visibility, or window",
- (char *) NULL);
- Tcl_Release(tkwin);
- Tcl_Release(interp);
- return TCL_ERROR;
- }
- }
-#endif
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_IncrRefCount(objv[2]);
- /* nameString = Tcl_GetString(objv[2]); */
- nameString = Tcl_GetStringFromObj(objv[2], &dummy);
-#else /* TCL_MAJOR_VERSION < 8 */
- nameString = objv[2];
-#endif
-
- param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param));
- Tcl_Preserve(param);
- param->thread = current_thread;
- param->done = 0;
-
- rb_thread_critical = thr_crit_bup;
-
- switch ((enum options) index) {
- case TKWAIT_VARIABLE:
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
- /*
- if (Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param) != TCL_OK) {
- return TCL_ERROR;
- }
- */
- ret = Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param);
-
- rb_thread_critical = thr_crit_bup;
-
- if (ret != TCL_OK) {
- Tcl_Release(param);
- Tcl_Free((char *)param);
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
-
- Tcl_Release(tkwin);
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
- /* if (!param->done) { */
- while(!param->done) {
- rb_thread_stop();
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (param->done > 0) {
- Tcl_UntraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param);
- }
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
-
- rb_thread_critical = thr_crit_bup;
-
- break;
-
- case TKWAIT_VISIBILITY:
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (Tk_MainWindow(interp) == (Tk_Window)NULL) {
- window = NULL;
- } else {
- window = Tk_NameToWindow(interp, nameString, tkwin);
- }
-
- if (window == NULL) {
- rb_thread_critical = thr_crit_bup;
-
- Tcl_Release(param);
- Tcl_Free((char *)param);
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
- Tcl_Release(tkwin);
- Tcl_Release(interp);
- return TCL_ERROR;
- }
- Tcl_Preserve(window);
-
- Tk_CreateEventHandler(window,
- VisibilityChangeMask|StructureNotifyMask,
- rb_threadWaitVisibilityProc, (ClientData) param);
-
- rb_thread_critical = thr_crit_bup;
-
- /* if (!param->done) { */
- /*
- while(!param->done) {
- rb_thread_stop();
- }
- */
- while(param->done != TKWAIT_MODE_VISIBILITY) {
- if (param->done == TKWAIT_MODE_DESTROY) break;
- rb_thread_stop();
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* when a window is destroyed, no need to call Tk_DeleteEventHandler */
- if (param->done != TKWAIT_MODE_DESTROY) {
- Tk_DeleteEventHandler(window,
- VisibilityChangeMask|StructureNotifyMask,
- rb_threadWaitVisibilityProc,
- (ClientData) param);
- }
-
- if (param->done != 1) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "window \"", nameString,
- "\" was deleted before its visibility changed",
- (char *) NULL);
-
- rb_thread_critical = thr_crit_bup;
-
- Tcl_Release(window);
-
- Tcl_Release(param);
- Tcl_Free((char *)param);
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
-
- Tcl_Release(tkwin);
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
- Tcl_Release(window);
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
-
- rb_thread_critical = thr_crit_bup;
-
- break;
-
- case TKWAIT_WINDOW:
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (Tk_MainWindow(interp) == (Tk_Window)NULL) {
- window = NULL;
- } else {
- window = Tk_NameToWindow(interp, nameString, tkwin);
- }
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(objv[2]);
-#endif
-
- if (window == NULL) {
- rb_thread_critical = thr_crit_bup;
-
- Tcl_Release(param);
- Tcl_Free((char *)param);
-
- Tcl_Release(tkwin);
- Tcl_Release(interp);
- return TCL_ERROR;
- }
-
- Tcl_Preserve(window);
-
- Tk_CreateEventHandler(window, StructureNotifyMask,
- rb_threadWaitWindowProc, (ClientData) param);
-
- rb_thread_critical = thr_crit_bup;
-
- /* if (!param->done) { */
- /*
- while(!param->done) {
- rb_thread_stop();
- }
- */
- while(param->done != TKWAIT_MODE_DESTROY) {
- rb_thread_stop();
- }
-
- Tcl_Release(window);
-
- /* when a window is destroyed, no need to call Tk_DeleteEventHandler
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- Tk_DeleteEventHandler(window, StructureNotifyMask,
- rb_threadWaitWindowProc, (ClientData) param);
-
- rb_thread_critical = thr_crit_bup;
- */
-
- break;
- } /* end of 'switch' statement */
-
- Tcl_Release(param);
- Tcl_Free((char *)param);
-
- /*
- * Clear out the interpreter's result, since it may have been set
- * by event handlers.
- */
-
- Tcl_ResetResult(interp);
-
- Tcl_Release(tkwin);
- Tcl_Release(interp);
- return TCL_OK;
-}
-
-static VALUE
-ip_thread_vwait(self, var)
- VALUE self;
- VALUE var;
-{
- VALUE argv[2];
- volatile VALUE cmd_str = rb_str_new2("thread_vwait");
-
- argv[0] = cmd_str;
- argv[1] = var;
- return ip_invoke_real(2, argv, self);
-}
-
-static VALUE
-ip_thread_tkwait(self, mode, target)
- VALUE self;
- VALUE mode;
- VALUE target;
-{
- VALUE argv[3];
- volatile VALUE cmd_str = rb_str_new2("thread_tkwait");
-
- argv[0] = cmd_str;
- argv[1] = mode;
- argv[2] = target;
- return ip_invoke_real(3, argv, self);
-}
-
-/* destroy interpreter */
-VALUE del_root(ip)
- Tcl_Interp *ip;
-{
- Tk_Window main_win;
-
- if (!Tcl_InterpDeleted(ip)) {
- Tcl_Preserve(ip);
-
- if ( (main_win = Tk_MainWindow(ip)) != (Tk_Window)NULL
- && !(((Tk_FakeWin*)main_win)->flags & TK_ALREADY_DEAD) ) {
- DUMP1("wait main_win is destroyed");
- Tk_DestroyWindow(main_win);
- }
-
- Tcl_Release(ip);
- }
- return Qnil;
-}
-
-
-static void
-delete_slaves(ip)
- Tcl_Interp *ip;
-{
- Tcl_Interp *slave;
- Tcl_Obj *slave_list, *elem;
- Tcl_CmdInfo info;
- char *slave_name;
- int i, len;
-
- if (Tcl_InterpDeleted(ip) || ip_null_namespace(ip)) {
- DUMP2("call delete_slaves() for deleted ip(%lx)", ip);
- return;
- }
-
- DUMP2("delete slaves of ip(%lx)", ip);
-
- Tcl_Preserve(ip);
-
- if (Tcl_Eval(ip, "info slaves") == TCL_ERROR) {
- DUMP2("ip(%lx) cannot get a list of slave IPs", ip);
- return;
- }
-
- slave_list = Tcl_GetObjResult(ip);
- Tcl_IncrRefCount(slave_list);
-
- if (Tcl_ListObjLength((Tcl_Interp*)NULL, slave_list, &len) == TCL_ERROR) {
- DUMP1("slave_list is not a list object");
- Tcl_DecrRefCount(slave_list);
- return;
- }
-
- for(i = 0; i < len; i++) {
- Tcl_ListObjIndex((Tcl_Interp*)NULL, slave_list, i, &elem);
- Tcl_IncrRefCount(elem);
-
- if (elem == (Tcl_Obj*)NULL) continue;
-
- /* get slave */
- slave_name = Tcl_GetString(elem);
- slave = Tcl_GetSlave(ip, slave_name);
- if (slave == (Tcl_Interp*)NULL) {
- DUMP2("slave \"%s\" does not exist", slave_name);
- continue;
- }
-
- Tcl_DecrRefCount(elem);
-
- Tcl_Preserve(slave);
-
- if (!Tcl_InterpDeleted(slave) && !ip_null_namespace(slave)) {
- if (Tcl_Eval(slave, DEF_CANCEL_AFTER_SCRIPTS_PROC) == TCL_OK) {
- if (Tcl_GetCommandInfo(slave, CANCEL_AFTER_SCRIPTS, &info)) {
- DUMP2("call cancel after scripts proc '%s'",
- CANCEL_AFTER_SCRIPTS);
- Tcl_Eval(slave, CANCEL_AFTER_SCRIPTS);
- }
- }
-
- if (Tcl_GetCommandInfo(slave, finalize_hook_name, &info)) {
- DUMP2("call finalize hook proc '%s'", finalize_hook_name);
- Tcl_Eval(slave, finalize_hook_name);
- }
- }
-
- /* delete slaves of slave */
- delete_slaves(slave);
-
- /* delete slave */
- del_root(slave);
- /* while(!rbtk_InterpDeleted(slave)) { */
- if (!Tcl_InterpDeleted(slave)) {
- DUMP1("wait ip is deleted");
- Tcl_DeleteInterp(slave);
- }
-
- Tcl_Release(slave);
-
- /* delete slave_name command */
- Tcl_DeleteCommand(ip, slave_name);
- }
-
- Tcl_DecrRefCount(slave_list);
-
- Tcl_Release(ip);
-}
-
-static void
-ip_free(ptr)
- struct tcltkip *ptr;
-{
- Tcl_CmdInfo info;
- int thr_crit_bup;
-
- DUMP2("free Tcl Interp %lx", ptr->ip);
- if (ptr) {
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- DUMP2("IP ref_count = %d", ptr->ref_count);
-
- if (!Tcl_InterpDeleted(ptr->ip) && !ip_null_namespace(ptr->ip)) {
- DUMP2("IP(%lx) is not deleted", ptr->ip);
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
-
- delete_slaves(ptr->ip);
-
- Tcl_ResetResult(ptr->ip);
-
- if (Tcl_Eval(ptr->ip, DEF_CANCEL_AFTER_SCRIPTS_PROC) == TCL_OK) {
- if (Tcl_GetCommandInfo(ptr->ip, CANCEL_AFTER_SCRIPTS, &info)) {
- DUMP2("call cancel after scripts proc '%s'",
- CANCEL_AFTER_SCRIPTS);
- Tcl_Eval(ptr->ip, CANCEL_AFTER_SCRIPTS);
- }
- }
-
- if (Tcl_GetCommandInfo(ptr->ip, finalize_hook_name, &info)) {
- DUMP2("call finalize hook proc '%s'", finalize_hook_name);
- Tcl_Eval(ptr->ip, finalize_hook_name);
- }
-
- /* del_root(ptr->ip); */
-
- DUMP1("delete interp");
- /* while(!rbtk_InterpDeleted(ptr->ip)) { */
- if (!Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("wait ip is deleted");
- Tcl_DeleteInterp(ptr->ip);
- }
-
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- }
-
- rbtk_release_ip(ptr);
- DUMP2("IP ref_count = %d", ptr->ref_count);
-
- free(ptr);
-
- rb_thread_critical = thr_crit_bup;
- }
- DUMP1("complete freeing Tcl Interp");
-}
-
-/* create and initialize interpreter */
-static VALUE ip_alloc _((VALUE));
-static VALUE
-ip_alloc(self)
- VALUE self;
-{
- return Data_Wrap_Struct(self, 0, ip_free, 0);
-}
-
-static VALUE
-ip_init(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- struct tcltkip *ptr; /* tcltkip data struct */
- VALUE argv0, opts;
- int cnt;
- int with_tk = 1;
- Tk_Window mainWin;
-
- /* security check */
- if (ruby_safe_level >= 4) {
- rb_raise(rb_eSecurityError, "Cannot create a TclTkIp object at level %d", ruby_safe_level);
- }
-
- /* create object */
- Data_Get_Struct(self, struct tcltkip, ptr);
- ptr = ALLOC(struct tcltkip);
- DATA_PTR(self) = ptr;
- ptr->ref_count = 0;
- ptr->allow_ruby_exit = 1;
- ptr->return_value = 0;
-
- /* from Tk_Main() */
- DUMP1("Tcl_CreateInterp");
- ptr->ip = Tcl_CreateInterp();
- if (ptr->ip == NULL) {
- rb_raise(rb_eRuntimeError, "fail to create a new Tk interpreter");
- }
-
- rbtk_preserve_ip(ptr);
- DUMP2("IP ref_count = %d", ptr->ref_count);
- current_interp = ptr->ip;
-
- ptr->has_orig_exit
- = Tcl_GetCommandInfo(ptr->ip, "exit", &(ptr->orig_exit_info));
-
- /* from Tcl_AppInit() */
- DUMP1("Tcl_Init");
- if (Tcl_Init(ptr->ip) == TCL_ERROR) {
-#if TCL_MAJOR_VERSION >= 8
- rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
-#endif
- }
-
- /* set variables */
- cnt = rb_scan_args(argc, argv, "02", &argv0, &opts);
- switch(cnt) {
- case 2:
- /* options */
- if (NIL_P(opts) || opts == Qfalse) {
- /* without Tk */
- with_tk = 0;
- } else {
- /* Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), 0); */
- Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), TCL_GLOBAL_ONLY);
- }
- case 1:
- /* argv0 */
- if (!NIL_P(argv0)) {
- if (strncmp(StringValuePtr(argv0), "-e", 3) == 0
- || strncmp(StringValuePtr(argv0), "-", 2) == 0) {
- Tcl_SetVar(ptr->ip, "argv0", "ruby", TCL_GLOBAL_ONLY);
- } else {
- /* Tcl_SetVar(ptr->ip, "argv0", StringValuePtr(argv0), 0); */
- Tcl_SetVar(ptr->ip, "argv0", StringValuePtr(argv0),
- TCL_GLOBAL_ONLY);
- }
- }
- case 0:
- /* no args */
- ;
- }
-
- /* from Tcl_AppInit() */
- if (with_tk) {
- DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
-#if TCL_MAJOR_VERSION >= 8
- rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
-#endif
- }
- DUMP1("Tcl_StaticPackage(\"Tk\")");
-#if TCL_MAJOR_VERSION >= 8
- Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
-#else /* TCL_MAJOR_VERSION < 8 */
- Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
- (Tcl_PackageInitProc *) NULL);
-#endif
- }
-
- /* get main window */
- mainWin = Tk_MainWindow(ptr->ip);
- Tk_Preserve((ClientData)mainWin);
-
- /* add ruby command to the interpreter */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"ruby\")");
- Tcl_CreateObjCommand(ptr->ip, "ruby", ip_ruby_eval, (ClientData)NULL,
- (Tcl_CmdDeleteProc *)NULL);
- DUMP1("Tcl_CreateObjCommand(\"ruby_eval\")");
- Tcl_CreateObjCommand(ptr->ip, "ruby_eval", ip_ruby_eval, (ClientData)NULL,
- (Tcl_CmdDeleteProc *)NULL);
- DUMP1("Tcl_CreateObjCommand(\"ruby_cmd\")");
- Tcl_CreateObjCommand(ptr->ip, "ruby_cmd", ip_ruby_cmd, (ClientData)NULL,
- (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"ruby\")");
- Tcl_CreateCommand(ptr->ip, "ruby", ip_ruby_eval, (ClientData)NULL,
- (Tcl_CmdDeleteProc *)NULL);
- DUMP1("Tcl_CreateCommand(\"ruby_eval\")");
- Tcl_CreateCommand(ptr->ip, "ruby_eval", ip_ruby_eval, (ClientData)NULL,
- (Tcl_CmdDeleteProc *)NULL);
- DUMP1("Tcl_CreateCommand(\"ruby_cmd\")");
- Tcl_CreateCommand(ptr->ip, "ruby_cmd", ip_ruby_cmd, (ClientData)NULL,
- (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- /* add 'interp_exit', 'ruby_exit' and replace 'exit' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"interp_exit\")");
- Tcl_CreateObjCommand(ptr->ip, "interp_exit", ip_InterpExitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
- DUMP1("Tcl_CreateObjCommand(\"ruby_exit\")");
- Tcl_CreateObjCommand(ptr->ip, "ruby_exit", ip_RubyExitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
- DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"ruby_exit\"");
- Tcl_CreateObjCommand(ptr->ip, "exit", ip_RubyExitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"interp_exit\")");
- Tcl_CreateCommand(ptr->ip, "interp_exit", ip_InterpExitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
- DUMP1("Tcl_CreateCommand(\"ruby_exit\")");
- Tcl_CreateCommand(ptr->ip, "ruby_exit", ip_RubyExitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
- DUMP1("Tcl_CreateCommand(\"exit\") --> \"ruby_exit\"");
- Tcl_CreateCommand(ptr->ip, "exit", ip_RubyExitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
-#if 0 /*
- Disable the following "update" and "thread_update". Bcause,
- they don't work in a callback-proc. After calling update in
- a callback-proc, the callback proc never be worked.
- If the problem will be fixed in the future, may enable the
- functions.
- */
- /* replace 'update' command */
-# if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"update\")");
- Tcl_CreateObjCommand(ptr->ip, "update", ip_rbUpdateObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-# else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"update\")");
- Tcl_CreateCommand(ptr->ip, "update", ip_rbUpdateCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-# endif
-
- /* add 'thread_update' command */
-# if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"thread_update\")");
- Tcl_CreateObjCommand(ptr->ip, "thread_update", ip_rb_threadUpdateObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-# else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"thread_update\")");
- Tcl_CreateCommand(ptr->ip, "thread_update", ip_rb_threadUpdateCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-# endif
-#endif
-
- /* replace 'vwait' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"vwait\")");
- Tcl_CreateObjCommand(ptr->ip, "vwait", ip_rbVwaitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"vwait\")");
- Tcl_CreateCommand(ptr->ip, "vwait", ip_rbVwaitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- /* replace 'tkwait' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"tkwait\")");
- Tcl_CreateObjCommand(ptr->ip, "tkwait", ip_rbTkWaitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"tkwait\")");
- Tcl_CreateCommand(ptr->ip, "tkwait", ip_rbTkWaitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- /* add 'thread_vwait' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"thread_vwait\")");
- Tcl_CreateObjCommand(ptr->ip, "thread_vwait", ip_rb_threadVwaitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"thread_vwait\")");
- Tcl_CreateCommand(ptr->ip, "thread_vwait", ip_rb_threadVwaitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- /* add 'thread_tkwait' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"thread_tkwait\")");
- Tcl_CreateObjCommand(ptr->ip, "thread_tkwait", ip_rb_threadTkWaitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"thread_tkwait\")");
- Tcl_CreateCommand(ptr->ip, "thread_tkwait", ip_rb_threadTkWaitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- Tk_Release((ClientData)mainWin);
-
- return self;
-}
-
-static VALUE
-ip_create_slave(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- struct tcltkip *master = get_ip(self);
- struct tcltkip *slave = ALLOC(struct tcltkip);
- VALUE safemode;
- VALUE name;
- int safe;
- int thr_crit_bup;
- Tk_Window mainWin;
-
- /* safe-mode check */
- if (rb_scan_args(argc, argv, "11", &name, &safemode) == 1) {
- safemode = Qfalse;
- }
- if (Tcl_IsSafe(master->ip) == 1) {
- safe = 1;
- } else if (safemode == Qfalse || NIL_P(safemode)) {
- safe = 0;
- rb_secure(4);
- } else {
- safe = 1;
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(master->ip)) {
- DUMP1("master-ip is deleted");
- rb_thread_critical = thr_crit_bup;
- rb_raise(rb_eRuntimeError, "deleted master cannot create a new slave interpreter");
- }
-
- /* create slave-ip */
- slave->ref_count = 0;
- slave->allow_ruby_exit = 0;
- slave->return_value = 0;
-
- slave->ip = Tcl_CreateSlave(master->ip, StringValuePtr(name), safe);
- if (slave->ip == NULL) {
- rb_thread_critical = thr_crit_bup;
- rb_raise(rb_eRuntimeError, "fail to create the new slave interpreter");
- }
- rbtk_preserve_ip(slave);
-
- slave->has_orig_exit
- = Tcl_GetCommandInfo(slave->ip, "exit", &(slave->orig_exit_info));
-
- /* replace 'exit' command --> 'interp_exit' command */
- mainWin = Tk_MainWindow(slave->ip);
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"interp_exit\"");
- Tcl_CreateObjCommand(slave->ip, "exit", ip_InterpExitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"exit\") --> \"interp_exit\"");
- Tcl_CreateCommand(slave->ip, "exit", ip_InterpExitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- rb_thread_critical = thr_crit_bup;
-
- return Data_Wrap_Struct(CLASS_OF(self), 0, ip_free, slave);
-}
-
-/* make ip "safe" */
-static VALUE
-ip_make_safe(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
- Tk_Window mainWin;
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- rb_raise(rb_eRuntimeError, "interpreter is deleted");
- }
-
- if (Tcl_MakeSafe(ptr->ip) == TCL_ERROR) {
-#if TCL_MAJOR_VERSION >= 8
- rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
-#endif
- }
-
- ptr->allow_ruby_exit = 0;
-
- /* replace 'exit' command --> 'interp_exit' command */
- mainWin = Tk_MainWindow(ptr->ip);
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"interp_exit\"");
- Tcl_CreateObjCommand(ptr->ip, "exit", ip_InterpExitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"exit\") --> \"interp_exit\"");
- Tcl_CreateCommand(ptr->ip, "exit", ip_InterpExitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- return self;
-}
-
-/* is safe? */
-static VALUE
-ip_is_safe_p(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- rb_raise(rb_eRuntimeError, "interpreter is deleted");
- }
-
- if (Tcl_IsSafe(ptr->ip)) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-/* allow_ruby_exit? */
-static VALUE
-ip_allow_ruby_exit_p(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- rb_raise(rb_eRuntimeError, "interpreter is deleted");
- }
-
- if (ptr->allow_ruby_exit) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-/* allow_ruby_exit = mode */
-static VALUE
-ip_allow_ruby_exit_set(self, val)
- VALUE self, val;
-{
- struct tcltkip *ptr = get_ip(self);
- Tk_Window mainWin;
-
- rb_secure(4);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- rb_raise(rb_eRuntimeError, "interpreter is deleted");
- }
-
- if (Tcl_IsSafe(ptr->ip)) {
- rb_raise(rb_eSecurityError,
- "insecure operation on a safe interpreter");
- }
-
- mainWin = Tk_MainWindow(ptr->ip);
-
- if (RTEST(val)) {
- ptr->allow_ruby_exit = 1;
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"ruby_exit\"");
- Tcl_CreateObjCommand(ptr->ip, "exit", ip_RubyExitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"exit\") --> \"ruby_exit\"");
- Tcl_CreateCommand(ptr->ip, "exit", ip_RubyExitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
- return Qtrue;
-
- } else {
- ptr->allow_ruby_exit = 0;
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"interp_exit\"");
- Tcl_CreateObjCommand(ptr->ip, "exit", ip_InterpExitObjCmd,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tcl_CreateCommand(\"exit\") --> \"interp_exit\"");
- Tcl_CreateCommand(ptr->ip, "exit", ip_InterpExitCommand,
- (ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
-#endif
- return Qfalse;
- }
-}
-
-/* delete interpreter */
-static VALUE
-ip_delete(self)
- VALUE self;
-{
- Tcl_CmdInfo info;
- struct tcltkip *ptr = get_ip(self);
-
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
-
- DUMP1("delete slaves");
- delete_slaves(ptr->ip);
-
- DUMP1("finalize operation");
- if (Tcl_Eval(ptr->ip, DEF_CANCEL_AFTER_SCRIPTS_PROC) == TCL_OK) {
- if (Tcl_GetCommandInfo(ptr->ip, CANCEL_AFTER_SCRIPTS, &info)) {
- DUMP2("call cancel after scripts proc '%s'",
- CANCEL_AFTER_SCRIPTS);
- Tcl_Eval(ptr->ip, CANCEL_AFTER_SCRIPTS);
- }
- }
-
- if (Tcl_GetCommandInfo(ptr->ip, finalize_hook_name, &info)) {
- DUMP2("call finalize hook proc '%s'", finalize_hook_name);
- Tcl_Eval(ptr->ip, finalize_hook_name);
- }
-
- del_root(ptr->ip);
-
- DUMP1("delete interp");
- /* while(!rbtk_InterpDeleted(ptr->ip)) { */
- if (!Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("wait ip is deleted");
- Tcl_DeleteInterp(ptr->ip);
- }
-
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
-
- return Qnil;
-}
-
-/* is deleted? */
-static int
-ip_null_namespace(interp)
- Tcl_Interp *interp;
-{
-#if TCL_MAJOR_VERSION < 8
- return 0;
-#else /* support Namespace */
- return ( Tcl_GetCurrentNamespace(interp) == (Tcl_Namespace *)NULL );
-#endif
-}
-
-static VALUE
-ip_has_null_namespace_p(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (ip_null_namespace(ptr->ip)) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-static VALUE
-ip_is_deleted_p(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_InterpDeleted(ptr->ip)) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-
-static VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-create_ip_exc(VALUE interp, VALUE exc, const char *fmt, ...)
-#else
-create_ip_exc(interp, exc, fmt, va_alist)
- VALUE interp:
- VALUE exc;
- const char *fmt;
- va_dcl
-#endif
-{
- va_list args;
- char buf[BUFSIZ];
- VALUE einfo;
-
- va_init_list(args,fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- buf[BUFSIZ - 1] = '\0';
- va_end(args);
- einfo = rb_exc_new2(exc, buf);
- rb_ivar_set(einfo, ID_at_interp, interp);
- Tcl_ResetResult(get_ip(interp)->ip);
-
- return einfo;
-}
-
-static VALUE
-ip_get_result_string_obj(interp)
- Tcl_Interp *interp;
-{
-#if TCL_MAJOR_VERSION >= 8
- int len;
- char *s;
-
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- s = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len);
- if (s == (char*)NULL) {
- return rb_tainted_str_new2("");
- } else {
- return(rb_tainted_str_new(s, len));
- }
-
-# else /* TCL_VERSION >= 8.1 */
- volatile VALUE strval;
- Tcl_Obj *retobj = Tcl_GetObjResult(interp);
- int thr_crit_bup;
-
- Tcl_IncrRefCount(retobj);
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (Tcl_GetCharLength(retobj) != Tcl_UniCharLen(Tcl_GetUnicode(retobj))) {
- /* possibly binary string */
- s = Tcl_GetByteArrayFromObj(retobj, &len);
- if (s == (char*)NULL) {
- strval = rb_tainted_str_new2("");
- } else {
- strval = rb_tainted_str_new(s, len);
- }
- rb_ivar_set(strval, ID_at_enc, rb_str_new2("binary"));
- } else {
- /* possibly text string */
- s = Tcl_GetStringFromObj(retobj, &len);
- if (s == (char*)NULL) {
- strval = rb_tainted_str_new2("");
- } else {
- strval = rb_tainted_str_new(s, len);
- }
- }
-
- rb_thread_critical = thr_crit_bup;
-
- Tcl_DecrRefCount(retobj);
-
- return(strval);
-
-# endif
-#else /* TCL_MAJOR_VERSION < 8 */
- return(rb_tainted_str_new2(interp->result));
-#endif
-}
-
-/* eval string in tcl by Tcl_Eval() */
-static VALUE
-ip_eval_real(self, cmd_str, cmd_len)
- VALUE self;
- char *cmd_str;
- int cmd_len;
-{
- volatile VALUE ret;
- char *s;
- int len;
- struct tcltkip *ptr = get_ip(self);
- int thr_crit_bup;
-
-#if TCL_MAJOR_VERSION >= 8
- /* call Tcl_EvalObj() */
- {
- Tcl_Obj *cmd;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- cmd = Tcl_NewStringObj(cmd_str, cmd_len);
- Tcl_IncrRefCount(cmd);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- Tcl_DecrRefCount(cmd);
- rb_thread_critical = thr_crit_bup;
- ptr->return_value = TCL_OK;
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
-
- ptr->return_value = Tcl_EvalObj(ptr->ip, cmd);
- /* ptr->return_value = Tcl_GlobalEvalObj(ptr->ip, cmd); */
- }
-
- Tcl_DecrRefCount(cmd);
-
- }
-
- if (ptr->return_value == TCL_ERROR) {
- volatile VALUE exc;
- exc = create_ip_exc(self, rb_eRuntimeError,
- "%s", Tcl_GetStringResult(ptr->ip));
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
-
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
- DUMP2("(TCL_Eval result) %d", ptr->return_value);
-
- /* pass back the result (as string) */
- ret = ip_get_result_string_obj(ptr->ip);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- return ret;
-
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP2("Tcl_Eval(%s)", cmd_str);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- ptr->return_value = TCL_OK;
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ptr->return_value = Tcl_Eval(ptr->ip, cmd_str);
- /* ptr->return_value = Tcl_GlobalEval(ptr->ip, cmd_str); */
- }
-
- if (ptr->return_value == TCL_ERROR) {
- volatile VALUE exc;
- exc = create_ip_exc(self, rb_eRuntimeError, "%s", ptr->ip->result);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_exc_raise(exc);
- }
- DUMP2("(TCL_Eval result) %d", ptr->return_value);
-
- /* pass back the result (as string) */
- ret = ip_get_result_string_obj(ptr->ip);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- return ret;
-#endif
-}
-
-static VALUE
-evq_safelevel_handler(arg, evq)
- VALUE arg;
- VALUE evq;
-{
- struct eval_queue *q;
-
- Data_Get_Struct(evq, struct eval_queue, q);
- DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
- rb_set_safe_level(q->safe_level);
- return ip_eval_real(q->interp, q->str, q->len);
-}
-
-int eval_queue_handler _((Tcl_Event *, int));
-int
-eval_queue_handler(evPtr, flags)
- Tcl_Event *evPtr;
- int flags;
-{
- struct eval_queue *q = (struct eval_queue *)evPtr;
- volatile VALUE ret;
- volatile VALUE q_dat;
-
- DUMP2("do_eval_queue_handler : evPtr = %p", evPtr);
- DUMP2("eval queue_thread : %lx", rb_thread_current());
- DUMP2("added by thread : %lx", q->thread);
-
- if (*(q->done)) {
- DUMP1("processed by another event-loop");
- return 0;
- } else {
- DUMP1("process it on current event-loop");
- }
-
- /* process it */
- *(q->done) = 1;
-
- /* check safe-level */
- if (rb_safe_level() != q->safe_level) {
-#ifdef HAVE_NATIVETHREAD
- if (!is_ruby_native_thread()) {
- rb_bug("cross-thread violation on eval_queue_handler()");
- }
-#endif
- /* q_dat = Data_Wrap_Struct(rb_cData,0,0,q); */
- q_dat = Data_Wrap_Struct(rb_cData,eval_queue_mark,0,q);
- ret = rb_funcall(rb_proc_new(evq_safelevel_handler, q_dat),
- ID_call, 0);
- rb_gc_force_recycle(q_dat);
- } else {
- DUMP2("call eval_real (for caller thread:%lx)", q->thread);
- DUMP2("call eval_real (current thread:%lx)", rb_thread_current());
- ret = ip_eval_real(q->interp, q->str, q->len);
- }
-
- /* set result */
- RARRAY(q->result)->ptr[0] = ret;
-
- /* complete */
- *(q->done) = -1;
-
- /* back to caller */
- DUMP2("back to caller (caller thread:%lx)", q->thread);
- DUMP2(" (current thread:%lx)", rb_thread_current());
- rb_thread_run(q->thread);
- DUMP1("finish back to caller");
-
- /* end of handler : remove it */
- return 1;
-}
-
-static VALUE
-ip_eval(self, str)
- VALUE self;
- VALUE str;
-{
- struct eval_queue *evq;
- char *eval_str;
- int *alloc_done;
- int thr_crit_bup;
- volatile VALUE current = rb_thread_current();
- volatile VALUE ip_obj = self;
- volatile VALUE result;
- volatile VALUE ret;
- Tcl_QueuePosition position;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
- StringValue(str);
- rb_thread_critical = thr_crit_bup;
-
- if (eventloop_thread == 0 || current == eventloop_thread) {
- if (eventloop_thread) {
- DUMP2("eval from current eventloop %lx", current);
- } else {
- DUMP2("eval from thread:%lx but no eventloop", current);
- }
- result = ip_eval_real(self, RSTRING(str)->ptr, RSTRING(str)->len);
- if (rb_obj_is_kind_of(result, rb_eException)) {
- rb_exc_raise(result);
- }
- return result;
- }
-
- DUMP2("eval from thread %lx (NOT current eventloop)", current);
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* allocate memory (protected from Tcl_ServiceEvent) */
- alloc_done = (int*)ALLOC(int);
- *alloc_done = 0;
-
- eval_str = ALLOC_N(char, RSTRING(str)->len + 1);
- strncpy(eval_str, RSTRING(str)->ptr, RSTRING(str)->len);
- eval_str[RSTRING(str)->len] = 0;
-
- /* allocate memory (freed by Tcl_ServiceEvent) */
- evq = (struct eval_queue *)Tcl_Alloc(sizeof(struct eval_queue));
- Tcl_Preserve(evq);
-
- /* allocate result obj */
- result = rb_ary_new2(1);
- RARRAY(result)->ptr[0] = Qnil;
- RARRAY(result)->len = 1;
-
- /* construct event data */
- evq->done = alloc_done;
- evq->str = eval_str;
- evq->len = RSTRING(str)->len;
- evq->interp = ip_obj;
- evq->result = result;
- evq->thread = current;
- evq->safe_level = rb_safe_level();
- evq->ev.proc = eval_queue_handler;
- position = TCL_QUEUE_TAIL;
-
- /* add the handler to Tcl event queue */
- DUMP1("add handler");
- Tcl_QueueEvent(&(evq->ev), position);
-
- rb_thread_critical = thr_crit_bup;
-
- /* wait for the handler to be processed */
- DUMP2("wait for handler (current thread:%lx)", current);
- while(*alloc_done >= 0) {
- rb_thread_stop();
- }
- DUMP2("back from handler (current thread:%lx)", current);
-
- /* get result & free allocated memory */
- ret = RARRAY(result)->ptr[0];
-
- free(alloc_done);
- free(eval_str);
- Tcl_Release(evq);
-
- if (rb_obj_is_kind_of(ret, rb_eException)) {
- rb_exc_raise(ret);
- }
-
- return ret;
-}
-
-
-/* restart Tk */
-static VALUE
-lib_restart(self)
- VALUE self;
-{
- volatile VALUE exc;
- struct tcltkip *ptr = get_ip(self);
- int thr_crit_bup;
-
- rb_secure(4);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- rb_raise(rb_eRuntimeError, "interpreter is deleted");
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
-
- /* destroy the root wdiget */
- ptr->return_value = Tcl_Eval(ptr->ip, "destroy .");
- /* ignore ERROR */
- DUMP2("(TCL_Eval result) %d", ptr->return_value);
- Tcl_ResetResult(ptr->ip);
-
- /* delete namespace ( tested on tk8.4.5 ) */
- ptr->return_value = Tcl_Eval(ptr->ip, "namespace delete ::tk::msgcat");
- /* ignore ERROR */
- DUMP2("(TCL_Eval result) %d", ptr->return_value);
- Tcl_ResetResult(ptr->ip);
-
- /* delete trace proc ( tested on tk8.4.5 ) */
- ptr->return_value = Tcl_Eval(ptr->ip, "trace vdelete ::tk_strictMotif w ::tk::EventMotifBindings");
- /* ignore ERROR */
- DUMP2("(TCL_Eval result) %d", ptr->return_value);
- Tcl_ResetResult(ptr->ip);
-
- /* execute Tk_Init of Tk_SafeInit */
-#if TCL_MAJOR_VERSION >= 8
- if (Tcl_IsSafe(ptr->ip)) {
- DUMP1("Tk_SafeInit");
- if (Tk_SafeInit(ptr->ip) == TCL_ERROR) {
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
- } else {
- DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
- exc = rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_exc_raise(exc);
- }
-#endif
-
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
-
- rb_thread_critical = thr_crit_bup;
-
- return Qnil;
-}
-
-
-static VALUE
-ip_restart(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- rb_secure(4);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- rb_raise(rb_eRuntimeError, "interpreter is deleted");
- }
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return Qnil;
- }
- return lib_restart(self);
-}
-
-static VALUE
-lib_toUTF8_core(ip_obj, src, encodename)
- VALUE ip_obj;
- VALUE src;
- VALUE encodename;
-{
- volatile VALUE str = src;
-
-#ifdef TCL_UTF_MAX
- Tcl_Interp *interp;
- Tcl_Encoding encoding;
- Tcl_DString dstr;
- int taint_flag = OBJ_TAINTED(str);
- struct tcltkip *ptr;
- char *buf;
- int thr_crit_bup;
-
- if (NIL_P(ip_obj)) {
- interp = (Tcl_Interp *)NULL;
- } else {
- interp = get_ip(ip_obj)->ip;
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(interp)) {
- DUMP1("ip is deleted");
- interp = (Tcl_Interp *)NULL;
- }
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (NIL_P(encodename)) {
- if (TYPE(str) == T_STRING) {
- volatile VALUE enc;
-
- enc = Qnil;
- if (RTEST(rb_ivar_defined(str, ID_at_enc))) {
- enc = rb_ivar_get(str, ID_at_enc);
- }
- if (NIL_P(enc)) {
- if (NIL_P(ip_obj)) {
- encoding = (Tcl_Encoding)NULL;
- } else {
- if (RTEST(rb_ivar_defined(ip_obj, ID_at_enc))) {
- enc = rb_ivar_get(ip_obj, ID_at_enc);
- }
- if (NIL_P(enc)) {
- encoding = (Tcl_Encoding)NULL;
- } else {
- StringValue(enc);
- encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr);
- if (encoding == (Tcl_Encoding)NULL) {
- rb_warning("Tk-interp has unknown encoding information (@encoding:'%s')", RSTRING(enc)->ptr);
- }
- }
- }
- } else {
- StringValue(enc);
- if (strcmp(RSTRING(enc)->ptr, "binary") == 0) {
- rb_thread_critical = thr_crit_bup;
- return str;
- }
- encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr);
- if (encoding == (Tcl_Encoding)NULL) {
- rb_warning("string has unknown encoding information (@encoding:'%s')", RSTRING(enc)->ptr);
- }
- }
- } else {
- encoding = (Tcl_Encoding)NULL;
- }
- } else {
- StringValue(encodename);
- encoding = Tcl_GetEncoding(interp, RSTRING(encodename)->ptr);
- if (encoding == (Tcl_Encoding)NULL) {
- /*
- rb_warning("unknown encoding name '%s'",
- RSTRING(encodename)->ptr);
- */
- rb_raise(rb_eArgError, "unknown encoding name '%s'",
- RSTRING(encodename)->ptr);
- }
- }
-
- StringValue(str);
- if (!RSTRING(str)->len) {
- rb_thread_critical = thr_crit_bup;
- return str;
- }
-
- buf = ALLOC_N(char,(RSTRING(str)->len)+1);
- strncpy(buf, RSTRING(str)->ptr, RSTRING(str)->len);
- buf[RSTRING(str)->len] = 0;
-
- Tcl_DStringInit(&dstr);
- Tcl_DStringFree(&dstr);
- /* Tcl_ExternalToUtfDString(encoding,buf,strlen(buf),&dstr); */
- Tcl_ExternalToUtfDString(encoding, buf, RSTRING(str)->len, &dstr);
-
- /* str = rb_tainted_str_new2(Tcl_DStringValue(&dstr)); */
- str = rb_str_new2(Tcl_DStringValue(&dstr));
- rb_ivar_set(str, ID_at_enc, rb_tainted_str_new2("utf-8"));
- if (taint_flag) OBJ_TAINT(str);
-
- if (encoding != (Tcl_Encoding)NULL) {
- Tcl_FreeEncoding(encoding);
- }
- Tcl_DStringFree(&dstr);
-
- free(buf);
-
- rb_thread_critical = thr_crit_bup;
-#endif
-
- return str;
-}
-
-static VALUE
-lib_toUTF8(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE str, encodename;
-
- if (rb_scan_args(argc, argv, "11", &str, &encodename) == 1) {
- encodename = Qnil;
- }
- return lib_toUTF8_core(Qnil, str, encodename);
-}
-
-static VALUE
-ip_toUTF8(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE str, encodename;
-
- if (rb_scan_args(argc, argv, "11", &str, &encodename) == 1) {
- encodename = Qnil;
- }
- return lib_toUTF8_core(self, str, encodename);
-}
-
-static VALUE
-lib_fromUTF8_core(ip_obj, src, encodename)
- VALUE ip_obj;
- VALUE src;
- VALUE encodename;
-{
- volatile VALUE str = src;
-
-#ifdef TCL_UTF_MAX
- Tcl_Interp *interp;
- Tcl_Encoding encoding;
- Tcl_DString dstr;
- int taint_flag = OBJ_TAINTED(str);
- char *buf;
- int thr_crit_bup;
-
- if (NIL_P(ip_obj)) {
- interp = (Tcl_Interp *)NULL;
- } else {
- interp = get_ip(ip_obj)->ip;
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- if (NIL_P(encodename)) {
- volatile VALUE enc;
-
- if (TYPE(str) == T_STRING) {
- enc = Qnil;
- if (RTEST(rb_ivar_defined(str, ID_at_enc))) {
- enc = rb_ivar_get(str, ID_at_enc);
- }
- if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) {
- rb_thread_critical = thr_crit_bup;
- return str;
- }
- }
-
- if (NIL_P(ip_obj)) {
- encoding = (Tcl_Encoding)NULL;
- } else {
- enc = Qnil;
- if (RTEST(rb_ivar_defined(ip_obj, ID_at_enc))) {
- enc = rb_ivar_get(ip_obj, ID_at_enc);
- }
- if (NIL_P(enc)) {
- encoding = (Tcl_Encoding)NULL;
- } else {
- StringValue(enc);
- encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr);
- if (encoding == (Tcl_Encoding)NULL) {
- rb_warning("Tk-interp has unknown encoding information (@encoding:'%s')", RSTRING(enc)->ptr);
- } else {
- encodename = rb_obj_dup(enc);
- }
- }
- }
-
- } else {
- StringValue(encodename);
-
- if (strcmp(RSTRING(encodename)->ptr, "binary") == 0) {
- char *s;
- int len;
-
- s = Tcl_GetByteArrayFromObj(Tcl_NewStringObj(RSTRING(str)->ptr,
- RSTRING(str)->len),
- &len);
- str = rb_tainted_str_new(s, len);
- rb_ivar_set(str, ID_at_enc, rb_tainted_str_new2("binary"));
-
- rb_thread_critical = thr_crit_bup;
- return str;
- }
-
- encoding = Tcl_GetEncoding(interp, RSTRING(encodename)->ptr);
- if (encoding == (Tcl_Encoding)NULL) {
- /*
- rb_warning("unknown encoding name '%s'",
- RSTRING(encodename)->ptr);
- encodename = Qnil;
- */
- rb_raise(rb_eArgError, "unknown encoding name '%s'",
- RSTRING(encodename)->ptr);
- }
- }
-
- StringValue(str);
-
- if (RSTRING(str)->len == 0) {
- rb_thread_critical = thr_crit_bup;
- return rb_tainted_str_new2("");
- }
-
- buf = ALLOC_N(char,strlen(RSTRING(str)->ptr)+1);
- strncpy(buf, RSTRING(str)->ptr, RSTRING(str)->len);
- buf[RSTRING(str)->len] = 0;
-
- Tcl_DStringInit(&dstr);
- Tcl_DStringFree(&dstr);
- /* Tcl_UtfToExternalDString(encoding,buf,strlen(buf),&dstr); */
- Tcl_UtfToExternalDString(encoding,buf,RSTRING(str)->len,&dstr);
-
- /* str = rb_tainted_str_new2(Tcl_DStringValue(&dstr)); */
- str = rb_str_new2(Tcl_DStringValue(&dstr));
- rb_ivar_set(str, ID_at_enc, encodename);
-
- if (taint_flag) OBJ_TAINT(str);
-
- if (encoding != (Tcl_Encoding)NULL) {
- Tcl_FreeEncoding(encoding);
- }
- Tcl_DStringFree(&dstr);
-
- free(buf);
-
- rb_thread_critical = thr_crit_bup;
-#endif
-
- return str;
-}
-
-static VALUE
-lib_fromUTF8(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE str, encodename;
-
- if (rb_scan_args(argc, argv, "11", &str, &encodename) == 1) {
- encodename = Qnil;
- }
- return lib_fromUTF8_core(Qnil, str, encodename);
-}
-
-static VALUE
-ip_fromUTF8(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE str, encodename;
-
- if (rb_scan_args(argc, argv, "11", &str, &encodename) == 1) {
- encodename = Qnil;
- }
- return lib_fromUTF8_core(self, str, encodename);
-}
-
-static VALUE
-lib_UTF_backslash_core(self, str, all_bs)
- VALUE self;
- VALUE str;
- int all_bs;
-{
-#ifdef TCL_UTF_MAX
- char *src_buf, *dst_buf, *ptr;
- int read_len = 0, dst_len = 0;
- int taint_flag = OBJ_TAINTED(str);
- int thr_crit_bup;
-
- StringValue(str);
- if (!RSTRING(str)->len) {
- return str;
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- src_buf = ALLOC_N(char,(RSTRING(str)->len)+1);
- strncpy(src_buf, RSTRING(str)->ptr, RSTRING(str)->len);
- src_buf[RSTRING(str)->len] = 0;
-
- dst_buf = ALLOC_N(char,(RSTRING(str)->len)+1);
-
- ptr = src_buf;
- while(RSTRING(str)->len > ptr - src_buf) {
- if (*ptr == '\\' && (all_bs || *(ptr + 1) == 'u')) {
- dst_len += Tcl_UtfBackslash(ptr, &read_len, (dst_buf + dst_len));
- ptr += read_len;
- } else {
- *(dst_buf + (dst_len++)) = *(ptr++);
- }
- }
-
- str = rb_str_new(dst_buf, dst_len);
- if (taint_flag) OBJ_TAINT(str);
-
- free(src_buf);
- free(dst_buf);
-
- rb_thread_critical = thr_crit_bup;
-#endif
-
- return str;
-}
-
-static VALUE
-lib_UTF_backslash(self, str)
- VALUE self;
- VALUE str;
-{
- return lib_UTF_backslash_core(self, str, 0);
-}
-
-static VALUE
-lib_Tcl_backslash(self, str)
- VALUE self;
- VALUE str;
-{
- return lib_UTF_backslash_core(self, str, 1);
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static VALUE
-ip_invoke_core(interp, objc, objv)
- VALUE interp;
- int objc;
- Tcl_Obj **objv;
-#else
-static VALUE
-ip_invoke_core(interp, argc, argv)
- VALUE interp;
- int argc;
- char **argv;
-#endif
-{
- struct tcltkip *ptr;
- int i;
- Tcl_CmdInfo info;
- char *cmd;
- char *s;
- int len;
- int thr_crit_bup;
-
-#if TCL_MAJOR_VERSION >= 8
- int argc = objc;
- char **argv = (char **)NULL;
- Tcl_Obj *resultPtr;
-#endif
-
- /* get the command name string */
-#if TCL_MAJOR_VERSION >= 8
- cmd = Tcl_GetStringFromObj(objv[0], &len);
-#else /* TCL_MAJOR_VERSION < 8 */
- cmd = argv[0];
-#endif
-
- /* get the data struct */
- ptr = get_ip(interp);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- return rb_tainted_str_new2("");
- }
-
- /* map from the command name to a C procedure */
- DUMP2("call Tcl_GetCommandInfo, %s", cmd);
- if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) {
- DUMP1("error Tcl_GetCommandInfo");
- /* if (event_loop_abort_on_exc || cmd[0] != '.') { */
- if (event_loop_abort_on_exc > 0) {
- /*rb_ip_raise(obj,rb_eNameError,"invalid command name `%s'",cmd);*/
- return create_ip_exc(interp, rb_eNameError,
- "invalid command name `%s'", cmd);
- } else {
- if (event_loop_abort_on_exc < 0) {
- rb_warning("invalid command name `%s' (ignore)", cmd);
- } else {
- rb_warn("invalid command name `%s' (ignore)", cmd);
- }
- Tcl_ResetResult(ptr->ip);
- return rb_tainted_str_new2("");
- }
- }
- DUMP1("end Tcl_GetCommandInfo");
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* memory allocation for arguments of this command */
-#if TCL_MAJOR_VERSION >= 8
- if (!info.isNativeObjectProc) {
- /* string interface */
- argv = (char **)ALLOC_N(char *, argc+1);
- for (i = 0; i < argc; ++i) {
- argv[i] = Tcl_GetStringFromObj(objv[i], &len);
- }
- argv[argc] = (char *)NULL;
- }
-#endif
-
- Tcl_ResetResult(ptr->ip);
-
- /* Invoke the C procedure */
-#if TCL_MAJOR_VERSION >= 8
- if (info.isNativeObjectProc) {
- ptr->return_value = (*info.objProc)(info.objClientData, ptr->ip,
- objc, objv);
-#if 0
- /* get the string value from the result object */
- resultPtr = Tcl_GetObjResult(ptr->ip);
- Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &len),
- TCL_VOLATILE);
-#endif
- }
- else
-#endif
- {
-#if TCL_MAJOR_VERSION >= 8
- ptr->return_value = (*info.proc)(info.clientData, ptr->ip,
- argc, (CONST84 char **)argv);
-
- free(argv);
-
-#else /* TCL_MAJOR_VERSION < 8 */
- ptr->return_value = (*info.proc)(info.clientData, ptr->ip,
- argc, argv);
-#endif
- }
-
- rb_thread_critical = thr_crit_bup;
-
- /* exception on mainloop */
- if (ptr->return_value == TCL_ERROR) {
- if (event_loop_abort_on_exc > 0 && !Tcl_InterpDeleted(ptr->ip)) {
-#if TCL_MAJOR_VERSION >= 8
- return create_ip_exc(interp, rb_eRuntimeError,
- "%s", Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- return create_ip_exc(interp, rb_eRuntimeError,
- "%s", ptr->ip->result);
-#endif
- } else {
- if (event_loop_abort_on_exc < 0) {
-#if TCL_MAJOR_VERSION >= 8
- rb_warning("%s (ignore)", Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- rb_warning("%s (ignore)", ptr->ip->result);
-#endif
- } else {
-#if TCL_MAJOR_VERSION >= 8
- rb_warn("%s (ignore)", Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- rb_warn("%s (ignore)", ptr->ip->result);
-#endif
- }
- Tcl_ResetResult(ptr->ip);
- return rb_tainted_str_new2("");
- }
- }
-
- /* pass back the result (as string) */
- return ip_get_result_string_obj(ptr->ip);
-}
-
-
-#if TCL_MAJOR_VERSION >= 8
-static Tcl_Obj **
-#else /* TCL_MAJOR_VERSION < 8 */
-static char **
-#endif
-alloc_invoke_arguments(argc, argv)
- int argc;
- VALUE *argv;
-{
- int i;
- VALUE v;
- char *s;
- int thr_crit_bup;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_Obj **av = (Tcl_Obj **)NULL;
- Tcl_Obj *resultPtr;
-#else /* TCL_MAJOR_VERSION < 8 */
- char **av = (char **)NULL;
-#endif
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* memory allocation */
-#if TCL_MAJOR_VERSION >= 8
- av = (Tcl_Obj **)ALLOC_N(Tcl_Obj *, argc+1);
- for (i = 0; i < argc; ++i) {
- VALUE enc;
-
- v = argv[i];
- s = StringValuePtr(v);
-
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- av[i] = Tcl_NewStringObj(s, RSTRING(v)->len);
-# else /* TCL_VERSION >= 8.1 */
- enc = Qnil;
- if (RTEST(rb_ivar_defined(v, ID_at_enc))) {
- enc = rb_ivar_get(v, ID_at_enc);
- }
- if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) {
- /* binary string */
- av[i] = Tcl_NewByteArrayObj(s, RSTRING(v)->len);
- } else if (strlen(s) != RSTRING(v)->len) {
- /* probably binary string */
- av[i] = Tcl_NewByteArrayObj(s, RSTRING(v)->len);
- } else {
- /* probably text string */
- av[i] = Tcl_NewStringObj(s, RSTRING(v)->len);
- }
-# endif
- Tcl_IncrRefCount(av[i]);
- }
- av[argc] = (Tcl_Obj *)NULL;
-
-#else /* TCL_MAJOR_VERSION < 8 */
- /* string interface */
- av = (char **)ALLOC_N(char *, argc+1);
- for (i = 0; i < argc; ++i) {
- v = argv[i];
- s = StringValuePtr(v);
- av[i] = ALLOC_N(char, strlen(s)+1);
- strcpy(av[i], s);
- }
- av[argc] = (char *)NULL;
-#endif
-
- rb_thread_critical = thr_crit_bup;
-
- return av;
-}
-
-static void
-free_invoke_arguments(argc, av)
- int argc;
-#if TCL_MAJOR_VERSION >= 8
- Tcl_Obj **av;
-#else /* TCL_MAJOR_VERSION < 8 */
- char **av;
-#endif
-{
- int i;
-
- for (i = 0; i < argc; ++i) {
-#if TCL_MAJOR_VERSION >= 8
- Tcl_DecrRefCount(av[i]);
-#else /* TCL_MAJOR_VERSION < 8 */
- free(av[i]);
-#endif
- }
- free(av);
-}
-
-static VALUE
-ip_invoke_real(argc, argv, interp)
- int argc;
- VALUE *argv;
- VALUE interp;
-{
- VALUE v;
- struct tcltkip *ptr; /* tcltkip data struct */
- int i;
- Tcl_CmdInfo info;
- char *s;
- int len;
- int thr_crit_bup;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_Obj **av = (Tcl_Obj **)NULL;
- Tcl_Obj *resultPtr;
-#else /* TCL_MAJOR_VERSION < 8 */
- char **av = (char **)NULL;
-#endif
-
- DUMP2("invoke_real called by thread:%lx", rb_thread_current());
-
- /* allocate memory for arguments */
- av = alloc_invoke_arguments(argc, argv);
-
- /* get the data struct */
- ptr = get_ip(interp);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return rb_tainted_str_new2("");
- }
-
- /* Invoke the C procedure */
- Tcl_ResetResult(ptr->ip);
- v = ip_invoke_core(interp, argc, av);
-
- /* free allocated memory */
- free_invoke_arguments(argc, av);
-
- return v;
-}
-
-VALUE
-ivq_safelevel_handler(arg, ivq)
- VALUE arg;
- VALUE ivq;
-{
- struct invoke_queue *q;
-
- Data_Get_Struct(ivq, struct invoke_queue, q);
- DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
- rb_set_safe_level(q->safe_level);
- return ip_invoke_core(q->interp, q->argc, q->argv);
-}
-
-int invoke_queue_handler _((Tcl_Event *, int));
-int
-invoke_queue_handler(evPtr, flags)
- Tcl_Event *evPtr;
- int flags;
-{
- struct invoke_queue *q = (struct invoke_queue *)evPtr;
- volatile VALUE ret;
- volatile VALUE q_dat;
-
- DUMP2("do_invoke_queue_handler : evPtr = %p", evPtr);
- DUMP2("invoke queue_thread : %lx", rb_thread_current());
- DUMP2("added by thread : %lx", q->thread);
-
- if (*(q->done)) {
- DUMP1("processed by another event-loop");
- return 0;
- } else {
- DUMP1("process it on current event-loop");
- }
-
- /* process it */
- *(q->done) = 1;
-
- /* check safe-level */
- if (rb_safe_level() != q->safe_level) {
- /* q_dat = Data_Wrap_Struct(rb_cData,0,0,q); */
- q_dat = Data_Wrap_Struct(rb_cData,invoke_queue_mark,0,q);
- ret = rb_funcall(rb_proc_new(ivq_safelevel_handler, q_dat),
- ID_call, 0);
- rb_gc_force_recycle(q_dat);
- } else {
- DUMP2("call invoke_real (for caller thread:%lx)", q->thread);
- DUMP2("call invoke_real (current thread:%lx)", rb_thread_current());
- ret = ip_invoke_core(q->interp, q->argc, q->argv);
- }
-
- /* set result */
- RARRAY(q->result)->ptr[0] = ret;
-
- /* complete */
- *(q->done) = -1;
-
- /* back to caller */
- DUMP2("back to caller (caller thread:%lx)", q->thread);
- DUMP2(" (current thread:%lx)", rb_thread_current());
- rb_thread_run(q->thread);
- DUMP1("finish back to caller");
-
- /* end of handler : remove it */
- return 1;
-}
-
-static VALUE
-ip_invoke_with_position(argc, argv, obj, position)
- int argc;
- VALUE *argv;
- VALUE obj;
- Tcl_QueuePosition position;
-{
- struct invoke_queue *ivq;
- char *s;
- int len;
- int i;
- int *alloc_done;
- int thr_crit_bup;
- volatile VALUE current = rb_thread_current();
- volatile VALUE ip_obj = obj;
- volatile VALUE result;
- volatile VALUE ret;
-
-#if TCL_MAJOR_VERSION >= 8
- Tcl_Obj **av = (Tcl_Obj **)NULL;
-#else /* TCL_MAJOR_VERSION < 8 */
- char **av = (char **)NULL;
-#endif
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "command name missing");
- }
- if (eventloop_thread == 0 || current == eventloop_thread) {
- if (eventloop_thread) {
- DUMP2("invoke from current eventloop %lx", current);
- } else {
- DUMP2("invoke from thread:%lx but no eventloop", current);
- }
- result = ip_invoke_real(argc, argv, ip_obj);
- if (rb_obj_is_kind_of(result, rb_eException)) {
- rb_exc_raise(result);
- }
- return result;
- }
-
- DUMP2("invoke from thread %lx (NOT current eventloop)", current);
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- /* allocate memory (for arguments) */
- av = alloc_invoke_arguments(argc, argv);
-
- /* allocate memory (keep result) */
- alloc_done = (int*)ALLOC(int);
- *alloc_done = 0;
-
- /* allocate memory (freed by Tcl_ServiceEvent) */
- ivq = (struct invoke_queue *)Tcl_Alloc(sizeof(struct invoke_queue));
- Tcl_Preserve(ivq);
-
- /* allocate result obj */
- result = rb_ary_new2(1);
- RARRAY(result)->ptr[0] = Qnil;
- RARRAY(result)->len = 1;
-
- /* construct event data */
- ivq->done = alloc_done;
- ivq->argc = argc;
- ivq->argv = av;
- ivq->interp = ip_obj;
- ivq->result = result;
- ivq->thread = current;
- ivq->safe_level = rb_safe_level();
- ivq->ev.proc = invoke_queue_handler;
-
- /* add the handler to Tcl event queue */
- DUMP1("add handler");
- Tcl_QueueEvent(&(ivq->ev), position);
-
- rb_thread_critical = thr_crit_bup;
-
- /* wait for the handler to be processed */
- DUMP2("wait for handler (current thread:%lx)", current);
- while(*alloc_done >= 0) {
- rb_thread_stop();
- }
- DUMP2("back from handler (current thread:%lx)", current);
-
- /* get result & free allocated memory */
- ret = RARRAY(result)->ptr[0];
- free(alloc_done);
-
- Tcl_Release(ivq);
-
- /* free allocated memory */
- free_invoke_arguments(argc, av);
-
- /* exception? */
- if (rb_obj_is_kind_of(ret, rb_eException)) {
- DUMP1("raise exception");
- rb_exc_raise(ret);
- }
-
- DUMP1("exit ip_invoke");
- return ret;
-}
-
-
-/* get return code from Tcl_Eval() */
-static VALUE
-ip_retval(self)
- VALUE self;
-{
- struct tcltkip *ptr; /* tcltkip data struct */
-
- /* get the data strcut */
- ptr = get_ip(self);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- DUMP1("ip is deleted");
- return rb_tainted_str_new2("");
- }
-
- return (INT2FIX(ptr->return_value));
-}
-
-static VALUE
-ip_invoke(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- return ip_invoke_with_position(argc, argv, obj, TCL_QUEUE_TAIL);
-}
-
-static VALUE
-ip_invoke_immediate(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- return ip_invoke_with_position(argc, argv, obj, TCL_QUEUE_HEAD);
-}
-
-/* access Tcl variables */
-static VALUE
-ip_get_variable(self, varname_arg, flag_arg)
- VALUE self;
- VALUE varname_arg;
- VALUE flag_arg;
-{
- struct tcltkip *ptr = get_ip(self);
- int thr_crit_bup;
- volatile VALUE varname, flag;
-
- varname = varname_arg;
- flag = flag_arg;
-
- StringValue(varname);
-
-#if TCL_MAJOR_VERSION >= 8
- {
- Tcl_Obj *nameobj, *ret;
- char *s;
- int len;
- volatile VALUE strval;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- nameobj = Tcl_NewStringObj(RSTRING(varname)->ptr,
- RSTRING(varname)->len);
- Tcl_IncrRefCount(nameobj);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- Tcl_DecrRefCount(nameobj);
- rb_thread_critical = thr_crit_bup;
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ret = Tcl_ObjGetVar2(ptr->ip, nameobj, (Tcl_Obj*)NULL,
- FIX2INT(flag));
- }
-
- Tcl_DecrRefCount(nameobj);
-
- if (ret == (Tcl_Obj*)NULL) {
- volatile VALUE exc;
-#if TCL_MAJOR_VERSION >= 8
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- exc = rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
-#endif
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
-
- Tcl_IncrRefCount(ret);
-
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- s = Tcl_GetStringFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- Tcl_DecrRefCount(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- return(strval);
-
-# else /* TCL_VERSION >= 8.1 */
- if (Tcl_GetCharLength(ret)
- != Tcl_UniCharLen(Tcl_GetUnicode(ret))) {
- /* possibly binary string */
- s = Tcl_GetByteArrayFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- rb_ivar_set(strval, ID_at_enc, rb_tainted_str_new2("binary"));
- } else {
- /* possibly text string */
- s = Tcl_GetStringFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- }
-
- Tcl_DecrRefCount(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
-
- return(strval);
-# endif
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- {
- char *ret;
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ret = Tcl_GetVar2(ptr->ip, RSTRING(varname)->ptr,
- (char*)NULL, FIX2INT(flag));
- }
-
- if (ret == (char*)NULL) {
- volatile VALUE exc;
-#if TCL_MAJOR_VERSION >= 8
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- exc = rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
-#endif
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
-
- strval = rb_tainted_str_new2(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
-
- return(strval);
- }
-#endif
-}
-
-static VALUE
-ip_get_variable2(self, varname_arg, index_arg, flag_arg)
- VALUE self;
- VALUE varname_arg;
- VALUE index_arg;
- VALUE flag_arg;
-{
- struct tcltkip *ptr = get_ip(self);
- int thr_crit_bup;
- volatile VALUE varname, index, flag;
-
- if (NIL_P(index_arg)) {
- return ip_get_variable(self, varname_arg, flag_arg);
- }
-
- varname = varname_arg;
- index = index_arg;
- flag = flag_arg;
-
- StringValue(varname);
- StringValue(index);
-
-#if TCL_MAJOR_VERSION >= 8
- {
- Tcl_Obj *nameobj, *idxobj, *ret;
- char *s;
- int len;
- volatile VALUE strval;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- nameobj = Tcl_NewStringObj(RSTRING(varname)->ptr,
- RSTRING(varname)->len);
- Tcl_IncrRefCount(nameobj);
- idxobj = Tcl_NewStringObj(RSTRING(index)->ptr, RSTRING(index)->len);
- Tcl_IncrRefCount(idxobj);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- Tcl_DecrRefCount(nameobj);
- Tcl_DecrRefCount(idxobj);
- rb_thread_critical = thr_crit_bup;
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ret = Tcl_ObjGetVar2(ptr->ip, nameobj, idxobj, FIX2INT(flag));
- }
-
- Tcl_DecrRefCount(nameobj);
- Tcl_DecrRefCount(idxobj);
-
- if (ret == (Tcl_Obj*)NULL) {
- volatile VALUE exc;
-#if TCL_MAJOR_VERSION >= 8
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- exc = rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
-#endif
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
-
- Tcl_IncrRefCount(ret);
-
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- s = Tcl_GetStringFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- Tcl_DecrRefCount(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- return(strval);
-
-# else /* TCL_VERSION >= 8.1 */
- if (Tcl_GetCharLength(ret)
- != Tcl_UniCharLen(Tcl_GetUnicode(ret))) {
- /* possibly binary string */
- s = Tcl_GetByteArrayFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- rb_ivar_set(strval, ID_at_enc, rb_tainted_str_new2("binary"));
- } else {
- /* possibly text string */
- s = Tcl_GetStringFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- }
-
- Tcl_DecrRefCount(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
-
- return(strval);
-# endif
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- {
- char *ret;
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ret = Tcl_GetVar2(ptr->ip, RSTRING(varname)->ptr,
- RSTRING(index)->ptr, FIX2INT(flag));
- }
-
- if (ret == (char*)NULL) {
- volatile VALUE exc;
-#if TCL_MAJOR_VERSION >= 8
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- exc = rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
-#endif
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
-
- strval = rb_tainted_str_new2(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
-
- return(strval);
- }
-#endif
-}
-
-static VALUE
-ip_set_variable(self, varname_arg, value_arg, flag_arg)
- VALUE self;
- VALUE varname_arg;
- VALUE value_arg;
- VALUE flag_arg;
-{
- struct tcltkip *ptr = get_ip(self);
- int thr_crit_bup;
- volatile VALUE varname, value, flag;
-
- varname = varname_arg;
- value = value_arg;
- flag = flag_arg;
-
- StringValue(varname);
- StringValue(value);
-
-#if TCL_MAJOR_VERSION >= 8
- {
- Tcl_Obj *nameobj, *valobj, *ret;
- char *s;
- int len;
- volatile VALUE strval;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- nameobj = Tcl_NewStringObj(RSTRING(varname)->ptr,
- RSTRING(varname)->len);
-
- Tcl_IncrRefCount(nameobj);
-
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- valobj = Tcl_NewStringObj(RSTRING(value)->ptr,
- RSTRING(value)->len);
- Tcl_IncrRefCount(valobj);
-# else /* TCL_VERSION >= 8.1 */
- {
- volatile VALUE enc = Qnil;
-
- if (RTEST(rb_ivar_defined(value, ID_at_enc))) {
- enc = rb_ivar_get(value, ID_at_enc);
- }
-
- if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) {
- /* binary string */
- valobj = Tcl_NewByteArrayObj(RSTRING(value)->ptr,
- RSTRING(value)->len);
- } else if (strlen(RSTRING(value)->ptr) != RSTRING(value)->len) {
- /* probably binary string */
- valobj = Tcl_NewByteArrayObj(RSTRING(value)->ptr,
- RSTRING(value)->len);
- } else {
- /* probably text string */
- valobj = Tcl_NewStringObj(RSTRING(value)->ptr,
- RSTRING(value)->len);
- }
-
- Tcl_IncrRefCount(valobj);
- }
-# endif
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- Tcl_DecrRefCount(nameobj);
- Tcl_DecrRefCount(valobj);
- rb_thread_critical = thr_crit_bup;
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ret = Tcl_ObjSetVar2(ptr->ip, nameobj, (Tcl_Obj*)NULL, valobj,
- FIX2INT(flag));
- }
-
- Tcl_DecrRefCount(nameobj);
- Tcl_DecrRefCount(valobj);
-
- if (ret == (Tcl_Obj*)NULL) {
- volatile VALUE exc;
-#if TCL_MAJOR_VERSION >= 8
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- exc = rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
-#endif
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
-
- Tcl_IncrRefCount(ret);
-
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- s = Tcl_GetStringFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
-# else /* TCL_VERSION >= 8.1 */
- {
- VALUE old_gc;
-
- old_gc = rb_gc_disable();
-
- if (Tcl_GetCharLength(ret) != Tcl_UniCharLen(Tcl_GetUnicode(ret))) {
- /* possibly binary string */
- s = Tcl_GetByteArrayFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- rb_ivar_set(strval, ID_at_enc, rb_str_new2("binary"));
- } else {
- /* possibly text string */
- s = Tcl_GetStringFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- }
- if (old_gc == Qfalse) rb_gc_enable();
- }
-# endif
-
- Tcl_DecrRefCount(ret);
-
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
-
- return(strval);
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- {
- CONST char *ret;
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ret = Tcl_SetVar2(ptr->ip, RSTRING(varname)->ptr, (char*)NULL,
- RSTRING(value)->ptr, (int)FIX2INT(flag));
- }
-
- if (ret == NULL) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
-
- strval = rb_tainted_str_new2(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
-
- return(strval);
- }
-#endif
-}
-
-static VALUE
-ip_set_variable2(self, varname_arg, index_arg, value_arg, flag_arg)
- VALUE self;
- VALUE varname_arg;
- VALUE index_arg;
- VALUE value_arg;
- VALUE flag_arg;
-{
- struct tcltkip *ptr = get_ip(self);
- int thr_crit_bup;
- volatile VALUE varname, index, value, flag;
-
- if (NIL_P(index_arg)) {
- return ip_set_variable(self, varname_arg, value_arg, flag_arg);
- }
-
- varname = varname_arg;
- index = index_arg;
- value = value_arg;
- flag = flag_arg;
-
- StringValue(varname);
- StringValue(index);
- StringValue(value);
-
-#if TCL_MAJOR_VERSION >= 8
- {
- Tcl_Obj *nameobj, *idxobj, *valobj, *ret;
- char *s;
- int len;
- volatile VALUE strval;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- nameobj = Tcl_NewStringObj(RSTRING(varname)->ptr,
- RSTRING(varname)->len);
- Tcl_IncrRefCount(nameobj);
-
- idxobj = Tcl_NewStringObj(RSTRING(index)->ptr,
- RSTRING(index)->len);
- Tcl_IncrRefCount(idxobj);
-
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- valobj = Tcl_NewStringObj(RSTRING(value)->ptr,
- RSTRING(value)->len);
-# else /* TCL_VERSION >= 8.1 */
- {
- VALUE enc = Qnil;
-
- if (RTEST(rb_ivar_defined(value, ID_at_enc))) {
- enc = rb_ivar_get(value, ID_at_enc);
- }
-
- if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) {
- /* binary string */
- valobj = Tcl_NewByteArrayObj(RSTRING(value)->ptr,
- RSTRING(value)->len);
- } else if (strlen(RSTRING(value)->ptr) != RSTRING(value)->len) {
- /* probably binary string */
- valobj = Tcl_NewByteArrayObj(RSTRING(value)->ptr,
- RSTRING(value)->len);
- } else {
- /* probably text string */
- valobj = Tcl_NewStringObj(RSTRING(value)->ptr,
- RSTRING(value)->len);
- }
- }
-
-# endif
- Tcl_IncrRefCount(valobj);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- Tcl_DecrRefCount(nameobj);
- Tcl_DecrRefCount(idxobj);
- Tcl_DecrRefCount(valobj);
- rb_thread_critical = thr_crit_bup;
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ret = Tcl_ObjSetVar2(ptr->ip, nameobj, idxobj, valobj,
- FIX2INT(flag));
- }
-
- Tcl_DecrRefCount(nameobj);
- Tcl_DecrRefCount(idxobj);
- Tcl_DecrRefCount(valobj);
-
- if (ret == (Tcl_Obj*)NULL) {
- volatile VALUE exc;
-#if TCL_MAJOR_VERSION >= 8
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- exc = rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
-#endif
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
- }
-
- Tcl_IncrRefCount(ret);
-
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- s = Tcl_GetStringFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
-# else /* TCL_VERSION >= 8.1 */
- if (Tcl_GetCharLength(ret) != Tcl_UniCharLen(Tcl_GetUnicode(ret))) {
- /* possibly binary string */
- s = Tcl_GetByteArrayFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- rb_ivar_set(strval, ID_at_enc, rb_str_new2("binary"));
- } else {
- /* possibly text string */
- s = Tcl_GetStringFromObj(ret, &len);
- strval = rb_tainted_str_new(s, len);
- }
-# endif
-
- Tcl_DecrRefCount(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
-
- return(strval);
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- {
- CONST char *ret;
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- return rb_tainted_str_new2("");
- } else {
- /* Tcl_Preserve(ptr->ip); */
- rbtk_preserve_ip(ptr);
- ret = Tcl_SetVar2(ptr->ip, RSTRING(varname)->ptr,
- RSTRING(index)->ptr,
- RSTRING(value)->ptr, FIX2INT(flag));
- }
-
- if (ret == (char*)NULL) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
-
- Tcl_IncrRefCount(ret);
-
- strval = rb_tainted_str_new2(ret);
-
- Tcl_DecrRefCount(ret);
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
-
- return(strval);
- }
-#endif
-}
-
-static VALUE
-ip_unset_variable(self, varname_arg, flag_arg)
- VALUE self;
- VALUE varname_arg;
- VALUE flag_arg;
-{
- struct tcltkip *ptr = get_ip(self);
- volatile VALUE varname, value, flag;
-
- varname = varname_arg;
- flag = flag_arg;
-
- StringValue(varname);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- return Qtrue;
- }
-
- ptr->return_value = Tcl_UnsetVar(ptr->ip, RSTRING(varname)->ptr,
- FIX2INT(flag));
- if (ptr->return_value == TCL_ERROR) {
- if (FIX2INT(flag) & TCL_LEAVE_ERR_MSG) {
-#if TCL_MAJOR_VERSION >= 8
- rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
-#endif
- }
- return Qfalse;
- }
- return Qtrue;
-}
-
-static VALUE
-ip_unset_variable2(self, varname_arg, index_arg, flag_arg)
- VALUE self;
- VALUE varname_arg;
- VALUE index_arg;
- VALUE flag_arg;
-{
- struct tcltkip *ptr = get_ip(self);
- volatile VALUE varname, index, value, flag;
-
- if (NIL_P(index_arg)) {
- return ip_unset_variable(self, varname_arg, flag_arg);
- }
-
- varname = varname_arg;
- index = index_arg;
- flag = flag_arg;
-
- StringValue(varname);
- StringValue(index);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip)) {
- DUMP1("ip is deleted");
- return Qtrue;
- }
-
- ptr->return_value = Tcl_UnsetVar2(ptr->ip, RSTRING(varname)->ptr,
- RSTRING(index)->ptr, FIX2INT(flag));
- if (ptr->return_value == TCL_ERROR) {
- if (FIX2INT(flag) & TCL_LEAVE_ERR_MSG) {
-#if TCL_MAJOR_VERSION >= 8
- rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(ptr->ip));
-#else /* TCL_MAJOR_VERSION < 8 */
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
-#endif
- }
- return Qfalse;
- }
- return Qtrue;
-}
-
-static VALUE
-ip_get_global_var(self, varname)
- VALUE self;
- VALUE varname;
-{
- return ip_get_variable(self, varname,
- INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
-}
-
-static VALUE
-ip_get_global_var2(self, varname, index)
- VALUE self;
- VALUE varname;
- VALUE index;
-{
- return ip_get_variable2(self, varname, index,
- INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
-}
-
-static VALUE
-ip_set_global_var(self, varname, value)
- VALUE self;
- VALUE varname;
- VALUE value;
-{
- return ip_set_variable(self, varname, value,
- INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
-}
-
-static VALUE
-ip_set_global_var2(self, varname, index, value)
- VALUE self;
- VALUE varname;
- VALUE index;
- VALUE value;
-{
- return ip_set_variable2(self, varname, index, value,
- INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
-}
-
-static VALUE
-ip_unset_global_var(self, varname)
- VALUE self;
- VALUE varname;
-{
- return ip_unset_variable(self, varname,
- INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
-}
-
-static VALUE
-ip_unset_global_var2(self, varname, index)
- VALUE self;
- VALUE varname;
- VALUE index;
-{
- return ip_unset_variable2(self, varname, index,
- INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
-}
-
-
-/* treat Tcl_List */
-static VALUE
-lib_split_tklist_core(ip_obj, list_str)
- VALUE ip_obj;
- VALUE list_str;
-{
- Tcl_Interp *interp;
- volatile VALUE ary, elem;
- int idx;
- int taint_flag = OBJ_TAINTED(list_str);
- int result;
- VALUE old_gc;
-
- if (NIL_P(ip_obj)) {
- interp = (Tcl_Interp *)NULL;
- } else {
- interp = get_ip(ip_obj)->ip;
- }
-
- StringValue(list_str);
-
- {
-#if TCL_MAJOR_VERSION >= 8
- /* object style interface */
- Tcl_Obj *listobj;
- int objc;
- Tcl_Obj **objv;
- int thr_crit_bup;
-
-# if 1
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- listobj = Tcl_NewStringObj(RSTRING(list_str)->ptr,
- RSTRING(list_str)->len);
-# else /* TCL_VERSION >= 8.1 */
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- {
- VALUE enc = Qnil;
-
- if (RTEST(rb_ivar_defined(list_str, ID_at_enc))) {
- enc = rb_ivar_get(list_str, ID_at_enc);
- }
-
- if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) {
- /* binary string */
- listobj = Tcl_NewByteArrayObj(RSTRING(list_str)->ptr,
- RSTRING(list_str)->len);
- } else if (strlen(RSTRING(list_str)->ptr)
- != RSTRING(list_str)->len) {
- /* probably binary string */
- listobj = Tcl_NewByteArrayObj(RSTRING(list_str)->ptr,
- RSTRING(list_str)->len);
- } else {
- /* probably text string */
- listobj = Tcl_NewStringObj(RSTRING(list_str)->ptr,
- RSTRING(list_str)->len);
- }
- }
-
- rb_thread_critical = thr_crit_bup;
-# endif
-# else
- listobj = Tcl_NewStringObj(RSTRING(list_str)->ptr,
- RSTRING(list_str)->len);
-# endif
-
- Tcl_IncrRefCount(listobj);
-
- result = Tcl_ListObjGetElements(interp, listobj, &objc, &objv);
-
- if (result == TCL_ERROR) {
- Tcl_DecrRefCount(listobj);
- if (interp == (Tcl_Interp*)NULL) {
- rb_raise(rb_eRuntimeError, "cannot get elements from list");
- } else {
-#if TCL_MAJOR_VERSION >= 8
- rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(interp));
-#else /* TCL_MAJOR_VERSION < 8 */
- rb_raise(rb_eRuntimeError, "%s", interp->result);
-#endif
- }
- }
-
- for(idx = 0; idx < objc; idx++) {
- Tcl_IncrRefCount(objv[idx]);
- }
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- ary = rb_ary_new2(objc);
- if (taint_flag) OBJ_TAINT(ary);
-
- old_gc = rb_gc_disable();
-
- for(idx = 0; idx < objc; idx++) {
- char *str;
- int len;
-
-# if 1
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
- str = Tcl_GetStringFromObj(objv[idx], &len);
- elem = rb_str_new(str, len);
-# else /* TCL_VERSION >= 8.1 */
- if (Tcl_GetCharLength(objv[idx])
- != Tcl_UniCharLen(Tcl_GetUnicode(objv[idx]))) {
- /* possibly binary string */
- str = Tcl_GetByteArrayFromObj(objv[idx], &len);
- elem = rb_str_new(str, len);
- rb_ivar_set(elem, ID_at_enc, rb_tainted_str_new2("binary"));
- } else {
- /* possibly text string */
- str = Tcl_GetStringFromObj(objv[idx], &len);
- elem = rb_str_new(str, len);
- }
-# endif
-# else
- str = Tcl_GetStringFromObj(objv[idx], &len);
- elem = rb_str_new(str, len);
-# endif
-
- if (taint_flag) OBJ_TAINT(elem);
- RARRAY(ary)->ptr[idx] = elem;
- }
-
- RARRAY(ary)->len = objc;
-
- if (old_gc == Qfalse) rb_gc_enable();
-
- rb_thread_critical = thr_crit_bup;
-
- for(idx = 0; idx < objc; idx++) {
- Tcl_DecrRefCount(objv[idx]);
- }
-
- Tcl_DecrRefCount(listobj);
-
-#else /* TCL_MAJOR_VERSION < 8 */
- /* string style interface */
- int argc;
- char **argv;
-
- if (Tcl_SplitList(interp, RSTRING(list_str)->ptr,
- &argc, &argv) == TCL_ERROR) {
- if (interp == (Tcl_Interp*)NULL) {
- rb_raise(rb_eRuntimeError, "cannot get elements from list");
- } else {
- rb_raise(rb_eRuntimeError, "%s", interp->result);
- }
- }
-
- ary = rb_ary_new2(argc);
- if (taint_flag) OBJ_TAINT(ary);
-
- old_gc = rb_gc_disable();
-
- for(idx = 0; idx < argc; idx++) {
- if (taint_flag) {
- elem = rb_tainted_str_new2(argv[idx]);
- } else {
- elem = rb_str_new2(argv[idx]);
- }
- /* rb_ivar_set(elem, ID_at_enc, rb_str_new2("binary")); */
- RARRAY(ary)->ptr[idx] = elem;
- }
- RARRAY(ary)->len = argc;
-
- if (old_gc == Qfalse) rb_gc_enable();
-#endif
- }
-
- return ary;
-}
-
-static VALUE
-lib_split_tklist(self, list_str)
- VALUE self;
- VALUE list_str;
-{
- return lib_split_tklist_core(Qnil, list_str);
-}
-
-
-static VALUE
-ip_split_tklist(self, list_str)
- VALUE self;
- VALUE list_str;
-{
- return lib_split_tklist_core(self, list_str);
-}
-
-static VALUE
-lib_merge_tklist(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- int num, len;
- int *flagPtr;
- char *dst, *result;
- volatile VALUE str;
- int taint_flag = 0;
- int thr_crit_bup;
- VALUE old_gc;
-
- if (argc == 0) return rb_str_new2("");
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
- old_gc = rb_gc_disable();
-
- /* based on Tcl/Tk's Tcl_Merge() */
- flagPtr = ALLOC_N(int, argc);
-
- /* pass 1 */
- len = 1;
- for(num = 0; num < argc; num++) {
- if (OBJ_TAINTED(argv[num])) taint_flag = 1;
- dst = StringValuePtr(argv[num]);
-#if TCL_MAJOR_VERSION >= 8
- len += Tcl_ScanCountedElement(dst, RSTRING(argv[num])->len,
- &flagPtr[num]) + 1;
-#else /* TCL_MAJOR_VERSION < 8 */
- len += Tcl_ScanElement(dst, &flagPtr[num]) + 1;
-#endif
- }
-
- /* pass 2 */
- result = (char *)Tcl_Alloc(len);
- dst = result;
- for(num = 0; num < argc; num++) {
-#if TCL_MAJOR_VERSION >= 8
- len = Tcl_ConvertCountedElement(RSTRING(argv[num])->ptr,
- RSTRING(argv[num])->len,
- dst, flagPtr[num]);
-#else /* TCL_MAJOR_VERSION < 8 */
- len = Tcl_ConvertElement(RSTRING(argv[num])->ptr, dst, flagPtr[num]);
-#endif
- dst += len;
- *dst = ' ';
- dst++;
- }
- if (dst == result) {
- *dst = 0;
- } else {
- dst[-1] = 0;
- }
-
- free(flagPtr);
-
- /* create object */
- str = rb_str_new(result, dst - result - 1);
- if (taint_flag) OBJ_TAINT(str);
- Tcl_Free(result);
-
- if (old_gc == Qfalse) rb_gc_enable();
- rb_thread_critical = thr_crit_bup;
-
- return str;
-}
-
-static VALUE
-lib_conv_listelement(self, src)
- VALUE self;
- VALUE src;
-{
- int len, scan_flag;
- volatile VALUE dst;
- int taint_flag = OBJ_TAINTED(src);
- int thr_crit_bup;
-
- thr_crit_bup = rb_thread_critical;
- rb_thread_critical = Qtrue;
-
- StringValue(src);
-
-#if TCL_MAJOR_VERSION >= 8
- len = Tcl_ScanCountedElement(RSTRING(src)->ptr, RSTRING(src)->len,
- &scan_flag);
- dst = rb_str_new(0, len + 1);
- len = Tcl_ConvertCountedElement(RSTRING(src)->ptr, RSTRING(src)->len,
- RSTRING(dst)->ptr, scan_flag);
-#else /* TCL_MAJOR_VERSION < 8 */
- len = Tcl_ScanElement(RSTRING(src)->ptr, &scan_flag);
- dst = rb_str_new(0, len + 1);
- len = Tcl_ConvertElement(RSTRING(src)->ptr, RSTRING(dst)->ptr, scan_flag);
-#endif
-
- RSTRING(dst)->len = len;
- RSTRING(dst)->ptr[len] = '\0';
- if (taint_flag) OBJ_TAINT(dst);
-
- rb_thread_critical = thr_crit_bup;
-
- return dst;
-}
-
-
-#ifdef __MACOS__
-static void
-_macinit()
-{
- tcl_macQdPtr = &qd; /* setup QuickDraw globals */
- Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
-}
-#endif
-
-static VALUE
-tcltklib_compile_info()
-{
- volatile VALUE ret;
- int size;
- char form[]
- = "tcltklib %s :: Ruby%s (%s) %s pthread :: Tcl%s(%s)/Tk%s(%s) %s";
- char *info;
-
- size = strlen(form)
- + strlen(TCLTKLIB_RELEASE_DATE)
- + strlen(RUBY_VERSION)
- + strlen(RUBY_RELEASE_DATE)
- + strlen("without")
- + strlen(TCL_PATCH_LEVEL)
- + strlen("without stub")
- + strlen(TK_PATCH_LEVEL)
- + strlen("without stub")
- + strlen("unknown tcl_threads");
-
- info = ALLOC_N(char, size);
-
- sprintf(info, form,
- TCLTKLIB_RELEASE_DATE,
- RUBY_VERSION, RUBY_RELEASE_DATE,
-#ifdef HAVE_NATIVETHREAD
- "with",
-#else
- "without",
-#endif
- TCL_PATCH_LEVEL,
-#ifdef USE_TCL_STUBS
- "with stub",
-#else
- "without stub",
-#endif
- TK_PATCH_LEVEL,
-#ifdef USE_TK_STUBS
- "with stub",
-#else
- "without stub",
-#endif
-#ifdef WITH_TCL_ENABLE_THREAD
-# if WITH_TCL_ENABLE_THREAD
- "with tcl_threads"
-# else
- "without tcl_threads"
-# endif
-#else
- "unknown tcl_threads"
-#endif
- );
-
- ret = rb_obj_freeze(rb_str_new2(info));
-
- free(info);
-
- return ret;
-}
-
-/*---- initialization ----*/
-void
-Init_tcltklib()
-{
- int thr_crit_bup;
-
- VALUE lib = rb_define_module("TclTkLib");
- VALUE ip = rb_define_class("TclTkIp", rb_cObject);
-
- VALUE ev_flag = rb_define_module_under(lib, "EventFlag");
- VALUE var_flag = rb_define_module_under(lib, "VarAccessFlag");
-
- /* --------------------------------------------------------------- */
-
-#if defined USE_TCL_STUBS && defined USE_TK_STUBS
- extern int ruby_tcltk_stubs();
- int ret = ruby_tcltk_stubs();
-
- if (ret)
- rb_raise(rb_eLoadError, "tcltklib: tcltk_stubs init error(%d)", ret);
-#endif
-
- /* --------------------------------------------------------------- */
-
- rb_global_variable(&eTkCallbackReturn);
- rb_global_variable(&eTkCallbackBreak);
- rb_global_variable(&eTkCallbackContinue);
-
- rb_global_variable(&eventloop_thread);
- rb_global_variable(&watchdog_thread);
-
- /* --------------------------------------------------------------- */
-
- rb_define_const(lib, "COMPILE_INFO", tcltklib_compile_info());
-
- rb_define_const(lib, "RELEASE_DATE",
- rb_obj_freeze(rb_str_new2(tcltklib_release_date)));
-
- rb_define_const(lib, "FINALIZE_PROC_NAME",
- rb_str_new2(finalize_hook_name));
-
- /* --------------------------------------------------------------- */
-
- rb_define_const(ev_flag, "NONE", INT2FIX(0));
- rb_define_const(ev_flag, "WINDOW", INT2FIX(TCL_WINDOW_EVENTS));
- rb_define_const(ev_flag, "FILE", INT2FIX(TCL_FILE_EVENTS));
- rb_define_const(ev_flag, "TIMER", INT2FIX(TCL_TIMER_EVENTS));
- rb_define_const(ev_flag, "IDLE", INT2FIX(TCL_IDLE_EVENTS));
- rb_define_const(ev_flag, "ALL", INT2FIX(TCL_ALL_EVENTS));
- rb_define_const(ev_flag, "DONT_WAIT", INT2FIX(TCL_DONT_WAIT));
-
- /* --------------------------------------------------------------- */
-
- rb_define_const(var_flag, "NONE", INT2FIX(0));
- rb_define_const(var_flag, "GLOBAL_ONLY", INT2FIX(TCL_GLOBAL_ONLY));
-#ifdef TCL_NAMESPACE_ONLY
- rb_define_const(var_flag, "NAMESPACE_ONLY", INT2FIX(TCL_NAMESPACE_ONLY));
-#else /* probably Tcl7.6 */
- rb_define_const(var_flag, "NAMESPACE_ONLY", INT2FIX(0));
-#endif
- rb_define_const(var_flag, "LEAVE_ERR_MSG", INT2FIX(TCL_LEAVE_ERR_MSG));
- rb_define_const(var_flag, "APPEND_VALUE", INT2FIX(TCL_APPEND_VALUE));
- rb_define_const(var_flag, "LIST_ELEMENT", INT2FIX(TCL_LIST_ELEMENT));
-#ifdef TCL_PARSE_PART1
- rb_define_const(var_flag, "PARSE_VARNAME", INT2FIX(TCL_PARSE_PART1));
-#else /* probably Tcl7.6 */
- rb_define_const(var_flag, "PARSE_VARNAME", INT2FIX(0));
-#endif
-
- /* --------------------------------------------------------------- */
-
- eTkCallbackBreak = rb_define_class("TkCallbackReturn", rb_eStandardError);
- eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError);
- eTkCallbackContinue = rb_define_class("TkCallbackContinue",
- rb_eStandardError);
-
- /* --------------------------------------------------------------- */
-
- eLocalJumpError = rb_const_get(rb_cObject, rb_intern("LocalJumpError"));
-
- ID_at_enc = rb_intern("@encoding");
- ID_at_interp = rb_intern("@interp");
-
- ID_stop_p = rb_intern("stop?");
- ID_kill = rb_intern("kill");
- ID_join = rb_intern("join");
-
- ID_call = rb_intern("call");
- ID_backtrace = rb_intern("backtrace");
- ID_message = rb_intern("message");
-
- ID_at_reason = rb_intern("@reason");
- ID_return = rb_intern("return");
- ID_break = rb_intern("break");
- ID_next = rb_intern("next");
-
- ID_to_s = rb_intern("to_s");
- ID_inspect = rb_intern("inspect");
-
- /* --------------------------------------------------------------- */
-
- rb_define_module_function(lib, "mainloop", lib_mainloop, -1);
- rb_define_module_function(lib, "mainloop_watchdog",
- lib_mainloop_watchdog, -1);
- rb_define_module_function(lib, "do_one_event", lib_do_one_event, -1);
- rb_define_module_function(lib, "mainloop_abort_on_exception",
- lib_evloop_abort_on_exc, 0);
- rb_define_module_function(lib, "mainloop_abort_on_exception=",
- lib_evloop_abort_on_exc_set, 1);
- rb_define_module_function(lib, "set_eventloop_tick",set_eventloop_tick,1);
- rb_define_module_function(lib, "get_eventloop_tick",get_eventloop_tick,0);
- rb_define_module_function(lib, "set_no_event_wait", set_no_event_wait, 1);
- rb_define_module_function(lib, "get_no_event_wait", get_no_event_wait, 0);
- rb_define_module_function(lib, "set_eventloop_weight",
- set_eventloop_weight, 2);
- rb_define_module_function(lib, "set_max_block_time", set_max_block_time,1);
- rb_define_module_function(lib, "get_eventloop_weight",
- get_eventloop_weight, 0);
- rb_define_module_function(lib, "num_of_mainwindows",
- lib_num_of_mainwindows, 0);
-
- /* --------------------------------------------------------------- */
-
- rb_define_module_function(lib, "_split_tklist", lib_split_tklist, 1);
- rb_define_module_function(lib, "_merge_tklist", lib_merge_tklist, -1);
- rb_define_module_function(lib, "_conv_listelement",
- lib_conv_listelement, 1);
- rb_define_module_function(lib, "_toUTF8", lib_toUTF8, -1);
- rb_define_module_function(lib, "_fromUTF8", lib_fromUTF8, -1);
- rb_define_module_function(lib, "_subst_UTF_backslash",
- lib_UTF_backslash, 1);
- rb_define_module_function(lib, "_subst_Tcl_backslash",
- lib_Tcl_backslash, 1);
-
- /* --------------------------------------------------------------- */
-
- rb_define_alloc_func(ip, ip_alloc);
- rb_define_method(ip, "initialize", ip_init, -1);
- rb_define_method(ip, "create_slave", ip_create_slave, -1);
- rb_define_method(ip, "make_safe", ip_make_safe, 0);
- rb_define_method(ip, "safe?", ip_is_safe_p, 0);
- rb_define_method(ip, "allow_ruby_exit?", ip_allow_ruby_exit_p, 0);
- rb_define_method(ip, "allow_ruby_exit=", ip_allow_ruby_exit_set, 1);
- rb_define_method(ip, "delete", ip_delete, 0);
- rb_define_method(ip, "deleted?", ip_is_deleted_p, 0);
- rb_define_method(ip, "null_namespace?", ip_has_null_namespace_p, 0);
- rb_define_method(ip, "_eval", ip_eval, 1);
- rb_define_method(ip, "_toUTF8", ip_toUTF8, -1);
- rb_define_method(ip, "_fromUTF8", ip_fromUTF8, -1);
- rb_define_method(ip, "_thread_vwait", ip_thread_vwait, 1);
- rb_define_method(ip, "_thread_tkwait", ip_thread_tkwait, 2);
- rb_define_method(ip, "_invoke", ip_invoke, -1);
- rb_define_method(ip, "_return_value", ip_retval, 0);
-
- /* --------------------------------------------------------------- */
-
- rb_define_method(ip, "_get_variable", ip_get_variable, 2);
- rb_define_method(ip, "_get_variable2", ip_get_variable2, 3);
- rb_define_method(ip, "_set_variable", ip_set_variable, 3);
- rb_define_method(ip, "_set_variable2", ip_set_variable2, 4);
- rb_define_method(ip, "_unset_variable", ip_unset_variable, 2);
- rb_define_method(ip, "_unset_variable2", ip_unset_variable2, 3);
- rb_define_method(ip, "_get_global_var", ip_get_global_var, 1);
- rb_define_method(ip, "_get_global_var2", ip_get_global_var2, 2);
- rb_define_method(ip, "_set_global_var", ip_set_global_var, 2);
- rb_define_method(ip, "_set_global_var2", ip_set_global_var2, 3);
- rb_define_method(ip, "_unset_global_var", ip_unset_global_var, 1);
- rb_define_method(ip, "_unset_global_var2", ip_unset_global_var2, 2);
-
- /* --------------------------------------------------------------- */
-
- rb_define_method(ip, "_split_tklist", ip_split_tklist, 1);
- rb_define_method(ip, "_merge_tklist", lib_merge_tklist, -1);
- rb_define_method(ip, "_conv_listelement", lib_conv_listelement, 1);
-
- /* --------------------------------------------------------------- */
-
- rb_define_method(ip, "mainloop", ip_mainloop, -1);
- rb_define_method(ip, "mainloop_watchdog", ip_mainloop_watchdog, -1);
- rb_define_method(ip, "do_one_event", ip_do_one_event, -1);
- rb_define_method(ip, "mainloop_abort_on_exception",
- ip_evloop_abort_on_exc, 0);
- rb_define_method(ip, "mainloop_abort_on_exception=",
- ip_evloop_abort_on_exc_set, 1);
- rb_define_method(ip, "set_eventloop_tick", ip_set_eventloop_tick, 1);
- rb_define_method(ip, "get_eventloop_tick", ip_get_eventloop_tick, 0);
- rb_define_method(ip, "set_no_event_wait", ip_set_no_event_wait, 1);
- rb_define_method(ip, "get_no_event_wait", ip_get_no_event_wait, 0);
- rb_define_method(ip, "set_eventloop_weight", ip_set_eventloop_weight, 2);
- rb_define_method(ip, "get_eventloop_weight", ip_get_eventloop_weight, 0);
- rb_define_method(ip, "set_max_block_time", set_max_block_time, 1);
- rb_define_method(ip, "restart", ip_restart, 0);
-
- /* --------------------------------------------------------------- */
-
- eventloop_thread = 0;
- watchdog_thread = 0;
-
- /* --------------------------------------------------------------- */
-
-#ifdef __MACOS__
- _macinit();
-#endif
-
- /* from Tk_Main() */
- DUMP1("Tcl_FindExecutable");
- Tcl_FindExecutable(RSTRING(rb_argv0)->ptr);
-
- /* --------------------------------------------------------------- */
-}
-
-/* eof */