12#include "ruby/internal/config.h"
31# include <AvailabilityMacros.h>
35#include "internal/class.h"
36#include "internal/error.h"
37#include "internal/eval.h"
38#include "internal/hash.h"
39#include "internal/io.h"
40#include "internal/load.h"
41#include "internal/object.h"
42#include "internal/process.h"
43#include "internal/string.h"
44#include "internal/symbol.h"
45#include "internal/thread.h"
46#include "internal/variable.h"
50#include "internal/vm.h"
51#include "ruby_assert.h"
68#define WIFEXITED(status) 1
72#define WEXITSTATUS(status) (status)
77int rb_str_end_with_asciichar(
VALUE str,
int c);
79long rb_backtrace_length_limit = -1;
83static VALUE rb_mWarning;
84static VALUE rb_cWarningBuffer;
88static ID id_deprecated;
89static ID id_experimental;
90static ID id_performance;
91static ID id_strict_unused_block;
92static VALUE sym_category;
93static VALUE sym_highlight;
98extern const char *rb_dynamic_description;
103#define defined_error(name, num) if (err == (num)) return (name);
104#define undefined_error(name)
105#include "known_errors.inc"
107#undef undefined_error
112err_position_0(
char *buf,
long len,
const char *file,
int line)
117 else if (line == 0) {
118 return snprintf(buf,
len,
"%s: ", file);
121 return snprintf(buf,
len,
"%s:%d: ", file, line);
127err_vcatf(
VALUE str, const
char *pre, const
char *file,
int line,
128 const
char *fmt, va_list args)
132 if (line) rb_str_catf(str,
":%d", line);
136 rb_str_vcatf(str, fmt, args);
143rb_syntax_error_append(
VALUE exc,
VALUE file,
int line,
int column,
146 const char *fn =
NIL_P(file) ? NULL : RSTRING_PTR(file);
148 VALUE mesg = rb_enc_str_new(0, 0, enc);
149 err_vcatf(mesg, NULL, fn, line, fmt, args);
151 rb_write_error_str(mesg);
155 exc = syntax_error_with_path(exc, file, &mesg, enc);
156 err_vcatf(mesg, NULL, fn, line, fmt, args);
162static unsigned int warning_disabled_categories = (
164 ~RB_WARN_CATEGORY_DEFAULT_BITS);
167rb_warning_category_mask(
VALUE category)
169 return 1U << rb_warning_category_from_name(category);
173rb_warning_category_from_name(
VALUE category)
179 !st_lookup(warning_categories.id2enum, cat_id, &cat_value)) {
180 rb_raise(
rb_eArgError,
"unknown category: %"PRIsVALUE, category);
189 if (!st_lookup(warning_categories.enum2id, category, &
id)) {
190 rb_raise(
rb_eArgError,
"invalid category: %d", (
int)category);
196rb_warning_category_update(
unsigned int mask,
unsigned int bits)
198 warning_disabled_categories &= ~mask;
199 warning_disabled_categories |= mask & ~bits;
205 return !(warning_disabled_categories & (1U << category));
233 return RBOOL(rb_warning_category_enabled_p(cat));
247 unsigned int mask = rb_warning_category_mask(category);
248 unsigned int disabled = warning_disabled_categories;
253 warning_disabled_categories = disabled;
265rb_warning_s_categories(
VALUE mod)
267 st_index_t num = warning_categories.id2enum->num_entries;
269 num = st_keys(warning_categories.id2enum, ids, num);
271 for (st_index_t i = 0; i < num; ++i) {
289rb_warning_s_warn(
int argc,
VALUE *argv,
VALUE mod)
300 if (!
NIL_P(category)) {
302 if (!rb_warning_category_enabled_p(cat))
return Qnil;
304 rb_write_error_str(str);
350rb_warning_warn_arity(
void)
353 return me ? rb_method_entry_arity(me) : 1;
360 rb_warning_category_from_name(category);
363 if (rb_warning_warn_arity() == 1) {
364 return rb_warning_warn(rb_mWarning, str);
369 args[1] = rb_hash_new_capa(1);
370 rb_hash_aset(args[1], sym_category, category);
376rb_write_warning_str(
VALUE str)
378 rb_warning_warn(rb_mWarning, str);
383warn_vsprintf(
rb_encoding *enc, const
char *file,
int line, const
char *fmt, va_list args)
385 VALUE str = rb_enc_str_new(0, 0, enc);
387 err_vcatf(str,
"warning: ", file, line, fmt, args);
391#define with_warn_vsprintf(enc, file, line, fmt) \
394 va_start(args, fmt); \
395 str = warn_vsprintf(enc, file, line, fmt, args); \
399rb_compile_warn(
const char *file,
int line,
const char *fmt, ...)
402 with_warn_vsprintf(NULL, file, line, fmt) {
403 rb_write_warning_str(str);
409rb_enc_compile_warn(
rb_encoding *enc,
const char *file,
int line,
const char *fmt, ...)
412 with_warn_vsprintf(enc, file, line, fmt) {
413 rb_write_warning_str(str);
420rb_compile_warning(
const char *file,
int line,
const char *fmt, ...)
423 with_warn_vsprintf(NULL, file, line, fmt) {
424 rb_write_warning_str(str);
431rb_enc_compile_warning(
rb_encoding *enc,
const char *file,
int line,
const char *fmt, ...)
434 with_warn_vsprintf(enc, file, line, fmt) {
435 rb_write_warning_str(str);
444 with_warn_vsprintf(NULL, file, line, fmt) {
445 rb_warn_category(str, rb_warning_category_to_name(category));
452warning_string(
rb_encoding *enc, const
char *fmt, va_list args)
455 const char *file = rb_source_location_cstr(&line);
456 return warn_vsprintf(enc, file, line, fmt, args);
459#define with_warning_string(mesg, enc, fmt) \
460 with_warning_string_from(mesg, enc, fmt, fmt)
461#define with_warning_string_from(mesg, enc, fmt, last_arg) \
463 va_list args; va_start(args, last_arg); \
464 mesg = warning_string(enc, fmt, args); \
471 with_warning_string(mesg, 0, fmt) {
472 rb_write_warning_str(mesg);
481 with_warning_string(mesg, 0, fmt) {
482 rb_warn_category(mesg, rb_warning_category_to_name(category));
491 with_warning_string(mesg, enc, fmt) {
492 rb_write_warning_str(mesg);
502 with_warning_string(mesg, 0, fmt) {
503 rb_write_warning_str(mesg);
513 with_warning_string(mesg, 0, fmt) {
514 rb_warn_category(mesg, rb_warning_category_to_name(category));
520rb_warning_string(
const char *fmt, ...)
522 with_warning_string(mesg, 0, fmt) {
529rb_enc_warning(
rb_encoding *enc,
const char *fmt, ...)
532 with_warning_string(mesg, enc, fmt) {
533 rb_write_warning_str(mesg);
540deprecation_warning_enabled(
void)
548warn_deprecated(
VALUE mesg,
const char *removal,
const char *suggest,
VALUE category)
553 rb_str_catf(mesg,
" and will be removed in Ruby %s", removal);
555 if (suggest) rb_str_catf(mesg,
"; use %s instead", suggest);
557 rb_warn_category(mesg, category);
561rb_warn_deprecated(
const char *fmt,
const char *suggest, ...)
563 if (!deprecation_warning_enabled())
return;
565 with_warning_string_from(mesg, 0, fmt, suggest) {
566 warn_deprecated(mesg, NULL, suggest,
ID2SYM(id_deprecated));
571rb_warn_deprecated_to_remove(
const char *removal,
const char *fmt,
const char *suggest, ...)
573 if (!deprecation_warning_enabled())
return;
575 with_warning_string_from(mesg, 0, fmt, suggest) {
576 warn_deprecated(mesg, removal, suggest,
ID2SYM(id_deprecated));
581rb_warn_to_remove(
const char *removal,
const char *fmt,
const char *suggest, ...)
585 with_warning_string_from(mesg, 0, fmt, suggest) {
586 warn_deprecated(mesg, removal, suggest,
Qnil);
591rb_warn_reserved_name(
const char *coming,
const char *fmt, ...)
593 if (!deprecation_warning_enabled())
return;
595 with_warning_string_from(mesg, 0, fmt, fmt) {
597 rb_str_catf(mesg,
" is reserved for Ruby %s\n", coming);
598 rb_warn_category(mesg,
ID2SYM(id_deprecated));
603end_with_asciichar(
VALUE str,
int c)
606 rb_str_end_with_asciichar(str, c);
611warning_write(
int argc,
VALUE *argv,
VALUE buf)
630 if (!
NIL_P(uplevel)) {
635 location = rb_ec_backtrace_location_ary(ec, lev + 1, 1, TRUE);
636 if (!
NIL_P(location)) {
640 if (argc > 1 || !
NIL_P(uplevel) || !end_with_asciichar(str,
'\n')) {
642 if (
NIL_P(uplevel)) {
645 else if (
NIL_P(location) ||
650 str = rb_sprintf(
"%s:%ld: warning: ",
654 RBASIC_SET_CLASS(str, rb_cWarningBuffer);
655 rb_io_puts(argc, argv, str);
659 if (!
NIL_P(category)) {
660 category = rb_to_symbol_type(category);
661 rb_warning_category_from_name(category);
664 if (exc == rb_mWarning) {
666 rb_write_error_str(str);
669 rb_warn_category(str, category);
675#define MAX_BUG_REPORTERS 0x100
678 void (*func)(
FILE *out,
void *data);
682static int bug_reporters_size;
685rb_bug_reporter_add(
void (*func)(
FILE *,
void *),
void *data)
688 if (bug_reporters_size >= MAX_BUG_REPORTERS) {
692 reporter->func = func;
693 reporter->data = data;
702#if defined __CYGWIN__ || defined DOSISH
703# define PATH_SEP_ENCODING 1
705 if (x ==
':')
return true;
706 if (x ==
'\\')
return true;
716static const char PATHSEP_REPLACE =
'!';
719append_pathname(
char *p,
const char *pe,
VALUE str)
721#ifdef PATH_SEP_ENCODING
724 const char *s = RSTRING_PTR(str);
725 const char *
const se = s + RSTRING_LEN(str);
730 while (p < pe && s < se && (c = *s) !=
'\0') {
732 if (s == se || !*s)
break;
733 if (path_sep_p(s[1]))
goto skipsep;
735 else if (path_sep_p(c)) {
737 *p++ = PATHSEP_REPLACE;
739 while (++s < se && path_sep_p(*s));
742 const char *
const ss = s;
743 while (p < pe && s < se && *s && !path_sep_p(*s)) {
744#ifdef PATH_SEP_ENCODING
745 int n = rb_enc_mbclen(s, se, enc);
752 if (s > ss) memcpy(p - (s - ss), ss, s - ss);
759append_basename(
char *p,
const char *pe,
struct path_string *path,
VALUE str)
762#ifdef PATH_SEP_ENCODING
765 const char *
const b = RSTRING_PTR(str), *
const e =
RSTRING_END(str), *p = e;
768 if (path_sep_p(p[-1])) {
769#ifdef PATH_SEP_ENCODING
770 const char *t = rb_enc_prev_char(b, p, e, enc);
785 size_t n = path->len;
786 if (p + n > pe) n = pe - p;
787 memcpy(p, path->ptr, n);
792finish_report(
FILE *out, rb_pid_t pid)
794 if (out != stdout && out != stderr) fclose(out);
795#ifdef HAVE_WORKING_FORK
796 if (pid > 0) waitpid(pid, NULL, 0);
825expand_report_argument(
const char **input_template,
struct report_expansion *values,
826 char *buf,
size_t size,
bool word)
829 char *end = buf + size;
830 const char *
template = *input_template;
833 if (p >= end-1 || !*
template)
return NULL;
835 char c = *
template++;
837 if (!store)
continue;
840 switch (c = *
template++) {
842 p = append_basename(p, end, &values->exe,
rb_argv0);
845 p = append_pathname(p, end,
rb_argv0);
848 p = append_basename(p, end, &values->script, GET_VM()->orig_progname);
851 p = append_pathname(p, end, GET_VM()->orig_progname);
854 if (!values->pid) values->pid = getpid();
859 if (!values->time) values->time = time(NULL);
860 snprintf(p, end-p,
"%" PRI_TIMET_PREFIX
"d", values->time);
864 if (c >=
'0' && c <=
'7') {
865 c = (
unsigned char)ruby_scan_oct(
template-1, 3, &n);
867 if (!c) store =
false;
872 if (p < end-1) *p++ = c;
874 *input_template =
template;
879FILE *ruby_popen_writer(
char *
const *argv, rb_pid_t *pid);
882open_report_path(
const char *
template,
char *buf,
size_t size, rb_pid_t *pid)
886 if (!
template)
return NULL;
887 if (0) fprintf(stderr,
"RUBY_CRASH_REPORT=%s\n", buf);
888 if (*
template ==
'|') {
889 char *argv[16], *bufend = buf + size, *p;
892 for (argc = 0; argc < numberof(argv) - 1; ++argc) {
893 while (*
template &&
ISSPACE(*
template))
template++;
894 p = expand_report_argument(&
template, &values, buf, bufend-buf,
true);
900 if (!p)
return ruby_popen_writer(argv, pid);
902 else if (*
template) {
903 expand_report_argument(&
template, &values, buf, size,
false);
904 return fopen(buf,
"w");
909static const char *crash_report;
912#define REPORT_BUG_BUFSIZ 256
914bug_report_file(
const char *file,
int line, rb_pid_t *pid)
916 char buf[REPORT_BUG_BUFSIZ];
917 const char *report = crash_report;
918 if (!report) report = getenv(
"RUBY_CRASH_REPORT");
919 FILE *out = open_report_path(report, buf,
sizeof(buf), pid);
920 int len = err_position_0(buf,
sizeof(buf), file, line);
926 setvbuf(out, NULL, _IONBF, 0);
927 if ((ssize_t)fwrite(buf, 1,
len, out) == (ssize_t)
len)
return out;
930 if ((ssize_t)fwrite(buf, 1,
len, stderr) == (ssize_t)
len) {
933 if ((ssize_t)fwrite(buf, 1,
len, stdout) == (ssize_t)
len) {
940FUNC_MINIMIZED(
static void bug_important_message(
FILE *out,
const char *
const msg,
size_t len));
943bug_important_message(
FILE *out,
const char *
const msg,
size_t len)
945 const char *
const endmsg = msg +
len;
949 if (isatty(fileno(out))) {
950 static const char red[] =
"\033[;31;1;7m";
951 static const char green[] =
"\033[;32;7m";
952 static const char reset[] =
"\033[m";
953 const char *e = strchr(p,
'\n');
954 const int w = (int)(e - p);
956 int i = (int)(e - p);
957 fputs(*p ==
' ' ? green : red, out);
958 fwrite(p, 1, e - p, out);
959 for (; i < w; ++i) fputc(
' ', out);
962 }
while ((p = e + 1) < endmsg && (e = strchr(p,
'\n')) != 0 && e > p + 1);
964 fwrite(p, 1, endmsg - p, out);
967#undef CRASH_REPORTER_MAY_BE_CREATED
968#if defined(__APPLE__) && \
969 (!defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 || defined(__POWERPC__))
970# define CRASH_REPORTER_MAY_BE_CREATED
973preface_dump(
FILE *out)
976 static const char msg[] =
""
977 "-- Crash Report log information "
978 "--------------------------------------------\n"
979 " See Crash Report log file in one of the following locations:\n"
980# ifdef CRASH_REPORTER_MAY_BE_CREATED
981 " * ~/Library/Logs/CrashReporter\n"
982 " * /Library/Logs/CrashReporter\n"
984 " * ~/Library/Logs/DiagnosticReports\n"
985 " * /Library/Logs/DiagnosticReports\n"
986 " for more details.\n"
987 "Don't forget to include the above Crash Report log file in bug reports.\n"
989 const size_t msglen =
sizeof(msg) - 1;
991 const char *msg = NULL;
992 const size_t msglen = 0;
994 bug_important_message(out, msg, msglen);
998postscript_dump(
FILE *out)
1000#if defined __APPLE__
1001 static const char msg[] =
""
1004 "\n""Don't forget to include the Crash Report log file under\n"
1005# ifdef CRASH_REPORTER_MAY_BE_CREATED
1008 "DiagnosticReports directory in bug reports.\n"
1011 const size_t msglen =
sizeof(msg) - 1;
1013 const char *msg = NULL;
1014 const size_t msglen = 0;
1016 bug_important_message(out, msg, msglen);
1021bug_report_begin_valist(
FILE *out, const
char *fmt, va_list args)
1023 char buf[REPORT_BUG_BUFSIZ];
1025 fputs(
"[BUG] ", out);
1026 vsnprintf(buf,
sizeof(buf), fmt, args);
1028 snprintf(buf,
sizeof(buf),
"\n%s\n\n", rb_dynamic_description);
1033#define bug_report_begin(out, fmt) do { \
1035 va_start(args, fmt); \
1036 bug_report_begin_valist(out, fmt, args); \
1041bug_report_end(
FILE *out, rb_pid_t pid)
1046 for (i=0; i<bug_reporters_size; i++) {
1048 (*reporter->func)(out, reporter->data);
1051 postscript_dump(out);
1052 finish_report(out, pid);
1063bug_report_claim(
void)
1068 bug_reporter_ec = ec;
1071 if (ec != NULL && ec == bug_reporter_ec) {
1076 for (
int i = 0; i < 100; i++) {
1080 struct timespec ts = { 0, 100 * 1000 * 1000 };
1081 nanosleep(&ts, NULL);
1087#define report_bug(file, line, fmt, ctx) do { \
1088 rb_pid_t pid = -1; \
1089 FILE *out = bug_report_claim() ? bug_report_file(file, line, &pid) : NULL; \
1091 bug_report_begin(out, fmt); \
1092 rb_vm_bugreport(ctx, out); \
1093 bug_report_end(out, pid); \
1097#define report_bug_valist(file, line, fmt, ctx, args) do { \
1098 rb_pid_t pid = -1; \
1099 FILE *out = bug_report_claim() ? bug_report_file(file, line, &pid) : NULL; \
1101 bug_report_begin_valist(out, fmt, args); \
1102 rb_vm_bugreport(ctx, out); \
1103 bug_report_end(out, pid); \
1108ruby_set_crash_report(
const char *
template)
1110 crash_report =
template;
1113 char buf[REPORT_BUG_BUFSIZ];
1114 FILE *out = open_report_path(
template, buf,
sizeof(buf), &pid);
1116 time_t t = time(NULL);
1117 fprintf(out,
"ruby_test_bug_report: %s", ctime(&t));
1118 finish_report(out, pid);
1123NORETURN(
static void die(
void));
1127#if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
1129 _set_abort_behavior( 0, _CALL_REPORTFAULT);
1135 signal(SIGABRT, SIG_DFL);
1141rb_bug_without_die_internal(const
char *fmt, va_list args)
1143 const char *file = NULL;
1146 if (rb_current_execution_context(
false)) {
1147 file = rb_source_location_cstr(&line);
1150 report_bug_valist(file, line, fmt, NULL, args);
1155rb_bug_without_die(const
char *fmt, ...)
1158 va_start(args, fmt);
1159 rb_bug_without_die_internal(fmt, args);
1164rb_bug(
const char *fmt, ...)
1167 va_start(args, fmt);
1168 rb_bug_without_die_internal(fmt, args);
1174rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler,
int sig,
const void *ctx,
const char *fmt, ...)
1176 const char *file = NULL;
1179 if (rb_current_execution_context(
false)) {
1180 file = rb_source_location_cstr(&line);
1183 report_bug(file, line, fmt, ctx);
1185 if (default_sighandler) default_sighandler(sig);
1196 rb_bug(
"%s: errno == 0 (NOERROR)", mesg);
1198 const char *errno_str = rb_strerrno(errno_arg);
1200 rb_bug(
"%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
1202 rb_bug(
"%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
1210#define write_or_abort(fd, str, len) (write((fd), (str), (len)) < 0 ? abort() : (void)0)
1211#define WRITE_CONST(fd,str) write_or_abort((fd),(str),sizeof(str) - 1)
1214rb_async_bug_errno(
const char *mesg,
int errno_arg)
1216 WRITE_CONST(2,
"[ASYNC BUG] ");
1217 write_or_abort(2, mesg, strlen(mesg));
1218 WRITE_CONST(2,
"\n");
1220 if (errno_arg == 0) {
1221 WRITE_CONST(2,
"errno == 0 (NOERROR)\n");
1224 const char *errno_str = rb_strerrno(errno_arg);
1227 errno_str =
"undefined errno";
1228 write_or_abort(2, errno_str, strlen(errno_str));
1230 WRITE_CONST(2,
"\n\n");
1231 write_or_abort(2, rb_dynamic_description, strlen(rb_dynamic_description));
1236rb_report_bug_valist(
VALUE file,
int line,
const char *fmt, va_list args)
1238 report_bug_valist(RSTRING_PTR(file), line, fmt, NULL, args);
1242rb_assert_failure(
const char *file,
int line,
const char *name,
const char *expr)
1244 rb_assert_failure_detail(file, line, name, expr, NULL);
1248rb_assert_failure_detail(
const char *file,
int line,
const char *name,
const char *expr,
1249 const char *fmt, ...)
1252 FILE *out = bug_report_claim() ? bug_report_file(file, line, &pid) : NULL;
1254 fputs(
"Assertion Failed: ", out);
1255 if (name) fprintf(out,
"%s:", name);
1260 va_start(args, fmt);
1262 vfprintf(out, fmt, args);
1265 fprintf(out,
"\n%s\n\n", rb_dynamic_description);
1268 rb_vm_bugreport(NULL, out);
1269 bug_report_end(out, pid);
1275static const char builtin_types[][10] = {
1308rb_builtin_type_name(
int t)
1311 if ((
unsigned int)t >= numberof(builtin_types))
return 0;
1312 name = builtin_types[t];
1313 if (*name)
return name;
1318displaying_class_of(
VALUE x)
1321 case Qfalse:
return rb_fstring_cstr(
"false");
1322 case Qnil:
return rb_fstring_cstr(
"nil");
1323 case Qtrue:
return rb_fstring_cstr(
"true");
1329builtin_class_name(
VALUE x)
1355rb_builtin_class_name(
VALUE x)
1357 const char *etype = builtin_class_name(x);
1365COLDFUNC NORETURN(
static void unexpected_type(
VALUE,
int,
int));
1366#define UNDEF_LEAKED "undef leaked to the Ruby space"
1371 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected %s)",
1378 rb_raise(
rb_eTypeError,
"wrong argument type %"PRIsVALUE
" (expected %s)",
1379 displaying_class_of(obj), expected);
1383unexpected_type(
VALUE x,
int xt,
int t)
1385 const char *tname = rb_builtin_type_name(t);
1391 else if (xt >
T_MASK && xt <= 0x3f) {
1392 mesg = rb_sprintf(
"unknown type 0x%x (0x%x given, probably comes"
1393 " from extension library for ruby 1.8)", t, xt);
1396 mesg = rb_sprintf(
"unknown type 0x%x (0x%x given)", t, xt);
1406 if (RB_UNLIKELY(UNDEF_P(x))) {
1407 rb_bug(UNDEF_LEAKED);
1423 unexpected_type(x, xt, t);
1430 if (RB_UNLIKELY(UNDEF_P(x))) {
1431 rb_bug(UNDEF_LEAKED);
1434 unexpected_type(x,
TYPE(x), t);
1437#undef rb_typeddata_inherited_p
1441 return rbimpl_typeddata_inherited_p_inline(child, parent);
1444#undef rb_typeddata_is_kind_of
1448 return rbimpl_typeddata_is_kind_of_inline(obj, data_type);
1451#undef rb_typeddata_is_instance_of
1455 return rb_typeddata_is_instance_of_inline(obj, data_type);
1461 return rbimpl_check_typeddata(obj, data_type);
1495static VALUE rb_eNOERROR;
1497ID ruby_static_id_cause;
1498#define id_cause ruby_static_id_cause
1499static ID id_message, id_detailed_message, id_backtrace;
1500static ID id_key, id_matchee, id_args, id_Errno, id_errno, id_i_path;
1501static ID id_receiver, id_recv, id_iseq, id_local_variables;
1502static ID id_private_call_p, id_top, id_bottom;
1504#define id_bt_locations idBt_locations
1505#define id_mesg idMesg
1506#define id_name idName
1508#undef rb_exc_new_cstr
1526 rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
1561exc_initialize(
int argc,
VALUE *argv,
VALUE exc)
1566 return exc_init(exc, arg);
1595exc_exception(
int argc,
VALUE *argv,
VALUE self)
1600 if (argc == 0)
return self;
1601 if (argc == 1 && self == argv[0])
return self;
1623 VALUE mesg = rb_attr_get(exc, idMesg);
1633rb_get_message(
VALUE exc)
1636 if (UNDEF_P(e))
return Qnil;
1651 if (UNDEF_P(e))
return Qnil;
1663exc_s_to_tty_p(
VALUE self)
1665 return RBOOL(rb_stderr_tty_p());
1669check_highlight_keyword(
VALUE opt,
int auto_tty_detect)
1674 highlight = rb_hash_lookup(opt, sym_highlight);
1676 switch (highlight) {
1678 rb_bool_expected(highlight,
"highlight", TRUE);
1684 if (
NIL_P(highlight)) {
1685 highlight = RBOOL(auto_tty_detect && rb_stderr_tty_p());
1692check_order_keyword(
VALUE opt)
1697 static VALUE kw_order;
1700 order = rb_hash_lookup(opt, kw_order);
1702 if (order !=
Qnil) {
1704 if (
id == id_bottom) order =
Qtrue;
1705 else if (
id == id_top) order =
Qfalse;
1708 "order: %+"PRIsVALUE, order);
1768exc_full_message(
int argc,
VALUE *argv,
VALUE exc)
1770 VALUE opt, str, emesg, errat;
1771 VALUE highlight, order;
1775 highlight = check_highlight_keyword(opt, 1);
1776 order = check_order_keyword(opt);
1779 if (
NIL_P(opt)) opt = rb_hash_new_capa(1);
1780 rb_hash_aset(opt, sym_highlight, highlight);
1784 errat = rb_get_backtrace(exc);
1785 emesg = rb_get_detailed_message(exc, opt);
1787 rb_error_write(exc, emesg, errat, str, opt, highlight, order);
1801exc_message(
VALUE exc)
1812load_decoration_gem(
VALUE feature)
1823require_decoration_gems(
void)
1829 VALUE saved_errinfo = rb_errinfo();
1830 static const char *
const gems[] = {
"ErrorHighlight",
"DidYouMean",
"SyntaxSuggest"};
1831 for (
size_t i = 0; i < numberof(gems); i++) {
1833 if (
NIL_P(feature))
continue;
1835 rb_protect(load_decoration_gem, feature, &state);
1838 rb_set_errinfo(saved_errinfo);
1847lazy_load_decoration_gems(
VALUE exc)
1849 if (ATOMIC_EXCHANGE(decoration_gems_loaded, 1))
return false;
1856 require_decoration_gems();
1864rb_eager_load_detailed_message_extension(
void)
1866 if (ATOMIC_EXCHANGE(decoration_gems_loaded, 1))
return;
1868 require_decoration_gems();
1917exc_detailed_message(
int argc,
VALUE *argv,
VALUE exc)
1919 if (lazy_load_decoration_gems(exc)) {
1927 VALUE highlight = check_highlight_keyword(opt, 0);
1929 extern VALUE rb_decorate_message(
const VALUE eclass,
VALUE emesg,
int highlight);
1931 return rb_decorate_message(
CLASS_OF(exc), rb_get_message(exc),
RTEST(highlight));
1948exc_inspect(
VALUE exc)
1954 if (RSTRING_LEN(exc) == 0) {
1963 rb_str_catf(str,
":%+"PRIsVALUE, exc);
2009exc_backtrace(
VALUE exc)
2013 obj = rb_attr_get(exc, id_bt);
2015 if (rb_backtrace_p(obj)) {
2016 obj = rb_backtrace_to_str_ary(obj);
2026rb_get_backtrace(
VALUE exc)
2028 ID mid = id_backtrace;
2036 info = exc_backtrace(exc);
2043 return rb_check_backtrace(info);
2085exc_backtrace_locations(
VALUE exc)
2089 obj = rb_attr_get(exc, id_bt_locations);
2091 obj = rb_backtrace_to_location_ary(obj);
2097rb_check_backtrace(
VALUE bt)
2100 static const char err[] =
"backtrace must be an Array of String or an Array of Thread::Backtrace::Location";
2104 if (rb_backtrace_p(bt))
return bt;
2223 VALUE btobj = rb_location_ary_to_backtrace(bt);
2230 return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
2237 return exc_set_backtrace(exc, bt);
2275 return rb_attr_get(exc, id_cause);
2279try_convert_to_exception(
VALUE obj)
2296 VALUE mesg, backtrace;
2298 if (exc == obj)
return Qtrue;
2303 obj = rb_protect(try_convert_to_exception, obj, &state);
2304 if (state || UNDEF_P(obj)) {
2305 rb_set_errinfo(
Qnil);
2310 if (UNDEF_P(mesg))
return Qfalse;
2312 if (UNDEF_P(backtrace))
return Qfalse;
2315 mesg = rb_attr_get(obj, id_mesg);
2316 backtrace = exc_backtrace(obj);
2319 if (!
rb_equal(rb_attr_get(exc, id_mesg), mesg))
2321 return rb_equal(exc_backtrace(exc), backtrace);
2337exit_initialize(
int argc,
VALUE *argv,
VALUE exc)
2345 status =
INT2FIX(EXIT_SUCCESS);
2350 status =
INT2FIX(EXIT_FAILURE);
2356 if (
NIL_P(status)) {
2357 status =
INT2FIX(EXIT_SUCCESS);
2360#if EXIT_SUCCESS != 0
2362 status =
INT2FIX(EXIT_SUCCESS);
2371 status =
INT2FIX(EXIT_SUCCESS);
2387exit_status(
VALUE exc)
2389 return rb_attr_get(exc, id_status);
2401exit_success_p(
VALUE exc)
2403 VALUE status_val = rb_attr_get(exc, id_status);
2406 if (
NIL_P(status_val))
2409 return RBOOL(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
2415 if (!UNDEF_P(recv))
rb_ivar_set(exc, id_recv, recv);
2432frozen_err_initialize(
int argc,
VALUE *argv,
VALUE self)
2435 VALUE values[numberof(keywords)], options;
2438 keywords[0] = id_receiver;
2439 rb_get_kwargs(options, keywords, 0, numberof(values), values);
2441 err_init_recv(self, values[0]);
2453#define frozen_err_receiver name_err_receiver
2461 va_start(args, fmt);
2476 va_start(args, fmt);
2490 cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
2492 err_init_recv(exc, recv);
2493 if (cfp && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
2494 rb_ivar_set(exc, id_iseq, rb_iseqw_new(CFP_ISEQ(cfp)));
2513name_err_initialize(
int argc,
VALUE *argv,
VALUE self)
2516 VALUE values[numberof(keywords)], name, options;
2519 keywords[0] = id_receiver;
2520 rb_get_kwargs(options, keywords, 0, numberof(values), values);
2521 name = (argc > 1) ? argv[--argc] :
Qnil;
2523 name_err_init_attr(self, values[0], name);
2532 exc_init(exc, rb_name_err_mesg_new(mesg, recv, method));
2533 return name_err_init_attr(exc, recv, method);
2540 return name_err_init(exc, mesg, recv, method);
2551name_err_name(
VALUE self)
2553 return rb_attr_get(self, id_name);
2567name_err_local_variables(
VALUE self)
2569 VALUE vars = rb_attr_get(self, id_local_variables);
2572 VALUE iseqw = rb_attr_get(self, id_iseq);
2573 if (!
NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
2581nometh_err_init_attr(
VALUE exc,
VALUE args,
int priv)
2605nometh_err_initialize(
int argc,
VALUE *argv,
VALUE self)
2608 VALUE args, options;
2610 priv = (argc > 3) && (--argc,
RTEST(argv[argc]));
2611 args = (argc > 2) ? argv[--argc] :
Qnil;
2612 if (!
NIL_P(options)) argv[argc++] = options;
2614 return nometh_err_init_attr(self, args, priv);
2621 name_err_init(exc, mesg, recv, method);
2622 return nometh_err_init_attr(exc, args, priv);
2632name_err_mesg_mark_and_move(
void *p)
2635 rb_gc_mark_and_move(&ptr->mesg);
2636 rb_gc_mark_and_move(&ptr->recv);
2637 rb_gc_mark_and_move(&ptr->name);
2643 name_err_mesg_mark_and_move,
2646 name_err_mesg_mark_and_move,
2648 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
2672name_err_mesg_alloc(
VALUE klass)
2679name_err_mesg_init_copy(
VALUE obj1,
VALUE obj2)
2681 if (obj1 == obj2)
return obj1;
2698 if (obj1 == obj2)
return Qtrue;
2715name_err_mesg_receiver_name(
VALUE obj)
2726name_err_mesg_to_str(
VALUE obj)
2731 VALUE mesg = ptr->mesg;
2734 struct RString s_str = {RBASIC_INIT}, c_str = {RBASIC_INIT}, d_str = {RBASIC_INIT};
2735 VALUE c, s, d = 0, args[4], c2;
2739#define rb_memsearch_lit(str, v) \
2740 rb_memsearch((str), rb_strlen_lit(str), RSTRING_PTR(v), RSTRING_LEN(v), rb_enc_get(v))
2741#define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
2742 c = s = FAKE_CSTR(&s_str,
"");
2746 c = d = FAKE_CSTR(&d_str,
"nil");
2749 c = d = FAKE_CSTR(&d_str,
"true");
2752 c = d = FAKE_CSTR(&d_str,
"false");
2755 if (rb_memsearch_lit(
"%2$s", mesg) >= 0) {
2756 d = rb_protect(name_err_mesg_receiver_name, obj, &state);
2757 if (state || NIL_OR_UNDEF_P(d))
2760 rb_set_errinfo(
Qnil);
2771 s = FAKE_CSTR(&s_str,
"module ");
2775 s = FAKE_CSTR(&s_str,
"class ");
2787 s = FAKE_CSTR(&s_str,
"");
2788 if (obj == rb_vm_top_self()) {
2789 c = FAKE_CSTR(&c_str,
"main");
2797 s = FAKE_CSTR(&s_str,
"an instance of ");
2801 c2 = rb_protect(name_err_mesg_receiver_name, c, &state);
2802 if (state || NIL_OR_UNDEF_P(c2))
2805 rb_set_errinfo(
Qnil);
2827 return name_err_mesg_to_str(obj);
2845name_err_receiver(
VALUE self)
2847 VALUE recv = rb_ivar_lookup(self, id_recv,
Qundef);
2848 if (!UNDEF_P(recv))
return recv;
2850 VALUE mesg = rb_attr_get(self, id_mesg);
2851 if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) {
2869nometh_err_args(
VALUE self)
2871 return rb_attr_get(self, id_args);
2882nometh_err_private_call_p(
VALUE self)
2884 return rb_attr_get(self, id_private_call_p);
2888type_err_cname(
VALUE val)
2893 else if (val ==
Qtrue) {
2896 else if (val ==
Qfalse) {
2902NORETURN(
static void type_err_raise(
VALUE val,
const char *tname,
const char *msg));
2904type_err_raise(
VALUE val,
const char *tname,
const char *msg)
2906 const char *cname = type_err_cname(val);
2914NORETURN(
void rb_no_implicit_conversion(
VALUE val,
const char *tname));
2916rb_no_implicit_conversion(
VALUE val,
const char *tname)
2918 type_err_raise(val, tname,
"no implicit conversion of");
2921NORETURN(
void rb_cant_convert(
VALUE val,
const char *tname));
2923rb_cant_convert(
VALUE val,
const char *tname)
2925 type_err_raise(val, tname,
"can't convert");
2928NORETURN(
void rb_cant_convert_invalid_return(
VALUE val,
const char *tname,
const char *method_name,
VALUE ret));
2930rb_cant_convert_invalid_return(
VALUE val,
const char *tname,
const char *method_name,
VALUE ret)
2932 const char *cname = type_err_cname(val);
2936 enc,
rb_eTypeError,
"can't convert %s into %s (%s#%s gives %s)",
2937 cname, tname, cname, method_name, type_err_cname(ret));
2940 const char *retname = type_err_cname(ret);
2945 enc,
rb_eTypeError,
"can't convert %"PRIsVALUE
" into %s (%"PRIsVALUE
"#%s gives %s)",
2946 klass, tname, klass, method_name, retname);
2965key_err_receiver(
VALUE self)
2969 recv = rb_ivar_lookup(self, id_receiver,
Qundef);
2970 if (!UNDEF_P(recv))
return recv;
2982key_err_key(
VALUE self)
2986 key = rb_ivar_lookup(self, id_key,
Qundef);
2987 if (!UNDEF_P(key))
return key;
3011key_err_initialize(
int argc,
VALUE *argv,
VALUE self)
3017 if (!
NIL_P(options)) {
3019 VALUE values[numberof(keywords)];
3021 keywords[0] = id_receiver;
3022 keywords[1] = id_key;
3023 rb_get_kwargs(options, keywords, 0, numberof(values), values);
3024 for (i = 0; i < numberof(values); ++i) {
3025 if (!UNDEF_P(values[i])) {
3042no_matching_pattern_key_err_matchee(
VALUE self)
3046 matchee = rb_ivar_lookup(self, id_matchee,
Qundef);
3047 if (!UNDEF_P(matchee))
return matchee;
3059no_matching_pattern_key_err_key(
VALUE self)
3063 key = rb_ivar_lookup(self, id_key,
Qundef);
3064 if (!UNDEF_P(key))
return key;
3077no_matching_pattern_key_err_initialize(
int argc,
VALUE *argv,
VALUE self)
3083 if (!
NIL_P(options)) {
3085 VALUE values[numberof(keywords)];
3087 keywords[0] = id_matchee;
3088 keywords[1] = id_key;
3089 rb_get_kwargs(options, keywords, 0, numberof(values), values);
3090 for (i = 0; i < numberof(values); ++i) {
3091 if (!UNDEF_P(values[i])) {
3109syntax_error_initialize(
int argc,
VALUE *argv,
VALUE self)
3113 mesg = rb_fstring_lit(
"compile error");
3124 *mesg = rb_enc_str_new(0, 0, enc);
3129 VALUE old_path = rb_attr_get(exc, id_i_path);
3130 if (old_path != path) {
3132 rb_raise(
rb_eArgError,
"SyntaxError#path changed: %+"PRIsVALUE
" (%p->%p)",
3133 old_path, (
void *)old_path, (
void *)path);
3136 rb_raise(
rb_eArgError,
"SyntaxError#path changed: %+"PRIsVALUE
"(%s%s)->%+"PRIsVALUE
"(%s)",
3137 old_path, rb_enc_name(rb_enc_get(old_path)),
3138 (
FL_TEST(old_path, RSTRING_FSTR) ?
":FSTR" :
""),
3139 path, rb_enc_name(rb_enc_get(path)));
3142 VALUE s = *mesg = rb_attr_get(exc, idMesg);
3143 if (RSTRING_LEN(s) > 0 && *(
RSTRING_END(s)-1) !=
'\n')
3204rb_free_warning(
void)
3206 st_free_table(warning_categories.id2enum);
3207 st_free_table(warning_categories.enum2id);
3208 st_free_table(syserr_tbl);
3212setup_syserr(
int n,
const char *name)
3221#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
3226 rb_eEWOULDBLOCK = error;
3229 rb_eEINPROGRESS = error;
3233 rb_define_const(error,
"Errno",
INT2NUM(n));
3234 st_add_direct(syserr_tbl, n, (st_data_t)error);
3239set_syserr(
int n,
const char *name)
3243 if (!st_lookup(syserr_tbl, n, &error)) {
3244 return setup_syserr(n, name);
3248 rb_define_const(
rb_mErrno, name, errclass);
3258 if (!st_lookup(syserr_tbl, n, &error)) {
3261 snprintf(name,
sizeof(name),
"E%03d", n);
3262 return setup_syserr(n, name);
3264 return (
VALUE)error;
3299syserr_initialize(
int argc,
VALUE *argv,
VALUE self)
3302 VALUE mesg, error, func, errmsg;
3306 st_data_t data = (st_data_t)klass;
3309 error = mesg; mesg =
Qnil;
3311 if (!
NIL_P(error) && st_lookup(syserr_tbl,
NUM2LONG(error), &data)) {
3312 klass = (
VALUE)data;
3317 RBASIC_SET_CLASS(self, klass);
3325 else err =
"unknown error";
3331 if (!
NIL_P(func)) rb_str_catf(errmsg,
" @ %"PRIsVALUE, func);
3332 rb_str_catf(errmsg,
" - %"PRIsVALUE, str);
3349syserr_errno(
VALUE self)
3351 return rb_attr_get(self, id_errno);
3372 num = rb_attr_get(exc, id_errno);
3756exception_alloc(
VALUE klass)
3758 return rb_class_allocate_instance(klass);
3762exception_dumper(
VALUE exc)
3772ivar_copy_i(
ID key,
VALUE val, st_data_t exc)
3778void rb_exc_check_circular_cause(
VALUE exc);
3794 rb_exc_check_circular_cause(exc);
3796 if (rb_attr_get(exc, id_bt) == rb_attr_get(exc, id_bt_locations)) {
3891 syserr_tbl = st_init_numtable();
3899 rb_mWarning = rb_define_module(
"Warning");
3907 rb_cWarningBuffer = rb_define_class_under(rb_mWarning,
"buffer",
rb_cString);
3931 id_iseq = rb_make_internal_id();
3932 id_recv = rb_make_internal_id();
3934 sym_category =
ID2SYM(id_category);
3937 warning_categories.id2enum = rb_init_identtable();
3943 warning_categories.enum2id = rb_init_identtable();
3957 va_start(args, fmt);
3965rb_vraise(
VALUE exc,
const char *fmt, va_list ap)
3971rb_raise(
VALUE exc_class,
const char *fmt, ...)
3974 va_start(args, fmt);
3980NORETURN(
static void raise_loaderror(
VALUE path,
VALUE mesg));
3996 va_start(args, fmt);
3999 raise_loaderror(
Qnil, mesg);
4008 va_start(args, fmt);
4011 raise_loaderror(path, mesg);
4018 "%"PRIsVALUE
"() function is unimplemented on this machine",
4019 rb_id2str(rb_frame_this_func()));
4023rb_fatal(
const char *fmt, ...)
4028 if (! ruby_thread_has_gvl_p()) {
4031 fprintf(stderr,
"[FATAL] rb_fatal() outside of GVL\n");
4032 rb_print_backtrace(stderr);
4036 va_start(args, fmt);
4044make_errno_exc(
const char *mesg)
4050 rb_bug(
"rb_sys_fail(%s) - errno == 0", mesg ? mesg :
"");
4056make_errno_exc_str(
VALUE mesg)
4061 if (!mesg) mesg =
Qnil;
4063 const char *s = !
NIL_P(mesg) ? RSTRING_PTR(mesg) :
"";
4064 rb_bug(
"rb_sys_fail_str(%s) - errno == 0", s);
4097rb_sys_fail(
const char *mesg)
4102#undef rb_sys_fail_str
4109#ifdef RUBY_FUNCTION_NAME_STRING
4111rb_sys_fail_path_in(
const char *func_name,
VALUE path)
4116 rb_syserr_fail_path_in(func_name, n, path);
4120rb_syserr_fail_path_in(
const char *func_name,
int n,
VALUE path)
4122 rb_exc_raise(rb_syserr_new_path_in(func_name, n, path));
4126rb_syserr_new_path_in(
const char *func_name,
int n,
VALUE path)
4130 if (!path) path =
Qnil;
4132 const char *s = !
NIL_P(path) ? RSTRING_PTR(path) :
"";
4133 if (!func_name) func_name =
"(null)";
4134 rb_bug(
"rb_sys_fail_path_in(%s, %s) - errno == 0",
4143NORETURN(
static void rb_mod_exc_raise(
VALUE exc,
VALUE mod));
4155 VALUE exc = make_errno_exc(mesg);
4156 rb_mod_exc_raise(exc, mod);
4162 VALUE exc = make_errno_exc_str(mesg);
4163 rb_mod_exc_raise(exc, mod);
4170 rb_mod_exc_raise(exc, mod);
4177 rb_mod_exc_raise(exc, mod);
4181syserr_warning(
VALUE mesg,
int err)
4184 rb_str_catf(mesg,
": %s\n", strerror(err));
4185 rb_write_warning_str(mesg);
4190rb_sys_warn(
const char *fmt, ...)
4193 int errno_save =
errno;
4194 with_warning_string(mesg, 0, fmt) {
4195 syserr_warning(mesg, errno_save);
4202rb_syserr_warn(
int err,
const char *fmt, ...)
4205 with_warning_string(mesg, 0, fmt) {
4206 syserr_warning(mesg, err);
4212rb_sys_enc_warn(
rb_encoding *enc,
const char *fmt, ...)
4215 int errno_save =
errno;
4216 with_warning_string(mesg, enc, fmt) {
4217 syserr_warning(mesg, errno_save);
4224rb_syserr_enc_warn(
int err,
rb_encoding *enc,
const char *fmt, ...)
4227 with_warning_string(mesg, enc, fmt) {
4228 syserr_warning(mesg, err);
4238 int errno_save =
errno;
4239 with_warning_string(mesg, 0, fmt) {
4240 syserr_warning(mesg, errno_save);
4248rb_syserr_warning(
int err,
const char *fmt, ...)
4251 with_warning_string(mesg, 0, fmt) {
4252 syserr_warning(mesg, err);
4259rb_sys_enc_warning(
rb_encoding *enc,
const char *fmt, ...)
4262 int errno_save =
errno;
4263 with_warning_string(mesg, enc, fmt) {
4264 syserr_warning(mesg, errno_save);
4271rb_syserr_enc_warning(
int err,
rb_encoding *enc,
const char *fmt, ...)
4274 with_warning_string(mesg, enc, fmt) {
4275 syserr_warning(mesg, err);
4281rb_load_fail(
VALUE path,
const char *err)
4286 raise_loaderror(path, mesg);
4301 va_start(args, fmt);
4310inspect_frozen_obj(
VALUE obj,
VALUE mesg,
int recur)
4322get_created_info(
VALUE obj,
int *pline)
4324 VALUE info = rb_attr_get(obj, id_debug_created_info);
4338 rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
4340 VALUE mesg = rb_sprintf(
"can't modify frozen %"PRIsVALUE
": ",
4348 VALUE created_path = get_created_info(frozen_obj, &created_line);
4349 if (!
NIL_P(created_path)) {
4350 rb_str_catf(mesg,
", created at %"PRIsVALUE
":%d", created_path, created_line);
4356rb_warn_unchilled_literal(
VALUE obj)
4361 VALUE file = rb_source_location(&line);
4365 if (line) rb_str_catf(mesg,
":%d", line);
4368 rb_str_cat2(mesg,
"warning: literal string will be frozen in the future");
4371 if (STR_SHARED_P(str)) {
4372 str =
RSTRING(obj)->as.heap.aux.shared;
4374 VALUE created = get_created_info(str, &line);
4375 if (
NIL_P(created)) {
4376 rb_str_cat2(mesg,
" (run with --debug-frozen-string-literal for more information)\n");
4381 if (line) rb_str_catf(mesg,
":%d", line);
4382 rb_str_cat2(mesg,
": info: the string was created here\n");
4384 rb_warn_category(mesg, rb_warning_category_to_name(category));
4388#undef rb_check_frozen
4399 rb_check_frozen(obj);
4406 rb_eNOERROR = setup_syserr(0,
"NOERROR");
4409 rb_define_const(
rb_mErrno,
"NOERROR", rb_eNOERROR);
4411#define defined_error(name, num) set_syserr((num), (name));
4412#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNOERROR);
4413#include "known_errors.inc"
4415#undef undefined_error
4418#include "warning.rbinc"
#define RUBY_DEBUG
Define this macro when you want assertions.
#define RUBY_ATOMIC_CAS(var, oldval, newval)
Atomic compare-and-swap.
std::atomic< unsigned > rb_atomic_t
Type that is eligible for atomic operations.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
Identical to rb_enc_sprintf(), except it takes a va_list instead of variadic arguments.
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
VALUE rb_singleton_class(VALUE obj)
Finds or creates the singleton class of the passed object.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
#define rb_str_new2
Old name of rb_str_new_cstr.
#define TYPE(_)
Old name of rb_type.
#define ISSPACE
Old name of rb_isspace.
#define T_STRING
Old name of RUBY_T_STRING.
#define T_MASK
Old name of RUBY_T_MASK.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define ID2SYM
Old name of RB_ID2SYM.
#define rb_str_buf_new2
Old name of rb_str_buf_new_cstr.
#define T_DATA
Old name of RUBY_T_DATA.
#define CLASS_OF
Old name of rb_class_of.
#define T_MODULE
Old name of RUBY_T_MODULE.
#define T_TRUE
Old name of RUBY_T_TRUE.
#define FL_ABLE
Old name of RB_FL_ABLE.
#define rb_ary_new3
Old name of rb_ary_new_from_args.
#define rb_exc_new3
Old name of rb_exc_new_str.
#define T_FALSE
Old name of RUBY_T_FALSE.
#define Qtrue
Old name of RUBY_Qtrue.
#define NUM2INT
Old name of RB_NUM2INT.
#define INT2NUM
Old name of RB_INT2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define T_OBJECT
Old name of RUBY_T_OBJECT.
#define NIL_P
Old name of RB_NIL_P.
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
#define T_CLASS
Old name of RUBY_T_CLASS.
#define FL_TEST
Old name of RB_FL_TEST.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
void rb_notimplement(void)
void rb_mod_sys_fail(VALUE mod, const char *mesg)
Identical to rb_sys_fail(), except it takes additional module to extend the exception object before r...
rb_warning_category_t
Warning categories.
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
void rb_category_warning(rb_warning_category_t category, const char *fmt,...)
Identical to rb_warning(), except it takes additional "category" parameter.
void rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
Identical to rb_mod_sys_fail(), except it does not depend on C global variable errno.
VALUE rb_eNotImpError
NotImplementedError exception.
VALUE rb_eScriptError
ScriptError exception.
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
VALUE rb_eKeyError
KeyError exception.
VALUE rb_cNameErrorMesg
NameError::Message class.
VALUE rb_eSystemExit
SystemExit exception.
void rb_name_error(ID id, const char *fmt,...)
Raises an instance of rb_eNameError.
void rb_sys_warning(const char *fmt,...)
Identical to rb_sys_fail(), except it does not raise an exception to render a warning instead.
void rb_check_copyable(VALUE obj, VALUE orig)
Ensures that the passed object can be initialize_copy relationship.
VALUE rb_eStandardError
StandardError exception.
VALUE rb_mErrno
Errno module.
VALUE rb_syserr_new_str(int n, VALUE arg)
Identical to rb_syserr_new(), except it takes the message in Ruby's String instead of C's.
void rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
Identical to rb_mod_syserr_fail(), except it takes the message in Ruby's String instead of C's.
void rb_error_frozen(const char *what)
Identical to rb_frozen_error_raise(), except its raising exception has a message like "can't modify f...
VALUE rb_eFrozenError
FrozenError exception.
VALUE rb_eNoMemError
NoMemoryError exception.
VALUE rb_eRangeError
RangeError exception.
VALUE rb_eLoadError
LoadError exception.
void rb_syserr_fail_str(int e, VALUE mesg)
Identical to rb_syserr_fail(), except it takes the message in Ruby's String instead of C's.
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
VALUE rb_eTypeError
TypeError exception.
void rb_unexpected_object_type(VALUE obj, const char *expected)
Fails with the given object's type incompatibility to the type.
VALUE rb_eNoMatchingPatternError
NoMatchingPatternError exception.
void rb_name_error_str(VALUE str, const char *fmt,...)
Identical to rb_name_error(), except it takes a VALUE instead of ID.
void rb_frozen_error_raise(VALUE frozen_obj, const char *fmt,...)
Raises an instance of rb_eFrozenError.
VALUE rb_eEncCompatError
Encoding::CompatibilityError exception.
void rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt,...)
Identical to rb_compile_warn(), except it also accepts category.
VALUE rb_eFatal
fatal exception.
void rb_invalid_str(const char *str, const char *type)
Honestly I don't understand the name, but it raises an instance of rb_eArgError.
VALUE rb_eInterrupt
Interrupt exception.
VALUE rb_eNameError
NameError exception.
VALUE rb_eNoMethodError
NoMethodError exception.
void rb_exc_fatal(VALUE mesg)
Raises a fatal error in the current thread.
VALUE rb_eRuntimeError
RuntimeError exception.
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead of returning false.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
VALUE rb_exc_new(VALUE etype, const char *ptr, long len)
Creates an instance of the passed exception class.
VALUE rb_eNoMatchingPatternKeyError
NoMatchingPatternKeyError exception.
void rb_error_frozen_object(VALUE frozen_obj)
Identical to rb_error_frozen(), except it takes arbitrary Ruby object instead of C's string.
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of C's.
VALUE rb_eArgError
ArgumentError exception.
void rb_bug_errno(const char *mesg, int errno_arg)
This is a wrapper of rb_bug() which automatically constructs appropriate message from the passed errn...
void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt,...)
Identical to rb_raise(), except it additionally takes an encoding.
void rb_loaderror(const char *fmt,...)
Raises an instance of rb_eLoadError.
VALUE rb_eException
Mother of all exceptions.
VALUE rb_eIndexError
IndexError exception.
void rb_loaderror_with_path(VALUE path, const char *fmt,...)
Identical to rb_loaderror(), except it additionally takes which file is unable to load.
VALUE rb_eSyntaxError
SyntaxError exception.
VALUE rb_eEncodingError
EncodingError exception.
void rb_unexpected_typeddata(const rb_data_type_t *actual, const rb_data_type_t *expected)
Fails with the given object's type incompatibility to the type.
VALUE rb_syserr_new(int n, const char *mesg)
Creates an exception object that represents the given C errno.
VALUE rb_eSecurityError
SecurityError exception.
void rb_unexpected_type(VALUE x, int t)
Fails with the given object's type incompatibility to the type.
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
Identical to rb_mod_sys_fail(), except it takes the message in Ruby's String instead of C's.
void rb_check_type(VALUE x, int t)
This was the old implementation of Check_Type(), but they diverged.
VALUE rb_eSystemCallError
SystemCallError exception.
void rb_warning(const char *fmt,...)
Issues a warning.
VALUE rb_eSignal
SignalException exception.
@ RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK
Warning is for checking unused block strictly.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
@ RB_WARN_CATEGORY_EXPERIMENTAL
Warning is for experimental features.
@ RB_WARN_CATEGORY_PERFORMANCE
Warning is for performance issues (not enabled by -w).
@ RB_WARN_CATEGORY_NONE
Category unspecified.
VALUE rb_check_to_int(VALUE val)
Identical to rb_check_to_integer(), except it uses #to_int for conversion.
VALUE rb_cObject
Object class.
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
VALUE rb_obj_init_copy(VALUE src, VALUE dst)
Default implementation of #initialize_copy, #initialize_dup and #initialize_clone.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_cEncoding
Encoding class.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
VALUE rb_obj_clone(VALUE obj)
Produces a shallow copy of the given object.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
VALUE rb_String(VALUE val)
This is the logic behind Kernel#String.
VALUE rb_cString
String class.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
Identical to rb_enc_str_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv(), except you can specify how to handle the last element of the given array.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat)
Identical to rb_call_super(), except you can specify how to handle the last element of the given arra...
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_freeze(VALUE obj)
Freeze an array, preventing further modifications.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
static void rb_check_frozen_inline(VALUE obj)
Just another name of rb_check_frozen.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
VALUE rb_require_string(VALUE feature)
Finds and loads the given feature, if absent.
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Marshal format compatibility layer.
void ruby_default_signal(int sig)
Pretends as if there was no custom signal handler.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_tmp_new(long len)
Allocates a "temporary" string.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
#define rb_str_buf_cat
Just another name of rb_str_cat.
#define rb_exc_new_cstr(exc, str)
Identical to rb_exc_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
#define rb_str_buf_new_cstr(str)
Identical to rb_str_new_cstr, except done differently.
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
VALUE rb_str_equal(VALUE str1, VALUE str2)
Equality of two strings.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
VALUE rb_const_get(VALUE space, ID name)
Identical to rb_const_defined(), except it returns the actual defined value.
VALUE rb_autoload_p(VALUE space, ID name)
Queries if an autoload is defined at a point.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well... Let us hesitate from describing what a "basic definition" is.
void rb_attr(VALUE klass, ID name, int need_reader, int need_writer, int honour_visibility)
This function resembles now-deprecated Module#attr.
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_check_funcall(), except you can specify how to handle the last element of the given a...
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
int len
Length of the buffer.
#define DECIMAL_SIZE_OF(expr)
An approximation of decimal representation size.
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
VALUE rb_vsprintf(const char *fmt, va_list ap)
Identical to rb_sprintf(), except it takes a va_list.
#define ALLOCA_N(type, n)
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_ivar_foreach(VALUE q, int_type *w, VALUE e)
Iteration over each instance variable of the object.
#define PRI_PIDT_PREFIX
A rb_sprintf() format prefix to be used for a pid_t parameter.
#define RARRAY_LEN
Just another name of rb_array_len.
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
#define RARRAY_AREF(a, i)
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
#define StringValue(v)
Ensures that the parameter object is a String.
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
#define RSTRING(obj)
Convenient casting macro.
char * rb_string_value_ptr(volatile VALUE *ptr)
Identical to rb_str_to_str(), except it returns the converted string's backend memory region.
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
VALUE rb_argv0
The value of $0 at process bootup.
const char * rb_obj_classname(VALUE obj)
Queries the name of the class of the passed object.
#define errno
Ractor-aware version of errno.
#define RB_PASS_KEYWORDS
Pass keywords, final argument must be a hash of keywords.
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
#define RTEST
This is an old name of RB_TEST.
char * ptr
Pointer to the contents of the string.
This is the struct that holds necessary info for a struct.
const char * wrap_struct_name
Name of structs of this kind.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj)
Queries the type of the object.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.