summaryrefslogtreecommitdiff
path: root/internal/error.h
blob: 11601858f4c47596226268a0693e1f690306039b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#ifndef INTERNAL_ERROR_H                                 /*-*-C-*-vi:se ft=c:*/
#define INTERNAL_ERROR_H
/**
 * @author     Ruby developers <ruby-core@ruby-lang.org>
 * @copyright  This  file  is   a  part  of  the   programming  language  Ruby.
 *             Permission  is hereby  granted,  to  either redistribute  and/or
 *             modify this file, provided that  the conditions mentioned in the
 *             file COPYING are met.  Consult the file for details.
 * @brief      Internal header for Exception.
 */
#include "ruby/internal/config.h"
#include <stdarg.h>             /* for va_list */
#include "internal/string.h"    /* for rb_fstring_cstr */
#include "ruby/internal/stdbool.h"     /* for bool */
#include "ruby/encoding.h"      /* for rb_encoding */
#include "ruby/intern.h"        /* for rb_exc_raise */
#include "ruby/ruby.h"          /* for enum ruby_value_type */

#ifdef Check_Type
# undef Check_Type               /* in ruby/ruby.h */
#endif

#ifdef rb_raise_static
# undef rb_raise_static
# undef rb_sys_fail_path
# undef rb_syserr_fail_path
#endif

#define rb_raise_static(e, m) \
    rb_raise_cstr_i((e), rb_str_new_static((m), rb_strlen_lit(m)))
#ifdef RUBY_FUNCTION_NAME_STRING
# define rb_sys_fail_path(path) rb_sys_fail_path_in(RUBY_FUNCTION_NAME_STRING, path)
# define rb_syserr_fail_path(err, path) rb_syserr_fail_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path))
# define rb_syserr_new_path(err, path) rb_syserr_new_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path))
#else
# define rb_sys_fail_path(path) rb_sys_fail_str(path)
# define rb_syserr_fail_path(err, path) rb_syserr_fail_str((err), (path))
# define rb_syserr_new_path(err, path) rb_syserr_new_str((err), (path))
#endif

/* error.c */
extern long rb_backtrace_length_limit;
extern VALUE rb_eEAGAIN;
extern VALUE rb_eEWOULDBLOCK;
extern VALUE rb_eEINPROGRESS;
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0)
void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args);
NORETURN(void rb_async_bug_errno(const char *,int));
const char *rb_builtin_type_name(int t);
const char *rb_builtin_class_name(VALUE x);
PRINTF_ARGS(void rb_warn_deprecated(const char *fmt, const char *suggest, ...), 1, 3);
PRINTF_ARGS(void rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...), 2, 4);
#if RUBY_DEBUG
# include "ruby/version.h"
# define RUBY_VERSION_SINCE(major, minor) (RUBY_API_VERSION_CODE >= (major * 10000) + (minor) * 100)
# define RUBY_VERSION_BEFORE(major, minor) (RUBY_API_VERSION_CODE < (major * 10000) + (minor) * 100)
# if defined(RBIMPL_WARNING_PRAGMA0)
#   define RBIMPL_TODO0(x) RBIMPL_WARNING_PRAGMA0(message(x))
# elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
#   define RBIMPL_TODO0(x) __pragma(message(x))
# endif

# if RBIMPL_HAS_ATTRIBUTE(diagnose_if) || defined(__OPTIMIZE__)

#define RUBY_VERSION_isdigit(c) ('0'<=(c)&&(c)<='9')
// upto 99
#define RUBY_VERSION__number_len(v, ofs) \
    (!RUBY_VERSION_isdigit((v)[ofs]) ? \
     0 : !RUBY_VERSION_isdigit((v)[(ofs) + 1]) ? 1 : 2)
#define RUBY_VERSION__to_number(v, ofs) \
    (!RUBY_VERSION_isdigit((v)[ofs]) ? \
     0 : !RUBY_VERSION_isdigit((v)[(ofs) + 1]) ? \
     ((v)[ofs]-'0') : \
     (((v)[ofs]-'0')*10+(v)[(ofs)+1]-'0'))

#define RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v) \
    (RUBY_VERSION__to_number(v, 0) * 10000 + \
     ((v)[RUBY_VERSION__number_len(v, 0)] == '.' ? \
      RUBY_VERSION__to_number(v, RUBY_VERSION__number_len(v, 0)+1) * 100 : 0))
#define RUBY_VERSION_STRING_SINCE(v) (RUBY_API_VERSION_CODE >= RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v))
#define RUBY_VERSION_STRING_BEFORE(v) (RUBY_API_VERSION_CODE < RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v))

