* process.c (rb_spawn_internal): new function to specify
[ruby-svn.git] / eval_error.c
blobaef3226f99e499c8a5a48f3f791a87626089bd3d
1 /* -*-c-*- */
2 /*
3 * included by eval.c
4 */
6 const char *
7 rb_sourcefile(void)
9 rb_thread_t *th = GET_THREAD();
10 rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
12 if (cfp) {
13 return RSTRING_PTR(cfp->iseq->filename);
15 else {
16 return 0;
20 int
21 rb_sourceline(void)
23 rb_thread_t *th = GET_THREAD();
24 rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
26 if (cfp) {
27 return vm_get_sourceline(cfp);
29 else {
30 return 0;
34 static void
35 warn_printf(const char *fmt, ...)
37 char buf[BUFSIZ];
38 va_list args;
40 va_init_list(args, fmt);
41 vsnprintf(buf, BUFSIZ, fmt, args);
42 va_end(args);
43 rb_write_error(buf);
46 #define warn_print(x) rb_write_error(x)
47 #define warn_print2(x,l) rb_write_error2(x,l)
49 static void
50 error_pos(void)
52 const char *sourcefile = rb_sourcefile();
53 int sourceline = rb_sourceline();
55 if (sourcefile) {
56 if (sourceline == 0) {
57 warn_printf("%s", sourcefile);
59 else if (rb_frame_callee()) {
60 warn_printf("%s:%d:in `%s'", sourcefile, sourceline,
61 rb_id2name(rb_frame_callee()));
63 else {
64 warn_printf("%s:%d", sourcefile, sourceline);
69 VALUE rb_check_backtrace(VALUE);
71 static VALUE
72 get_backtrace(VALUE info)
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);
82 static void
83 set_backtrace(VALUE info, VALUE bt)
85 rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
88 static void
89 error_print(void)
91 VALUE errat = Qnil; /* OK */
92 VALUE errinfo = GET_THREAD()->errinfo;
93 volatile VALUE eclass, e;
94 char *einfo;
95 long elen;
97 if (NIL_P(errinfo))
98 return;
100 PUSH_TAG();
101 if (EXEC_TAG() == 0) {
102 errat = get_backtrace(errinfo);
104 else {
105 errat = Qnil;
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);
117 else if (RARRAY_LEN(errat) == 0) {
118 error_pos();
120 else {
121 VALUE mesg = RARRAY_PTR(errat)[0];
123 if (NIL_P(mesg))
124 error_pos();
125 else {
126 warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
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);
137 else {
138 einfo = "";
139 elen = 0;
141 if (EXEC_TAG())
142 goto error;
143 if (eclass == rb_eRuntimeError && elen == 0) {
144 warn_print(": unhandled exception\n");
146 else {
147 VALUE epath;
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");
155 else {
156 char *tail = 0;
157 long len = elen;
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 */
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");
172 if (tail) {
173 warn_print2(tail, elen - len - 1);
174 if (einfo[elen-1] != '\n') warn_print2("\n", 1);
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;
185 #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
186 #define TRACE_HEAD 8
187 #define TRACE_TAIL 5
189 for (i = 1; i < len; i++) {
190 if (TYPE(ptr[i]) == T_STRING) {
191 warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
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;
200 error:
201 POP_TAG();
204 void
205 ruby_error_print(void)
207 error_print();
210 void
211 rb_print_undef(VALUE klass, ID id, int scope)
213 char *v;
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;
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));
227 static int
228 sysexit_status(VALUE err)
230 VALUE st = rb_iv_get(err, "status");
231 return NUM2INT(st);
234 static int
235 error_handle(int ex)
237 int status = EXIT_FAILURE;
238 rb_thread_t *th = GET_THREAD();
240 if (rb_thread_set_raised(th))
241 return EXIT_FAILURE;
242 switch (ex & TAG_MASK) {
243 case 0:
244 status = EXIT_SUCCESS;
245 break;
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);
278 else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
279 /* no message when exiting by signal */
281 else {
282 error_print();
284 break;
286 default:
287 rb_bug("Unknown longjmp status %d", ex);
288 break;
290 rb_thread_reset_raised(th);
291 return status;