Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

eval_error.c
Go to the documentation of this file.
1 /* -*-c-*- */
2 /*
3 * included by eval.c
4 */
5
6 static void
7 warn_printf(const char *fmt, ...)
8 {
9 char buf[BUFSIZ];
10 va_list args;
11
12 va_init_list(args, fmt);
13 vsnprintf(buf, BUFSIZ, fmt, args);
14 va_end(args);
15 rb_write_error(buf);
16 }
17
18 #define warn_print(x) rb_write_error(x)
19 #define warn_print2(x,l) rb_write_error2((x),(l))
20
21 static void
22 error_pos(void)
23 {
24 const char *sourcefile = rb_sourcefile();
25 int sourceline = rb_sourceline();
26
27 if (sourcefile) {
28 if (sourceline == 0) {
29 warn_printf("%s", sourcefile);
30 }
31 else if (rb_frame_callee()) {
32 warn_printf("%s:%d:in `%s'", sourcefile, sourceline,
33 rb_id2name(rb_frame_callee()));
34 }
35 else {
36 warn_printf("%s:%d", sourcefile, sourceline);
37 }
38 }
39 }
40
41 static VALUE
42 get_backtrace(VALUE info)
43 {
44 if (NIL_P(info))
45 return Qnil;
46 info = rb_funcall(info, rb_intern("backtrace"), 0);
47 if (NIL_P(info))
48 return Qnil;
49 return rb_check_backtrace(info);
50 }
51
52 VALUE
53 rb_get_backtrace(VALUE info)
54 {
55 return get_backtrace(info);
56 }
57
58 VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt);
59
60 static void
61 set_backtrace(VALUE info, VALUE bt)
62 {
63 ID set_backtrace = rb_intern("set_backtrace");
64
65 if (rb_backtrace_p(bt)) {
66 if (rb_method_basic_definition_p(CLASS_OF(info), set_backtrace)) {
67 rb_exc_set_backtrace(info, bt);
68 return;
69 }
70 else {
71 bt = rb_backtrace_to_str_ary(bt);
72 }
73 }
74 rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
75 }
76
77 static void
78 error_print(void)
79 {
80 volatile VALUE errat = Qnil; /* OK */
81 rb_thread_t *th = GET_THREAD();
82 VALUE errinfo = th->errinfo;
83 int raised_flag = th->raised_flag;
84 volatile VALUE eclass, e;
85 const char *volatile einfo;
86 volatile long elen;
87
88 if (NIL_P(errinfo))
89 return;
90 rb_thread_raised_clear(th);
91
92 TH_PUSH_TAG(th);
93 if (TH_EXEC_TAG() == 0) {
94 errat = get_backtrace(errinfo);
95 }
96 else {
97 errat = Qnil;
98 }
99 if (TH_EXEC_TAG())
100 goto error;
101 if (NIL_P(errat)) {
102 const char *file = rb_sourcefile();
103 int line = rb_sourceline();
104 if (!file)
105 warn_printf("%d", line);
106 else if (!line)
107 warn_printf("%s", file);
108 else
109 warn_printf("%s:%d", file, line);
110 }
111 else if (RARRAY_LEN(errat) == 0) {
112 error_pos();
113 }
114 else {
115 VALUE mesg = RARRAY_PTR(errat)[0];
116
117 if (NIL_P(mesg))
118 error_pos();
119 else {
120 warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
121 }
122 }
123
124 eclass = CLASS_OF(errinfo);
125 if (TH_EXEC_TAG() == 0) {
126 e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
127 StringValue(e);
128 einfo = RSTRING_PTR(e);
129 elen = RSTRING_LEN(e);
130 }
131 else {
132 einfo = "";
133 elen = 0;
134 }
135 if (TH_EXEC_TAG())
136 goto error;
137 if (eclass == rb_eRuntimeError && elen == 0) {
138 warn_print(": unhandled exception\n");
139 }
140 else {
141 VALUE epath;
142
143 epath = rb_class_name(eclass);
144 if (elen == 0) {
145 warn_print(": ");
146 warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
147 warn_print("\n");
148 }
149 else {
150 char *tail = 0;
151 long len = elen;
152
153 if (RSTRING_PTR(epath)[0] == '#')
154 epath = 0;
155 if ((tail = memchr(einfo, '\n', elen)) != 0) {
156 len = tail - einfo;
157 tail++; /* skip newline */
158 }
159 warn_print(": ");
160 warn_print2(einfo, len);
161 if (epath) {
162 warn_print(" (");
163 warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
164 warn_print(")\n");
165 }
166 if (tail) {
167 warn_print2(tail, elen - len - 1);
168 if (einfo[elen-1] != '\n') warn_print2("\n", 1);
169 }
170 }
171 }
172
173 if (!NIL_P(errat)) {
174 long i;
175 long len = RARRAY_LEN(errat);
176 VALUE *ptr = RARRAY_PTR(errat);
177 int skip = eclass == rb_eSysStackError;
178
179 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
180 #define TRACE_HEAD 8
181 #define TRACE_TAIL 5
182
183 for (i = 1; i < len; i++) {
184 if (RB_TYPE_P(ptr[i], T_STRING)) {
185 warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
186 }
187 if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
188 warn_printf("\t ... %ld levels...\n",
189 len - TRACE_HEAD - TRACE_TAIL);
190 i = len - TRACE_TAIL;
191 }
192 }
193 }
194 error:
195 TH_POP_TAG();
196 rb_thread_raised_set(th, raised_flag);
197 }
198
199 void
200 ruby_error_print(void)
201 {
202 error_print();
203 }
204
205 void
206 rb_print_undef(VALUE klass, ID id, int scope)
207 {
208 const char *v;
209
210 switch (scope) {
211 default:
212 case NOEX_PUBLIC: v = ""; break;
213 case NOEX_PRIVATE: v = " private"; break;
214 case NOEX_PROTECTED: v = " protected"; break;
215 }
216 rb_name_error(id, "undefined%s method `%"PRIsVALUE"' for %s `%"PRIsVALUE"'", v,
217 QUOTE_ID(id),
218 (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",
219 rb_class_name(klass));
220 }
221
222 void
223 rb_print_undef_str(VALUE klass, VALUE name)
224 {
225 rb_name_error_str(name, "undefined method `%"PRIsVALUE"' for %s `%"PRIsVALUE"'",
226 QUOTE(name),
227 (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",
228 rb_class_name(klass));
229 }
230
231 static int
232 sysexit_status(VALUE err)
233 {
234 VALUE st = rb_iv_get(err, "status");
235 return NUM2INT(st);
236 }
237
238 static int
239 error_handle(int ex)
240 {
241 int status = EXIT_FAILURE;
242 rb_thread_t *th = GET_THREAD();
243
244 if (rb_threadptr_set_raised(th))
245 return EXIT_FAILURE;
246 switch (ex & TAG_MASK) {
247 case 0:
248 status = EXIT_SUCCESS;
249 break;
250
251 case TAG_RETURN:
252 error_pos();
253 warn_print(": unexpected return\n");
254 break;
255 case TAG_NEXT:
256 error_pos();
257 warn_print(": unexpected next\n");
258 break;
259 case TAG_BREAK:
260 error_pos();
261 warn_print(": unexpected break\n");
262 break;
263 case TAG_REDO:
264 error_pos();
265 warn_print(": unexpected redo\n");
266 break;
267 case TAG_RETRY:
268 error_pos();
269 warn_print(": retry outside of rescue clause\n");
270 break;
271 case TAG_THROW:
272 /* TODO: fix me */
273 error_pos();
274 warn_printf(": unexpected throw\n");
275 break;
276 case TAG_RAISE: {
277 VALUE errinfo = GET_THREAD()->errinfo;
278 if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
279 status = sysexit_status(errinfo);
280 }
281 else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
282 /* no message when exiting by signal */
283 }
284 else {
285 error_print();
286 }
287 break;
288 }
289 case TAG_FATAL:
290 error_print();
291 break;
292 default:
293 rb_bug("Unknown longjmp status %d", ex);
294 break;
295 }
296 rb_threadptr_reset_raised(th);
297 return status;
298 }
RB_TYPE_P
#define RB_TYPE_P(obj, type)
RARRAY_PTR
RARRAY_PTR(q->result)[0]
warn_print2
#define warn_print2(x, l)
Definition: eval_error.c:19
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:290
tail
#define tail
Definition: st.c:108
TAG_NEXT
#define TAG_NEXT
Definition: eval_intern.h:137
th
static VALUE VALUE th
Definition: tcltklib.c:2948
rb_eSignal
VALUE rb_eSignal
Definition: error.c:507
TAG_THROW
#define TAG_THROW
Definition: eval_intern.h:141
i
ssize_t i
Definition: bigdecimal.c:5655
TAG_BREAK
#define TAG_BREAK
Definition: eval_intern.h:136
info
Tcl_CmdInfo * info
Definition: tcltklib.c:1463
error_pos
static void error_pos(void)
Definition: eval_error.c:22
set_backtrace
static void set_backtrace(VALUE info, VALUE bt)
Definition: eval_error.c:61
rb_iv_get
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2583
status
int status
Definition: tcltklib.c:2197
sysexit_status
static int sysexit_status(VALUE err)
Definition: eval_error.c:232
exc
VALUE exc
Definition: tcltklib.c:3096
QUOTE_ID
#define QUOTE_ID(id)
RSTRING_PTR
#define RSTRING_PTR(str)
CLASS_OF
#define CLASS_OF(v)
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
rb_print_undef_str
void rb_print_undef_str(VALUE klass, VALUE name)
Definition: eval_error.c:223
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
TH_EXEC_TAG
#define TH_EXEC_TAG()
Definition: eval_intern.h:111
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:383
rb_backtrace_to_str_ary
VALUE rb_backtrace_to_str_ary(VALUE obj)
Definition: vm_backtrace.c:586
TAG_RAISE
#define TAG_RAISE
Definition: eval_intern.h:140
rb_thread_struct
Definition: vm_core.h:493
args
VALUE VALUE args
Definition: tcltklib.c:2561
einfo
VALUE einfo
Definition: tcltklib.c:847
rb_name_error_str
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:914
fmt
const char * fmt
Definition: tcltklib.c:841
rb_name_error
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:899
TAG_FATAL
#define TAG_FATAL
Definition: eval_intern.h:142
TH_POP_TAG
#define TH_POP_TAG()
Definition: eval_intern.h:101
rb_obj_is_instance_of
VALUE rb_obj_is_instance_of(VALUE, VALUE)
Definition: object.c:545
get_backtrace
static VALUE get_backtrace(VALUE info)
Definition: eval_error.c:42
error_handle
static int error_handle(int ex)
Definition: eval_error.c:239
rb_threadptr_set_raised
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:2043
RARRAY_LEN
#define RARRAY_LEN(a)
Qnil
#define Qnil
Definition: tcltklib.c:1896
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:510
vsnprintf
vsnprintf(buf, BUFSIZ, fmt, args)
rb_eSysStackError
VALUE rb_eSysStackError
Definition: eval.c:30
ID
unsigned long ID
Definition: ripper.y:105
va_end
va_end(args)
RSTRING_LEN
#define RSTRING_LEN(str)
rb_get_backtrace
VALUE rb_get_backtrace(VALUE info)
Definition: eval_error.c:53
T_STRING
#define T_STRING
TRACE_MAX
#define TRACE_MAX
rb_sourcefile
#define rb_sourcefile()
Definition: tcltklib.c:97
TAG_REDO
#define TAG_REDO
Definition: eval_intern.h:139
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
err
int err
Definition: win32.c:87
rb_exc_set_backtrace
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt)
Definition: error.c:747
EXIT_FAILURE
#define EXIT_FAILURE
Definition: eval_intern.h:24
TAG_MASK
#define TAG_MASK
Definition: eval_intern.h:143
rb_thread_raised_clear
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:173
TAG_RETURN
#define TAG_RETURN
Definition: eval_intern.h:135
EXIT_SUCCESS
#define EXIT_SUCCESS
Definition: error.c:31
StringValue
#define StringValue(v)
QUOTE
#define QUOTE(str)
TRACE_HEAD
#define TRACE_HEAD
rb_thread_raised_set
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:170
TRACE_TAIL
#define TRACE_TAIL
ex
ssize_t ex
Definition: bigdecimal.c:5087
rb_threadptr_reset_raised
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:2053
NOEX_PROTECTED
Definition: method.h:26
TH_PUSH_TAG
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:94
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:816
rb_thread_struct::raised_flag
int raised_flag
Definition: vm_core.h:502
ptr
return ptr
Definition: tcltklib.c:784
ruby_error_print
void ruby_error_print(void)
Definition: eval_error.c:200
va_init_list
#define va_init_list(a, b)
Definition: tcltklib.c:61
warn_printf
static void warn_printf(const char *fmt,...)
Definition: eval_error.c:7
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:582
rb_method_basic_definition_p
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1498
rb_frame_callee
ID rb_frame_callee(void)
Definition: eval.c:919
klass
klass
Definition: tcltklib.c:3504
rb_check_backtrace
VALUE rb_check_backtrace(VALUE bt)
Definition: error.c:710
rb_write_error
void rb_write_error(const char *)
Definition: io.c:7064
T_MODULE
#define T_MODULE
rb_backtrace_p
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:413
NUM2INT
#define NUM2INT(x)
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17005
PRIsVALUE
#define PRIsVALUE
e
BDIGIT e
Definition: bigdecimal.c:5085
VALUE
unsigned long VALUE
Definition: ripper.y:104
warn_print
#define warn_print(x)
Definition: eval_error.c:18
rb_print_undef
void rb_print_undef(VALUE klass, ID id, int scope)
Definition: eval_error.c:206
NOEX_PUBLIC
Definition: method.h:23
error_print
static void error_print(void)
Definition: eval_error.c:78
rb_intern
#define rb_intern(str)
v
BDIGIT v
Definition: bigdecimal.c:5656
rb_eSystemExit
VALUE rb_eSystemExit
Definition: error.c:505
name
const char * name
Definition: nkf.c:208
rb_thread_struct::errinfo
VALUE errinfo
Definition: vm_core.h:542
GET_THREAD
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:883
NOEX_PRIVATE
Definition: method.h:25
st
Tcl_Interp *int * st
Definition: stubs.c:510
TAG_RETRY
#define TAG_RETRY
Definition: eval_intern.h:138
len
size_t len
Definition: tcltklib.c:3568