summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c18
-rw-r--r--include/ruby/backward/cxxanyargs.hpp376
-rw-r--r--include/ruby/ruby.h5
-rw-r--r--template/Doxyfile.tmpl2
-rwxr-xr-xtool/rbinstall.rb4
5 files changed, 399 insertions, 6 deletions
diff --git a/eval.c b/eval.c
index eb34c35f01..1b62498f36 100644
--- a/eval.c
+++ b/eval.c
@@ -948,12 +948,26 @@ VALUE
rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
VALUE (* r_proc) (VALUE, VALUE), VALUE data2, ...)
{
+ va_list ap;
+ va_start(ap, data2);
+ return rb_vrescue2(b_proc, data1, r_proc, data2, ap);
+ va_end(ap);
+}
+
+/*!
+ * \copydoc rb_rescue2
+ * \param[in] args exception classes, terminated by 0.
+ */
+VALUE
+rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
+ VALUE (* r_proc) (VALUE, VALUE), VALUE data2,
+ va_list args)
+{
enum ruby_tag_type state;
rb_execution_context_t * volatile ec = GET_EC();
rb_control_frame_t *volatile cfp = ec->cfp;
volatile VALUE result = Qfalse;
volatile VALUE e_info = ec->errinfo;
- va_list args;
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
@@ -976,14 +990,12 @@ rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
int handle = FALSE;
VALUE eclass;
- va_init_list(args, data2);
while ((eclass = va_arg(args, VALUE)) != 0) {
if (rb_obj_is_kind_of(ec->errinfo, eclass)) {
handle = TRUE;
break;
}
}
- va_end(args);
if (handle) {
result = Qnil;
diff --git a/include/ruby/backward/cxxanyargs.hpp b/include/ruby/backward/cxxanyargs.hpp
new file mode 100644
index 0000000000..70191a91d0
--- /dev/null
+++ b/include/ruby/backward/cxxanyargs.hpp
@@ -0,0 +1,376 @@
+#ifndef RUBY_BACKWARD_CXXANYARGS_HPP // -*- C++ -*-
+#define RUBY_BACKWARD_CXXANYARGS_HPP
+/// @file
+/// @brief Provides old prototypes for C++ programs.
+/// @author \@shyouhei
+/// @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.
+/// @note DO NOT MODERNIZE THIS FILE! As the file name implies it is
+/// meant to be a backwards compatibility shim. Please stick to
+/// C++ 98 and never use newer features, like `constexpr`.
+
+/// @brief The main namespace.
+/// @note The name "ruby" might already be taken, but that must not be a
+/// problem because namespaces are allowed to reopen.
+namespace ruby {
+
+/// @brief Backwards compatibility layer.
+namespace backward {
+
+/// @brief Provides ANYARGS deprecation warnings.
+///
+/// In C, ANYARGS means there is no function prototype. Literally anything,
+/// even including nothing, can be a valid ANYARGS. So passing a correctly
+/// prototyped function pointer to an ANYARGS-ed function parameter is valid,
+/// at the same time passing an ANYARGS-ed function pointer to a granular typed
+/// function parameter is also valid. However on the other hand in C++,
+/// ANYARGS doesn't actually mean any number of arguments. C++'s ANYARGS means
+/// _variadic_ number of arguments. This is incompatible with ordinal, correct
+/// function prototypes.
+///
+/// Luckily, function prototypes being distinct each other means they can be
+/// overloaded. We can provide a compatibility layer for older Ruby APIs which
+/// used to have ANYARGS. This namespace includes such attempts.
+namespace cxxanyargs {
+
+/// @brief ANYARGS-ed function type.
+typedef VALUE type(ANYARGS);
+
+/// @brief ANYARGS-ed function type, void variant.
+typedef void void_type(ANYARGS);
+
+/// @brief ANYARGS-ed function type, int variant.
+typedef int int_type(ANYARGS);
+
+/// @name Hooking global variables
+/// @{
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Define a function-backended global variable.
+/// @param[in] q Name of the variable.
+/// @param[in] w Getter function.
+/// @param[in] e Setter function.
+/// @note Both functions can be nullptr.
+/// @see rb_define_hooked_variable()
+/// @deprecated Use glanular typed overload instead.
+inline void
+rb_define_virtual_variable(const char *q, type *w, void_type *e)
+{
+ rb_gvar_getter_t *r = reinterpret_cast<rb_gvar_getter_t*>(w);
+ rb_gvar_setter_t *t = reinterpret_cast<rb_gvar_setter_t*>(e);
+ ::rb_define_virtual_variable(q, r, t);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Define a function-backended global variable.
+/// @param[in] q Name of the variable.
+/// @param[in] w Variable storage.
+/// @param[in] e Getter function.
+/// @param[in] r Setter function.
+/// @note Both functions can be nullptr.
+/// @see rb_define_virtual_variable()
+/// @deprecated Use glanular typed overload instead.
+inline void
+rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
+{
+ rb_gvar_getter_t *t = reinterpret_cast<rb_gvar_getter_t*>(e);
+ rb_gvar_setter_t *y = reinterpret_cast<rb_gvar_setter_t*>(r);
+ ::rb_define_hooked_variable(q, w, t, y);
+}
+
+/// @}
+/// @name Exceptions and tag jumps
+/// @{
+
+DEPRECATED_BY(::rb_block_call,)
+/// @brief Old way to implement iterators.
+/// @param[in] q A function that can yield.
+/// @param[in] w Passed to `q`.
+/// @param[in] e What is to be yielded.
+/// @param[in] r Passed to `e`.
+/// @return The return value of `q`.
+/// @note `e` can be nullptr.
+/// @deprecated This function is obsolated since long before 2.x era. Do not
+/// use it any longer. rb_block_call() is provided instead.
+inline VALUE
+rb_iterate(VALUE(*q)(VALUE), VALUE w, type *e, VALUE r)
+{
+ rb_block_call_func_t t = reinterpret_cast<rb_block_call_func_t>(e);
+ return ::rb_iterate(q, w, t, r);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Call a method with a block.
+/// @param[in] q The self.
+/// @param[in] w The method.
+/// @param[in] e The 3 of elems of `r`
+/// @param[in] r The arguments.
+/// @param[in] t What is to be yielded.
+/// @param[in] y Passed to `t`
+/// @return Return value of `q#w(*r,&t)`
+/// @note 't' can be nullptr.
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
+{
+ rb_block_call_func_t u = reinterpret_cast<rb_block_call_func_t>(t);
+ return ::rb_block_call(q, w, e, r, u, y);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief An equivalent of `rescue` clause.
+/// @param[in] q A function that can raise.
+/// @param[in] w Passed to `q`.
+/// @param[in] e A function that cleans-up.
+/// @param[in] r Passed to `e`.
+/// @return The return value of `q` if no exception occurs, or the return
+/// value of `e` if otherwise.
+/// @note `e` can be nullptr.
+/// @see rb_ensure()
+/// @see rb_rescue2()
+/// @see rb_protect()
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_rescue(type *q, VALUE w, type *e, VALUE r)
+{
+ typedef VALUE func1_t(VALUE);
+ typedef VALUE func2_t(VALUE, VALUE);
+ func1_t *t = reinterpret_cast<func1_t*>(q);
+ func2_t *y = reinterpret_cast<func2_t*>(e);
+ return ::rb_rescue(t, w, y, r);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief An equivalent of `rescue` clause.
+/// @param[in] q A function that can raise.
+/// @param[in] w Passed to `q`.
+/// @param[in] e A function that cleans-up.
+/// @param[in] r Passed to `e`.
+/// @param[in] ... 0-terminated list of subclass of @ref rb_eException.
+/// @return The return value of `q` if no exception occurs, or the return
+/// value of `e` if otherwise.
+/// @note `e` can be nullptr.
+/// @see rb_ensure()
+/// @see rb_rescue()
+/// @see rb_protect()
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_rescue2(type *q, VALUE w, type *e, VALUE r, ...)
+{
+ typedef VALUE func1_t(VALUE);
+ typedef VALUE func2_t(VALUE, VALUE);
+ func1_t *t = reinterpret_cast<func1_t*>(q);
+ func2_t *y = reinterpret_cast<func2_t*>(e);
+ va_list ap;
+ va_start(ap, r);
+ return ::rb_vrescue2(t, w, y, r, ap);
+ va_end(ap);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief An equivalent of `ensure` clause.
+/// @param[in] q A function that can raise.
+/// @param[in] w Passed to `q`.
+/// @param[in] e A function that ensures.
+/// @param[in] r Passed to `e`.
+/// @return The return value of `q`.
+/// @note It makes no sense to pass nullptr to `e`.
+/// @see rb_rescue()
+/// @see rb_rescue2()
+/// @see rb_protect()
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_ensure(type *q, VALUE w, type *e, VALUE r)
+{
+ typedef VALUE func1_t(VALUE);
+ func1_t *t = reinterpret_cast<func1_t*>(q);
+ func1_t *y = reinterpret_cast<func1_t*>(e);
+ return ::rb_ensure(t, w, y, r);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief An equivalent of `Kernel#catch`.
+/// @param[in] q The "tag" string.
+/// @param[in] w A function that can throw.
+/// @param[in] e Passed to `w`.
+/// @return What was thrown.
+/// @note `q` can be a nullptr but makes no sense to pass nullptr to`w`.
+/// @see rb_block_call()
+/// @see rb_protect()
+/// @see rb_rb_catch_obj()
+/// @see rb_rescue()
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_catch(const char *q, type *w, VALUE e)
+{
+ rb_block_call_func_t r = reinterpret_cast<rb_block_call_func_t>(w);
+ return ::rb_catch(q, r, e);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief An equivalent of `Kernel#catch`.
+/// @param[in] q The "tag" object.
+/// @param[in] w A function that can throw.
+/// @param[in] e Passed to `w`.
+/// @return What was thrown.
+/// @note It makes no sense to pass nullptr to`w`.
+/// @see rb_block_call()
+/// @see rb_protect()
+/// @see rb_rb_catch_obj()
+/// @see rb_rescue()
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_catch_obj(VALUE q, type *w, VALUE e)
+{
+ rb_block_call_func_t r = reinterpret_cast<rb_block_call_func_t>(w);
+ return ::rb_catch_obj(q, r, e);
+}
+
+/// @}
+/// @name Procs, Fibers and Threads
+/// @{
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Creates a @ref rb_cFiber instance.
+/// @param[in] q The fiber body.
+/// @param[in] w Passed to `q`.
+/// @return What was allocated.
+/// @note It makes no sense to pass nullptr to`q`.
+/// @see rb_proc_new()
+/// @see rb_thread_creatr()
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_fiber_new(type *q, VALUE w)
+{
+ rb_block_call_func_t e = reinterpret_cast<rb_block_call_func_t>(q);
+ return ::rb_fiber_new(e, w);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Creates a @ref rb_cProc instance.
+/// @param[in] q The proc body.
+/// @param[in] w Passed to `q`.
+/// @return What was allocated.
+/// @note It makes no sense to pass nullptr to`q`.
+/// @see rb_fiber_new()
+/// @see rb_thread_creatr()
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_proc_new(type *q, VALUE w)
+{
+ rb_block_call_func_t e = reinterpret_cast<rb_block_call_func_t>(q);
+ return ::rb_proc_new(e, w);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Creates a @ref rb_cThread instance.
+/// @param[in] q The thread body.
+/// @param[in] w Passed to `q`.
+/// @return What was allocated.
+/// @note It makes no sense to pass nullptr to`q`.
+/// @see rb_proc_new()
+/// @see rb_fiber_new()
+/// @deprecated Use glanular typed overload instead.
+inline VALUE
+rb_thread_create(type *q, void *w)
+{
+ typedef VALUE ptr_t(void*);
+ ptr_t *e = reinterpret_cast<ptr_t*>(q);
+ return ::rb_thread_create(e, w);
+}
+
+/// @}
+/// @name Hash and st_table
+/// @{
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Iteration over the given table.
+/// @param[in] q A table to scan.
+/// @param[in] w A function to iterate.
+/// @param[in] e Passed to `w`.
+/// @retval 0 Always returns 0.
+/// @note It makes no sense to pass nullptr to`w`.
+/// @see st_foreach_check()
+/// @see rb_hash_foreach()
+/// @deprecated Use glanular typed overload instead.
+inline int
+st_foreach(st_table *q, int_type *w, st_data_t e)
+{
+ st_foreach_callback_func *r =
+ reinterpret_cast<st_foreach_callback_func*>(w);
+ return ::st_foreach(q, r, e);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Iteration over the given table.
+/// @param[in] q A table to scan.
+/// @param[in] w A function to iterate.
+/// @param[in] e Passed to `w`.
+/// @retval 0 Successful end of iteration.
+/// @retval 1 Element removed during traversing.
+/// @note It makes no sense to pass nullptr to`w`.
+/// @see st_foreach()
+/// @deprecated Use glanular typed overload instead.
+inline int
+st_foreach_check(st_table *q, int_type *w, st_data_t e, st_data_t)
+{
+ st_foreach_check_callback_func *t =
+ reinterpret_cast<st_foreach_check_callback_func*>(w);
+ return ::st_foreach_check(q, t, e, 0);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Iteration over the given table.
+/// @param[in] q A table to scan.
+/// @param[in] w A function to iterate.
+/// @param[in] e Passed to `w`.
+/// @note It makes no sense to pass nullptr to`w`.
+/// @see st_foreach_check()
+/// @deprecated Use glanular typed overload instead.
+inline void
+st_foreach_safe(st_table *q, int_type *w, st_data_t e)
+{
+ st_foreach_callback_func *r =
+ reinterpret_cast<st_foreach_callback_func*>(w);
+ ::st_foreach_safe(q, r, e);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Iteration over the given hash.
+/// @param[in] q A hash to scan.
+/// @param[in] w A function to iterate.
+/// @param[in] e Passed to `w`.
+/// @note It makes no sense to pass nullptr to`w`.
+/// @see st_foreach()
+/// @deprecated Use glanular typed overload instead.
+inline void
+rb_hash_foreach(VALUE q, int_type *w, VALUE e)
+{
+ st_foreach_callback_func *r =
+ reinterpret_cast<st_foreach_callback_func*>(w);
+ ::rb_hash_foreach(q, r, e);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief Iteration over each instance variable of the object.
+/// @param[in] q An object.
+/// @param[in] w A function to iterate.
+/// @param[in] e Passed to `w`.
+/// @note It makes no sense to pass nullptr to`w`.
+/// @see st_foreach()
+/// @deprecated Use glanular typed overload instead.
+inline void
+rb_ivar_foreach(VALUE q, int_type *w, VALUE e)
+{
+ st_foreach_callback_func *r =
+ reinterpret_cast<st_foreach_callback_func*>(w);
+ ::rb_ivar_foreach(q, r, e);
+}
+
+/// @}
+}}}
+
+using namespace ruby::backward::cxxanyargs;
+#endif // RUBY_BACKWARD_CXXANYARGS_HPP
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 893bd2b0b0..65bcd382f2 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1968,6 +1968,7 @@ VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE);
VALUE rb_block_call(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE);
VALUE rb_rescue(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE);
VALUE rb_rescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,...);
+VALUE rb_vrescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,va_list);
VALUE rb_ensure(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE),VALUE);
VALUE rb_catch(const char*,rb_block_call_func_t,VALUE);
VALUE rb_catch_obj(VALUE,rb_block_call_func_t,VALUE);
@@ -2820,4 +2821,8 @@ __attribute__((__unused__,__weakref__("rb_define_global_function"),__nonnull__(1
#endif
#endif
+#ifdef __cplusplus
+#include "backward/cxxanyargs.hpp"
+#endif
+
#endif /* RUBY_RUBY_H */
diff --git a/template/Doxyfile.tmpl b/template/Doxyfile.tmpl
index 0f7675381d..2fc882edd9 100644
--- a/template/Doxyfile.tmpl
+++ b/template/Doxyfile.tmpl
@@ -102,7 +102,7 @@ WARN_LOGFILE =
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT_ENCODING = UTF-8
-FILE_PATTERNS = *.c *.h *.y *.def
+FILE_PATTERNS = *.c *.h *.hpp *.y *.def
RECURSIVE = YES
EXCLUDE = <%=srcdir%>/ext/dl/callback <%=srcdir%>/ccan <%=srcdir%>/ext/psych/yaml
EXCLUDE_SYMLINKS = YES
diff --git a/tool/rbinstall.rb b/tool/rbinstall.rb
index a316e07e79..0475901646 100755
--- a/tool/rbinstall.rb
+++ b/tool/rbinstall.rb
@@ -253,7 +253,7 @@ def install_recursive(srcdir, dest, options = {})
elsif stat.symlink?
# skip
else
- files << [src, d, false] if File.fnmatch?(glob, f) and !skip[f]
+ files << [src, d, false] if File.fnmatch?(glob, f, File::FNM_EXTGLOB) and !skip[f]
end
end
paths.insert(0, *files)
@@ -576,7 +576,7 @@ install?(:local, :comm, :hdr, :'comm-hdr') do
noinst << "win32.h"
end
noinst = nil if noinst.empty?
- install_recursive(File.join(srcdir, "include"), rubyhdrdir, :no_install => noinst, :glob => "*.h", :mode => $data_mode)
+ install_recursive(File.join(srcdir, "include"), rubyhdrdir, :no_install => noinst, :glob => "*.{h,hpp}", :mode => $data_mode)
end
install?(:local, :comm, :man) do