00001 #ifndef RUBY_EVAL_INTERN_H
00002 #define RUBY_EVAL_INTERN_H
00003
00004 #include "ruby/ruby.h"
00005 #include "vm_core.h"
00006
00007 #define PASS_PASSED_BLOCK_TH(th) do { \
00008 (th)->passed_block = rb_vm_control_frame_block_ptr(th->cfp); \
00009 (th)->cfp->flag |= VM_FRAME_FLAG_PASSED; \
00010 } while (0)
00011
00012 #define PASS_PASSED_BLOCK() do { \
00013 rb_thread_t * const __th__ = GET_THREAD(); \
00014 PASS_PASSED_BLOCK_TH(__th__); \
00015 } while (0)
00016
00017 #ifdef HAVE_STDLIB_H
00018 #include <stdlib.h>
00019 #endif
00020 #ifndef EXIT_SUCCESS
00021 #define EXIT_SUCCESS 0
00022 #endif
00023 #ifndef EXIT_FAILURE
00024 #define EXIT_FAILURE 1
00025 #endif
00026
00027 #include <stdio.h>
00028 #include <setjmp.h>
00029
00030 #ifdef __APPLE__
00031 # ifdef HAVE_CRT_EXTERNS_H
00032 # include <crt_externs.h>
00033 # else
00034 # include "missing/crt_externs.h"
00035 # endif
00036 #endif
00037
00038 #ifndef HAVE_STRING_H
00039 char *strrchr(const char *, const char);
00040 #endif
00041
00042 #ifdef HAVE_UNISTD_H
00043 #include <unistd.h>
00044 #endif
00045
00046 #ifdef HAVE_NET_SOCKET_H
00047 #include <net/socket.h>
00048 #endif
00049
00050 #define ruby_setjmp(env) RUBY_SETJMP(env)
00051 #define ruby_longjmp(env,val) RUBY_LONGJMP((env),(val))
00052 #ifdef __CYGWIN__
00053 # ifndef _setjmp
00054 int _setjmp(jmp_buf);
00055 # endif
00056 # ifndef _longjmp
00057 NORETURN(void _longjmp(jmp_buf, int));
00058 # endif
00059 #endif
00060
00061 #include <sys/types.h>
00062 #include <signal.h>
00063 #include <errno.h>
00064
00065 #ifdef HAVE_SYS_SELECT_H
00066 #include <sys/select.h>
00067 #endif
00068
00069
00070
00071
00072
00073
00074
00075 #ifdef HAVE_SELECT_LARGE_FDSET
00076 #define select(n, r, w, e, t) select_large_fdset((n), (r), (w), (e), (t))
00077 extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval *);
00078 #endif
00079
00080 #ifdef HAVE_SYS_PARAM_H
00081 #include <sys/param.h>
00082 #endif
00083
00084 #include <sys/stat.h>
00085
00086 #ifdef _MSC_VER
00087 #define SAVE_ROOT_JMPBUF_BEFORE_STMT \
00088 __try {
00089 #define SAVE_ROOT_JMPBUF_AFTER_STMT \
00090 } \
00091 __except (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW ? \
00092 (rb_thread_raised_set(GET_THREAD(), RAISED_STACKOVERFLOW), \
00093 raise(SIGSEGV), \
00094 EXCEPTION_EXECUTE_HANDLER) : \
00095 EXCEPTION_CONTINUE_SEARCH) { \
00096 \
00097 }
00098 #elif defined(__MINGW32__)
00099 LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *);
00100 #define SAVE_ROOT_JMPBUF_BEFORE_STMT \
00101 do { \
00102 PVOID _handler = AddVectoredExceptionHandler(1, rb_w32_stack_overflow_handler);
00103
00104 #define SAVE_ROOT_JMPBUF_AFTER_STMT \
00105 RemoveVectoredExceptionHandler(_handler); \
00106 } while (0);
00107 #else
00108 #define SAVE_ROOT_JMPBUF_BEFORE_STMT
00109 #define SAVE_ROOT_JMPBUF_AFTER_STMT
00110 #endif
00111
00112 #define SAVE_ROOT_JMPBUF(th, stmt) do \
00113 if (ruby_setjmp((th)->root_jmpbuf) == 0) { \
00114 SAVE_ROOT_JMPBUF_BEFORE_STMT \
00115 stmt; \
00116 SAVE_ROOT_JMPBUF_AFTER_STMT \
00117 } \
00118 else { \
00119 rb_fiber_start(); \
00120 } while (0)
00121
00122 #define TH_PUSH_TAG(th) do { \
00123 rb_thread_t * const _th = (th); \
00124 struct rb_vm_tag _tag; \
00125 _tag.tag = 0; \
00126 _tag.prev = _th->tag;
00127
00128 #define TH_POP_TAG() \
00129 _th->tag = _tag.prev; \
00130 } while (0)
00131
00132 #define TH_POP_TAG2() \
00133 _th->tag = _tag.prev
00134
00135 #define TH_PUSH_TAG2() (_th->tag = &_tag, 0)
00136
00137 #define TH_TMPPOP_TAG() TH_POP_TAG2()
00138
00139 #define TH_REPUSH_TAG() TH_PUSH_TAG2()
00140
00141 #define PUSH_TAG() TH_PUSH_TAG(GET_THREAD())
00142 #define POP_TAG() TH_POP_TAG()
00143
00144
00145 static inline int
00146 rb_threadptr_tag_state(rb_thread_t *th)
00147 {
00148 int state = th->state;
00149 th->state = 0;
00150 return state;
00151 }
00152
00153 NORETURN(static inline void rb_threadptr_tag_jump(rb_thread_t *, int));
00154 static inline void
00155 rb_threadptr_tag_jump(rb_thread_t *th, int st)
00156 {
00157 th->state = st;
00158 ruby_longjmp(th->tag->buf, 1);
00159 }
00160
00161
00162
00163
00164
00165 #define TH_EXEC_TAG() \
00166 (ruby_setjmp(_tag.buf) ? rb_threadptr_tag_state(_th) : TH_PUSH_TAG2())
00167
00168 #define EXEC_TAG() \
00169 TH_EXEC_TAG()
00170
00171 #define TH_JUMP_TAG(th, st) rb_threadptr_tag_jump(th, st)
00172
00173 #define JUMP_TAG(st) TH_JUMP_TAG(GET_THREAD(), (st))
00174
00175 #define INTERNAL_EXCEPTION_P(exc) FIXNUM_P(exc)
00176
00177 enum ruby_tag_type {
00178 RUBY_TAG_RETURN = 0x1,
00179 RUBY_TAG_BREAK = 0x2,
00180 RUBY_TAG_NEXT = 0x3,
00181 RUBY_TAG_RETRY = 0x4,
00182 RUBY_TAG_REDO = 0x5,
00183 RUBY_TAG_RAISE = 0x6,
00184 RUBY_TAG_THROW = 0x7,
00185 RUBY_TAG_FATAL = 0x8,
00186 RUBY_TAG_MASK = 0xf
00187 };
00188 #define TAG_RETURN RUBY_TAG_RETURN
00189 #define TAG_BREAK RUBY_TAG_BREAK
00190 #define TAG_NEXT RUBY_TAG_NEXT
00191 #define TAG_RETRY RUBY_TAG_RETRY
00192 #define TAG_REDO RUBY_TAG_REDO
00193 #define TAG_RAISE RUBY_TAG_RAISE
00194 #define TAG_THROW RUBY_TAG_THROW
00195 #define TAG_FATAL RUBY_TAG_FATAL
00196 #define TAG_MASK RUBY_TAG_MASK
00197
00198 #define NEW_THROW_OBJECT(val, pt, st) \
00199 ((VALUE)rb_node_newnode(NODE_LIT, (VALUE)(val), (VALUE)(pt), (VALUE)(st)))
00200 #define SET_THROWOBJ_CATCH_POINT(obj, val) \
00201 (RNODE((obj))->u2.value = (val))
00202 #define SET_THROWOBJ_STATE(obj, val) \
00203 (RNODE((obj))->u3.value = (val))
00204
00205 #define GET_THROWOBJ_VAL(obj) ((VALUE)RNODE((obj))->u1.value)
00206 #define GET_THROWOBJ_CATCH_POINT(obj) ((VALUE*)RNODE((obj))->u2.value)
00207 #define GET_THROWOBJ_STATE(obj) ((int)RNODE((obj))->u3.value)
00208
00209 #define SCOPE_TEST(f) (rb_vm_cref()->nd_visi & (f))
00210 #define SCOPE_CHECK(f) (rb_vm_cref()->nd_visi == (f))
00211 #define SCOPE_SET(f) (rb_vm_cref()->nd_visi = (f))
00212
00213 void rb_thread_cleanup(void);
00214 void rb_thread_wait_other_threads(void);
00215
00216 enum {
00217 RAISED_EXCEPTION = 1,
00218 RAISED_STACKOVERFLOW = 2,
00219 RAISED_NOMEMORY = 4
00220 };
00221 int rb_threadptr_set_raised(rb_thread_t *th);
00222 int rb_threadptr_reset_raised(rb_thread_t *th);
00223 #define rb_thread_raised_set(th, f) ((th)->raised_flag |= (f))
00224 #define rb_thread_raised_reset(th, f) ((th)->raised_flag &= ~(f))
00225 #define rb_thread_raised_p(th, f) (((th)->raised_flag & (f)) != 0)
00226 #define rb_thread_raised_clear(th) ((th)->raised_flag = 0)
00227
00228 VALUE rb_f_eval(int argc, VALUE *argv, VALUE self);
00229 VALUE rb_make_exception(int argc, VALUE *argv);
00230
00231 NORETURN(void rb_method_name_error(VALUE, VALUE));
00232
00233 NORETURN(void rb_fiber_start(void));
00234
00235 NORETURN(void rb_print_undef(VALUE, ID, int));
00236 NORETURN(void rb_print_undef_str(VALUE, VALUE));
00237 NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
00238 NORETURN(void rb_vm_jump_tag_but_local_jump(int));
00239 NORETURN(void rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
00240 VALUE obj, int call_status));
00241
00242 VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val);
00243 NODE *rb_vm_cref(void);
00244 VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename);
00245 void rb_vm_set_progname(VALUE filename);
00246 void rb_thread_terminate_all(void);
00247 VALUE rb_vm_top_self();
00248 VALUE rb_vm_cbase(void);
00249
00250 #ifndef CharNext
00251 # ifdef HAVE_MBLEN
00252 # define CharNext(p) ((p) + mblen((p), RUBY_MBCHAR_MAXSIZE))
00253 # else
00254 # define CharNext(p) ((p) + 1)
00255 # endif
00256 #endif
00257
00258 #if defined DOSISH || defined __CYGWIN__
00259 static inline void
00260 translit_char(char *p, int from, int to)
00261 {
00262 while (*p) {
00263 if ((unsigned char)*p == from)
00264 *p = to;
00265 p = CharNext(p);
00266 }
00267 }
00268 #endif
00269
00270 #endif
00271