|
Ruby
2.0.0p481(2014-05-08revision45883)
|
00001 /************************************************ 00002 00003 stubs.c - Tcl/Tk stubs support 00004 00005 ************************************************/ 00006 00007 #include "ruby.h" 00008 #include "stubs.h" 00009 00010 #if !defined(RSTRING_PTR) 00011 #define RSTRING_PTR(s) (RSTRING(s)->ptr) 00012 #define RSTRING_LEN(s) (RSTRING(s)->len) 00013 #endif 00014 00015 #include <tcl.h> 00016 #include <tk.h> 00017 00018 /*------------------------------*/ 00019 00020 #ifdef __MACOS__ 00021 # include <tkMac.h> 00022 # include <Quickdraw.h> 00023 00024 static int call_macinit = 0; 00025 00026 static void 00027 _macinit() 00028 { 00029 if (!call_macinit) { 00030 tcl_macQdPtr = &qd; /* setup QuickDraw globals */ 00031 Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */ 00032 call_macinit = 1; 00033 } 00034 } 00035 #endif 00036 00037 /*------------------------------*/ 00038 00039 static int nativethread_checked = 0; 00040 00041 static void 00042 _nativethread_consistency_check(ip) 00043 Tcl_Interp *ip; 00044 { 00045 if (nativethread_checked || ip == (Tcl_Interp *)NULL) { 00046 return; 00047 } 00048 00049 /* If the variable "tcl_platform(threaded)" exists, 00050 then the Tcl interpreter was compiled with threads enabled. */ 00051 if (Tcl_GetVar2(ip, "tcl_platform", "threaded", TCL_GLOBAL_ONLY) != (char*)NULL) { 00052 #ifdef HAVE_NATIVETHREAD 00053 /* consistent */ 00054 #else 00055 rb_warn("Inconsistency. Loaded Tcl/Tk libraries are enabled nativethread-support. But `tcltklib' is not. The inconsistency causes SEGV or other troubles frequently."); 00056 #endif 00057 } else { 00058 #ifdef HAVE_NATIVETHREAD 00059 rb_warning("Inconsistency.`tcltklib' is enabled nativethread-support. But loaded Tcl/Tk libraries are not. (Probably, the inconsistency doesn't cause any troubles.)"); 00060 #else 00061 /* consistent */ 00062 #endif 00063 } 00064 00065 Tcl_ResetResult(ip); 00066 00067 nativethread_checked = 1; 00068 } 00069 00070 /*------------------------------*/ 00071 00072 #if defined USE_TCL_STUBS && defined USE_TK_STUBS 00073 00074 #if defined _WIN32 || defined __CYGWIN__ 00075 # ifdef HAVE_RUBY_RUBY_H 00076 # include "ruby/util.h" 00077 # else 00078 # include "util.h" 00079 # endif 00080 # include <windows.h> 00081 typedef HINSTANCE DL_HANDLE; 00082 # define DL_OPEN LoadLibrary 00083 # define DL_SYM GetProcAddress 00084 # define TCL_INDEX 4 00085 # define TK_INDEX 3 00086 # define TCL_NAME "tcl89" 00087 # define TK_NAME "tk89" 00088 # undef DLEXT 00089 # define DLEXT ".dll" 00090 #elif defined HAVE_DLOPEN 00091 # include <dlfcn.h> 00092 typedef void *DL_HANDLE; 00093 # define DL_OPEN(file) dlopen(file, RTLD_LAZY|RTLD_GLOBAL) 00094 # define DL_SYM dlsym 00095 # define TCL_INDEX 8 00096 # define TK_INDEX 7 00097 # define TCL_NAME "libtcl8.9" 00098 # define TK_NAME "libtk8.9" 00099 # ifdef __APPLE__ 00100 # undef DLEXT 00101 # define DLEXT ".dylib" 00102 # endif 00103 #endif 00104 00105 static DL_HANDLE tcl_dll = (DL_HANDLE)0; 00106 static DL_HANDLE tk_dll = (DL_HANDLE)0; 00107 00108 int 00109 #ifdef HAVE_PROTOTYPES 00110 ruby_open_tcl_dll(char *appname) 00111 #else 00112 ruby_open_tcl_dll(appname) 00113 char *appname; 00114 #endif 00115 { 00116 void (*p_Tcl_FindExecutable)(const char *); 00117 int n; 00118 char *ruby_tcl_dll = 0; 00119 00120 if (tcl_dll) return TCLTK_STUBS_OK; 00121 00122 ruby_tcl_dll = getenv("RUBY_TCL_DLL"); 00123 #if defined _WIN32 00124 if (ruby_tcl_dll) ruby_tcl_dll = ruby_strdup(ruby_tcl_dll); 00125 #endif 00126 if (ruby_tcl_dll) { 00127 tcl_dll = (DL_HANDLE)DL_OPEN(ruby_tcl_dll); 00128 } else { 00129 char tcl_name[] = TCL_NAME DLEXT; 00130 /* examine from 8.9 to 8.1 */ 00131 for (n = '9'; n > '0'; n--) { 00132 tcl_name[TCL_INDEX] = n; 00133 tcl_dll = (DL_HANDLE)DL_OPEN(tcl_name); 00134 if (tcl_dll) 00135 break; 00136 } 00137 } 00138 00139 #if defined _WIN32 00140 if (ruby_tcl_dll) ruby_xfree(ruby_tcl_dll); 00141 #endif 00142 00143 if (!tcl_dll) 00144 return NO_TCL_DLL; 00145 00146 p_Tcl_FindExecutable = (void (*)(const char *))DL_SYM(tcl_dll, "Tcl_FindExecutable"); 00147 if (!p_Tcl_FindExecutable) 00148 return NO_FindExecutable; 00149 00150 if (appname) { 00151 p_Tcl_FindExecutable(appname); 00152 } else { 00153 p_Tcl_FindExecutable("ruby"); 00154 } 00155 00156 return TCLTK_STUBS_OK; 00157 } 00158 00159 int 00160 ruby_open_tk_dll() 00161 { 00162 int n; 00163 char *ruby_tk_dll = 0; 00164 00165 if (!tcl_dll) { 00166 /* int ret = ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */ 00167 int ret = ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0); 00168 if (ret != TCLTK_STUBS_OK) return ret; 00169 } 00170 00171 if (tk_dll) return TCLTK_STUBS_OK; 00172 00173 ruby_tk_dll = getenv("RUBY_TK_DLL"); 00174 if (ruby_tk_dll) { 00175 tk_dll = (DL_HANDLE)DL_OPEN(ruby_tk_dll); 00176 } else { 00177 char tk_name[] = TK_NAME DLEXT; 00178 /* examine from 8.9 to 8.1 */ 00179 for (n = '9'; n > '0'; n--) { 00180 tk_name[TK_INDEX] = n; 00181 tk_dll = (DL_HANDLE)DL_OPEN(tk_name); 00182 if (tk_dll) 00183 break; 00184 } 00185 } 00186 00187 if (!tk_dll) 00188 return NO_TK_DLL; 00189 00190 return TCLTK_STUBS_OK; 00191 } 00192 00193 int 00194 #ifdef HAVE_PROTOTYPES 00195 ruby_open_tcltk_dll(char *appname) 00196 #else 00197 ruby_open_tcltk_dll(appname) 00198 char *appname; 00199 #endif 00200 { 00201 return( ruby_open_tcl_dll(appname) || ruby_open_tk_dll() ); 00202 } 00203 00204 int 00205 tcl_stubs_init_p() 00206 { 00207 return(tclStubsPtr != (TclStubs*)NULL); 00208 } 00209 00210 int 00211 tk_stubs_init_p() 00212 { 00213 return(tkStubsPtr != (TkStubs*)NULL); 00214 } 00215 00216 00217 Tcl_Interp * 00218 #ifdef HAVE_PROTOTYPES 00219 ruby_tcl_create_ip_and_stubs_init(int *st) 00220 #else 00221 ruby_tcl_create_ip_and_stubs_init(st) 00222 int *st; 00223 #endif 00224 { 00225 Tcl_Interp *tcl_ip; 00226 00227 if (st) *st = 0; 00228 00229 if (tcl_stubs_init_p()) { 00230 tcl_ip = Tcl_CreateInterp(); 00231 00232 if (!tcl_ip) { 00233 if (st) *st = FAIL_CreateInterp; 00234 return (Tcl_Interp*)NULL; 00235 } 00236 00237 _nativethread_consistency_check(tcl_ip); 00238 00239 return tcl_ip; 00240 00241 } else { 00242 Tcl_Interp *(*p_Tcl_CreateInterp)(); 00243 Tcl_Interp *(*p_Tcl_DeleteInterp)(); 00244 00245 if (!tcl_dll) { 00246 /* int ret = ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */ 00247 int ret = ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0); 00248 00249 if (ret != TCLTK_STUBS_OK) { 00250 if (st) *st = ret; 00251 return (Tcl_Interp*)NULL; 00252 } 00253 } 00254 00255 p_Tcl_CreateInterp 00256 = (Tcl_Interp *(*)())DL_SYM(tcl_dll, "Tcl_CreateInterp"); 00257 if (!p_Tcl_CreateInterp) { 00258 if (st) *st = NO_CreateInterp; 00259 return (Tcl_Interp*)NULL; 00260 } 00261 00262 p_Tcl_DeleteInterp 00263 = (Tcl_Interp *(*)())DL_SYM(tcl_dll, "Tcl_DeleteInterp"); 00264 if (!p_Tcl_DeleteInterp) { 00265 if (st) *st = NO_DeleteInterp; 00266 return (Tcl_Interp*)NULL; 00267 } 00268 00269 tcl_ip = (*p_Tcl_CreateInterp)(); 00270 if (!tcl_ip) { 00271 if (st) *st = FAIL_CreateInterp; 00272 return (Tcl_Interp*)NULL; 00273 } 00274 00275 if (!Tcl_InitStubs(tcl_ip, "8.1", 0)) { 00276 if (st) *st = FAIL_Tcl_InitStubs; 00277 (*p_Tcl_DeleteInterp)(tcl_ip); 00278 return (Tcl_Interp*)NULL; 00279 } 00280 00281 _nativethread_consistency_check(tcl_ip); 00282 00283 return tcl_ip; 00284 } 00285 } 00286 00287 int 00288 ruby_tcl_stubs_init() 00289 { 00290 int st; 00291 Tcl_Interp *tcl_ip; 00292 00293 if (!tcl_stubs_init_p()) { 00294 tcl_ip = ruby_tcl_create_ip_and_stubs_init(&st); 00295 00296 if (!tcl_ip) return st; 00297 00298 Tcl_DeleteInterp(tcl_ip); 00299 } 00300 00301 return TCLTK_STUBS_OK; 00302 } 00303 00304 int 00305 #ifdef HAVE_PROTOTYPES 00306 ruby_tk_stubs_init(Tcl_Interp *tcl_ip) 00307 #else 00308 ruby_tk_stubs_init(tcl_ip) 00309 Tcl_Interp *tcl_ip; 00310 #endif 00311 { 00312 Tcl_ResetResult(tcl_ip); 00313 00314 if (tk_stubs_init_p()) { 00315 if (Tk_Init(tcl_ip) == TCL_ERROR) { 00316 return FAIL_Tk_Init; 00317 } 00318 } else { 00319 int (*p_Tk_Init)(Tcl_Interp *); 00320 00321 if (!tk_dll) { 00322 int ret = ruby_open_tk_dll(); 00323 if (ret != TCLTK_STUBS_OK) return ret; 00324 } 00325 00326 p_Tk_Init = (int (*)(Tcl_Interp *))DL_SYM(tk_dll, "Tk_Init"); 00327 if (!p_Tk_Init) 00328 return NO_Tk_Init; 00329 00330 #if defined USE_TK_STUBS && defined TK_FRAMEWORK && defined(__APPLE__) 00331 /* 00332 FIX ME : dirty hack for Mac OS X frameworks. 00333 With stubs, fails to find Resource/Script directory of Tk.framework. 00334 So, teach it to a Tcl interpreter by an environment variable. 00335 e.g. when $tcl_library == 00336 /Library/Frameworks/Tcl.framwwork/8.5/Resources/Scripts 00337 ==> /Library/Frameworks/Tk.framwwork/8.5/Resources/Scripts 00338 */ 00339 if (Tcl_Eval(tcl_ip, 00340 "if {[array get env TK_LIBRARY] == {}} { set env(TK_LIBRARY) [regsub -all -nocase {(t)cl} $tcl_library {\\1k}] }" 00341 ) != TCL_OK) { 00342 return FAIL_Tk_Init; 00343 } 00344 #endif 00345 00346 if ((*p_Tk_Init)(tcl_ip) == TCL_ERROR) 00347 return FAIL_Tk_Init; 00348 00349 if (!Tk_InitStubs(tcl_ip, (char *)"8.1", 0)) 00350 return FAIL_Tk_InitStubs; 00351 00352 #ifdef __MACOS__ 00353 _macinit(); 00354 #endif 00355 } 00356 00357 return TCLTK_STUBS_OK; 00358 } 00359 00360 int 00361 #ifdef HAVE_PROTOTYPES 00362 ruby_tk_stubs_safeinit(Tcl_Interp *tcl_ip) 00363 #else 00364 ruby_tk_stubs_safeinit(tcl_ip) 00365 Tcl_Interp *tcl_ip; 00366 #endif 00367 { 00368 Tcl_ResetResult(tcl_ip); 00369 00370 if (tk_stubs_init_p()) { 00371 if (Tk_SafeInit(tcl_ip) == TCL_ERROR) 00372 return FAIL_Tk_Init; 00373 } else { 00374 int (*p_Tk_SafeInit)(Tcl_Interp *); 00375 00376 if (!tk_dll) { 00377 int ret = ruby_open_tk_dll(); 00378 if (ret != TCLTK_STUBS_OK) return ret; 00379 } 00380 00381 p_Tk_SafeInit = (int (*)(Tcl_Interp *))DL_SYM(tk_dll, "Tk_SafeInit"); 00382 if (!p_Tk_SafeInit) 00383 return NO_Tk_Init; 00384 00385 if ((*p_Tk_SafeInit)(tcl_ip) == TCL_ERROR) 00386 return FAIL_Tk_Init; 00387 00388 if (!Tk_InitStubs(tcl_ip, (char *)"8.1", 0)) 00389 return FAIL_Tk_InitStubs; 00390 00391 #ifdef __MACOS__ 00392 _macinit(); 00393 #endif 00394 } 00395 00396 return TCLTK_STUBS_OK; 00397 } 00398 00399 int 00400 ruby_tcltk_stubs() 00401 { 00402 int st; 00403 Tcl_Interp *tcl_ip; 00404 00405 /* st = ruby_open_tcltk_dll(RSTRING_PTR(rb_argv0)); */ 00406 st = ruby_open_tcltk_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0); 00407 switch(st) { 00408 case NO_FindExecutable: 00409 return -7; 00410 case NO_TCL_DLL: 00411 case NO_TK_DLL: 00412 return -1; 00413 } 00414 00415 tcl_ip = ruby_tcl_create_ip_and_stubs_init(&st); 00416 if (!tcl_ip) { 00417 switch(st) { 00418 case NO_CreateInterp: 00419 case NO_DeleteInterp: 00420 return -2; 00421 case FAIL_CreateInterp: 00422 return -3; 00423 case FAIL_Tcl_InitStubs: 00424 return -5; 00425 } 00426 } 00427 00428 st = ruby_tk_stubs_init(tcl_ip); 00429 switch(st) { 00430 case NO_Tk_Init: 00431 Tcl_DeleteInterp(tcl_ip); 00432 return -4; 00433 case FAIL_Tk_Init: 00434 case FAIL_Tk_InitStubs: 00435 Tcl_DeleteInterp(tcl_ip); 00436 return -6; 00437 } 00438 00439 Tcl_DeleteInterp(tcl_ip); 00440 00441 return 0; 00442 } 00443 00444 /*###################################################*/ 00445 #else /* ! USE_TCL_STUBS || ! USE_TK_STUBS) */ 00446 /*###################################################*/ 00447 00448 static int open_tcl_dll = 0; 00449 static int call_tk_stubs_init = 0; 00450 00451 int 00452 #ifdef HAVE_PROTOTYPES 00453 ruby_open_tcl_dll(char *appname) 00454 #else 00455 ruby_open_tcl_dll(appname) 00456 char *appname; 00457 #endif 00458 { 00459 if (appname) { 00460 Tcl_FindExecutable(appname); 00461 } else { 00462 Tcl_FindExecutable("ruby"); 00463 } 00464 open_tcl_dll = 1; 00465 00466 return TCLTK_STUBS_OK; 00467 } 00468 00469 int 00470 ruby_open_tk_dll() 00471 { 00472 if (!open_tcl_dll) { 00473 /* ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */ 00474 ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0); 00475 } 00476 00477 return TCLTK_STUBS_OK; 00478 } 00479 00480 int 00481 #ifdef HAVE_PROTOTYPES 00482 ruby_open_tcltk_dll(char *appname) 00483 #else 00484 ruby_open_tcltk_dll(appname) 00485 char *appname; 00486 #endif 00487 { 00488 return( ruby_open_tcl_dll(appname) || ruby_open_tk_dll() ); 00489 } 00490 00491 int 00492 tcl_stubs_init_p() 00493 { 00494 return 1; 00495 } 00496 00497 int 00498 tk_stubs_init_p() 00499 { 00500 return call_tk_stubs_init; 00501 } 00502 00503 Tcl_Interp * 00504 #ifdef HAVE_PROTOTYPES 00505 ruby_tcl_create_ip_and_stubs_init(int *st) 00506 #else 00507 ruby_tcl_create_ip_and_stubs_init(st) 00508 int *st; 00509 #endif 00510 { 00511 Tcl_Interp *tcl_ip; 00512 00513 if (!open_tcl_dll) { 00514 /* ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */ 00515 ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0); 00516 } 00517 00518 if (st) *st = 0; 00519 tcl_ip = Tcl_CreateInterp(); 00520 if (!tcl_ip) { 00521 if (st) *st = FAIL_CreateInterp; 00522 return (Tcl_Interp*)NULL; 00523 } 00524 00525 _nativethread_consistency_check(tcl_ip); 00526 00527 return tcl_ip; 00528 } 00529 00530 int 00531 ruby_tcl_stubs_init() 00532 { 00533 return TCLTK_STUBS_OK; 00534 } 00535 00536 int 00537 #ifdef HAVE_PROTOTYPES 00538 ruby_tk_stubs_init(Tcl_Interp *tcl_ip) 00539 #else 00540 ruby_tk_stubs_init(tcl_ip) 00541 Tcl_Interp *tcl_ip; 00542 #endif 00543 { 00544 if (Tk_Init(tcl_ip) == TCL_ERROR) 00545 return FAIL_Tk_Init; 00546 00547 if (!call_tk_stubs_init) { 00548 #ifdef __MACOS__ 00549 _macinit(); 00550 #endif 00551 call_tk_stubs_init = 1; 00552 } 00553 00554 return TCLTK_STUBS_OK; 00555 } 00556 00557 int 00558 #ifdef HAVE_PROTOTYPES 00559 ruby_tk_stubs_safeinit(Tcl_Interp *tcl_ip) 00560 #else 00561 ruby_tk_stubs_safeinit(tcl_ip) 00562 Tcl_Interp *tcl_ip; 00563 #endif 00564 { 00565 #if TCL_MAJOR_VERSION >= 8 00566 if (Tk_SafeInit(tcl_ip) == TCL_ERROR) 00567 return FAIL_Tk_Init; 00568 00569 if (!call_tk_stubs_init) { 00570 #ifdef __MACOS__ 00571 _macinit(); 00572 #endif 00573 call_tk_stubs_init = 1; 00574 } 00575 00576 return TCLTK_STUBS_OK; 00577 00578 #else /* TCL_MAJOR_VERSION < 8 */ 00579 00580 return FAIL_Tk_Init; 00581 #endif 00582 } 00583 00584 int 00585 ruby_tcltk_stubs() 00586 { 00587 /* Tcl_FindExecutable(RSTRING_PTR(rb_argv0)); */ 00588 Tcl_FindExecutable(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0); 00589 return 0; 00590 } 00591 00592 #endif 00593
1.7.6.1