Ruby
2.1.3p242(2014-09-19revision47630)
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
VALUE
str;
10
va_list args;
11
12
va_init_list
(args, fmt);
13
str =
rb_vsprintf
(fmt, args);
14
va_end(args);
15
rb_write_error_str
(str);
16
}
17
18
#define warn_print(x) rb_write_error(x)
19
#define warn_print2(x,l) rb_write_error2((x),(l))
20
#define warn_print_str(x) rb_write_error_str(x)
21
22
static
void
23
error_pos
(
void
)
24
{
25
const
char
*sourcefile =
rb_sourcefile
();
26
int
sourceline =
rb_sourceline
();
27
28
if
(sourcefile) {
29
ID
caller_name;
30
if
(sourceline == 0) {
31
warn_printf
(
"%s"
, sourcefile);
32
}
33
else
if
((caller_name =
rb_frame_callee
()) != 0) {
34
warn_printf
(
"%s:%d:in `%s'"
, sourcefile, sourceline,
35
rb_id2name
(caller_name));
36
}
37
else
{
38
warn_printf
(
"%s:%d"
, sourcefile, sourceline);
39
}
40
}
41
}
42
43
static
VALUE
44
get_backtrace
(
VALUE
info)
45
{
46
if
(
NIL_P
(info))
47
return
Qnil
;
48
info =
rb_funcall
(info,
rb_intern
(
"backtrace"
), 0);
49
if
(
NIL_P
(info))
50
return
Qnil
;
51
return
rb_check_backtrace
(info);
52
}
53
54
VALUE
55
rb_get_backtrace
(
VALUE
info)
56
{
57
return
get_backtrace
(info);
58
}
59
60
VALUE
rb_exc_set_backtrace
(
VALUE
exc,
VALUE
bt);
61
62
static
void
63
set_backtrace
(
VALUE
info,
VALUE
bt)
64
{
65
ID
set_backtrace
=
rb_intern
(
"set_backtrace"
);
66
67
if
(
rb_backtrace_p
(bt)) {
68
if
(
rb_method_basic_definition_p
(
CLASS_OF
(info), set_backtrace)) {
69
rb_exc_set_backtrace
(info, bt);
70
return
;
71
}
72
else
{
73
bt =
rb_backtrace_to_str_ary
(bt);
74
}
75
}
76
rb_funcall
(info,
rb_intern
(
"set_backtrace"
), 1, bt);
77
}
78
79
static
void
80
error_print
(
void
)
81
{
82
volatile
VALUE
errat =
Qundef
;
83
rb_thread_t
*th =
GET_THREAD
();
84
VALUE
errinfo = th->
errinfo
;
85
int
raised_flag = th->
raised_flag
;
86
volatile
VALUE
eclass =
Qundef
, e =
Qundef
;
87
const
char
*
volatile
einfo;
88
volatile
long
elen;
89
90
if
(
NIL_P
(errinfo))
91
return
;
92
rb_thread_raised_clear
(th);
93
94
TH_PUSH_TAG
(th);
95
if
(
TH_EXEC_TAG
() == 0) {
96
errat =
get_backtrace
(errinfo);
97
}
98
else
if
(errat ==
Qundef
) {
99
errat =
Qnil
;
100
}
101
else
if
(eclass ==
Qundef
|| e !=
Qundef
) {
102
goto
error;
103
}
104
else
{
105
goto
no_message;
106
}
107
if
(
NIL_P
(errat)) {
108
const
char
*file =
rb_sourcefile
();
109
int
line =
rb_sourceline
();
110
if
(!file)
111
warn_printf
(
"%d"
, line);
112
else
if
(!line)
113
warn_printf
(
"%s"
, file);
114
else
115
warn_printf
(
"%s:%d"
, file, line);
116
}
117
else
if
(
RARRAY_LEN
(errat) == 0) {
118
error_pos
();
119
}
120
else
{
121
VALUE
mesg =
RARRAY_AREF
(errat, 0);
122
123
if
(
NIL_P
(mesg))
124
error_pos
();
125
else
{
126
warn_print_str
(mesg);
127
}
128
}
129
130
eclass =
CLASS_OF
(errinfo);
131
if
(eclass !=
Qundef
&&
132
(e =
rb_check_funcall
(errinfo,
rb_intern
(
"message"
), 0, 0)) !=
Qundef
&&
133
(
RB_TYPE_P
(e,
T_STRING
) || !
NIL_P
(e =
rb_check_string_type
(e)))) {
134
einfo =
RSTRING_PTR
(e);
135
elen =
RSTRING_LEN
(e);
136
}
137
else
{
138
no_message:
139
einfo =
""
;
140
elen = 0;
141
}
142
if
(eclass ==
rb_eRuntimeError
&& elen == 0) {
143
warn_print
(
": unhandled exception\n"
);
144
}
145
else
{
146
VALUE
epath;
147
148
epath =
rb_class_name
(eclass);
149
if
(elen == 0) {
150
warn_print
(
": "
);
151
warn_print_str
(epath);
152
warn_print
(
"\n"
);
153
}
154
else
{
155
char
*
tail
= 0;
156
long
len = elen;
157
158
if
(
RSTRING_PTR
(epath)[0] ==
'#'
)
159
epath = 0;
160
if
((tail = memchr(einfo,
'\n'
, elen)) != 0) {
161
len = tail - einfo;
162
tail++;
/* skip newline */
163
}
164
warn_print
(
": "
);
165
warn_print2
(einfo, len);
166
if
(epath) {
167
warn_print
(
" ("
);
168
warn_print_str
(epath);
169
warn_print
(
")\n"
);
170
}
171
if
(tail) {
172
warn_print2
(tail, elen - len - 1);
173
if
(einfo[elen-1] !=
'\n'
)
warn_print2
(
"\n"
, 1);
174
}
175
}
176
}
177
178
if
(!
NIL_P
(errat)) {
179
long
i;
180
long
len =
RARRAY_LEN
(errat);
181
int
skip = eclass ==
rb_eSysStackError
;
182
183
#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
184
#define TRACE_HEAD 8
185
#define TRACE_TAIL 5
186
187
for
(i = 1; i < len; i++) {
188
VALUE
line =
RARRAY_AREF
(errat, i);
189
if
(
RB_TYPE_P
(line,
T_STRING
)) {
190
warn_printf
(
"\tfrom %"
PRIsVALUE
"\n"
, line);
191
}
192
if
(skip && i ==
TRACE_HEAD
&& len >
TRACE_MAX
) {
193
warn_printf
(
"\t ... %ld levels...\n"
,
194
len -
TRACE_HEAD
-
TRACE_TAIL
);
195
i = len -
TRACE_TAIL
;
196
}
197
}
198
}
199
error:
200
TH_POP_TAG
();
201
th->
errinfo
= errinfo;
202
rb_thread_raised_set
(th, raised_flag);
203
}
204
205
void
206
ruby_error_print
(
void
)
207
{
208
error_print
();
209
}
210
211
void
212
rb_print_undef
(
VALUE
klass,
ID
id
,
int
scope)
213
{
214
const
char
*v;
215
216
switch
(scope) {
217
default
:
218
case
NOEX_PUBLIC
: v =
""
;
break
;
219
case
NOEX_PRIVATE
: v =
" private"
;
break
;
220
case
NOEX_PROTECTED
: v =
" protected"
;
break
;
221
}
222
rb_name_error
(
id
,
"undefined%s method `%"
PRIsVALUE
"' for %s `%"
PRIsVALUE
"'"
, v,
223
QUOTE_ID
(
id
),
224
(
RB_TYPE_P
(klass,
T_MODULE
)) ?
"module"
:
"class"
,
225
rb_class_name
(klass));
226
}
227
228
void
229
rb_print_undef_str
(
VALUE
klass,
VALUE
name
)
230
{
231
rb_name_error_str
(name,
"undefined method `%"
PRIsVALUE
"' for %s `%"
PRIsVALUE
"'"
,
232
QUOTE
(name),
233
(
RB_TYPE_P
(klass,
T_MODULE
)) ?
"module"
:
"class"
,
234
rb_class_name
(klass));
235
}
236
237
static
int
238
sysexit_status
(
VALUE
err
)
239
{
240
VALUE
st =
rb_iv_get
(err,
"status"
);
241
return
NUM2INT
(st);
242
}
243
244
static
int
245
error_handle
(
int
ex)
246
{
247
int
status =
EXIT_FAILURE
;
248
rb_thread_t
*th =
GET_THREAD
();
249
250
if
(
rb_threadptr_set_raised
(th))
251
return
EXIT_FAILURE
;
252
switch
(ex &
TAG_MASK
) {
253
case
0:
254
status =
EXIT_SUCCESS
;
255
break
;
256
257
case
TAG_RETURN
:
258
error_pos
();
259
warn_print
(
": unexpected return\n"
);
260
break
;
261
case
TAG_NEXT
:
262
error_pos
();
263
warn_print
(
": unexpected next\n"
);
264
break
;
265
case
TAG_BREAK
:
266
error_pos
();
267
warn_print
(
": unexpected break\n"
);
268
break
;
269
case
TAG_REDO
:
270
error_pos
();
271
warn_print
(
": unexpected redo\n"
);
272
break
;
273
case
TAG_RETRY
:
274
error_pos
();
275
warn_print
(
": retry outside of rescue clause\n"
);
276
break
;
277
case
TAG_THROW
:
278
/* TODO: fix me */
279
error_pos
();
280
warn_printf
(
": unexpected throw\n"
);
281
break
;
282
case
TAG_RAISE
: {
283
VALUE
errinfo =
GET_THREAD
()->
errinfo
;
284
if
(
rb_obj_is_kind_of
(errinfo,
rb_eSystemExit
)) {
285
status =
sysexit_status
(errinfo);
286
}
287
else
if
(
rb_obj_is_instance_of
(errinfo,
rb_eSignal
)) {
288
/* no message when exiting by signal */
289
}
290
else
{
291
error_print
();
292
}
293
break
;
294
}
295
case
TAG_FATAL
:
296
error_print
();
297
break
;
298
default
:
299
rb_bug
(
"Unknown longjmp status %d"
, ex);
300
break
;
301
}
302
rb_threadptr_reset_raised
(th);
303
return
status;
304
}
305
Generated on Mon Sep 22 2014 11:05:20 for Ruby by
1.8.2