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