1#ifndef RUBY_EVAL_INTERN_H
2#define RUBY_EVAL_INTERN_H
3
4#include "ruby/ruby.h"
5#include "vm_core.h"
6
7#define PASS_PASSED_BLOCK_TH(th) do { \
8    (th)->passed_block = rb_vm_control_frame_block_ptr(th->cfp); \
9    (th)->cfp->flag |= VM_FRAME_FLAG_PASSED; \
10} while (0)
11
12#define PASS_PASSED_BLOCK() do { \
13    rb_thread_t * const __th__ = GET_THREAD(); \
14    PASS_PASSED_BLOCK_TH(__th__); \
15} while (0)
16
17#ifdef HAVE_STDLIB_H
18#include <stdlib.h>
19#endif
20#ifndef EXIT_SUCCESS
21#define EXIT_SUCCESS 0
22#endif
23#ifndef EXIT_FAILURE
24#define EXIT_FAILURE 1
25#endif
26
27#include <stdio.h>
28#include <setjmp.h>
29
30#ifdef __APPLE__
31# ifdef HAVE_CRT_EXTERNS_H
32#  include <crt_externs.h>
33# else
34#  include "missing/crt_externs.h"
35# endif
36#endif
37
38#ifndef HAVE_STRING_H
39char *strrchr(const char *, const char);
40#endif
41
42#ifdef HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45
46#ifdef HAVE_NET_SOCKET_H
47#include <net/socket.h>
48#endif
49
50#define ruby_setjmp(env) RUBY_SETJMP(env)
51#define ruby_longjmp(env,val) RUBY_LONGJMP((env),(val))
52#ifdef __CYGWIN__
53# ifndef _setjmp
54int _setjmp(jmp_buf);
55# endif
56# ifndef _longjmp
57NORETURN(void _longjmp(jmp_buf, int));
58# endif
59#endif
60
61#include <sys/types.h>
62#include <signal.h>
63#include <errno.h>
64
65#ifdef HAVE_SYS_SELECT_H
66#include <sys/select.h>
67#endif
68
69/*
70  Solaris sys/select.h switches select to select_large_fdset to support larger
71  file descriptors if FD_SETSIZE is larger than 1024 on 32bit environment.
72  But Ruby doesn't change FD_SETSIZE because fd_set is allocated dynamically.
73  So following definition is required to use select_large_fdset.
74*/
75#ifdef HAVE_SELECT_LARGE_FDSET
76#define select(n, r, w, e, t) select_large_fdset((n), (r), (w), (e), (t))
77extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval *);
78#endif
79
80#ifdef HAVE_SYS_PARAM_H
81#include <sys/param.h>
82#endif
83
84#include <sys/stat.h>
85
86#define SAVE_ROOT_JMPBUF(th, stmt) do \
87  if (ruby_setjmp((th)->root_jmpbuf) == 0) { \
88      stmt; \
89  } \
90  else { \
91      rb_fiber_start(); \
92  } while (0)
93
94#define TH_PUSH_TAG(th) do { \
95  rb_thread_t * const _th = (th); \
96  struct rb_vm_tag _tag; \
97  _tag.tag = 0; \
98  _tag.prev = _th->tag; \
99  _th->tag = &_tag;
100
101#define TH_POP_TAG() \
102  _th->tag = _tag.prev; \
103} while (0)
104
105#define TH_POP_TAG2() \
106  _th->tag = _tag.prev
107
108#define PUSH_TAG() TH_PUSH_TAG(GET_THREAD())
109#define POP_TAG()      TH_POP_TAG()
110
111#define TH_EXEC_TAG() ruby_setjmp(_th->tag->buf)
112
113#define EXEC_TAG() \
114  TH_EXEC_TAG()
115
116#define TH_JUMP_TAG(th, st) do { \
117  ruby_longjmp((th)->tag->buf,(st)); \
118} while (0)
119
120#define JUMP_TAG(st) TH_JUMP_TAG(GET_THREAD(), (st))
121
122#define INTERNAL_EXCEPTION_P(exc) FIXNUM_P(exc)
123
124enum ruby_tag_type {
125    RUBY_TAG_RETURN	= 0x1,
126    RUBY_TAG_BREAK	= 0x2,
127    RUBY_TAG_NEXT	= 0x3,
128    RUBY_TAG_RETRY	= 0x4,
129    RUBY_TAG_REDO	= 0x5,
130    RUBY_TAG_RAISE	= 0x6,
131    RUBY_TAG_THROW	= 0x7,
132    RUBY_TAG_FATAL	= 0x8,
133    RUBY_TAG_MASK	= 0xf
134};
135#define TAG_RETURN	RUBY_TAG_RETURN
136#define TAG_BREAK	RUBY_TAG_BREAK
137#define TAG_NEXT	RUBY_TAG_NEXT
138#define TAG_RETRY	RUBY_TAG_RETRY
139#define TAG_REDO	RUBY_TAG_REDO
140#define TAG_RAISE	RUBY_TAG_RAISE
141#define TAG_THROW	RUBY_TAG_THROW
142#define TAG_FATAL	RUBY_TAG_FATAL
143#define TAG_MASK	RUBY_TAG_MASK
144
145#define NEW_THROW_OBJECT(val, pt, st) \
146  ((VALUE)rb_node_newnode(NODE_LIT, (VALUE)(val), (VALUE)(pt), (VALUE)(st)))
147#define SET_THROWOBJ_CATCH_POINT(obj, val) \
148  (RNODE((obj))->u2.value = (val))
149#define SET_THROWOBJ_STATE(obj, val) \
150  (RNODE((obj))->u3.value = (val))
151
152#define GET_THROWOBJ_VAL(obj)         ((VALUE)RNODE((obj))->u1.value)
153#define GET_THROWOBJ_CATCH_POINT(obj) ((VALUE*)RNODE((obj))->u2.value)
154#define GET_THROWOBJ_STATE(obj)       ((int)RNODE((obj))->u3.value)
155
156#define SCOPE_TEST(f)  (rb_vm_cref()->nd_visi & (f))
157#define SCOPE_CHECK(f) (rb_vm_cref()->nd_visi == (f))
158#define SCOPE_SET(f)   (rb_vm_cref()->nd_visi = (f))
159
160void rb_thread_cleanup(void);
161void rb_thread_wait_other_threads(void);
162
163enum {
164    RAISED_EXCEPTION = 1,
165    RAISED_STACKOVERFLOW = 2,
166    RAISED_NOMEMORY = 4
167};
168int rb_threadptr_set_raised(rb_thread_t *th);
169int rb_threadptr_reset_raised(rb_thread_t *th);
170#define rb_thread_raised_set(th, f)   ((th)->raised_flag |= (f))
171#define rb_thread_raised_reset(th, f) ((th)->raised_flag &= ~(f))
172#define rb_thread_raised_p(th, f)     (((th)->raised_flag & (f)) != 0)
173#define rb_thread_raised_clear(th)    ((th)->raised_flag = 0)
174
175VALUE rb_f_eval(int argc, VALUE *argv, VALUE self);
176VALUE rb_make_exception(int argc, VALUE *argv);
177
178NORETURN(void rb_method_name_error(VALUE, VALUE));
179
180NORETURN(void rb_fiber_start(void));
181
182NORETURN(void rb_print_undef(VALUE, ID, int));
183NORETURN(void rb_print_undef_str(VALUE, VALUE));
184NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
185NORETURN(void rb_vm_jump_tag_but_local_jump(int));
186NORETURN(void rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
187				      VALUE obj, int call_status));
188
189VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val);
190NODE *rb_vm_cref(void);
191VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename);
192void rb_vm_set_progname(VALUE filename);
193void rb_thread_terminate_all(void);
194VALUE rb_vm_top_self();
195VALUE rb_vm_cbase(void);
196
197#ifndef CharNext		/* defined as CharNext[AW] on Windows. */
198#define CharNext(p) ((p) + mblen((p), RUBY_MBCHAR_MAXSIZE))
199#endif
200
201#if defined DOSISH || defined __CYGWIN__
202static inline void
203translit_char(char *p, int from, int to)
204{
205    while (*p) {
206	if ((unsigned char)*p == from)
207	    *p = to;
208	p = CharNext(p);
209    }
210}
211#endif
212
213#endif /* RUBY_EVAL_INTERN_H */
214