00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "ruby.h"
00016 #include "node.h"
00017 #include "env.h"
00018 #include "util.h"
00019 #include "rubysig.h"
00020
00021 #ifdef HAVE_STDLIB_H
00022 #include <stdlib.h>
00023 #endif
00024 #ifndef EXIT_SUCCESS
00025 #define EXIT_SUCCESS 0
00026 #endif
00027 #ifndef EXIT_FAILURE
00028 #define EXIT_FAILURE 1
00029 #endif
00030
00031 #include <stdio.h>
00032 #if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
00033 #include <ucontext.h>
00034 #define USE_CONTEXT
00035 #endif
00036 #include <setjmp.h>
00037
00038 #include "st.h"
00039 #include "dln.h"
00040
00041 #ifdef __APPLE__
00042 #include <crt_externs.h>
00043 #endif
00044
00045
00046 #ifdef __GNUC__
00047 # ifndef atarist
00048 # ifndef alloca
00049 # define alloca __builtin_alloca
00050 # endif
00051 # endif
00052 #else
00053 # ifdef HAVE_ALLOCA_H
00054 # include <alloca.h>
00055 # else
00056 # ifdef _AIX
00057 #pragma alloca
00058 # else
00059 # ifndef alloca
00060 void *alloca ();
00061 # endif
00062 # endif
00063 # endif
00064 #endif
00065
00066 #ifdef HAVE_STDARG_PROTOTYPES
00067 #include <stdarg.h>
00068 #define va_init_list(a,b) va_start(a,b)
00069 #else
00070 #include <varargs.h>
00071 #define va_init_list(a,b) va_start(a)
00072 #endif
00073
00074 #ifndef HAVE_STRING_H
00075 char *strrchr (const char*,const char);
00076 #endif
00077
00078 #ifdef HAVE_UNISTD_H
00079 #include <unistd.h>
00080 #endif
00081
00082 #ifdef __BEOS__
00083 #include <net/socket.h>
00084 #endif
00085
00086 #ifdef __MACOS__
00087 #include "macruby_private.h"
00088 #endif
00089
00090 #ifdef __VMS
00091 #include "vmsruby_private.h"
00092 #endif
00093
00094 #ifdef USE_CONTEXT
00095 typedef struct {
00096 ucontext_t context;
00097 volatile int status;
00098 } rb_jmpbuf_t[1];
00101 static void rb_jump_context(rb_jmpbuf_t, int);
00102 static inline void
00103 rb_jump_context(env, val)
00104 rb_jmpbuf_t env;
00105 int val;
00106 {
00107 env->status = val;
00108 setcontext(&env->context);
00109 abort();
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 #if defined (__GNUC__) && (defined(sparc) || defined(__sparc__))
00142 #define FUNCTION_CALL_MAY_RETURN_TWICE \
00143 ({ __asm__ volatile ("" : : : \
00144 "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", \
00145 "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", \
00146 "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i7"); })
00147 #else
00148 static jmp_buf function_call_may_return_twice_jmp_buf;
00149 int function_call_may_return_twice_false = 0;
00150 #define FUNCTION_CALL_MAY_RETURN_TWICE \
00151 (function_call_may_return_twice_false ? \
00152 setjmp(function_call_may_return_twice_jmp_buf) : \
00153 0)
00154 #endif
00155 #define ruby_longjmp(env, val) rb_jump_context(env, val)
00156 #define ruby_setjmp(j) ((j)->status = 0, \
00157 FUNCTION_CALL_MAY_RETURN_TWICE, \
00158 getcontext(&(j)->context), \
00159 (j)->status)
00160 #else
00161 typedef jmp_buf rb_jmpbuf_t;
00162 #if !defined(setjmp) && defined(HAVE__SETJMP)
00163 #define ruby_setjmp(env) _setjmp(env)
00164 #define ruby_longjmp(env,val) _longjmp(env,val)
00165 #else
00166 #define ruby_setjmp(env) setjmp(env)
00167 #define ruby_longjmp(env,val) longjmp(env,val)
00168 #endif
00169 #endif
00170
00171 #include <sys/types.h>
00172 #include <signal.h>
00173 #include <errno.h>
00174
00175 #if defined(__VMS)
00176 #pragma nostandard
00177 #endif
00178
00179 #ifdef HAVE_SYS_SELECT_H
00180 #include <sys/select.h>
00181 #endif
00182
00183 #include <sys/stat.h>
00184
00185 VALUE rb_cProc;
00186 static VALUE rb_cBinding;
00187 static VALUE proc_invoke (VALUE,VALUE,VALUE,VALUE);
00188 static VALUE rb_f_binding (VALUE);
00189 static void rb_f_END (void);
00190 static VALUE rb_f_block_given_p (void);
00191 static VALUE block_pass (VALUE,NODE*);
00192 static VALUE rb_cMethod;
00193 static VALUE method_call (int, VALUE*, VALUE);
00194 static VALUE rb_cUnboundMethod;
00195 static VALUE umethod_bind (VALUE, VALUE);
00196 static VALUE rb_mod_define_method (int, VALUE*, VALUE);
00198 static void rb_raise_jump (VALUE);
00199 static VALUE rb_make_exception (int argc, VALUE *argv);
00200
00201 static int scope_vmode;
00202 #define SCOPE_PUBLIC 0
00203 #define SCOPE_PRIVATE 1
00204 #define SCOPE_PROTECTED 2
00205 #define SCOPE_MODFUNC 5
00206 #define SCOPE_MASK 7
00207 #define SCOPE_SET(f) (scope_vmode=(f))
00208 #define SCOPE_TEST(f) (scope_vmode&(f))
00209
00210 NODE* ruby_current_node;
00211 int ruby_safe_level = 0;
00212
00213
00214
00215
00216
00217
00218
00219
00220 static VALUE safe_getter (void);
00221 static void safe_setter (VALUE val);
00222
00223 void
00224 rb_secure(level)
00225 int level;
00226 {
00227 if (level <= ruby_safe_level) {
00228 if (ruby_frame->last_func) {
00229 rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
00230 rb_id2name(ruby_frame->last_func), ruby_safe_level);
00231 }
00232 else {
00233 rb_raise(rb_eSecurityError, "Insecure operation at level %d", ruby_safe_level);
00234 }
00235 }
00236 }
00237
00238 void
00239 rb_secure_update(obj)
00240 VALUE obj;
00241 {
00242 if (!OBJ_TAINTED(obj)) rb_secure(4);
00243 }
00244
00245 void
00246 rb_check_safe_obj(x)
00247 VALUE x;
00248 {
00249 if (ruby_safe_level > 0 && OBJ_TAINTED(x)){
00250 if (ruby_frame->last_func) {
00251 rb_raise(rb_eSecurityError, "Insecure operation - %s",
00252 rb_id2name(ruby_frame->last_func));
00253 }
00254 else {
00255 rb_raise(rb_eSecurityError, "Insecure operation: -r");
00256 }
00257 }
00258 rb_secure(4);
00259 }
00260
00261 void
00262 rb_check_safe_str(x)
00263 VALUE x;
00264 {
00265 rb_check_safe_obj(x);
00266 if (TYPE(x)!= T_STRING) {
00267 rb_raise(rb_eTypeError, "wrong argument type %s (expected String)",
00268 rb_obj_classname(x));
00269 }
00270 }
00273 static void print_undef (VALUE, ID);
00274 static void
00275 print_undef(klass, id)
00276 VALUE klass;
00277 ID id;
00278 {
00279 rb_name_error(id, "undefined method `%s' for %s `%s'",
00280 rb_id2name(id),
00281 (TYPE(klass) == T_MODULE) ? "module" : "class",
00282 rb_class2name(klass));
00283 }
00284
00285 static ID removed, singleton_removed, undefined, singleton_undefined;
00286
00287 #define CACHE_SIZE 0x800
00288 #define CACHE_MASK 0x7ff
00289 #define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
00290
00291 struct cache_entry {
00292 ID mid;
00293 ID mid0;
00294 VALUE klass;
00295 VALUE origin;
00296 NODE *method;
00297 int noex;
00298 };
00299
00300 static struct cache_entry cache[CACHE_SIZE];
00301 static int ruby_running = 0;
00302
00303 void
00304 rb_clear_cache()
00305 {
00306 struct cache_entry *ent, *end;
00307
00308 if (!ruby_running) return;
00309 ent = cache; end = ent + CACHE_SIZE;
00310 while (ent < end) {
00311 ent->mid = 0;
00312 ent++;
00313 }
00314 }
00315
00316 static void
00317 rb_clear_cache_for_undef(klass, id)
00318 VALUE klass;
00319 ID id;
00320 {
00321 struct cache_entry *ent, *end;
00322
00323 if (!ruby_running) return;
00324 ent = cache; end = ent + CACHE_SIZE;
00325 while (ent < end) {
00326 if (ent->origin == klass && ent->mid == id) {
00327 ent->mid = 0;
00328 }
00329 ent++;
00330 }
00331 }
00332
00333 static void
00334 rb_clear_cache_by_id(id)
00335 ID id;
00336 {
00337 struct cache_entry *ent, *end;
00338
00339 if (!ruby_running) return;
00340 ent = cache; end = ent + CACHE_SIZE;
00341 while (ent < end) {
00342 if (ent->mid == id) {
00343 ent->mid = 0;
00344 }
00345 ent++;
00346 }
00347 }
00348
00349 void
00350 rb_clear_cache_by_class(klass)
00351 VALUE klass;
00352 {
00353 struct cache_entry *ent, *end;
00354
00355 if (!ruby_running) return;
00356 ent = cache; end = ent + CACHE_SIZE;
00357 while (ent < end) {
00358 if (ent->klass == klass || ent->origin == klass) {
00359 ent->mid = 0;
00360 }
00361 ent++;
00362 }
00363 }
00364
00365 static ID init, eqq, each, aref, aset, match, missing;
00366 static ID added, singleton_added;
00367 static ID __id__, __send__, respond_to;
00368
00369 #define NOEX_TAINTED 8
00370 #define NOEX_SAFE(n) ((n) >> 4)
00371 #define NOEX_WITH(n, v) ((n) | (v) << 4)
00372 #define NOEX_WITH_SAFE(n) NOEX_WITH(n, ruby_safe_level)
00373
00374 void
00375 rb_add_method(klass, mid, node, noex)
00376 VALUE klass;
00377 ID mid;
00378 NODE *node;
00379 int noex;
00380 {
00381 NODE *body;
00382
00383 if (NIL_P(klass)) klass = rb_cObject;
00384 if (ruby_safe_level >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
00385 rb_raise(rb_eSecurityError, "Insecure: can't define method");
00386 }
00387 if (!FL_TEST(klass, FL_SINGLETON) &&
00388 node && nd_type(node) != NODE_ZSUPER &&
00389 (mid == rb_intern("initialize" )|| mid == rb_intern("initialize_copy"))) {
00390 noex = NOEX_PRIVATE | noex;
00391 }
00392 else if (FL_TEST(klass, FL_SINGLETON) && node && nd_type(node) == NODE_CFUNC &&
00393 mid == rb_intern("allocate")) {
00394 rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()",
00395 rb_class2name(rb_iv_get(klass, "__attached__")));
00396 mid = ID_ALLOCATOR;
00397 }
00398 if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
00399 rb_clear_cache_by_id(mid);
00400 body = NEW_METHOD(node, NOEX_WITH_SAFE(noex));
00401 st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t)body);
00402 if (node && mid != ID_ALLOCATOR && ruby_running) {
00403 if (FL_TEST(klass, FL_SINGLETON)) {
00404 rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, ID2SYM(mid));
00405 }
00406 else {
00407 rb_funcall(klass, added, 1, ID2SYM(mid));
00408 }
00409 }
00410 }
00411
00412 void
00413 rb_define_alloc_func(klass, func)
00414 VALUE klass;
00415 VALUE (*func) (VALUE);
00416 {
00417 Check_Type(klass, T_CLASS);
00418 rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PRIVATE);
00419 }
00420
00421 void
00422 rb_undef_alloc_func(klass)
00423 VALUE klass;
00424 {
00425 Check_Type(klass, T_CLASS);
00426 rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
00427 }
00428
00429 static NODE*
00430 search_method(klass, id, origin)
00431 VALUE klass, *origin;
00432 ID id;
00433 {
00434 NODE *body;
00435
00436 if (!klass) return 0;
00437 while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *)&body)) {
00438 klass = RCLASS(klass)->super;
00439 if (!klass) return 0;
00440 }
00441
00442 if (origin) *origin = klass;
00443 return body;
00444 }
00445
00446 static NODE*
00447 rb_get_method_body(klassp, idp, noexp)
00448 VALUE *klassp;
00449 ID *idp;
00450 int *noexp;
00451 {
00452 ID id = *idp;
00453 VALUE klass = *klassp;
00454 VALUE origin;
00455 NODE * volatile body;
00456 struct cache_entry *ent;
00457
00458 if ((body = search_method(klass, id, &origin)) == 0 || !body->nd_body) {
00459
00460 ent = cache + EXPR1(klass, id);
00461 ent->klass = klass;
00462 ent->origin = klass;
00463 ent->mid = ent->mid0 = id;
00464 ent->noex = 0;
00465 ent->method = 0;
00466
00467 return 0;
00468 }
00469
00470 if (ruby_running) {
00471
00472 ent = cache + EXPR1(klass, id);
00473 ent->klass = klass;
00474 ent->noex = body->nd_noex;
00475 if (noexp) *noexp = body->nd_noex;
00476 body = body->nd_body;
00477 if (nd_type(body) == NODE_FBODY) {
00478 ent->mid = id;
00479 *klassp = body->nd_orig;
00480 ent->origin = body->nd_orig;
00481 *idp = ent->mid0 = body->nd_mid;
00482 body = ent->method = body->nd_head;
00483 }
00484 else {
00485 *klassp = origin;
00486 ent->origin = origin;
00487 ent->mid = ent->mid0 = id;
00488 ent->method = body;
00489 }
00490 }
00491 else {
00492 if (noexp) *noexp = body->nd_noex;
00493 body = body->nd_body;
00494 if (nd_type(body) == NODE_FBODY) {
00495 *klassp = body->nd_orig;
00496 *idp = body->nd_mid;
00497 body = body->nd_head;
00498 }
00499 else {
00500 *klassp = origin;
00501 }
00502 }
00503
00504 return body;
00505 }
00506
00507 NODE*
00508 rb_method_node(klass, id)
00509 VALUE klass;
00510 ID id;
00511 {
00512 int noex;
00513
00514 return rb_get_method_body(&klass, &id, &noex);
00515 }
00516
00517 static void
00518 remove_method(klass, mid)
00519 VALUE klass;
00520 ID mid;
00521 {
00522 NODE *body;
00523
00524 if (klass == rb_cObject) {
00525 rb_secure(4);
00526 }
00527 if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) {
00528 rb_raise(rb_eSecurityError, "Insecure: can't remove method");
00529 }
00530 if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
00531 if (mid == __id__ || mid == __send__ || mid == init) {
00532 rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
00533 }
00534 if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *)&body) ||
00535 !body->nd_body) {
00536 rb_name_error(mid, "method `%s' not defined in %s",
00537 rb_id2name(mid), rb_class2name(klass));
00538 }
00539 rb_clear_cache_for_undef(klass, mid);
00540 if (FL_TEST(klass, FL_SINGLETON)) {
00541 rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, ID2SYM(mid));
00542 }
00543 else {
00544 rb_funcall(klass, removed, 1, ID2SYM(mid));
00545 }
00546 }
00547
00548 void
00549 rb_remove_method(klass, name)
00550 VALUE klass;
00551 const char *name;
00552 {
00553 remove_method(klass, rb_intern(name));
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 static VALUE
00565 rb_mod_remove_method(argc, argv, mod)
00566 int argc;
00567 VALUE *argv;
00568 VALUE mod;
00569 {
00570 int i;
00571
00572 for (i=0; i<argc; i++) {
00573 remove_method(mod, rb_to_id(argv[i]));
00574 }
00575 return mod;
00576 }
00577
00578 #undef rb_disable_super
00579 #undef rb_enable_super
00580
00581 void
00582 rb_disable_super(klass, name)
00583 VALUE klass;
00584 const char *name;
00585 {
00586
00587 }
00588
00589 void
00590 rb_enable_super(klass, name)
00591 VALUE klass;
00592 const char *name;
00593 {
00594 rb_warn("rb_enable_super() is obsolete");
00595 }
00596
00597 static void
00598 rb_export_method(klass, name, noex)
00599 VALUE klass;
00600 ID name;
00601 ID noex;
00602 {
00603 NODE *body;
00604 VALUE origin;
00605
00606 if (klass == rb_cObject) {
00607 rb_secure(4);
00608 }
00609 body = search_method(klass, name, &origin);
00610 if (!body && TYPE(klass) == T_MODULE) {
00611 body = search_method(rb_cObject, name, &origin);
00612 }
00613 if (!body || !body->nd_body) {
00614 print_undef(klass, name);
00615 }
00616 if (body->nd_noex != noex) {
00617 if (klass == origin) {
00618 body->nd_noex = noex;
00619 }
00620 else {
00621 rb_add_method(klass, name, NEW_ZSUPER(), noex);
00622 }
00623 }
00624 }
00625
00626 int
00627 rb_method_boundp(klass, id, ex)
00628 VALUE klass;
00629 ID id;
00630 int ex;
00631 {
00632 struct cache_entry *ent;
00633 int noex;
00634
00635
00636 ent = cache + EXPR1(klass, id);
00637 if (ent->mid == id && ent->klass == klass) {
00638 if (ex && (ent->noex & NOEX_PRIVATE))
00639 return Qfalse;
00640 if (!ent->method) return Qfalse;
00641 return Qtrue;
00642 }
00643 if (rb_get_method_body(&klass, &id, &noex)) {
00644 if (ex && (noex & NOEX_PRIVATE))
00645 return Qfalse;
00646 return Qtrue;
00647 }
00648 return Qfalse;
00649 }
00650
00651 void
00652 rb_attr(klass, id, read, write, ex)
00653 VALUE klass;
00654 ID id;
00655 int read, write, ex;
00656 {
00657 const char *name;
00658 char *buf;
00659 ID attriv;
00660 int noex;
00661 size_t len;
00662
00663 if (!ex) noex = NOEX_PUBLIC;
00664 else {
00665 if (SCOPE_TEST(SCOPE_PRIVATE)) {
00666 noex = NOEX_PRIVATE;
00667 rb_warning((scope_vmode == SCOPE_MODFUNC) ?
00668 "attribute accessor as module_function" :
00669 "private attribute?");
00670 }
00671 else if (SCOPE_TEST(SCOPE_PROTECTED)) {
00672 noex = NOEX_PROTECTED;
00673 }
00674 else {
00675 noex = NOEX_PUBLIC;
00676 }
00677 }
00678
00679 if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
00680 rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
00681 }
00682 name = rb_id2name(id);
00683 if (!name) {
00684 rb_raise(rb_eArgError, "argument needs to be symbol or string");
00685 }
00686 len = strlen(name)+2;
00687 buf = ALLOCA_N(char,len);
00688 snprintf(buf, len, "@%s", name);
00689 attriv = rb_intern(buf);
00690 if (read) {
00691 rb_add_method(klass, id, NEW_IVAR(attriv), noex);
00692 }
00693 if (write) {
00694 rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
00695 }
00696 }
00697
00698 extern int ruby_in_compile;
00699
00700 VALUE ruby_errinfo = Qnil;
00701 extern NODE *ruby_eval_tree_begin;
00702 extern NODE *ruby_eval_tree;
00703 extern int ruby_nerrs;
00704
00705 static VALUE rb_eLocalJumpError;
00706 static VALUE rb_eSysStackError;
00707
00708 extern VALUE ruby_top_self;
00709
00710 struct FRAME *ruby_frame;
00711 struct SCOPE *ruby_scope;
00712 static struct FRAME *top_frame;
00713 static struct SCOPE *top_scope;
00714
00715 static unsigned long frame_unique = 0;
00716
00717 #define PUSH_FRAME() do { \
00718 struct FRAME _frame; \
00719 _frame.prev = ruby_frame; \
00720 _frame.tmp = 0; \
00721 _frame.node = ruby_current_node; \
00722 _frame.iter = ruby_iter->iter; \
00723 _frame.argc = 0; \
00724 _frame.argv = 0; \
00725 _frame.flags = FRAME_ALLOCA; \
00726 _frame.uniq = frame_unique++; \
00727 ruby_frame = &_frame
00728
00729 #define POP_FRAME() \
00730 ruby_current_node = _frame.node; \
00731 ruby_frame = _frame.prev; \
00732 } while (0)
00733
00734 struct BLOCK {
00735 NODE *var;
00736 NODE *body;
00737 VALUE self;
00738 struct FRAME frame;
00739 struct SCOPE *scope;
00740 VALUE klass;
00741 NODE *cref;
00742 int iter;
00743 int vmode;
00744 int flags;
00745 int uniq;
00746 struct RVarmap *dyna_vars;
00747 VALUE orig_thread;
00748 VALUE wrapper;
00749 VALUE block_obj;
00750 struct BLOCK *outer;
00751 struct BLOCK *prev;
00752 };
00753
00754 #define BLOCK_D_SCOPE 1
00755 #define BLOCK_LAMBDA 2
00756
00757 static struct BLOCK *ruby_block;
00758 static unsigned long block_unique = 0;
00759
00760 #define PUSH_BLOCK(v,b) do { \
00761 struct BLOCK _block; \
00762 _block.var = (v); \
00763 _block.body = (b); \
00764 _block.self = self; \
00765 _block.frame = *ruby_frame; \
00766 _block.klass = ruby_class; \
00767 _block.cref = ruby_cref; \
00768 _block.frame.node = ruby_current_node;\
00769 _block.scope = ruby_scope; \
00770 _block.prev = ruby_block; \
00771 _block.outer = ruby_block; \
00772 _block.iter = ruby_iter->iter; \
00773 _block.vmode = scope_vmode; \
00774 _block.flags = BLOCK_D_SCOPE; \
00775 _block.dyna_vars = ruby_dyna_vars; \
00776 _block.wrapper = ruby_wrapper; \
00777 _block.block_obj = 0; \
00778 _block.uniq = (b)?block_unique++:0; \
00779 if (b) { \
00780 prot_tag->blkid = _block.uniq; \
00781 } \
00782 ruby_block = &_block
00783
00784 #define POP_BLOCK() \
00785 ruby_block = _block.prev; \
00786 } while (0)
00787
00788 struct RVarmap *ruby_dyna_vars;
00789 #define PUSH_VARS() do { \
00790 struct RVarmap * volatile _old; \
00791 _old = ruby_dyna_vars; \
00792 ruby_dyna_vars = 0
00793
00794 #define POP_VARS() \
00795 if (_old && (ruby_scope->flags & SCOPE_DONT_RECYCLE)) {\
00796 if (RBASIC(_old)->flags) \
00797 FL_SET(_old, DVAR_DONT_RECYCLE); \
00798 }\
00799 ruby_dyna_vars = _old; \
00800 } while (0)
00801
00802 #define DVAR_DONT_RECYCLE FL_USER2
00803
00804 static struct RVarmap*
00805 new_dvar(id, value, prev)
00806 ID id;
00807 VALUE value;
00808 struct RVarmap *prev;
00809 {
00810 NEWOBJ(vars, struct RVarmap);
00811 OBJSETUP(vars, 0, T_VARMAP);
00812 vars->id = id;
00813 vars->val = value;
00814 vars->next = prev;
00815
00816 return vars;
00817 }
00818
00819 VALUE
00820 rb_dvar_defined(id)
00821 ID id;
00822 {
00823 struct RVarmap *vars = ruby_dyna_vars;
00824
00825 while (vars) {
00826 if (vars->id == id) return Qtrue;
00827 vars = vars->next;
00828 }
00829 return Qfalse;
00830 }
00831
00832 VALUE
00833 rb_dvar_curr(id)
00834 ID id;
00835 {
00836 struct RVarmap *vars = ruby_dyna_vars;
00837
00838 while (vars) {
00839 if (vars->id == 0) break;
00840 if (vars->id == id) return Qtrue;
00841 vars = vars->next;
00842 }
00843 return Qfalse;
00844 }
00845
00846 VALUE
00847 rb_dvar_ref(id)
00848 ID id;
00849 {
00850 struct RVarmap *vars = ruby_dyna_vars;
00851
00852 while (vars) {
00853 if (vars->id == id) {
00854 return vars->val;
00855 }
00856 vars = vars->next;
00857 }
00858 return Qnil;
00859 }
00860
00861 void
00862 rb_dvar_push(id, value)
00863 ID id;
00864 VALUE value;
00865 {
00866 ruby_dyna_vars = new_dvar(id, value, ruby_dyna_vars);
00867 }
00868
00869 static void
00870 dvar_asgn_internal(id, value, curr)
00871 ID id;
00872 VALUE value;
00873 int curr;
00874 {
00875 int n = 0;
00876 struct RVarmap *vars = ruby_dyna_vars;
00877
00878 while (vars) {
00879 if (curr && vars->id == 0) {
00880
00881 n++;
00882 if (n == 2) break;
00883 }
00884 if (vars->id == id) {
00885 vars->val = value;
00886 return;
00887 }
00888 vars = vars->next;
00889 }
00890 if (!ruby_dyna_vars) {
00891 ruby_dyna_vars = new_dvar(id, value, 0);
00892 }
00893 else {
00894 vars = new_dvar(id, value, ruby_dyna_vars->next);
00895 ruby_dyna_vars->next = vars;
00896 }
00897 }
00898
00899 static inline void
00900 dvar_asgn(id, value)
00901 ID id;
00902 VALUE value;
00903 {
00904 dvar_asgn_internal(id, value, 0);
00905 }
00906
00907 static inline void
00908 dvar_asgn_curr(id, value)
00909 ID id;
00910 VALUE value;
00911 {
00912 dvar_asgn_internal(id, value, 1);
00913 }
00914
00915 VALUE *
00916 rb_svar(cnt)
00917 int cnt;
00918 {
00919 struct RVarmap *vars = ruby_dyna_vars;
00920 ID id;
00921
00922 if (!ruby_scope->local_tbl) return NULL;
00923 if (cnt >= ruby_scope->local_tbl[0]) return NULL;
00924 id = ruby_scope->local_tbl[cnt+1];
00925 while (vars) {
00926 if (vars->id == id) return &vars->val;
00927 vars = vars->next;
00928 }
00929 if (ruby_scope->local_vars == 0) return NULL;
00930 return &ruby_scope->local_vars[cnt];
00931 }
00932
00933 struct iter {
00934 int iter;
00935 struct iter *prev;
00936 };
00937 static struct iter *ruby_iter;
00938
00939 #define ITER_NOT 0
00940 #define ITER_PRE 1
00941 #define ITER_CUR 2
00942 #define ITER_PAS 3
00943
00944 #define PUSH_ITER(i) do { \
00945 struct iter _iter; \
00946 _iter.prev = ruby_iter; \
00947 _iter.iter = (i); \
00948 ruby_iter = &_iter
00949
00950 #define POP_ITER() \
00951 ruby_iter = _iter.prev; \
00952 } while (0)
00953
00954 struct tag {
00955 rb_jmpbuf_t buf;
00956 struct FRAME *frame;
00957 struct iter *iter;
00958 VALUE tag;
00959 VALUE retval;
00960 struct SCOPE *scope;
00961 VALUE dst;
00962 struct tag *prev;
00963 int blkid;
00964 };
00965 static struct tag *prot_tag;
00966
00967 #define PUSH_TAG(ptag) do { \
00968 struct tag _tag; \
00969 _tag.retval = Qnil; \
00970 _tag.frame = ruby_frame; \
00971 _tag.iter = ruby_iter; \
00972 _tag.prev = prot_tag; \
00973 _tag.scope = ruby_scope; \
00974 _tag.tag = ptag; \
00975 _tag.dst = 0; \
00976 _tag.blkid = 0; \
00977 prot_tag = &_tag
00978
00979 #define PROT_NONE Qfalse
00980 #define PROT_THREAD Qtrue
00981 #define PROT_FUNC INT2FIX(0)
00982 #define PROT_LOOP INT2FIX(1)
00983 #define PROT_LAMBDA INT2FIX(2)
00984 #define PROT_YIELD INT2FIX(3)
00985
00986 #define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, ruby_setjmp(prot_tag->buf))
00987
00988 #define JUMP_TAG(st) do { \
00989 ruby_frame = prot_tag->frame; \
00990 ruby_iter = prot_tag->iter; \
00991 ruby_longjmp(prot_tag->buf,(st)); \
00992 } while (0)
00993
00994 #define POP_TAG() \
00995 prot_tag = _tag.prev; \
00996 } while (0)
00997
00998 #define TAG_DST() (_tag.dst == (VALUE)ruby_frame->uniq)
00999
01000 #define TAG_RETURN 0x1
01001 #define TAG_BREAK 0x2
01002 #define TAG_NEXT 0x3
01003 #define TAG_RETRY 0x4
01004 #define TAG_REDO 0x5
01005 #define TAG_RAISE 0x6
01006 #define TAG_THROW 0x7
01007 #define TAG_FATAL 0x8
01008 #define TAG_MASK 0xf
01009
01010 VALUE ruby_class;
01011 static VALUE ruby_wrapper;
01012
01013 #define PUSH_CLASS(c) do { \
01014 VALUE _class = ruby_class; \
01015 ruby_class = (c)
01016
01017 #define POP_CLASS() ruby_class = _class; \
01018 } while (0)
01019
01020 static NODE *ruby_cref = 0;
01021 static NODE *top_cref;
01022 #define PUSH_CREF(c) ruby_cref = NEW_NODE(NODE_CREF,(c),0,ruby_cref)
01023 #define POP_CREF() ruby_cref = ruby_cref->nd_next
01024
01025 #define PUSH_SCOPE() do { \
01026 volatile int _vmode = scope_vmode; \
01027 struct SCOPE * volatile _old; \
01028 NEWOBJ(_scope, struct SCOPE); \
01029 OBJSETUP(_scope, 0, T_SCOPE); \
01030 _scope->local_tbl = 0; \
01031 _scope->local_vars = 0; \
01032 _scope->flags = 0; \
01033 _old = ruby_scope; \
01034 ruby_scope = _scope; \
01035 scope_vmode = SCOPE_PUBLIC
01036
01037 typedef struct thread * rb_thread_t;
01038 static rb_thread_t curr_thread = 0;
01039 static rb_thread_t main_thread;
01040 static void scope_dup (struct SCOPE *);
01041
01042 #define POP_SCOPE() \
01043 if (ruby_scope->flags & SCOPE_DONT_RECYCLE) {\
01044 if (_old) scope_dup(_old); \
01045 } \
01046 if (!(ruby_scope->flags & SCOPE_MALLOC)) {\
01047 ruby_scope->local_vars = 0; \
01048 ruby_scope->local_tbl = 0; \
01049 if (!(ruby_scope->flags & SCOPE_DONT_RECYCLE) && \
01050 ruby_scope != top_scope) { \
01051 rb_gc_force_recycle((VALUE)ruby_scope);\
01052 } \
01053 } \
01054 ruby_scope->flags |= SCOPE_NOSTACK; \
01055 ruby_scope = _old; \
01056 scope_vmode = _vmode; \
01057 } while (0)
01058
01059 static VALUE rb_eval (VALUE,NODE*);
01060 static VALUE eval (VALUE,VALUE,VALUE,char*,int);
01061 static NODE *compile (VALUE, char*, int);
01062
01063 static VALUE rb_yield_0 (VALUE, VALUE, VALUE, int, int);
01064
01065 #define YIELD_LAMBDA_CALL 1
01066 #define YIELD_PROC_CALL 2
01067 #define YIELD_PUBLIC_DEF 4
01068 #define YIELD_FUNC_AVALUE 1
01069 #define YIELD_FUNC_SVALUE 2
01070
01071 static VALUE rb_call (VALUE,VALUE,ID,int,const VALUE*,int);
01072 static VALUE module_setup (VALUE,NODE*);
01073
01074 static VALUE massign (VALUE,NODE*,VALUE,int);
01075 static void assign (VALUE,NODE*,VALUE,int);
01076
01077 typedef struct event_hook {
01078 rb_event_hook_func_t func;
01079 rb_event_t events;
01080 struct event_hook *next;
01081 } rb_event_hook_t;
01082
01083 static rb_event_hook_t *event_hooks;
01084
01085 #define EXEC_EVENT_HOOK(event, node, self, id, klass) \
01086 do { \
01087 rb_event_hook_t *hook; \
01088 \
01089 for (hook = event_hooks; hook; hook = hook->next) { \
01090 if (hook->events & event) \
01091 (*hook->func)(event, node, self, id, klass); \
01092 } \
01093 } while (0)
01094
01095 static VALUE trace_func = 0;
01096 static int tracing = 0;
01097 static void call_trace_func (rb_event_t,NODE*,VALUE,ID,VALUE);
01098
01099 #if 0
01100 #define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \
01101 ruby_sourceline = nd_line(ruby_current_node))
01102 #else
01103 #define SET_CURRENT_SOURCE() ((void)0)
01104 #endif
01105
01106 void
01107 ruby_set_current_source()
01108 {
01109 if (ruby_current_node) {
01110 ruby_sourcefile = ruby_current_node->nd_file;
01111 ruby_sourceline = nd_line(ruby_current_node);
01112 }
01113 }
01114
01115 static void
01116 #ifdef HAVE_STDARG_PROTOTYPES
01117 warn_printf(const char *fmt, ...)
01118 #else
01119 warn_printf(fmt, va_alist)
01120 const char *fmt;
01121 va_dcl
01122 #endif
01123 {
01124 char buf[BUFSIZ];
01125 va_list args;
01126
01127 va_init_list(args, fmt);
01128 vsnprintf(buf, BUFSIZ, fmt, args);
01129 va_end(args);
01130 rb_write_error(buf);
01131 }
01132
01133 #define warn_print(x) rb_write_error(x)
01134 #define warn_print2(x,l) rb_write_error2(x,l)
01135
01136 static void
01137 error_pos()
01138 {
01139 ruby_set_current_source();
01140 if (ruby_sourcefile) {
01141 if (ruby_frame->last_func) {
01142 warn_printf("%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline,
01143 rb_id2name(ruby_frame->last_func));
01144 }
01145 else if (ruby_sourceline == 0) {
01146 warn_printf("%s", ruby_sourcefile);
01147 }
01148 else {
01149 warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline);
01150 }
01151 }
01152 }
01153
01154 static VALUE
01155 get_backtrace(info)
01156 VALUE info;
01157 {
01158 if (NIL_P(info)) return Qnil;
01159 info = rb_funcall(info, rb_intern("backtrace"), 0);
01160 if (NIL_P(info)) return Qnil;
01161 return rb_check_array_type(info);
01162 }
01163
01164 static void
01165 set_backtrace(info, bt)
01166 VALUE info, bt;
01167 {
01168 rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
01169 }
01170
01171 static void
01172 error_print()
01173 {
01174 VALUE errat = Qnil;
01175 volatile VALUE eclass, e;
01176 char *einfo;
01177 long elen;
01178
01179 if (NIL_P(ruby_errinfo)) return;
01180
01181 PUSH_TAG(PROT_NONE);
01182 if (EXEC_TAG() == 0) {
01183 errat = get_backtrace(ruby_errinfo);
01184 }
01185 else {
01186 errat = Qnil;
01187 }
01188 if (EXEC_TAG()) goto error;
01189 if (NIL_P(errat)){
01190 ruby_set_current_source();
01191 if (ruby_sourcefile)
01192 warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline);
01193 else
01194 warn_printf("%d", ruby_sourceline);
01195 }
01196 else if (RARRAY(errat)->len == 0) {
01197 error_pos();
01198 }
01199 else {
01200 VALUE mesg = RARRAY(errat)->ptr[0];
01201
01202 if (NIL_P(mesg)) error_pos();
01203 else {
01204 warn_print2(RSTRING(mesg)->ptr, RSTRING(mesg)->len);
01205 }
01206 }
01207
01208 eclass = CLASS_OF(ruby_errinfo);
01209 if (EXEC_TAG() == 0) {
01210 e = rb_funcall(ruby_errinfo, rb_intern("message"), 0, 0);
01211 StringValue(e);
01212 einfo = RSTRING(e)->ptr;
01213 elen = RSTRING(e)->len;
01214 }
01215 else {
01216 einfo = "";
01217 elen = 0;
01218 }
01219 if (EXEC_TAG()) goto error;
01220 if (eclass == rb_eRuntimeError && elen == 0) {
01221 warn_print(": unhandled exception\n");
01222 }
01223 else {
01224 VALUE epath;
01225
01226 epath = rb_class_name(eclass);
01227 if (elen == 0) {
01228 warn_print(": ");
01229 warn_print2(RSTRING(epath)->ptr, RSTRING(epath)->len);
01230 warn_print("\n");
01231 }
01232 else {
01233 char *tail = 0;
01234 long len = elen;
01235
01236 if (RSTRING(epath)->ptr[0] == '#') epath = 0;
01237 if (tail = memchr(einfo, '\n', elen)) {
01238 len = tail - einfo;
01239 tail++;
01240 }
01241 warn_print(": ");
01242 warn_print2(einfo, len);
01243 if (epath) {
01244 warn_print(" (");
01245 warn_print2(RSTRING(epath)->ptr, RSTRING(epath)->len);
01246 warn_print(")\n");
01247 }
01248 if (tail) {
01249 warn_print2(tail, elen-len-1);
01250 }
01251 }
01252 }
01253
01254 if (!NIL_P(errat)) {
01255 long i;
01256 struct RArray *ep = RARRAY(errat);
01257
01258 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
01259 #define TRACE_HEAD 8
01260 #define TRACE_TAIL 5
01261
01262 ep = RARRAY(errat);
01263 for (i=1; i<ep->len; i++) {
01264 if (TYPE(ep->ptr[i]) == T_STRING) {
01265 warn_printf("\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
01266 }
01267 if (i == TRACE_HEAD && ep->len > TRACE_MAX) {
01268 warn_printf("\t ... %ld levels...\n",
01269 ep->len - TRACE_HEAD - TRACE_TAIL);
01270 i = ep->len - TRACE_TAIL;
01271 }
01272 }
01273 }
01274 error:
01275 POP_TAG();
01276 }
01277
01278 #if defined(__APPLE__)
01279 #define environ (*_NSGetEnviron())
01280 #elif !defined(_WIN32) && !defined(__MACOS__) || defined(_WIN32_WCE)
01281 extern char **environ;
01282 #endif
01283 char **rb_origenviron;
01284
01285 void rb_call_inits (void);
01286 void Init_stack (VALUE*);
01287 void Init_heap (void);
01288 void Init_ext (void);
01289
01290 #ifdef HAVE_NATIVETHREAD
01291 static rb_nativethread_t ruby_thid;
01292 int
01293 is_ruby_native_thread() {
01294 return NATIVETHREAD_EQUAL(ruby_thid, NATIVETHREAD_CURRENT());
01295 }
01296 #endif
01297
01298 void
01299 ruby_init()
01300 {
01301 static int initialized = 0;
01302 static struct FRAME frame;
01303 static struct iter iter;
01304 int state;
01305
01306 if (initialized)
01307 return;
01308 initialized = 1;
01309 #ifdef HAVE_NATIVETHREAD
01310 ruby_thid = NATIVETHREAD_CURRENT();
01311 #endif
01312
01313 ruby_frame = top_frame = &frame;
01314 ruby_iter = &iter;
01315
01316 #ifdef __MACOS__
01317 rb_origenviron = 0;
01318 #else
01319 rb_origenviron = environ;
01320 #endif
01321
01322 Init_stack((void*)&state);
01323 Init_heap();
01324 PUSH_SCOPE();
01325 ruby_scope->local_vars = 0;
01326 ruby_scope->local_tbl = 0;
01327 top_scope = ruby_scope;
01328
01329 SCOPE_SET(SCOPE_PRIVATE);
01330
01331 PUSH_TAG(PROT_NONE);
01332 if ((state = EXEC_TAG()) == 0) {
01333 rb_call_inits();
01334 ruby_class = rb_cObject;
01335 ruby_frame->self = ruby_top_self;
01336 top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
01337 ruby_cref = top_cref;
01338 rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self));
01339 #ifdef __MACOS__
01340 _macruby_init();
01341 #elif defined(__VMS)
01342 _vmsruby_init();
01343 #endif
01344 ruby_prog_init();
01345 ALLOW_INTS;
01346 }
01347 POP_TAG();
01348 if (state) {
01349 error_print();
01350 exit(EXIT_FAILURE);
01351 }
01352 POP_SCOPE();
01353 ruby_scope = top_scope;
01354 top_scope->flags &= ~SCOPE_NOSTACK;
01355 ruby_running = 1;
01356 }
01357
01358 static VALUE
01359 eval_node(self, node)
01360 VALUE self;
01361 NODE *node;
01362 {
01363 NODE *beg_tree = ruby_eval_tree_begin;
01364
01365 ruby_eval_tree_begin = 0;
01366 if (beg_tree) {
01367 rb_eval(self, beg_tree);
01368 }
01369
01370 if (!node) return Qnil;
01371 return rb_eval(self, node);
01372 }
01373
01374 int ruby_in_eval;
01375
01376 static void rb_thread_cleanup (void);
01377 static void rb_thread_wait_other_threads (void);
01378
01379 static int thread_set_raised();
01380 static int thread_reset_raised();
01381
01382 static VALUE exception_error;
01383 static VALUE sysstack_error;
01384
01385 static int
01386 sysexit_status(err)
01387 VALUE err;
01388 {
01389 VALUE st = rb_iv_get(err, "status");
01390 return NUM2INT(st);
01391 }
01392
01393 static int
01394 error_handle(ex)
01395 int ex;
01396 {
01397 int status = EXIT_FAILURE;
01398
01399 if (thread_set_raised()) return EXIT_FAILURE;
01400