Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 418 lines (363 sloc) 9.869 kb
8354436 Hiroshi Mimaki add file header
mimaki authored
1 /*
2 ** error.c - Exception class
4ec6d41 rm whitespace
roco authored
3 **
8354436 Hiroshi Mimaki add file header
mimaki authored
4 ** See Copyright Notice in mruby.h
5 */
6
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
7 #include "mruby.h"
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <setjmp.h>
c9fe903 Yukihiro "Matz" Matsumoto now segmented list can be used as instance variable tables by -DMRB_USE_...
matz authored
11 #include <string.h>
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
12 #include "error.h"
2fc1b8a Yukihiro "Matz" Matsumoto mv variable.h to mruby/variable.h
matz authored
13 #include "mruby/variable.h"
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
14 #include "mruby/string.h"
15 #include "mruby/class.h"
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
16 #include "mruby/proc.h"
17 #include "mruby/irep.h"
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
18
19 #define warn_printf printf
20
21 mrb_value
22 mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len)
23 {
24 return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, mrb_str_new(mrb, ptr, len));
25 }
26
27 mrb_value
28 mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str)
29 {
30 //StringValue(str);
31 mrb_string_value(mrb, &str);
32 return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, str);
33 }
34
35 /*
36 * call-seq:
37 * Exception.new(msg = nil) -> exception
38 *
39 * Construct a new Exception object, optionally passing in
40 * a message.
41 */
42
43 static mrb_value
44 exc_initialize(mrb_state *mrb, mrb_value exc)
45 {
46 mrb_value mesg;
47
fae483f Yukihiro "Matz" Matsumoto the argument for Exception.new is optinal
matz authored
48 if (mrb_get_args(mrb, "|o", &mesg) == 1) {
49 mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), mesg);
50 }
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
51 return exc;
52 }
53
54 /*
55 * Document-method: exception
56 *
57 * call-seq:
58 * exc.exception(string) -> an_exception or exc
59 *
60 * With no argument, or if the argument is the same as the receiver,
61 * return the receiver. Otherwise, create a new
62 * exception object of the same class as the receiver, but with a
63 * message equal to <code>string.to_str</code>.
64 *
65 */
66
67 static mrb_value
68 exc_exception(mrb_state *mrb, mrb_value self)
69 {
70 mrb_value exc;
8f9b958 Yukihiro "Matz" Matsumoto raise should initialize Exception object
matz authored
71 mrb_value a;
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
72 int argc;
73
8f9b958 Yukihiro "Matz" Matsumoto raise should initialize Exception object
matz authored
74 argc = mrb_get_args(mrb, "|o", &a);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
75 if (argc == 0) return self;
8f9b958 Yukihiro "Matz" Matsumoto raise should initialize Exception object
matz authored
76 if (mrb_obj_equal(mrb, self, a)) return self;
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
77 exc = mrb_obj_clone(mrb, self);
8f9b958 Yukihiro "Matz" Matsumoto raise should initialize Exception object
matz authored
78 mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), a);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
79
80 return exc;
81 }
82
83 /*
84 * call-seq:
85 * exception.to_s -> string
86 *
87 * Returns exception's message (or the name of the exception if
88 * no message is set).
89 */
90
91 static mrb_value
92 exc_to_s(mrb_state *mrb, mrb_value exc)
93 {
94 mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg"));
95
96 if (mrb_nil_p(mesg)) return mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
97 return mesg;
98 }
99
100 /*
101 * call-seq:
102 * exception.message -> string
103 *
104 * Returns the result of invoking <code>exception.to_s</code>.
105 * Normally this returns the exception's message or name. By
106 * supplying a to_str method, exceptions are agreeing to
107 * be used where Strings are expected.
108 */
109
110 static mrb_value
111 exc_message(mrb_state *mrb, mrb_value exc)
112 {
113 return mrb_funcall(mrb, exc, "to_s", 0);
114 }
115
116 /*
117 * call-seq:
118 * exception.inspect -> string
119 *
120 * Return this exception's class name an message
121 */
122
123 static mrb_value
124 exc_inspect(mrb_state *mrb, mrb_value exc)
125 {
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
126 mrb_value str, mesg, file, line;
127
128 mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg"));
129 file = mrb_attr_get(mrb, exc, mrb_intern(mrb, "file"));
130 line = mrb_attr_get(mrb, exc, mrb_intern(mrb, "line"));
131
132 if (!mrb_nil_p(file) && !mrb_nil_p(line)) {
133 str = file;
134 mrb_str_cat2(mrb, str, ":");
135 mrb_str_append(mrb, str, line);
6bdd257 Yukihiro "Matz" Matsumoto inspect format for exception has changed
matz authored
136 mrb_str_cat2(mrb, str, ": ");
7a7f267 Tomoyuki Sahara check if an Exception instance has a "mesg" attribute
tsahara-iij authored
137 if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
138 mrb_str_append(mrb, str, mesg);
139 mrb_str_cat2(mrb, str, " (");
140 }
141 mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc));
7a7f267 Tomoyuki Sahara check if an Exception instance has a "mesg" attribute
tsahara-iij authored
142 if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
143 mrb_str_cat2(mrb, str, ")");
144 }
145 }
146 else {
147 str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
7a7f267 Tomoyuki Sahara check if an Exception instance has a "mesg" attribute
tsahara-iij authored
148 if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) {
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
149 mrb_str_cat2(mrb, str, ": ");
150 mrb_str_append(mrb, str, mesg);
7a7f267 Tomoyuki Sahara check if an Exception instance has a "mesg" attribute
tsahara-iij authored
151 } else {
152 mrb_str_cat2(mrb, str, ": ");
153 mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc));
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
154 }
6bdd257 Yukihiro "Matz" Matsumoto inspect format for exception has changed
matz authored
155 }
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
156 return str;
157 }
158
159
160 static mrb_value
161 exc_equal(mrb_state *mrb, mrb_value exc)
162 {
163 mrb_value obj;
164 mrb_value mesg;
165 mrb_sym id_mesg = mrb_intern(mrb, "mesg");
166
167 mrb_get_args(mrb, "o", &obj);
168 if (mrb_obj_equal(mrb, exc, obj)) return mrb_true_value();
169
170 if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) {
d271bf0 Yukihiro "Matz" Matsumoto make mrb_funcall_argv and mrb_funcall_with_block to take mrb_sym as a me...
matz authored
171 if (mrb_respond_to(mrb, obj, mrb_intern(mrb, "message"))) {
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
172 mesg = mrb_funcall(mrb, obj, "message", 0);
173 }
174 else
175 return mrb_false_value();
176 }
177 else {
178 mesg = mrb_attr_get(mrb, obj, id_mesg);
179 }
180
181 if (!mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg))
182 return mrb_false_value();
183 return mrb_true_value();
184 }
185
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
186 static void
187 exc_debug_info(mrb_state *mrb, struct RObject *exc)
188 {
189 mrb_callinfo *ci = mrb->ci;
190 mrb_code *pc = ci->pc;
191
ba0154c Yukihiro "Matz" Matsumoto should print file:line when exception is raised within mrblib
matz authored
192 ci--;
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
193 while (ci >= mrb->cibase) {
194 if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
195 mrb_irep *irep = ci->proc->body.irep;
196
4e8317f Yukihiro "Matz" Matsumoto do no generate lineno info if no filename is specified
matz authored
197 if (irep->filename && irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) {
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
198 mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "file"), mrb_str_new_cstr(mrb, irep->filename));
199 mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "line"), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1]));
200 return;
201 }
202 }
ba0154c Yukihiro "Matz" Matsumoto should print file:line when exception is raised within mrblib
matz authored
203 pc = ci->pc;
f114916 Yukihiro "Matz" Matsumoto source position added to exception representation
matz authored
204 ci--;
205 }
206 }
207
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
208 void
209 mrb_exc_raise(mrb_state *mrb, mrb_value exc)
210 {
2830624 Yukihiro "Matz" Matsumoto fix indent of mrb_exc_raise
matz authored
211 mrb->exc = (struct RObject*)mrb_object(exc);
212 exc_debug_info(mrb, mrb->exc);
213 if (!mrb->jmp) {
214 abort();
215 }
216 longjmp(*(jmp_buf*)mrb->jmp, 1);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
217 }
218
219 void
220 mrb_raise(mrb_state *mrb, struct RClass *c, const char *fmt, ...)
221 {
222 va_list args;
223 char buf[256];
ccec3da Masaki Muranaka Use return value of vsnprintf() for the string length. It is redundant u...
monaka authored
224 int n;
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
225
226 va_start(args, fmt);
d534f26 Masaki Muranaka Use sizeof to get char array sizes.
monaka authored
227 n = vsnprintf(buf, sizeof(buf), fmt, args);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
228 va_end(args);
ccec3da Masaki Muranaka Use return value of vsnprintf() for the string length. It is redundant u...
monaka authored
229 if (n < 0) {
230 n = 0;
231 }
232 mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, n));
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
233 }
234
235 void
236 mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...)
237 {
238 mrb_value exc, argv[2];
239 va_list args;
240 char buf[256];
ccec3da Masaki Muranaka Use return value of vsnprintf() for the string length. It is redundant u...
monaka authored
241 int n;
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
242
243 va_start(args, fmt);
d534f26 Masaki Muranaka Use sizeof to get char array sizes.
monaka authored
244 n = vsnprintf(buf, sizeof(buf), fmt, args);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
245 va_end(args);
ccec3da Masaki Muranaka Use return value of vsnprintf() for the string length. It is redundant u...
monaka authored
246 if (n < 0) {
247 n = 0;
248 }
249 argv[0] = mrb_str_new(mrb, buf, n);
742c4fb Yukihiro "Matz" Matsumoto ignore id to create NameError
matz authored
250 argv[1] = mrb_symbol_value(id); /* ignore now */
251 exc = mrb_class_new_instance(mrb, 1, argv, E_NAME_ERROR);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
252 mrb_exc_raise(mrb, exc);
253 }
df7be84 Yukihiro "Matz" Matsumoto add newline between functions
matz authored
254
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
255 mrb_value
256 mrb_sprintf(mrb_state *mrb, const char *fmt, ...)
257 {
258 va_list args;
259 char buf[256];
ccec3da Masaki Muranaka Use return value of vsnprintf() for the string length. It is redundant u...
monaka authored
260 int n;
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
261
262 va_start(args, fmt);
d534f26 Masaki Muranaka Use sizeof to get char array sizes.
monaka authored
263 n = vsnprintf(buf, sizeof(buf), fmt, args);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
264 va_end(args);
ccec3da Masaki Muranaka Use return value of vsnprintf() for the string length. It is redundant u...
monaka authored
265 if (n < 0) {
266 n = 0;
267 }
268 return mrb_str_new(mrb, buf, n);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
269 }
270
271 void
272 mrb_warn(const char *fmt, ...)
273 {
274 va_list args;
275
276 va_start(args, fmt);
195d1dd Yukihiro "Matz" Matsumoto do not use fixed sized buffer in mrb_bug/mrb_warn; close #287
matz authored
277 printf("warning: ");
278 vprintf(fmt, args);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
279 va_end(args);
280 }
281
282 void
283 mrb_bug(const char *fmt, ...)
284 {
285 va_list args;
286
287 va_start(args, fmt);
195d1dd Yukihiro "Matz" Matsumoto do not use fixed sized buffer in mrb_bug/mrb_warn; close #287
matz authored
288 printf("bug: ");
289 vprintf(fmt, args);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
290 va_end(args);
195d1dd Yukihiro "Matz" Matsumoto do not use fixed sized buffer in mrb_bug/mrb_warn; close #287
matz authored
291 exit(EXIT_FAILURE);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
292 }
293
294 static const char *
295 mrb_strerrno(int err)
296 {
297 #define defined_error(name, num) if (err == num) return name;
298 #define undefined_error(name)
299 //#include "known_errors.inc"
300 #undef defined_error
301 #undef undefined_error
302 return NULL;
303 }
304
305 void
306 mrb_bug_errno(const char *mesg, int errno_arg)
307 {
308 if (errno_arg == 0)
309 mrb_bug("%s: errno == 0 (NOERROR)", mesg);
310 else {
311 const char *errno_str = mrb_strerrno(errno_arg);
312 if (errno_str)
313 mrb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
314 else
315 mrb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
316 }
317 }
318
319 int
320 sysexit_status(mrb_state *mrb, mrb_value err)
321 {
322 mrb_value st = mrb_iv_get(mrb, err, mrb_intern(mrb, "status"));
323 return mrb_fixnum(st);
324 }
325
326 static void
327 set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt)
328 {
e5dde46 Yukihiro "Matz" Matsumoto reduce mrb_funcall invocations
matz authored
329 mrb_funcall(mrb, info, "set_backtrace", 1, bt);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
330 }
331
332 mrb_value
333 make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr)
334 {
335 mrb_value mesg;
336 int n;
337
338 mesg = mrb_nil_value();
339 switch (argc) {
340 case 0:
341 break;
342 case 1:
343 if (mrb_nil_p(argv[0]))
344 break;
345 if (isstr) {
346 mesg = mrb_check_string_type(mrb, argv[0]);
347 if (!mrb_nil_p(mesg)) {
ef50e63 Yukihiro "Matz" Matsumoto remove RuntimeError from mrb_state
matz authored
348 mesg = mrb_exc_new3(mrb, E_RUNTIME_ERROR, mesg);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
349 break;
350 }
351 }
352 n = 0;
353 goto exception_call;
354
355 case 2:
356 case 3:
357 n = 1;
358 exception_call:
d271bf0 Yukihiro "Matz" Matsumoto make mrb_funcall_argv and mrb_funcall_with_block to take mrb_sym as a me...
matz authored
359 {
360 mrb_sym exc = mrb_intern(mrb, "exception");
361 if (mrb_respond_to(mrb, argv[0], exc)) {
362 mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1);
363 }
364 else {
365 /* undef */
366 mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
367 }
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
368 }
369
370 break;
371 default:
372 mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 0..3)", argc);
373 break;
374 }
375 if (argc > 0) {
376 if (!mrb_obj_is_kind_of(mrb, mesg, mrb->eException_class))
377 mrb_raise(mrb, E_TYPE_ERROR, "exception object expected");
378 if (argc > 2)
379 set_backtrace(mrb, mesg, argv[2]);
380 }
381
382 return mesg;
383 }
384
385 mrb_value
386 mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv)
387 {
388 return make_exception(mrb, argc, argv, TRUE);
389 }
390
391 void
392 mrb_sys_fail(mrb_state *mrb, const char *mesg)
393 {
ef50e63 Yukihiro "Matz" Matsumoto remove RuntimeError from mrb_state
matz authored
394 mrb_raise(mrb, E_RUNTIME_ERROR, "%s", mesg);
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
395 }
396
397 void
398 mrb_init_exception(mrb_state *mrb)
399 {
400 struct RClass *e;
401
402 mrb->eException_class = e = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
403 mrb_define_class_method(mrb, e, "exception", mrb_instance_new, ARGS_ANY());
404 mrb_define_method(mrb, e, "exception", exc_exception, ARGS_ANY());
405 mrb_define_method(mrb, e, "initialize", exc_initialize, ARGS_ANY());
406 mrb_define_method(mrb, e, "==", exc_equal, ARGS_REQ(1));
407 mrb_define_method(mrb, e, "to_s", exc_to_s, ARGS_NONE());
408 mrb_define_method(mrb, e, "message", exc_message, ARGS_NONE());
409 mrb_define_method(mrb, e, "inspect", exc_inspect, ARGS_NONE());
410
ef50e63 Yukihiro "Matz" Matsumoto remove RuntimeError from mrb_state
matz authored
411 mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
412 mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
9e7ca5d Yukihiro "Matz" Matsumoto mrb might be intialized incompletely from mrbc; close #457
matz authored
413
414 mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
415 e = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */
416 mrb_define_class(mrb, "SyntaxError", e); /* 15.2.38 */
e0d6430 Hiroshi Mimaki add mruby sources
mimaki authored
417 }
Something went wrong with that request. Please try again.