Ruby 2.1.5p273(2014-11-13revision48405)

- 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 }
warn_print2
#define warn_print2(x, l)
Definition: eval_error.c:19
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:327
tail
#define tail
Definition: st.c:108
TAG_NEXT
#define TAG_NEXT
Definition: eval_intern.h:190
rb_eSignal
VALUE rb_eSignal
Definition: error.c:544
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:630
TAG_THROW
#define TAG_THROW
Definition: eval_intern.h:194
QUOTE_ID
#define QUOTE_ID(id)
Definition: internal.h:715
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:440
T_MODULE
#define T_MODULE
Definition: ruby.h:480
TAG_BREAK
#define TAG_BREAK
Definition: eval_intern.h:189
error_pos
static void error_pos(void)
Definition: eval_error.c:23
set_backtrace
static void set_backtrace(VALUE info, VALUE bt)
Definition: eval_error.c:63
sysexit_status
static int sysexit_status(VALUE err)
Definition: eval_error.c:238
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
rb_print_undef_str
void rb_print_undef_str(VALUE klass, VALUE name)
Definition: eval_error.c:229
rb_iv_get
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2601
TH_EXEC_TAG
#define TH_EXEC_TAG()
Definition: eval_intern.h:165
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
TAG_RAISE
#define TAG_RAISE
Definition: eval_intern.h:193
rb_thread_struct
Definition: vm_core.h:524
rb_name_error_str
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:982
rb_name_error
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:967
TAG_FATAL
#define TAG_FATAL
Definition: eval_intern.h:195
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
TH_POP_TAG
#define TH_POP_TAG()
Definition: eval_intern.h:128
get_backtrace
static VALUE get_backtrace(VALUE info)
Definition: eval_error.c:44
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:391
error_handle
static int error_handle(int ex)
Definition: eval_error.c:245
rb_threadptr_set_raised
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:2096
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:547
rb_eSysStackError
VALUE rb_eSysStackError
Definition: eval.c:28
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
rb_get_backtrace
VALUE rb_get_backtrace(VALUE info)
Definition: eval_error.c:55
warn_print_str
#define warn_print_str(x)
Definition: eval_error.c:20
TRACE_MAX
#define TRACE_MAX
rb_sourcefile
#define rb_sourcefile()
Definition: tcltklib.c:98
TAG_REDO
#define TAG_REDO
Definition: eval_intern.h:192
err
int err
Definition: win32.c:114
EXIT_FAILURE
#define EXIT_FAILURE
Definition: eval_intern.h:24
TAG_MASK
#define TAG_MASK
Definition: eval_intern.h:196
rb_backtrace_p
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:417
rb_thread_raised_clear
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:226
TAG_RETURN
#define TAG_RETURN
Definition: eval_intern.h:188
rb_backtrace_to_str_ary
VALUE rb_backtrace_to_str_ary(VALUE obj)
Definition: vm_backtrace.c:590
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
EXIT_SUCCESS
#define EXIT_SUCCESS
Definition: error.c:29
rb_exc_set_backtrace
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt)
Definition: error.c:807
TRACE_HEAD
#define TRACE_HEAD
rb_thread_raised_set
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:223
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:137
ID
unsigned long ID
Definition: ruby.h:89
Qnil
#define Qnil
Definition: ruby.h:427
TRACE_TAIL
#define TRACE_TAIL
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_threadptr_reset_raised
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:2106
NOEX_PROTECTED
Definition: method.h:28
TH_PUSH_TAG
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:122
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:409
rb_thread_struct::raised_flag
int raised_flag
Definition: vm_core.h:533
ruby_error_print
void ruby_error_print(void)
Definition: eval_error.c:206
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
va_init_list
#define va_init_list(a, b)
Definition: tcltklib.c:62
warn_printf
static void warn_printf(const char *fmt,...)
Definition: eval_error.c:7
rb_write_error_str
void rb_write_error_str(VALUE mesg)
Definition: io.c:7163
rb_obj_is_instance_of
VALUE rb_obj_is_instance_of(VALUE, VALUE)
Definition: object.c:615
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:1001
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
rb_frame_callee
ID rb_frame_callee(void)
Definition: eval.c:949
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:1679
T_STRING
#define T_STRING
Definition: ruby.h:482
rb_method_basic_definition_p
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1573
rb_check_backtrace
VALUE rb_check_backtrace(VALUE bt)
Definition: error.c:769
name
const char * name
Definition: nkf.c:208
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17230
warn_print
#define warn_print(x)
Definition: eval_error.c:18
QUOTE
#define QUOTE(str)
Definition: internal.h:714
rb_print_undef
void rb_print_undef(VALUE klass, ID id, int scope)
Definition: eval_error.c:212
NOEX_PUBLIC
Definition: method.h:25
error_print
static void error_print(void)
Definition: eval_error.c:80
rb_intern
#define rb_intern(str)
rb_vsprintf
VALUE rb_vsprintf(const char *, va_list)
Definition: sprintf.c:1244
rb_eSystemExit
VALUE rb_eSystemExit
Definition: error.c:542
Qundef
#define Qundef
Definition: ruby.h:428
rb_thread_struct::errinfo
VALUE errinfo
Definition: vm_core.h:573
GET_THREAD
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:927
NOEX_PRIVATE
Definition: method.h:27
TAG_RETRY
#define TAG_RETRY
Definition: eval_intern.h:191