Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 273 lines (246 sloc) 5.325 kB
511dc44 initial import
Laurent Sansonetti authored
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 VALUE rb_check_backtrace(VALUE);
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
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
54 VALUE
55 rb_get_backtrace(VALUE info)
56 {
57 return get_backtrace(info);
58 }
59
511dc44 initial import
Laurent Sansonetti authored
60 static void
61 set_backtrace(VALUE info, VALUE bt)
62 {
63 rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
64 }
65
66 static void
67 error_print(void)
68 {
69 VALUE errat = Qnil; /* OK */
70 VALUE errinfo = GET_THREAD()->errinfo;
71 volatile VALUE eclass, e;
cb88a4e lots of misc fixes and performance/memory usage improvements
Laurent Sansonetti authored
72 const char *einfo;
511dc44 initial import
Laurent Sansonetti authored
73 long elen;
74
75 if (NIL_P(errinfo))
76 return;
77
78 PUSH_TAG();
79 if (EXEC_TAG() == 0) {
80 errat = get_backtrace(errinfo);
81 }
82 else {
83 errat = Qnil;
84 }
85 if (EXEC_TAG())
86 goto error;
87 if (NIL_P(errat)) {
88 const char *file = rb_sourcefile();
89 int line = rb_sourceline();
90 if (file)
91 warn_printf("%s:%d", file, line);
92 else
93 warn_printf("%d", line);
94 }
95 else if (RARRAY_LEN(errat) == 0) {
96 error_pos();
97 }
98 else {
f0849e8 - Hash is now a shortcut to NSMutableDictionary.
Laurent Sansonetti authored
99 VALUE mesg = RARRAY_AT(errat, 0);
511dc44 initial import
Laurent Sansonetti authored
100
101 if (NIL_P(mesg))
102 error_pos();
103 else {
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
104 warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
511dc44 initial import
Laurent Sansonetti authored
105 }
106 }
107
108 eclass = CLASS_OF(errinfo);
109 if (EXEC_TAG() == 0) {
110 e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
111 StringValue(e);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
112 einfo = RSTRING_PTR(e);
113 elen = RSTRING_LEN(e);
511dc44 initial import
Laurent Sansonetti authored
114 }
115 else {
116 einfo = "";
117 elen = 0;
118 }
119 if (EXEC_TAG())
120 goto error;
121 if (eclass == rb_eRuntimeError && elen == 0) {
122 warn_print(": unhandled exception\n");
123 }
124 else {
125 VALUE epath;
126
127 epath = rb_class_name(eclass);
128 if (elen == 0) {
129 warn_print(": ");
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
130 warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
511dc44 initial import
Laurent Sansonetti authored
131 warn_print("\n");
132 }
133 else {
134 char *tail = 0;
135 long len = elen;
136
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
137 if (RSTRING_PTR(epath)[0] == '#')
511dc44 initial import
Laurent Sansonetti authored
138 epath = 0;
139 if ((tail = memchr(einfo, '\n', elen)) != 0) {
140 len = tail - einfo;
141 tail++; /* skip newline */
142 }
143 warn_print(": ");
144 warn_print2(einfo, len);
145 if (epath) {
146 warn_print(" (");
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
147 warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
511dc44 initial import
Laurent Sansonetti authored
148 warn_print(")\n");
149 }
150 if (tail) {
151 warn_print2(tail, elen - len - 1);
152 if (einfo[elen-1] != '\n') warn_print2("\n", 1);
153 }
154 }
155 }
156
157 if (!NIL_P(errat)) {
158 long i;
159 long len = RARRAY_LEN(errat);
160 int skip = eclass == rb_eSysStackError;
161
162 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
163 #define TRACE_HEAD 8
164 #define TRACE_TAIL 5
165
166 for (i = 1; i < len; i++) {
f0849e8 - Hash is now a shortcut to NSMutableDictionary.
Laurent Sansonetti authored
167 VALUE v = RARRAY_AT(errat, i);
168 if (TYPE(v) == T_STRING) {
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
169 warn_printf("\tfrom %s\n", RSTRING_PTR(v));
511dc44 initial import
Laurent Sansonetti authored
170 }
171 if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
172 warn_printf("\t ... %ld levels...\n",
173 len - TRACE_HEAD - TRACE_TAIL);
174 i = len - TRACE_TAIL;
175 }
176 }
177 }
178 error:
179 POP_TAG();
180 }
181
182 void
183 ruby_error_print(void)
184 {
185 error_print();
186 }
187
188 void
189 rb_print_undef(VALUE klass, ID id, int scope)
190 {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
191 const char *v;
511dc44 initial import
Laurent Sansonetti authored
192
193 switch (scope) {
194 default:
195 case NOEX_PUBLIC: v = ""; break;
196 case NOEX_PRIVATE: v = " private"; break;
197 case NOEX_PROTECTED: v = " protected"; break;
198 }
199 rb_name_error(id, "undefined%s method `%s' for %s `%s'", v,
200 rb_id2name(id),
201 (TYPE(klass) == T_MODULE) ? "module" : "class",
202 rb_class2name(klass));
203 }
204
205 static int
206 sysexit_status(VALUE err)
207 {
208 VALUE st = rb_iv_get(err, "status");
209 return NUM2INT(st);
210 }
211
212 static int
213 error_handle(int ex)
214 {
215 int status = EXIT_FAILURE;
216 rb_thread_t *th = GET_THREAD();
217
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
218 if (rb_thread_set_raised(th))
511dc44 initial import
Laurent Sansonetti authored
219 return EXIT_FAILURE;
220 switch (ex & TAG_MASK) {
221 case 0:
222 status = EXIT_SUCCESS;
223 break;
224
225 case TAG_RETURN:
226 error_pos();
227 warn_print(": unexpected return\n");
228 break;
229 case TAG_NEXT:
230 error_pos();
231 warn_print(": unexpected next\n");
232 break;
233 case TAG_BREAK:
234 error_pos();
235 warn_print(": unexpected break\n");
236 break;
237 case TAG_REDO:
238 error_pos();
239 warn_print(": unexpected redo\n");
240 break;
241 case TAG_RETRY:
242 error_pos();
243 warn_print(": retry outside of rescue clause\n");
244 break;
245 case TAG_THROW:
246 /* TODO: fix me */
247 error_pos();
248 warn_printf(": unexpected throw\n");
249 break;
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
250 case TAG_RAISE: {
511dc44 initial import
Laurent Sansonetti authored
251 VALUE errinfo = GET_THREAD()->errinfo;
252 if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
253 status = sysexit_status(errinfo);
254 }
255 else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
256 /* no message when exiting by signal */
257 }
258 else {
259 error_print();
260 }
261 break;
262 }
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
263 case TAG_FATAL:
264 error_print();
265 break;
511dc44 initial import
Laurent Sansonetti authored
266 default:
267 rb_bug("Unknown longjmp status %d", ex);
268 break;
269 }
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
270 rb_thread_reset_raised(th);
511dc44 initial import
Laurent Sansonetti authored
271 return status;
272 }
Something went wrong with that request. Please try again.