ruby/error.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

4085 строки
104 KiB
C
Исходник Обычный вид История

/**********************************************************************
error.c -
$Author$
created at: Mon Aug 9 16:11:34 JST 1993
* encoding.c: provide basic features for M17N. * parse.y: encoding aware parsing. * parse.y (pragma_encoding): encoding specification pragma. * parse.y (rb_intern3): encoding specified symbols. * string.c (rb_str_length): length based on characters. for older behavior, bytesize method added. * string.c (rb_str_index_m): index based on characters. rindex as well. * string.c (succ_char): encoding aware succeeding string. * string.c (rb_str_reverse): reverse based on characters. * string.c (rb_str_inspect): encoding aware string description. * string.c (rb_str_upcase_bang): encoding aware case conversion. downcase, capitalize, swapcase as well. * string.c (rb_str_tr_bang): tr based on characters. delete, squeeze, tr_s, count as well. * string.c (rb_str_split_m): split based on characters. * string.c (rb_str_each_line): encoding aware each_line. * string.c (rb_str_each_char): added. iteration based on characters. * string.c (rb_str_strip_bang): encoding aware whitespace stripping. lstrip, rstrip as well. * string.c (rb_str_justify): encoding aware justifying (ljust, rjust, center). * string.c (str_encoding): get encoding attribute from a string. * re.c (rb_reg_initialize): encoding aware regular expression * sprintf.c (rb_str_format): formatting (i.e. length count) based on characters. * io.c (rb_io_getc): getc to return one-character string. for older behavior, getbyte method added. * ext/stringio/stringio.c (strio_getc): ditto. * io.c (rb_io_ungetc): allow pushing arbitrary string at the current reading point. * ext/stringio/stringio.c (strio_ungetc): ditto. * ext/strscan/strscan.c: encoding support. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
Copyright (C) 1993-2007 Yukihiro Matsumoto
**********************************************************************/
#include "ruby/internal/config.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#if defined __APPLE__
# include <AvailabilityMacros.h>
#endif
#include "internal.h"
#include "internal/class.h"
#include "internal/error.h"
#include "internal/eval.h"
#include "internal/hash.h"
#include "internal/io.h"
#include "internal/load.h"
#include "internal/object.h"
#include "internal/process.h"
#include "internal/string.h"
#include "internal/symbol.h"
#include "internal/thread.h"
#include "internal/variable.h"
#include "ruby/encoding.h"
#include "ruby/st.h"
#include "ruby/util.h"
#include "ruby_assert.h"
#include "vm_core.h"
#include "yjit.h"
#include "builtin.h"
/*!
* \addtogroup exception
* \{
*/
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef WIFEXITED
#define WIFEXITED(status) 1
#endif
#ifndef WEXITSTATUS
#define WEXITSTATUS(status) (status)
#endif
VALUE rb_iseqw_local_variables(VALUE iseqval);
VALUE rb_iseqw_new(const rb_iseq_t *);
int rb_str_end_with_asciichar(VALUE str, int c);
long rb_backtrace_length_limit = -1;
VALUE rb_eEAGAIN;
VALUE rb_eEWOULDBLOCK;
VALUE rb_eEINPROGRESS;
ruby/ruby.h: remove unnecessary exports from C-API Needlessly exporting can reduce performance locally and increase binary size. Increasing the footprint of our C-API larger is also detrimental to our development as it encourages tighter coupling with our internals; making it harder for us to preserve compatibility. If some parts of the core codebase needs access to globals, internal.h should be used instead of anything in include/ruby/*. "Urabe, Shyouhei" <shyouhei@ruby-lang.org> wrote: > On Thu, Jan 18, 2018 at 7:33 PM, Eric Wong <normalperson@yhbt.net> wrote: > > shyouhei@ruby-lang.org wrote: > >> https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61908 > >> > >> export rb_mFConst > > > > Why are we exporting all these and making the public C-API bigger? > > If anything, we should make these static. Thanks. > > No concrete reason, except they have already been externed in 2.5. > These variables had lacked declarations so far, which resulted in their > visibility to be that of extern. The commit is just confirming the status quo. > > I'm not against to turn them into static. This reverts changes from r61910, r61909, r61908, r61907, and r61906. * transcode.c (rb_eUndefinedConversionError): make static (rb_eInvalidByteSequenceError): ditto (rb_eConverterNotFoundError): ditto * process.c (rb_mProcGID, rb_mProcUid, rb_mProcID_Syscall): ditto * file.c (rb_mFConst): ditto * error.c (rb_mWarning, rb_cWarningBuffer): ditto * enumerator.c (rb_cLazy): ditto [Misc #14381] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-25 00:07:14 +03:00
static VALUE rb_mWarning;
static VALUE rb_cWarningBuffer;
static ID id_warn;
static ID id_category;
2020-12-15 09:15:23 +03:00
static ID id_deprecated;
static ID id_experimental;
static ID id_performance;
static ID id_strict_unused_block;
static VALUE sym_category;
2022-02-07 10:05:45 +03:00
static VALUE sym_highlight;
static struct {
st_table *id2enum, *enum2id;
} warning_categories;
extern const char *rb_dynamic_description;
static const char *
rb_strerrno(int err)
{
#define defined_error(name, num) if (err == (num)) return (name);
#define undefined_error(name)
#include "known_errors.inc"
#undef defined_error
#undef undefined_error
return NULL;
}
static int
err_position_0(char *buf, long len, const char *file, int line)
{
if (!file) {
return 0;
}
else if (line == 0) {
return snprintf(buf, len, "%s: ", file);
}
else {
return snprintf(buf, len, "%s:%d: ", file, line);
}
}
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 5, 0)
static VALUE
err_vcatf(VALUE str, const char *pre, const char *file, int line,
const char *fmt, va_list args)
{
if (file) {
rb_str_cat2(str, file);
if (line) rb_str_catf(str, ":%d", line);
rb_str_cat2(str, ": ");
}
if (pre) rb_str_cat2(str, pre);
rb_str_vcatf(str, fmt, args);
return str;
}
static VALUE syntax_error_with_path(VALUE, VALUE, VALUE*, rb_encoding*);
VALUE
rb_syntax_error_append(VALUE exc, VALUE file, int line, int column,
rb_encoding *enc, const char *fmt, va_list args)
{
const char *fn = NIL_P(file) ? NULL : RSTRING_PTR(file);
if (!exc) {
VALUE mesg = rb_enc_str_new(0, 0, enc);
err_vcatf(mesg, NULL, fn, line, fmt, args);
rb_str_cat2(mesg, "\n");
rb_write_error_str(mesg);
}
else {
VALUE mesg;
exc = syntax_error_with_path(exc, file, &mesg, enc);
err_vcatf(mesg, NULL, fn, line, fmt, args);
}
return exc;
}
static unsigned int warning_disabled_categories = (
(1U << RB_WARN_CATEGORY_DEPRECATED) |
~RB_WARN_CATEGORY_DEFAULT_BITS);
2019-11-12 12:34:49 +03:00
static unsigned int
rb_warning_category_mask(VALUE category)
{
return 1U << rb_warning_category_from_name(category);
}
rb_warning_category_t
rb_warning_category_from_name(VALUE category)
{
st_data_t cat_value;
ID cat_id;
2019-11-12 12:34:49 +03:00
Check_Type(category, T_SYMBOL);
if (!(cat_id = rb_check_id(&category)) ||
!st_lookup(warning_categories.id2enum, cat_id, &cat_value)) {
2019-11-12 12:34:49 +03:00
rb_raise(rb_eArgError, "unknown category: %"PRIsVALUE, category);
}
return (rb_warning_category_t)cat_value;
}
static VALUE
rb_warning_category_to_name(rb_warning_category_t category)
{
st_data_t id;
if (!st_lookup(warning_categories.enum2id, category, &id)) {
rb_raise(rb_eArgError, "invalid category: %d", (int)category);
}
return id ? ID2SYM(id) : Qnil;
2019-11-12 12:34:49 +03:00
}
void
rb_warning_category_update(unsigned int mask, unsigned int bits)
{
warning_disabled_categories &= ~mask;
warning_disabled_categories |= mask & ~bits;
}
2023-03-07 08:34:31 +03:00
bool
rb_warning_category_enabled_p(rb_warning_category_t category)
2019-11-12 12:34:49 +03:00
{
return !(warning_disabled_categories & (1U << category));
2019-11-12 12:34:49 +03:00
}
/*
2020-12-08 11:49:51 +03:00
* call-seq:
* Warning[category] -> true or false
*
* Returns the flag to show the warning messages for +category+.
* Supported categories are:
*
* +:deprecated+ ::
* deprecation warnings
* * assignment of non-nil value to <code>$,</code> and <code>$;</code>
* * keyword arguments
* etc.
*
* +:experimental+ ::
* experimental features
*
* +:performance+ ::
* performance hints
* * Shape variation limit
*/
2019-11-12 12:34:49 +03:00
static VALUE
rb_warning_s_aref(VALUE mod, VALUE category)
{
rb_warning_category_t cat = rb_warning_category_from_name(category);
2021-08-02 06:06:44 +03:00
return RBOOL(rb_warning_category_enabled_p(cat));
2019-11-12 12:34:49 +03:00
}
/*
2020-12-08 11:49:51 +03:00
* call-seq:
* Warning[category] = flag -> flag
*
* Sets the warning flags for +category+.
* See Warning.[] for the categories.
*/
2019-11-12 12:34:49 +03:00
static VALUE
rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag)
{
unsigned int mask = rb_warning_category_mask(category);
unsigned int disabled = warning_disabled_categories;
if (!RTEST(flag))
disabled |= mask;
else
disabled &= ~mask;
warning_disabled_categories = disabled;
return flag;
}
/*
* call-seq:
* categories -> array
*
* Returns a list of the supported category symbols.
*/
static VALUE
rb_warning_s_categories(VALUE mod)
{
st_index_t num = warning_categories.id2enum->num_entries;
ID *ids = ALLOCA_N(ID, num);
num = st_keys(warning_categories.id2enum, ids, num);
VALUE ary = rb_ary_new_capa(num);
for (st_index_t i = 0; i < num; ++i) {
rb_ary_push(ary, ID2SYM(ids[i]));
}
return rb_ary_freeze(ary);
}
/*
* call-seq:
* warn(msg, category: nil) -> nil
*
* Writes warning message +msg+ to $stderr. This method is called by
* Ruby for all emitted warnings. A +category+ may be included with
* the warning.
2020-10-02 13:02:54 +03:00
*
* See the documentation of the Warning module for how to customize this.
*/
static VALUE
rb_warning_s_warn(int argc, VALUE *argv, VALUE mod)
{
VALUE str;
VALUE opt;
VALUE category = Qnil;
rb_scan_args(argc, argv, "1:", &str, &opt);
if (!NIL_P(opt)) rb_get_kwargs(opt, &id_category, 0, 1, &category);
Check_Type(str, T_STRING);
rb_must_asciicompat(str);
if (!NIL_P(category)) {
rb_warning_category_t cat = rb_warning_category_from_name(category);
if (!rb_warning_category_enabled_p(cat)) return Qnil;
}
rb_write_error_str(str);
return Qnil;
}
/*
* Document-module: Warning
*
* The Warning module contains a single method named #warn, and the
* module extends itself, making Warning.warn available.
* Warning.warn is called for all warnings issued by Ruby.
* By default, warnings are printed to $stderr.
*
2020-10-02 13:02:54 +03:00
* Changing the behavior of Warning.warn is useful to customize how warnings are
* handled by Ruby, for instance by filtering some warnings, and/or outputting
* warnings somewhere other than <tt>$stderr</tt>.
2020-10-02 13:02:54 +03:00
*
* If you want to change the behavior of Warning.warn you should use
* <tt>Warning.extend(MyNewModuleWithWarnMethod)</tt> and you can use +super+
* to get the default behavior of printing the warning to <tt>$stderr</tt>.
2020-10-02 13:02:54 +03:00
*
* Example:
* module MyWarningFilter
* def warn(message, category: nil, **kwargs)
* if /some warning I want to ignore/.match?(message)
2020-10-02 13:02:54 +03:00
* # ignore
* else
* super
2020-10-02 13:02:54 +03:00
* end
* end
* end
* Warning.extend MyWarningFilter
*
* You should never redefine Warning#warn (the instance method), as that will
* then no longer provide a way to use the default behavior.
*
* The warning[https://rubygems.org/gems/warning] gem provides convenient ways to customize Warning.warn.
*/
static VALUE
rb_warning_warn(VALUE mod, VALUE str)
{
return rb_funcallv(mod, id_warn, 1, &str);
}
static int
rb_warning_warn_arity(void)
{
const rb_method_entry_t *me = rb_method_entry(rb_singleton_class(rb_mWarning), id_warn);
return me ? rb_method_entry_arity(me) : 1;
}
static VALUE
rb_warn_category(VALUE str, VALUE category)
{
if (RUBY_DEBUG && !NIL_P(category)) {
rb_warning_category_from_name(category);
}
if (rb_warning_warn_arity() == 1) {
return rb_warning_warn(rb_mWarning, str);
}
else {
VALUE args[2];
args[0] = str;
args[1] = rb_hash_new();
rb_hash_aset(args[1], sym_category, category);
return rb_funcallv_kw(rb_mWarning, id_warn, 2, args, RB_PASS_KEYWORDS);
}
}
static void
rb_write_warning_str(VALUE str)
{
rb_warning_warn(rb_mWarning, str);
}
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 0)
static VALUE
warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_list args)
{
VALUE str = rb_enc_str_new(0, 0, enc);
err_vcatf(str, "warning: ", file, line, fmt, args);
return rb_str_cat2(str, "\n");
}
2024-05-07 22:23:10 +03:00
#define with_warn_vsprintf(enc, file, line, fmt) \
2022-08-09 07:22:21 +03:00
VALUE str; \
va_list args; \
va_start(args, fmt); \
2024-05-07 22:23:10 +03:00
str = warn_vsprintf(enc, file, line, fmt, args); \
2022-08-09 07:22:21 +03:00
va_end(args);
void
rb_compile_warn(const char *file, int line, const char *fmt, ...)
{
2022-08-09 07:22:21 +03:00
if (!NIL_P(ruby_verbose)) {
2024-05-07 22:23:10 +03:00
with_warn_vsprintf(NULL, file, line, fmt) {
rb_write_warning_str(str);
}
}
}
void
rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
with_warn_vsprintf(enc, file, line, fmt) {
2022-08-09 07:22:21 +03:00
rb_write_warning_str(str);
}
}
}
/* rb_compile_warning() reports only in verbose mode */
void
rb_compile_warning(const char *file, int line, const char *fmt, ...)
{
2022-08-09 07:22:21 +03:00
if (RTEST(ruby_verbose)) {
2024-05-07 22:23:10 +03:00
with_warn_vsprintf(NULL, file, line, fmt) {
rb_write_warning_str(str);
}
}
}
/* rb_enc_compile_warning() reports only in verbose mode */
void
rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
with_warn_vsprintf(enc, file, line, fmt) {
2022-08-09 07:22:21 +03:00
rb_write_warning_str(str);
}
}
}
void
rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...)
{
2022-08-09 07:22:21 +03:00
if (!NIL_P(ruby_verbose)) {
2024-05-07 22:23:10 +03:00
with_warn_vsprintf(NULL, file, line, fmt) {
2022-08-09 07:22:21 +03:00
rb_warn_category(str, rb_warning_category_to_name(category));
}
}
}
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
static VALUE
warning_string(rb_encoding *enc, const char *fmt, va_list args)
{
int line;
const char *file = rb_source_location_cstr(&line);
return warn_vsprintf(enc, file, line, fmt, args);
}
#define with_warning_string(mesg, enc, fmt) \
with_warning_string_from(mesg, enc, fmt, fmt)
#define with_warning_string_from(mesg, enc, fmt, last_arg) \
VALUE mesg; \
va_list args; va_start(args, last_arg); \
mesg = warning_string(enc, fmt, args); \
va_end(args);
void
rb_warn(const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
with_warning_string(mesg, 0, fmt) {
rb_write_warning_str(mesg);
}
}
}
void
rb_category_warn(rb_warning_category_t category, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
with_warning_string(mesg, 0, fmt) {
rb_warn_category(mesg, rb_warning_category_to_name(category));
}
}
}
void
rb_enc_warn(rb_encoding *enc, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
with_warning_string(mesg, enc, fmt) {
rb_write_warning_str(mesg);
}
}
}
/* rb_warning() reports only in verbose mode */
void
rb_warning(const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
with_warning_string(mesg, 0, fmt) {
rb_write_warning_str(mesg);
}
}
}
/* rb_category_warning() reports only in verbose mode */
void
rb_category_warning(rb_warning_category_t category, const char *fmt, ...)
{
if (RTEST(ruby_verbose) && rb_warning_category_enabled_p(category)) {
with_warning_string(mesg, 0, fmt) {
rb_warn_category(mesg, rb_warning_category_to_name(category));
}
}
}
VALUE
rb_warning_string(const char *fmt, ...)
{
with_warning_string(mesg, 0, fmt) {
}
return mesg;
}
#if 0
void
rb_enc_warning(rb_encoding *enc, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
with_warning_string(mesg, enc, fmt) {
rb_write_warning_str(mesg);
}
}
}
#endif
static bool
deprecation_warning_enabled(void)
{
if (NIL_P(ruby_verbose)) return false;
if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return false;
return true;
}
static void
2020-12-28 13:17:52 +03:00
warn_deprecated(VALUE mesg, const char *removal, const char *suggest)
{
rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1);
rb_str_cat_cstr(mesg, " is deprecated");
2020-12-28 13:17:52 +03:00
if (removal) {
rb_str_catf(mesg, " and will be removed in Ruby %s", removal);
}
if (suggest) rb_str_catf(mesg, "; use %s instead", suggest);
rb_str_cat_cstr(mesg, "\n");
rb_warn_category(mesg, ID2SYM(id_deprecated));
}
2019-12-17 11:17:07 +03:00
void
rb_warn_deprecated(const char *fmt, const char *suggest, ...)
{
if (!deprecation_warning_enabled()) return;
2022-10-10 07:52:25 +03:00
with_warning_string_from(mesg, 0, fmt, suggest) {
warn_deprecated(mesg, NULL, suggest);
}
2019-12-17 11:17:07 +03:00
}
void
2020-12-28 13:17:52 +03:00
rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...)
{
if (!deprecation_warning_enabled()) return;
2022-10-10 07:52:25 +03:00
with_warning_string_from(mesg, 0, fmt, suggest) {
warn_deprecated(mesg, removal, suggest);
}
}
static inline int
end_with_asciichar(VALUE str, int c)
{
return RB_TYPE_P(str, T_STRING) &&
rb_str_end_with_asciichar(str, c);
}
/* :nodoc: */
static VALUE
warning_write(int argc, VALUE *argv, VALUE buf)
{
while (argc-- > 0) {
rb_str_append(buf, *argv++);
}
return buf;
}
VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal);
static VALUE
rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALUE category)
2019-12-10 14:22:42 +03:00
{
VALUE location = Qnil;
int argc = RARRAY_LENINT(msgs);
const VALUE *argv = RARRAY_CONST_PTR(msgs);
if (!NIL_P(ruby_verbose) && argc > 0) {
VALUE str = argv[0];
if (!NIL_P(uplevel)) {
long lev = NUM2LONG(uplevel);
if (lev < 0) {
rb_raise(rb_eArgError, "negative level (%ld)", lev);
}
location = rb_ec_backtrace_location_ary(ec, lev + 1, 1, TRUE);
2019-12-10 14:22:42 +03:00
if (!NIL_P(location)) {
location = rb_ary_entry(location, 0);
}
}
if (argc > 1 || !NIL_P(uplevel) || !end_with_asciichar(str, '\n')) {
VALUE path;
if (NIL_P(uplevel)) {
str = rb_str_tmp_new(0);
}
else if (NIL_P(location) ||
NIL_P(path = rb_funcall(location, rb_intern("path"), 0))) {
str = rb_str_new_cstr("warning: ");
}
else {
str = rb_sprintf("%s:%ld: warning: ",
rb_string_value_ptr(&path),
NUM2LONG(rb_funcall(location, rb_intern("lineno"), 0)));
}
RBASIC_SET_CLASS(str, rb_cWarningBuffer);
rb_io_puts(argc, argv, str);
RBASIC_SET_CLASS(str, rb_cString);
}
if (!NIL_P(category)) {
category = rb_to_symbol_type(category);
rb_warning_category_from_name(category);
}
if (exc == rb_mWarning) {
rb_must_asciicompat(str);
rb_write_error_str(str);
}
else {
rb_warn_category(str, category);
}
}
return Qnil;
}
#define MAX_BUG_REPORTERS 0x100
static struct bug_reporters {
void (*func)(FILE *out, void *data);
void *data;
} bug_reporters[MAX_BUG_REPORTERS];
static int bug_reporters_size;
int
rb_bug_reporter_add(void (*func)(FILE *, void *), void *data)
{
struct bug_reporters *reporter;
if (bug_reporters_size >= MAX_BUG_REPORTERS) {
return 0; /* failed to register */
}
reporter = &bug_reporters[bug_reporters_size++];
reporter->func = func;
reporter->data = data;
return 1;
}
2023-07-31 22:12:22 +03:00
/* returns true if x can not be used as file name */
static bool
path_sep_p(char x)
{
#if defined __CYGWIN__ || defined DOSISH
# define PATH_SEP_ENCODING 1
// Assume that "/" is only the first byte in any encoding.
if (x == ':') return true; // drive letter or ADS
if (x == '\\') return true;
#endif
return x == '/';
}
struct path_string {
const char *ptr;
size_t len;
};
static const char PATHSEP_REPLACE = '!';
static char *
append_pathname(char *p, const char *pe, VALUE str)
{
#ifdef PATH_SEP_ENCODING
rb_encoding *enc = rb_enc_get(str);
#endif
const char *s = RSTRING_PTR(str);
const char *const se = s + RSTRING_LEN(str);
char c;
--pe; // for terminator
while (p < pe && s < se && (c = *s) != '\0') {
if (c == '.') {
if (s == se || !*s) break; // chomp "." basename
if (path_sep_p(s[1])) goto skipsep; // skip "./"
}
else if (path_sep_p(c)) {
// squeeze successive separators
*p++ = PATHSEP_REPLACE;
skipsep:
while (++s < se && path_sep_p(*s));
continue;
}
const char *const ss = s;
while (p < pe && s < se && *s && !path_sep_p(*s)) {
#ifdef PATH_SEP_ENCODING
int n = rb_enc_mbclen(s, se, enc);
#else
const int n = 1;
#endif
p += n;
s += n;
}
if (s > ss) memcpy(p - (s - ss), ss, s - ss);
}
return p;
}
static char *
append_basename(char *p, const char *pe, struct path_string *path, VALUE str)
{
if (!path->ptr) {
#ifdef PATH_SEP_ENCODING
rb_encoding *enc = rb_enc_get(str);
#endif
const char *const b = RSTRING_PTR(str), *const e = RSTRING_END(str), *p = e;
while (p > b) {
if (path_sep_p(p[-1])) {
#ifdef PATH_SEP_ENCODING
const char *t = rb_enc_prev_char(b, p, e, enc);
if (t == p-1) break;
p = t;
#else
break;
#endif
}
else {
--p;
}
}
path->ptr = p;
path->len = e - p;
}
size_t n = path->len;
if (p + n > pe) n = pe - p;
memcpy(p, path->ptr, n);
return p + n;
}
static void
finish_report(FILE *out, rb_pid_t pid)
2023-07-31 22:12:22 +03:00
{
if (out != stdout && out != stderr) fclose(out);
#ifdef HAVE_WORKING_FORK
if (pid > 0) waitpid(pid, NULL, 0);
#endif
2023-07-31 22:12:22 +03:00
}
2023-08-05 13:56:29 +03:00
struct report_expansion {
struct path_string exe, script;
rb_pid_t pid;
time_t time;
};
2023-07-31 22:12:22 +03:00
/*
* Open a bug report file to write. The `RUBY_CRASH_REPORT`
2023-07-31 22:12:22 +03:00
* environment variable can be set to define a template that is used
* to name bug report files. The template can contain % specifiers
* which are substituted by the following values when a bug report
* file is created:
*
* %% A single % character.
* %e The base name of the executable filename.
* %E Pathname of executable, with slashes ('/') replaced by
* exclamation marks ('!').
* %f Similar to %e with the main script filename.
* %F Similar to %E with the main script filename.
* %p PID of dumped process in decimal.
* %t Time of dump, expressed as seconds since the Epoch,
* 1970-01-01 00:00:00 +0000 (UTC).
* %NNN Octal char code, upto 3 digits.
2023-07-31 22:12:22 +03:00
*/
2023-08-05 13:56:29 +03:00
static char *
expand_report_argument(const char **input_template, struct report_expansion *values,
char *buf, size_t size, bool word)
2023-08-05 13:56:29 +03:00
{
char *p = buf;
char *end = buf + size;
const char *template = *input_template;
bool store = true;
2023-08-05 13:56:29 +03:00
if (p >= end-1 || !*template) return NULL;
do {
char c = *template++;
if (word && ISSPACE(c)) break;
if (!store) continue;
2023-08-05 13:56:29 +03:00
if (c == '%') {
size_t n;
2023-08-05 13:56:29 +03:00
switch (c = *template++) {
case 'e':
p = append_basename(p, end, &values->exe, rb_argv0);
continue;
case 'E':
p = append_pathname(p, end, rb_argv0);
continue;
case 'f':
p = append_basename(p, end, &values->script, GET_VM()->orig_progname);
continue;
case 'F':
p = append_pathname(p, end, GET_VM()->orig_progname);
continue;
case 'p':
if (!values->pid) values->pid = getpid();
snprintf(p, end-p, "%" PRI_PIDT_PREFIX "d", values->pid);
p += strlen(p);
continue;
case 't':
if (!values->time) values->time = time(NULL);
snprintf(p, end-p, "%" PRI_TIMET_PREFIX "d", values->time);
p += strlen(p);
continue;
default:
if (c >= '0' && c <= '7') {
c = (unsigned char)ruby_scan_oct(template-1, 3, &n);
template += n - 1;
if (!c) store = false;
}
break;
2023-08-05 13:56:29 +03:00
}
}
if (p < end-1) *p++ = c;
} while (*template);
*input_template = template;
*p = '\0';
return ++p;
}
FILE *ruby_popen_writer(char *const *argv, rb_pid_t *pid);
2023-07-31 22:12:22 +03:00
static FILE *
open_report_path(const char *template, char *buf, size_t size, rb_pid_t *pid)
2023-07-31 22:12:22 +03:00
{
2023-08-05 13:56:29 +03:00
struct report_expansion values = {{0}};
if (!template) return NULL;
if (0) fprintf(stderr, "RUBY_CRASH_REPORT=%s\n", buf);
if (*template == '|') {
char *argv[16], *bufend = buf + size, *p;
int argc;
template++;
for (argc = 0; argc < numberof(argv) - 1; ++argc) {
while (*template && ISSPACE(*template)) template++;
p = expand_report_argument(&template, &values, buf, bufend-buf, true);
if (!p) break;
argv[argc] = buf;
buf = p;
}
argv[argc] = NULL;
if (!p) return ruby_popen_writer(argv, pid);
}
else if (*template) {
expand_report_argument(&template, &values, buf, size, false);
2023-07-31 22:12:22 +03:00
return fopen(buf, "w");
}
return NULL;
}
static const char *crash_report;
/* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */
#define REPORT_BUG_BUFSIZ 256
static FILE *
bug_report_file(const char *file, int line, rb_pid_t *pid)
{
char buf[REPORT_BUG_BUFSIZ];
const char *report = crash_report;
if (!report) report = getenv("RUBY_CRASH_REPORT");
FILE *out = open_report_path(report, buf, sizeof(buf), pid);
int len = err_position_0(buf, sizeof(buf), file, line);
2023-07-31 22:12:22 +03:00
if (out) {
if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len) return out;
fclose(out);
}
if ((ssize_t)fwrite(buf, 1, len, stderr) == (ssize_t)len) {
return stderr;
}
if ((ssize_t)fwrite(buf, 1, len, stdout) == (ssize_t)len) {
return stdout;
}
return NULL;
}
FUNC_MINIMIZED(static void bug_important_message(FILE *out, const char *const msg, size_t len));
static void
bug_important_message(FILE *out, const char *const msg, size_t len)
{
const char *const endmsg = msg + len;
const char *p = msg;
if (!len) return;
if (isatty(fileno(out))) {
static const char red[] = "\033[;31;1;7m";
static const char green[] = "\033[;32;7m";
static const char reset[] = "\033[m";
const char *e = strchr(p, '\n');
const int w = (int)(e - p);
do {
int i = (int)(e - p);
fputs(*p == ' ' ? green : red, out);
fwrite(p, 1, e - p, out);
for (; i < w; ++i) fputc(' ', out);
fputs(reset, out);
fputc('\n', out);
} while ((p = e + 1) < endmsg && (e = strchr(p, '\n')) != 0 && e > p + 1);
}
fwrite(p, 1, endmsg - p, out);
}
#undef CRASH_REPORTER_MAY_BE_CREATED
#if defined(__APPLE__) && \
(!defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 || defined(__POWERPC__)) /* 10.6 PPC case */
# define CRASH_REPORTER_MAY_BE_CREATED
#endif
static void
preface_dump(FILE *out)
{
#if defined __APPLE__
static const char msg[] = ""
"-- Crash Report log information "
"--------------------------------------------\n"
2021-02-06 17:05:37 +03:00
" See Crash Report log file in one of the following locations:\n"
# ifdef CRASH_REPORTER_MAY_BE_CREATED
" * ~/Library/Logs/CrashReporter\n"
" * /Library/Logs/CrashReporter\n"
# endif
" * ~/Library/Logs/DiagnosticReports\n"
" * /Library/Logs/DiagnosticReports\n"
" for more details.\n"
"Don't forget to include the above Crash Report log file in bug reports.\n"
"\n";
const size_t msglen = sizeof(msg) - 1;
#else
const char *msg = NULL;
const size_t msglen = 0;
#endif
bug_important_message(out, msg, msglen);
}
static void
postscript_dump(FILE *out)
{
#if defined __APPLE__
static const char msg[] = ""
"[IMPORTANT]"
/*" ------------------------------------------------"*/
"\n""Don't forget to include the Crash Report log file under\n"
# ifdef CRASH_REPORTER_MAY_BE_CREATED
"CrashReporter or "
# endif
"DiagnosticReports directory in bug reports.\n"
/*"------------------------------------------------------------\n"*/
"\n";
const size_t msglen = sizeof(msg) - 1;
#else
const char *msg = NULL;
const size_t msglen = 0;
#endif
bug_important_message(out, msg, msglen);
}
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
static void
bug_report_begin_valist(FILE *out, const char *fmt, va_list args)
{
char buf[REPORT_BUG_BUFSIZ];
fputs("[BUG] ", out);
vsnprintf(buf, sizeof(buf), fmt, args);
fputs(buf, out);
snprintf(buf, sizeof(buf), "\n%s\n\n", rb_dynamic_description);
fputs(buf, out);
preface_dump(out);
}
#define bug_report_begin(out, fmt) do { \
va_list args; \
va_start(args, fmt); \
bug_report_begin_valist(out, fmt, args); \
va_end(args); \
} while (0)
static void
bug_report_end(FILE *out, rb_pid_t pid)
{
/* call additional bug reporters */
{
int i;
for (i=0; i<bug_reporters_size; i++) {
struct bug_reporters *reporter = &bug_reporters[i];
(*reporter->func)(out, reporter->data);
}
}
postscript_dump(out);
finish_report(out, pid);
}
#define report_bug(file, line, fmt, ctx) do { \
rb_pid_t pid = -1; \
FILE *out = bug_report_file(file, line, &pid); \
if (out) { \
bug_report_begin(out, fmt); \
2023-07-31 21:04:42 +03:00
rb_vm_bugreport(ctx, out); \
bug_report_end(out, pid); \
} \
} while (0) \
#define report_bug_valist(file, line, fmt, ctx, args) do { \
rb_pid_t pid = -1; \
FILE *out = bug_report_file(file, line, &pid); \
if (out) { \
bug_report_begin_valist(out, fmt, args); \
2023-07-31 21:04:42 +03:00
rb_vm_bugreport(ctx, out); \
bug_report_end(out, pid); \
} \
} while (0) \
2023-08-04 10:56:55 +03:00
void
ruby_set_crash_report(const char *template)
2023-08-04 10:56:55 +03:00
{
crash_report = template;
#if RUBY_DEBUG
2023-08-05 16:12:04 +03:00
rb_pid_t pid = -1;
2023-08-04 10:56:55 +03:00
char buf[REPORT_BUG_BUFSIZ];
2023-08-05 16:12:04 +03:00
FILE *out = open_report_path(template, buf, sizeof(buf), &pid);
2023-08-04 10:56:55 +03:00
if (out) {
time_t t = time(NULL);
fprintf(out, "ruby_test_bug_report: %s", ctime(&t));
2023-08-05 16:12:04 +03:00
finish_report(out, pid);
2023-08-04 10:56:55 +03:00
}
#endif
2023-08-04 10:56:55 +03:00
}
NORETURN(static void die(void));
static void
die(void)
{
#if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
_set_abort_behavior( 0, _CALL_REPORTFAULT);
#endif
abort();
}
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0)
void
rb_bug_without_die(const char *fmt, va_list args)
{
const char *file = NULL;
int line = 0;
if (GET_EC()) {
file = rb_source_location_cstr(&line);
}
report_bug_valist(file, line, fmt, NULL, args);
}
void
rb_bug(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
rb_bug_without_die(fmt, args);
va_end(args);
die();
}
void
2019-10-09 17:39:58 +03:00
rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *ctx, const char *fmt, ...)
{
const char *file = NULL;
int line = 0;
if (GET_EC()) {
file = rb_source_location_cstr(&line);
}
report_bug(file, line, fmt, ctx);
if (default_sighandler) default_sighandler(sig);
ruby_default_signal(sig);
die();
}
void
rb_bug_errno(const char *mesg, int errno_arg)
{
if (errno_arg == 0)
rb_bug("%s: errno == 0 (NOERROR)", mesg);
else {
const char *errno_str = rb_strerrno(errno_arg);
if (errno_str)
rb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str);
else
rb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg);
}
}
/*
* this is safe to call inside signal handler and timer thread
* (which isn't a Ruby Thread object)
*/
#define write_or_abort(fd, str, len) (write((fd), (str), (len)) < 0 ? abort() : (void)0)
#define WRITE_CONST(fd,str) write_or_abort((fd),(str),sizeof(str) - 1)
void
rb_async_bug_errno(const char *mesg, int errno_arg)
{
WRITE_CONST(2, "[ASYNC BUG] ");
write_or_abort(2, mesg, strlen(mesg));
WRITE_CONST(2, "\n");
if (errno_arg == 0) {
WRITE_CONST(2, "errno == 0 (NOERROR)\n");
}
else {
const char *errno_str = rb_strerrno(errno_arg);
if (!errno_str)
errno_str = "undefined errno";
write_or_abort(2, errno_str, strlen(errno_str));
}
WRITE_CONST(2, "\n\n");
write_or_abort(2, rb_dynamic_description, strlen(rb_dynamic_description));
abort();
}
void
rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args)
{
report_bug_valist(RSTRING_PTR(file), line, fmt, NULL, args);
}
2023-03-07 08:34:31 +03:00
void
rb_assert_failure(const char *file, int line, const char *name, const char *expr)
{
rb_assert_failure_detail(file, line, name, expr, NULL);
}
void
rb_assert_failure_detail(const char *file, int line, const char *name, const char *expr,
const char *fmt, ...)
{
rb_pid_t pid = -1;
FILE *out = bug_report_file(file, line, &pid);
if (out) {
fputs("Assertion Failed: ", out);
if (name) fprintf(out, "%s:", name);
fputs(expr, out);
if (fmt && *fmt) {
va_list args;
va_start(args, fmt);
fputs(": ", out);
vfprintf(out, fmt, args);
va_end(args);
}
fprintf(out, "\n%s\n\n", rb_dynamic_description);
preface_dump(out);
rb_vm_bugreport(NULL, out);
bug_report_end(out, pid);
}
die();
}
static const char builtin_types[][10] = {
"", /* 0x00, */
"Object",
"Class",
"Module",
"Float",
"String",
"Regexp",
"Array",
"Hash",
"Struct",
"Integer",
"File",
"Data", /* internal use: wrapped C pointers */
"MatchData", /* data of $~ */
"Complex",
"Rational",
"", /* 0x10 */
"nil",
"true",
"false",
"Symbol", /* :symbol */
"Integer",
"undef", /* internal use: #undef; should not happen */
"", /* 0x17 */
"", /* 0x18 */
"", /* 0x19 */
2021-08-14 04:17:38 +03:00
"<Memo>", /* internal use: general memo */
"<Node>", /* internal use: syntax tree node */
"<iClass>", /* internal use: mixed-in module holder */
};
const char *
rb_builtin_type_name(int t)
{
const char *name;
if ((unsigned int)t >= numberof(builtin_types)) return 0;
name = builtin_types[t];
if (*name) return name;
return 0;
}
static VALUE
displaying_class_of(VALUE x)
{
switch (x) {
case Qfalse: return rb_fstring_cstr("false");
case Qnil: return rb_fstring_cstr("nil");
case Qtrue: return rb_fstring_cstr("true");
default: return rb_obj_class(x);
}
}
static const char *
builtin_class_name(VALUE x)
{
const char *etype;
if (NIL_P(x)) {
etype = "nil";
}
else if (FIXNUM_P(x)) {
etype = "Integer";
}
else if (SYMBOL_P(x)) {
etype = "Symbol";
}
else if (RB_TYPE_P(x, T_TRUE)) {
etype = "true";
}
else if (RB_TYPE_P(x, T_FALSE)) {
etype = "false";
}
else {
etype = NULL;
}
return etype;
}
const char *
rb_builtin_class_name(VALUE x)
{
const char *etype = builtin_class_name(x);
if (!etype) {
etype = rb_obj_classname(x);
}
return etype;
}
2021-08-14 04:16:37 +03:00
COLDFUNC NORETURN(static void unexpected_type(VALUE, int, int));
#define UNDEF_LEAKED "undef leaked to the Ruby space"
static void
unexpected_type(VALUE x, int xt, int t)
{
const char *tname = rb_builtin_type_name(t);
VALUE mesg, exc = rb_eFatal;
if (tname) {
mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)",
displaying_class_of(x), tname);
exc = rb_eTypeError;
}
else if (xt > T_MASK && xt <= 0x3f) {
mesg = rb_sprintf("unknown type 0x%x (0x%x given, probably comes"
" from extension library for ruby 1.8)", t, xt);
}
else {
mesg = rb_sprintf("unknown type 0x%x (0x%x given)", t, xt);
}
rb_exc_raise(rb_exc_new_str(exc, mesg));
}
void
rb_check_type(VALUE x, int t)
{
int xt;
2022-11-15 07:24:08 +03:00
if (RB_UNLIKELY(UNDEF_P(x))) {
rb_bug(UNDEF_LEAKED);
}
xt = TYPE(x);
if (xt != t || (xt == T_DATA && rbimpl_rtypeddata_p(x))) {
/*
* Typed data is not simple `T_DATA`, but in a sense an
* extension of `struct RVALUE`, which are incompatible with
* each other except when inherited.
*
* So it is not enough to just check `T_DATA`, it must be
* identified by its `type` using `Check_TypedStruct` instead.
*/
unexpected_type(x, xt, t);
}
}
void
rb_unexpected_type(VALUE x, int t)
{
2022-11-15 07:24:08 +03:00
if (RB_UNLIKELY(UNDEF_P(x))) {
rb_bug(UNDEF_LEAKED);
}
unexpected_type(x, TYPE(x), t);
}
int
rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent)
{
while (child) {
if (child == parent) return 1;
child = child->parent;
}
return 0;
}
int
rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
{
if (!RB_TYPE_P(obj, T_DATA) ||
!RTYPEDDATA_P(obj) || !rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
return 0;
}
return 1;
}
#undef rb_typeddata_is_instance_of
int
rb_typeddata_is_instance_of(VALUE obj, const rb_data_type_t *data_type)
{
return rb_typeddata_is_instance_of_inline(obj, data_type);
}
void *
rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
{
VALUE actual;
if (!RB_TYPE_P(obj, T_DATA)) {
actual = displaying_class_of(obj);
}
else if (!RTYPEDDATA_P(obj)) {
actual = displaying_class_of(obj);
}
else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
const char *name = RTYPEDDATA_TYPE(obj)->wrap_struct_name;
actual = rb_str_new_cstr(name); /* or rb_fstring_cstr? not sure... */
}
else {
return RTYPEDDATA_GET_DATA(obj);
}
const char *expected = data_type->wrap_struct_name;
rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)",
actual, expected);
UNREACHABLE_RETURN(NULL);
}
/* exception classes */
VALUE rb_eException;
VALUE rb_eSystemExit;
VALUE rb_eInterrupt;
VALUE rb_eSignal;
VALUE rb_eFatal;
VALUE rb_eStandardError;
VALUE rb_eRuntimeError;
VALUE rb_eFrozenError;
VALUE rb_eTypeError;
VALUE rb_eArgError;
VALUE rb_eIndexError;
VALUE rb_eKeyError;
VALUE rb_eRangeError;
VALUE rb_eNameError;
VALUE rb_eEncodingError;
VALUE rb_eEncCompatError;
VALUE rb_eNoMethodError;
VALUE rb_eSecurityError;
VALUE rb_eNotImpError;
VALUE rb_eNoMemError;
VALUE rb_cNameErrorMesg;
VALUE rb_eNoMatchingPatternError;
VALUE rb_eNoMatchingPatternKeyError;
VALUE rb_eScriptError;
VALUE rb_eSyntaxError;
VALUE rb_eLoadError;
VALUE rb_eSystemCallError;
VALUE rb_mErrno;
static VALUE rb_eNOERROR;
ID ruby_static_id_cause;
#define id_cause ruby_static_id_cause
static ID id_message, id_detailed_message, id_backtrace;
static ID id_key, id_matchee, id_args, id_Errno, id_errno, id_i_path;
static ID id_receiver, id_recv, id_iseq, id_local_variables;
static ID id_private_call_p, id_top, id_bottom;
#define id_bt idBt
#define id_bt_locations idBt_locations
#define id_mesg idMesg
2019-08-03 02:37:08 +03:00
#define id_name idName
#undef rb_exc_new_cstr
VALUE
rb_exc_new(VALUE etype, const char *ptr, long len)
{
VALUE mesg = rb_str_new(ptr, len);
return rb_class_new_instance(1, &mesg, etype);
}
VALUE
rb_exc_new_cstr(VALUE etype, const char *s)
{
return rb_exc_new(etype, s, strlen(s));
}
VALUE
rb_exc_new_str(VALUE etype, VALUE str)
{
rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
StringValue(str);
return rb_class_new_instance(1, &str, etype);
}
static VALUE
exc_init(VALUE exc, VALUE mesg)
{
rb_ivar_set(exc, id_mesg, mesg);
rb_ivar_set(exc, id_bt, Qnil);
return exc;
}
/*
2024-06-26 20:31:40 +03:00
* call-seq:
* Exception.new(message = nil) -> exception
*
* Returns a new exception object.
*
* The given +message+ should be
* a {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects];
* see method #message;
* if not given, the message is the class name of the new instance
* (which may be the name of a subclass):
*
* Examples:
*
* Exception.new # => #<Exception: Exception>
* LoadError.new # => #<LoadError: LoadError> # Subclass of Exception.
* Exception.new('Boom') # => #<Exception: Boom>
*
*/
static VALUE
exc_initialize(int argc, VALUE *argv, VALUE exc)
{
VALUE arg;
arg = (!rb_check_arity(argc, 0, 1) ? Qnil : argv[0]);
return exc_init(exc, arg);
}
/*
* Document-method: exception
*
* call-seq:
2024-06-26 20:31:40 +03:00
* exception(message = nil) -> self or new_exception
*
* Returns an exception object of the same class as +self+;
* useful for creating a similar exception, but with a different message.
*
* With +message+ +nil+, returns +self+:
*
* x0 = StandardError.new('Boom') # => #<StandardError: Boom>
* x1 = x0.exception # => #<StandardError: Boom>
* x0.__id__ == x1.__id__ # => true
*
2024-06-26 20:31:40 +03:00
* With {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects]
* +message+ (even the same as the original message),
* returns a new exception object whose class is the same as +self+,
* and whose message is the given +message+:
*
* x1 = x0.exception('Boom') # => #<StandardError: Boom>
* x0..equal?(x1) # => false
*
*/
static VALUE
exc_exception(int argc, VALUE *argv, VALUE self)
{
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
VALUE exc;
argc = rb_check_arity(argc, 0, 1);
if (argc == 0) return self;
if (argc == 1 && self == argv[0]) return self;
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
exc = rb_obj_clone(self);
rb_ivar_set(exc, id_mesg, argv[0]);
return exc;
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* to_s -> string
*
* Returns a string representation of +self+:
*
* x = RuntimeError.new('Boom')
* x.to_s # => "Boom"
* x = RuntimeError.new
* x.to_s # => "RuntimeError"
*
*/
static VALUE
exc_to_s(VALUE exc)
{
VALUE mesg = rb_attr_get(exc, idMesg);
if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
return rb_String(mesg);
}
/* FIXME: Include eval_error.c */
void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE opt, VALUE highlight, VALUE reverse);
VALUE
rb_get_message(VALUE exc)
{
VALUE e = rb_check_funcall(exc, id_message, 0, 0);
2022-11-15 07:24:08 +03:00
if (UNDEF_P(e)) return Qnil;
if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
return e;
}
VALUE
rb_get_detailed_message(VALUE exc, VALUE opt)
{
VALUE e;
if (NIL_P(opt)) {
e = rb_check_funcall(exc, id_detailed_message, 0, 0);
}
else {
e = rb_check_funcall_kw(exc, id_detailed_message, 1, &opt, 1);
}
2022-11-15 07:24:08 +03:00
if (UNDEF_P(e)) return Qnil;
if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
return e;
}
/*
2024-06-26 20:31:40 +03:00
* call-seq:
* Exception.to_tty? -> true or false
*
2024-06-26 20:31:40 +03:00
* Returns +true+ if exception messages will be sent to a terminal device.
*/
static VALUE
exc_s_to_tty_p(VALUE self)
{
2021-08-02 06:06:44 +03:00
return RBOOL(rb_stderr_tty_p());
}
static VALUE
check_highlight_keyword(VALUE opt, int auto_tty_detect)
{
VALUE highlight = Qnil;
if (!NIL_P(opt)) {
2022-05-21 16:58:45 +03:00
highlight = rb_hash_lookup(opt, sym_highlight);
switch (highlight) {
default:
rb_bool_expected(highlight, "highlight", TRUE);
UNREACHABLE;
case Qtrue: case Qfalse: case Qnil: break;
}
}
if (NIL_P(highlight)) {
2022-06-05 08:21:01 +03:00
highlight = RBOOL(auto_tty_detect && rb_stderr_tty_p());
}
return highlight;
}
static VALUE
check_order_keyword(VALUE opt)
{
VALUE order = Qnil;
if (!NIL_P(opt)) {
static VALUE kw_order;
if (!kw_order) kw_order = ID2SYM(rb_intern_const("order"));
2022-05-21 16:58:45 +03:00
order = rb_hash_lookup(opt, kw_order);
if (order != Qnil) {
ID id = rb_check_id(&order);
if (id == id_bottom) order = Qtrue;
else if (id == id_top) order = Qfalse;
else {
rb_raise(rb_eArgError, "expected :top or :bottom as "
"order: %+"PRIsVALUE, order);
}
}
}
if (NIL_P(order)) order = Qfalse;
return order;
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* full_message(highlight: true, order: :top) -> string
*
* Returns an enhanced message string:
*
* - Includes the exception class name.
* - If the value of keyword +highlight+ is true (not +nil+ or +false+),
* includes bolding ANSI codes (see below) to enhance the appearance of the message.
* - Includes the {backtrace}[rdoc-ref:exceptions.md@Backtraces]:
*
* - If the value of keyword +order+ is +:top+ (the default),
* lists the error message and the innermost backtrace entry first.
* - If the value of keyword +order+ is +:bottom+,
* lists the error message the the innermost entry last.
*
* Example:
*
2024-06-26 20:31:40 +03:00
* def baz
* begin
* 1 / 0
* rescue => x
* pp x.message
* pp x.full_message(highlight: false).split("\n")
* pp x.full_message.split("\n")
* end
* end
* def bar; baz; end
* def foo; bar; end
* foo
*
2024-06-26 20:31:40 +03:00
* Output:
*
2024-06-26 20:31:40 +03:00
* "divided by 0"
* ["t.rb:3:in `/': divided by 0 (ZeroDivisionError)",
* "\tfrom t.rb:3:in `baz'",
* "\tfrom t.rb:10:in `bar'",
* "\tfrom t.rb:11:in `foo'",
* "\tfrom t.rb:12:in `<main>'"]
* ["t.rb:3:in `/': \e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m",
* "\tfrom t.rb:3:in `baz'",
* "\tfrom t.rb:10:in `bar'",
* "\tfrom t.rb:11:in `foo'",
* "\tfrom t.rb:12:in `<main>'"]
*
2024-10-08 20:36:17 +03:00
* An overriding method should be careful with ANSI code enhancements;
2024-06-26 20:31:40 +03:00
* see {Messages}[rdoc-ref:exceptions.md@Messages].
*/
static VALUE
exc_full_message(int argc, VALUE *argv, VALUE exc)
{
VALUE opt, str, emesg, errat;
VALUE highlight, order;
rb_scan_args(argc, argv, "0:", &opt);
highlight = check_highlight_keyword(opt, 1);
order = check_order_keyword(opt);
{
if (NIL_P(opt)) opt = rb_hash_new();
2022-02-07 10:05:45 +03:00
rb_hash_aset(opt, sym_highlight, highlight);
}
str = rb_str_new2("");
errat = rb_get_backtrace(exc);
emesg = rb_get_detailed_message(exc, opt);
rb_error_write(exc, emesg, errat, str, opt, highlight, order);
return str;
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* message -> string
*
* Returns #to_s.
*
2024-06-26 20:31:40 +03:00
* See {Messages}[rdoc-ref:exceptions.md@Messages].
*/
* gc.c (Init_stack): stack region is far smaller than usual if pthread is used. * marshal.c (w_extended): singleton methods should not be checked when dumping via marshal_dump() or _dump(). [ruby-talk:85909] * file.c (getcwdofdrv): avoid using getcwd() directly, use my_getcwd() instead. * merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine <sunshine@sunshineco.com>. [ruby-core:01596] * marshal.c (w_object): LINK check earlier than anything else, i.e. do not dump TYPE_IVAR for already dumped objects. (ruby-bugs PR#1220) * eval.c (rb_eval): call "inherited" only when a new class is generated; not on reopening. * eval.c (eval): prepend error position in evaluating string to * configure.in: revived NextStep, OpenStep, and Rhapsody ports which had become unbuildable; enhanced --enable-fat-binary option so that it accepts a list of desired architectures (rather than assuming a fixed list), or defaults to a platform-appropriate list if user does not provide an explicit list; made the default list of architectures for MAB (fat binary) more comprehensive; now uses -fno-common even when building the interpreter (in addition to using it for extensions), thus allowing the interpreter to be embedded into a plugin module of an external project (in addition to allowing embedding directly into an application); added checks for <netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now ensures that -I/usr/local/include is employed when extensions' extconf.rb scripts invoke have_header() since extension checks on NextStep and OpenStep will fail without it if the desired resource resides in the /usr/local tree; fixed formatting of --help message. * Makefile.in: $(LIBRUBY_A) rule now deletes the archive before invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives (see configure's --enable-fat-binary option); added rule for new missing/getcwd.c. * defines.h: fixed endian handling during MAB build (see configure's --enable-fat-binary option) to ensure that all portions of the project see the correct WORDS_BIGENDIAN value (some extension modules were getting the wrong endian setting); added missing constants GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H define in NeXT section. * dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on NextStep since, on some installations, this value always resolves uselessly to zero. * dln.c: added error reporting to NextStep extension loader since the previous behavior of failing silently was not useful; now ensures that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice on Rhapsody since this header lacks multiple-include protection, which resulted in "redefinition" compilation errors. * main.c: also create hard reference to objc_msgSend() on NeXT platforms (in addition to Apple platforms). * lib/mkmf.rb: now exports XCFLAGS from configure script to extension makefiles so that extensions can be built MAB (see configure's --enable-fat-binary option); also utilize XCFLAGS in cc_command() (but not cpp_command() because MAB flags are incompatible with direct invocation of `cpp'). * ext/curses/extconf.rb: now additionally checks for presence of these curses functions which are not present on NextStep or Openstep: bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(), setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(), wscrl(), wsetscrreg() * ext/curses/curses.c: added appropriate #ifdef's for additional set of curses functions now checked by extconf.rb; fixed curses_bkgd() and window_bkgd() to correctly return boolean result rather than numeric result; fixed window_getbkgd() to correctly signal an error by returning nil rather than -1. * ext/etc/etc.c: setup_passwd() and setup_group() now check for null pointers before invoking rb_tainted_str_new2() upon fields extracted from `struct passwd' and `struct group' since null pointers in some fields are common on NextStep/OpenStep (especially so for the `pw_comment' field) and rb_tainted_str_new2() throws an exception when it receives a null pointer. * ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). * ext/socket/getaddrinfo.c: cast first argument of getservbyname(), gethostbyaddr(), and gethostbyname() from (const char*) to non-const (char*) for older platforms such as NextStep and OpenStep. * ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(); include <netinet/in_systm.h> if present for NextStep and OpenStep; cast first argument of gethostbyaddr() and getservbyname() from (const char*) to non-const (char*) for older platforms. * ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-22 07:00:03 +03:00
static VALUE
exc_message(VALUE exc)
* gc.c (Init_stack): stack region is far smaller than usual if pthread is used. * marshal.c (w_extended): singleton methods should not be checked when dumping via marshal_dump() or _dump(). [ruby-talk:85909] * file.c (getcwdofdrv): avoid using getcwd() directly, use my_getcwd() instead. * merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine <sunshine@sunshineco.com>. [ruby-core:01596] * marshal.c (w_object): LINK check earlier than anything else, i.e. do not dump TYPE_IVAR for already dumped objects. (ruby-bugs PR#1220) * eval.c (rb_eval): call "inherited" only when a new class is generated; not on reopening. * eval.c (eval): prepend error position in evaluating string to * configure.in: revived NextStep, OpenStep, and Rhapsody ports which had become unbuildable; enhanced --enable-fat-binary option so that it accepts a list of desired architectures (rather than assuming a fixed list), or defaults to a platform-appropriate list if user does not provide an explicit list; made the default list of architectures for MAB (fat binary) more comprehensive; now uses -fno-common even when building the interpreter (in addition to using it for extensions), thus allowing the interpreter to be embedded into a plugin module of an external project (in addition to allowing embedding directly into an application); added checks for <netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now ensures that -I/usr/local/include is employed when extensions' extconf.rb scripts invoke have_header() since extension checks on NextStep and OpenStep will fail without it if the desired resource resides in the /usr/local tree; fixed formatting of --help message. * Makefile.in: $(LIBRUBY_A) rule now deletes the archive before invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives (see configure's --enable-fat-binary option); added rule for new missing/getcwd.c. * defines.h: fixed endian handling during MAB build (see configure's --enable-fat-binary option) to ensure that all portions of the project see the correct WORDS_BIGENDIAN value (some extension modules were getting the wrong endian setting); added missing constants GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H define in NeXT section. * dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on NextStep since, on some installations, this value always resolves uselessly to zero. * dln.c: added error reporting to NextStep extension loader since the previous behavior of failing silently was not useful; now ensures that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice on Rhapsody since this header lacks multiple-include protection, which resulted in "redefinition" compilation errors. * main.c: also create hard reference to objc_msgSend() on NeXT platforms (in addition to Apple platforms). * lib/mkmf.rb: now exports XCFLAGS from configure script to extension makefiles so that extensions can be built MAB (see configure's --enable-fat-binary option); also utilize XCFLAGS in cc_command() (but not cpp_command() because MAB flags are incompatible with direct invocation of `cpp'). * ext/curses/extconf.rb: now additionally checks for presence of these curses functions which are not present on NextStep or Openstep: bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(), setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(), wscrl(), wsetscrreg() * ext/curses/curses.c: added appropriate #ifdef's for additional set of curses functions now checked by extconf.rb; fixed curses_bkgd() and window_bkgd() to correctly return boolean result rather than numeric result; fixed window_getbkgd() to correctly signal an error by returning nil rather than -1. * ext/etc/etc.c: setup_passwd() and setup_group() now check for null pointers before invoking rb_tainted_str_new2() upon fields extracted from `struct passwd' and `struct group' since null pointers in some fields are common on NextStep/OpenStep (especially so for the `pw_comment' field) and rb_tainted_str_new2() throws an exception when it receives a null pointer. * ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). * ext/socket/getaddrinfo.c: cast first argument of getservbyname(), gethostbyaddr(), and gethostbyname() from (const char*) to non-const (char*) for older platforms such as NextStep and OpenStep. * ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(); include <netinet/in_systm.h> if present for NextStep and OpenStep; cast first argument of gethostbyaddr() and getservbyname() from (const char*) to non-const (char*) for older platforms. * ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-22 07:00:03 +03:00
{
return rb_funcallv(exc, idTo_s, 0, 0);
* gc.c (Init_stack): stack region is far smaller than usual if pthread is used. * marshal.c (w_extended): singleton methods should not be checked when dumping via marshal_dump() or _dump(). [ruby-talk:85909] * file.c (getcwdofdrv): avoid using getcwd() directly, use my_getcwd() instead. * merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine <sunshine@sunshineco.com>. [ruby-core:01596] * marshal.c (w_object): LINK check earlier than anything else, i.e. do not dump TYPE_IVAR for already dumped objects. (ruby-bugs PR#1220) * eval.c (rb_eval): call "inherited" only when a new class is generated; not on reopening. * eval.c (eval): prepend error position in evaluating string to * configure.in: revived NextStep, OpenStep, and Rhapsody ports which had become unbuildable; enhanced --enable-fat-binary option so that it accepts a list of desired architectures (rather than assuming a fixed list), or defaults to a platform-appropriate list if user does not provide an explicit list; made the default list of architectures for MAB (fat binary) more comprehensive; now uses -fno-common even when building the interpreter (in addition to using it for extensions), thus allowing the interpreter to be embedded into a plugin module of an external project (in addition to allowing embedding directly into an application); added checks for <netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now ensures that -I/usr/local/include is employed when extensions' extconf.rb scripts invoke have_header() since extension checks on NextStep and OpenStep will fail without it if the desired resource resides in the /usr/local tree; fixed formatting of --help message. * Makefile.in: $(LIBRUBY_A) rule now deletes the archive before invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives (see configure's --enable-fat-binary option); added rule for new missing/getcwd.c. * defines.h: fixed endian handling during MAB build (see configure's --enable-fat-binary option) to ensure that all portions of the project see the correct WORDS_BIGENDIAN value (some extension modules were getting the wrong endian setting); added missing constants GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H define in NeXT section. * dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on NextStep since, on some installations, this value always resolves uselessly to zero. * dln.c: added error reporting to NextStep extension loader since the previous behavior of failing silently was not useful; now ensures that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice on Rhapsody since this header lacks multiple-include protection, which resulted in "redefinition" compilation errors. * main.c: also create hard reference to objc_msgSend() on NeXT platforms (in addition to Apple platforms). * lib/mkmf.rb: now exports XCFLAGS from configure script to extension makefiles so that extensions can be built MAB (see configure's --enable-fat-binary option); also utilize XCFLAGS in cc_command() (but not cpp_command() because MAB flags are incompatible with direct invocation of `cpp'). * ext/curses/extconf.rb: now additionally checks for presence of these curses functions which are not present on NextStep or Openstep: bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(), setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(), wscrl(), wsetscrreg() * ext/curses/curses.c: added appropriate #ifdef's for additional set of curses functions now checked by extconf.rb; fixed curses_bkgd() and window_bkgd() to correctly return boolean result rather than numeric result; fixed window_getbkgd() to correctly signal an error by returning nil rather than -1. * ext/etc/etc.c: setup_passwd() and setup_group() now check for null pointers before invoking rb_tainted_str_new2() upon fields extracted from `struct passwd' and `struct group' since null pointers in some fields are common on NextStep/OpenStep (especially so for the `pw_comment' field) and rb_tainted_str_new2() throws an exception when it receives a null pointer. * ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). * ext/socket/getaddrinfo.c: cast first argument of getservbyname(), gethostbyaddr(), and gethostbyname() from (const char*) to non-const (char*) for older platforms such as NextStep and OpenStep. * ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(); include <netinet/in_systm.h> if present for NextStep and OpenStep; cast first argument of gethostbyaddr() and getservbyname() from (const char*) to non-const (char*) for older platforms. * ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-22 07:00:03 +03:00
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* detailed_message(highlight: false, **kwargs) -> string
*
* Returns the message string with enhancements:
*
* - Includes the exception class name in the first line.
* - If the value of keyword +highlight+ is +true+,
* includes bolding and underlining ANSI codes (see below)
* to enhance the appearance of the message.
*
2024-06-26 20:31:40 +03:00
* Examples:
*
2024-06-26 20:31:40 +03:00
* begin
* 1 / 0
* rescue => x
* p x.message
* p x.detailed_message # Class name added.
* p x.detailed_message(highlight: true) # Class name, bolding, and underlining added.
* end
*
2024-06-26 20:31:40 +03:00
* Output:
*
2024-06-26 20:31:40 +03:00
* "divided by 0"
* "divided by 0 (ZeroDivisionError)"
* "\e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m"
*
2024-06-26 20:31:40 +03:00
* This method is overridden by some gems in the Ruby standard library to add information:
*
2024-06-26 20:31:40 +03:00
* - DidYouMean::Correctable#detailed_message.
* - ErrorHighlight::CoreExt#detailed_message.
* - SyntaxSuggest#detailed_message.
*
2024-06-26 20:31:40 +03:00
* An overriding method must be tolerant of passed keyword arguments,
* which may include (but may not be limited to):
*
* - +:highlight+.
* - +:did_you_mean+.
* - +:error_highlight+.
* - +:syntax_suggest+.
*
2024-10-08 20:36:17 +03:00
* An overriding method should also be careful with ANSI code enhancements;
2024-06-26 20:31:40 +03:00
* see {Messages}[rdoc-ref:exceptions.md@Messages].
*/
static VALUE
exc_detailed_message(int argc, VALUE *argv, VALUE exc)
{
VALUE opt;
rb_scan_args(argc, argv, "0:", &opt);
VALUE highlight = check_highlight_keyword(opt, 0);
extern VALUE rb_decorate_message(const VALUE eclass, VALUE emesg, int highlight);
return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), RTEST(highlight));
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* inspect -> string
*
* Returns a string representation of +self+:
*
* x = RuntimeError.new('Boom')
* x.inspect # => "#<RuntimeError: Boom>"
* x = RuntimeError.new
* x.inspect # => "#<RuntimeError: RuntimeError>"
*
*/
static VALUE
exc_inspect(VALUE exc)
{
VALUE str, klass;
klass = CLASS_OF(exc);
exc = rb_obj_as_string(exc);
if (RSTRING_LEN(exc) == 0) {
2019-06-13 12:07:19 +03:00
return rb_class_name(klass);
}
str = rb_str_buf_new2("#<");
klass = rb_class_name(klass);
rb_str_buf_append(str, klass);
if (RTEST(rb_str_include(exc, rb_str_new2("\n")))) {
rb_str_catf(str, ":%+"PRIsVALUE, exc);
}
else {
rb_str_buf_cat(str, ": ", 2);
rb_str_buf_append(str, exc);
}
rb_str_buf_cat(str, ">", 1);
return str;
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* backtrace -> array or nil
*
2024-06-26 20:31:40 +03:00
* Returns a backtrace value for +self+;
* the returned value depends on the form of the stored backtrace value:
*
2024-06-26 20:31:40 +03:00
* - \Array of Thread::Backtrace::Location objects:
* returns the array of strings given by
* <tt>Exception#backtrace_locations.map {|loc| loc.to_s }</tt>.
* This is the normal case, where the backtrace value was stored by Kernel#raise.
* - \Array of strings: returns that array.
* This is the unusual case, where the backtrace value was explicitly
* stored as an array of strings.
* - +nil+: returns +nil+.
*
2024-06-26 20:31:40 +03:00
* Example:
*
2024-06-26 20:31:40 +03:00
* begin
* 1 / 0
* rescue => x
* x.backtrace.take(2)
* end
* # => ["(irb):132:in `/'", "(irb):132:in `<top (required)>'"]
*
2024-06-26 20:31:40 +03:00
* see {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
*/
static VALUE
exc_backtrace(VALUE exc)
{
VALUE obj;
obj = rb_attr_get(exc, id_bt);
if (rb_backtrace_p(obj)) {
obj = rb_backtrace_to_str_ary(obj);
/* rb_ivar_set(exc, id_bt, obj); */
}
return obj;
}
static VALUE rb_check_backtrace(VALUE);
VALUE
rb_get_backtrace(VALUE exc)
{
ID mid = id_backtrace;
VALUE info;
if (rb_method_basic_definition_p(CLASS_OF(exc), id_backtrace)) {
VALUE klass = rb_eException;
rb_execution_context_t *ec = GET_EC();
if (NIL_P(exc))
return Qnil;
EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, exc, mid, mid, klass, Qundef);
info = exc_backtrace(exc);
EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, exc, mid, mid, klass, info);
}
else {
info = rb_funcallv(exc, mid, 0, 0);
}
if (NIL_P(info)) return Qnil;
return rb_check_backtrace(info);
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* backtrace_locations -> array or nil
*
* Returns a backtrace value for +self+;
* the returned value depends on the form of the stored backtrace value:
*
2024-06-26 20:31:40 +03:00
* - \Array of Thread::Backtrace::Location objects: returns that array.
* - \Array of strings or +nil+: returns +nil+.
*
* Example:
*
2024-06-26 20:31:40 +03:00
* begin
* 1 / 0
* rescue => x
* x.backtrace_locations.take(2)
* end
* # => ["(irb):150:in `/'", "(irb):150:in `<top (required)>'"]
*
* See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
*/
static VALUE
exc_backtrace_locations(VALUE exc)
{
VALUE obj;
obj = rb_attr_get(exc, id_bt_locations);
if (!NIL_P(obj)) {
obj = rb_backtrace_to_location_ary(obj);
}
return obj;
}
static VALUE
rb_check_backtrace(VALUE bt)
{
long i;
static const char err[] = "backtrace must be an Array of String or an Array of Thread::Backtrace::Location";
if (!NIL_P(bt)) {
if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
if (rb_backtrace_p(bt)) return bt;
if (!RB_TYPE_P(bt, T_ARRAY)) {
rb_raise(rb_eTypeError, err);
}
for (i=0;i<RARRAY_LEN(bt);i++) {
VALUE e = RARRAY_AREF(bt, i);
if (!RB_TYPE_P(e, T_STRING)) {
rb_raise(rb_eTypeError, err);
}
}
}
return bt;
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* set_backtrace(value) -> value
*
* Sets the backtrace value for +self+; returns the given +value:
*
* x = RuntimeError.new('Boom')
* x.set_backtrace(%w[foo bar baz]) # => ["foo", "bar", "baz"]
* x.backtrace # => ["foo", "bar", "baz"]
*
2024-06-26 20:31:40 +03:00
* The given +value+ must be an array of strings, a single string, or +nil+.
*
2024-06-26 20:31:40 +03:00
* Does not affect the value returned by #backtrace_locations.
*
* See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
*/
static VALUE
exc_set_backtrace(VALUE exc, VALUE bt)
{
VALUE btobj = rb_location_ary_to_backtrace(bt);
if (RTEST(btobj)) {
rb_ivar_set(exc, id_bt, btobj);
rb_ivar_set(exc, id_bt_locations, btobj);
return bt;
}
else {
return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
}
}
2023-03-07 08:34:31 +03:00
VALUE
rb_exc_set_backtrace(VALUE exc, VALUE bt)
{
return exc_set_backtrace(exc, bt);
}
/*
2024-06-26 20:31:40 +03:00
* call-seq:
* cause -> exception or nil
*
* Returns the previous value of global variable <tt>$!</tt>,
* which may be +nil+
* (see {Global Variables}[rdoc-ref:exceptions.md@Global+Variables]):
*
* begin
* raise('Boom 0')
* rescue => x0
* puts "Exception: #{x0}; $!: #{$!}; cause: #{x0.cause.inspect}."
* begin
* raise('Boom 1')
* rescue => x1
* puts "Exception: #{x1}; $!: #{$!}; cause: #{x1.cause}."
* begin
* raise('Boom 2')
* rescue => x2
* puts "Exception: #{x2}; $!: #{$!}; cause: #{x2.cause}."
* end
* end
* end
*
* Output:
*
* Exception: Boom 0; $!: Boom 0; cause: nil.
* Exception: Boom 1; $!: Boom 1; cause: Boom 0.
* Exception: Boom 2; $!: Boom 2; cause: Boom 1.
*
*/
static VALUE
exc_cause(VALUE exc)
{
return rb_attr_get(exc, id_cause);
}
static VALUE
try_convert_to_exception(VALUE obj)
{
return rb_check_funcall(obj, idException, 0, 0);
}
/*
* call-seq:
2024-06-26 20:31:40 +03:00
* self == object -> true or false
*
* Returns whether +object+ is the same class as +self+
* and its #message and #backtrace are equal to those of +self+.
*
*/
static VALUE
exc_equal(VALUE exc, VALUE obj)
{
VALUE mesg, backtrace;
if (exc == obj) return Qtrue;
if (rb_obj_class(exc) != rb_obj_class(obj)) {
int state;
2022-07-21 19:23:58 +03:00
obj = rb_protect(try_convert_to_exception, obj, &state);
2022-11-15 07:24:08 +03:00
if (state || UNDEF_P(obj)) {
rb_set_errinfo(Qnil);
return Qfalse;
}
if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
mesg = rb_check_funcall(obj, id_message, 0, 0);
2022-11-15 07:24:08 +03:00
if (UNDEF_P(mesg)) return Qfalse;
backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
2022-11-15 07:24:08 +03:00
if (UNDEF_P(backtrace)) return Qfalse;
}
else {
mesg = rb_attr_get(obj, id_mesg);
backtrace = exc_backtrace(obj);
}
if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
return Qfalse;
2021-09-15 02:11:05 +03:00
return rb_equal(exc_backtrace(exc), backtrace);
}
/*
* call-seq:
* SystemExit.new -> system_exit
* SystemExit.new(status) -> system_exit
* SystemExit.new(status, msg) -> system_exit
* SystemExit.new(msg) -> system_exit
*
* Create a new +SystemExit+ exception with the given status and message.
* Status is true, false, or an integer.
* If status is not given, true is used.
*/
static VALUE
exit_initialize(int argc, VALUE *argv, VALUE exc)
{
VALUE status;
if (argc > 0) {
status = *argv;
2022-07-21 19:23:58 +03:00
switch (status) {
case Qtrue:
status = INT2FIX(EXIT_SUCCESS);
++argv;
--argc;
break;
case Qfalse:
status = INT2FIX(EXIT_FAILURE);
++argv;
--argc;
break;
default:
status = rb_check_to_int(status);
if (NIL_P(status)) {
status = INT2FIX(EXIT_SUCCESS);
}
else {
#if EXIT_SUCCESS != 0
if (status == INT2FIX(0))
status = INT2FIX(EXIT_SUCCESS);
#endif
++argv;
--argc;
}
break;
}
}
else {
status = INT2FIX(EXIT_SUCCESS);
}
rb_call_super(argc, argv);
rb_ivar_set(exc, id_status, status);
return exc;
}
/*
* call-seq:
* system_exit.status -> integer
*
* Return the status value associated with this system exit.
*/
static VALUE
exit_status(VALUE exc)
{
return rb_attr_get(exc, id_status);
}
/*
* call-seq:
* system_exit.success? -> true or false
*
* Returns +true+ if exiting successful, +false+ if not.
*/
static VALUE
exit_success_p(VALUE exc)
{
VALUE status_val = rb_attr_get(exc, id_status);
int status;
if (NIL_P(status_val))
return Qtrue;
status = NUM2INT(status_val);
2021-09-15 02:11:05 +03:00
return RBOOL(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
}
static VALUE
err_init_recv(VALUE exc, VALUE recv)
{
2022-11-15 07:24:08 +03:00
if (!UNDEF_P(recv)) rb_ivar_set(exc, id_recv, recv);
return exc;
}
/*
* call-seq:
* FrozenError.new(msg=nil, receiver: nil) -> frozen_error
*
* Construct a new FrozenError exception. If given the <i>receiver</i>
* parameter may subsequently be examined using the FrozenError#receiver
* method.
*
* a = [].freeze
* raise FrozenError.new("can't modify frozen array", receiver: a)
*/
static VALUE
frozen_err_initialize(int argc, VALUE *argv, VALUE self)
{
ID keywords[1];
VALUE values[numberof(keywords)], options;
argc = rb_scan_args(argc, argv, "*:", NULL, &options);
keywords[0] = id_receiver;
rb_get_kwargs(options, keywords, 0, numberof(values), values);
rb_call_super(argc, argv);
err_init_recv(self, values[0]);
return self;
}
/*
* Document-method: FrozenError#receiver
* call-seq:
* frozen_error.receiver -> object
*
* Return the receiver associated with this FrozenError exception.
*/
#define frozen_err_receiver name_err_receiver
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
void
rb_name_error(ID id, const char *fmt, ...)
{
VALUE exc, argv[2];
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
va_list args;
va_start(args, fmt);
argv[0] = rb_vsprintf(fmt, args);
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
va_end(args);
argv[1] = ID2SYM(id);
exc = rb_class_new_instance(2, argv, rb_eNameError);
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
rb_exc_raise(exc);
}
void
rb_name_error_str(VALUE str, const char *fmt, ...)
{
VALUE exc, argv[2];
va_list args;
va_start(args, fmt);
argv[0] = rb_vsprintf(fmt, args);
va_end(args);
argv[1] = str;
exc = rb_class_new_instance(2, argv, rb_eNameError);
rb_exc_raise(exc);
}
static VALUE
name_err_init_attr(VALUE exc, VALUE recv, VALUE method)
{
const rb_execution_context_t *ec = GET_EC();
rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
rb_ivar_set(exc, id_name, method);
err_init_recv(exc, recv);
Fix crash in NoMethodError for dummy frames [Bug #19793] Dummy frames are created at the top level when requiring another file. While requiring a file, it will try to convert using encodings. Some of these encodings will not respond to to_str. If method_missing is redefined on Object, then it will call method_missing and attempt raise an error. However, the iseq is invalid as it's a dummy frame so it will write an invalid iseq to the created NoMethodError. The following script crashes: ``` GC.stress = true class Object public :method_missing end File.write("/tmp/empty.rb", "") require "/tmp/empty.rb" ``` With the following backtrace: ``` frame #0: 0x00000001000fa8b8 miniruby`RVALUE_MARKED(obj=4308637824) at gc.c:1638:12 frame #1: 0x00000001000fb440 miniruby`RVALUE_BLACK_P(obj=4308637824) at gc.c:1763:12 frame #2: 0x00000001000facdc miniruby`gc_writebarrier_incremental(a=4308637824, b=4308332208, objspace=0x000000010180b000) at gc.c:8822:9 frame #3: 0x00000001000faad8 miniruby`rb_gc_writebarrier(a=4308637824, b=4308332208) at gc.c:8864:17 frame #4: 0x000000010016aff0 miniruby`rb_obj_written(a=4308637824, oldv=36, b=4308332208, filename="../iseq.c", line=1279) at gc.h:804:9 frame #5: 0x0000000100162a60 miniruby`rb_obj_write(a=4308637824, slot=0x0000000100d09888, b=4308332208, filename="../iseq.c", line=1279) at gc.h:837:5 frame #6: 0x0000000100165b0c miniruby`iseqw_new(iseq=0x0000000100d09880) at iseq.c:1279:9 frame #7: 0x0000000100165a64 miniruby`rb_iseqw_new(iseq=0x0000000100d09880) at iseq.c:1289:12 frame #8: 0x00000001000d8324 miniruby`name_err_init_attr(exc=4309777920, recv=4304780496, method=827660) at error.c:1830:35 frame #9: 0x00000001000d1b80 miniruby`name_err_init(exc=4309777920, mesg=4308332496, recv=4304780496, method=827660) at error.c:1869:12 frame #10: 0x00000001000d1bd4 miniruby`rb_nomethod_err_new(mesg=4308332496, recv=4304780496, method=827660, args=4308332448, priv=0) at error.c:1957:5 frame #11: 0x000000010039049c miniruby`rb_make_no_method_exception(exc=4304914512, format=4308332496, obj=4304780496, argc=1, argv=0x000000016fdfab00, priv=0) at vm_eval.c:959:16 frame #12: 0x00000001003b3274 miniruby`raise_method_missing(ec=0x0000000100b06f40, argc=1, argv=0x000000016fdfab00, obj=4304780496, last_call_status=MISSING_NOENTRY) at vm_eval.c:999:15 frame #13: 0x00000001003945d4 miniruby`rb_method_missing(argc=1, argv=0x000000016fdfab00, obj=4304780496) at vm_eval.c:944:5 ... frame #23: 0x000000010038f5e4 miniruby`rb_vm_call_kw(ec=0x0000000100b06f40, recv=4304780496, id=2865, argc=1, argv=0x000000016fdfab00, me=0x0000000100cbfcf0, kw_splat=0) at vm_eval.c:326:12 frame #24: 0x00000001003c18e4 miniruby`call_method_entry(ec=0x0000000100b06f40, defined_class=4304927952, obj=4304780496, id=2865, cme=0x0000000100cbfcf0, argc=1, argv=0x000000016fdfab00, kw_splat=0) at vm_method.c:2720:20 frame #25: 0x00000001003c440c miniruby`check_funcall_exec(v=6171896792) at vm_eval.c:589:12 frame #26: 0x00000001000dec00 miniruby`rb_vrescue2(b_proc=(miniruby`check_funcall_exec at vm_eval.c:587), data1=6171896792, r_proc=(miniruby`check_funcall_failed at vm_eval.c:596), data2=6171896792, args="Pȗ") at eval.c:919:18 frame #27: 0x00000001000deab0 miniruby`rb_rescue2(b_proc=(miniruby`check_funcall_exec at vm_eval.c:587), data1=6171896792, r_proc=(miniruby`check_funcall_failed at vm_eval.c:596), data2=6171896792) at eval.c:900:17 frame #28: 0x000000010039008c miniruby`check_funcall_missing(ec=0x0000000100b06f40, klass=4304923536, recv=4304780496, mid=3233, argc=0, argv=0x0000000000000000, respond=-1, def=36, kw_splat=0) at vm_eval.c:666:15 frame #29: 0x000000010038fa60 miniruby`rb_check_funcall_default_kw(recv=4304780496, mid=3233, argc=0, argv=0x0000000000000000, def=36, kw_splat=0) at vm_eval.c:703:21 frame #30: 0x000000010038fb04 miniruby`rb_check_funcall(recv=4304780496, mid=3233, argc=0, argv=0x0000000000000000) at vm_eval.c:685:12 frame #31: 0x00000001001c469c miniruby`convert_type_with_id(val=4304780496, tname="String", method=3233, raise=0, index=-1) at object.c:3061:15 frame #32: 0x00000001001c4a4c miniruby`rb_check_convert_type_with_id(val=4304780496, type=5, tname="String", method=3233) at object.c:3153:9 frame #33: 0x00000001002d59f8 miniruby`rb_check_string_type(str=4304780496) at string.c:2571:11 frame #34: 0x000000010014b7b0 miniruby`io_encoding_set(fptr=0x0000000100d09ca0, v1=4304780496, v2=4, opt=4) at io.c:11655:19 frame #35: 0x0000000100139a58 miniruby`rb_io_set_encoding(argc=1, argv=0x000000016fdfb450, io=4308334032) at io.c:13497:5 frame #36: 0x00000001003c0004 miniruby`ractor_safe_call_cfunc_m1(recv=4308334032, argc=1, argv=0x000000016fdfb450, func=(miniruby`rb_io_set_encoding at io.c:13487)) at vm_insnhelper.c:3271:12 ... frame #43: 0x0000000100390b08 miniruby`rb_funcall(recv=4308334032, mid=16593, n=1) at vm_eval.c:1137:12 frame #44: 0x00000001002a43d8 miniruby`load_file_internal(argp_v=6171899936) at ruby.c:2500:5 ... ```
2023-08-01 23:53:45 +03:00
if (cfp && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
rb_ivar_set(exc, id_iseq, rb_iseqw_new(cfp->iseq));
}
return exc;
}
/*
* call-seq:
* NameError.new(msg=nil, name=nil, receiver: nil) -> name_error
*
* Construct a new NameError exception. If given the <i>name</i>
* parameter may subsequently be examined using the NameError#name
* method. <i>receiver</i> parameter allows to pass object in
* context of which the error happened. Example:
*
* [1, 2, 3].method(:rject) # NameError with name "rject" and receiver: Array
* [1, 2, 3].singleton_method(:rject) # NameError with name "rject" and receiver: [1, 2, 3]
*/
static VALUE
name_err_initialize(int argc, VALUE *argv, VALUE self)
{
ID keywords[1];
VALUE values[numberof(keywords)], name, options;
argc = rb_scan_args(argc, argv, "*:", NULL, &options);
keywords[0] = id_receiver;
rb_get_kwargs(options, keywords, 0, numberof(values), values);
name = (argc > 1) ? argv[--argc] : Qnil;
rb_call_super(argc, argv);
name_err_init_attr(self, values[0], name);
return self;
}
static VALUE rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method);
static VALUE
name_err_init(VALUE exc, VALUE mesg, VALUE recv, VALUE method)
{
exc_init(exc, rb_name_err_mesg_new(mesg, recv, method));
return name_err_init_attr(exc, recv, method);
}
VALUE
rb_name_err_new(VALUE mesg, VALUE recv, VALUE method)
{
VALUE exc = rb_obj_alloc(rb_eNameError);
return name_err_init(exc, mesg, recv, method);
}
/*
* call-seq:
* name_error.name -> string or nil
*
* Return the name associated with this NameError exception.
*/
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
static VALUE
name_err_name(VALUE self)
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
{
return rb_attr_get(self, id_name);
}
/*
* call-seq:
* name_error.local_variables -> array
*
* Return a list of the local variable names defined where this
* NameError exception was raised.
*
* Internal use only.
*/
static VALUE
name_err_local_variables(VALUE self)
{
VALUE vars = rb_attr_get(self, id_local_variables);
if (NIL_P(vars)) {
VALUE iseqw = rb_attr_get(self, id_iseq);
if (!NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
if (NIL_P(vars)) vars = rb_ary_new();
rb_ivar_set(self, id_local_variables, vars);
}
return vars;
}
static VALUE
nometh_err_init_attr(VALUE exc, VALUE args, int priv)
{
rb_ivar_set(exc, id_args, args);
2021-08-02 06:06:44 +03:00
rb_ivar_set(exc, id_private_call_p, RBOOL(priv));
return exc;
}
/*
* call-seq:
* NoMethodError.new(msg=nil, name=nil, args=nil, private=false, receiver: nil) -> no_method_error
*
* Construct a NoMethodError exception for a method of the given name
* called with the given arguments. The name may be accessed using
* the <code>#name</code> method on the resulting object, and the
* arguments using the <code>#args</code> method.
*
* If <i>private</i> argument were passed, it designates method was
* attempted to call in private context, and can be accessed with
* <code>#private_call?</code> method.
*
* <i>receiver</i> argument stores an object whose method was called.
*/
static VALUE
nometh_err_initialize(int argc, VALUE *argv, VALUE self)
{
int priv;
VALUE args, options;
argc = rb_scan_args(argc, argv, "*:", NULL, &options);
priv = (argc > 3) && (--argc, RTEST(argv[argc]));
args = (argc > 2) ? argv[--argc] : Qnil;
if (!NIL_P(options)) argv[argc++] = options;
Make rb_scan_args handle keywords more similar to Ruby methods (#2460) Cfuncs that use rb_scan_args with the : entry suffer similar keyword argument separation issues that Ruby methods suffer if the cfuncs accept optional or variable arguments. This makes the following changes to : handling. * Treats as **kw, prompting keyword argument separation warnings if called with a positional hash. * Do not look for an option hash if empty keywords are provided. For backwards compatibility, treat an empty keyword splat as a empty mandatory positional hash argument, but emit a a warning, as this behavior will be removed in Ruby 3. The argument number check needs to be moved lower so it can correctly handle an empty positional argument being added. * If the last argument is nil and it is necessary to treat it as an option hash in order to make sure all arguments are processed, continue to treat the last argument as the option hash. Emit a warning in this case, as this behavior will be removed in Ruby 3. * If splitting the keyword hash into two hashes, issue a warning, as we will not be splitting hashes in Ruby 3. * If the keyword argument is required to fill a mandatory positional argument, continue to do so, but emit a warning as this behavior will be going away in Ruby 3. * If keyword arguments are provided and the last argument is not a hash, that indicates something wrong. This can happen if a cfunc is calling rb_scan_args multiple times, and providing arguments that were not passed to it from Ruby. Callers need to switch to the new rb_scan_args_kw function, which allows passing of whether keywords were provided. This commit fixes all warnings caused by the changes above. It switches some function calls to *_kw versions with appropriate kw_splat flags. If delegating arguments, RB_PASS_CALLED_KEYWORDS is used. If creating new arguments, RB_PASS_KEYWORDS is used if the last argument is a hash to be treated as keywords. In open_key_args in io.c, use rb_scan_args_kw. In this case, the arguments provided come from another C function, not Ruby. The last argument may or may not be a hash, so we can't set keyword argument mode. However, if it is a hash, we don't want to warn when treating it as keywords. In Ruby files, make sure to appropriately use keyword splats or literal keywords when calling Cfuncs that now issue keyword argument separation warnings through rb_scan_args. Also, make sure not to pass nil in place of an option hash. Work around Kernel#warn warnings due to problems in the Rubygems override of the method. There is an open pull request to fix these issues in Rubygems, but part of the Rubygems tests for their override fail on ruby-head due to rb_scan_args not recognizing empty keyword splats, which this commit fixes. Implementation wise, adding rb_scan_args_kw is kind of a pain, because rb_scan_args takes a variable number of arguments. In order to not duplicate all the code, the function internals need to be split into two functions taking a va_list, and to avoid passing in a ton of arguments, a single struct argument is used to handle the variables previously local to the function.
2019-09-25 21:18:49 +03:00
rb_call_super_kw(argc, argv, RB_PASS_CALLED_KEYWORDS);
return nometh_err_init_attr(self, args, priv);
}
VALUE
rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv)
{
VALUE exc = rb_obj_alloc(rb_eNoMethodError);
name_err_init(exc, mesg, recv, method);
return nometh_err_init_attr(exc, args, priv);
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
}
typedef struct name_error_message_struct {
VALUE mesg;
VALUE recv;
VALUE name;
} name_error_message_t;
static void
name_err_mesg_mark(void *p)
{
name_error_message_t *ptr = (name_error_message_t *)p;
rb_gc_mark_movable(ptr->mesg);
rb_gc_mark_movable(ptr->recv);
rb_gc_mark_movable(ptr->name);
}
static void
name_err_mesg_update(void *p)
{
name_error_message_t *ptr = (name_error_message_t *)p;
ptr->mesg = rb_gc_location(ptr->mesg);
ptr->recv = rb_gc_location(ptr->recv);
ptr->name = rb_gc_location(ptr->name);
}
static const rb_data_type_t name_err_mesg_data_type = {
"name_err_mesg",
{
name_err_mesg_mark,
RUBY_TYPED_DEFAULT_FREE,
NULL, // No external memory to report,
name_err_mesg_update,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
/* :nodoc: */
static VALUE
rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE name)
{
name_error_message_t *message;
VALUE result = TypedData_Make_Struct(klass, name_error_message_t, &name_err_mesg_data_type, message);
RB_OBJ_WRITE(result, &message->mesg, mesg);
RB_OBJ_WRITE(result, &message->recv, recv);
RB_OBJ_WRITE(result, &message->name, name);
return result;
}
/* :nodoc: */
static VALUE
rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
{
return rb_name_err_mesg_init(rb_cNameErrorMesg, mesg, recv, method);
}
/* :nodoc: */
static VALUE
name_err_mesg_alloc(VALUE klass)
{
return rb_name_err_mesg_init(klass, Qnil, Qnil, Qnil);
}
/* :nodoc: */
static VALUE
name_err_mesg_init_copy(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2) return obj1;
rb_obj_init_copy(obj1, obj2);
name_error_message_t *ptr1, *ptr2;
TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1);
TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2);
RB_OBJ_WRITE(obj1, &ptr1->mesg, ptr2->mesg);
RB_OBJ_WRITE(obj1, &ptr1->recv, ptr2->recv);
RB_OBJ_WRITE(obj1, &ptr1->name, ptr2->name);
return obj1;
}
/* :nodoc: */
static VALUE
name_err_mesg_equal(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2) return Qtrue;
if (rb_obj_class(obj2) != rb_cNameErrorMesg)
return Qfalse;
name_error_message_t *ptr1, *ptr2;
TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1);
TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2);
if (!rb_equal(ptr1->mesg, ptr2->mesg)) return Qfalse;
if (!rb_equal(ptr1->recv, ptr2->recv)) return Qfalse;
if (!rb_equal(ptr1->name, ptr2->name)) return Qfalse;
return Qtrue;
}
/* :nodoc: */
static VALUE
name_err_mesg_receiver_name(VALUE obj)
{
if (RB_SPECIAL_CONST_P(obj)) return Qundef;
if (RB_BUILTIN_TYPE(obj) == T_MODULE || RB_BUILTIN_TYPE(obj) == T_CLASS) {
return rb_check_funcall(obj, rb_intern("name"), 0, 0);
}
return Qundef;
}
/* :nodoc: */
static VALUE
name_err_mesg_to_str(VALUE obj)
{
name_error_message_t *ptr;
TypedData_Get_Struct(obj, name_error_message_t, &name_err_mesg_data_type, ptr);
VALUE mesg = ptr->mesg;
if (NIL_P(mesg)) return Qnil;
else {
struct RString s_str, c_str, d_str;
VALUE c, s, d = 0, args[4], c2;
int state = 0;
rb_encoding *usascii = rb_usascii_encoding();
#define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
c = s = FAKE_CSTR(&s_str, "");
obj = ptr->recv;
switch (obj) {
case Qnil:
c = d = FAKE_CSTR(&d_str, "nil");
break;
case Qtrue:
c = d = FAKE_CSTR(&d_str, "true");
break;
case Qfalse:
c = d = FAKE_CSTR(&d_str, "false");
break;
default:
if (strstr(RSTRING_PTR(mesg), "%2$s")) {
d = rb_protect(name_err_mesg_receiver_name, obj, &state);
if (state || NIL_OR_UNDEF_P(d))
d = rb_protect(rb_inspect, obj, &state);
if (state) {
rb_set_errinfo(Qnil);
}
d = rb_check_string_type(d);
if (NIL_P(d)) {
d = rb_any_to_s(obj);
}
}
if (!RB_SPECIAL_CONST_P(obj)) {
switch (RB_BUILTIN_TYPE(obj)) {
2023-02-20 04:50:49 +03:00
case T_MODULE:
s = FAKE_CSTR(&s_str, "module ");
c = obj;
break;
case T_CLASS:
s = FAKE_CSTR(&s_str, "class ");
c = obj;
break;
default:
goto object;
}
}
else {
VALUE klass;
2023-02-20 04:50:49 +03:00
object:
klass = CLASS_OF(obj);
if (RB_TYPE_P(klass, T_CLASS) && RCLASS_SINGLETON_P(klass)) {
s = FAKE_CSTR(&s_str, "");
if (obj == rb_vm_top_self()) {
c = FAKE_CSTR(&c_str, "main");
}
else {
c = rb_any_to_s(obj);
}
break;
}
else {
s = FAKE_CSTR(&s_str, "an instance of ");
c = rb_class_real(klass);
}
}
c2 = rb_protect(name_err_mesg_receiver_name, c, &state);
if (state || NIL_OR_UNDEF_P(c2))
c2 = rb_protect(rb_inspect, c, &state);
if (state) {
rb_set_errinfo(Qnil);
}
c2 = rb_check_string_type(c2);
if (NIL_P(c2)) {
c2 = rb_any_to_s(c);
}
c = c2;
break;
}
args[0] = rb_obj_as_string(ptr->name);
args[1] = d;
args[2] = s;
args[3] = c;
mesg = rb_str_format(4, args, mesg);
}
return mesg;
}
/* :nodoc: */
static VALUE
name_err_mesg_dump(VALUE obj, VALUE limit)
{
return name_err_mesg_to_str(obj);
}
/* :nodoc: */
static VALUE
name_err_mesg_load(VALUE klass, VALUE str)
{
return str;
}
/*
* call-seq:
* name_error.receiver -> object
*
* Return the receiver associated with this NameError exception.
*/
static VALUE
name_err_receiver(VALUE self)
{
VALUE recv = rb_ivar_lookup(self, id_recv, Qundef);
2022-11-15 07:24:08 +03:00
if (!UNDEF_P(recv)) return recv;
VALUE mesg = rb_attr_get(self, id_mesg);
if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) {
rb_raise(rb_eArgError, "no receiver is available");
}
name_error_message_t *ptr;
TypedData_Get_Struct(mesg, name_error_message_t, &name_err_mesg_data_type, ptr);
return ptr->recv;
}
/*
* call-seq:
* no_method_error.args -> obj
*
* Return the arguments passed in as the third parameter to
* the constructor.
*/
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
static VALUE
nometh_err_args(VALUE self)
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
{
return rb_attr_get(self, id_args);
* error.c (exc_exception): clone the receiver exception instead of creating brand new exception object of the receiver. * eval.c (rb_eval_string_wrap): extend new ruby_top_self, not original self. * eval.c (rb_eval_cmd): respect ruby_wrapper if set. * eval.c (eval): do not update ruby_class unless scope is not provided. * eval.c (eval): preserve wrapper information. * eval.c (proc_invoke): ditto. * eval.c (block_pass): ditto. * parse.y (void_expr): too much warnings for void context (e.g. foo[1] that can be mere Proc call). * error.c (rb_name_error): new function to raise NameError with name attribute set. * eval.c (rb_f_missing): set name and args in the exception object. [new] * error.c (name_name): NameError#name - new method. * error.c (nometh_args): NoMethodError#args - new method. * lex.c (rb_reserved_word): lex_state after tRESCUE should be EXPR_MID. * gc.c (add_heap): allocation size of the heap unit is doubled for each allocation. * dir.c (isdelim): space, tab, and newline are no longer delimiters for glob patterns. * eval.c (svalue_to_avalue): new conversion scheme between single value and array values. * eval.c (avalue_to_svalue): ditto. * eval.c (rb_eval): REXPAND now uses avalue_to_svalue(), return and yield too. * eval.c (rb_yield_0): use avalue_to_svalue(). * eval.c (proc_invoke): Proc#call gives avaules, whereas Proc#yield gives mvalues. * eval.c (bmcall): convert given value (svalue) to avalue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1555 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-07-02 12:46:28 +04:00
}
/*
* call-seq:
* no_method_error.private_call? -> true or false
*
* Return true if the caused method was called as private.
*/
static VALUE
nometh_err_private_call_p(VALUE self)
{
return rb_attr_get(self, id_private_call_p);
}
void
rb_invalid_str(const char *str, const char *type)
{
VALUE s = rb_str_new2(str);
rb_raise(rb_eArgError, "invalid value for %s: %+"PRIsVALUE, type, s);
}
/*
* call-seq:
* key_error.receiver -> object
*
* Return the receiver associated with this KeyError exception.
*/
static VALUE
key_err_receiver(VALUE self)
{
VALUE recv;
recv = rb_ivar_lookup(self, id_receiver, Qundef);
2022-11-15 07:24:08 +03:00
if (!UNDEF_P(recv)) return recv;
rb_raise(rb_eArgError, "no receiver is available");
}
/*
* call-seq:
* key_error.key -> object
*
* Return the key caused this KeyError exception.
*/
static VALUE
key_err_key(VALUE self)
{
VALUE key;
key = rb_ivar_lookup(self, id_key, Qundef);
2022-11-15 07:24:08 +03:00
if (!UNDEF_P(key)) return key;
rb_raise(rb_eArgError, "no key is available");
}
VALUE
rb_key_err_new(VALUE mesg, VALUE recv, VALUE key)
{
VALUE exc = rb_obj_alloc(rb_eKeyError);
rb_ivar_set(exc, id_mesg, mesg);
rb_ivar_set(exc, id_bt, Qnil);
rb_ivar_set(exc, id_key, key);
rb_ivar_set(exc, id_receiver, recv);
return exc;
}
/*
* call-seq:
* KeyError.new(message=nil, receiver: nil, key: nil) -> key_error
*
* Construct a new +KeyError+ exception with the given message,
* receiver and key.
*/
static VALUE
key_err_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE options;
rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
if (!NIL_P(options)) {
ID keywords[2];
VALUE values[numberof(keywords)];
int i;
keywords[0] = id_receiver;
keywords[1] = id_key;
rb_get_kwargs(options, keywords, 0, numberof(values), values);
for (i = 0; i < numberof(values); ++i) {
2022-11-15 07:24:08 +03:00
if (!UNDEF_P(values[i])) {
rb_ivar_set(self, keywords[i], values[i]);
}
}
}
return self;
}
/*
* call-seq:
* no_matching_pattern_key_error.matchee -> object
*
* Return the matchee associated with this NoMatchingPatternKeyError exception.
*/
static VALUE
no_matching_pattern_key_err_matchee(VALUE self)
{
VALUE matchee;
matchee = rb_ivar_lookup(self, id_matchee, Qundef);
2022-11-15 07:24:08 +03:00
if (!UNDEF_P(matchee)) return matchee;
rb_raise(rb_eArgError, "no matchee is available");
}
/*
* call-seq:
* no_matching_pattern_key_error.key -> object
*
* Return the key caused this NoMatchingPatternKeyError exception.
*/
static VALUE
no_matching_pattern_key_err_key(VALUE self)
{
VALUE key;
key = rb_ivar_lookup(self, id_key, Qundef);
2022-11-15 07:24:08 +03:00
if (!UNDEF_P(key)) return key;
rb_raise(rb_eArgError, "no key is available");
}
/*
* call-seq:
* NoMatchingPatternKeyError.new(message=nil, matchee: nil, key: nil) -> no_matching_pattern_key_error
*
* Construct a new +NoMatchingPatternKeyError+ exception with the given message,
* matchee and key.
*/
static VALUE
no_matching_pattern_key_err_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE options;
rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
if (!NIL_P(options)) {
ID keywords[2];
VALUE values[numberof(keywords)];
int i;
keywords[0] = id_matchee;
keywords[1] = id_key;
rb_get_kwargs(options, keywords, 0, numberof(values), values);
for (i = 0; i < numberof(values); ++i) {
2022-11-15 07:24:08 +03:00
if (!UNDEF_P(values[i])) {
rb_ivar_set(self, keywords[i], values[i]);
}
}
}
return self;
}
/*
* call-seq:
* SyntaxError.new([msg]) -> syntax_error
*
* Construct a SyntaxError exception.
*/
static VALUE
syntax_error_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE mesg;
if (argc == 0) {
mesg = rb_fstring_lit("compile error");
argc = 1;
argv = &mesg;
}
return rb_call_super(argc, argv);
}
static VALUE
syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc)
{
if (NIL_P(exc)) {
*mesg = rb_enc_str_new(0, 0, enc);
exc = rb_class_new_instance(1, mesg, rb_eSyntaxError);
rb_ivar_set(exc, id_i_path, path);
}
else {
2024-05-26 14:14:18 +03:00
VALUE old_path = rb_attr_get(exc, id_i_path);
if (old_path != path) {
if (rb_str_equal(path, old_path)) {
rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE" (%p->%p)",
old_path, (void *)old_path, (void *)path);
}
else {
rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE"(%s%s)->%+"PRIsVALUE"(%s)",
old_path, rb_enc_name(rb_enc_get(old_path)),
(FL_TEST(old_path, RSTRING_FSTR) ? ":FSTR" : ""),
path, rb_enc_name(rb_enc_get(path)));
}
}
VALUE s = *mesg = rb_attr_get(exc, idMesg);
if (RSTRING_LEN(s) > 0 && *(RSTRING_END(s)-1) != '\n')
rb_str_cat_cstr(s, "\n");
}
return exc;
}
/*
* Document-module: Errno
2024-06-05 23:27:00 +03:00
* When an operating system encounters an error,
* it typically reports the error as an integer error code:
*
* $ ls nosuch.txt
* ls: cannot access 'nosuch.txt': No such file or directory
* $ echo $? # Code for last error.
* 2
*
* When the Ruby interpreter interacts with the operating system
* and receives such an error code (e.g., +2+),
* it maps the code to a particular Ruby exception class (e.g., +Errno::ENOENT+):
*
* File.open('nosuch.txt')
* # => No such file or directory @ rb_sysopen - nosuch.txt (Errno::ENOENT)
*
* Each such class is:
*
* - A nested class in this module, +Errno+.
* - A subclass of class SystemCallError.
* - Associated with an error code.
*
* Thus:
*
2024-06-05 23:27:00 +03:00
* Errno::ENOENT.superclass # => SystemCallError
* Errno::ENOENT::Errno # => 2
*
2024-06-05 23:27:00 +03:00
* The names of nested classes are returned by method +Errno.constants+:
*
2024-06-05 23:27:00 +03:00
* Errno.constants.size # => 158
* Errno.constants.sort.take(5) # => [:E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, :EADV]
*
2024-06-05 23:27:00 +03:00
* As seen above, the error code associated with each class
* is available as the value of a constant;
* the value for a particular class may vary among operating systems.
* If the class is not needed for the particular operating system,
* the value is zero:
*
2024-06-05 23:27:00 +03:00
* Errno::ENOENT::Errno # => 2
* Errno::ENOTCAPABLE::Errno # => 0
*
*/
static st_table *syserr_tbl;
void
rb_free_warning(void)
{
st_free_table(warning_categories.id2enum);
st_free_table(warning_categories.enum2id);
st_free_table(syserr_tbl);
}
static VALUE
2024-01-11 16:46:49 +03:00
setup_syserr(int n, const char *name)
{
2024-01-11 16:46:49 +03:00
VALUE error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
2024-01-11 16:46:49 +03:00
/* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
switch (n) {
case EAGAIN:
rb_eEAGAIN = error;
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
2024-01-11 16:46:49 +03:00
break;
case EWOULDBLOCK:
#endif
2024-01-11 16:46:49 +03:00
rb_eEWOULDBLOCK = error;
break;
case EINPROGRESS:
rb_eEINPROGRESS = error;
break;
}
rb_define_const(error, "Errno", INT2NUM(n));
st_add_direct(syserr_tbl, n, (st_data_t)error);
return error;
}
static VALUE
set_syserr(int n, const char *name)
{
st_data_t error;
2024-01-11 16:46:49 +03:00
if (!st_lookup(syserr_tbl, n, &error)) {
return setup_syserr(n, name);
}
else {
2024-01-11 16:46:49 +03:00
VALUE errclass = (VALUE)error;
rb_define_const(rb_mErrno, name, errclass);
return errclass;
}
}
static VALUE
get_syserr(int n)
{
st_data_t error;
if (!st_lookup(syserr_tbl, n, &error)) {
2024-01-11 16:46:49 +03:00
char name[DECIMAL_SIZE_OF(n) + sizeof("E-")];
snprintf(name, sizeof(name), "E%03d", n);
2024-01-11 16:46:49 +03:00
return setup_syserr(n, name);
}
2024-01-11 16:46:49 +03:00
return (VALUE)error;
}
/*
* call-seq:
* SystemCallError.new(msg, errno) -> system_call_error_subclass
*
* If _errno_ corresponds to a known system error code, constructs the
* appropriate Errno class for that error, otherwise constructs a
* generic SystemCallError object. The error number is subsequently
* available via the #errno method.
*/
static VALUE
syserr_initialize(int argc, VALUE *argv, VALUE self)
{
* sprintf.c (rb_str_format): allow %c to print one character string (e.g. ?x). * lib/tempfile.rb (Tempfile::make_tmpname): put dot between basename and pid. [ruby-talk:196272] * parse.y (do_block): remove -> style block. * parse.y (parser_yylex): remove tLAMBDA_ARG. * eval.c (rb_call0): binding for the return event hook should have consistent scope. [ruby-core:07928] * eval.c (proc_invoke): return behavior should depend whether it is surrounded by a lambda or a mere block. * eval.c (formal_assign): handles post splat arguments. * eval.c (rb_call0): ditto. * st.c (strhash): use FNV-1a hash. * parse.y (parser_yylex): removed experimental ';;' terminator. * eval.c (rb_node_arity): should be aware of post splat arguments. * eval.c (rb_proc_arity): ditto. * parse.y (f_args): syntax rule enhanced to support arguments after the splat. * parse.y (block_param): ditto for block parameters. * parse.y (f_post_arg): mandatory formal arguments after the splat argument. * parse.y (new_args_gen): generate nodes for mandatory formal arguments after the splat argument. * eval.c (rb_eval): dispatch mandatory formal arguments after the splat argument. * parse.y (args): allow more than one splat in the argument list. * parse.y (method_call): allow aref [] to accept all kind of method argument, including assocs, splat, and block argument. * eval.c (SETUP_ARGS0): prepare block argument as well. * lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931] * eval.c (error_line): print receivers true/false/nil specially. * eval.c (rb_proc_yield): handles parameters in yield semantics. * eval.c (nil_yield): gives LocalJumpError to denote no block error. * io.c (rb_io_getc): now takes one-character string. * string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo hashing algorithm. * string.c (rb_str_aref): str[0] now returns 1 character string, instead of a fixnum. [Ruby2] * parse.y (parser_yylex): ?c now returns 1 character string, instead of a fixnum. [Ruby2] * string.c (rb_str_aset): no longer support fixnum insertion. * eval.c (umethod_bind): should not update original class. [ruby-dev:28636] * eval.c (ev_const_get): should support constant access from within instance_eval(). [ruby-dev:28327] * time.c (time_timeval): should round for usec floating number. [ruby-core:07896] * time.c (time_add): ditto. * dir.c (sys_warning): should not call a vararg function rb_sys_warning() indirectly. [ruby-core:07886] * numeric.c (flo_divmod): the first element of Float#divmod should be an integer. [ruby-dev:28589] * test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder. * re.c (rb_reg_initialize): should not allow modifying literal regexps. frozen check moved from rb_reg_initialize_m as well. * re.c (rb_reg_initialize): should not modify untainted objects in safe levels higher than 3. * re.c (rb_memcmp): type change from char* to const void*. * dir.c (dir_close): should not close untainted dir stream. * dir.c (GetDIR): add tainted/frozen check for each dir operation. * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg): typo fixed. a patch from Florian Gross <florg at florg.net>. * eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from event_hooks. no guarantee for arbitrary hook deletion. [ruby-dev:28632] * util.c (ruby_strtod): differ addition to minimize error. [ruby-dev:28619] * util.c (ruby_strtod): should not raise ERANGE when the input string does not have any digits. [ruby-dev:28629] * eval.c (proc_invoke): should restore old ruby_frame->block. thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833] also fix [ruby-dev:28614] as well. * signal.c (trap): sig should be less then NSIG. Coverity found this bug. a patch from Kevin Tew <tewk at tewk.com>. [ruby-core:07823] * math.c (math_log2): add new method inspired by [ruby-talk:191237]. * math.c (math_log): add optional base argument to Math::log(). [ruby-talk:191308] * ext/syck/emitter.c (syck_scan_scalar): avoid accessing uninitialized array element. a patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07809] * array.c (rb_ary_fill): initialize local variables first. a patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810] * ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free type_tag. a patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07808] * ext/socket/socket.c (make_hostent_internal): accept ai_family check from Sam Roberts <sroberts at uniserve.com>. [ruby-core:07691] * util.c (ruby_strtod): should not cut off 18 digits for no reason. [ruby-core:07796] * array.c (rb_ary_fill): internalize local variable "beg" to pacify Coverity. [ruby-core:07770] * pack.c (pack_unpack): now supports CRLF newlines. a patch from <tommy at tmtm.org>. [ruby-dev:28601] * applied code clean-up patch from Stefan Huehner <stefan at huehner.org>. [ruby-core:07764] * lib/jcode.rb (String::tr_s): should have translated non squeezing character sequence (i.e. a character) as well. thanks to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090] * ext/socket/socket.c: document update patch from Sam Roberts <sroberts at uniserve.com>. [ruby-core:07701] * lib/mathn.rb (Integer): need not to remove gcd2. a patch from NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570] * parse.y (arg): too much NEW_LIST() * eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen. * eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1. [ruby-dev:28585] * parse.y (arg): use NODE_ARGSCAT for placeholder. * lib/getoptlong.rb (GetoptLong::get): RDoc update patch from mathew <meta at pobox.com>. [ruby-core:07738] * variable.c (rb_const_set): raise error when no target klass is supplied. [ruby-dev:28582] * prec.c (prec_prec_f): documentation patch from <gerardo.santana at gmail.com>. [ruby-core:07689] * bignum.c (rb_big_pow): second operand may be too big even if it's a Fixnum. [ruby-talk:187984] * README.EXT: update symbol description. [ruby-talk:188104] * COPYING: explicitly note GPLv2. [ruby-talk:187922] * parse.y: remove some obsolete syntax rules (unparenthesized method calls in argument list). * eval.c (rb_call0): insecure calling should be checked for non NODE_SCOPE method invocations too. * eval.c (rb_alias): should preserve the current safe level as well as method definition. * process.c (rb_f_sleep): remove RDoc description about SIGALRM which is not valid on the current implementation. [ruby-dev:28464] Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp> * eval.c (method_missing): should support argument splat in super. a bug in combination of super, splat and method_missing. [ruby-talk:185438] * configure.in: Solaris SunPro compiler -rapth patch from <kuwa at labs.fujitsu.com>. [ruby-dev:28443] * configure.in: remove enable_rpath=no for Solaris. [ruby-dev:28440] * ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby String object. * ruby.1: a clarification patch from David Lutterkort <dlutter at redhat.com>. [ruby-core:7508] * lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems directories. a patch from Eric Hodel <drbrain at segment7.net>. [ruby-core:07423] * eval.c (rb_clear_cache_by_class): clearing wrong cache. * ext/extmk.rb: use :remove_destination to install extension libraries to avoid SEGV. [ruby-dev:28417] * eval.c (rb_thread_fd_writable): should not re-schedule output from KILLED thread (must be error printing). * array.c (rb_ary_flatten_bang): allow specifying recursion level. [ruby-talk:182170] * array.c (rb_ary_flatten): ditto. * gc.c (add_heap): a heap_slots may overflow. a patch from Stefan Weil <weil at mail.berlios.de>. * eval.c (rb_call): use separate cache for fcall/vcall invocation. * eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local functions. * eval.c (rb_mod_local): a new method to specify newly added visibility "local". * eval.c (search_method): search for local methods which are visible only from the current class. * class.c (rb_class_local_methods): a method to list local methods. * object.c (Init_Object): add BasicObject class as a top level BlankSlate class. * ruby.h (SYM2ID): should not cast to signed long. [ruby-core:07414] * class.c (rb_include_module): allow module duplication. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
const char *err;
VALUE mesg, error, func, errmsg;
VALUE klass = rb_obj_class(self);
if (klass == rb_eSystemCallError) {
st_data_t data = (st_data_t)klass;
rb_scan_args(argc, argv, "12", &mesg, &error, &func);
if (argc == 1 && FIXNUM_P(mesg)) {
error = mesg; mesg = Qnil;
}
if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
klass = (VALUE)data;
/* change class */
if (!RB_TYPE_P(self, T_OBJECT)) { /* insurance to avoid type crash */
rb_raise(rb_eTypeError, "invalid instance type");
}
* include/ruby/ruby.h: constify RBasic::klass and add RBASIC_CLASS(obj) macro which returns a class of `obj'. This change is a part of RGENGC branch [ruby-trunk - Feature #8339]. * object.c: add new function rb_obj_reveal(). This function reveal interal (hidden) object by rb_obj_hide(). Note that do not change class before and after hiding. Only permitted example is: klass = RBASIC_CLASS(obj); rb_obj_hide(obj); .... rb_obj_reveal(obj, klass); TODO: API design. rb_obj_reveal() should be replaced with others. TODO: modify constified variables using cast may be harmful for compiler's analysis and optimizaton. Any idea to prohibt inserting RBasic::klass directly? If rename RBasic::klass and force to use RBASIC_CLASS(obj), then all codes such as `RBASIC(obj)->klass' will be compilation error. Is it acceptable? (We have similar experience at Ruby 1.9, for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)". * internal.h: add some macros. * RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal object. * RBASIC_SET_CLASS(obj, cls) set RBasic::klass. * RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS without write barrier (planned). * RCLASS_SET_SUPER(a, b) set super class of a. * array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c, file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c, parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c, string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c: Use above macros and functions to access RBasic::klass. * ext/coverage/coverage.c, ext/readline/readline.c, ext/socket/ancdata.c, ext/socket/init.c, * ext/zlib/zlib.c: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
RBASIC_SET_CLASS(self, klass);
}
}
else {
rb_scan_args(argc, argv, "02", &mesg, &func);
error = rb_const_get(klass, id_Errno);
}
if (!NIL_P(error)) err = strerror(NUM2INT(error));
else err = "unknown error";
errmsg = rb_enc_str_new_cstr(err, rb_locale_encoding());
if (!NIL_P(mesg)) {
VALUE str = StringValue(mesg);
if (!NIL_P(func)) rb_str_catf(errmsg, " @ %"PRIsVALUE, func);
rb_str_catf(errmsg, " - %"PRIsVALUE, str);
}
mesg = errmsg;
rb_call_super(1, &mesg);
rb_ivar_set(self, id_errno, error);
return self;
}
/*
* call-seq:
* system_call_error.errno -> integer
*
* Return this SystemCallError's error number.
*/
static VALUE
syserr_errno(VALUE self)
{
return rb_attr_get(self, id_errno);
}
/*
* call-seq:
* system_call_error === other -> true or false
*
* Return +true+ if the receiver is a generic +SystemCallError+, or
* if the error numbers +self+ and _other_ are the same.
*/
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
static VALUE
syserr_eqq(VALUE self, VALUE exc)
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
{
VALUE num, e;
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
if (!rb_respond_to(exc, id_errno)) return Qfalse;
}
else if (self == rb_eSystemCallError) return Qtrue;
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
num = rb_attr_get(exc, id_errno);
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
if (NIL_P(num)) {
num = rb_funcallv(exc, id_errno, 0, 0);
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
}
e = rb_const_get(self, id_Errno);
return RBOOL(FIXNUM_P(num) ? num == e : rb_equal(num, e));
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
}
/*
* Document-class: StandardError
*
* The most standard error types are subclasses of StandardError. A
* rescue clause without an explicit Exception class will rescue all
* StandardErrors (and only those).
*
* def foo
* raise "Oups"
* end
* foo rescue "Hello" #=> "Hello"
*
* On the other hand:
*
* require 'does/not/exist' rescue "Hi"
*
* <em>raises the exception:</em>
*
* LoadError: no such file to load -- does/not/exist
*
*/
/*
* Document-class: SystemExit
*
* Raised by +exit+ to initiate the termination of the script.
*/
/*
* Document-class: SignalException
*
* Raised when a signal is received.
*
* begin
* Process.kill('HUP',Process.pid)
* sleep # wait for receiver to handle signal sent by Process.kill
* rescue SignalException => e
* puts "received Exception #{e}"
* end
*
* <em>produces:</em>
*
* received Exception SIGHUP
*/
/*
* Document-class: Interrupt
*
* Raised when the interrupt signal is received, typically because the
* user has pressed Control-C (on most posix platforms). As such, it is a
* subclass of +SignalException+.
*
* begin
* puts "Press ctrl-C when you get bored"
* loop {}
* rescue Interrupt => e
* puts "Note: You will typically use Signal.trap instead."
* end
*
* <em>produces:</em>
*
* Press ctrl-C when you get bored
*
* <em>then waits until it is interrupted with Control-C and then prints:</em>
*
* Note: You will typically use Signal.trap instead.
*/
/*
* Document-class: TypeError
*
* Raised when encountering an object that is not of the expected type.
*
* [1, 2, 3].first("two")
*
* <em>raises the exception:</em>
*
* TypeError: no implicit conversion of String into Integer
*
*/
/*
* Document-class: ArgumentError
*
* Raised when the arguments are wrong and there isn't a more specific
* Exception class.
*
* Ex: passing the wrong number of arguments
*
* [1, 2, 3].first(4, 5)
*
* <em>raises the exception:</em>
*
* ArgumentError: wrong number of arguments (given 2, expected 1)
*
* Ex: passing an argument that is not acceptable:
*
* [1, 2, 3].first(-4)
*
* <em>raises the exception:</em>
*
* ArgumentError: negative array size
*/
/*
* Document-class: IndexError
*
* Raised when the given index is invalid.
*
* a = [:foo, :bar]
* a.fetch(0) #=> :foo
* a[4] #=> nil
* a.fetch(4) #=> IndexError: index 4 outside of array bounds: -2...2
*
*/
/*
* Document-class: KeyError
*
* Raised when the specified key is not found. It is a subclass of
* IndexError.
*
* h = {"foo" => :bar}
* h.fetch("foo") #=> :bar
* h.fetch("baz") #=> KeyError: key not found: "baz"
*
*/
/*
* Document-class: RangeError
*
* Raised when a given numerical value is out of range.
*
* [1, 2, 3].drop(1 << 100)
*
* <em>raises the exception:</em>
*
* RangeError: bignum too big to convert into `long'
*/
/*
* Document-class: ScriptError
*
* ScriptError is the superclass for errors raised when a script
* can not be executed because of a +LoadError+,
* +NotImplementedError+ or a +SyntaxError+. Note these type of
* +ScriptErrors+ are not +StandardError+ and will not be
* rescued unless it is specified explicitly (or its ancestor
* +Exception+).
*/
/*
* Document-class: SyntaxError
*
* Raised when encountering Ruby code with an invalid syntax.
*
* eval("1+1=2")
*
* <em>raises the exception:</em>
*
* SyntaxError: (eval):1: syntax error, unexpected '=', expecting $end
*/
/*
* Document-class: LoadError
*
* Raised when a file required (a Ruby script, extension library, ...)
* fails to load.
*
* require 'this/file/does/not/exist'
*
* <em>raises the exception:</em>
*
* LoadError: no such file to load -- this/file/does/not/exist
*/
/*
* Document-class: NotImplementedError
*
* Raised when a feature is not implemented on the current platform. For
* example, methods depending on the +fsync+ or +fork+ system calls may
* raise this exception if the underlying operating system or Ruby
* runtime does not support them.
*
* Note that if +fork+ raises a +NotImplementedError+, then
* <code>respond_to?(:fork)</code> returns +false+.
*/
/*
* Document-class: NameError
*
* Raised when a given name is invalid or undefined.
*
* puts foo
*
* <em>raises the exception:</em>
*
* NameError: undefined local variable or method `foo' for main:Object
*
* Since constant names must start with a capital:
*
* Integer.const_set :answer, 42
*
* <em>raises the exception:</em>
*
* NameError: wrong constant name answer
*/
/*
* Document-class: NoMethodError
*
* Raised when a method is called on a receiver which doesn't have it
* defined and also fails to respond with +method_missing+.
*
* "hello".to_ary
*
* <em>raises the exception:</em>
*
* NoMethodError: undefined method `to_ary' for an instance of String
*/
/*
* Document-class: FrozenError
*
* Raised when there is an attempt to modify a frozen object.
*
* [1, 2, 3].freeze << 4
*
* <em>raises the exception:</em>
*
* FrozenError: can't modify frozen Array
*/
/*
* Document-class: RuntimeError
*
* A generic error class raised when an invalid operation is attempted.
* Kernel#raise will raise a RuntimeError if no Exception class is
* specified.
*
* raise "ouch"
*
* <em>raises the exception:</em>
*
* RuntimeError: ouch
*/
/*
* Document-class: SecurityError
*
* No longer used by internal code.
*/
/*
* Document-class: NoMemoryError
*
* Raised when memory allocation fails.
*/
/*
* Document-class: SystemCallError
*
* SystemCallError is the base class for all low-level
* platform-dependent errors.
*
* The errors available on the current platform are subclasses of
* SystemCallError and are defined in the Errno module.
*
* File.open("does/not/exist")
*
* <em>raises the exception:</em>
*
* Errno::ENOENT: No such file or directory - does/not/exist
*/
/*
* Document-class: EncodingError
*
* EncodingError is the base class for encoding errors.
*/
/*
* Document-class: Encoding::CompatibilityError
*
* Raised by Encoding and String methods when the source encoding is
* incompatible with the target encoding.
*/
/*
* Document-class: fatal
*
2024-01-12 16:44:56 +03:00
* +fatal+ is an Exception that is raised when Ruby has encountered a fatal
* error and must exit.
*/
/*
* Document-class: NameError::message
* :nodoc:
*/
/*
* Document-class: Exception
*
2024-06-26 20:31:40 +03:00
* \Class +Exception+ and its subclasses are used to indicate that an error
* or other problem has occurred,
* and may need to be handled.
* See {Exceptions}[rdoc-ref:exceptions.md].
*
2024-06-26 20:31:40 +03:00
* An +Exception+ object carries certain information:
*
2024-06-26 20:31:40 +03:00
* - The type (the exception's class),
* commonly StandardError, RuntimeError, or a subclass of one or the other;
* see {Built-In Exception Class Hierarchy}[rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy].
* - An optional descriptive message;
* see methods ::new, #message.
* - Optional backtrace information;
* see methods #backtrace, #backtrace_locations, #set_backtrace.
* - An optional cause;
* see method #cause.
*
2024-06-26 20:31:40 +03:00
* == Built-In \Exception \Class Hierarchy
*
2024-06-26 20:31:40 +03:00
* The hierarchy of built-in subclasses of class +Exception+:
*
* * NoMemoryError
* * ScriptError
2024-06-26 20:31:40 +03:00
* * {LoadError}[https://docs.ruby-lang.org/en/master/LoadError.html]
* * NotImplementedError
* * SyntaxError
* * SecurityError
* * SignalException
* * Interrupt
* * StandardError
* * ArgumentError
* * UncaughtThrowError
* * EncodingError
* * FiberError
* * IOError
* * EOFError
* * IndexError
* * KeyError
* * StopIteration
* * ClosedQueueError
* * LocalJumpError
* * NameError
* * NoMethodError
* * RangeError
* * FloatDomainError
* * RegexpError
* * RuntimeError
* * FrozenError
* * SystemCallError
2024-06-26 20:31:40 +03:00
* * Errno (and its subclasses, representing system errors)
* * ThreadError
* * TypeError
* * ZeroDivisionError
* * SystemExit
* * SystemStackError
2024-06-26 20:31:40 +03:00
* * {fatal}[https://docs.ruby-lang.org/en/master/fatal.html]
*
*/
static VALUE
exception_alloc(VALUE klass)
{
return rb_class_allocate_instance(klass);
}
static VALUE
exception_dumper(VALUE exc)
{
// TODO: Currently, the instance variables "bt" and "bt_locations"
// refers to the same object (Array of String). But "bt_locations"
// should have an Array of Thread::Backtrace::Locations.
return exc;
}
static int
ivar_copy_i(ID key, VALUE val, st_data_t exc)
{
rb_ivar_set((VALUE)exc, key, val);
return ST_CONTINUE;
}
void rb_exc_check_circular_cause(VALUE exc);
static VALUE
exception_loader(VALUE exc, VALUE obj)
{
// The loader function of rb_marshal_define_compat seems to be called for two events:
// one is for fixup (r_fixup_compat), the other is for TYPE_USERDEF.
// In the former case, the first argument is an instance of Exception (because
// we pass rb_eException to rb_marshal_define_compat). In the latter case, the first
// argument is a class object (see TYPE_USERDEF case in r_object0).
2020-09-15 08:03:22 +03:00
// We want to copy all instance variables (but "bt_locations") from obj to exc.
// But we do not want to do so in the second case, so the following branch is for that.
if (RB_TYPE_P(exc, T_CLASS)) return obj; // maybe called from Marshal's TYPE_USERDEF
rb_ivar_foreach(obj, ivar_copy_i, exc);
rb_exc_check_circular_cause(exc);
if (rb_attr_get(exc, id_bt) == rb_attr_get(exc, id_bt_locations)) {
rb_ivar_set(exc, id_bt_locations, Qnil);
}
return exc;
}
void
Init_Exception(void)
{
rb_eException = rb_define_class("Exception", rb_cObject);
rb_define_alloc_func(rb_eException, exception_alloc);
rb_marshal_define_compat(rb_eException, rb_eException, exception_dumper, exception_loader);
rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
rb_define_singleton_method(rb_eException, "to_tty?", exc_s_to_tty_p, 0);
rb_define_method(rb_eException, "exception", exc_exception, -1);
rb_define_method(rb_eException, "initialize", exc_initialize, -1);
rb_define_method(rb_eException, "==", exc_equal, 1);
rb_define_method(rb_eException, "to_s", exc_to_s, 0);
rb_define_method(rb_eException, "message", exc_message, 0);
rb_define_method(rb_eException, "detailed_message", exc_detailed_message, -1);
rb_define_method(rb_eException, "full_message", exc_full_message, -1);
rb_define_method(rb_eException, "inspect", exc_inspect, 0);
rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
rb_define_method(rb_eException, "backtrace_locations", exc_backtrace_locations, 0);
rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
rb_define_method(rb_eException, "cause", exc_cause, 0);
rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
rb_define_method(rb_eSystemExit, "status", exit_status, 0);
rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
rb_eFatal = rb_define_class("fatal", rb_eException);
rb_eSignal = rb_define_class("SignalException", rb_eException);
rb_eInterrupt = rb_define_class("Interrupt", rb_eSignal);
rb_eStandardError = rb_define_class("StandardError", rb_eException);
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
rb_define_method(rb_eKeyError, "initialize", key_err_initialize, -1);
rb_define_method(rb_eKeyError, "receiver", key_err_receiver, 0);
rb_define_method(rb_eKeyError, "key", key_err_key, 0);
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 08:22:21 +04:00
rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
rb_eScriptError = rb_define_class("ScriptError", rb_eException);
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
rb_define_method(rb_eSyntaxError, "initialize", syntax_error_initialize, -1);
/* RDoc will use literal name value while parsing rb_attr,
* and will render `idPath` as an attribute name without this trick */
ID path = idPath;
/* the path that failed to parse */
rb_attr(rb_eSyntaxError, path, TRUE, FALSE, FALSE);
rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
/* the path that failed to load */
rb_attr(rb_eLoadError, path, TRUE, FALSE, FALSE);
rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
rb_eNameError = rb_define_class("NameError", rb_eStandardError);
rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
rb_define_method(rb_eNameError, "name", name_err_name, 0);
rb_define_method(rb_eNameError, "receiver", name_err_receiver, 0);
rb_define_method(rb_eNameError, "local_variables", name_err_local_variables, 0);
rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cObject);
rb_define_alloc_func(rb_cNameErrorMesg, name_err_mesg_alloc);
rb_define_method(rb_cNameErrorMesg, "initialize_copy", name_err_mesg_init_copy, 1);
rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_dump, 1);
rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
rb_define_method(rb_eNoMethodError, "private_call?", nometh_err_private_call_p, 0);
rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
rb_eFrozenError = rb_define_class("FrozenError", rb_eRuntimeError);
rb_define_method(rb_eFrozenError, "initialize", frozen_err_initialize, -1);
rb_define_method(rb_eFrozenError, "receiver", frozen_err_receiver, 0);
rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
rb_eNoMatchingPatternError = rb_define_class("NoMatchingPatternError", rb_eStandardError);
rb_eNoMatchingPatternKeyError = rb_define_class("NoMatchingPatternKeyError", rb_eNoMatchingPatternError);
rb_define_method(rb_eNoMatchingPatternKeyError, "initialize", no_matching_pattern_key_err_initialize, -1);
rb_define_method(rb_eNoMatchingPatternKeyError, "matchee", no_matching_pattern_key_err_matchee, 0);
rb_define_method(rb_eNoMatchingPatternKeyError, "key", no_matching_pattern_key_err_key, 0);
syserr_tbl = st_init_numtable();
rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
rb_mErrno = rb_define_module("Errno");
rb_mWarning = rb_define_module("Warning");
2019-11-12 12:34:49 +03:00
rb_define_singleton_method(rb_mWarning, "[]", rb_warning_s_aref, 1);
rb_define_singleton_method(rb_mWarning, "[]=", rb_warning_s_aset, 2);
rb_define_singleton_method(rb_mWarning, "categories", rb_warning_s_categories, 0);
rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1);
rb_extend_object(rb_mWarning, rb_mWarning);
/* :nodoc: */
rb_cWarningBuffer = rb_define_class_under(rb_mWarning, "buffer", rb_cString);
rb_define_method(rb_cWarningBuffer, "write", warning_write, -1);
id_cause = rb_intern_const("cause");
id_message = rb_intern_const("message");
id_detailed_message = rb_intern_const("detailed_message");
id_backtrace = rb_intern_const("backtrace");
id_key = rb_intern_const("key");
id_matchee = rb_intern_const("matchee");
id_args = rb_intern_const("args");
id_receiver = rb_intern_const("receiver");
id_private_call_p = rb_intern_const("private_call?");
id_local_variables = rb_intern_const("local_variables");
id_Errno = rb_intern_const("Errno");
id_errno = rb_intern_const("errno");
id_i_path = rb_intern_const("@path");
id_warn = rb_intern_const("warn");
id_category = rb_intern_const("category");
2020-12-15 09:15:23 +03:00
id_deprecated = rb_intern_const("deprecated");
id_experimental = rb_intern_const("experimental");
id_performance = rb_intern_const("performance");
id_strict_unused_block = rb_intern_const("strict_unused_block");
id_top = rb_intern_const("top");
id_bottom = rb_intern_const("bottom");
id_iseq = rb_make_internal_id();
id_recv = rb_make_internal_id();
sym_category = ID2SYM(id_category);
2022-02-07 10:05:45 +03:00
sym_highlight = ID2SYM(rb_intern_const("highlight"));
warning_categories.id2enum = rb_init_identtable();
st_add_direct(warning_categories.id2enum, id_deprecated, RB_WARN_CATEGORY_DEPRECATED);
st_add_direct(warning_categories.id2enum, id_experimental, RB_WARN_CATEGORY_EXPERIMENTAL);
st_add_direct(warning_categories.id2enum, id_performance, RB_WARN_CATEGORY_PERFORMANCE);
st_add_direct(warning_categories.id2enum, id_strict_unused_block, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK);
warning_categories.enum2id = rb_init_identtable();
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_NONE, 0);
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_DEPRECATED, id_deprecated);
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_EXPERIMENTAL, id_experimental);
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_PERFORMANCE, id_performance);
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK, id_strict_unused_block);
}
void
rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
{
va_list args;
VALUE mesg;
va_start(args, fmt);
mesg = rb_enc_vsprintf(enc, fmt, args);
va_end(args);
rb_exc_raise(rb_exc_new3(exc, mesg));
}
void
rb_vraise(VALUE exc, const char *fmt, va_list ap)
{
rb_exc_raise(rb_exc_new3(exc, rb_vsprintf(fmt, ap)));
}
void
rb_raise(VALUE exc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
rb_vraise(exc, fmt, args);
va_end(args);
}
NORETURN(static void raise_loaderror(VALUE path, VALUE mesg));
static void
raise_loaderror(VALUE path, VALUE mesg)
{
VALUE err = rb_exc_new3(rb_eLoadError, mesg);
rb_ivar_set(err, id_i_path, path);
rb_exc_raise(err);
}
void
rb_loaderror(const char *fmt, ...)
{
va_list args;
VALUE mesg;
va_start(args, fmt);
mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
va_end(args);
raise_loaderror(Qnil, mesg);
}
void
rb_loaderror_with_path(VALUE path, const char *fmt, ...)
{
va_list args;
VALUE mesg;
va_start(args, fmt);
mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
va_end(args);
raise_loaderror(path, mesg);
}
void
rb_notimplement(void)
{
rb_raise(rb_eNotImpError,
"%"PRIsVALUE"() function is unimplemented on this machine",
rb_id2str(rb_frame_this_func()));
}
void
rb_fatal(const char *fmt, ...)
{
va_list args;
VALUE mesg;
if (! ruby_thread_has_gvl_p()) {
/* The thread has no GVL. Object allocation impossible (cant run GC),
* thus no message can be printed out. */
fprintf(stderr, "[FATAL] rb_fatal() outside of GVL\n");
2023-07-31 21:04:42 +03:00
rb_print_backtrace(stderr);
die();
}
va_start(args, fmt);
mesg = rb_vsprintf(fmt, args);
va_end(args);
rb_exc_fatal(rb_exc_new3(rb_eFatal, mesg));
}
static VALUE
make_errno_exc(const char *mesg)
{
int n = errno;
errno = 0;
if (n == 0) {
rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
* array.c (rb_ary_modify): should copy the internal buffer if the modifying buffer is shared. * array.c (ary_make_shared): make an internal buffer of an array to be shared. * array.c (rb_ary_shift): avoid sliding an internal buffer by using shared buffer. * array.c (rb_ary_subseq): avoid copying the buffer. * parse.y (gettable): should freeze __LINE__ string. * io.c (rb_io_puts): old behavoir restored. rationale: a) if you want to call to_s for arrays, you can just call print a, "\n". b) to_s wastes memory if array (and sum of its contents) is huge. c) now any object that has to_ary is treated as an array, using rb_check_convert_type(). * hash.c (rb_hash_initialize): now accepts a block to calculate the default value. [new] * hash.c (rb_hash_aref): call "default" method to get the value corrensponding to the non existing key. * hash.c (rb_hash_default): get the default value based on the block given to 'new'. Now it takes an optinal "key" argument. "default" became the method to get the value for non existing key. Users may override "default" method to change the hash behavior. * hash.c (rb_hash_set_default): clear the flag if a block is given to 'new' * object.c (Init_Object): undef Data.allocate, left Data.new. * ext/curses/curses.c (window_scrollok): use RTEST(). * ext/curses/curses.c (window_idlok): ditto. * ext/curses/curses.c (window_keypad): ditto. * ext/curses/curses.c (window_idlok): idlok() may return void on some platforms; so don't use return value. * ext/curses/curses.c (window_scrollok): ditto for consistency. * ext/curses/curses.c: replace FIX2INT() by typechecking NUM2INT(). * parse.y (str_extend): should not process immature #$x and #@x interpolation, e.g #@#@ etc. * enum.c (enum_sort_by): sort_by does not have to be stable always. * enum.c (enum_sort_by): call qsort directly to gain performance. * util.c (ruby_qsort): ruby_qsort(qs6) is now native thread safe. * error.c (rb_sys_fail): it must be a bug if it's called when errno == 0. * regex.c (WC2MBC1ST): should not pass through > 0x80 number in UTF-8. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1896 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-12-10 10:18:16 +03:00
}
return rb_syserr_new(n, mesg);
}
* array.c (rb_ary_modify): should copy the internal buffer if the modifying buffer is shared. * array.c (ary_make_shared): make an internal buffer of an array to be shared. * array.c (rb_ary_shift): avoid sliding an internal buffer by using shared buffer. * array.c (rb_ary_subseq): avoid copying the buffer. * parse.y (gettable): should freeze __LINE__ string. * io.c (rb_io_puts): old behavoir restored. rationale: a) if you want to call to_s for arrays, you can just call print a, "\n". b) to_s wastes memory if array (and sum of its contents) is huge. c) now any object that has to_ary is treated as an array, using rb_check_convert_type(). * hash.c (rb_hash_initialize): now accepts a block to calculate the default value. [new] * hash.c (rb_hash_aref): call "default" method to get the value corrensponding to the non existing key. * hash.c (rb_hash_default): get the default value based on the block given to 'new'. Now it takes an optinal "key" argument. "default" became the method to get the value for non existing key. Users may override "default" method to change the hash behavior. * hash.c (rb_hash_set_default): clear the flag if a block is given to 'new' * object.c (Init_Object): undef Data.allocate, left Data.new. * ext/curses/curses.c (window_scrollok): use RTEST(). * ext/curses/curses.c (window_idlok): ditto. * ext/curses/curses.c (window_keypad): ditto. * ext/curses/curses.c (window_idlok): idlok() may return void on some platforms; so don't use return value. * ext/curses/curses.c (window_scrollok): ditto for consistency. * ext/curses/curses.c: replace FIX2INT() by typechecking NUM2INT(). * parse.y (str_extend): should not process immature #$x and #@x interpolation, e.g #@#@ etc. * enum.c (enum_sort_by): sort_by does not have to be stable always. * enum.c (enum_sort_by): call qsort directly to gain performance. * util.c (ruby_qsort): ruby_qsort(qs6) is now native thread safe. * error.c (rb_sys_fail): it must be a bug if it's called when errno == 0. * regex.c (WC2MBC1ST): should not pass through > 0x80 number in UTF-8. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1896 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-12-10 10:18:16 +03:00
static VALUE
make_errno_exc_str(VALUE mesg)
{
int n = errno;
errno = 0;
if (!mesg) mesg = Qnil;
if (n == 0) {
const char *s = !NIL_P(mesg) ? RSTRING_PTR(mesg) : "";
rb_bug("rb_sys_fail_str(%s) - errno == 0", s);
}
return rb_syserr_new_str(n, mesg);
}
VALUE
rb_syserr_new(int n, const char *mesg)
{
VALUE arg;
arg = mesg ? rb_str_new2(mesg) : Qnil;
return rb_syserr_new_str(n, arg);
}
VALUE
rb_syserr_new_str(int n, VALUE arg)
{
return rb_class_new_instance(1, &arg, get_syserr(n));
}
void
rb_syserr_fail(int e, const char *mesg)
{
rb_exc_raise(rb_syserr_new(e, mesg));
}
void
rb_syserr_fail_str(int e, VALUE mesg)
{
rb_exc_raise(rb_syserr_new_str(e, mesg));
}
#undef rb_sys_fail
void
rb_sys_fail(const char *mesg)
{
rb_exc_raise(make_errno_exc(mesg));
}
#undef rb_sys_fail_str
void
rb_sys_fail_str(VALUE mesg)
{
rb_exc_raise(make_errno_exc_str(mesg));
}
#ifdef RUBY_FUNCTION_NAME_STRING
void
rb_sys_fail_path_in(const char *func_name, VALUE path)
{
int n = errno;
errno = 0;
rb_syserr_fail_path_in(func_name, n, path);
}
void
rb_syserr_fail_path_in(const char *func_name, int n, VALUE path)
{
rb_exc_raise(rb_syserr_new_path_in(func_name, n, path));
}
VALUE
rb_syserr_new_path_in(const char *func_name, int n, VALUE path)
{
VALUE args[2];
if (!path) path = Qnil;
if (n == 0) {
const char *s = !NIL_P(path) ? RSTRING_PTR(path) : "";
if (!func_name) func_name = "(null)";
rb_bug("rb_sys_fail_path_in(%s, %s) - errno == 0",
func_name, s);
}
args[0] = path;
args[1] = rb_str_new_cstr(func_name);
return rb_class_new_instance(2, args, get_syserr(n));
}
#endif
NORETURN(static void rb_mod_exc_raise(VALUE exc, VALUE mod));
static void
rb_mod_exc_raise(VALUE exc, VALUE mod)
{
rb_extend_object(exc, mod);
rb_exc_raise(exc);
}
void
rb_mod_sys_fail(VALUE mod, const char *mesg)
{
VALUE exc = make_errno_exc(mesg);
rb_mod_exc_raise(exc, mod);
}
void
rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
{
VALUE exc = make_errno_exc_str(mesg);
rb_mod_exc_raise(exc, mod);
}
void
rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
{
VALUE exc = rb_syserr_new(e, mesg);
rb_mod_exc_raise(exc, mod);
}
void
rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
{
VALUE exc = rb_syserr_new_str(e, mesg);
rb_mod_exc_raise(exc, mod);
}
static void
syserr_warning(VALUE mesg, int err)
{
rb_str_set_len(mesg, RSTRING_LEN(mesg)-1);
rb_str_catf(mesg, ": %s\n", strerror(err));
rb_write_warning_str(mesg);
}
#if 0
void
rb_sys_warn(const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
int errno_save = errno;
with_warning_string(mesg, 0, fmt) {
syserr_warning(mesg, errno_save);
}
errno = errno_save;
}
}
void
rb_syserr_warn(int err, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
with_warning_string(mesg, 0, fmt) {
syserr_warning(mesg, err);
}
}
}
void
rb_sys_enc_warn(rb_encoding *enc, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
int errno_save = errno;
with_warning_string(mesg, enc, fmt) {
syserr_warning(mesg, errno_save);
}
errno = errno_save;
}
}
void
rb_syserr_enc_warn(int err, rb_encoding *enc, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
with_warning_string(mesg, enc, fmt) {
syserr_warning(mesg, err);
}
}
}
#endif
void
rb_sys_warning(const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
int errno_save = errno;
with_warning_string(mesg, 0, fmt) {
syserr_warning(mesg, errno_save);
}
errno = errno_save;
}
}
#if 0
void
rb_syserr_warning(int err, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
with_warning_string(mesg, 0, fmt) {
syserr_warning(mesg, err);
}
}
}
#endif
void
rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
int errno_save = errno;
with_warning_string(mesg, enc, fmt) {
syserr_warning(mesg, errno_save);
}
errno = errno_save;
}
}
void
rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
with_warning_string(mesg, enc, fmt) {
syserr_warning(mesg, err);
}
}
}
void
rb_load_fail(VALUE path, const char *err)
{
VALUE mesg = rb_str_buf_new_cstr(err);
rb_str_cat2(mesg, " -- ");
rb_str_append(mesg, path); /* should be ASCII compatible */
raise_loaderror(path, mesg);
}
void
rb_error_frozen(const char *what)
{
rb_raise(rb_eFrozenError, "can't modify frozen %s", what);
}
void
rb_frozen_error_raise(VALUE frozen_obj, const char *fmt, ...)
{
va_list args;
VALUE exc, mesg;
va_start(args, fmt);
mesg = rb_vsprintf(fmt, args);
va_end(args);
exc = rb_exc_new3(rb_eFrozenError, mesg);
rb_ivar_set(exc, id_recv, frozen_obj);
rb_exc_raise(exc);
}
static VALUE
inspect_frozen_obj(VALUE obj, VALUE mesg, int recur)
{
if (recur) {
rb_str_cat_cstr(mesg, " ...");
}
else {
rb_str_append(mesg, rb_inspect(obj));
}
return mesg;
}
static VALUE
get_created_info(VALUE obj, int *pline)
{
VALUE info = rb_attr_get(obj, id_debug_created_info);
if (NIL_P(info)) return Qnil;
VALUE path = rb_ary_entry(info, 0);
VALUE line = rb_ary_entry(info, 1);
if (NIL_P(path)) return Qnil;
*pline = NUM2INT(line);
return StringValue(path);
}
void
rb_error_frozen_object(VALUE frozen_obj)
{
rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ",
CLASS_OF(frozen_obj));
VALUE exc = rb_exc_new_str(rb_eFrozenError, mesg);
rb_ivar_set(exc, id_recv, frozen_obj);
rb_exec_recursive(inspect_frozen_obj, frozen_obj, mesg);
int created_line;
VALUE created_path = get_created_info(frozen_obj, &created_line);
if (!NIL_P(created_path)) {
rb_str_catf(mesg, ", created at %"PRIsVALUE":%d", created_path, created_line);
}
rb_exc_raise(exc);
}
void
rb_warn_unchilled(VALUE obj)
{
rb_warning_category_t category = RB_WARN_CATEGORY_DEPRECATED;
if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
int line;
VALUE file = rb_source_location(&line);
VALUE mesg = NIL_P(file) ? rb_str_new(0, 0) : rb_str_dup(file);
if (!NIL_P(file)) {
if (line) rb_str_catf(mesg, ":%d", line);
rb_str_cat2(mesg, ": ");
}
rb_str_cat2(mesg, "warning: literal string will be frozen in the future");
VALUE str = obj;
if (STR_SHARED_P(str)) {
str = RSTRING(obj)->as.heap.aux.shared;
}
VALUE created = get_created_info(str, &line);
if (NIL_P(created)) {
rb_str_cat2(mesg, " (run with --debug-frozen-string-literal for more information)\n");
} else {
rb_str_cat2(mesg, "\n");
rb_str_append(mesg, created);
if (line) rb_str_catf(mesg, ":%d", line);
rb_str_cat2(mesg, ": info: the string was created here\n");
}
rb_warn_category(mesg, rb_warning_category_to_name(category));
}
}
#undef rb_check_frozen
void
rb_check_frozen(VALUE obj)
{
rb_check_frozen_inline(obj);
}
void
rb_check_copyable(VALUE obj, VALUE orig)
{
if (!FL_ABLE(obj)) return;
rb_check_frozen(obj);
if (!FL_ABLE(orig)) return;
}
void
Init_syserr(void)
{
2024-01-11 16:46:49 +03:00
rb_eNOERROR = setup_syserr(0, "NOERROR");
#if 0
/* No error */
rb_define_const(rb_mErrno, "NOERROR", rb_eNOERROR);
#endif
#define defined_error(name, num) set_syserr((num), (name));
2024-01-13 10:34:32 +03:00
#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNOERROR);
#include "known_errors.inc"
#undef defined_error
#undef undefined_error
}
2019-12-10 14:22:42 +03:00
#include "warning.rbinc"
/*!
* \}
*/