1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13: #include "ruby/ruby.h"
14: #include "ruby/st.h"
15: #include "vm_core.h"
16:
17: #include <stdio.h>
18: #include <stdarg.h>
19: #ifdef HAVE_STDLIB_H
20: #include <stdlib.h>
21: #endif
22: #ifndef EXIT_SUCCESS
23: #define EXIT_SUCCESS 0
24: #endif
25:
26: extern const char ruby_description[];
27:
28: static int
29: err_position_0(char *buf, long len, const char *file, int line)
30: {
31: if (!file) {
32: return 0;
33: }
34: else if (line == 0) {
35: return snprintf(buf, len, "%s: ", file);
36: }
37: else {
38: return snprintf(buf, len, "%s:%d: ", file, line);
39: }
40: }
41:
42: static int
43: err_position(char *buf, long len)
44: {
45: return err_position_0(buf, len, rb_sourcefile(), rb_sourceline());
46: }
47:
48: static void
49: err_snprintf(char *buf, long len, const char *fmt, va_list args)
50: {
51: long n;
52:
53: n = err_position(buf, len);
54: if (len > n) {
55: vsnprintf((char*)buf+n, len-n, fmt, args);
56: }
57: }
58:
59: static void
60: compile_snprintf(char *buf, long len, const char *file, int line, const char *fmt, va_list args)
61: {
62: long n;
63:
64: n = err_position_0(buf, len, file, line);
65: if (len > n) {
66: vsnprintf((char*)buf+n, len-n, fmt, args);
67: }
68: }
69:
70: static void err_append(const char*);
71:
72: void
73: rb_compile_error(const char *file, int line, const char *fmt, ...)
74: {
75: va_list args;
76: char buf[BUFSIZ];
77:
78: va_start(args, fmt);
79: compile_snprintf(buf, BUFSIZ, file, line, fmt, args);
80: va_end(args);
81: err_append(buf);
82: }
83:
84: void
85: rb_compile_error_append(const char *fmt, ...)
86: {
87: va_list args;
88: char buf[BUFSIZ];
89:
90: va_start(args, fmt);
91: vsnprintf(buf, BUFSIZ, fmt, args);
92: va_end(args);
93: err_append(buf);
94: }
95:
96: static void
97: compile_warn_print(const char *file, int line, const char *fmt, va_list args)
98: {
99: char buf[BUFSIZ];
100: int len;
101:
102: compile_snprintf(buf, BUFSIZ, file, line, fmt, args);
103: len = strlen(buf);
104: buf[len++] = '\n';
105: rb_write_error2(buf, len);
106: }
107:
108: void
109: rb_compile_warn(const char *file, int line, const char *fmt, ...)
110: {
111: char buf[BUFSIZ];
112: va_list args;
113:
114: if (NIL_P(ruby_verbose)) return;
115:
116: snprintf(buf, BUFSIZ, "warning: %s", fmt);
117:
118: va_start(args, fmt);
119: compile_warn_print(file, line, buf, args);
120: va_end(args);
121: }
122:
123:
124: void
125: rb_compile_warning(const char *file, int line, const char *fmt, ...)
126: {
127: char buf[BUFSIZ];
128: va_list args;
129:
130: if (!RTEST(ruby_verbose)) return;
131:
132: snprintf(buf, BUFSIZ, "warning: %s", fmt);
133:
134: va_start(args, fmt);
135: compile_warn_print(file, line, buf, args);
136: va_end(args);
137: }
138:
139: static void
140: warn_print(const char *fmt, va_list args)
141: {
142: char buf[BUFSIZ];
143: int len;
144:
145: err_snprintf(buf, BUFSIZ, fmt, args);
146: len = strlen(buf);
147: buf[len++] = '\n';
148: rb_write_error2(buf, len);
149: }
150:
151: void
152: rb_warn(const char *fmt, ...)
153: {
154: char buf[BUFSIZ];
155: va_list args;
156:
157: if (NIL_P(ruby_verbose)) return;
158:
159: snprintf(buf, BUFSIZ, "warning: %s", fmt);
160:
161: va_start(args, fmt);
162: warn_print(buf, args);
163: va_end(args);
164: }
165:
166:
167: void
168: rb_warning(const char *fmt, ...)
169: {
170: char buf[BUFSIZ];
171: va_list args;
172:
173: if (!RTEST(ruby_verbose)) return;
174:
175: snprintf(buf, BUFSIZ, "warning: %s", fmt);
176:
177: va_start(args, fmt);
178: warn_print(buf, args);
179: va_end(args);
180: }
181:
182:
183:
184:
185:
186:
187:
188:
189:
190: static VALUE
191: rb_warn_m(VALUE self, VALUE mesg)
192: {
193: if (!NIL_P(ruby_verbose)) {
194: rb_io_write(rb_stderr, mesg);
195: rb_io_write(rb_stderr, rb_default_rs);
196: }
197: return Qnil;
198: }
199:
200: void rb_vm_bugreport(void);
201:
202: static void
203: report_bug(const char *file, int line, const char *fmt, va_list args)
204: {
205: char buf[BUFSIZ];
206: FILE *out = stderr;
207: int len = err_position_0(buf, BUFSIZ, file, line);
208:
209: if (fwrite(buf, 1, len, out) == len ||
210: fwrite(buf, 1, len, (out = stdout)) == len) {
211: fputs("[BUG] ", out);
212: vfprintf(out, fmt, args);
213: fprintf(out, "\n%s\n\n", ruby_description);
214: rb_vm_bugreport();
215: }
216: }
217:
218: void
219: rb_bug(const char *fmt, ...)
220: {
221: va_list args;
222:
223: va_start(args, fmt);
224: report_bug(rb_sourcefile(), rb_sourceline(), fmt, args);
225: va_end(args);
226:
227: abort();
228: }
229:
230: void
231: rb_compile_bug(const char *file, int line, const char *fmt, ...)
232: {
233: va_list args;
234:
235: va_start(args, fmt);
236: report_bug(file, line, fmt, args);
237: va_end(args);
238:
239: abort();
240: }
241:
242: static struct types {
243: int type;
244: const char *name;
245: } builtin_types[] = {
246: {T_NIL, "nil"},
247: {T_OBJECT, "Object"},
248: {T_CLASS, "Class"},
249: {T_ICLASS, "iClass"},
250: {T_MODULE, "Module"},
251: {T_FLOAT, "Float"},
252: {T_STRING, "String"},
253: {T_REGEXP, "Regexp"},
254: {T_ARRAY, "Array"},
255: {T_FIXNUM, "Fixnum"},
256: {T_HASH, "Hash"},
257: {T_STRUCT, "Struct"},
258: {T_BIGNUM, "Bignum"},
259: {T_FILE, "File"},
260: {T_TRUE, "true"},
261: {T_FALSE, "false"},
262: {T_SYMBOL, "Symbol"},
263: {T_DATA, "Data"},
264: {T_MATCH, "MatchData"},
265: {T_NODE, "Node"},
266: {T_UNDEF, "undef"},
267: {-1, 0}
268: };
269:
270: void
271: rb_check_type(VALUE x, int t)
272: {
273: struct types *type = builtin_types;
274:
275: if (x == Qundef) {
276: rb_bug("undef leaked to the Ruby space");
277: }
278:
279: if (TYPE(x) != t) {
280: while (type->type >= 0) {
281: if (type->type == t) {
282: const char *etype;
283:
284: if (NIL_P(x)) {
285: etype = "nil";
286: }
287: else if (FIXNUM_P(x)) {
288: etype = "Fixnum";
289: }
290: else if (SYMBOL_P(x)) {
291: etype = "Symbol";
292: }
293: else if (rb_special_const_p(x)) {
294: etype = RSTRING_PTR(rb_obj_as_string(x));
295: }
296: else {
297: etype = rb_obj_classname(x);
298: }
299: rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
300: etype, type->name);
301: }
302: type++;
303: }
304: rb_bug("unknown type 0x%x (0x%x given)", t, TYPE(x));
305: }
306: }
307:
308:
309: #include <errno.h>
310:
311: VALUE rb_eException;
312: VALUE rb_eSystemExit;
313: VALUE rb_eInterrupt;
314: VALUE rb_eSignal;
315: VALUE rb_eFatal;
316: VALUE rb_eStandardError;
317: VALUE rb_eRuntimeError;
318: VALUE rb_eTypeError;
319: VALUE rb_eArgError;
320: VALUE rb_eIndexError;
321: VALUE rb_eKeyError;
322: VALUE rb_eRangeError;
323: VALUE rb_eNameError;
324: VALUE rb_eNoMethodError;
325: VALUE rb_eSecurityError;
326: VALUE rb_eNotImpError;
327: VALUE rb_eNoMemError;
328: VALUE rb_cNameErrorMesg;
329:
330: VALUE rb_eScriptError;
331: VALUE rb_eSyntaxError;
332: VALUE rb_eLoadError;
333:
334: VALUE rb_eSystemCallError;
335: VALUE rb_mErrno;
336: static VALUE eNOERROR;
337:
338: VALUE
339: rb_exc_new(VALUE etype, const char *ptr, long len)
340: {
341: return rb_funcall(etype, rb_intern("new"), 1, rb_str_new(ptr, len));
342: }
343:
344: VALUE
345: rb_exc_new2(VALUE etype, const char *s)
346: {
347: return rb_exc_new(etype, s, strlen(s));
348: }
349:
350: VALUE
351: rb_exc_new3(VALUE etype, VALUE str)
352: {
353: StringValue(str);
354: return rb_funcall(etype, rb_intern("new"), 1, str);
355: }
356:
357:
358:
359:
360:
361:
362:
363:
364:
365: static VALUE
366: exc_initialize(int argc, VALUE *argv, VALUE exc)
367: {
368: VALUE arg;
369:
370: rb_scan_args(argc, argv, "01", &arg);
371: rb_iv_set(exc, "mesg", arg);
372: rb_iv_set(exc, "bt", Qnil);
373:
374: return exc;
375: }
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390: static VALUE
391: exc_exception(int argc, VALUE *argv, VALUE self)
392: {
393: VALUE exc;
394:
395: if (argc == 0) return self;
396: if (argc == 1 && self == argv[0]) return self;
397: exc = rb_obj_clone(self);
398: exc_initialize(argc, argv, exc);
399:
400: return exc;
401: }
402:
403:
404:
405:
406:
407:
408:
409:
410:
411: static VALUE
412: exc_to_s(VALUE exc)
413: {
414: VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
415:
416: if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
417: if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
418: return mesg;
419: }
420:
421:
422:
423:
424:
425:
426:
427:
428:
429:
430:
431: static VALUE
432: exc_message(VALUE exc)
433: {
434: return rb_funcall(exc, rb_intern("to_s"), 0, 0);
435: }
436:
437:
438:
439:
440:
441:
442:
443:
444: static VALUE
445: exc_inspect(VALUE exc)
446: {
447: VALUE str, klass;
448:
449: klass = CLASS_OF(exc);
450: exc = rb_obj_as_string(exc);
451: if (RSTRING_LEN(exc) == 0) {
452: return rb_str_dup(rb_class_name(klass));
453: }
454:
455: str = rb_str_buf_new2("#<");
456: klass = rb_class_name(klass);
457: rb_str_buf_append(str, klass);
458: rb_str_buf_cat(str, ": ", 2);
459: rb_str_buf_append(str, exc);
460: rb_str_buf_cat(str, ">", 1);
461:
462: return str;
463: }
464:
465:
466:
467:
468:
469:
470:
471:
472:
473:
474:
475:
476:
477:
478:
479:
480:
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494: static VALUE
495: exc_backtrace(VALUE exc)
496: {
497: static ID bt;
498:
499: if (!bt) bt = rb_intern("bt");
500: return rb_attr_get(exc, bt);
501: }
502:
503: VALUE
504: rb_check_backtrace(VALUE bt)
505: {
506: long i;
507: static const char *err = "backtrace must be Array of String";
508:
509: if (!NIL_P(bt)) {
510: int t = TYPE(bt);
511:
512: if (t == T_STRING) return rb_ary_new3(1, bt);
513: if (t != T_ARRAY) {
514: rb_raise(rb_eTypeError, err);
515: }
516: for (i=0;i<RARRAY_LEN(bt);i++) {
517: if (TYPE(RARRAY_PTR(bt)[i]) != T_STRING) {
518: rb_raise(rb_eTypeError, err);
519: }
520: }
521: }
522: return bt;
523: }
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534:
535: static VALUE
536: exc_set_backtrace(VALUE exc, VALUE bt)
537: {
538: return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
539: }
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550: static VALUE
551: exc_equal(VALUE exc, VALUE obj)
552: {
553: ID id_mesg = rb_intern("mesg");
554:
555: if (exc == obj) return Qtrue;
556: if (rb_obj_class(exc) != rb_obj_class(obj))
557: return Qfalse;
558: if (!rb_equal(rb_attr_get(exc, id_mesg), rb_attr_get(obj, id_mesg)))
559: return Qfalse;
560: if (!rb_equal(exc_backtrace(exc), exc_backtrace(obj)))
561: return Qfalse;
562: return Qtrue;
563: }
564:
565:
566:
567:
568:
569:
570:
571:
572: static VALUE
573: exit_initialize(int argc, VALUE *argv, VALUE exc)
574: {
575: VALUE status = INT2FIX(EXIT_SUCCESS);
576: if (argc > 0 && FIXNUM_P(argv[0])) {
577: status = *argv++;
578: --argc;
579: }
580: rb_call_super(argc, argv);
581: rb_iv_set(exc, "status", status);
582: return exc;
583: }
584:
585:
586:
587:
588:
589:
590:
591:
592:
593: static VALUE
594: exit_status(VALUE exc)
595: {
596: return rb_attr_get(exc, rb_intern("status"));
597: }
598:
599:
600:
601:
602:
603:
604:
605:
606:
607: static VALUE
608: exit_success_p(VALUE exc)
609: {
610: VALUE status = rb_attr_get(exc, rb_intern("status"));
611: if (NIL_P(status)) return Qtrue;
612: if (status == INT2FIX(EXIT_SUCCESS)) return Qtrue;
613: return Qfalse;
614: }
615:
616: void
617: rb_name_error(ID id, const char *fmt, ...)
618: {
619: VALUE exc, argv[2];
620: va_list args;
621: char buf[BUFSIZ];
622:
623: va_start(args, fmt);
624: vsnprintf(buf, BUFSIZ, fmt, args);
625: va_end(args);
626:
627: argv[0] = rb_str_new2(buf);
628: argv[1] = ID2SYM(id);
629: exc = rb_class_new_instance(2, argv, rb_eNameError);
630: rb_exc_raise(exc);
631: }
632:
633:
634:
635:
636:
637:
638:
639:
640:
641:
642: static VALUE
643: name_err_initialize(int argc, VALUE *argv, VALUE self)
644: {
645: VALUE name;
646:
647: name = (argc > 1) ? argv[--argc] : Qnil;
648: rb_call_super(argc, argv);
649: rb_iv_set(self, "name", name);
650: return self;
651: }
652