Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals

eval.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   eval.c -
00004 
00005   $Author: nobu $
00006   $Date: 2005/12/20 13:41:47 $
00007   created at: Thu Jun 10 14:22:17 JST 1993
00008 
00009   Copyright (C) 1993-2003 Yukihiro Matsumoto
00010   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
00011   Copyright (C) 2000  Information-technology Promotion Agency, Japan
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 /* Make alloca work the best possible way.  */
00046 #ifdef __GNUC__
00047 # ifndef atarist
00048 #  ifndef alloca
00049 #   define alloca __builtin_alloca
00050 #  endif
00051 # endif /* atarist */
00052 #else
00053 # ifdef HAVE_ALLOCA_H
00054 #  include <alloca.h>
00055 # else
00056 #  ifdef _AIX
00057  #pragma alloca
00058 #  else
00059 #   ifndef alloca /* predefined by HP cc +Olibcalls */
00060 void *alloca ();
00061 #   endif
00062 #  endif /* AIX */
00063 # endif /* HAVE_ALLOCA_H */
00064 #endif /* __GNUC__ */
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();                    /* ensure noreturn */
00110 }
00111 /*
00112  * FUNCTION_CALL_MAY_RETURN_TWICE is a magic for getcontext, gcc,
00113  * IA64 register stack and SPARC register window combination problem.
00114  *
00115  * Assume following code sequence.
00116  * 
00117  * 1. set a register in the register stack/window such as r32/l0.
00118  * 2. call getcontext.
00119  * 3. use the register.
00120  * 4. update the register for other use.
00121  * 5. call setcontext indirectly (or directly).
00122  *
00123  * This code should be run as 1->2->3->4->5->3->4.
00124  * But after second getcontext return (second 3),
00125  * the register is broken (updated).
00126  * It's because getcontext/setcontext doesn't preserve the content of the
00127  * register stack/window.
00128  *
00129  * setjmp also doesn't preserve the content of the register stack/window.
00130  * But it has not the problem because gcc knows setjmp may return twice.
00131  * gcc detects setjmp and generates setjmp safe code.
00132  *
00133  * So setjmp call before getcontext call makes the code somewhat safe.
00134  * It fix the problem on IA64.
00135  * It is not required that setjmp is called at run time, since the problem is
00136  * register usage.
00137  *
00138  * Since the magic setjmp is not enough for SPARC,
00139  * inline asm is used to prohibit registers in register windows.
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 /* safe-level:
00213    0 - strings from streams/environment/ARGV are tainted (default)
00214    1 - no dangerous operation by tainted value
00215    2 - process/file operations prohibited
00216    3 - all generated objects are tainted
00217    4 - no global (non-tainted) variable modification/no direct output
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 {            /* method hash table. */
00292     ID mid;                     /* method's id */
00293     ID mid0;                    /* method's original id */
00294     VALUE klass;                /* receiver's class */
00295     VALUE origin;               /* where method defined  */
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         /* store empty info in cache */
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         /* store in cache */
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  *  call-seq:
00558  *     remove_method(symbol)   => self
00559  *  
00560  *  Removes the method identified by _symbol_ from the current
00561  *  class. For an example, see <code>Module.undef_method</code>.
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     /* obsolete - no use */
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     /* is it in the method cache? */
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) /* unless it's already recycled */ \
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             /* first null is a dvar header */
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      /* 0 */
00980 #define PROT_THREAD Qtrue       /* 2 */
00981 #define PROT_FUNC   INT2FIX(0)  /* 1 */
00982 #define PROT_LOOP   INT2FIX(1)  /* 3 */
00983 #define PROT_LAMBDA INT2FIX(2)  /* 5 */
00984 #define PROT_YIELD  INT2FIX(3)  /* 7 */
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;      /* security 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;         /* OK */
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++;         /* skip newline */
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     /* default visibility is private at toplevel */
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