# if RBIMPL_HAS_ATTRIBUTE(diagnose_if)
RBIMPL_ATTR_FORCEINLINE()
static void
rb_deprecated_method_to_be_removed(const char *removal)
    RBIMPL_ATTR_DIAGNOSE_IF(!RUBY_VERSION_isdigit(removal[0]), "malformed version number", "error")
    RBIMPL_ATTR_DIAGNOSE_IF(RUBY_VERSION_STRING_SINCE(removal), "deprecated method to be removed", "error")
{
}
# else
RBIMPL_ATTR_ERROR(("deprecated"))
void rb_deprecated_method_to_be_removed(const char *);
#   define rb_deprecated_method_to_be_removed(removal) \
    (sizeof(char[1-2*(!RUBY_VERSION_isdigit(removal[0]) || RUBY_VERSION_STRING_SINCE(removal))])!=1 ? \
     rb_deprecated_method_to_be_removed(removal) : \
     RBIMPL_ASSERT_NOTHING)
# endif
# define rb_warn_deprecated_to_remove_at(removal, ...) \
    (rb_deprecated_method_to_be_removed(#removal), \
     rb_warn_deprecated_to_remove(#removal, __VA_ARGS__))
# endif
#endif
#ifndef rb_warn_deprecated_to_remove_at
# define rb_warn_deprecated_to_remove_at(removal, ...) \
        rb_warn_deprecated_to_remove(#removal, __VA_ARGS__)
#endif
#ifndef RUBY_VERSION_SINCE
# define RUBY_VERSION_SINCE(major, minor) 0
#endif
#ifndef RUBY_VERSION_BEFORE
# define RUBY_VERSION_BEFORE(major, minor) 0
#endif
#ifndef RBIMPL_TODO0
# define RBIMPL_TODO0(x)
#endif
#define RBIMPL_TODO(message) RBIMPL_TODO0("TODO: " message)
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 6, 0)
VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list);
PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3);
PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3);
PRINTF_ARGS(void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...), 3, 4);
rb_warning_category_t rb_warning_category_from_name(VALUE category);
bool rb_warning_category_enabled_p(rb_warning_category_t category);
VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method);
VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv);
VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name);
PRINTF_ARGS(VALUE rb_warning_string(const char *fmt, ...), 1, 2);
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
NORETURN(void rb_vraise(VALUE, const char *, va_list));
NORETURN(static inline void rb_raise_cstr(VALUE etype, const char *mesg));
NORETURN(static inline void rb_raise_cstr_i(VALUE etype, VALUE mesg));
NORETURN(static inline void rb_name_err_raise_str(VALUE mesg, VALUE recv, VALUE name));
NORETURN(static inline void rb_name_err_raise(const char *mesg, VALUE recv, VALUE name));
NORETURN(static inline void rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name));
static inline void Check_Type(VALUE v, enum ruby_value_type t);
static inline bool rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type);
#define rb_typeddata_is_instance_of rb_typeddata_is_instance_of_inline

RUBY_SYMBOL_EXPORT_BEGIN
/* error.c (export) */
int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
#ifdef RUBY_FUNCTION_NAME_STRING
NORETURN(void rb_sys_fail_path_in(const char *func_name, VALUE path));
NORETURN(void rb_syserr_fail_path_in(const char *func_name, int err, VALUE path));
VALUE rb_syserr_new_path_in(const char *func_name, int n, VALUE path);
#endif
RUBY_SYMBOL_EXPORT_END

static inline void
rb_raise_cstr_i(VALUE etype, VALUE mesg)
{
    VALUE exc = rb_exc_new_str(etype, mesg);
    rb_exc_raise(exc);
}

static inline void
rb_raise_cstr(VALUE etype, const char *mesg)
{
    VALUE str = rb_str_new_cstr(mesg);
    rb_raise_cstr_i(etype, str);
}

static inline void
rb_name_err_raise_str(VALUE mesg, VALUE recv, VALUE name)
{
    VALUE exc = rb_name_err_new(mesg, recv, name);
    rb_exc_raise(exc);
}

static inline void
rb_name_err_raise(const char *mesg, VALUE recv, VALUE name)
{
    VALUE str = rb_fstring_cstr(mesg);
    rb_name_err_raise_str(str, recv, name);
}

static inline void
rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name)
{
    VALUE exc = rb_key_err_new(mesg, recv, name);
    rb_exc_raise(exc);
}

static inline bool
rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type)
{
    return RB_TYPE_P(obj, T_DATA) && RTYPEDDATA_P(obj) && (RTYPEDDATA_TYPE(obj) == data_type);
}

#endif /* INTERNAL_ERROR_H */