/error.c

https://github.com/wanabe/ruby · C · 3428 lines · 2175 code · 420 blank · 833 comment · 304 complexity · 24858c7f38a94191932051acdf391430 MD5 · raw file

Large files are truncated click here to view the full file

  1. /**********************************************************************
  2. error.c -
  3. $Author$
  4. created at: Mon Aug 9 16:11:34 JST 1993
  5. Copyright (C) 1993-2007 Yukihiro Matsumoto
  6. **********************************************************************/
  7. #include "ruby/internal/config.h"
  8. #include <errno.h>
  9. #include <stdarg.h>
  10. #include <stdio.h>
  11. #ifdef HAVE_STDLIB_H
  12. # include <stdlib.h>
  13. #endif
  14. #ifdef HAVE_UNISTD_H
  15. # include <unistd.h>
  16. #endif
  17. #if defined __APPLE__
  18. # include <AvailabilityMacros.h>
  19. #endif
  20. #include "internal.h"
  21. #include "internal/error.h"
  22. #include "internal/eval.h"
  23. #include "internal/hash.h"
  24. #include "internal/io.h"
  25. #include "internal/load.h"
  26. #include "internal/object.h"
  27. #include "internal/symbol.h"
  28. #include "internal/thread.h"
  29. #include "internal/variable.h"
  30. #include "ruby/encoding.h"
  31. #include "ruby/st.h"
  32. #include "ruby_assert.h"
  33. #include "vm_core.h"
  34. #include "builtin.h"
  35. /*!
  36. * \addtogroup exception
  37. * \{
  38. */
  39. #ifndef EXIT_SUCCESS
  40. #define EXIT_SUCCESS 0
  41. #endif
  42. #ifndef WIFEXITED
  43. #define WIFEXITED(status) 1
  44. #endif
  45. #ifndef WEXITSTATUS
  46. #define WEXITSTATUS(status) (status)
  47. #endif
  48. VALUE rb_iseqw_local_variables(VALUE iseqval);
  49. VALUE rb_iseqw_new(const rb_iseq_t *);
  50. int rb_str_end_with_asciichar(VALUE str, int c);
  51. long rb_backtrace_length_limit = -1;
  52. VALUE rb_eEAGAIN;
  53. VALUE rb_eEWOULDBLOCK;
  54. VALUE rb_eEINPROGRESS;
  55. static VALUE rb_mWarning;
  56. static VALUE rb_cWarningBuffer;
  57. static ID id_warn;
  58. static ID id_category;
  59. static ID id_deprecated;
  60. static ID id_experimental;
  61. static VALUE sym_category;
  62. static struct {
  63. st_table *id2enum, *enum2id;
  64. } warning_categories;
  65. extern const char ruby_description[];
  66. static const char *
  67. rb_strerrno(int err)
  68. {
  69. #define defined_error(name, num) if (err == (num)) return (name);
  70. #define undefined_error(name)
  71. #include "known_errors.inc"
  72. #undef defined_error
  73. #undef undefined_error
  74. return NULL;
  75. }
  76. static int
  77. err_position_0(char *buf, long len, const char *file, int line)
  78. {
  79. if (!file) {
  80. return 0;
  81. }
  82. else if (line == 0) {
  83. return snprintf(buf, len, "%s: ", file);
  84. }
  85. else {
  86. return snprintf(buf, len, "%s:%d: ", file, line);
  87. }
  88. }
  89. RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 5, 0)
  90. static VALUE
  91. err_vcatf(VALUE str, const char *pre, const char *file, int line,
  92. const char *fmt, va_list args)
  93. {
  94. if (file) {
  95. rb_str_cat2(str, file);
  96. if (line) rb_str_catf(str, ":%d", line);
  97. rb_str_cat2(str, ": ");
  98. }
  99. if (pre) rb_str_cat2(str, pre);
  100. rb_str_vcatf(str, fmt, args);
  101. return str;
  102. }
  103. VALUE
  104. rb_syntax_error_append(VALUE exc, VALUE file, int line, int column,
  105. rb_encoding *enc, const char *fmt, va_list args)
  106. {
  107. const char *fn = NIL_P(file) ? NULL : RSTRING_PTR(file);
  108. if (!exc) {
  109. VALUE mesg = rb_enc_str_new(0, 0, enc);
  110. err_vcatf(mesg, NULL, fn, line, fmt, args);
  111. rb_str_cat2(mesg, "\n");
  112. rb_write_error_str(mesg);
  113. }
  114. else {
  115. VALUE mesg;
  116. if (NIL_P(exc)) {
  117. mesg = rb_enc_str_new(0, 0, enc);
  118. exc = rb_class_new_instance(1, &mesg, rb_eSyntaxError);
  119. }
  120. else {
  121. mesg = rb_attr_get(exc, idMesg);
  122. if (RSTRING_LEN(mesg) > 0 && *(RSTRING_END(mesg)-1) != '\n')
  123. rb_str_cat_cstr(mesg, "\n");
  124. }
  125. err_vcatf(mesg, NULL, fn, line, fmt, args);
  126. }
  127. return exc;
  128. }
  129. static unsigned int warning_disabled_categories = (
  130. 1U << RB_WARN_CATEGORY_DEPRECATED |
  131. 0);
  132. static unsigned int
  133. rb_warning_category_mask(VALUE category)
  134. {
  135. return 1U << rb_warning_category_from_name(category);
  136. }
  137. rb_warning_category_t
  138. rb_warning_category_from_name(VALUE category)
  139. {
  140. st_data_t cat_value;
  141. ID cat_id;
  142. Check_Type(category, T_SYMBOL);
  143. if (!(cat_id = rb_check_id(&category)) ||
  144. !st_lookup(warning_categories.id2enum, cat_id, &cat_value)) {
  145. rb_raise(rb_eArgError, "unknown category: %"PRIsVALUE, category);
  146. }
  147. return (rb_warning_category_t)cat_value;
  148. }
  149. static VALUE
  150. rb_warning_category_to_name(rb_warning_category_t category)
  151. {
  152. st_data_t id;
  153. if (!st_lookup(warning_categories.enum2id, category, &id)) {
  154. rb_raise(rb_eArgError, "invalid category: %d", (int)category);
  155. }
  156. return id ? ID2SYM(id) : Qnil;
  157. }
  158. void
  159. rb_warning_category_update(unsigned int mask, unsigned int bits)
  160. {
  161. warning_disabled_categories &= ~mask;
  162. warning_disabled_categories |= mask & ~bits;
  163. }
  164. MJIT_FUNC_EXPORTED bool
  165. rb_warning_category_enabled_p(rb_warning_category_t category)
  166. {
  167. return !(warning_disabled_categories & (1U << category));
  168. }
  169. /*
  170. * call-seq:
  171. * Warning[category] -> true or false
  172. *
  173. * Returns the flag to show the warning messages for +category+.
  174. * Supported categories are:
  175. *
  176. * +:deprecated+ :: deprecation warnings
  177. * * assignment of non-nil value to <code>$,</code> and <code>$;</code>
  178. * * keyword arguments
  179. * * proc/lambda without block
  180. * etc.
  181. *
  182. * +:experimental+ :: experimental features
  183. * * Pattern matching
  184. */
  185. static VALUE
  186. rb_warning_s_aref(VALUE mod, VALUE category)
  187. {
  188. rb_warning_category_t cat = rb_warning_category_from_name(category);
  189. return RBOOL(rb_warning_category_enabled_p(cat));
  190. }
  191. /*
  192. * call-seq:
  193. * Warning[category] = flag -> flag
  194. *
  195. * Sets the warning flags for +category+.
  196. * See Warning.[] for the categories.
  197. */
  198. static VALUE
  199. rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag)
  200. {
  201. unsigned int mask = rb_warning_category_mask(category);
  202. unsigned int disabled = warning_disabled_categories;
  203. if (!RTEST(flag))
  204. disabled |= mask;
  205. else
  206. disabled &= ~mask;
  207. warning_disabled_categories = disabled;
  208. return flag;
  209. }
  210. /*
  211. * call-seq:
  212. * warn(msg, category: nil) -> nil
  213. *
  214. * Writes warning message +msg+ to $stderr. This method is called by
  215. * Ruby for all emitted warnings. A +category+ may be included with
  216. * the warning.
  217. *
  218. * See the documentation of the Warning module for how to customize this.
  219. */
  220. static VALUE
  221. rb_warning_s_warn(int argc, VALUE *argv, VALUE mod)
  222. {
  223. VALUE str;
  224. VALUE opt;
  225. VALUE category = Qnil;
  226. rb_scan_args(argc, argv, "1:", &str, &opt);
  227. if (!NIL_P(opt)) rb_get_kwargs(opt, &id_category, 0, 1, &category);
  228. Check_Type(str, T_STRING);
  229. rb_must_asciicompat(str);
  230. if (!NIL_P(category)) {
  231. rb_warning_category_t cat = rb_warning_category_from_name(category);
  232. if (!rb_warning_category_enabled_p(cat)) return Qnil;
  233. }
  234. rb_write_error_str(str);
  235. return Qnil;
  236. }
  237. /*
  238. * Document-module: Warning
  239. *
  240. * The Warning module contains a single method named #warn, and the
  241. * module extends itself, making Warning.warn available.
  242. * Warning.warn is called for all warnings issued by Ruby.
  243. * By default, warnings are printed to $stderr.
  244. *
  245. * Changing the behavior of Warning.warn is useful to customize how warnings are
  246. * handled by Ruby, for instance by filtering some warnings, and/or outputting
  247. * warnings somewhere other than $stderr.
  248. *
  249. * If you want to change the behavior of Warning.warn you should use
  250. * +Warning.extend(MyNewModuleWithWarnMethod)+ and you can use `super`
  251. * to get the default behavior of printing the warning to $stderr.
  252. *
  253. * Example:
  254. * module MyWarningFilter
  255. * def warn(message, category: nil, **kwargs)
  256. * if /some warning I want to ignore/.match?(message)
  257. * # ignore
  258. * else
  259. * super
  260. * end
  261. * end
  262. * end
  263. * Warning.extend MyWarningFilter
  264. *
  265. * You should never redefine Warning#warn (the instance method), as that will
  266. * then no longer provide a way to use the default behavior.
  267. *
  268. * The +warning+ gem provides convenient ways to customize Warning.warn.
  269. */
  270. static VALUE
  271. rb_warning_warn(VALUE mod, VALUE str)
  272. {
  273. return rb_funcallv(mod, id_warn, 1, &str);
  274. }
  275. static int
  276. rb_warning_warn_arity(void)
  277. {
  278. return rb_method_entry_arity(rb_method_entry(rb_singleton_class(rb_mWarning), id_warn));
  279. }
  280. static VALUE
  281. rb_warn_category(VALUE str, VALUE category)
  282. {
  283. if (RUBY_DEBUG && !NIL_P(category)) {
  284. rb_warning_category_from_name(category);
  285. }
  286. if (rb_warning_warn_arity() == 1) {
  287. return rb_warning_warn(rb_mWarning, str);
  288. }
  289. else {
  290. VALUE args[2];
  291. args[0] = str;
  292. args[1] = rb_hash_new();
  293. rb_hash_aset(args[1], sym_category, category);
  294. return rb_funcallv_kw(rb_mWarning, id_warn, 2, args, RB_PASS_KEYWORDS);
  295. }
  296. }
  297. static void
  298. rb_write_warning_str(VALUE str)
  299. {
  300. rb_warning_warn(rb_mWarning, str);
  301. }
  302. RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 0)
  303. static VALUE
  304. warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_list args)
  305. {
  306. VALUE str = rb_enc_str_new(0, 0, enc);
  307. err_vcatf(str, "warning: ", file, line, fmt, args);
  308. return rb_str_cat2(str, "\n");
  309. }
  310. void
  311. rb_compile_warn(const char *file, int line, const char *fmt, ...)
  312. {
  313. VALUE str;
  314. va_list args;
  315. if (NIL_P(ruby_verbose)) return;
  316. va_start(args, fmt);
  317. str = warn_vsprintf(NULL, file, line, fmt, args);
  318. va_end(args);
  319. rb_write_warning_str(str);
  320. }
  321. /* rb_compile_warning() reports only in verbose mode */
  322. void
  323. rb_compile_warning(const char *file, int line, const char *fmt, ...)
  324. {
  325. VALUE str;
  326. va_list args;
  327. if (!RTEST(ruby_verbose)) return;
  328. va_start(args, fmt);
  329. str = warn_vsprintf(NULL, file, line, fmt, args);
  330. va_end(args);
  331. rb_write_warning_str(str);
  332. }
  333. void
  334. rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...)
  335. {
  336. VALUE str;
  337. va_list args;
  338. if (NIL_P(ruby_verbose)) return;
  339. va_start(args, fmt);
  340. str = warn_vsprintf(NULL, file, line, fmt, args);
  341. va_end(args);
  342. rb_warn_category(str, rb_warning_category_to_name(category));
  343. }
  344. RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
  345. static VALUE
  346. warning_string(rb_encoding *enc, const char *fmt, va_list args)
  347. {
  348. int line;
  349. const char *file = rb_source_location_cstr(&line);
  350. return warn_vsprintf(enc, file, line, fmt, args);
  351. }
  352. #define with_warning_string(mesg, enc, fmt) \
  353. VALUE mesg; \
  354. va_list args; va_start(args, fmt); \
  355. mesg = warning_string(enc, fmt, args); \
  356. va_end(args);
  357. void
  358. rb_warn(const char *fmt, ...)
  359. {
  360. if (!NIL_P(ruby_verbose)) {
  361. with_warning_string(mesg, 0, fmt) {
  362. rb_write_warning_str(mesg);
  363. }
  364. }
  365. }
  366. void
  367. rb_category_warn(rb_warning_category_t category, const char *fmt, ...)
  368. {
  369. if (!NIL_P(ruby_verbose)) {
  370. with_warning_string(mesg, 0, fmt) {
  371. rb_warn_category(mesg, rb_warning_category_to_name(category));
  372. }
  373. }
  374. }
  375. void
  376. rb_enc_warn(rb_encoding *enc, const char *fmt, ...)
  377. {
  378. if (!NIL_P(ruby_verbose)) {
  379. with_warning_string(mesg, enc, fmt) {
  380. rb_write_warning_str(mesg);
  381. }
  382. }
  383. }
  384. /* rb_warning() reports only in verbose mode */
  385. void
  386. rb_warning(const char *fmt, ...)
  387. {
  388. if (RTEST(ruby_verbose)) {
  389. with_warning_string(mesg, 0, fmt) {
  390. rb_write_warning_str(mesg);
  391. }
  392. }
  393. }
  394. /* rb_category_warning() reports only in verbose mode */
  395. void
  396. rb_category_warning(rb_warning_category_t category, const char *fmt, ...)
  397. {
  398. if (RTEST(ruby_verbose)) {
  399. with_warning_string(mesg, 0, fmt) {
  400. rb_warn_category(mesg, rb_warning_category_to_name(category));
  401. }
  402. }
  403. }
  404. VALUE
  405. rb_warning_string(const char *fmt, ...)
  406. {
  407. with_warning_string(mesg, 0, fmt) {
  408. }
  409. return mesg;
  410. }
  411. #if 0
  412. void
  413. rb_enc_warning(rb_encoding *enc, const char *fmt, ...)
  414. {
  415. if (RTEST(ruby_verbose)) {
  416. with_warning_string(mesg, enc, fmt) {
  417. rb_write_warning_str(mesg);
  418. }
  419. }
  420. }
  421. #endif
  422. static bool
  423. deprecation_warning_enabled(void)
  424. {
  425. if (NIL_P(ruby_verbose)) return false;
  426. if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return false;
  427. return true;
  428. }
  429. static void
  430. warn_deprecated(VALUE mesg, const char *removal, const char *suggest)
  431. {
  432. rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1);
  433. rb_str_cat_cstr(mesg, " is deprecated");
  434. if (removal) {
  435. rb_str_catf(mesg, " and will be removed in Ruby %s", removal);
  436. }
  437. if (suggest) rb_str_catf(mesg, "; use %s instead", suggest);
  438. rb_str_cat_cstr(mesg, "\n");
  439. rb_warn_category(mesg, ID2SYM(id_deprecated));
  440. }
  441. void
  442. rb_warn_deprecated(const char *fmt, const char *suggest, ...)
  443. {
  444. if (!deprecation_warning_enabled()) return;
  445. va_list args;
  446. va_start(args, suggest);
  447. VALUE mesg = warning_string(0, fmt, args);
  448. va_end(args);
  449. warn_deprecated(mesg, NULL, suggest);
  450. }
  451. void
  452. rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...)
  453. {
  454. if (!deprecation_warning_enabled()) return;
  455. va_list args;
  456. va_start(args, suggest);
  457. VALUE mesg = warning_string(0, fmt, args);
  458. va_end(args);
  459. warn_deprecated(mesg, removal, suggest);
  460. }
  461. static inline int
  462. end_with_asciichar(VALUE str, int c)
  463. {
  464. return RB_TYPE_P(str, T_STRING) &&
  465. rb_str_end_with_asciichar(str, c);
  466. }
  467. /* :nodoc: */
  468. static VALUE
  469. warning_write(int argc, VALUE *argv, VALUE buf)
  470. {
  471. while (argc-- > 0) {
  472. rb_str_append(buf, *argv++);
  473. }
  474. return buf;
  475. }
  476. VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal);
  477. static VALUE
  478. rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALUE category)
  479. {
  480. VALUE location = Qnil;
  481. int argc = RARRAY_LENINT(msgs);
  482. const VALUE *argv = RARRAY_CONST_PTR(msgs);
  483. if (!NIL_P(ruby_verbose) && argc > 0) {
  484. VALUE str = argv[0];
  485. if (!NIL_P(uplevel)) {
  486. long lev = NUM2LONG(uplevel);
  487. if (lev < 0) {
  488. rb_raise(rb_eArgError, "negative level (%ld)", lev);
  489. }
  490. location = rb_ec_backtrace_location_ary(ec, lev + 1, 1, TRUE);
  491. if (!NIL_P(location)) {
  492. location = rb_ary_entry(location, 0);
  493. }
  494. }
  495. if (argc > 1 || !NIL_P(uplevel) || !end_with_asciichar(str, '\n')) {
  496. VALUE path;
  497. if (NIL_P(uplevel)) {
  498. str = rb_str_tmp_new(0);
  499. }
  500. else if (NIL_P(location) ||
  501. NIL_P(path = rb_funcall(location, rb_intern("path"), 0))) {
  502. str = rb_str_new_cstr("warning: ");
  503. }
  504. else {
  505. str = rb_sprintf("%s:%ld: warning: ",
  506. rb_string_value_ptr(&path),
  507. NUM2LONG(rb_funcall(location, rb_intern("lineno"), 0)));
  508. }
  509. RBASIC_SET_CLASS(str, rb_cWarningBuffer);
  510. rb_io_puts(argc, argv, str);
  511. RBASIC_SET_CLASS(str, rb_cString);
  512. }
  513. if (!NIL_P(category)) {
  514. category = rb_to_symbol_type(category);
  515. rb_warning_category_from_name(category);
  516. }
  517. if (exc == rb_mWarning) {
  518. rb_must_asciicompat(str);
  519. rb_write_error_str(str);
  520. }
  521. else {
  522. rb_warn_category(str, category);
  523. }
  524. }
  525. return Qnil;
  526. }
  527. #define MAX_BUG_REPORTERS 0x100
  528. static struct bug_reporters {
  529. void (*func)(FILE *out, void *data);
  530. void *data;
  531. } bug_reporters[MAX_BUG_REPORTERS];
  532. static int bug_reporters_size;
  533. int
  534. rb_bug_reporter_add(void (*func)(FILE *, void *), void *data)
  535. {
  536. struct bug_reporters *reporter;
  537. if (bug_reporters_size >= MAX_BUG_REPORTERS) {
  538. return 0; /* failed to register */
  539. }
  540. reporter = &bug_reporters[bug_reporters_size++];
  541. reporter->func = func;
  542. reporter->data = data;
  543. return 1;
  544. }
  545. /* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */
  546. #define REPORT_BUG_BUFSIZ 256
  547. static FILE *
  548. bug_report_file(const char *file, int line)
  549. {
  550. char buf[REPORT_BUG_BUFSIZ];
  551. FILE *out = stderr;
  552. int len = err_position_0(buf, sizeof(buf), file, line);
  553. if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len ||
  554. (ssize_t)fwrite(buf, 1, len, (out = stdout)) == (ssize_t)len) {
  555. return out;
  556. }
  557. return NULL;
  558. }
  559. FUNC_MINIMIZED(static void bug_important_message(FILE *out, const char *const msg, size_t len));
  560. static void
  561. bug_important_message(FILE *out, const char *const msg, size_t len)
  562. {
  563. const char *const endmsg = msg + len;
  564. const char *p = msg;
  565. if (!len) return;
  566. if (isatty(fileno(out))) {
  567. static const char red[] = "\033[;31;1;7m";
  568. static const char green[] = "\033[;32;7m";
  569. static const char reset[] = "\033[m";
  570. const char *e = strchr(p, '\n');
  571. const int w = (int)(e - p);
  572. do {
  573. int i = (int)(e - p);
  574. fputs(*p == ' ' ? green : red, out);
  575. fwrite(p, 1, e - p, out);
  576. for (; i < w; ++i) fputc(' ', out);
  577. fputs(reset, out);
  578. fputc('\n', out);
  579. } while ((p = e + 1) < endmsg && (e = strchr(p, '\n')) != 0 && e > p + 1);
  580. }
  581. fwrite(p, 1, endmsg - p, out);
  582. }
  583. static void
  584. preface_dump(FILE *out)
  585. {
  586. #if defined __APPLE__
  587. static const char msg[] = ""
  588. "-- Crash Report log information "
  589. "--------------------------------------------\n"
  590. " See Crash Report log file in one of the following locations:\n"
  591. # if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
  592. " * ~/Library/Logs/CrashReporter\n"
  593. " * /Library/Logs/CrashReporter\n"
  594. # endif
  595. " * ~/Library/Logs/DiagnosticReports\n"
  596. " * /Library/Logs/DiagnosticReports\n"
  597. " for more details.\n"
  598. "Don't forget to include the above Crash Report log file in bug reports.\n"
  599. "\n";
  600. const size_t msglen = sizeof(msg) - 1;
  601. #else
  602. const char *msg = NULL;
  603. const size_t msglen = 0;
  604. #endif
  605. bug_important_message(out, msg, msglen);
  606. }
  607. static void
  608. postscript_dump(FILE *out)
  609. {
  610. #if defined __APPLE__
  611. static const char msg[] = ""
  612. "[IMPORTANT]"
  613. /*" ------------------------------------------------"*/
  614. "\n""Don't forget to include the Crash Report log file under\n"
  615. # if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
  616. "CrashReporter or "
  617. # endif
  618. "DiagnosticReports directory in bug reports.\n"
  619. /*"------------------------------------------------------------\n"*/
  620. "\n";
  621. const size_t msglen = sizeof(msg) - 1;
  622. #else
  623. const char *msg = NULL;
  624. const size_t msglen = 0;
  625. #endif
  626. bug_important_message(out, msg, msglen);
  627. }
  628. RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
  629. static void
  630. bug_report_begin_valist(FILE *out, const char *fmt, va_list args)
  631. {
  632. char buf[REPORT_BUG_BUFSIZ];
  633. fputs("[BUG] ", out);
  634. vsnprintf(buf, sizeof(buf), fmt, args);
  635. fputs(buf, out);
  636. snprintf(buf, sizeof(buf), "\n%s\n\n", ruby_description);
  637. fputs(buf, out);
  638. preface_dump(out);
  639. }
  640. #define bug_report_begin(out, fmt) do { \
  641. va_list args; \
  642. va_start(args, fmt); \
  643. bug_report_begin_valist(out, fmt, args); \
  644. va_end(args); \
  645. } while (0)
  646. static void
  647. bug_report_end(FILE *out)
  648. {
  649. /* call additional bug reporters */
  650. {
  651. int i;
  652. for (i=0; i<bug_reporters_size; i++) {
  653. struct bug_reporters *reporter = &bug_reporters[i];
  654. (*reporter->func)(out, reporter->data);
  655. }
  656. }
  657. postscript_dump(out);
  658. }
  659. #define report_bug(file, line, fmt, ctx) do { \
  660. FILE *out = bug_report_file(file, line); \
  661. if (out) { \
  662. bug_report_begin(out, fmt); \
  663. rb_vm_bugreport(ctx); \
  664. bug_report_end(out); \
  665. } \
  666. } while (0) \
  667. #define report_bug_valist(file, line, fmt, ctx, args) do { \
  668. FILE *out = bug_report_file(file, line); \
  669. if (out) { \
  670. bug_report_begin_valist(out, fmt, args); \
  671. rb_vm_bugreport(ctx); \
  672. bug_report_end(out); \
  673. } \
  674. } while (0) \
  675. NORETURN(static void die(void));
  676. static void
  677. die(void)
  678. {
  679. #if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
  680. _set_abort_behavior( 0, _CALL_REPORTFAULT);
  681. #endif
  682. abort();
  683. }
  684. RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0)
  685. void
  686. rb_bug_without_die(const char *fmt, va_list args)
  687. {
  688. const char *file = NULL;
  689. int line = 0;
  690. if (GET_EC()) {
  691. file = rb_source_location_cstr(&line);
  692. }
  693. report_bug_valist(file, line, fmt, NULL, args);
  694. }
  695. void
  696. rb_bug(const char *fmt, ...)
  697. {
  698. va_list args;
  699. va_start(args, fmt);
  700. rb_bug_without_die(fmt, args);
  701. va_end(args);
  702. die();
  703. }
  704. void
  705. rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *ctx, const char *fmt, ...)
  706. {
  707. const char *file = NULL;
  708. int line = 0;
  709. if (GET_EC()) {
  710. file = rb_source_location_cstr(&line);
  711. }
  712. report_bug(file, line, fmt, ctx);
  713. if (default_sighandler) default_sighandler(sig);
  714. die();
  715. }
  716. void
  717. rb_bug_errno(const char *mesg, int errno_arg)
  718. {
  719. if (errno_arg == 0)
  720. rb_bug("%s: errno == 0 (NOERROR)", mesg);
  721. else {
  722. const char *errno_str = rb_strerrno(errno_arg);
  723. if (errno_str)
  724. rb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
  725. else
  726. rb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
  727. }
  728. }
  729. /*
  730. * this is safe to call inside signal handler and timer thread
  731. * (which isn't a Ruby Thread object)
  732. */
  733. #define write_or_abort(fd, str, len) (write((fd), (str), (len)) < 0 ? abort() : (void)0)
  734. #define WRITE_CONST(fd,str) write_or_abort((fd),(str),sizeof(str) - 1)
  735. void
  736. rb_async_bug_errno(const char *mesg, int errno_arg)
  737. {
  738. WRITE_CONST(2, "[ASYNC BUG] ");
  739. write_or_abort(2, mesg, strlen(mesg));
  740. WRITE_CONST(2, "\n");
  741. if (errno_arg == 0) {
  742. WRITE_CONST(2, "errno == 0 (NOERROR)\n");
  743. }
  744. else {
  745. const char *errno_str = rb_strerrno(errno_arg);
  746. if (!errno_str)
  747. errno_str = "undefined errno";
  748. write_or_abort(2, errno_str, strlen(errno_str));
  749. }
  750. WRITE_CONST(2, "\n\n");
  751. write_or_abort(2, ruby_description, strlen(ruby_description));
  752. abort();
  753. }
  754. void
  755. rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args)
  756. {
  757. report_bug_valist(RSTRING_PTR(file), line, fmt, NULL, args);
  758. }
  759. MJIT_FUNC_EXPORTED void
  760. rb_assert_failure(const char *file, int line, const char *name, const char *expr)
  761. {
  762. FILE *out = stderr;
  763. fprintf(out, "Assertion Failed: %s:%d:", file, line);
  764. if (name) fprintf(out, "%s:", name);
  765. fprintf(out, "%s\n%s\n\n", expr, ruby_description);
  766. preface_dump(out);
  767. rb_vm_bugreport(NULL);
  768. bug_report_end(out);
  769. die();
  770. }
  771. static const char builtin_types[][10] = {
  772. "", /* 0x00, */
  773. "Object",
  774. "Class",
  775. "Module",
  776. "Float",
  777. "String",
  778. "Regexp",
  779. "Array",
  780. "Hash",
  781. "Struct",
  782. "Integer",
  783. "File",
  784. "Data", /* internal use: wrapped C pointers */
  785. "MatchData", /* data of $~ */
  786. "Complex",
  787. "Rational",
  788. "", /* 0x10 */
  789. "nil",
  790. "true",
  791. "false",
  792. "Symbol", /* :symbol */
  793. "Integer",
  794. "undef", /* internal use: #undef; should not happen */
  795. "", /* 0x17 */
  796. "", /* 0x18 */
  797. "", /* 0x19 */
  798. "<Memo>", /* internal use: general memo */
  799. "<Node>", /* internal use: syntax tree node */
  800. "<iClass>", /* internal use: mixed-in module holder */
  801. };
  802. const char *
  803. rb_builtin_type_name(int t)
  804. {
  805. const char *name;
  806. if ((unsigned int)t >= numberof(builtin_types)) return 0;
  807. name = builtin_types[t];
  808. if (*name) return name;
  809. return 0;
  810. }
  811. static VALUE
  812. displaying_class_of(VALUE x)
  813. {
  814. switch (x) {
  815. case Qfalse: return rb_fstring_cstr("false");
  816. case Qnil: return rb_fstring_cstr("nil");
  817. case Qtrue: return rb_fstring_cstr("true");
  818. default: return rb_obj_class(x);
  819. }
  820. }
  821. static const char *
  822. builtin_class_name(VALUE x)
  823. {
  824. const char *etype;
  825. if (NIL_P(x)) {
  826. etype = "nil";
  827. }
  828. else if (FIXNUM_P(x)) {
  829. etype = "Integer";
  830. }
  831. else if (SYMBOL_P(x)) {
  832. etype = "Symbol";
  833. }
  834. else if (RB_TYPE_P(x, T_TRUE)) {
  835. etype = "true";
  836. }
  837. else if (RB_TYPE_P(x, T_FALSE)) {
  838. etype = "false";
  839. }
  840. else {
  841. etype = NULL;
  842. }
  843. return etype;
  844. }
  845. const char *
  846. rb_builtin_class_name(VALUE x)
  847. {
  848. const char *etype = builtin_class_name(x);
  849. if (!etype) {
  850. etype = rb_obj_classname(x);
  851. }
  852. return etype;
  853. }
  854. COLDFUNC NORETURN(static void unexpected_type(VALUE, int, int));
  855. #define UNDEF_LEAKED "undef leaked to the Ruby space"
  856. static void
  857. unexpected_type(VALUE x, int xt, int t)
  858. {
  859. const char *tname = rb_builtin_type_name(t);
  860. VALUE mesg, exc = rb_eFatal;
  861. if (tname) {
  862. mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)",
  863. displaying_class_of(x), tname);
  864. exc = rb_eTypeError;
  865. }
  866. else if (xt > T_MASK && xt <= 0x3f) {
  867. mesg = rb_sprintf("unknown type 0x%x (0x%x given, probably comes"
  868. " from extension library for ruby 1.8)", t, xt);
  869. }
  870. else {
  871. mesg = rb_sprintf("unknown type 0x%x (0x%x given)", t, xt);
  872. }
  873. rb_exc_raise(rb_exc_new_str(exc, mesg));
  874. }
  875. void
  876. rb_check_type(VALUE x, int t)
  877. {
  878. int xt;
  879. if (RB_UNLIKELY(x == Qundef)) {
  880. rb_bug(UNDEF_LEAKED);
  881. }
  882. xt = TYPE(x);
  883. if (xt != t || (xt == T_DATA && rbimpl_rtypeddata_p(x))) {
  884. /*
  885. * Typed data is not simple `T_DATA`, but in a sense an
  886. * extension of `struct RVALUE`, which are incompatible with
  887. * each other except when inherited.
  888. *
  889. * So it is not enough to just check `T_DATA`, it must be
  890. * identified by its `type` using `Check_TypedStruct` instead.
  891. */
  892. unexpected_type(x, xt, t);
  893. }
  894. }
  895. void
  896. rb_unexpected_type(VALUE x, int t)
  897. {
  898. if (RB_UNLIKELY(x == Qundef)) {
  899. rb_bug(UNDEF_LEAKED);
  900. }
  901. unexpected_type(x, TYPE(x), t);
  902. }
  903. int
  904. rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent)
  905. {
  906. while (child) {
  907. if (child == parent) return 1;
  908. child = child->parent;
  909. }
  910. return 0;
  911. }
  912. int
  913. rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
  914. {
  915. if (!RB_TYPE_P(obj, T_DATA) ||
  916. !RTYPEDDATA_P(obj) || !rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
  917. return 0;
  918. }
  919. return 1;
  920. }
  921. #undef rb_typeddata_is_instance_of
  922. int
  923. rb_typeddata_is_instance_of(VALUE obj, const rb_data_type_t *data_type)
  924. {
  925. return rb_typeddata_is_instance_of_inline(obj, data_type);
  926. }
  927. void *
  928. rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
  929. {
  930. VALUE actual;
  931. if (!RB_TYPE_P(obj, T_DATA)) {
  932. actual = displaying_class_of(obj);
  933. }
  934. else if (!RTYPEDDATA_P(obj)) {
  935. actual = displaying_class_of(obj);
  936. }
  937. else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
  938. const char *name = RTYPEDDATA_TYPE(obj)->wrap_struct_name;
  939. actual = rb_str_new_cstr(name); /* or rb_fstring_cstr? not sure... */
  940. }
  941. else {
  942. return DATA_PTR(obj);
  943. }
  944. const char *expected = data_type->wrap_struct_name;
  945. rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)",
  946. actual, expected);
  947. UNREACHABLE_RETURN(NULL);
  948. }
  949. /* exception classes */
  950. VALUE rb_eException;
  951. VALUE rb_eSystemExit;
  952. VALUE rb_eInterrupt;
  953. VALUE rb_eSignal;
  954. VALUE rb_eFatal;
  955. VALUE rb_eStandardError;
  956. VALUE rb_eRuntimeError;
  957. VALUE rb_eFrozenError;
  958. VALUE rb_eTypeError;
  959. VALUE rb_eArgError;
  960. VALUE rb_eIndexError;
  961. VALUE rb_eKeyError;
  962. VALUE rb_eRangeError;
  963. VALUE rb_eNameError;
  964. VALUE rb_eEncodingError;
  965. VALUE rb_eEncCompatError;
  966. VALUE rb_eNoMethodError;
  967. VALUE rb_eSecurityError;
  968. VALUE rb_eNotImpError;
  969. VALUE rb_eNoMemError;
  970. VALUE rb_cNameErrorMesg;
  971. VALUE rb_eNoMatchingPatternError;
  972. VALUE rb_eNoMatchingPatternKeyError;
  973. VALUE rb_eScriptError;
  974. VALUE rb_eSyntaxError;
  975. VALUE rb_eLoadError;
  976. VALUE rb_eSystemCallError;
  977. VALUE rb_mErrno;
  978. static VALUE rb_eNOERROR;
  979. ID ruby_static_id_cause;
  980. #define id_cause ruby_static_id_cause
  981. static ID id_message, id_backtrace;
  982. static ID id_key, id_matchee, id_args, id_Errno, id_errno, id_i_path;
  983. static ID id_receiver, id_recv, id_iseq, id_local_variables;
  984. static ID id_private_call_p, id_top, id_bottom;
  985. #define id_bt idBt
  986. #define id_bt_locations idBt_locations
  987. #define id_mesg idMesg
  988. #define id_name idName
  989. #undef rb_exc_new_cstr
  990. VALUE
  991. rb_exc_new(VALUE etype, const char *ptr, long len)
  992. {
  993. VALUE mesg = rb_str_new(ptr, len);
  994. return rb_class_new_instance(1, &mesg, etype);
  995. }
  996. VALUE
  997. rb_exc_new_cstr(VALUE etype, const char *s)
  998. {
  999. return rb_exc_new(etype, s, strlen(s));
  1000. }
  1001. VALUE
  1002. rb_exc_new_str(VALUE etype, VALUE str)
  1003. {
  1004. StringValue(str);
  1005. return rb_class_new_instance(1, &str, etype);
  1006. }
  1007. static VALUE
  1008. exc_init(VALUE exc, VALUE mesg)
  1009. {
  1010. rb_ivar_set(exc, id_mesg, mesg);
  1011. rb_ivar_set(exc, id_bt, Qnil);
  1012. return exc;
  1013. }
  1014. /*
  1015. * call-seq:
  1016. * Exception.new(msg = nil) -> exception
  1017. * Exception.exception(msg = nil) -> exception
  1018. *
  1019. * Construct a new Exception object, optionally passing in
  1020. * a message.
  1021. */
  1022. static VALUE
  1023. exc_initialize(int argc, VALUE *argv, VALUE exc)
  1024. {
  1025. VALUE arg;
  1026. arg = (!rb_check_arity(argc, 0, 1) ? Qnil : argv[0]);
  1027. return exc_init(exc, arg);
  1028. }
  1029. /*
  1030. * Document-method: exception
  1031. *
  1032. * call-seq:
  1033. * exc.exception([string]) -> an_exception or exc
  1034. *
  1035. * With no argument, or if the argument is the same as the receiver,
  1036. * return the receiver. Otherwise, create a new
  1037. * exception object of the same class as the receiver, but with a
  1038. * message equal to <code>string.to_str</code>.
  1039. *
  1040. */
  1041. static VALUE
  1042. exc_exception(int argc, VALUE *argv, VALUE self)
  1043. {
  1044. VALUE exc;
  1045. argc = rb_check_arity(argc, 0, 1);
  1046. if (argc == 0) return self;
  1047. if (argc == 1 && self == argv[0]) return self;
  1048. exc = rb_obj_clone(self);
  1049. rb_ivar_set(exc, id_mesg, argv[0]);
  1050. return exc;
  1051. }
  1052. /*
  1053. * call-seq:
  1054. * exception.to_s -> string
  1055. *
  1056. * Returns exception's message (or the name of the exception if
  1057. * no message is set).
  1058. */
  1059. static VALUE
  1060. exc_to_s(VALUE exc)
  1061. {
  1062. VALUE mesg = rb_attr_get(exc, idMesg);
  1063. if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
  1064. return rb_String(mesg);
  1065. }
  1066. /* FIXME: Include eval_error.c */
  1067. void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlight, VALUE reverse);
  1068. VALUE
  1069. rb_get_message(VALUE exc)
  1070. {
  1071. VALUE e = rb_check_funcall(exc, id_message, 0, 0);
  1072. if (e == Qundef) return Qnil;
  1073. if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
  1074. return e;
  1075. }
  1076. /*
  1077. * call-seq:
  1078. * Exception.to_tty? -> true or false
  1079. *
  1080. * Returns +true+ if exception messages will be sent to a tty.
  1081. */
  1082. static VALUE
  1083. exc_s_to_tty_p(VALUE self)
  1084. {
  1085. return RBOOL(rb_stderr_tty_p());
  1086. }
  1087. /*
  1088. * call-seq:
  1089. * exception.full_message(highlight: bool, order: [:top or :bottom]) -> string
  1090. *
  1091. * Returns formatted string of _exception_.
  1092. * The returned string is formatted using the same format that Ruby uses
  1093. * when printing an uncaught exceptions to stderr.
  1094. *
  1095. * If _highlight_ is +true+ the default error handler will send the
  1096. * messages to a tty.
  1097. *
  1098. * _order_ must be either of +:top+ or +:bottom+, and places the error
  1099. * message and the innermost backtrace come at the top or the bottom.
  1100. *
  1101. * The default values of these options depend on <code>$stderr</code>
  1102. * and its +tty?+ at the timing of a call.
  1103. */
  1104. static VALUE
  1105. exc_full_message(int argc, VALUE *argv, VALUE exc)
  1106. {
  1107. VALUE opt, str, emesg, errat;
  1108. enum {kw_highlight, kw_order, kw_max_};
  1109. static ID kw[kw_max_];
  1110. VALUE args[kw_max_] = {Qnil, Qnil};
  1111. rb_scan_args(argc, argv, "0:", &opt);
  1112. if (!NIL_P(opt)) {
  1113. if (!kw[0]) {
  1114. #define INIT_KW(n) kw[kw_##n] = rb_intern_const(#n)
  1115. INIT_KW(highlight);
  1116. INIT_KW(order);
  1117. #undef INIT_KW
  1118. }
  1119. rb_get_kwargs(opt, kw, 0, kw_max_, args);
  1120. switch (args[kw_highlight]) {
  1121. default:
  1122. rb_bool_expected(args[kw_highlight], "highlight");
  1123. UNREACHABLE;
  1124. case Qundef: args[kw_highlight] = Qnil; break;
  1125. case Qtrue: case Qfalse: case Qnil: break;
  1126. }
  1127. if (args[kw_order] == Qundef) {
  1128. args[kw_order] = Qnil;
  1129. }
  1130. else {
  1131. ID id = rb_check_id(&args[kw_order]);
  1132. if (id == id_bottom) args[kw_order] = Qtrue;
  1133. else if (id == id_top) args[kw_order] = Qfalse;
  1134. else {
  1135. rb_raise(rb_eArgError, "expected :top or :bottom as "
  1136. "order: %+"PRIsVALUE, args[kw_order]);
  1137. }
  1138. }
  1139. }
  1140. str = rb_str_new2("");
  1141. errat = rb_get_backtrace(exc);
  1142. emesg = rb_get_message(exc);
  1143. rb_error_write(exc, emesg, errat, str, args[kw_highlight], args[kw_order]);
  1144. return str;
  1145. }
  1146. /*
  1147. * call-seq:
  1148. * exception.message -> string
  1149. *
  1150. * Returns the result of invoking <code>exception.to_s</code>.
  1151. * Normally this returns the exception's message or name.
  1152. */
  1153. static VALUE
  1154. exc_message(VALUE exc)
  1155. {
  1156. return rb_funcallv(exc, idTo_s, 0, 0);
  1157. }
  1158. /*
  1159. * call-seq:
  1160. * exception.inspect -> string
  1161. *
  1162. * Return this exception's class name and message.
  1163. */
  1164. static VALUE
  1165. exc_inspect(VALUE exc)
  1166. {
  1167. VALUE str, klass;
  1168. klass = CLASS_OF(exc);
  1169. exc = rb_obj_as_string(exc);
  1170. if (RSTRING_LEN(exc) == 0) {
  1171. return rb_class_name(klass);
  1172. }
  1173. str = rb_str_buf_new2("#<");
  1174. klass = rb_class_name(klass);
  1175. rb_str_buf_append(str, klass);
  1176. rb_str_buf_cat(str, ": ", 2);
  1177. rb_str_buf_append(str, exc);
  1178. rb_str_buf_cat(str, ">", 1);
  1179. return str;
  1180. }
  1181. /*
  1182. * call-seq:
  1183. * exception.backtrace -> array or nil
  1184. *
  1185. * Returns any backtrace associated with the exception. The backtrace
  1186. * is an array of strings, each containing either ``filename:lineNo: in
  1187. * `method''' or ``filename:lineNo.''
  1188. *
  1189. * def a
  1190. * raise "boom"
  1191. * end
  1192. *
  1193. * def b
  1194. * a()
  1195. * end
  1196. *
  1197. * begin
  1198. * b()
  1199. * rescue => detail
  1200. * print detail.backtrace.join("\n")
  1201. * end
  1202. *
  1203. * <em>produces:</em>
  1204. *
  1205. * prog.rb:2:in `a'
  1206. * prog.rb:6:in `b'
  1207. * prog.rb:10
  1208. *
  1209. * In the case no backtrace has been set, +nil+ is returned
  1210. *
  1211. * ex = StandardError.new
  1212. * ex.backtrace
  1213. * #=> nil
  1214. */
  1215. static VALUE
  1216. exc_backtrace(VALUE exc)
  1217. {
  1218. VALUE obj;
  1219. obj = rb_attr_get(exc, id_bt);
  1220. if (rb_backtrace_p(obj)) {
  1221. obj = rb_backtrace_to_str_ary(obj);
  1222. /* rb_ivar_set(exc, id_bt, obj); */
  1223. }
  1224. return obj;
  1225. }
  1226. static VALUE rb_check_backtrace(VALUE);
  1227. VALUE
  1228. rb_get_backtrace(VALUE exc)
  1229. {
  1230. ID mid = id_backtrace;
  1231. VALUE info;
  1232. if (rb_method_basic_definition_p(CLASS_OF(exc), id_backtrace)) {
  1233. VALUE klass = rb_eException;
  1234. rb_execution_context_t *ec = GET_EC();
  1235. if (NIL_P(exc))
  1236. return Qnil;
  1237. EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, exc, mid, mid, klass, Qundef);
  1238. info = exc_backtrace(exc);
  1239. EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, exc, mid, mid, klass, info);
  1240. }
  1241. else {
  1242. info = rb_funcallv(exc, mid, 0, 0);
  1243. }
  1244. if (NIL_P(info)) return Qnil;
  1245. return rb_check_backtrace(info);
  1246. }
  1247. /*
  1248. * call-seq:
  1249. * exception.backtrace_locations -> array or nil
  1250. *
  1251. * Returns any backtrace associated with the exception. This method is
  1252. * similar to Exception#backtrace, but the backtrace is an array of
  1253. * Thread::Backtrace::Location.
  1254. *
  1255. * This method is not affected by Exception#set_backtrace().
  1256. */
  1257. static VALUE
  1258. exc_backtrace_locations(VALUE exc)
  1259. {
  1260. VALUE obj;
  1261. obj = rb_attr_get(exc, id_bt_locations);
  1262. if (!NIL_P(obj)) {
  1263. obj = rb_backtrace_to_location_ary(obj);
  1264. }
  1265. return obj;
  1266. }
  1267. static VALUE
  1268. rb_check_backtrace(VALUE bt)
  1269. {
  1270. long i;
  1271. static const char err[] = "backtrace must be Array of String";
  1272. if (!NIL_P(bt)) {
  1273. if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
  1274. if (rb_backtrace_p(bt)) return bt;
  1275. if (!RB_TYPE_P(bt, T_ARRAY)) {
  1276. rb_raise(rb_eTypeError, err);
  1277. }
  1278. for (i=0;i<RARRAY_LEN(bt);i++) {
  1279. VALUE e = RARRAY_AREF(bt, i);
  1280. if (!RB_TYPE_P(e, T_STRING)) {
  1281. rb_raise(rb_eTypeError, err);
  1282. }
  1283. }
  1284. }
  1285. return bt;
  1286. }
  1287. /*
  1288. * call-seq:
  1289. * exc.set_backtrace(backtrace) -> array
  1290. *
  1291. * Sets the backtrace information associated with +exc+. The +backtrace+ must
  1292. * be an array of String objects or a single String in the format described
  1293. * in Exception#backtrace.
  1294. *
  1295. */
  1296. static VALUE
  1297. exc_set_backtrace(VALUE exc, VALUE bt)
  1298. {
  1299. return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
  1300. }
  1301. MJIT_FUNC_EXPORTED VALUE
  1302. rb_exc_set_backtrace(VALUE exc, VALUE bt)
  1303. {
  1304. return exc_set_backtrace(exc, bt);
  1305. }
  1306. /*
  1307. * call-seq:
  1308. * exception.cause -> an_exception or nil
  1309. *
  1310. * Returns the previous exception ($!) at the time this exception was raised.
  1311. * This is useful for wrapping exceptions and retaining the original exception
  1312. * information.
  1313. */
  1314. static VALUE
  1315. exc_cause(VALUE exc)
  1316. {
  1317. return rb_attr_get(exc, id_cause);
  1318. }
  1319. static VALUE
  1320. try_convert_to_exception(VALUE obj)
  1321. {
  1322. return rb_check_funcall(obj, idException, 0, 0);
  1323. }
  1324. /*
  1325. * call-seq:
  1326. * exc == obj -> true or false
  1327. *
  1328. * Equality---If <i>obj</i> is not an Exception, returns
  1329. * <code>false</code>. Otherwise, returns <code>true</code> if <i>exc</i> and
  1330. * <i>obj</i> share same class, messages, and backtrace.
  1331. */
  1332. static VALUE
  1333. exc_equal(VALUE exc, VALUE obj)
  1334. {
  1335. VALUE mesg, backtrace;
  1336. if (exc == obj) return Qtrue;
  1337. if (rb_obj_class(exc) != rb_obj_class(obj)) {
  1338. int state;
  1339. obj = rb_protect(try_convert_to_exception, obj, &state);
  1340. if (state || obj == Qundef) {
  1341. rb_set_errinfo(Qnil);
  1342. return Qfalse;
  1343. }
  1344. if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
  1345. mesg = rb_check_funcall(obj, id_message, 0, 0);
  1346. if (mesg == Qundef) return Qfalse;
  1347. backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
  1348. if (backtrace == Qundef) return Qfalse;
  1349. }
  1350. else {
  1351. mesg = rb_attr_get(obj, id_mesg);
  1352. backtrace = exc_backtrace(obj);
  1353. }
  1354. if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
  1355. return Qfalse;
  1356. return rb_equal(exc_backtrace(exc), backtrace);
  1357. }
  1358. /*
  1359. * call-seq:
  1360. * SystemExit.new -> system_exit
  1361. * SystemExit.new(status) -> system_exit
  1362. * SystemExit.new(status, msg) -> system_exit
  1363. * SystemExit.new(msg) -> system_exit
  1364. *
  1365. * Create a new +SystemExit+ exception with the given status and message.
  1366. * Status is true, false, or an integer.
  1367. * If status is not given, true is used.
  1368. */
  1369. static VALUE
  1370. exit_initialize(int argc, VALUE *argv, VALUE exc)
  1371. {
  1372. VALUE status;
  1373. if (argc > 0) {
  1374. status = *argv;
  1375. switch (status) {
  1376. case Qtrue:
  1377. status = INT2FIX(EXIT_SUCCESS);
  1378. ++argv;
  1379. --argc;
  1380. break;
  1381. case Qfalse:
  1382. status = INT2FIX(EXIT_FAILURE);
  1383. ++argv;
  1384. --argc;
  1385. break;
  1386. default:
  1387. status = rb_check_to_int(status);
  1388. if (NIL_P(status)) {
  1389. status = INT2FIX(EXIT_SUCCESS);
  1390. }
  1391. else {
  1392. #if EXIT_SUCCESS != 0
  1393. if (status == INT2FIX(0))
  1394. status = INT2FIX(EXIT_SUCCESS);
  1395. #endif
  1396. ++argv;
  1397. --argc;
  1398. }
  1399. break;
  1400. }
  1401. }
  1402. else {
  1403. status = INT2FIX(EXIT_SUCCESS);
  1404. }
  1405. rb_call_super(argc, argv);
  1406. rb_ivar_set(exc, id_status, status);
  1407. return exc;
  1408. }
  1409. /*
  1410. * call-seq:
  1411. * system_exit.status -> integer
  1412. *
  1413. * Return the status value associated with this system exit.
  1414. */
  1415. static VALUE
  1416. exit_status(VALUE exc)
  1417. {
  1418. return rb_attr_get(exc, id_status);
  1419. }
  1420. /*
  1421. * call-seq:
  1422. * system_exit.success? -> true or false
  1423. *
  1424. * Returns +true+ if exiting successful, +false+ if not.
  1425. */
  1426. static VALUE
  1427. exit_success_p(VALUE exc)
  1428. {
  1429. VALUE status_val = rb_attr_get(exc, id_status);
  1430. int status;
  1431. if (NIL_P(status_val))
  1432. return Qtrue;
  1433. status = NUM2INT(status_val);
  1434. return RBOOL(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
  1435. }
  1436. static VALUE
  1437. err_init_recv(VALUE exc, VALUE recv)
  1438. {
  1439. if (recv != Qundef) rb_ivar_set(exc, id_recv, recv);
  1440. return exc;
  1441. }
  1442. /*
  1443. * call-seq:
  1444. * FrozenError.new(msg=nil, receiver: nil) -> frozen_error
  1445. *
  1446. * Construct a new FrozenError exception. If given the <i>receiver</i>
  1447. * parameter may subsequently be examined using the FrozenError#receiver
  1448. * method.
  1449. *
  1450. * a = [].freeze
  1451. * raise FrozenError.new("can't modify frozen array", receiver: a)
  1452. */
  1453. static VALUE
  1454. frozen_err_initialize(int argc, VALUE *argv, VALUE self)
  1455. {
  1456. ID keywords[1];
  1457. VALUE values[numberof(keywords)], options;
  1458. argc = rb_scan_args(argc, argv, "*:", NULL, &options);
  1459. keywords[0] = id_receiver;
  1460. rb_get_kwargs(options, keywords, 0, numberof(values), values);
  1461. rb_call_super(argc, argv);
  1462. err_init_recv(self, values[0]);
  1463. return self;
  1464. }
  1465. /*
  1466. * Document-method: FrozenError#receiver
  1467. * call-seq:
  1468. * frozen_error.receiver -> object
  1469. *
  1470. * Return the receiver associated with this FrozenError exception.
  1471. */
  1472. #define frozen_err_receiver name_err_receiver
  1473. void
  1474. rb_name_error(ID id, const char *fmt, ...)
  1475. {
  1476. VALUE exc, argv[2];
  1477. va_list args;
  1478. va_start(args, fmt);
  1479. argv[0] = rb_vsprintf(fmt, args);
  1480. va_end(args);
  1481. argv[1] = ID2SYM(id);
  1482. exc = rb_class_new_instance(2, argv, rb_eNameError);
  1483. rb_exc_raise(exc);
  1484. }
  1485. void
  1486. rb_name_error_str(VALUE str, const char *fmt, ...)
  1487. {
  1488. VALUE exc, argv[2];
  1489. va_list args;
  1490. va_start(args, fmt);
  1491. argv[0] = rb_vsprintf(fmt, args);
  1492. va_end(args);
  1493. argv[1] = str;
  1494. exc = rb_class_new_instance(2, argv, rb_eNameError);
  1495. rb_exc_raise(exc);
  1496. }
  1497. static VALUE
  1498. name_err_init_attr(VALUE exc, VALUE recv, VALUE method)
  1499. {
  1500. const rb_execution_context_t *ec = GET_EC();
  1501. rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
  1502. cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
  1503. rb_ivar_set(exc, id_name, method);
  1504. err_init_recv(exc, recv);
  1505. if (cfp) rb_ivar_set(exc, id_iseq, rb_iseqw_new(cfp->iseq));
  1506. return exc;
  1507. }
  1508. /*
  1509. * call-seq:
  1510. * NameError.new(msg=nil, name=nil, receiver: nil) -> name_error
  1511. *
  1512. * Construct a new NameError exception. If given the <i>name</i>
  1513. * parameter may subsequently be examined using the NameError#name
  1514. * method. <i>receiver</i> parameter allows to pass object in
  1515. * context of which the error happened. Example:
  1516. *
  1517. * [1, 2, 3].method(:rject) # NameError with name "rject" and receiver: Array
  1518. * [1, 2, 3].singleton_method(:rject) # NameError with name "rject" and receiver: [1, 2, 3]
  1519. */
  1520. static VALUE
  1521. name_err_initialize(int argc, VALUE *argv, VALUE self)
  1522. {
  1523. ID keywords[1];
  1524. VALUE values[numberof(keywords)], name, options;
  1525. argc = rb_scan_args(argc, argv, "*:", NULL, &options);
  1526. keywords[0] = id_receiver;
  1527. rb_get_kwargs(options, keywords, 0, numberof(values), values);
  1528. name = (argc > 1) ? argv[--argc] : Qnil;
  1529. rb_call_super(argc, argv);
  1530. name_err_init_attr(self, values[0], name);
  1531. return self;
  1532. }
  1533. static VALUE rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method);
  1534. static VALUE
  1535. name_err_init(VALUE exc, VALUE mesg, VALUE recv, VALUE method)
  1536. {
  1537. exc_init(exc, rb_name_err_mesg_new(mesg, recv, method));
  1538. return name_err_init_attr(exc, recv, method);
  1539. }
  1540. VALUE
  1541. rb_name_err_new(VALUE mesg, VALUE recv, VALUE method)
  1542. {
  1543. VALUE exc = rb_obj_alloc(rb_eNameError);
  1544. return name_err_init(exc, mesg, recv, method);
  1545. }
  1546. /*
  1547. * call-seq:
  1548. * name_error.name -> string or nil
  1549. *
  1550. * Return the name associated with this NameError exception.
  1551. */
  1552. static VALUE
  1553. name_err_name(VALUE self)
  1554. {
  1555. return rb_attr_get(self, id_name);
  1556. }
  1557. /*
  1558. * call-seq:
  1559. * name_error.local_variables -> array
  1560. *
  1561. * Return a list of the local variable names defined where this
  1562. * NameError exception was raised.
  1563. *
  1564. * Internal use only.
  1565. */
  1566. static VALUE
  1567. name_err_local_variables(VALUE self)
  1568. {
  1569. VALUE vars = rb_attr_get(self, id_local_variables);
  1570. if (NIL_P(vars)) {
  1571. VALUE iseqw = rb_attr_get(self, id_iseq);
  1572. if (!NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
  1573. if (NIL_P(vars)) vars = rb_ary_new();
  1574. rb_ivar_set(self, id_local_variables, vars);
  1575. }
  1576. return vars;
  1577. }
  1578. static VALUE
  1579. nometh_err_init_attr(VALUE exc, VALUE args, int priv)
  1580. {
  1581. rb_ivar_set(exc, id_args, args);
  1582. rb_ivar_set(exc, id_private_call_p, RBOOL(priv));
  1583. return exc;
  1584. }
  1585. /*
  1586. * call-seq:
  1587. * NoMethodError.new(msg=nil, name=nil, args=nil, private=false, receiver: nil) -> no_method_error
  1588. *
  1589. * Construct a NoMethodError exception for a method of the given name
  1590. * called with the given arguments. The name may be accessed using
  1591. * the <code>#name</code> method on the resulting object, and the
  1592. * arguments using the <code>#args</code> method.
  1593. *
  1594. * If <i>private</i> argument were passed, it designates method was
  1595. * attempted to call in private context, and can be accessed with
  1596. * <code>#private_call?</code> method.
  1597. *
  1598. * <i>receiver</i> argument stores an object whose method was called.
  1599. */
  1600. static VALUE
  1601. nometh_err_initialize(int argc, VALUE *argv, VALUE self)
  1602. {
  1603. int priv;
  1604. VALUE args, options;
  1605. argc = rb_scan_args(argc, argv, "*:", NULL, &options);
  1606. priv = (argc > 3) && (--argc, RTEST(argv[argc]));
  1607. args = (argc > 2) ? argv[--argc] : Qnil;
  1608. if (!NIL_P(options)) argv[argc++] = options;
  1609. rb_call_super_kw(argc, argv, RB_PASS_CALLED_KEYWORDS);
  1610. return nometh_err_init_attr(self, args, priv);
  1611. }
  1612. VALUE
  1613. rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv)
  1614. {
  1615. VALUE exc = rb_obj_alloc(rb_eNoMethodError);
  1616. name_err_init(exc, mesg, recv, method);
  1617. return nometh_err_init_attr(exc, args, priv);
  1618. }
  1619. /* :nodoc: */
  1620. enum {
  1621. NAME_ERR_MESG__MESG,
  1622. NAME_ERR_MESG__RECV,
  1623. NAME_ERR_MESG__NAME,
  1624. NAME_ERR_MESG_COUNT
  1625. };
  1626. static void
  1627. name_err_mesg_mark(void *p)
  1628. {
  1629. VALUE *ptr = p;
  1630. rb_gc_mark_locations(ptr, ptr+NAME_ERR_MESG_COUNT);
  1631. }
  1632. #define name_err_mesg_free RUBY_TYPED_DEFAULT_FREE
  1633. static size_t
  1634. name_err_mesg_memsize(const void *p)
  1635. {
  1636. return NAME_ERR_MESG_COUNT * sizeof(VALUE);
  1637. }
  1638. static const rb_data_type_t name_err_mesg_data_type = {
  1639. "name_err_mesg",
  1640. {
  1641. name_err_mesg_mark,
  1642. name_err_mesg_free,
  1643. name_err_mesg_memsize,
  1644. },
  1645. 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
  1646. };
  1647. /* :nodoc: */
  1648. static VALUE
  1649. rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE method)
  1650. {
  1651. VALUE result = TypedData_Wrap_Struct(klass, &name_err_mesg_data_type, 0);
  1652. VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT);
  1653. ptr[NAME_ERR_MESG__MESG] = mesg;
  1654. ptr[NAME_ERR_MESG__RECV] = recv;
  1655. ptr[NAME_ERR_MESG__NAME] = method;
  1656. RTYPEDDATA_DATA(result) = ptr;
  1657. return result;
  1658. }
  1659. /* :nodoc: */
  1660. static VALUE
  1661. rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
  1662. {
  1663. return rb_name_err_mesg_init(rb_cNameErrorMesg, mesg, recv, method);
  1664. }
  1665. /* :nodoc: */
  1666. static VALUE
  1667. name_err_mesg_alloc(VALUE klass)
  1668. {
  1669. return rb_name_err_mesg_init(klass, Qnil, Qnil, Qnil);
  1670. }
  1671. /* :nodoc: */
  1672. static VALUE
  1673. name_err_mesg_init_copy(VALUE obj1, VALUE obj2)
  1674. {
  1675. VALUE *ptr1, *ptr2;
  1676. if (obj1 == obj2) return obj1;
  1677. rb_obj_init_copy(obj1, obj2);
  1678. TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
  1679. TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
  1680. MEMCPY(ptr1, ptr2, VALUE, NAME_ERR_MESG_COUNT);
  1681. return obj1;
  1682. }
  1683. /* :nodoc: */
  1684. static VALUE
  1685. name_err_mesg_equal(VALUE obj1, VALUE obj2)
  1686. {
  1687. VALUE *ptr1, *ptr2;
  1688. int i;
  1689. if (obj1 == obj2) return Qtrue;
  1690. if (rb_obj_class(obj2) != rb_cNameErrorMesg)
  1691. return Qfalse;
  1692. TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
  1693. TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
  1694. for (i=0; i<NAME_ERR_MESG_COUNT; i++) {
  1695. if (!rb_equal(ptr1[i], ptr2[i]))
  1696. return Qfalse;
  1697. }
  1698. return Qtrue;
  1699. }
  1700. /* :nodoc: */
  1701. static VALUE
  1702. name_err_mesg_receiver_name(VALUE obj)
  1703. {
  1704. if (RB_SPECIAL_CONST_P(obj)) return Qundef;
  1705. if (RB_BUILTIN_TYPE(obj) == T_MODULE || RB_BUILTIN_TYPE(obj) == T_CLASS) {
  1706. return rb_check_funcall(obj, rb_intern("name"), 0, 0);
  1707. }
  1708. return Qundef;
  1709. }
  1710. /* :nodoc: */
  1711. static VALUE
  1712. name_err_mesg_to_str(VALUE obj)
  1713. {
  1714. VALUE *ptr, mesg;
  1715. TypedData_Get_Struct(obj, VALUE, &name_err_mesg_data_type, ptr);
  1716. mesg = ptr[NAME_ERR_MESG__MESG];
  1717. if (NIL_P(mesg)) return Qnil;
  1718. else {
  1719. struct RString s_str, d_str;
  1720. VALUE c, s, d = 0, args[4];
  1721. int state = 0, singleton = 0;
  1722. rb_encoding *usascii = rb_usascii_encoding();
  1723. #define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
  1724. obj = ptr[NAME_ERR_MESG__RECV];
  1725. switch (obj) {
  1726. case Qnil:
  1727. d = FAKE_CSTR(&d_str, "nil");
  1728. break;
  1729. case Qtrue:
  1730. d = FAKE_CSTR(&d_str, "true");
  1731. break;
  1732. case Qfalse:
  1733. d = FAKE_CSTR(&d_str, "false");
  1734. break;
  1735. default:
  1736. d = rb_protect(name_err_mesg_receiver_name, obj, &state);
  1737. if (state || d == Qundef || d == Qnil)
  1738. d = rb_protect(rb_inspect, obj, &state);
  1739. if (state) {
  1740. rb_set_errinfo(Qnil);
  1741. }
  1742. d = rb_check_string_type(d);
  1743. if (NIL_P(d)) {
  1744. d = rb_any_to_s(obj);
  1745. }
  1746. singleton = (RSTRING_LEN(d) > 0 && RSTRING_PTR(d)[0] == '#');
  1747. break;
  1748. }
  1749. if (!singleton) {
  1750. s = FAKE_CSTR(&s_str, ":");
  1751. c = rb_class_name(CLASS_OF(obj));
  1752. }
  1753. else {
  1754. c = s = FAKE_CSTR(&s_str, "");
  1755. }
  1756. args[0] = rb_obj_as_string(ptr[NAME_ERR_MESG__NAME]);
  1757. args[1] = d;
  1758. args[2] = s;
  1759. args[3] = c;
  1760. mesg = rb_str_format(4, args, mesg);
  1761. }
  1762. return mesg;
  1763. }
  1764. /* :nodoc: */
  1765. static VALUE
  1766. name_err_mesg_dump(VALUE obj, VALUE limit)
  1767. {
  1768. return name_err_mesg_to_str(obj);
  1769. }
  1770. /* :nodoc: */
  1771. static VALUE
  1772. name_err_mesg_load(VALUE klass, VALUE str)
  1773. {
  1774. return str;
  1775. }
  1776. /*
  1777. * call-seq:
  1778. * name_error.receiver -> object
  1779. *
  1780. * Return the receiver associated with this NameError exception.
  1781. */
  1782. static VALUE
  1783. name_err_receiver(VALUE self)
  1784. {
  1785. VALUE *ptr, recv, mesg;
  1786. recv = rb_ivar_lookup(self, id_recv, Qundef);
  1787. if (recv != Qundef) return recv;
  1788. mesg = rb_attr_get(self, id_mesg);
  1789. if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) {
  1790. rb_raise(rb_eArgError, "no receiver is available");
  1791. }
  1792. ptr = DATA_PTR(mesg);
  1793. return ptr[NAME_ERR_MESG__RECV];
  1794. }
  1795. /*
  1796. * call-seq:
  1797. * no_method_error.args -> obj
  1798. *
  1799. * Return the arguments passed in as the third parameter to
  1800. * the constructor.
  1801. */
  1802. static VALUE
  1803. nometh_err_args(VALUE self)
  1804. {
  1805. return rb_attr_get(self, id_args);
  1806. }
  1807. /*
  1808. * call-seq:
  1809. * no_method_error.private_call? -> true or false
  1810. *
  1811. * Return true if the caused method was called as private.
  1812. */
  1813. static VALUE
  1814. nometh_err_private_call_p(VALUE self)
  1815. {
  1816. return rb_attr_get(self, id_private_call_p);
  1817. }
  1818. void
  1819. rb_invalid_str(const char *str, const char *type)
  1820. {
  1821. VALUE s = rb_str_new2(str);
  1822. rb_raise(rb_eArgError, "invalid value for %s: %+"PRIsVALUE, type, s);
  1823. }
  1824. /*
  1825. * call-seq:
  1826. * key_error.receiver -> object
  1827. *
  1828. * Return the receiver associated with this KeyError exception.
  1829. */
  1830. static VALUE
  1831. key_err_receiver(VALUE self)
  1832. {
  1833. VALUE recv;
  1834. recv = rb_ivar_lookup(self, id_receiver, Qundef);
  1835. if (recv != Qundef) return recv;
  1836. rb_raise(rb_eArgError, "no receiver is available");
  1837. }
  1838. /*
  1839. * call-seq:
  1840. * key_error.key -> object
  1841. *
  1842. * Return the key caused this KeyError exception.
  1843. */
  1844. static VALUE
  1845. key_err_key(VALUE self)
  1846. {
  1847. VALUE key;
  1848. key = rb_ivar_lookup(self, id_key, Qundef);
  1849. if (key != Qundef) return key;
  1850. rb_raise(rb_eArgError, "no key is available");
  1851. }
  1852. VALUE
  1853. rb_key_err_new(VALUE mesg, VALUE recv, VALUE key)
  1854. {
  1855. VALUE exc