1:
2:
3:
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;
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++;
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: }
175: }
176: }
177:
178: if (!NIL_P(errat)) {
179: long i;
180: long len = RARRAY_LEN(errat);
181: VALUE *ptr = RARRAY_PTR(errat);
182: int skip = eclass == rb_eSysStackError;
183:
184: #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
185: #define TRACE_HEAD 8
186: #define TRACE_TAIL 5
187:
188: for (i = 1; i < len; i++) {
189: if (TYPE(ptr[i]) == T_STRING) {
190: warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
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: POP_TAG();
201: }
202:
203: void
204: ruby_error_print(void)
205: {
206: error_print();
207: }
208:
209: void
210: rb_print_undef(VALUE klass, ID id, int scope)
211: {
212: char *v;
213:
214: switch (scope) {
215: default:
216: case NOEX_PUBLIC: v = ""; break;
217: case NOEX_PRIVATE: v = " private"; break;
218: case NOEX_PROTECTED: v = " protected"; break;
219: }
220: rb_name_error(id, "undefined%s method `%s' for %s `%s'", v,
221: rb_id2name(id),
222: (TYPE(klass) == T_MODULE) ? "module" : "class",
223: rb_class2name(klass));
224: }
225:
226: static int
227: sysexit_status(VALUE err)
228: {
229: VALUE st = rb_iv_get(err, "status");
230: return NUM2INT(st);
231: }
232:
233: static int
234: error_handle(int ex)
235: {
236: int status = EXIT_FAILURE;
237: rb_thread_t *th = GET_THREAD();
238:
239: if (thread_set_raised(th))
240: return EXIT_FAILURE;
241: switch (ex & TAG_MASK) {
242: case 0:
243: status = EXIT_SUCCESS;
244: break;
245:
246: case TAG_RETURN:
247: error_pos();
248: warn_print(": unexpected return\n");
249: break;
250: case TAG_NEXT:
251: error_pos();
252: warn_print(": unexpected next\n");
253: break;
254: case TAG_BREAK:
255: error_pos();
256: warn_print(": unexpected break\n");
257: break;
258: case TAG_REDO:
259: error_pos();
260: warn_print(": unexpected redo\n");
261: break;
262: case TAG_RETRY:
263: error_pos();
264: warn_print(": retry outside of rescue clause\n");
265: break;
266: case TAG_THROW:
267:
268: error_pos();
269: warn_printf(": unexpected throw\n");
270: break;
271: case TAG_RAISE:
272: case TAG_FATAL: {
273: VALUE errinfo = GET_THREAD()->errinfo;
274: if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
275: status = sysexit_status(errinfo);
276: }
277: else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
278:
279: }
280: else {
281: error_print();
282: }
283: break;
284: }
285: default:
286: rb_bug("Unknown longjmp status %d", ex);
287: break;
288: }
289: thread_reset_raised(th);
290: return status;
291: }