Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 293 lines (263 sloc) 5.67 kB
511dc44 initial import
Laurent Sansonetti authored
1 /* -*-c-*- */
2 /*
3 * included by eval.c
4 */
5
6 const char *
7 rb_sourcefile(void)
8 {
9 rb_thread_t *th = GET_THREAD();
10 rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
11
12 if (cfp) {
13 return RSTRING_PTR(cfp->iseq->filename);
14 }
15 else {
16 return 0;
17 }
18 }
19
20 int
21 rb_sourceline(void)
22 {
23 rb_thread_t *th = GET_THREAD();
24 rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
25
26 if (cfp) {
27 return vm_get_sourceline(cfp);
28 }
29 else {
30 return 0;
31 }
32 }
33
34 static void
35 warn_printf(const char *fmt, ...)
36 {
37 char buf[BUFSIZ];
38 va_list args;
39
40 va_init_list(args, fmt);
41 vsnprintf(buf, BUFSIZ, fmt, args);
42 va_end(args);
43 rb_write_error(buf);
44 }
45
46 #define warn_print(x) rb_write_error(x)
47 #define warn_print2(x,l) rb_write_error2(x,l)
48
49 static void
50 error_pos(void)
51 {
52 const char *sourcefile = rb_sourcefile();
53 int sourceline = rb_sourceline();
54
55 if (sourcefile) {
56 if (sourceline == 0) {
57 warn_printf("%s", sourcefile);
58 }
59 else if (rb_frame_callee()) {
60 warn_printf("%s:%d:in `%s'", sourcefile, sourceline,
61 rb_id2name(rb_frame_callee()));
62 }
63 else {
64 warn_printf("%s:%d", sourcefile, sourceline);
65 }
66 }
67 }
68
69 VALUE rb_check_backtrace(VALUE);
70
71 static VALUE
72 get_backtrace(VALUE info)
73 {
74 if (NIL_P(info))
75 return Qnil;
76 info = rb_funcall(info, rb_intern("backtrace"), 0);
77 if (NIL_P(info))
78 return Qnil;
79 return rb_check_backtrace(info);
80 }
81
82 static void
83 set_backtrace(VALUE info, VALUE bt)
84 {
85 rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
86 }
87
88 static void
89 error_print(void)
90 {
91 VALUE errat = Qnil; /* OK */
92 VALUE errinfo = GET_THREAD()->errinfo;
93 volatile VALUE eclass, e;
94 char *einfo;
95 long elen;
96
97 if (NIL_P(errinfo))
98 return;
99
100 PUSH_TAG();
101 if (EXEC_TAG() == 0) {
102 errat = get_backtrace(errinfo);
103 }
104 else {
105 errat = Qnil;
106 }
107 if (EXEC_TAG())
108 goto error;
109 if (NIL_P(errat)) {
110 const char *file = rb_sourcefile();
111 int line = rb_sourceline();
112 if (file)
113 warn_printf("%s:%d", file, line);
114 else
115 warn_printf("%d", line);
116 }
117 else if (RARRAY_LEN(errat) == 0) {
118 error_pos();
119 }
120 else {
121 VALUE mesg = RARRAY_PTR(errat)[0];
122
123 if (NIL_P(mesg))
124 error_pos();
125 else {
126 warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
127 }
128 }
129
130 eclass = CLASS_OF(errinfo);
131 if (EXEC_TAG() == 0) {
132 e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
133 StringValue(e);
134 einfo = RSTRING_PTR(e);
135 elen = RSTRING_LEN(e);
136 }
137 else {
138 einfo = "";
139 elen = 0;
140 }
141 if (EXEC_TAG())
142 goto error;
143 if (eclass == rb_eRuntimeError && elen == 0) {
144 warn_print(": unhandled exception\n");
145 }
146 else {
147 VALUE epath;
148
149 epath = rb_class_name(eclass);
150 if (elen == 0) {
151 warn_print(": ");
152 warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
153 warn_print("\n");
154 }
155 else {
156 char *tail = 0;
157 long len = elen;
158
159 if (RSTRING_PTR(epath)[0] == '#')
160 epath = 0;
161 if ((tail = memchr(einfo, '\n', elen)) != 0) {
162 len = tail - einfo;
163 tail++; /* skip newline */
164 }
165 warn_print(": ");
166 warn_print2(einfo, len);
167 if (epath) {
168 warn_print(" (");
169 warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
170 warn_print(")\n");
171 }
172 if (tail) {
173 warn_print2(tail, elen - len - 1);
174 if (einfo[elen-1] != '\n') warn_print2("\n", 1);
175 }
176 }
177 }
178
179 if (!NIL_P(errat)) {
180 long i;
181 long len = RARRAY_LEN(errat);
182 VALUE *ptr = RARRAY_PTR(errat);
183 int skip = eclass == rb_eSysStackError;
184
185 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
186 #define TRACE_HEAD 8
187 #define TRACE_TAIL 5
188
189 for (i = 1; i < len; i++) {
190 if (TYPE(ptr[i]) == T_STRING) {
191 warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
192 }
193 if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
194 warn_printf("\t ... %ld levels...\n",
195 len - TRACE_HEAD - TRACE_TAIL);
196 i = len - TRACE_TAIL;
197 }
198 }
199 }
200 error:
201 POP_TAG();
202 }
203
204 void
205 ruby_error_print(void)
206 {
207 error_print();
208 }
209
210 void
211 rb_print_undef(VALUE klass, ID id, int scope)
212 {
213 char *v;
214
215 switch (scope) {
216 default:
217 case NOEX_PUBLIC: v = ""; break;
218 case NOEX_PRIVATE: v = " private"; break;
219 case NOEX_PROTECTED: v = " protected"; break;
220 }
221 rb_name_error(id, "undefined%s method `%s' for %s `%s'", v,
222 rb_id2name(id),
223 (TYPE(klass) == T_MODULE) ? "module" : "class",
224 rb_class2name(klass));
225 }
226
227 static int
228 sysexit_status(VALUE err)
229 {
230 VALUE st = rb_iv_get(err, "status");
231 return NUM2INT(st);
232 }
233
234 static int
235 error_handle(int ex)
236 {
237 int status = EXIT_FAILURE;
238 rb_thread_t *th = GET_THREAD();
239
6537c7a merging with trunk
Laurent Sansonetti authored
240 if (rb_thread_set_raised(th))
511dc44 initial import
Laurent Sansonetti authored
241 return EXIT_FAILURE;
242 switch (ex & TAG_MASK) {
243 case 0:
244 status = EXIT_SUCCESS;
245 break;
246
247 case TAG_RETURN:
248 error_pos();
249 warn_print(": unexpected return\n");
250 break;
251 case TAG_NEXT:
252 error_pos();
253 warn_print(": unexpected next\n");
254 break;
255 case TAG_BREAK:
256 error_pos();
257 warn_print(": unexpected break\n");
258 break;
259 case TAG_REDO:
260 error_pos();
261 warn_print(": unexpected redo\n");
262 break;
263 case TAG_RETRY:
264 error_pos();
265 warn_print(": retry outside of rescue clause\n");
266 break;
267 case TAG_THROW:
268 /* TODO: fix me */
269 error_pos();
270 warn_printf(": unexpected throw\n");
271 break;
272 case TAG_RAISE:
273 case TAG_FATAL: {
274 VALUE errinfo = GET_THREAD()->errinfo;
275 if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
276 status = sysexit_status(errinfo);
277 }
278 else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
279 /* no message when exiting by signal */
280 }
281 else {
282 error_print();
283 }
284 break;
285 }
286 default:
287 rb_bug("Unknown longjmp status %d", ex);
288 break;
289 }
6537c7a merging with trunk
Laurent Sansonetti authored
290 rb_thread_reset_raised(th);
511dc44 initial import
Laurent Sansonetti authored
291 return status;
292 }
Something went wrong with that request. Please try again.