aboutsummaryrefslogtreecommitdiffstats
path: root/spec/rubyspec/optional/capi/ext
diff options
context:
space:
mode:
Diffstat (limited to 'spec/rubyspec/optional/capi/ext')
-rw-r--r--spec/rubyspec/optional/capi/ext/.gitignore9
-rw-r--r--spec/rubyspec/optional/capi/ext/array_spec.c452
-rw-r--r--spec/rubyspec/optional/capi/ext/bignum_spec.c149
-rw-r--r--spec/rubyspec/optional/capi/ext/boolean_spec.c34
-rw-r--r--spec/rubyspec/optional/capi/ext/class_id_under_autoload_spec.c5
-rw-r--r--spec/rubyspec/optional/capi/ext/class_spec.c261
-rw-r--r--spec/rubyspec/optional/capi/ext/class_under_autoload_spec.c5
-rw-r--r--spec/rubyspec/optional/capi/ext/complex_spec.c76
-rw-r--r--spec/rubyspec/optional/capi/ext/constants_spec.c646
-rw-r--r--spec/rubyspec/optional/capi/ext/data_spec.c97
-rw-r--r--spec/rubyspec/optional/capi/ext/encoding_spec.c424
-rw-r--r--spec/rubyspec/optional/capi/ext/enumerator_spec.c27
-rw-r--r--spec/rubyspec/optional/capi/ext/exception_spec.c72
-rw-r--r--spec/rubyspec/optional/capi/ext/file_spec.c44
-rw-r--r--spec/rubyspec/optional/capi/ext/fixnum_spec.c36
-rw-r--r--spec/rubyspec/optional/capi/ext/float_spec.c54
-rw-r--r--spec/rubyspec/optional/capi/ext/gc_spec.c61
-rw-r--r--spec/rubyspec/optional/capi/ext/globals_spec.c199
-rw-r--r--spec/rubyspec/optional/capi/ext/hash_spec.c208
-rw-r--r--spec/rubyspec/optional/capi/ext/integer_spec.c40
-rw-r--r--spec/rubyspec/optional/capi/ext/io_spec.c296
-rw-r--r--spec/rubyspec/optional/capi/ext/jruby.h10
-rw-r--r--spec/rubyspec/optional/capi/ext/kernel_spec.c404
-rw-r--r--spec/rubyspec/optional/capi/ext/marshal_spec.c36
-rw-r--r--spec/rubyspec/optional/capi/ext/module_spec.c252
-rw-r--r--spec/rubyspec/optional/capi/ext/module_under_autoload_spec.c7
-rw-r--r--spec/rubyspec/optional/capi/ext/mutex_spec.c91
-rw-r--r--spec/rubyspec/optional/capi/ext/numeric_spec.c166
-rw-r--r--spec/rubyspec/optional/capi/ext/object_spec.c608
-rw-r--r--spec/rubyspec/optional/capi/ext/proc_spec.c65
-rw-r--r--spec/rubyspec/optional/capi/ext/range_spec.c47
-rw-r--r--spec/rubyspec/optional/capi/ext/rational_spec.c95
-rw-r--r--spec/rubyspec/optional/capi/ext/regexp_spec.c84
-rw-r--r--spec/rubyspec/optional/capi/ext/rubinius.h8
-rw-r--r--spec/rubyspec/optional/capi/ext/rubyspec.h612
-rw-r--r--spec/rubyspec/optional/capi/ext/string_spec.c664
-rw-r--r--spec/rubyspec/optional/capi/ext/struct_spec.c131
-rw-r--r--spec/rubyspec/optional/capi/ext/symbol_spec.c138
-rw-r--r--spec/rubyspec/optional/capi/ext/thread_spec.c181
-rw-r--r--spec/rubyspec/optional/capi/ext/time_spec.c127
-rw-r--r--spec/rubyspec/optional/capi/ext/truffleruby.h6
-rw-r--r--spec/rubyspec/optional/capi/ext/typed_data_spec.c177
-rw-r--r--spec/rubyspec/optional/capi/ext/util_spec.c95
43 files changed, 7199 insertions, 0 deletions
diff --git a/spec/rubyspec/optional/capi/ext/.gitignore b/spec/rubyspec/optional/capi/ext/.gitignore
new file mode 100644
index 0000000000..577d117bb1
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/.gitignore
@@ -0,0 +1,9 @@
+# signature of implementation that
+# last compiled an extension
+*.sig
+
+# build artifacts
+*.o
+*.so
+*.bundle
+*.dll
diff --git a/spec/rubyspec/optional/capi/ext/array_spec.c b/spec/rubyspec/optional/capi/ext/array_spec.c
new file mode 100644
index 0000000000..8bc144195c
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/array_spec.c
@@ -0,0 +1,452 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_ARRAY
+static VALUE array_spec_rb_Array(VALUE self, VALUE object) {
+ return rb_Array(object);
+}
+#endif
+
+#if defined(HAVE_RARRAY_LEN) && defined(HAVE_RARRAY_PTR)
+static VALUE array_spec_RARRAY_PTR_iterate(VALUE self, VALUE array) {
+ int i;
+ VALUE* ptr;
+
+ ptr = RARRAY_PTR(array);
+ for(i = 0; i < RARRAY_LEN(array); i++) {
+ rb_yield(ptr[i]);
+ }
+ return Qnil;
+}
+
+static VALUE array_spec_RARRAY_PTR_assign(VALUE self, VALUE array, VALUE value) {
+ int i;
+ VALUE* ptr;
+
+ ptr = RARRAY_PTR(array);
+ for(i = 0; i < RARRAY_LEN(array); i++) {
+ ptr[i] = value;
+ }
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RARRAY_LEN
+static VALUE array_spec_RARRAY_LEN(VALUE self, VALUE array) {
+ return INT2FIX(RARRAY_LEN(array));
+}
+#endif
+
+#ifdef HAVE_RARRAY_AREF
+static VALUE array_spec_RARRAY_AREF(VALUE self, VALUE array, VALUE index) {
+ return RARRAY_AREF(array, FIX2INT(index));
+}
+#endif
+
+#ifdef HAVE_RB_ARY_AREF
+static VALUE array_spec_rb_ary_aref(int argc, VALUE *argv, VALUE self) {
+ VALUE ary, args;
+ rb_scan_args(argc, argv, "1*", &ary, &args);
+ return rb_ary_aref((int)RARRAY_LEN(args), RARRAY_PTR(args), ary);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_CLEAR
+static VALUE array_spec_rb_ary_clear(VALUE self, VALUE array) {
+ return rb_ary_clear(array);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_DELETE
+static VALUE array_spec_rb_ary_delete(VALUE self, VALUE array, VALUE item) {
+ return rb_ary_delete(array, item);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_DELETE_AT
+static VALUE array_spec_rb_ary_delete_at(VALUE self, VALUE array, VALUE index) {
+ return rb_ary_delete_at(array, NUM2LONG(index));
+}
+#endif
+
+#ifdef HAVE_RB_ARY_DUP
+static VALUE array_spec_rb_ary_dup(VALUE self, VALUE array) {
+ return rb_ary_dup(array);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_ENTRY
+static VALUE array_spec_rb_ary_entry(VALUE self, VALUE array, VALUE offset) {
+ return rb_ary_entry(array, FIX2INT(offset));
+}
+#endif
+
+#ifdef HAVE_RB_ARY_INCLUDES
+static VALUE array_spec_rb_ary_includes(VALUE self, VALUE ary, VALUE item) {
+ return rb_ary_includes(ary, item);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_JOIN
+static VALUE array_spec_rb_ary_join(VALUE self, VALUE array1, VALUE array2) {
+ return rb_ary_join(array1, array2);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_TO_S
+static VALUE array_spec_rb_ary_to_s(VALUE self, VALUE array) {
+ return rb_ary_to_s(array);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_NEW
+static VALUE array_spec_rb_ary_new(VALUE self) {
+ VALUE ret;
+ ret = rb_ary_new();
+ return ret;
+}
+#endif
+
+#ifdef HAVE_RB_ARY_NEW2
+static VALUE array_spec_rb_ary_new2(VALUE self, VALUE length) {
+ return rb_ary_new2(NUM2LONG(length));
+}
+#endif
+
+#ifdef HAVE_RB_ARY_NEW_CAPA
+static VALUE array_spec_rb_ary_new_capa(VALUE self, VALUE length) {
+ return rb_ary_new_capa(NUM2LONG(length));
+}
+#endif
+
+#ifdef HAVE_RB_ARY_NEW3
+static VALUE array_spec_rb_ary_new3(VALUE self, VALUE first, VALUE second, VALUE third) {
+ return rb_ary_new3(3, first, second, third);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_NEW_FROM_ARGS
+static VALUE array_spec_rb_ary_new_from_args(VALUE self, VALUE first, VALUE second, VALUE third) {
+ return rb_ary_new_from_args(3, first, second, third);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_NEW4
+static VALUE array_spec_rb_ary_new4(VALUE self, VALUE first, VALUE second, VALUE third) {
+ VALUE values[3];
+ values[0] = first;
+ values[1] = second;
+ values[2] = third;
+ return rb_ary_new4(3, values);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_NEW_FROM_VALUES
+static VALUE array_spec_rb_ary_new_from_values(VALUE self, VALUE first, VALUE second, VALUE third) {
+ VALUE values[3];
+ values[0] = first;
+ values[1] = second;
+ values[2] = third;
+ return rb_ary_new_from_values(3, values);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_POP
+static VALUE array_spec_rb_ary_pop(VALUE self, VALUE array) {
+ return rb_ary_pop(array);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_PUSH
+static VALUE array_spec_rb_ary_push(VALUE self, VALUE array, VALUE item) {
+ rb_ary_push(array, item);
+ return array;
+}
+#endif
+
+#ifdef HAVE_RB_ARY_CAT
+static VALUE array_spec_rb_ary_cat(int argc, VALUE *argv, VALUE self) {
+ VALUE ary, args;
+ rb_scan_args(argc, argv, "1*", &ary, &args);
+ return rb_ary_cat(ary, RARRAY_PTR(args), RARRAY_LEN(args));
+}
+#endif
+
+#ifdef HAVE_RB_ARY_REVERSE
+static VALUE array_spec_rb_ary_reverse(VALUE self, VALUE array) {
+ return rb_ary_reverse(array);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_ROTATE
+static VALUE array_spec_rb_ary_rotate(VALUE self, VALUE array, VALUE count) {
+ return rb_ary_rotate(array, NUM2LONG(count));
+}
+#endif
+
+#ifdef HAVE_RB_ARY_SHIFT
+static VALUE array_spec_rb_ary_shift(VALUE self, VALUE array) {
+ return rb_ary_shift(array);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_STORE
+static VALUE array_spec_rb_ary_store(VALUE self, VALUE array, VALUE offset, VALUE value) {
+ rb_ary_store(array, FIX2INT(offset), value);
+
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_ARY_CONCAT
+static VALUE array_spec_rb_ary_concat(VALUE self, VALUE array1, VALUE array2) {
+ return rb_ary_concat(array1, array2);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_PLUS
+static VALUE array_spec_rb_ary_plus(VALUE self, VALUE array1, VALUE array2) {
+ return rb_ary_plus(array1, array2);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_UNSHIFT
+static VALUE array_spec_rb_ary_unshift(VALUE self, VALUE array, VALUE val) {
+ return rb_ary_unshift(array, val);
+}
+#endif
+
+#ifdef HAVE_RB_ASSOC_NEW
+static VALUE array_spec_rb_assoc_new(VALUE self, VALUE first, VALUE second) {
+ return rb_assoc_new(first, second);
+}
+#endif
+
+#if defined(HAVE_RB_ITERATE) && defined(HAVE_RB_EACH)
+static VALUE copy_ary(VALUE el, VALUE new_ary) {
+ return rb_ary_push(new_ary, el);
+}
+
+static VALUE array_spec_rb_iterate(VALUE self, VALUE ary) {
+ VALUE new_ary = rb_ary_new();
+
+ rb_iterate(rb_each, ary, copy_ary, new_ary);
+
+ return new_ary;
+}
+
+static VALUE sub_pair(VALUE el, VALUE holder) {
+ return rb_ary_push(holder, rb_ary_entry(el, 1));
+}
+
+static VALUE each_pair(VALUE obj) {
+ return rb_funcall(obj, rb_intern("each_pair"), 0);
+}
+
+static VALUE array_spec_rb_iterate_each_pair(VALUE self, VALUE obj) {
+ VALUE new_ary = rb_ary_new();
+
+ rb_iterate(each_pair, obj, sub_pair, new_ary);
+
+ return new_ary;
+}
+
+static VALUE iter_yield(VALUE el, VALUE ary) {
+ rb_yield(el);
+ return Qnil;
+}
+
+static VALUE array_spec_rb_iterate_then_yield(VALUE self, VALUE obj) {
+ rb_iterate(rb_each, obj, iter_yield, obj);
+ return Qnil;
+}
+#endif
+
+#if defined(HAVE_RB_MEM_CLEAR)
+static VALUE array_spec_rb_mem_clear(VALUE self, VALUE obj) {
+ VALUE ary[1];
+ ary[0] = obj;
+ rb_mem_clear(ary, 1);
+ return ary[0];
+}
+#endif
+
+#ifdef HAVE_RB_ARY_FREEZE
+static VALUE array_spec_rb_ary_freeze(VALUE self, VALUE ary) {
+ return rb_ary_freeze(ary);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_TO_ARY
+static VALUE array_spec_rb_ary_to_ary(VALUE self, VALUE ary) {
+ return rb_ary_to_ary(ary);
+}
+#endif
+
+#ifdef HAVE_RB_ARY_SUBSEQ
+static VALUE array_spec_rb_ary_subseq(VALUE self, VALUE ary, VALUE begin, VALUE len) {
+ return rb_ary_subseq(ary, FIX2LONG(begin), FIX2LONG(len));
+}
+#endif
+
+void Init_array_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiArraySpecs", rb_cObject);
+
+#ifdef HAVE_RB_ARRAY
+ rb_define_method(cls, "rb_Array", array_spec_rb_Array, 1);
+#endif
+
+#ifdef HAVE_RARRAY_LEN
+ rb_define_method(cls, "RARRAY_LEN", array_spec_RARRAY_LEN, 1);
+#endif
+
+#if defined(HAVE_RARRAY_LEN) && defined(HAVE_RARRAY_PTR)
+ rb_define_method(cls, "RARRAY_PTR_iterate", array_spec_RARRAY_PTR_iterate, 1);
+ rb_define_method(cls, "RARRAY_PTR_assign", array_spec_RARRAY_PTR_assign, 2);
+#endif
+
+#ifdef HAVE_RARRAY_AREF
+ rb_define_method(cls, "RARRAY_AREF", array_spec_RARRAY_AREF, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_AREF
+ rb_define_method(cls, "rb_ary_aref", array_spec_rb_ary_aref, -1);
+#endif
+
+#ifdef HAVE_RB_ARY_CLEAR
+ rb_define_method(cls, "rb_ary_clear", array_spec_rb_ary_clear, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_DELETE
+ rb_define_method(cls, "rb_ary_delete", array_spec_rb_ary_delete, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_DELETE_AT
+ rb_define_method(cls, "rb_ary_delete_at", array_spec_rb_ary_delete_at, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_DUP
+ rb_define_method(cls, "rb_ary_dup", array_spec_rb_ary_dup, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_ENTRY
+ rb_define_method(cls, "rb_ary_entry", array_spec_rb_ary_entry, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_INCLUDES
+ rb_define_method(cls, "rb_ary_includes", array_spec_rb_ary_includes, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_JOIN
+ rb_define_method(cls, "rb_ary_join", array_spec_rb_ary_join, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_TO_S
+ rb_define_method(cls, "rb_ary_to_s", array_spec_rb_ary_to_s, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_NEW
+ rb_define_method(cls, "rb_ary_new", array_spec_rb_ary_new, 0);
+#endif
+
+#ifdef HAVE_RB_ARY_NEW2
+ rb_define_method(cls, "rb_ary_new2", array_spec_rb_ary_new2, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_NEW_CAPA
+ rb_define_method(cls, "rb_ary_new_capa", array_spec_rb_ary_new_capa, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_NEW3
+ rb_define_method(cls, "rb_ary_new3", array_spec_rb_ary_new3, 3);
+#endif
+
+#ifdef HAVE_RB_ARY_NEW_FROM_ARGS
+ rb_define_method(cls, "rb_ary_new_from_args", array_spec_rb_ary_new_from_args, 3);
+#endif
+
+#ifdef HAVE_RB_ARY_NEW4
+ rb_define_method(cls, "rb_ary_new4", array_spec_rb_ary_new4, 3);
+#endif
+
+#ifdef HAVE_RB_ARY_NEW_FROM_VALUES
+ rb_define_method(cls, "rb_ary_new_from_values", array_spec_rb_ary_new_from_values, 3);
+#endif
+
+#ifdef HAVE_RB_ARY_POP
+ rb_define_method(cls, "rb_ary_pop", array_spec_rb_ary_pop, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_PUSH
+ rb_define_method(cls, "rb_ary_push", array_spec_rb_ary_push, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_CAT
+ rb_define_method(cls, "rb_ary_cat", array_spec_rb_ary_cat, -1);
+#endif
+
+#ifdef HAVE_RB_ARY_REVERSE
+ rb_define_method(cls, "rb_ary_reverse", array_spec_rb_ary_reverse, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_ROTATE
+ rb_define_method(cls, "rb_ary_rotate", array_spec_rb_ary_rotate, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_SHIFT
+ rb_define_method(cls, "rb_ary_shift", array_spec_rb_ary_shift, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_STORE
+ rb_define_method(cls, "rb_ary_store", array_spec_rb_ary_store, 3);
+#endif
+
+#ifdef HAVE_RB_ARY_CONCAT
+ rb_define_method(cls, "rb_ary_concat", array_spec_rb_ary_concat, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_PLUS
+ rb_define_method(cls, "rb_ary_plus", array_spec_rb_ary_plus, 2);
+#endif
+
+#ifdef HAVE_RB_ARY_UNSHIFT
+ rb_define_method(cls, "rb_ary_unshift", array_spec_rb_ary_unshift, 2);
+#endif
+
+#ifdef HAVE_RB_ASSOC_NEW
+ rb_define_method(cls, "rb_assoc_new", array_spec_rb_assoc_new, 2);
+#endif
+
+#if defined(HAVE_RB_ITERATE) && defined(HAVE_RB_EACH)
+ rb_define_method(cls, "rb_iterate", array_spec_rb_iterate, 1);
+ rb_define_method(cls, "rb_iterate_each_pair", array_spec_rb_iterate_each_pair, 1);
+ rb_define_method(cls, "rb_iterate_then_yield", array_spec_rb_iterate_then_yield, 1);
+#endif
+
+#if defined(HAVE_RB_MEM_CLEAR)
+ rb_define_method(cls, "rb_mem_clear", array_spec_rb_mem_clear, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_FREEZE
+ rb_define_method(cls, "rb_ary_freeze", array_spec_rb_ary_freeze, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_TO_ARY
+ rb_define_method(cls, "rb_ary_to_ary", array_spec_rb_ary_to_ary, 1);
+#endif
+
+#ifdef HAVE_RB_ARY_SUBSEQ
+ rb_define_method(cls, "rb_ary_subseq", array_spec_rb_ary_subseq, 3);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/bignum_spec.c b/spec/rubyspec/optional/capi/ext/bignum_spec.c
new file mode 100644
index 0000000000..ab3b36eadc
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/bignum_spec.c
@@ -0,0 +1,149 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_BIG2DBL
+static VALUE bignum_spec_rb_big2dbl(VALUE self, VALUE num) {
+ return rb_float_new(rb_big2dbl(num));
+}
+#endif
+
+#ifdef HAVE_RB_DBL2BIG
+static VALUE bignum_spec_rb_dbl2big(VALUE self, VALUE num) {
+ double dnum = NUM2DBL(num);
+
+ return rb_dbl2big(dnum);
+}
+#endif
+
+#ifdef HAVE_RB_BIG2LL
+static VALUE bignum_spec_rb_big2ll(VALUE self, VALUE num) {
+ return rb_ll2inum(rb_big2ll(num));
+}
+#endif
+
+#ifdef HAVE_RB_BIG2LONG
+static VALUE bignum_spec_rb_big2long(VALUE self, VALUE num) {
+ return LONG2NUM(rb_big2long(num));
+}
+#endif
+
+#ifdef HAVE_RB_BIG2STR
+static VALUE bignum_spec_rb_big2str(VALUE self, VALUE num, VALUE base) {
+ return rb_big2str(num, FIX2INT(base));
+}
+#endif
+
+#ifdef HAVE_RB_BIG2ULONG
+static VALUE bignum_spec_rb_big2ulong(VALUE self, VALUE num) {
+ return ULONG2NUM(rb_big2ulong(num));
+}
+#endif
+
+#ifdef HAVE_RB_BIG_CMP
+static VALUE bignum_spec_rb_big_cmp(VALUE self, VALUE x, VALUE y) {
+ return rb_big_cmp(x, y);
+}
+#endif
+
+#ifdef HAVE_RB_BIG_PACK
+static VALUE bignum_spec_rb_big_pack(VALUE self, VALUE val) {
+ unsigned long buff;
+
+ rb_big_pack(val, &buff, 1);
+
+ return ULONG2NUM(buff);
+}
+#endif
+
+#if HAVE_ABSINT_SIZE
+static VALUE bignum_spec_rb_big_pack_length(VALUE self, VALUE val) {
+ long long_len;
+ int leading_bits = 0;
+ int divisor = SIZEOF_LONG;
+ size_t len = rb_absint_size(val, &leading_bits);
+ if (leading_bits == 0) {
+ len += 1;
+ }
+
+ long_len = len / divisor + ((len % divisor == 0) ? 0 : 1);
+ return LONG2NUM(long_len);
+}
+#endif
+
+#ifdef HAVE_RB_BIG_PACK
+static VALUE bignum_spec_rb_big_pack_array(VALUE self, VALUE val, VALUE len) {
+ int i;
+ long long_len = NUM2LONG(len);
+
+ VALUE ary = rb_ary_new_capa(long_len);
+ unsigned long *buf = malloc(long_len * SIZEOF_LONG);
+
+ /* The array should be filled with recognisable junk so we can check
+ it is all cleared properly. */
+
+ for (i = 0; i < long_len; i++) {
+#if SIZEOF_LONG == 8
+ buf[i] = 0xfedcba9876543210L;
+#else
+ buf[i] = 0xfedcba98L;
+#endif
+ }
+
+ rb_big_pack(val, buf, long_len);
+ for (i = 0; i < long_len; i++) {
+ rb_ary_store(ary, i, ULONG2NUM(buf[i]));
+ }
+ free(buf);
+ return ary;
+}
+#endif
+
+void Init_bignum_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiBignumSpecs", rb_cObject);
+
+#ifdef HAVE_RB_BIG2DBL
+ rb_define_method(cls, "rb_big2dbl", bignum_spec_rb_big2dbl, 1);
+#endif
+
+#ifdef HAVE_RB_DBL2BIG
+ rb_define_method(cls, "rb_dbl2big", bignum_spec_rb_dbl2big, 1);
+#endif
+
+#ifdef HAVE_RB_BIG2LL
+ rb_define_method(cls, "rb_big2ll", bignum_spec_rb_big2ll, 1);
+#endif
+
+#ifdef HAVE_RB_BIG2LONG
+ rb_define_method(cls, "rb_big2long", bignum_spec_rb_big2long, 1);
+#endif
+
+#ifdef HAVE_RB_BIG2STR
+ rb_define_method(cls, "rb_big2str", bignum_spec_rb_big2str, 2);
+#endif
+
+#ifdef HAVE_RB_BIG2ULONG
+ rb_define_method(cls, "rb_big2ulong", bignum_spec_rb_big2ulong, 1);
+#endif
+
+#ifdef HAVE_RB_BIG_CMP
+ rb_define_method(cls, "rb_big_cmp", bignum_spec_rb_big_cmp, 2);
+#endif
+
+#ifdef HAVE_RB_BIG_PACK
+ rb_define_method(cls, "rb_big_pack", bignum_spec_rb_big_pack, 1);
+ rb_define_method(cls, "rb_big_pack_array", bignum_spec_rb_big_pack_array, 2);
+#endif
+
+#ifdef HAVE_ABSINT_SIZE
+ rb_define_method(cls, "rb_big_pack_length", bignum_spec_rb_big_pack_length, 1);
+#endif
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/boolean_spec.c b/spec/rubyspec/optional/capi/ext/boolean_spec.c
new file mode 100644
index 0000000000..94d79c0fc0
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/boolean_spec.c
@@ -0,0 +1,34 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static VALUE boolean_spec_is_true(VALUE self, VALUE boolean) {
+ if (boolean) {
+ return INT2NUM(1);
+ } else {
+ return INT2NUM(2);
+ }
+}
+
+static VALUE boolean_spec_q_true(VALUE self) {
+ return Qtrue;
+}
+
+static VALUE boolean_spec_q_false(VALUE self) {
+ return Qfalse;
+}
+
+void Init_boolean_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiBooleanSpecs", rb_cObject);
+ rb_define_method(cls, "is_true", boolean_spec_is_true, 1);
+ rb_define_method(cls, "q_true", boolean_spec_q_true, 0);
+ rb_define_method(cls, "q_false", boolean_spec_q_false, 0);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/class_id_under_autoload_spec.c b/spec/rubyspec/optional/capi/ext/class_id_under_autoload_spec.c
new file mode 100644
index 0000000000..64393a9397
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/class_id_under_autoload_spec.c
@@ -0,0 +1,5 @@
+#include "ruby.h"
+
+void Init_class_id_under_autoload_spec(void) {
+ rb_define_class_id_under(rb_cObject, rb_intern("ClassIdUnderAutoload"), rb_cObject);
+}
diff --git a/spec/rubyspec/optional/capi/ext/class_spec.c b/spec/rubyspec/optional/capi/ext/class_spec.c
new file mode 100644
index 0000000000..e3860df1da
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/class_spec.c
@@ -0,0 +1,261 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_CALL_SUPER
+static VALUE class_spec_call_super_method(VALUE self) {
+ return rb_call_super(0, 0);
+}
+
+static VALUE class_spec_define_call_super_method(VALUE self, VALUE obj, VALUE str_name) {
+ rb_define_method(obj, RSTRING_PTR(str_name), class_spec_call_super_method, 0);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_CLASS_PATH
+static VALUE class_spec_rb_class_path(VALUE self, VALUE klass) {
+ return rb_class_path(klass);
+}
+#endif
+
+#ifdef HAVE_RB_CLASS_NAME
+static VALUE class_spec_rb_class_name(VALUE self, VALUE klass) {
+ return rb_class_name(klass);
+}
+#endif
+
+#ifdef HAVE_RB_CLASS2NAME
+static VALUE class_spec_rb_class2name(VALUE self, VALUE klass) {
+ return rb_str_new2( rb_class2name(klass) );
+}
+#endif
+
+#ifdef HAVE_RB_PATH2CLASS
+static VALUE class_spec_rb_path2class(VALUE self, VALUE path) {
+ return rb_path2class(RSTRING_PTR(path));
+}
+#endif
+
+#ifdef HAVE_RB_PATH_TO_CLASS
+static VALUE class_spec_rb_path_to_class(VALUE self, VALUE path) {
+ return rb_path_to_class(path);
+}
+#endif
+
+#ifdef HAVE_RB_CLASS_NEW
+static VALUE class_spec_rb_class_new(VALUE self, VALUE super) {
+ return rb_class_new(super);
+}
+#endif
+
+#ifdef HAVE_RB_CLASS_NEW_INSTANCE
+static VALUE class_spec_rb_class_new_instance(VALUE self,
+ VALUE nargs, VALUE args,
+ VALUE klass) {
+ int c_nargs = FIX2INT(nargs);
+ VALUE *c_args = alloca(sizeof(VALUE) * c_nargs);
+ int i;
+
+ for (i = 0; i < c_nargs; i++)
+ c_args[i] = rb_ary_entry(args, i);
+
+ return rb_class_new_instance(c_nargs, c_args, klass);
+}
+#endif
+
+#ifdef HAVE_RB_CLASS_REAL
+static VALUE class_spec_rb_class_real(VALUE self, VALUE object) {
+ if(rb_type_p(object, T_FIXNUM)) {
+ return INT2FIX(rb_class_real(FIX2INT(object)));
+ } else {
+ return rb_class_real(CLASS_OF(object));
+ }
+}
+#endif
+
+#ifdef HAVE_RB_CLASS_SUPERCLASS
+static VALUE class_spec_rb_class_superclass(VALUE self, VALUE klass) {
+ return rb_class_superclass(klass);
+}
+#endif
+
+#ifdef HAVE_RB_CVAR_DEFINED
+static VALUE class_spec_cvar_defined(VALUE self, VALUE klass, VALUE id) {
+ ID as_id = rb_intern(StringValuePtr(id));
+ return rb_cvar_defined(klass, as_id);
+}
+#endif
+
+#ifdef HAVE_RB_CVAR_GET
+static VALUE class_spec_cvar_get(VALUE self, VALUE klass, VALUE name) {
+ return rb_cvar_get(klass, rb_intern(StringValuePtr(name)));
+}
+#endif
+
+#ifdef HAVE_RB_CVAR_SET
+static VALUE class_spec_cvar_set(VALUE self, VALUE klass, VALUE name, VALUE val) {
+ rb_cvar_set(klass, rb_intern(StringValuePtr(name)), val);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_CV_GET
+static VALUE class_spec_cv_get(VALUE self, VALUE klass, VALUE name) {
+ return rb_cv_get(klass, StringValuePtr(name));
+}
+#endif
+
+#ifdef HAVE_RB_CV_SET
+static VALUE class_spec_cv_set(VALUE self, VALUE klass, VALUE name, VALUE val) {
+ rb_cv_set(klass, StringValuePtr(name), val);
+
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_ATTR
+VALUE class_spec_define_attr(VALUE self, VALUE klass, VALUE sym, VALUE read, VALUE write) {
+ int int_read, int_write;
+ int_read = read == Qtrue ? 1 : 0;
+ int_write = write == Qtrue ? 1 : 0;
+ rb_define_attr(klass, rb_id2name(SYM2ID(sym)), int_read, int_write);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_CLASS
+static VALUE class_spec_rb_define_class(VALUE self, VALUE name, VALUE super) {
+ if(NIL_P(super)) super = 0;
+ return rb_define_class(RSTRING_PTR(name), super);
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_CLASS_UNDER
+static VALUE class_spec_rb_define_class_under(VALUE self, VALUE outer,
+ VALUE name, VALUE super) {
+ if(NIL_P(super)) super = 0;
+ return rb_define_class_under(outer, RSTRING_PTR(name), super);
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_CLASS_ID_UNDER
+static VALUE class_spec_rb_define_class_id_under(VALUE self, VALUE outer,
+ VALUE name, VALUE super) {
+ if(NIL_P(super)) super = 0;
+ return rb_define_class_id_under(outer, SYM2ID(name), super);
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_CLASS_VARIABLE
+static VALUE class_spec_define_class_variable(VALUE self, VALUE klass, VALUE name, VALUE val) {
+ rb_define_class_variable(klass, StringValuePtr(name), val);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_INCLUDE_MODULE
+static VALUE class_spec_include_module(VALUE self, VALUE klass, VALUE module) {
+ rb_include_module(klass, module);
+ return klass;
+}
+#endif
+
+void Init_class_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiClassSpecs", rb_cObject);
+
+#ifdef HAVE_RB_CALL_SUPER
+ rb_define_method(cls, "define_call_super_method", class_spec_define_call_super_method, 2);
+#endif
+
+#ifdef HAVE_RB_CLASS_PATH
+ rb_define_method(cls, "rb_class_path", class_spec_rb_class_path, 1);
+#endif
+
+#ifdef HAVE_RB_CLASS_NAME
+ rb_define_method(cls, "rb_class_name", class_spec_rb_class_name, 1);
+#endif
+
+#ifdef HAVE_RB_CLASS2NAME
+ rb_define_method(cls, "rb_class2name", class_spec_rb_class2name, 1);
+#endif
+
+#ifdef HAVE_RB_PATH2CLASS
+ rb_define_method(cls, "rb_path2class", class_spec_rb_path2class, 1);
+#endif
+
+#ifdef HAVE_RB_PATH_TO_CLASS
+ rb_define_method(cls, "rb_path_to_class", class_spec_rb_path_to_class, 1);
+#endif
+
+#ifdef HAVE_RB_CLASS_NEW
+ rb_define_method(cls, "rb_class_new", class_spec_rb_class_new, 1);
+#endif
+
+#ifdef HAVE_RB_CLASS_NEW_INSTANCE
+ rb_define_method(cls, "rb_class_new_instance", class_spec_rb_class_new_instance, 3);
+#endif
+
+#ifdef HAVE_RB_CLASS_REAL
+ rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1);
+#endif
+
+#ifdef HAVE_RB_CLASS_SUPERCLASS
+ rb_define_method(cls, "rb_class_superclass", class_spec_rb_class_superclass, 1);
+#endif
+
+#ifdef HAVE_RB_CVAR_DEFINED
+ rb_define_method(cls, "rb_cvar_defined", class_spec_cvar_defined, 2);
+#endif
+
+#ifdef HAVE_RB_CVAR_GET
+ rb_define_method(cls, "rb_cvar_get", class_spec_cvar_get, 2);
+#endif
+
+#ifdef HAVE_RB_CVAR_SET
+ rb_define_method(cls, "rb_cvar_set", class_spec_cvar_set, 3);
+#endif
+
+#ifdef HAVE_RB_CV_GET
+ rb_define_method(cls, "rb_cv_get", class_spec_cv_get, 2);
+#endif
+
+#ifdef HAVE_RB_CV_SET
+ rb_define_method(cls, "rb_cv_set", class_spec_cv_set, 3);
+#endif
+
+#ifdef HAVE_RB_DEFINE_ATTR
+ rb_define_method(cls, "rb_define_attr", class_spec_define_attr, 4);
+#endif
+
+#ifdef HAVE_RB_DEFINE_CLASS
+ rb_define_method(cls, "rb_define_class", class_spec_rb_define_class, 2);
+#endif
+
+#ifdef HAVE_RB_DEFINE_CLASS_UNDER
+ rb_define_method(cls, "rb_define_class_under", class_spec_rb_define_class_under, 3);
+#endif
+
+#ifdef HAVE_RB_DEFINE_CLASS_ID_UNDER
+ rb_define_method(cls, "rb_define_class_id_under", class_spec_rb_define_class_id_under, 3);
+#endif
+
+#ifdef HAVE_RB_DEFINE_CLASS_VARIABLE
+ rb_define_method(cls, "rb_define_class_variable", class_spec_define_class_variable, 3);
+#endif
+
+#ifdef HAVE_RB_INCLUDE_MODULE
+ rb_define_method(cls, "rb_include_module", class_spec_include_module, 2);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/class_under_autoload_spec.c b/spec/rubyspec/optional/capi/ext/class_under_autoload_spec.c
new file mode 100644
index 0000000000..120dec7327
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/class_under_autoload_spec.c
@@ -0,0 +1,5 @@
+#include "ruby.h"
+
+void Init_class_under_autoload_spec(void) {
+ rb_define_class_under(rb_cObject, "ClassUnderAutoload", rb_cObject);
+}
diff --git a/spec/rubyspec/optional/capi/ext/complex_spec.c b/spec/rubyspec/optional/capi/ext/complex_spec.c
new file mode 100644
index 0000000000..476bbce31c
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/complex_spec.c
@@ -0,0 +1,76 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_COMPLEX
+static VALUE complex_spec_rb_Complex(VALUE self, VALUE num, VALUE den) {
+ return rb_Complex(num, den);
+}
+#endif
+
+#ifdef HAVE_RB_COMPLEX1
+static VALUE complex_spec_rb_Complex1(VALUE self, VALUE num) {
+ return rb_Complex1(num);
+}
+#endif
+
+#ifdef HAVE_RB_COMPLEX2
+static VALUE complex_spec_rb_Complex2(VALUE self, VALUE num, VALUE den) {
+ return rb_Complex2(num, den);
+}
+#endif
+
+#ifdef HAVE_RB_COMPLEX_NEW
+static VALUE complex_spec_rb_complex_new(VALUE self, VALUE num, VALUE den) {
+ return rb_complex_new(num, den);
+}
+#endif
+
+#ifdef HAVE_RB_COMPLEX_NEW1
+static VALUE complex_spec_rb_complex_new1(VALUE self, VALUE num) {
+ return rb_complex_new1(num);
+}
+#endif
+
+#ifdef HAVE_RB_COMPLEX_NEW2
+static VALUE complex_spec_rb_complex_new2(VALUE self, VALUE num, VALUE den) {
+ return rb_complex_new2(num, den);
+}
+#endif
+
+void Init_complex_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiComplexSpecs", rb_cObject);
+
+#ifdef HAVE_RB_COMPLEX
+ rb_define_method(cls, "rb_Complex", complex_spec_rb_Complex, 2);
+#endif
+
+#ifdef HAVE_RB_COMPLEX1
+ rb_define_method(cls, "rb_Complex1", complex_spec_rb_Complex1, 1);
+#endif
+
+#ifdef HAVE_RB_COMPLEX2
+ rb_define_method(cls, "rb_Complex2", complex_spec_rb_Complex2, 2);
+#endif
+
+#ifdef HAVE_RB_COMPLEX_NEW
+ rb_define_method(cls, "rb_complex_new", complex_spec_rb_complex_new, 2);
+#endif
+
+#ifdef HAVE_RB_COMPLEX_NEW1
+ rb_define_method(cls, "rb_complex_new1", complex_spec_rb_complex_new1, 1);
+#endif
+
+#ifdef HAVE_RB_COMPLEX_NEW2
+ rb_define_method(cls, "rb_complex_new2", complex_spec_rb_complex_new2, 2);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/spec/rubyspec/optional/capi/ext/constants_spec.c b/spec/rubyspec/optional/capi/ext/constants_spec.c
new file mode 100644
index 0000000000..7751b12224
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/constants_spec.c
@@ -0,0 +1,646 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_CARRAY
+static VALUE constants_spec_rb_cArray(VALUE self) {
+ return rb_cArray;
+}
+#endif
+
+#ifdef HAVE_RB_CBIGNUM
+static VALUE constants_spec_rb_cBignum(VALUE self) {
+ return rb_cBignum;
+}
+#endif
+
+#ifdef HAVE_RB_CCLASS
+static VALUE constants_spec_rb_cClass(VALUE self) {
+ return rb_cClass;
+}
+#endif
+
+#ifdef HAVE_RB_CDATA
+static VALUE constants_spec_rb_cData(VALUE self) {
+ return rb_cData;
+}
+#endif
+
+#ifdef HAVE_RB_CFALSECLASS
+static VALUE constants_spec_rb_cFalseClass(VALUE self) {
+ return rb_cFalseClass;
+}
+#endif
+
+#ifdef HAVE_RB_CFILE
+static VALUE constants_spec_rb_cFile(VALUE self) {
+ return rb_cFile;
+}
+#endif
+
+#ifdef HAVE_RB_CFIXNUM
+static VALUE constants_spec_rb_cFixnum(VALUE self) {
+ return rb_cFixnum;
+}
+#endif
+
+#ifdef HAVE_RB_CFLOAT
+static VALUE constants_spec_rb_cFloat(VALUE self) {
+ return rb_cFloat;
+}
+#endif
+
+#ifdef HAVE_RB_CHASH
+static VALUE constants_spec_rb_cHash(VALUE self) {
+ return rb_cHash;
+}
+#endif
+
+#ifdef HAVE_RB_CINTEGER
+static VALUE constants_spec_rb_cInteger(VALUE self) {
+ return rb_cInteger;
+}
+#endif
+
+#ifdef HAVE_RB_CIO
+static VALUE constants_spec_rb_cIO(VALUE self) {
+ return rb_cIO;
+}
+#endif
+
+#ifdef HAVE_RB_CMODULE
+static VALUE constants_spec_rb_cModule(VALUE self) {
+ return rb_cModule;
+}
+#endif
+
+#ifdef HAVE_RB_CMATCH
+static VALUE constants_spec_rb_cMatch(VALUE self) {
+ return rb_cMatch;
+}
+#endif
+
+#ifdef HAVE_RB_CNILCLASS
+static VALUE constants_spec_rb_cNilClass(VALUE self) {
+ return rb_cNilClass;
+}
+#endif
+
+#ifdef HAVE_RB_CNUMERIC
+static VALUE constants_spec_rb_cNumeric(VALUE self) {
+ return rb_cNumeric;
+}
+#endif
+
+#ifdef HAVE_RB_COBJECT
+static VALUE constants_spec_rb_cObject(VALUE self) {
+ return rb_cObject;
+}
+#endif
+
+#ifdef HAVE_RB_CRANGE
+static VALUE constants_spec_rb_cRange(VALUE self) {
+ return rb_cRange;
+}
+#endif
+
+#ifdef HAVE_RB_CREGEXP
+static VALUE constants_spec_rb_cRegexp(VALUE self) {
+ return rb_cRegexp;
+}
+#endif
+
+#ifdef HAVE_RB_CSTRING
+static VALUE constants_spec_rb_cString(VALUE self) {
+ return rb_cString;
+}
+#endif
+
+#ifdef HAVE_RB_CSTRUCT
+static VALUE constants_spec_rb_cStruct(VALUE self) {
+ return rb_cStruct;
+}
+#endif
+
+#ifdef HAVE_RB_CSYMBOL
+static VALUE constants_spec_rb_cSymbol(VALUE self) {
+ return rb_cSymbol;
+}
+#endif
+
+#ifdef HAVE_RB_CTIME
+static VALUE constants_spec_rb_cTime(VALUE self) {
+ return rb_cTime;
+}
+#endif
+
+#ifdef HAVE_RB_CTHREAD
+static VALUE constants_spec_rb_cThread(VALUE self) {
+ return rb_cThread;
+}
+#endif
+
+#ifdef HAVE_RB_CTRUECLASS
+static VALUE constants_spec_rb_cTrueClass(VALUE self) {
+ return rb_cTrueClass;
+}
+#endif
+
+#ifdef HAVE_RB_CPROC
+static VALUE constants_spec_rb_cProc(VALUE self) {
+ return rb_cProc;
+}
+#endif
+
+#ifdef HAVE_RB_CMETHOD
+static VALUE constants_spec_rb_cMethod(VALUE self) {
+ return rb_cMethod;
+}
+#endif
+
+#ifdef HAVE_RB_CENUMERATOR
+static VALUE constants_spec_rb_cEnumerator(VALUE self) {
+ return rb_cEnumerator;
+}
+#endif
+
+#ifdef HAVE_RB_MCOMPARABLE
+static VALUE constants_spec_rb_mComparable(VALUE self) {
+ return rb_mComparable;
+}
+#endif
+
+#ifdef HAVE_RB_MENUMERABLE
+static VALUE constants_spec_rb_mEnumerable(VALUE self) {
+ return rb_mEnumerable;
+}
+#endif
+
+#ifdef HAVE_RB_MKERNEL
+static VALUE constants_spec_rb_mKernel(VALUE self) {
+ return rb_mKernel;
+}
+#endif
+
+#ifdef HAVE_RB_EARGERROR
+static VALUE constants_spec_rb_eArgError(VALUE self) {
+ return rb_eArgError;
+}
+#endif
+
+#ifdef HAVE_RB_EEOFERROR
+static VALUE constants_spec_rb_eEOFError(VALUE self) {
+ return rb_eEOFError;
+}
+#endif
+
+#ifdef HAVE_RB_MERRNO
+static VALUE constants_spec_rb_mErrno(VALUE self) {
+ return rb_mErrno;
+}
+#endif
+
+#ifdef HAVE_RB_EEXCEPTION
+static VALUE constants_spec_rb_eException(VALUE self) {
+ return rb_eException;
+}
+#endif
+
+#ifdef HAVE_RB_EFLOATDOMAINERROR
+static VALUE constants_spec_rb_eFloatDomainError(VALUE self) {
+ return rb_eFloatDomainError;
+}
+#endif
+
+#ifdef HAVE_RB_EINDEXERROR
+static VALUE constants_spec_rb_eIndexError(VALUE self) {
+ return rb_eIndexError;
+}
+#endif
+
+#ifdef HAVE_RB_EINTERRUPT
+static VALUE constants_spec_rb_eInterrupt(VALUE self) {
+ return rb_eInterrupt;
+}
+#endif
+
+#ifdef HAVE_RB_EIOERROR
+static VALUE constants_spec_rb_eIOError(VALUE self) {
+ return rb_eIOError;
+}
+#endif
+
+#ifdef HAVE_RB_ELOADERROR
+static VALUE constants_spec_rb_eLoadError(VALUE self) {
+ return rb_eLoadError;
+}
+#endif
+
+#ifdef HAVE_RB_ELOCALJUMPERROR
+static VALUE constants_spec_rb_eLocalJumpError(VALUE self) {
+ return rb_eLocalJumpError;
+}
+#endif
+
+#ifdef HAVE_RB_ENAMEERROR
+static VALUE constants_spec_rb_eNameError(VALUE self) {
+ return rb_eNameError;
+}
+#endif
+
+#ifdef HAVE_RB_ENOMEMERROR
+static VALUE constants_spec_rb_eNoMemError(VALUE self) {
+ return rb_eNoMemError;
+}
+#endif
+
+#ifdef HAVE_RB_ENOMETHODERROR
+static VALUE constants_spec_rb_eNoMethodError(VALUE self) {
+ return rb_eNoMethodError;
+}
+#endif
+
+#ifdef HAVE_RB_ENOTIMPERROR
+static VALUE constants_spec_rb_eNotImpError(VALUE self) {
+ return rb_eNotImpError;
+}
+#endif
+
+#ifdef HAVE_RB_ERANGEERROR
+static VALUE constants_spec_rb_eRangeError(VALUE self) {
+ return rb_eRangeError;
+}
+#endif
+
+#ifdef HAVE_RB_EREGEXPERROR
+static VALUE constants_spec_rb_eRegexpError(VALUE self) {
+ return rb_eRegexpError;
+}
+#endif
+
+#ifdef HAVE_RB_ERUNTIMEERROR
+static VALUE constants_spec_rb_eRuntimeError(VALUE self) {
+ return rb_eRuntimeError;
+}
+#endif
+
+#ifdef HAVE_RB_ESCRIPTERROR
+static VALUE constants_spec_rb_eScriptError(VALUE self) {
+ return rb_eScriptError;
+}
+#endif
+
+#ifdef HAVE_RB_ESECURITYERROR
+static VALUE constants_spec_rb_eSecurityError(VALUE self) {
+ return rb_eSecurityError;
+}
+#endif
+
+#ifdef HAVE_RB_ESIGNAL
+static VALUE constants_spec_rb_eSignal(VALUE self) {
+ return rb_eSignal;
+}
+#endif
+
+#ifdef HAVE_RB_ESTANDARDERROR
+static VALUE constants_spec_rb_eStandardError(VALUE self) {
+ return rb_eStandardError;
+}
+#endif
+
+#ifdef HAVE_RB_ESYNTAXERROR
+static VALUE constants_spec_rb_eSyntaxError(VALUE self) {
+ return rb_eSyntaxError;
+}
+#endif
+
+#ifdef HAVE_RB_ESYSTEMCALLERROR
+static VALUE constants_spec_rb_eSystemCallError(VALUE self) {
+ return rb_eSystemCallError;
+}
+#endif
+
+#ifdef HAVE_RB_ESYSTEMEXIT
+static VALUE constants_spec_rb_eSystemExit(VALUE self) {
+ return rb_eSystemExit;
+}
+#endif
+
+#ifdef HAVE_RB_ESYSSTACKERROR
+static VALUE constants_spec_rb_eSysStackError(VALUE self) {
+ return rb_eSysStackError;
+}
+#endif
+
+#ifdef HAVE_RB_ETYPEERROR
+static VALUE constants_spec_rb_eTypeError(VALUE self) {
+ return rb_eTypeError;
+}
+#endif
+
+#ifdef HAVE_RB_ETHREADERROR
+static VALUE constants_spec_rb_eThreadError(VALUE self) {
+ return rb_eThreadError;
+}
+#endif
+
+#ifdef HAVE_RB_EZERODIVERROR
+static VALUE constants_spec_rb_eZeroDivError(VALUE self) {
+ return rb_eZeroDivError;
+}
+#endif
+
+#ifdef HAVE_RB_EMATHDOMAINERROR
+static VALUE constants_spec_rb_eMathDomainError(VALUE self) {
+ return rb_eMathDomainError;
+}
+#endif
+
+#ifdef HAVE_RB_EENCCOMPATERROR
+static VALUE constants_spec_rb_eEncCompatError(VALUE self) {
+ return rb_eEncCompatError;
+}
+#endif
+
+#ifdef HAVE_RB_MWAITREADABLE
+static VALUE constants_spec_rb_mWaitReadable(VALUE self) {
+ return rb_mWaitReadable;
+}
+#endif
+
+#ifdef HAVE_RB_MWAITWRITABLE
+static VALUE constants_spec_rb_mWaitWritable(VALUE self) {
+ return rb_mWaitWritable;
+}
+#endif
+
+#ifdef HAVE_RB_CDIR
+static VALUE constants_spec_rb_cDir(VALUE self) {
+ return rb_cDir;
+}
+#endif
+
+void Init_constants_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiConstantsSpecs", rb_cObject);
+
+#ifdef HAVE_RB_CARRAY
+ rb_define_method(cls, "rb_cArray", constants_spec_rb_cArray, 0);
+#endif
+
+#ifdef HAVE_RB_CBIGNUM
+ rb_define_method(cls, "rb_cBignum", constants_spec_rb_cBignum, 0);
+#endif
+
+#ifdef HAVE_RB_CCLASS
+ rb_define_method(cls, "rb_cClass", constants_spec_rb_cClass, 0);
+#endif
+
+#ifdef HAVE_RB_CDATA
+ rb_define_method(cls, "rb_cData", constants_spec_rb_cData, 0);
+#endif
+
+#ifdef HAVE_RB_CFALSECLASS
+ rb_define_method(cls, "rb_cFalseClass", constants_spec_rb_cFalseClass, 0);
+#endif
+
+#ifdef HAVE_RB_CFILE
+ rb_define_method(cls, "rb_cFile", constants_spec_rb_cFile, 0);
+#endif
+
+#ifdef HAVE_RB_CFIXNUM
+ rb_define_method(cls, "rb_cFixnum", constants_spec_rb_cFixnum, 0);
+#endif
+
+#ifdef HAVE_RB_CFLOAT
+ rb_define_method(cls, "rb_cFloat", constants_spec_rb_cFloat, 0);
+#endif
+
+#ifdef HAVE_RB_CHASH
+ rb_define_method(cls, "rb_cHash", constants_spec_rb_cHash, 0);
+#endif
+
+#ifdef HAVE_RB_CINTEGER
+ rb_define_method(cls, "rb_cInteger", constants_spec_rb_cInteger, 0);
+#endif
+
+#ifdef HAVE_RB_CIO
+ rb_define_method(cls, "rb_cIO", constants_spec_rb_cIO, 0);
+#endif
+
+#ifdef HAVE_RB_CMATCH
+ rb_define_method(cls, "rb_cMatch", constants_spec_rb_cMatch, 0);
+#endif
+
+#ifdef HAVE_RB_CMODULE
+ rb_define_method(cls, "rb_cModule", constants_spec_rb_cModule, 0);
+#endif
+
+#ifdef HAVE_RB_CNILCLASS
+ rb_define_method(cls, "rb_cNilClass", constants_spec_rb_cNilClass, 0);
+#endif
+
+#ifdef HAVE_RB_CNUMERIC
+ rb_define_method(cls, "rb_cNumeric", constants_spec_rb_cNumeric, 0);
+#endif
+
+#ifdef HAVE_RB_COBJECT
+ rb_define_method(cls, "rb_cObject", constants_spec_rb_cObject, 0);
+#endif
+
+#ifdef HAVE_RB_CRANGE
+ rb_define_method(cls, "rb_cRange", constants_spec_rb_cRange, 0);
+#endif
+
+#ifdef HAVE_RB_CREGEXP
+ rb_define_method(cls, "rb_cRegexp", constants_spec_rb_cRegexp, 0);
+#endif
+
+#ifdef HAVE_RB_CSTRING
+ rb_define_method(cls, "rb_cString", constants_spec_rb_cString, 0);
+#endif
+
+#ifdef HAVE_RB_CSTRUCT
+ rb_define_method(cls, "rb_cStruct", constants_spec_rb_cStruct, 0);
+#endif
+
+#ifdef HAVE_RB_CSYMBOL
+ rb_define_method(cls, "rb_cSymbol", constants_spec_rb_cSymbol, 0);
+#endif
+
+#ifdef HAVE_RB_CTIME
+ rb_define_method(cls, "rb_cTime", constants_spec_rb_cTime, 0);
+#endif
+
+#ifdef HAVE_RB_CTHREAD
+ rb_define_method(cls, "rb_cThread", constants_spec_rb_cThread, 0);
+#endif
+
+#ifdef HAVE_RB_CTRUECLASS
+ rb_define_method(cls, "rb_cTrueClass", constants_spec_rb_cTrueClass, 0);
+#endif
+
+#ifdef HAVE_RB_CPROC
+ rb_define_method(cls, "rb_cProc", constants_spec_rb_cProc, 0);
+#endif
+
+#ifdef HAVE_RB_CMETHOD
+ rb_define_method(cls, "rb_cMethod", constants_spec_rb_cMethod, 0);
+#endif
+
+#ifdef HAVE_RB_CENUMERATOR
+ rb_define_method(cls, "rb_cEnumerator", constants_spec_rb_cEnumerator, 0);
+#endif
+
+#ifdef HAVE_RB_MCOMPARABLE
+ rb_define_method(cls, "rb_mComparable", constants_spec_rb_mComparable, 0);
+#endif
+
+#ifdef HAVE_RB_MENUMERABLE
+ rb_define_method(cls, "rb_mEnumerable", constants_spec_rb_mEnumerable, 0);
+#endif
+
+#ifdef HAVE_RB_MKERNEL
+ rb_define_method(cls, "rb_mKernel", constants_spec_rb_mKernel, 0);
+#endif
+
+#ifdef HAVE_RB_EARGERROR
+ rb_define_method(cls, "rb_eArgError", constants_spec_rb_eArgError, 0);
+#endif
+
+#ifdef HAVE_RB_EEOFERROR
+ rb_define_method(cls, "rb_eEOFError", constants_spec_rb_eEOFError, 0);
+#endif
+
+#ifdef HAVE_RB_MERRNO
+ rb_define_method(cls, "rb_mErrno", constants_spec_rb_mErrno, 0);
+#endif
+
+#ifdef HAVE_RB_EEXCEPTION
+ rb_define_method(cls, "rb_eException", constants_spec_rb_eException, 0);
+#endif
+
+#ifdef HAVE_RB_EFLOATDOMAINERROR
+ rb_define_method(cls, "rb_eFloatDomainError", constants_spec_rb_eFloatDomainError, 0);
+#endif
+
+#ifdef HAVE_RB_EINDEXERROR
+ rb_define_method(cls, "rb_eIndexError", constants_spec_rb_eIndexError, 0);
+#endif
+
+#ifdef HAVE_RB_EINTERRUPT
+ rb_define_method(cls, "rb_eInterrupt", constants_spec_rb_eInterrupt, 0);
+#endif
+
+#ifdef HAVE_RB_EIOERROR
+ rb_define_method(cls, "rb_eIOError", constants_spec_rb_eIOError, 0);
+#endif
+
+#ifdef HAVE_RB_ELOADERROR
+ rb_define_method(cls, "rb_eLoadError", constants_spec_rb_eLoadError, 0);
+#endif
+
+#ifdef HAVE_RB_ELOCALJUMPERROR
+ rb_define_method(cls, "rb_eLocalJumpError", constants_spec_rb_eLocalJumpError, 0);
+#endif
+
+#ifdef HAVE_RB_ENAMEERROR
+ rb_define_method(cls, "rb_eNameError", constants_spec_rb_eNameError, 0);
+#endif
+
+#ifdef HAVE_RB_ENOMEMERROR
+ rb_define_method(cls, "rb_eNoMemError", constants_spec_rb_eNoMemError, 0);
+#endif
+
+#ifdef HAVE_RB_ENOMETHODERROR
+ rb_define_method(cls, "rb_eNoMethodError", constants_spec_rb_eNoMethodError, 0);
+#endif
+
+#ifdef HAVE_RB_ENOTIMPERROR
+ rb_define_method(cls, "rb_eNotImpError", constants_spec_rb_eNotImpError, 0);
+#endif
+
+#ifdef HAVE_RB_ERANGEERROR
+ rb_define_method(cls, "rb_eRangeError", constants_spec_rb_eRangeError, 0);
+#endif
+
+#ifdef HAVE_RB_EREGEXPERROR
+ rb_define_method(cls, "rb_eRegexpError", constants_spec_rb_eRegexpError, 0);
+#endif
+
+#ifdef HAVE_RB_ERUNTIMEERROR
+ rb_define_method(cls, "rb_eRuntimeError", constants_spec_rb_eRuntimeError, 0);
+#endif
+
+#ifdef HAVE_RB_ESCRIPTERROR
+ rb_define_method(cls, "rb_eScriptError", constants_spec_rb_eScriptError, 0);
+#endif
+
+#ifdef HAVE_RB_ESECURITYERROR
+ rb_define_method(cls, "rb_eSecurityError", constants_spec_rb_eSecurityError, 0);
+#endif
+
+#ifdef HAVE_RB_ESIGNAL
+ rb_define_method(cls, "rb_eSignal", constants_spec_rb_eSignal, 0);
+#endif
+
+#ifdef HAVE_RB_ESTANDARDERROR
+ rb_define_method(cls, "rb_eStandardError", constants_spec_rb_eStandardError, 0);
+#endif
+
+#ifdef HAVE_RB_ESYNTAXERROR
+ rb_define_method(cls, "rb_eSyntaxError", constants_spec_rb_eSyntaxError, 0);
+#endif
+
+#ifdef HAVE_RB_ESYSTEMCALLERROR
+ rb_define_method(cls, "rb_eSystemCallError", constants_spec_rb_eSystemCallError, 0);
+#endif
+
+#ifdef HAVE_RB_ESYSTEMEXIT
+ rb_define_method(cls, "rb_eSystemExit", constants_spec_rb_eSystemExit, 0);
+#endif
+
+#ifdef HAVE_RB_ESYSSTACKERROR
+ rb_define_method(cls, "rb_eSysStackError", constants_spec_rb_eSysStackError, 0);
+#endif
+
+#ifdef HAVE_RB_ETYPEERROR
+ rb_define_method(cls, "rb_eTypeError", constants_spec_rb_eTypeError, 0);
+#endif
+
+#ifdef HAVE_RB_ETHREADERROR
+ rb_define_method(cls, "rb_eThreadError", constants_spec_rb_eThreadError, 0);
+#endif
+
+#ifdef HAVE_RB_EZERODIVERROR
+ rb_define_method(cls, "rb_eZeroDivError", constants_spec_rb_eZeroDivError, 0);
+#endif
+
+#ifdef HAVE_RB_EMATHDOMAINERROR
+ rb_define_method(cls, "rb_eMathDomainError", constants_spec_rb_eMathDomainError, 0);
+#endif
+
+#ifdef HAVE_RB_EENCCOMPATERROR
+ rb_define_method(cls, "rb_eEncCompatError", constants_spec_rb_eEncCompatError, 0);
+#endif
+
+#ifdef HAVE_RB_MWAITREADABLE
+ rb_define_method(cls, "rb_mWaitReadable", constants_spec_rb_mWaitReadable, 0);
+#endif
+
+#ifdef HAVE_RB_MWAITWRITABLE
+ rb_define_method(cls, "rb_mWaitWritable", constants_spec_rb_mWaitWritable, 0);
+#endif
+
+#ifdef HAVE_RB_CDIR
+ rb_define_method(cls, "rb_cDir", constants_spec_rb_cDir, 0);
+#endif
+
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/data_spec.c b/spec/rubyspec/optional/capi/ext/data_spec.c
new file mode 100644
index 0000000000..ed79497897
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/data_spec.c
@@ -0,0 +1,97 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(HAVE_RDATA) && defined(HAVE_DATA_WRAP_STRUCT)
+struct sample_wrapped_struct {
+ int foo;
+};
+
+void sample_wrapped_struct_free(void* st) {
+ free(st);
+}
+
+void sample_wrapped_struct_mark(void* st) {
+}
+
+VALUE sdaf_alloc_func(VALUE klass) {
+ struct sample_wrapped_struct* bar = (struct sample_wrapped_struct *)malloc(sizeof(struct sample_wrapped_struct));
+ bar->foo = 42;
+ return Data_Wrap_Struct(klass, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar);
+}
+
+VALUE sdaf_get_struct(VALUE self) {
+ struct sample_wrapped_struct* bar;
+ Data_Get_Struct(self, struct sample_wrapped_struct, bar);
+
+ return INT2FIX((*bar).foo);
+}
+
+VALUE sws_wrap_struct(VALUE self, VALUE val) {
+ struct sample_wrapped_struct* bar = (struct sample_wrapped_struct *)malloc(sizeof(struct sample_wrapped_struct));
+ bar->foo = FIX2INT(val);
+ return Data_Wrap_Struct(rb_cObject, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar);
+}
+
+VALUE sws_wrap_struct_null(VALUE self, VALUE val) {
+ struct sample_wrapped_struct* bar = (struct sample_wrapped_struct *)malloc(sizeof(struct sample_wrapped_struct));
+ bar->foo = FIX2INT(val);
+ return Data_Wrap_Struct(0, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar);
+}
+
+VALUE sws_get_struct(VALUE self, VALUE obj) {
+ struct sample_wrapped_struct* bar;
+ Data_Get_Struct(obj, struct sample_wrapped_struct, bar);
+
+ return INT2FIX((*bar).foo);
+}
+
+VALUE sws_get_struct_rdata(VALUE self, VALUE obj) {
+ struct sample_wrapped_struct* bar;
+ bar = (struct sample_wrapped_struct*) RDATA(obj)->data;
+ return INT2FIX(bar->foo);
+}
+
+VALUE sws_get_struct_data_ptr(VALUE self, VALUE obj) {
+ struct sample_wrapped_struct* bar;
+ bar = (struct sample_wrapped_struct*) DATA_PTR(obj);
+ return INT2FIX(bar->foo);
+}
+
+VALUE sws_change_struct(VALUE self, VALUE obj, VALUE new_val) {
+ struct sample_wrapped_struct *old_struct, *new_struct;
+ new_struct = (struct sample_wrapped_struct *)malloc(sizeof(struct sample_wrapped_struct));
+ new_struct->foo = FIX2INT(new_val);
+ old_struct = RDATA(obj)->data;
+ free(old_struct);
+ RDATA(obj)->data = new_struct;
+ return Qnil;
+}
+#endif
+
+void Init_data_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiAllocSpecs", rb_cObject);
+
+#if defined(HAVE_RDATA) && defined(HAVE_DATA_WRAP_STRUCT)
+ rb_define_alloc_func(cls, sdaf_alloc_func);
+ rb_define_method(cls, "wrapped_data", sdaf_get_struct, 0);
+
+ cls = rb_define_class("CApiWrappedStructSpecs", rb_cObject);
+ rb_define_method(cls, "wrap_struct", sws_wrap_struct, 1);
+ rb_define_method(cls, "wrap_struct_null", sws_wrap_struct_null, 1);
+ rb_define_method(cls, "get_struct", sws_get_struct, 1);
+ rb_define_method(cls, "get_struct_rdata", sws_get_struct_rdata, 1);
+ rb_define_method(cls, "get_struct_data_ptr", sws_get_struct_data_ptr, 1);
+ rb_define_method(cls, "change_struct", sws_change_struct, 2);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/encoding_spec.c b/spec/rubyspec/optional/capi/ext/encoding_spec.c
new file mode 100644
index 0000000000..2e555ebc77
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/encoding_spec.c
@@ -0,0 +1,424 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include "ruby/encoding.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_ENC_CODERANGE_ASCIIONLY
+static VALUE encoding_spec_ENC_CODERANGE_ASCIIONLY(VALUE self, VALUE obj) {
+ if(ENC_CODERANGE_ASCIIONLY(obj)) {
+ return Qtrue;
+ } else {
+ return Qfalse;
+ }
+}
+#endif
+
+#ifdef HAVE_RB_USASCII_ENCODING
+static VALUE encoding_spec_rb_usascii_encoding(VALUE self) {
+ return rb_str_new2(rb_usascii_encoding()->name);
+}
+#endif
+
+#ifdef HAVE_RB_USASCII_ENCINDEX
+static VALUE encoding_spec_rb_usascii_encindex(VALUE self) {
+ return INT2NUM(rb_usascii_encindex());
+}
+#endif
+
+#ifdef HAVE_RB_ASCII8BIT_ENCODING
+static VALUE encoding_spec_rb_ascii8bit_encoding(VALUE self) {
+ return rb_str_new2(rb_ascii8bit_encoding()->name);
+}
+#endif
+
+#ifdef HAVE_RB_ASCII8BIT_ENCINDEX
+static VALUE encoding_spec_rb_ascii8bit_encindex(VALUE self) {
+ return INT2NUM(rb_ascii8bit_encindex());
+}
+#endif
+
+#ifdef HAVE_RB_UTF8_ENCODING
+static VALUE encoding_spec_rb_utf8_encoding(VALUE self) {
+ return rb_str_new2(rb_utf8_encoding()->name);
+}
+#endif
+
+#ifdef HAVE_RB_UTF8_ENCINDEX
+static VALUE encoding_spec_rb_utf8_encindex(VALUE self) {
+ return INT2NUM(rb_utf8_encindex());
+}
+#endif
+
+#ifdef HAVE_RB_LOCALE_ENCODING
+static VALUE encoding_spec_rb_locale_encoding(VALUE self) {
+ return rb_str_new2(rb_locale_encoding()->name);
+}
+#endif
+
+#ifdef HAVE_RB_LOCALE_ENCINDEX
+static VALUE encoding_spec_rb_locale_encindex(VALUE self) {
+ return INT2NUM(rb_locale_encindex());
+}
+#endif
+
+#ifdef HAVE_RB_FILESYSTEM_ENCODING
+static VALUE encoding_spec_rb_filesystem_encoding(VALUE self) {
+ return rb_str_new2(rb_filesystem_encoding()->name);
+}
+#endif
+
+#ifdef HAVE_RB_FILESYSTEM_ENCINDEX
+static VALUE encoding_spec_rb_filesystem_encindex(VALUE self) {
+ return INT2NUM(rb_filesystem_encindex());
+}
+#endif
+
+#ifdef HAVE_RB_DEFAULT_INTERNAL_ENCODING
+static VALUE encoding_spec_rb_default_internal_encoding(VALUE self) {
+ rb_encoding* enc = rb_default_internal_encoding();
+ if(enc == 0) return Qnil;
+ return rb_str_new2(enc->name);
+}
+#endif
+
+#ifdef HAVE_RB_DEFAULT_EXTERNAL_ENCODING
+static VALUE encoding_spec_rb_default_external_encoding(VALUE self) {
+ rb_encoding* enc = rb_default_external_encoding();
+ if(enc == 0) return Qnil;
+ return rb_str_new2(enc->name);
+}
+#endif
+
+#ifdef HAVE_RB_ENCDB_ALIAS
+/* Not exposed by MRI C-API encoding.h but used in the pg gem. */
+extern int rb_encdb_alias(const char* alias, const char* orig);
+
+static VALUE encoding_spec_rb_encdb_alias(VALUE self, VALUE alias, VALUE orig) {
+ return INT2NUM(rb_encdb_alias(RSTRING_PTR(alias), RSTRING_PTR(orig)));
+}
+#endif
+
+#if defined(HAVE_RB_ENC_ASSOCIATE) && defined(HAVE_RB_ENC_FIND)
+static VALUE encoding_spec_rb_enc_associate(VALUE self, VALUE obj, VALUE enc) {
+ return rb_enc_associate(obj, NIL_P(enc) ? NULL : rb_enc_find(RSTRING_PTR(enc)));
+}
+#endif
+
+#if defined(HAVE_RB_ENC_ASSOCIATE_INDEX) && defined(HAVE_RB_ENC_FIND_INDEX)
+static VALUE encoding_spec_rb_enc_associate_index(VALUE self, VALUE obj, VALUE index) {
+ return rb_enc_associate_index(obj, FIX2INT(index));
+}
+#endif
+
+#ifdef HAVE_RB_ENC_COMPATIBLE
+static VALUE encoding_spec_rb_enc_compatible(VALUE self, VALUE a, VALUE b) {
+ rb_encoding* enc = rb_enc_compatible(a, b);
+
+ if(!enc) return INT2FIX(0);
+
+ return rb_enc_from_encoding(enc);
+}
+#endif
+
+#ifdef HAVE_RB_ENC_COPY
+static VALUE encoding_spec_rb_enc_copy(VALUE self, VALUE dest, VALUE src) {
+ rb_enc_copy(dest, src);
+ return dest;
+}
+#endif
+
+#ifdef HAVE_RB_ENC_FIND
+static VALUE encoding_spec_rb_enc_find(VALUE self, VALUE name) {
+ return rb_str_new2(rb_enc_find(RSTRING_PTR(name))->name);
+}
+#endif
+
+#ifdef HAVE_RB_ENC_FIND_INDEX
+static VALUE encoding_spec_rb_enc_find_index(VALUE self, VALUE name) {
+ return INT2NUM(rb_enc_find_index(RSTRING_PTR(name)));
+}
+#endif
+
+#ifdef HAVE_RB_ENC_FROM_INDEX
+static VALUE encoding_spec_rb_enc_from_index(VALUE self, VALUE index) {
+ return rb_str_new2(rb_enc_from_index(NUM2INT(index))->name);
+}
+#endif
+
+#ifdef HAVE_RB_ENC_FROM_ENCODING
+static VALUE encoding_spec_rb_enc_from_encoding(VALUE self, VALUE name) {
+ return rb_enc_from_encoding(rb_enc_find(RSTRING_PTR(name)));
+}
+#endif
+
+#ifdef HAVE_RB_ENC_GET
+static VALUE encoding_spec_rb_enc_get(VALUE self, VALUE obj) {
+ return rb_str_new2(rb_enc_get(obj)->name);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_ENCODING
+static VALUE encoding_spec_rb_obj_encoding(VALUE self, VALUE obj) {
+ return rb_obj_encoding(obj);
+}
+#endif
+
+#ifdef HAVE_RB_ENC_GET_INDEX
+static VALUE encoding_spec_rb_enc_get_index(VALUE self, VALUE obj) {
+ return INT2NUM(rb_enc_get_index(obj));
+}
+#endif
+
+#if defined(HAVE_RB_ENC_SET_INDEX) \
+ && defined(HAVE_RB_ENC_FIND_INDEX) \
+ && defined(HAVE_RB_ENC_FIND_INDEX)
+static VALUE encoding_spec_rb_enc_set_index(VALUE self, VALUE obj, VALUE index) {
+ int i = NUM2INT(index);
+
+ rb_encoding* enc = rb_enc_from_index(i);
+ rb_enc_set_index(obj, i);
+
+ return rb_ary_new3(2, rb_str_new2(rb_enc_name(enc)),
+ rb_str_new2(rb_enc_name(rb_enc_get(obj))));
+}
+#endif
+
+#ifdef HAVE_RB_ENC_STR_CODERANGE
+static VALUE encoding_spec_rb_enc_str_coderange(VALUE self, VALUE str) {
+ int coderange = rb_enc_str_coderange(str);
+
+ switch(coderange) {
+ case ENC_CODERANGE_UNKNOWN:
+ return ID2SYM(rb_intern("coderange_unknown"));
+ case ENC_CODERANGE_7BIT:
+ return ID2SYM(rb_intern("coderange_7bit"));
+ case ENC_CODERANGE_VALID:
+ return ID2SYM(rb_intern("coderange_valid"));
+ case ENC_CODERANGE_BROKEN:
+ return ID2SYM(rb_intern("coderange_broken"));
+ default:
+ return ID2SYM(rb_intern("coderange_unrecognized"));
+ }
+}
+#endif
+
+#ifdef HAVE_RB_ENC_STR_NEW
+static VALUE encoding_spec_rb_enc_str_new(VALUE self, VALUE str, VALUE len, VALUE enc) {
+ return rb_enc_str_new(RSTRING_PTR(str), FIX2INT(len), rb_to_encoding(enc));
+}
+#endif
+
+#ifdef HAVE_ENCODING_GET
+static VALUE encoding_spec_ENCODING_GET(VALUE self, VALUE obj) {
+ return INT2NUM(ENCODING_GET(obj));
+}
+#endif
+
+#ifdef HAVE_ENCODING_SET
+static VALUE encoding_spec_ENCODING_SET(VALUE self, VALUE obj, VALUE index) {
+ int i = NUM2INT(index);
+
+ rb_encoding* enc = rb_enc_from_index(i);
+ ENCODING_SET(obj, i);
+
+ return rb_ary_new3(2, rb_str_new2(rb_enc_name(enc)),
+ rb_str_new2(rb_enc_name(rb_enc_get(obj))));
+}
+#endif
+
+#if defined(HAVE_RB_ENC_TO_INDEX) && defined(HAVE_RB_ENC_FIND)
+static VALUE encoding_spec_rb_enc_to_index(VALUE self, VALUE name) {
+ return INT2NUM(rb_enc_to_index(NIL_P(name) ? NULL : rb_enc_find(RSTRING_PTR(name))));
+}
+#endif
+
+#ifdef HAVE_RB_TO_ENCODING
+static VALUE encoding_spec_rb_to_encoding(VALUE self, VALUE obj) {
+ return rb_str_new2(rb_to_encoding(obj)->name);
+}
+#endif
+
+#ifdef HAVE_RB_TO_ENCODING_INDEX
+static VALUE encoding_spec_rb_to_encoding_index(VALUE self, VALUE obj) {
+ return INT2NUM(rb_to_encoding_index(obj));
+}
+#endif
+
+#ifdef HAVE_RB_ENC_NTH
+static VALUE encoding_spec_rb_enc_nth(VALUE self, VALUE str, VALUE index) {
+ char* start = RSTRING_PTR(str);
+ char* end = start + RSTRING_LEN(str);
+ char* ptr = rb_enc_nth(start, end, FIX2LONG(index), rb_enc_get(str));
+ return LONG2NUM(ptr - start);
+}
+#endif
+
+#ifdef HAVE_RB_ENC_CODEPOINT_LEN
+static VALUE encoding_spec_rb_enc_codepoint_len(VALUE self, VALUE str) {
+ char* start = RSTRING_PTR(str);
+ char* end = start + RSTRING_LEN(str);
+
+ int len;
+ unsigned int codepoint = rb_enc_codepoint_len(start, end, &len, rb_enc_get(str));
+
+ return rb_ary_new3(2, LONG2NUM(codepoint), LONG2NUM(len));
+}
+#endif
+
+void Init_encoding_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiEncodingSpecs", rb_cObject);
+
+#ifdef HAVE_ENC_CODERANGE_ASCIIONLY
+ rb_define_method(cls, "ENC_CODERANGE_ASCIIONLY",
+ encoding_spec_ENC_CODERANGE_ASCIIONLY, 1);
+#endif
+
+#ifdef HAVE_RB_USASCII_ENCODING
+ rb_define_method(cls, "rb_usascii_encoding", encoding_spec_rb_usascii_encoding, 0);
+#endif
+
+#ifdef HAVE_RB_USASCII_ENCINDEX
+ rb_define_method(cls, "rb_usascii_encindex", encoding_spec_rb_usascii_encindex, 0);
+#endif
+
+#ifdef HAVE_RB_ASCII8BIT_ENCODING
+ rb_define_method(cls, "rb_ascii8bit_encoding", encoding_spec_rb_ascii8bit_encoding, 0);
+#endif
+
+#ifdef HAVE_RB_ASCII8BIT_ENCINDEX
+ rb_define_method(cls, "rb_ascii8bit_encindex", encoding_spec_rb_ascii8bit_encindex, 0);
+#endif
+
+#ifdef HAVE_RB_UTF8_ENCODING
+ rb_define_method(cls, "rb_utf8_encoding", encoding_spec_rb_utf8_encoding, 0);
+#endif
+
+#ifdef HAVE_RB_UTF8_ENCINDEX
+ rb_define_method(cls, "rb_utf8_encindex", encoding_spec_rb_utf8_encindex, 0);
+#endif
+
+#ifdef HAVE_RB_LOCALE_ENCODING
+ rb_define_method(cls, "rb_locale_encoding", encoding_spec_rb_locale_encoding, 0);
+#endif
+
+#ifdef HAVE_RB_LOCALE_ENCINDEX
+ rb_define_method(cls, "rb_locale_encindex", encoding_spec_rb_locale_encindex, 0);
+#endif
+
+#ifdef HAVE_RB_FILESYSTEM_ENCODING
+ rb_define_method(cls, "rb_filesystem_encoding", encoding_spec_rb_filesystem_encoding, 0);
+#endif
+
+#ifdef HAVE_RB_FILESYSTEM_ENCINDEX
+ rb_define_method(cls, "rb_filesystem_encindex", encoding_spec_rb_filesystem_encindex, 0);
+#endif
+
+#ifdef HAVE_RB_DEFAULT_INTERNAL_ENCODING
+ rb_define_method(cls, "rb_default_internal_encoding",
+ encoding_spec_rb_default_internal_encoding, 0);
+#endif
+
+#ifdef HAVE_RB_DEFAULT_EXTERNAL_ENCODING
+ rb_define_method(cls, "rb_default_external_encoding",
+ encoding_spec_rb_default_external_encoding, 0);
+#endif
+
+#ifdef HAVE_RB_ENCDB_ALIAS
+ rb_define_method(cls, "rb_encdb_alias", encoding_spec_rb_encdb_alias, 2);
+#endif
+
+#ifdef HAVE_RB_ENC_ASSOCIATE
+ rb_define_method(cls, "rb_enc_associate", encoding_spec_rb_enc_associate, 2);
+#endif
+
+#ifdef HAVE_RB_ENC_ASSOCIATE_INDEX
+ rb_define_method(cls, "rb_enc_associate_index", encoding_spec_rb_enc_associate_index, 2);
+#endif
+
+#ifdef HAVE_RB_ENC_COMPATIBLE
+ rb_define_method(cls, "rb_enc_compatible", encoding_spec_rb_enc_compatible, 2);
+#endif
+
+#ifdef HAVE_RB_ENC_COPY
+ rb_define_method(cls, "rb_enc_copy", encoding_spec_rb_enc_copy, 2);
+#endif
+
+#ifdef HAVE_RB_ENC_FIND
+ rb_define_method(cls, "rb_enc_find", encoding_spec_rb_enc_find, 1);
+#endif
+
+#ifdef HAVE_RB_ENC_FIND_INDEX
+ rb_define_method(cls, "rb_enc_find_index", encoding_spec_rb_enc_find_index, 1);
+#endif
+
+#ifdef HAVE_RB_ENC_FROM_INDEX
+ rb_define_method(cls, "rb_enc_from_index", encoding_spec_rb_enc_from_index, 1);
+#endif
+
+#ifdef HAVE_RB_ENC_FROM_ENCODING
+ rb_define_method(cls, "rb_enc_from_encoding", encoding_spec_rb_enc_from_encoding, 1);
+#endif
+
+#ifdef HAVE_RB_ENC_GET
+ rb_define_method(cls, "rb_enc_get", encoding_spec_rb_enc_get, 1);
+#endif
+
+#ifdef HAVE_RB_OBJ_ENCODING
+ rb_define_method(cls, "rb_obj_encoding", encoding_spec_rb_obj_encoding, 1);
+#endif
+
+#ifdef HAVE_RB_ENC_GET_INDEX
+ rb_define_method(cls, "rb_enc_get_index", encoding_spec_rb_enc_get_index, 1);
+#endif
+
+#if defined(HAVE_RB_ENC_SET_INDEX) \
+ && defined(HAVE_RB_ENC_FIND_INDEX) \
+ && defined(HAVE_RB_ENC_FIND_INDEX)
+ rb_define_method(cls, "rb_enc_set_index", encoding_spec_rb_enc_set_index, 2);
+#endif
+
+#ifdef HAVE_RB_ENC_STR_CODERANGE
+ rb_define_method(cls, "rb_enc_str_coderange", encoding_spec_rb_enc_str_coderange, 1);
+#endif
+
+#ifdef HAVE_RB_ENC_STR_NEW
+ rb_define_method(cls, "rb_enc_str_new", encoding_spec_rb_enc_str_new, 3);
+#endif
+
+#ifdef HAVE_ENCODING_GET
+ rb_define_method(cls, "ENCODING_GET", encoding_spec_ENCODING_GET, 1);
+#endif
+
+#ifdef HAVE_ENCODING_SET
+ rb_define_method(cls, "ENCODING_SET", encoding_spec_ENCODING_SET, 2);
+#endif
+
+#if defined(HAVE_RB_ENC_TO_INDEX) && defined(HAVE_RB_ENC_FIND)
+ rb_define_method(cls, "rb_enc_to_index", encoding_spec_rb_enc_to_index, 1);
+#endif
+
+#ifdef HAVE_RB_TO_ENCODING
+ rb_define_method(cls, "rb_to_encoding", encoding_spec_rb_to_encoding, 1);
+#endif
+
+#ifdef HAVE_RB_TO_ENCODING_INDEX
+ rb_define_method(cls, "rb_to_encoding_index", encoding_spec_rb_to_encoding_index, 1);
+#endif
+
+#ifdef HAVE_RB_ENC_NTH
+ rb_define_method(cls, "rb_enc_nth", encoding_spec_rb_enc_nth, 2);
+#endif
+
+#ifdef HAVE_RB_ENC_CODEPOINT_LEN
+ rb_define_method(cls, "rb_enc_codepoint_len", encoding_spec_rb_enc_codepoint_len, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/enumerator_spec.c b/spec/rubyspec/optional/capi/ext/enumerator_spec.c
new file mode 100644
index 0000000000..6b08feab52
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/enumerator_spec.c
@@ -0,0 +1,27 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_ENUMERATORIZE
+VALUE enumerator_spec_rb_enumeratorize(int argc, VALUE *argv, VALUE self) {
+ VALUE obj, meth, args;
+ rb_scan_args(argc, argv, "2*", &obj, &meth, &args);
+ return rb_enumeratorize(obj, meth, (int)RARRAY_LEN(args), RARRAY_PTR(args));
+}
+#endif
+
+void Init_enumerator_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiEnumeratorSpecs", rb_cObject);
+
+#ifdef HAVE_RB_ENUMERATORIZE
+ rb_define_method(cls, "rb_enumeratorize", enumerator_spec_rb_enumeratorize, -1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/exception_spec.c b/spec/rubyspec/optional/capi/ext/exception_spec.c
new file mode 100644
index 0000000000..b37f74f03e
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/exception_spec.c
@@ -0,0 +1,72 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_EXC_NEW
+VALUE exception_spec_rb_exc_new(VALUE self, VALUE str) {
+ char *cstr = StringValuePtr(str);
+ return rb_exc_new(rb_eException, cstr, strlen(cstr));
+}
+#endif
+
+#ifdef HAVE_RB_EXC_NEW2
+VALUE exception_spec_rb_exc_new2(VALUE self, VALUE str) {
+ char *cstr = StringValuePtr(str);
+ return rb_exc_new2(rb_eException, cstr);
+}
+#endif
+
+#ifdef HAVE_RB_EXC_NEW3
+VALUE exception_spec_rb_exc_new3(VALUE self, VALUE str) {
+ return rb_exc_new3(rb_eException, str);
+}
+#endif
+
+#ifdef HAVE_RB_EXC_RAISE
+VALUE exception_spec_rb_exc_raise(VALUE self, VALUE exc) {
+ if (self != Qundef) rb_exc_raise(exc);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_SET_ERRINFO
+VALUE exception_spec_rb_set_errinfo(VALUE self, VALUE exc) {
+ rb_set_errinfo(exc);
+ return Qnil;
+}
+#endif
+
+void Init_exception_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiExceptionSpecs", rb_cObject);
+
+#ifdef HAVE_RB_EXC_NEW
+ rb_define_method(cls, "rb_exc_new", exception_spec_rb_exc_new, 1);
+#endif
+
+#ifdef HAVE_RB_EXC_NEW2
+ rb_define_method(cls, "rb_exc_new2", exception_spec_rb_exc_new2, 1);
+#endif
+
+#ifdef HAVE_RB_EXC_NEW3
+ rb_define_method(cls, "rb_exc_new3", exception_spec_rb_exc_new3, 1);
+#endif
+
+#ifdef HAVE_RB_EXC_RAISE
+ rb_define_method(cls, "rb_exc_raise", exception_spec_rb_exc_raise, 1);
+#endif
+
+#ifdef HAVE_RB_SET_ERRINFO
+ rb_define_method(cls, "rb_set_errinfo", exception_spec_rb_set_errinfo, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/file_spec.c b/spec/rubyspec/optional/capi/ext/file_spec.c
new file mode 100644
index 0000000000..98f8db1595
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/file_spec.c
@@ -0,0 +1,44 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_FILE_OPEN
+VALUE file_spec_rb_file_open(VALUE self, VALUE name, VALUE mode) {
+ return rb_file_open(RSTRING_PTR(name), RSTRING_PTR(mode));
+}
+#endif
+
+#ifdef HAVE_RB_FILE_OPEN_STR
+VALUE file_spec_rb_file_open_str(VALUE self, VALUE name, VALUE mode) {
+ return rb_file_open_str(name, RSTRING_PTR(mode));
+}
+#endif
+
+#ifdef HAVE_FILEPATHVALUE
+VALUE file_spec_FilePathValue(VALUE self, VALUE obj) {
+ return FilePathValue(obj);
+}
+#endif
+
+void Init_file_spec(void) {
+ VALUE cls = rb_define_class("CApiFileSpecs", rb_cObject);
+
+#ifdef HAVE_RB_FILE_OPEN
+ rb_define_method(cls, "rb_file_open", file_spec_rb_file_open, 2);
+#endif
+
+#ifdef HAVE_RB_FILE_OPEN_STR
+ rb_define_method(cls, "rb_file_open_str", file_spec_rb_file_open_str, 2);
+#endif
+
+#ifdef HAVE_FILEPATHVALUE
+ rb_define_method(cls, "FilePathValue", file_spec_FilePathValue, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/fixnum_spec.c b/spec/rubyspec/optional/capi/ext/fixnum_spec.c
new file mode 100644
index 0000000000..4c0572186d
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/fixnum_spec.c
@@ -0,0 +1,36 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_FIX2UINT
+static VALUE fixnum_spec_rb_fix2uint(VALUE self, VALUE value) {
+ return INT2FIX(rb_fix2uint(value));
+}
+#endif
+
+#ifdef HAVE_RB_FIX2INT
+static VALUE fixnum_spec_rb_fix2int(VALUE self, VALUE value) {
+ return INT2FIX(rb_fix2int(value));
+}
+#endif
+
+
+void Init_fixnum_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiFixnumSpecs", rb_cObject);
+
+#ifdef HAVE_RB_FIX2UINT
+ rb_define_method(cls, "rb_fix2uint", fixnum_spec_rb_fix2uint, 1);
+#endif
+
+#ifdef HAVE_RB_FIX2INT
+ rb_define_method(cls, "rb_fix2int", fixnum_spec_rb_fix2int, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/float_spec.c b/spec/rubyspec/optional/capi/ext/float_spec.c
new file mode 100644
index 0000000000..15c74e62c9
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/float_spec.c
@@ -0,0 +1,54 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <math.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_FLOAT_NEW
+static VALUE float_spec_new_zero(VALUE self) {
+ double flt = 0;
+ return rb_float_new(flt);
+}
+
+static VALUE float_spec_new_point_five(VALUE self) {
+ double flt = 0.555;
+ return rb_float_new(flt);
+}
+#endif
+
+#ifdef HAVE_RB_RFLOAT
+static VALUE float_spec_rb_Float(VALUE self, VALUE float_str) {
+ return rb_Float(float_str);
+}
+#endif
+
+#ifdef HAVE_RFLOAT_VALUE
+static VALUE float_spec_RFLOAT_VALUE(VALUE self, VALUE float_h) {
+ return rb_float_new(RFLOAT_VALUE(float_h));
+}
+#endif
+
+void Init_float_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiFloatSpecs", rb_cObject);
+
+#ifdef HAVE_RB_FLOAT_NEW
+ rb_define_method(cls, "new_zero", float_spec_new_zero, 0);
+ rb_define_method(cls, "new_point_five", float_spec_new_point_five, 0);
+#endif
+
+#ifdef HAVE_RB_RFLOAT
+ rb_define_method(cls, "rb_Float", float_spec_rb_Float, 1);
+#endif
+
+#ifdef HAVE_RFLOAT_VALUE
+ rb_define_method(cls, "RFLOAT_VALUE", float_spec_RFLOAT_VALUE, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/gc_spec.c b/spec/rubyspec/optional/capi/ext/gc_spec.c
new file mode 100644
index 0000000000..c5895eb0aa
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/gc_spec.c
@@ -0,0 +1,61 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_GC_REGISTER_ADDRESS
+VALUE registered_tagged_value;
+VALUE registered_reference_value;
+
+static VALUE registered_tagged_address(VALUE self) {
+ return registered_tagged_value;
+}
+
+static VALUE registered_reference_address(VALUE self) {
+ return registered_reference_value;
+}
+#endif
+
+#ifdef HAVE_RB_GC_ENABLE
+static VALUE gc_spec_rb_gc_enable() {
+ return rb_gc_enable();
+}
+#endif
+
+#ifdef HAVE_RB_GC_DISABLE
+static VALUE gc_spec_rb_gc_disable() {
+ return rb_gc_disable();
+}
+#endif
+
+
+void Init_gc_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiGCSpecs", rb_cObject);
+
+#ifdef HAVE_RB_GC_REGISTER_ADDRESS
+ registered_tagged_value = INT2NUM(10);
+ registered_reference_value = rb_str_new2("Globally registered data");
+
+ rb_gc_register_address(&registered_tagged_value);
+ rb_gc_register_address(&registered_reference_value);
+
+ rb_define_method(cls, "registered_tagged_address", registered_tagged_address, 0);
+ rb_define_method(cls, "registered_reference_address", registered_reference_address, 0);
+#endif
+
+#ifdef HAVE_RB_GC_ENABLE
+ rb_define_method(cls, "rb_gc_enable", gc_spec_rb_gc_enable, 0);
+#endif
+
+#ifdef HAVE_RB_GC_DISABLE
+ rb_define_method(cls, "rb_gc_disable", gc_spec_rb_gc_disable, 0);
+#endif
+
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/globals_spec.c b/spec/rubyspec/optional/capi/ext/globals_spec.c
new file mode 100644
index 0000000000..0c28a7f8ab
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/globals_spec.c
@@ -0,0 +1,199 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_DEFINE_HOOKED_VARIABLE
+VALUE g_hooked_var;
+
+void var_2x_setter(VALUE val, ID id, VALUE *var) {
+ *var = INT2NUM(NUM2INT(val) * 2);
+}
+
+static VALUE sb_define_hooked_variable(VALUE self, VALUE var_name) {
+ rb_define_hooked_variable(StringValuePtr(var_name), &g_hooked_var, 0, var_2x_setter);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_READONLY_VARIABLE
+VALUE g_ro_var;
+
+static VALUE sb_define_readonly_variable(VALUE self, VALUE var_name, VALUE val) {
+ g_ro_var = val;
+ rb_define_readonly_variable(StringValuePtr(var_name), &g_ro_var);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_VARIABLE
+VALUE g_var;
+
+static VALUE sb_get_global_value(VALUE self) {
+ return g_var;
+}
+
+static VALUE sb_define_variable(VALUE self, VALUE var_name, VALUE val) {
+ g_var = val;
+ rb_define_variable(StringValuePtr(var_name), &g_var);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_F_GLOBAL_VARIABLES
+static VALUE sb_f_global_variables(VALUE self) {
+ return rb_f_global_variables();
+}
+#endif
+
+#ifdef HAVE_RB_GV_GET
+static VALUE sb_gv_get(VALUE self, VALUE var) {
+ return rb_gv_get(StringValuePtr(var));
+}
+#endif
+
+#ifdef HAVE_RB_GV_SET
+static VALUE sb_gv_set(VALUE self, VALUE var, VALUE val) {
+ return rb_gv_set(StringValuePtr(var), val);
+}
+#endif
+
+#ifdef HAVE_RB_STDIN
+static VALUE global_spec_rb_stdin(VALUE self) {
+ return rb_stdin;
+}
+#endif
+
+#ifdef HAVE_RB_STDOUT
+static VALUE global_spec_rb_stdout(VALUE self) {
+ return rb_stdout;
+}
+#endif
+
+#ifdef HAVE_RB_STDERR
+static VALUE global_spec_rb_stderr(VALUE self) {
+ return rb_stderr;
+}
+#endif
+
+#ifdef HAVE_RB_DEFOUT
+static VALUE global_spec_rb_defout(VALUE self) {
+ return rb_defout;
+}
+#endif
+
+#ifdef HAVE_RB_RS
+static VALUE global_spec_rb_rs(VALUE self) {
+ return rb_rs;
+}
+#endif
+
+#ifdef HAVE_RB_DEFAULT_RS
+static VALUE global_spec_rb_default_rs(VALUE self) {
+ return rb_default_rs;
+}
+#endif
+
+#ifdef HAVE_RB_OUTPUT_RS
+static VALUE global_spec_rb_output_rs(VALUE self) {
+ return rb_output_rs;
+}
+#endif
+
+#ifdef HAVE_RB_OUTPUT_FS
+static VALUE global_spec_rb_output_fs(VALUE self) {
+ return rb_output_fs;
+}
+#endif
+
+#ifdef HAVE_RB_LASTLINE_SET
+static VALUE global_spec_rb_lastline_set(VALUE self, VALUE line) {
+ rb_lastline_set(line);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_LASTLINE_GET
+static VALUE global_spec_rb_lastline_get(VALUE self) {
+ return rb_lastline_get();
+}
+#endif
+
+void Init_globals_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiGlobalSpecs", rb_cObject);
+
+#ifdef HAVE_RB_DEFINE_HOOKED_VARIABLE
+ g_hooked_var = Qnil;
+ rb_define_method(cls, "rb_define_hooked_variable_2x", sb_define_hooked_variable, 1);
+#endif
+
+#ifdef HAVE_RB_DEFINE_READONLY_VARIABLE
+ g_ro_var = Qnil;
+ rb_define_method(cls, "rb_define_readonly_variable", sb_define_readonly_variable, 2);
+#endif
+
+#ifdef HAVE_RB_DEFINE_VARIABLE
+ g_var = Qnil;
+ rb_define_method(cls, "rb_define_variable", sb_define_variable, 2);
+ rb_define_method(cls, "sb_get_global_value", sb_get_global_value, 0);
+#endif
+
+#ifdef HAVE_RB_F_GLOBAL_VARIABLES
+ rb_define_method(cls, "rb_f_global_variables", sb_f_global_variables, 0);
+#endif
+
+#ifdef HAVE_RB_GV_GET
+ rb_define_method(cls, "sb_gv_get", sb_gv_get, 1);
+#endif
+
+#ifdef HAVE_RB_GV_SET
+ rb_define_method(cls, "sb_gv_set", sb_gv_set, 2);
+#endif
+
+#ifdef HAVE_RB_STDIN
+ rb_define_method(cls, "rb_stdin", global_spec_rb_stdin, 0);
+#endif
+
+#ifdef HAVE_RB_STDOUT
+ rb_define_method(cls, "rb_stdout", global_spec_rb_stdout, 0);
+#endif
+
+#ifdef HAVE_RB_STDERR
+ rb_define_method(cls, "rb_stderr", global_spec_rb_stderr, 0);
+#endif
+
+#ifdef HAVE_RB_DEFOUT
+ rb_define_method(cls, "rb_defout", global_spec_rb_defout, 0);
+#endif
+
+#ifdef HAVE_RB_RS
+ rb_define_method(cls, "rb_rs", global_spec_rb_rs, 0);
+#endif
+
+#ifdef HAVE_RB_DEFAULT_RS
+ rb_define_method(cls, "rb_default_rs", global_spec_rb_default_rs, 0);
+#endif
+
+#ifdef HAVE_RB_OUTPUT_RS
+ rb_define_method(cls, "rb_output_rs", global_spec_rb_output_rs, 0);
+#endif
+
+#ifdef HAVE_RB_OUTPUT_FS
+ rb_define_method(cls, "rb_output_fs", global_spec_rb_output_fs, 0);
+#endif
+
+#ifdef HAVE_RB_LASTLINE_SET
+ rb_define_method(cls, "rb_lastline_set", global_spec_rb_lastline_set, 1);
+#endif
+
+#ifdef HAVE_RB_LASTLINE_GET
+ rb_define_method(cls, "rb_lastline_get", global_spec_rb_lastline_get, 0);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/hash_spec.c b/spec/rubyspec/optional/capi/ext/hash_spec.c
new file mode 100644
index 0000000000..ac45003844
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/hash_spec.c
@@ -0,0 +1,208 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_HASH
+VALUE hash_spec_rb_hash(VALUE self, VALUE hash) {
+ return rb_hash(hash);
+}
+#endif
+
+#ifdef HAVE_RB_HASH2
+VALUE hash_spec_rb_Hash(VALUE self, VALUE val) {
+ return rb_Hash(val);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_DUP
+VALUE hash_spec_rb_hash_dup(VALUE self, VALUE hash) {
+ return rb_hash_dup(hash);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_FREEZE
+VALUE hash_spec_rb_hash_freeze(VALUE self, VALUE hash) {
+ return rb_hash_freeze(hash);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_AREF
+VALUE hash_spec_rb_hash_aref(VALUE self, VALUE hash, VALUE key) {
+ return rb_hash_aref(hash, key);
+}
+
+VALUE hash_spec_rb_hash_aref_nil(VALUE self, VALUE hash, VALUE key) {
+ VALUE ret = rb_hash_aref(hash, key);
+ return NIL_P(ret) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_HASH_ASET
+VALUE hash_spec_rb_hash_aset(VALUE self, VALUE hash, VALUE key, VALUE val) {
+ return rb_hash_aset(hash, key, val);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_CLEAR
+VALUE hash_spec_rb_hash_clear(VALUE self, VALUE hash) {
+ return rb_hash_clear(hash);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_DELETE
+VALUE hash_spec_rb_hash_delete(VALUE self, VALUE hash, VALUE key) {
+ return rb_hash_delete(hash, key);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_DELETE_IF
+VALUE hash_spec_rb_hash_delete_if(VALUE self, VALUE hash) {
+ return rb_hash_delete_if(hash);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_FOREACH
+static int foreach_i(VALUE key, VALUE val, VALUE other) {
+ rb_hash_aset(other, key, val);
+ return 0; /* ST_CONTINUE; */
+}
+
+static int foreach_stop_i(VALUE key, VALUE val, VALUE other) {
+ rb_hash_aset(other, key, val);
+ return 1; /* ST_STOP; */
+}
+
+static int foreach_delete_i(VALUE key, VALUE val, VALUE other) {
+ rb_hash_aset(other, key, val);
+ return 2; /* ST_DELETE; */
+}
+
+VALUE hash_spec_rb_hash_foreach(VALUE self, VALUE hsh) {
+ VALUE other = rb_hash_new();
+ rb_hash_foreach(hsh, foreach_i, other);
+ return other;
+}
+
+VALUE hash_spec_rb_hash_foreach_stop(VALUE self, VALUE hsh) {
+ VALUE other = rb_hash_new();
+ rb_hash_foreach(hsh, foreach_stop_i, other);
+ return other;
+}
+
+VALUE hash_spec_rb_hash_foreach_delete(VALUE self, VALUE hsh) {
+ VALUE other = rb_hash_new();
+ rb_hash_foreach(hsh, foreach_delete_i, other);
+ return other;
+}
+#endif
+
+#ifdef HAVE_RB_HASH_LOOKUP
+VALUE hash_spec_rb_hash_lookup(VALUE self, VALUE hash, VALUE key) {
+ return rb_hash_lookup(hash, key);
+}
+
+VALUE hash_spec_rb_hash_lookup_nil(VALUE self, VALUE hash, VALUE key) {
+ VALUE ret = rb_hash_lookup(hash, key);
+ return ret == Qnil ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_HASH_LOOKUP2
+VALUE hash_spec_rb_hash_lookup2(VALUE self, VALUE hash, VALUE key, VALUE def) {
+ return rb_hash_lookup2(hash, key, def);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_NEW
+VALUE hash_spec_rb_hash_new(VALUE self) {
+ return rb_hash_new();
+}
+#endif
+
+#ifdef HAVE_RB_HASH_SIZE
+VALUE hash_spec_rb_hash_size(VALUE self, VALUE hash) {
+ return rb_hash_size(hash);
+}
+#endif
+
+#ifdef HAVE_RB_HASH_SET_IFNONE
+VALUE hash_spec_rb_hash_set_ifnone(VALUE self, VALUE hash, VALUE def) {
+ return rb_hash_set_ifnone(hash, def);
+}
+#endif
+
+void Init_hash_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiHashSpecs", rb_cObject);
+
+#ifdef HAVE_RB_HASH
+ rb_define_method(cls, "rb_hash", hash_spec_rb_hash, 1);
+#endif
+
+#ifdef HAVE_RB_HASH2
+ rb_define_method(cls, "rb_Hash", hash_spec_rb_Hash, 1);
+#endif
+
+#ifdef HAVE_RB_HASH_DUP
+ rb_define_method(cls, "rb_hash_dup", hash_spec_rb_hash_dup, 1);
+#endif
+
+#ifdef HAVE_RB_HASH_FREEZE
+ rb_define_method(cls, "rb_hash_freeze", hash_spec_rb_hash_freeze, 1);
+#endif
+
+#ifdef HAVE_RB_HASH_AREF
+ rb_define_method(cls, "rb_hash_aref", hash_spec_rb_hash_aref, 2);
+ rb_define_method(cls, "rb_hash_aref_nil", hash_spec_rb_hash_aref_nil, 2);
+#endif
+
+#ifdef HAVE_RB_HASH_ASET
+ rb_define_method(cls, "rb_hash_aset", hash_spec_rb_hash_aset, 3);
+#endif
+
+#ifdef HAVE_RB_HASH_CLEAR
+ rb_define_method(cls, "rb_hash_clear", hash_spec_rb_hash_clear, 1);
+#endif
+
+#ifdef HAVE_RB_HASH_DELETE
+ rb_define_method(cls, "rb_hash_delete", hash_spec_rb_hash_delete, 2);
+#endif
+
+#ifdef HAVE_RB_HASH_DELETE_IF
+ rb_define_method(cls, "rb_hash_delete_if", hash_spec_rb_hash_delete_if, 1);
+#endif
+
+#ifdef HAVE_RB_HASH_FOREACH
+ rb_define_method(cls, "rb_hash_foreach", hash_spec_rb_hash_foreach, 1);
+ rb_define_method(cls, "rb_hash_foreach_stop", hash_spec_rb_hash_foreach_stop, 1);
+ rb_define_method(cls, "rb_hash_foreach_delete", hash_spec_rb_hash_foreach_delete, 1);
+#endif
+
+#ifdef HAVE_RB_HASH_LOOKUP
+ rb_define_method(cls, "rb_hash_lookup_nil", hash_spec_rb_hash_lookup_nil, 2);
+ rb_define_method(cls, "rb_hash_lookup", hash_spec_rb_hash_lookup, 2);
+#endif
+
+#ifdef HAVE_RB_HASH_LOOKUP2
+ rb_define_method(cls, "rb_hash_lookup2", hash_spec_rb_hash_lookup2, 3);
+#endif
+
+#ifdef HAVE_RB_HASH_NEW
+ rb_define_method(cls, "rb_hash_new", hash_spec_rb_hash_new, 0);
+#endif
+
+#ifdef HAVE_RB_HASH_SIZE
+ rb_define_method(cls, "rb_hash_size", hash_spec_rb_hash_size, 1);
+#endif
+
+#ifdef HAVE_RB_HASH_SET_IFNONE
+ rb_define_method(cls, "rb_hash_set_ifnone", hash_spec_rb_hash_set_ifnone, 2);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/integer_spec.c b/spec/rubyspec/optional/capi/ext/integer_spec.c
new file mode 100644
index 0000000000..821d8373c9
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/integer_spec.c
@@ -0,0 +1,40 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_INTEGER_PACK
+static VALUE integer_spec_rb_integer_pack(VALUE self, VALUE value,
+ VALUE words, VALUE numwords, VALUE wordsize, VALUE nails, VALUE flags)
+{
+ int result = rb_integer_pack(value, (void*)RSTRING_PTR(words), FIX2INT(numwords),
+ FIX2INT(wordsize), FIX2INT(nails), FIX2INT(flags));
+ return INT2FIX(result);
+}
+#endif
+
+void Init_integer_spec(void) {
+#ifdef HAVE_RB_INTEGER_PACK
+ VALUE cls;
+ cls = rb_define_class("CApiIntegerSpecs", rb_cObject);
+
+ rb_define_const(cls, "MSWORD", INT2NUM(INTEGER_PACK_MSWORD_FIRST));
+ rb_define_const(cls, "LSWORD", INT2NUM(INTEGER_PACK_LSWORD_FIRST));
+ rb_define_const(cls, "MSBYTE", INT2NUM(INTEGER_PACK_MSBYTE_FIRST));
+ rb_define_const(cls, "LSBYTE", INT2NUM(INTEGER_PACK_LSBYTE_FIRST));
+ rb_define_const(cls, "NATIVE", INT2NUM(INTEGER_PACK_NATIVE_BYTE_ORDER));
+ rb_define_const(cls, "PACK_2COMP", INT2NUM(INTEGER_PACK_2COMP));
+ rb_define_const(cls, "LITTLE_ENDIAN", INT2NUM(INTEGER_PACK_LITTLE_ENDIAN));
+ rb_define_const(cls, "BIG_ENDIAN", INT2NUM(INTEGER_PACK_BIG_ENDIAN));
+ rb_define_const(cls, "FORCE_BIGNUM", INT2NUM(INTEGER_PACK_FORCE_BIGNUM));
+ rb_define_const(cls, "NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE));
+
+ rb_define_method(cls, "rb_integer_pack", integer_spec_rb_integer_pack, 6);
+#endif
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/io_spec.c b/spec/rubyspec/optional/capi/ext/io_spec.c
new file mode 100644
index 0000000000..982284deab
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/io_spec.c
@@ -0,0 +1,296 @@
+#include "ruby.h"
+#include "rubyspec.h"
+#include "ruby/io.h"
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static int set_non_blocking(int fd) {
+ int flags;
+#if defined(O_NONBLOCK)
+ if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
+ flags = 0;
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+#else
+ flags = 1;
+ return ioctl(fd, FIOBIO, &flags);
+#endif
+}
+
+#ifdef HAVE_GET_OPEN_FILE
+static int io_spec_get_fd(VALUE io) {
+ rb_io_t* fp;
+ GetOpenFile(io, fp);
+ return fp->fd;
+}
+
+VALUE io_spec_GetOpenFile_fd(VALUE self, VALUE io) {
+ return INT2NUM(io_spec_get_fd(io));
+}
+#endif
+
+#ifdef HAVE_RB_IO_ADDSTR
+VALUE io_spec_rb_io_addstr(VALUE self, VALUE io, VALUE str) {
+ return rb_io_addstr(io, str);
+}
+#endif
+
+#ifdef HAVE_RB_IO_PRINTF
+VALUE io_spec_rb_io_printf(VALUE self, VALUE io, VALUE ary) {
+ long argc = RARRAY_LEN(ary);
+ VALUE *argv = alloca(sizeof(VALUE) * argc);
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ argv[i] = rb_ary_entry(ary, i);
+ }
+
+ return rb_io_printf((int)argc, argv, io);
+}
+#endif
+
+#ifdef HAVE_RB_IO_PRINT
+VALUE io_spec_rb_io_print(VALUE self, VALUE io, VALUE ary) {
+ long argc = RARRAY_LEN(ary);
+ VALUE *argv = alloca(sizeof(VALUE) * argc);
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ argv[i] = rb_ary_entry(ary, i);
+ }
+
+ return rb_io_print((int)argc, argv, io);
+}
+#endif
+
+#ifdef HAVE_RB_IO_PUTS
+VALUE io_spec_rb_io_puts(VALUE self, VALUE io, VALUE ary) {
+ long argc = RARRAY_LEN(ary);
+ VALUE *argv = alloca(sizeof(VALUE) * argc);
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ argv[i] = rb_ary_entry(ary, i);
+ }
+
+ return rb_io_puts((int)argc, argv, io);
+}
+#endif
+
+#ifdef HAVE_RB_IO_WRITE
+VALUE io_spec_rb_io_write(VALUE self, VALUE io, VALUE str) {
+ return rb_io_write(io, str);
+}
+#endif
+
+#ifdef HAVE_RB_IO_CHECK_IO
+VALUE io_spec_rb_io_check_io(VALUE self, VALUE io) {
+ return rb_io_check_io(io);
+}
+#endif
+
+#ifdef HAVE_RB_IO_CHECK_READABLE
+VALUE io_spec_rb_io_check_readable(VALUE self, VALUE io) {
+ rb_io_t* fp;
+ GetOpenFile(io, fp);
+ rb_io_check_readable(fp);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_IO_CHECK_WRITABLE
+VALUE io_spec_rb_io_check_writable(VALUE self, VALUE io) {
+ rb_io_t* fp;
+ GetOpenFile(io, fp);
+ rb_io_check_writable(fp);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_IO_CHECK_CLOSED
+VALUE io_spec_rb_io_check_closed(VALUE self, VALUE io) {
+ rb_io_t* fp;
+ GetOpenFile(io, fp);
+ rb_io_check_closed(fp);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_IO_TAINT_CHECK
+VALUE io_spec_rb_io_taint_check(VALUE self, VALUE io) {
+ /*rb_io_t* fp;
+ GetOpenFile(io, fp);*/
+ rb_io_taint_check(io);
+ return io;
+}
+#endif
+
+typedef int wait_bool;
+#define wait_bool_to_ruby_bool(x) (x ? Qtrue : Qfalse)
+
+#ifdef HAVE_RB_IO_WAIT_READABLE
+#define RB_IO_WAIT_READABLE_BUF 13
+
+VALUE io_spec_rb_io_wait_readable(VALUE self, VALUE io, VALUE read_p) {
+ int fd = io_spec_get_fd(io);
+ char buf[RB_IO_WAIT_READABLE_BUF];
+ wait_bool ret;
+
+ set_non_blocking(fd);
+
+ if(RTEST(read_p)) {
+ rb_ivar_set(self, rb_intern("@write_data"), Qtrue);
+ if(read(fd, buf, RB_IO_WAIT_READABLE_BUF) != -1) {
+ return Qnil;
+ }
+ }
+
+ ret = rb_io_wait_readable(fd);
+
+ if(RTEST(read_p)) {
+ if(read(fd, buf, RB_IO_WAIT_READABLE_BUF) != 13) {
+ return Qnil;
+ }
+ rb_ivar_set(self, rb_intern("@read_data"),
+ rb_str_new(buf, RB_IO_WAIT_READABLE_BUF));
+ }
+
+ return wait_bool_to_ruby_bool(ret);
+}
+#endif
+
+#ifdef HAVE_RB_IO_WAIT_WRITABLE
+VALUE io_spec_rb_io_wait_writable(VALUE self, VALUE io) {
+ wait_bool ret;
+ ret = rb_io_wait_writable(io_spec_get_fd(io));
+ return wait_bool_to_ruby_bool(ret);
+}
+#endif
+
+#ifdef HAVE_RB_THREAD_WAIT_FD
+VALUE io_spec_rb_thread_wait_fd(VALUE self, VALUE io) {
+ rb_thread_wait_fd(io_spec_get_fd(io));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_THREAD_FD_WRITABLE
+VALUE io_spec_rb_thread_fd_writable(VALUE self, VALUE io) {
+ rb_thread_fd_writable(io_spec_get_fd(io));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_IO_BINMODE
+VALUE io_spec_rb_io_binmode(VALUE self, VALUE io) {
+ return rb_io_binmode(io);
+}
+#endif
+
+#ifdef HAVE_RB_FD_FIX_CLOEXEC
+VALUE io_spec_rb_fd_fix_cloexec(VALUE self, VALUE io) {
+ rb_fd_fix_cloexec(io_spec_get_fd(io));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_CLOEXEC_OPEN
+VALUE io_spec_rb_cloexec_open(VALUE self, VALUE path, VALUE flags, VALUE mode) {
+ const char *pathname = StringValuePtr(path);
+ int fd = rb_cloexec_open(pathname, FIX2INT(flags), FIX2INT(mode));
+ return rb_funcall(rb_cIO, rb_intern("for_fd"), 1, INT2FIX(fd));
+}
+#endif
+
+#ifdef HAVE_RB_IO_CLOSE
+VALUE io_spec_rb_io_close(VALUE self, VALUE io) {
+ return rb_io_close(io);
+}
+#endif
+
+void Init_io_spec(void) {
+ VALUE cls = rb_define_class("CApiIOSpecs", rb_cObject);
+
+#ifdef HAVE_GET_OPEN_FILE
+ rb_define_method(cls, "GetOpenFile_fd", io_spec_GetOpenFile_fd, 1);
+#endif
+
+#ifdef HAVE_RB_IO_ADDSTR
+ rb_define_method(cls, "rb_io_addstr", io_spec_rb_io_addstr, 2);
+#endif
+
+#ifdef HAVE_RB_IO_PRINTF
+ rb_define_method(cls, "rb_io_printf", io_spec_rb_io_printf, 2);
+#endif
+
+#ifdef HAVE_RB_IO_PRINT
+ rb_define_method(cls, "rb_io_print", io_spec_rb_io_print, 2);
+#endif
+
+#ifdef HAVE_RB_IO_PUTS
+ rb_define_method(cls, "rb_io_puts", io_spec_rb_io_puts, 2);
+#endif
+
+#ifdef HAVE_RB_IO_WRITE
+ rb_define_method(cls, "rb_io_write", io_spec_rb_io_write, 2);
+#endif
+
+#ifdef HAVE_RB_IO_CLOSE
+ rb_define_method(cls, "rb_io_close", io_spec_rb_io_close, 1);
+#endif
+
+#ifdef HAVE_RB_IO_CHECK_IO
+ rb_define_method(cls, "rb_io_check_io", io_spec_rb_io_check_io, 1);
+#endif
+
+#ifdef HAVE_RB_IO_CHECK_READABLE
+ rb_define_method(cls, "rb_io_check_readable", io_spec_rb_io_check_readable, 1);
+#endif
+
+#ifdef HAVE_RB_IO_CHECK_WRITABLE
+ rb_define_method(cls, "rb_io_check_writable", io_spec_rb_io_check_writable, 1);
+#endif
+
+#ifdef HAVE_RB_IO_CHECK_CLOSED
+ rb_define_method(cls, "rb_io_check_closed", io_spec_rb_io_check_closed, 1);
+#endif
+
+#ifdef HAVE_RB_IO_TAINT_CHECK
+ rb_define_method(cls, "rb_io_taint_check", io_spec_rb_io_taint_check, 1);
+#endif
+
+#ifdef HAVE_RB_IO_WAIT_READABLE
+ rb_define_method(cls, "rb_io_wait_readable", io_spec_rb_io_wait_readable, 2);
+#endif
+
+#ifdef HAVE_RB_IO_WAIT_WRITABLE
+ rb_define_method(cls, "rb_io_wait_writable", io_spec_rb_io_wait_writable, 1);
+#endif
+
+#ifdef HAVE_RB_THREAD_WAIT_FD
+ rb_define_method(cls, "rb_thread_wait_fd", io_spec_rb_thread_wait_fd, 1);
+#endif
+
+#ifdef HAVE_RB_THREAD_FD_WRITABLE
+ rb_define_method(cls, "rb_thread_fd_writable", io_spec_rb_thread_fd_writable, 1);
+#endif
+
+#ifdef HAVE_RB_IO_BINMODE
+ rb_define_method(cls, "rb_io_binmode", io_spec_rb_io_binmode, 1);
+#endif
+
+#ifdef HAVE_RB_FD_FIX_CLOEXEC
+ rb_define_method(cls, "rb_fd_fix_cloexec", io_spec_rb_fd_fix_cloexec, 1);
+#endif
+
+#ifdef HAVE_RB_CLOEXEC_OPEN
+ rb_define_method(cls, "rb_cloexec_open", io_spec_rb_cloexec_open, 3);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/jruby.h b/spec/rubyspec/optional/capi/ext/jruby.h
new file mode 100644
index 0000000000..00a9789f14
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/jruby.h
@@ -0,0 +1,10 @@
+#ifndef RUBYSPEC_CAPI_JRUBY_H
+#define RUBYSPEC_CAPI_JRUBY_H
+
+/* #undef any HAVE_ defines that JRuby does not have. */
+#undef HAVE_RB_DEFINE_HOOKED_VARIABLE
+#undef HAVE_RB_DEFINE_VARIABLE
+
+#undef HAVE_RB_EXEC_RECURSIVE
+
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/kernel_spec.c b/spec/rubyspec/optional/capi/ext/kernel_spec.c
new file mode 100644
index 0000000000..d855b5689f
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/kernel_spec.c
@@ -0,0 +1,404 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <errno.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+VALUE kernel_spec_call_proc(VALUE arg_array) {
+ VALUE arg = rb_ary_pop(arg_array);
+ VALUE proc = rb_ary_pop(arg_array);
+ return rb_funcall(proc, rb_intern("call"), 1, arg);
+}
+
+#ifdef HAVE_RB_BLOCK_GIVEN_P
+static VALUE kernel_spec_rb_block_given_p(VALUE self) {
+ return rb_block_given_p() ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_NEED_BLOCK
+VALUE kernel_spec_rb_need_block(VALUE self) {
+ rb_need_block();
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_BLOCK_PROC
+VALUE kernel_spec_rb_block_proc(VALUE self) {
+ return rb_block_proc();
+}
+#endif
+
+#ifdef HAVE_RB_BLOCK_CALL
+
+VALUE block_call_inject(VALUE yield_value, VALUE data2) {
+ /* yield_value yields the first block argument */
+ VALUE elem = yield_value;
+ VALUE elem_incr = INT2FIX(FIX2INT(elem) + 1);
+ return elem_incr;
+}
+
+VALUE kernel_spec_rb_block_call(VALUE self, VALUE ary) {
+ return rb_block_call(ary, rb_intern("map"), 0, NULL, block_call_inject, Qnil);
+}
+
+VALUE block_call_inject_multi_arg(VALUE yield_value, VALUE data2, int argc, VALUE argv[]) {
+ /* yield_value yields the first block argument */
+ VALUE sum = yield_value;
+ VALUE elem = argv[1];
+
+ return INT2FIX(FIX2INT(sum) + FIX2INT(elem));
+}
+
+VALUE kernel_spec_rb_block_call_multi_arg(VALUE self, VALUE ary) {
+ VALUE method_args[1];
+ method_args[0] = INT2FIX(0);
+ return rb_block_call(ary, rb_intern("inject"), 1, method_args, block_call_inject_multi_arg, Qnil);
+}
+
+VALUE kernel_spec_rb_block_call_no_func(VALUE self, VALUE ary) {
+ return rb_block_call(ary, rb_intern("map"), 0, NULL, NULL, Qnil);
+}
+
+#endif
+
+#ifdef HAVE_RB_ENSURE
+VALUE kernel_spec_rb_ensure(VALUE self, VALUE main_proc, VALUE arg,
+ VALUE ensure_proc, VALUE arg2) {
+ VALUE main_array, ensure_array;
+
+ main_array = rb_ary_new();
+ rb_ary_push(main_array, main_proc);
+ rb_ary_push(main_array, arg);
+
+ ensure_array = rb_ary_new();
+ rb_ary_push(ensure_array, ensure_proc);
+ rb_ary_push(ensure_array, arg2);
+
+ return rb_ensure(kernel_spec_call_proc, main_array,
+ kernel_spec_call_proc, ensure_array);
+}
+#endif
+
+#ifdef HAVE_RB_CATCH
+VALUE kernel_spec_call_proc_with_catch(VALUE arg, VALUE data) {
+ return rb_funcall(data, rb_intern("call"), 0);
+}
+
+VALUE kernel_spec_rb_catch(VALUE self, VALUE sym, VALUE main_proc) {
+ return rb_catch(StringValuePtr(sym), kernel_spec_call_proc_with_catch, main_proc);
+}
+#endif
+
+#ifdef HAVE_RB_CATCH_OBJ
+VALUE kernel_spec_call_proc_with_catch_obj(VALUE arg, VALUE data) {
+ return rb_funcall(data, rb_intern("call"), 0);
+}
+
+VALUE kernel_spec_rb_catch_obj(VALUE self, VALUE obj, VALUE main_proc) {
+ return rb_catch_obj(obj, kernel_spec_call_proc_with_catch, main_proc);
+}
+#endif
+
+#ifdef HAVE_RB_EVAL_STRING
+VALUE kernel_spec_rb_eval_string(VALUE self, VALUE str) {
+ return rb_eval_string(RSTRING_PTR(str));
+}
+#endif
+
+#ifdef HAVE_RB_RAISE
+VALUE kernel_spec_rb_raise(VALUE self, VALUE hash) {
+ rb_hash_aset(hash, ID2SYM(rb_intern("stage")), ID2SYM(rb_intern("before")));
+ if (self != Qundef)
+ rb_raise(rb_eTypeError, "Wrong argument type %s (expected %s)", "Integer", "String");
+ rb_hash_aset(hash, ID2SYM(rb_intern("stage")), ID2SYM(rb_intern("after")));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_THROW
+VALUE kernel_spec_rb_throw(VALUE self, VALUE result) {
+ if (self != Qundef) rb_throw("foo", result);
+ return ID2SYM(rb_intern("rb_throw_failed"));
+}
+#endif
+
+#ifdef HAVE_RB_THROW_OBJ
+VALUE kernel_spec_rb_throw_obj(VALUE self, VALUE obj, VALUE result) {
+ if (self != Qundef) rb_throw_obj(obj, result);
+ return ID2SYM(rb_intern("rb_throw_failed"));
+}
+#endif
+
+#ifdef HAVE_RB_RESCUE
+VALUE kernel_spec_call_proc_with_raised_exc(VALUE arg_array, VALUE raised_exc) {
+ VALUE argv[2];
+ int argc;
+
+ VALUE arg = rb_ary_pop(arg_array);
+ VALUE proc = rb_ary_pop(arg_array);
+
+ argv[0] = arg;
+ argv[1] = raised_exc;
+
+ argc = 2;
+
+ return rb_funcall2(proc, rb_intern("call"), argc, argv);
+}
+
+VALUE kernel_spec_rb_rescue(VALUE self, VALUE main_proc, VALUE arg,
+ VALUE raise_proc, VALUE arg2) {
+ VALUE main_array, raise_array;
+
+ main_array = rb_ary_new();
+ rb_ary_push(main_array, main_proc);
+ rb_ary_push(main_array, arg);
+
+ raise_array = rb_ary_new();
+ rb_ary_push(raise_array, raise_proc);
+ rb_ary_push(raise_array, arg2);
+
+ return rb_rescue(kernel_spec_call_proc, main_array,
+ kernel_spec_call_proc_with_raised_exc, raise_array);
+}
+#endif
+
+#ifdef HAVE_RB_RESCUE2
+VALUE kernel_spec_rb_rescue2(int argc, VALUE *args, VALUE self) {
+ VALUE main_array, raise_array;
+
+ main_array = rb_ary_new();
+ rb_ary_push(main_array, args[0]);
+ rb_ary_push(main_array, args[1]);
+
+ raise_array = rb_ary_new();
+ rb_ary_push(raise_array, args[2]);
+ rb_ary_push(raise_array, args[3]);
+
+ return rb_rescue2(kernel_spec_call_proc, main_array,
+ kernel_spec_call_proc, raise_array, args[4], args[5], (VALUE)0);
+}
+#endif
+
+#ifdef HAVE_RB_SYS_FAIL
+VALUE kernel_spec_rb_sys_fail(VALUE self, VALUE msg) {
+ errno = 1;
+ if(msg == Qnil) {
+ rb_sys_fail(0);
+ } else if (self != Qundef) {
+ rb_sys_fail(StringValuePtr(msg));
+ }
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_SYSERR_FAIL
+VALUE kernel_spec_rb_syserr_fail(VALUE self, VALUE err, VALUE msg) {
+ if(msg == Qnil) {
+ rb_syserr_fail(NUM2INT(err), NULL);
+ } else if (self != Qundef) {
+ rb_syserr_fail(NUM2INT(err), StringValuePtr(msg));
+ }
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_WARN
+VALUE kernel_spec_rb_warn(VALUE self, VALUE msg) {
+ rb_warn("%s", StringValuePtr(msg));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_YIELD
+static VALUE kernel_spec_rb_yield(VALUE self, VALUE obj) {
+ return rb_yield(obj);
+}
+#endif
+
+#ifdef HAVE_RB_YIELD_SPLAT
+static VALUE kernel_spec_rb_yield_splat(VALUE self, VALUE ary) {
+ return rb_yield_splat(ary);
+}
+#endif
+
+#ifdef HAVE_RB_YIELD_VALUES
+static VALUE kernel_spec_rb_yield_values(VALUE self, VALUE obj1, VALUE obj2) {
+ return rb_yield_values(2, obj1, obj2);
+}
+#endif
+
+#ifdef HAVE_RB_EXEC_RECURSIVE
+static VALUE do_rec(VALUE obj, VALUE arg, int is_rec) {
+ if(is_rec) {
+ return obj;
+ } else if(arg == Qtrue) {
+ return rb_exec_recursive(do_rec, obj, Qnil);
+ } else {
+ return Qnil;
+ }
+}
+
+static VALUE kernel_spec_rb_exec_recursive(VALUE self, VALUE obj) {
+ return rb_exec_recursive(do_rec, obj, Qtrue);
+}
+#endif
+
+#ifdef HAVE_RB_SET_END_PROC
+static void write_io(VALUE io) {
+ rb_funcall(io, rb_intern("write"), 1, rb_str_new2("e"));
+}
+
+static VALUE kernel_spec_rb_set_end_proc(VALUE self, VALUE io) {
+ rb_set_end_proc(write_io, io);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_F_SPRINTF
+static VALUE kernel_spec_rb_f_sprintf(VALUE self, VALUE ary) {
+ return rb_f_sprintf((int)RARRAY_LEN(ary), RARRAY_PTR(ary));
+}
+#endif
+
+#ifdef HAVE_RB_MAKE_BACKTRACE
+static VALUE kernel_spec_rb_make_backtrace(VALUE self) {
+ return rb_make_backtrace();
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_METHOD
+static VALUE kernel_spec_rb_obj_method(VALUE self, VALUE obj, VALUE method) {
+ return rb_obj_method(obj, method);
+}
+#endif
+
+#ifdef HAVE_RB_FUNCALL3
+static VALUE kernel_spec_rb_funcall3(VALUE self, VALUE obj, VALUE method) {
+ return rb_funcall3(obj, SYM2ID(method), 0, NULL);
+}
+#endif
+
+#ifdef HAVE_RB_FUNCALL_WITH_BLOCK
+static VALUE kernel_spec_rb_funcall_with_block(VALUE self, VALUE obj, VALUE method, VALUE block) {
+ return rb_funcall_with_block(obj, SYM2ID(method), 0, NULL, block);
+}
+#endif
+
+void Init_kernel_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiKernelSpecs", rb_cObject);
+
+#ifdef HAVE_RB_BLOCK_GIVEN_P
+ rb_define_method(cls, "rb_block_given_p", kernel_spec_rb_block_given_p, 0);
+#endif
+
+#ifdef HAVE_RB_NEED_BLOCK
+ rb_define_method(cls, "rb_need_block", kernel_spec_rb_need_block, 0);
+#endif
+
+#ifdef HAVE_RB_BLOCK_CALL
+ rb_define_method(cls, "rb_block_call", kernel_spec_rb_block_call, 1);
+ rb_define_method(cls, "rb_block_call_multi_arg", kernel_spec_rb_block_call_multi_arg, 1);
+ rb_define_method(cls, "rb_block_call_no_func", kernel_spec_rb_block_call_no_func, 1);
+#endif
+
+#ifdef HAVE_RB_BLOCK_PROC
+ rb_define_method(cls, "rb_block_proc", kernel_spec_rb_block_proc, 0);
+#endif
+
+#ifdef HAVE_RB_ENSURE
+ rb_define_method(cls, "rb_ensure", kernel_spec_rb_ensure, 4);
+#endif
+
+#ifdef HAVE_RB_EVAL_STRING
+ rb_define_method(cls, "rb_eval_string", kernel_spec_rb_eval_string, 1);
+#endif
+
+#ifdef HAVE_RB_RAISE
+ rb_define_method(cls, "rb_raise", kernel_spec_rb_raise, 1);
+#endif
+
+#ifdef HAVE_RB_THROW
+ rb_define_method(cls, "rb_throw", kernel_spec_rb_throw, 1);
+#endif
+
+#ifdef HAVE_RB_THROW_OBJ
+ rb_define_method(cls, "rb_throw_obj", kernel_spec_rb_throw_obj, 2);
+#endif
+
+#ifdef HAVE_RB_RESCUE
+ rb_define_method(cls, "rb_rescue", kernel_spec_rb_rescue, 4);
+#endif
+
+#ifdef HAVE_RB_RESCUE2
+ rb_define_method(cls, "rb_rescue2", kernel_spec_rb_rescue2, -1);
+#endif
+
+#ifdef HAVE_RB_CATCH
+ rb_define_method(cls, "rb_catch", kernel_spec_rb_catch, 2);
+#endif
+
+#ifdef HAVE_RB_CATCH_OBJ
+ rb_define_method(cls, "rb_catch_obj", kernel_spec_rb_catch_obj, 2);
+#endif
+
+#ifdef HAVE_RB_SYS_FAIL
+ rb_define_method(cls, "rb_sys_fail", kernel_spec_rb_sys_fail, 1);
+#endif
+
+#ifdef HAVE_RB_SYSERR_FAIL
+ rb_define_method(cls, "rb_syserr_fail", kernel_spec_rb_syserr_fail, 2);
+#endif
+
+#ifdef HAVE_RB_WARN
+ rb_define_method(cls, "rb_warn", kernel_spec_rb_warn, 1);
+#endif
+
+#ifdef HAVE_RB_YIELD
+ rb_define_method(cls, "rb_yield", kernel_spec_rb_yield, 1);
+#endif
+
+#ifdef HAVE_RB_YIELD_VALUES
+ rb_define_method(cls, "rb_yield_values", kernel_spec_rb_yield_values, 2);
+#endif
+
+#ifdef HAVE_RB_YIELD_SPLAT
+ rb_define_method(cls, "rb_yield_splat", kernel_spec_rb_yield_splat, 1);
+#endif
+
+#ifdef HAVE_RB_EXEC_RECURSIVE
+ rb_define_method(cls, "rb_exec_recursive", kernel_spec_rb_exec_recursive, 1);
+#endif
+
+#ifdef HAVE_RB_SET_END_PROC
+ rb_define_method(cls, "rb_set_end_proc", kernel_spec_rb_set_end_proc, 1);
+#endif
+
+#ifdef HAVE_RB_F_SPRINTF
+ rb_define_method(cls, "rb_f_sprintf", kernel_spec_rb_f_sprintf, 1);
+#endif
+
+#ifdef HAVE_RB_MAKE_BACKTRACE
+ rb_define_method(cls, "rb_make_backtrace", kernel_spec_rb_make_backtrace, 0);
+#endif
+
+#ifdef HAVE_RB_OBJ_METHOD
+ rb_define_method(cls, "rb_obj_method", kernel_spec_rb_obj_method, 2);
+#endif
+
+#ifdef HAVE_RB_FUNCALL3
+ rb_define_method(cls, "rb_funcall3", kernel_spec_rb_funcall3, 2);
+#endif
+
+#ifdef HAVE_RB_FUNCALL_WITH_BLOCK
+ rb_define_method(cls, "rb_funcall_with_block", kernel_spec_rb_funcall_with_block, 3);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/marshal_spec.c b/spec/rubyspec/optional/capi/ext/marshal_spec.c
new file mode 100644
index 0000000000..dbb6e71abf
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/marshal_spec.c
@@ -0,0 +1,36 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_MARSHAL_DUMP
+VALUE marshal_spec_rb_marshal_dump(VALUE self, VALUE obj, VALUE port) {
+ return rb_marshal_dump(obj, port);
+}
+#endif
+
+#ifdef HAVE_RB_MARSHAL_LOAD
+VALUE marshal_spec_rb_marshal_load(VALUE self, VALUE data) {
+ return rb_marshal_load(data);
+}
+#endif
+
+void Init_marshal_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiMarshalSpecs", rb_cObject);
+
+#ifdef HAVE_RB_MARSHAL_DUMP
+ rb_define_method(cls, "rb_marshal_dump", marshal_spec_rb_marshal_dump, 2);
+#endif
+
+#ifdef HAVE_RB_MARSHAL_LOAD
+ rb_define_method(cls, "rb_marshal_load", marshal_spec_rb_marshal_load, 1);
+#endif
+
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/module_spec.c b/spec/rubyspec/optional/capi/ext/module_spec.c
new file mode 100644
index 0000000000..275bc4da32
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/module_spec.c
@@ -0,0 +1,252 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static VALUE module_specs_test_method(VALUE self) {
+ return ID2SYM(rb_intern("test_method"));
+}
+
+#ifdef HAVE_RB_CONST_DEFINED
+static VALUE module_specs_const_defined(VALUE self, VALUE klass, VALUE id) {
+ return rb_const_defined(klass, SYM2ID(id)) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_CONST_DEFINED_AT
+static VALUE module_specs_const_defined_at(VALUE self, VALUE klass, VALUE id) {
+ return rb_const_defined_at(klass, SYM2ID(id)) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_CONST_GET
+static VALUE module_specs_const_get(VALUE self, VALUE klass, VALUE val) {
+ return rb_const_get(klass, SYM2ID(val));
+}
+#endif
+
+#ifdef HAVE_RB_CONST_GET_AT
+static VALUE module_specs_const_get_at(VALUE self, VALUE klass, VALUE val) {
+ return rb_const_get_at(klass, SYM2ID(val));
+}
+#endif
+
+#ifdef HAVE_RB_CONST_GET_FROM
+static VALUE module_specs_const_get_from(VALUE self, VALUE klass, VALUE val) {
+ return rb_const_get_from(klass, SYM2ID(val));
+}
+#endif
+
+#ifdef HAVE_RB_CONST_SET
+static VALUE module_specs_const_set(VALUE self, VALUE klass, VALUE name, VALUE val) {
+ rb_const_set(klass, SYM2ID(name), val);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_ALIAS
+static VALUE module_specs_rb_define_alias(VALUE self, VALUE obj,
+ VALUE new_name, VALUE old_name) {
+
+ rb_define_alias(obj, RSTRING_PTR(new_name), RSTRING_PTR(old_name));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_ALIAS
+static VALUE module_specs_rb_alias(VALUE self, VALUE obj,
+ VALUE new_name, VALUE old_name) {
+
+ rb_alias(obj, SYM2ID(new_name), SYM2ID(old_name));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_MODULE
+static VALUE module_specs_rb_define_module(VALUE self, VALUE name) {
+ return rb_define_module(RSTRING_PTR(name));
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_MODULE_UNDER
+static VALUE module_specs_rb_define_module_under(VALUE self, VALUE outer, VALUE name) {
+ return rb_define_module_under(outer, RSTRING_PTR(name));
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_CONST
+static VALUE module_specs_define_const(VALUE self, VALUE klass, VALUE str_name, VALUE val) {
+ rb_define_const(klass, RSTRING_PTR(str_name), val);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_GLOBAL_CONST
+static VALUE module_specs_define_global_const(VALUE self, VALUE str_name, VALUE obj) {
+ rb_define_global_const(RSTRING_PTR(str_name), obj);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_GLOBAL_FUNCTION
+static VALUE module_specs_rb_define_global_function(VALUE self, VALUE str_name) {
+ rb_define_global_function(RSTRING_PTR(str_name), module_specs_test_method, 0);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_METHOD
+static VALUE module_specs_rb_define_method(VALUE self, VALUE cls, VALUE str_name) {
+ rb_define_method(cls, RSTRING_PTR(str_name), module_specs_test_method, 0);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_MODULE_FUNCTION
+static VALUE module_specs_rb_define_module_function(VALUE self, VALUE cls, VALUE str_name) {
+ rb_define_module_function(cls, RSTRING_PTR(str_name), module_specs_test_method, 0);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_PRIVATE_METHOD
+static VALUE module_specs_rb_define_private_method(VALUE self, VALUE cls, VALUE str_name) {
+ rb_define_private_method(cls, RSTRING_PTR(str_name), module_specs_test_method, 0);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_PROTECTED_METHOD
+static VALUE module_specs_rb_define_protected_method(VALUE self, VALUE cls, VALUE str_name) {
+ rb_define_protected_method(cls, RSTRING_PTR(str_name), module_specs_test_method, 0);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_DEFINE_SINGLETON_METHOD
+static VALUE module_specs_rb_define_singleton_method(VALUE self, VALUE cls, VALUE str_name) {
+ rb_define_singleton_method(cls, RSTRING_PTR(str_name), module_specs_test_method, 0);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_UNDEF_METHOD
+static VALUE module_specs_rb_undef_method(VALUE self, VALUE cls, VALUE str_name) {
+ rb_undef_method(cls, RSTRING_PTR(str_name));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_UNDEF
+static VALUE module_specs_rb_undef(VALUE self, VALUE cls, VALUE symbol_name) {
+ rb_undef(cls, SYM2ID(symbol_name));
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_CLASS2NAME
+static VALUE module_specs_rbclass2name(VALUE self, VALUE klass) {
+ return rb_str_new2(rb_class2name(klass));
+}
+#endif
+
+void Init_module_spec(void) {
+ VALUE cls;
+
+ cls = rb_define_class("CApiModuleSpecs", rb_cObject);
+
+#ifdef HAVE_RB_CONST_DEFINED
+ rb_define_method(cls, "rb_const_defined", module_specs_const_defined, 2);
+#endif
+
+#ifdef HAVE_RB_CONST_DEFINED_AT
+ rb_define_method(cls, "rb_const_defined_at", module_specs_const_defined_at, 2);
+#endif
+
+#ifdef HAVE_RB_CONST_GET
+ rb_define_method(cls, "rb_const_get", module_specs_const_get, 2);
+#endif
+
+#ifdef HAVE_RB_CONST_GET_AT
+ rb_define_method(cls, "rb_const_get_at", module_specs_const_get_at, 2);
+#endif
+
+#ifdef HAVE_RB_CONST_GET_FROM
+ rb_define_method(cls, "rb_const_get_from", module_specs_const_get_from, 2);
+#endif
+
+#ifdef HAVE_RB_CONST_SET
+ rb_define_method(cls, "rb_const_set", module_specs_const_set, 3);
+#endif
+
+#ifdef HAVE_RB_DEFINE_ALIAS
+ rb_define_method(cls, "rb_define_alias", module_specs_rb_define_alias, 3);
+#endif
+
+#ifdef HAVE_RB_ALIAS
+ rb_define_method(cls, "rb_alias", module_specs_rb_alias, 3);
+#endif
+
+#ifdef HAVE_RB_DEFINE_MODULE
+ rb_define_method(cls, "rb_define_module", module_specs_rb_define_module, 1);
+#endif
+
+#ifdef HAVE_RB_DEFINE_MODULE_UNDER
+ rb_define_method(cls, "rb_define_module_under", module_specs_rb_define_module_under, 2);
+#endif
+
+#ifdef HAVE_RB_DEFINE_CONST
+ rb_define_method(cls, "rb_define_const", module_specs_define_const, 3);
+#endif
+
+#ifdef HAVE_RB_DEFINE_GLOBAL_CONST
+ rb_define_method(cls, "rb_define_global_const", module_specs_define_global_const, 2);
+#endif
+
+#ifdef HAVE_RB_DEFINE_GLOBAL_FUNCTION
+ rb_define_method(cls, "rb_define_global_function",
+ module_specs_rb_define_global_function, 1);
+#endif
+
+#ifdef HAVE_RB_DEFINE_METHOD
+ rb_define_method(cls, "rb_define_method", module_specs_rb_define_method, 2);
+#endif
+
+#ifdef HAVE_RB_DEFINE_MODULE_FUNCTION
+ rb_define_method(cls, "rb_define_module_function",
+ module_specs_rb_define_module_function, 2);
+#endif
+
+#ifdef HAVE_RB_DEFINE_PRIVATE_METHOD
+ rb_define_method(cls, "rb_define_private_method",
+ module_specs_rb_define_private_method, 2);
+#endif
+
+#ifdef HAVE_RB_DEFINE_PROTECTED_METHOD
+ rb_define_method(cls, "rb_define_protected_method",
+ module_specs_rb_define_protected_method, 2);
+#endif
+
+#ifdef HAVE_RB_DEFINE_SINGLETON_METHOD
+ rb_define_method(cls, "rb_define_singleton_method",
+ module_specs_rb_define_singleton_method, 2);
+#endif
+
+#ifdef HAVE_RB_UNDEF_METHOD
+ rb_define_method(cls, "rb_undef_method", module_specs_rb_undef_method, 2);
+#endif
+
+#ifdef HAVE_RB_UNDEF
+ rb_define_method(cls, "rb_undef", module_specs_rb_undef, 2);
+#endif
+
+#ifdef HAVE_RB_CLASS2NAME
+ rb_define_method(cls, "rb_class2name", module_specs_rbclass2name, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/module_under_autoload_spec.c b/spec/rubyspec/optional/capi/ext/module_under_autoload_spec.c
new file mode 100644
index 0000000000..c8f19a287b
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/module_under_autoload_spec.c
@@ -0,0 +1,7 @@
+#include "ruby.h"
+
+void Init_module_under_autoload_spec(void) {
+ VALUE specs = rb_const_get(rb_cObject, rb_intern("CApiModuleSpecs"));
+ rb_define_module_under(specs, "ModuleUnderAutoload");
+ rb_define_module_under(specs, "RubyUnderAutoload");
+}
diff --git a/spec/rubyspec/optional/capi/ext/mutex_spec.c b/spec/rubyspec/optional/capi/ext/mutex_spec.c
new file mode 100644
index 0000000000..d5ce06e124
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/mutex_spec.c
@@ -0,0 +1,91 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_MUTEX_NEW
+VALUE mutex_spec_rb_mutex_new(VALUE self) {
+ return rb_mutex_new();
+}
+#endif
+
+#ifdef HAVE_RB_MUTEX_LOCKED_P
+VALUE mutex_spec_rb_mutex_locked_p(VALUE self, VALUE mutex) {
+ return rb_mutex_locked_p(mutex);
+}
+#endif
+
+#ifdef HAVE_RB_MUTEX_TRYLOCK
+VALUE mutex_spec_rb_mutex_trylock(VALUE self, VALUE mutex) {
+ return rb_mutex_trylock(mutex);
+}
+#endif
+
+#ifdef HAVE_RB_MUTEX_LOCK
+VALUE mutex_spec_rb_mutex_lock(VALUE self, VALUE mutex) {
+ return rb_mutex_lock(mutex);
+}
+#endif
+
+#ifdef HAVE_RB_MUTEX_UNLOCK
+VALUE mutex_spec_rb_mutex_unlock(VALUE self, VALUE mutex) {
+ return rb_mutex_unlock(mutex);
+}
+#endif
+
+#ifdef HAVE_RB_MUTEX_SLEEP
+VALUE mutex_spec_rb_mutex_sleep(VALUE self, VALUE mutex, VALUE timeout) {
+ return rb_mutex_sleep(mutex, timeout);
+}
+#endif
+
+#ifdef HAVE_RB_MUTEX_SYNCHRONIZE
+
+VALUE mutex_spec_rb_mutex_callback(VALUE arg) {
+ return rb_funcall(arg, rb_intern("call"), 0);
+}
+
+VALUE mutex_spec_rb_mutex_synchronize(VALUE self, VALUE mutex, VALUE value) {
+ return rb_mutex_synchronize(mutex, mutex_spec_rb_mutex_callback, value);
+}
+#endif
+
+void Init_mutex_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiMutexSpecs", rb_cObject);
+
+#ifdef HAVE_RB_MUTEX_NEW
+ rb_define_method(cls, "rb_mutex_new", mutex_spec_rb_mutex_new, 0);
+#endif
+
+#ifdef HAVE_RB_MUTEX_LOCKED_P
+ rb_define_method(cls, "rb_mutex_locked_p", mutex_spec_rb_mutex_locked_p, 1);
+#endif
+
+#ifdef HAVE_RB_MUTEX_TRYLOCK
+ rb_define_method(cls, "rb_mutex_trylock", mutex_spec_rb_mutex_trylock, 1);
+#endif
+
+#ifdef HAVE_RB_MUTEX_LOCK
+ rb_define_method(cls, "rb_mutex_lock", mutex_spec_rb_mutex_lock, 1);
+#endif
+
+#ifdef HAVE_RB_MUTEX_UNLOCK
+ rb_define_method(cls, "rb_mutex_unlock", mutex_spec_rb_mutex_unlock, 1);
+#endif
+
+#ifdef HAVE_RB_MUTEX_SLEEP
+ rb_define_method(cls, "rb_mutex_sleep", mutex_spec_rb_mutex_sleep, 2);
+#endif
+
+#ifdef HAVE_RB_MUTEX_SYNCHRONIZE
+ rb_define_method(cls, "rb_mutex_synchronize", mutex_spec_rb_mutex_synchronize, 2);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/spec/rubyspec/optional/capi/ext/numeric_spec.c b/spec/rubyspec/optional/capi/ext/numeric_spec.c
new file mode 100644
index 0000000000..cd643cc66f
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/numeric_spec.c
@@ -0,0 +1,166 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_NUM2CHR
+static VALUE numeric_spec_NUM2CHR(VALUE self, VALUE value) {
+ return INT2FIX(NUM2CHR(value));
+}
+#endif
+
+#ifdef HAVE_RB_INT2INUM
+static VALUE numeric_spec_rb_int2inum_14(VALUE self) {
+ return rb_int2inum(14);
+}
+#endif
+
+#ifdef HAVE_RB_INTEGER
+static VALUE numeric_spec_rb_Integer(VALUE self, VALUE str) {
+ return rb_Integer(str);
+}
+#endif
+
+#ifdef HAVE_RB_LL2INUM
+static VALUE numeric_spec_rb_ll2inum_14(VALUE self) {
+ return rb_ll2inum(14);
+}
+#endif
+
+#ifdef HAVE_RB_NUM2DBL
+static VALUE numeric_spec_rb_num2dbl(VALUE self, VALUE num) {
+ return rb_float_new(rb_num2dbl(num));
+}
+#endif
+
+#ifdef HAVE_RB_NUM2INT
+static VALUE numeric_spec_rb_num2int(VALUE self, VALUE num) {
+ return LONG2NUM(rb_num2int(num));
+}
+#endif
+
+#ifdef HAVE_RB_INT2NUM
+static VALUE numeric_spec_rb_int2num(VALUE self, VALUE num) {
+ return INT2NUM(rb_num2long(num));
+}
+#endif
+
+#ifdef HAVE_RB_NUM2LONG
+static VALUE numeric_spec_rb_num2long(VALUE self, VALUE num) {
+ return LONG2NUM(rb_num2long(num));
+}
+#endif
+
+#ifdef HAVE_RB_NUM2UINT
+static VALUE numeric_spec_rb_num2uint(VALUE self, VALUE num) {
+ return ULONG2NUM(rb_num2uint(num));
+}
+#endif
+
+#ifdef HAVE_RB_NUM2ULONG
+static VALUE numeric_spec_rb_num2ulong(VALUE self, VALUE num) {
+ return ULONG2NUM(rb_num2ulong(num));
+}
+#endif
+
+#ifdef HAVE_RB_NUM_ZERODIV
+static VALUE numeric_spec_rb_num_zerodiv(VALUE self) {
+ rb_num_zerodiv();
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_CMPINT
+static VALUE numeric_spec_rb_cmpint(VALUE self, VALUE val, VALUE b) {
+ return INT2FIX(rb_cmpint(val, val, b));
+}
+#endif
+
+#ifdef HAVE_RB_NUM_COERCE_BIN
+static VALUE numeric_spec_rb_num_coerce_bin(VALUE self, VALUE x, VALUE y, VALUE op) {
+ return rb_num_coerce_bin(x, y, SYM2ID(op));
+}
+#endif
+
+#ifdef HAVE_RB_NUM_COERCE_CMP
+static VALUE numeric_spec_rb_num_coerce_cmp(VALUE self, VALUE x, VALUE y, VALUE op) {
+ return rb_num_coerce_cmp(x, y, SYM2ID(op));
+}
+#endif
+
+#ifdef HAVE_RB_NUM_COERCE_RELOP
+static VALUE numeric_spec_rb_num_coerce_relop(VALUE self, VALUE x, VALUE y, VALUE op) {
+ return rb_num_coerce_relop(x, y, SYM2ID(op));
+}
+#endif
+
+void Init_numeric_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiNumericSpecs", rb_cObject);
+
+#ifdef HAVE_NUM2CHR
+ rb_define_method(cls, "NUM2CHR", numeric_spec_NUM2CHR, 1);
+#endif
+
+#ifdef HAVE_RB_INT2INUM
+ rb_define_method(cls, "rb_int2inum_14", numeric_spec_rb_int2inum_14, 0);
+#endif
+
+#ifdef HAVE_RB_INTEGER
+ rb_define_method(cls, "rb_Integer", numeric_spec_rb_Integer, 1);
+#endif
+
+#ifdef HAVE_RB_LL2INUM
+ rb_define_method(cls, "rb_ll2inum_14", numeric_spec_rb_ll2inum_14, 0);
+#endif
+
+#ifdef HAVE_RB_NUM2DBL
+ rb_define_method(cls, "rb_num2dbl", numeric_spec_rb_num2dbl, 1);
+#endif
+
+#ifdef HAVE_RB_NUM2INT
+ rb_define_method(cls, "rb_num2int", numeric_spec_rb_num2int, 1);
+#endif
+
+#ifdef HAVE_RB_NUM2LONG
+ rb_define_method(cls, "rb_num2long", numeric_spec_rb_num2long, 1);
+#endif
+
+#ifdef HAVE_RB_INT2NUM
+ rb_define_method(cls, "rb_int2num", numeric_spec_rb_int2num, 1);
+#endif
+
+#ifdef HAVE_RB_NUM2UINT
+ rb_define_method(cls, "rb_num2uint", numeric_spec_rb_num2uint, 1);
+#endif
+
+#ifdef HAVE_RB_NUM2ULONG
+ rb_define_method(cls, "rb_num2ulong", numeric_spec_rb_num2ulong, 1);
+#endif
+
+#ifdef HAVE_RB_NUM_ZERODIV
+ rb_define_method(cls, "rb_num_zerodiv", numeric_spec_rb_num_zerodiv, 0);
+#endif
+
+#ifdef HAVE_RB_CMPINT
+ rb_define_method(cls, "rb_cmpint", numeric_spec_rb_cmpint, 2);
+#endif
+
+#ifdef HAVE_RB_NUM_COERCE_BIN
+ rb_define_method(cls, "rb_num_coerce_bin", numeric_spec_rb_num_coerce_bin, 3);
+#endif
+
+#ifdef HAVE_RB_NUM_COERCE_CMP
+ rb_define_method(cls, "rb_num_coerce_cmp", numeric_spec_rb_num_coerce_cmp, 3);
+#endif
+
+#ifdef HAVE_RB_NUM_COERCE_RELOP
+ rb_define_method(cls, "rb_num_coerce_relop", numeric_spec_rb_num_coerce_relop, 3);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/object_spec.c b/spec/rubyspec/optional/capi/ext/object_spec.c
new file mode 100644
index 0000000000..ad1ebecc78
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/object_spec.c
@@ -0,0 +1,608 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_OBJ_TAINT
+static VALUE object_spec_OBJ_TAINT(VALUE self, VALUE obj) {
+ OBJ_TAINT(obj);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_OBJ_TAINTED
+static VALUE object_spec_OBJ_TAINTED(VALUE self, VALUE obj) {
+ return OBJ_TAINTED(obj) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_OBJ_INFECT
+static VALUE object_spec_OBJ_INFECT(VALUE self, VALUE host, VALUE source) {
+ OBJ_INFECT(host, source);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_ANY_TO_S
+static VALUE object_spec_rb_any_to_s(VALUE self, VALUE obj) {
+ return rb_any_to_s(obj);
+}
+#endif
+
+#ifdef HAVE_RB_ATTR_GET
+static VALUE so_attr_get(VALUE self, VALUE obj, VALUE attr) {
+ return rb_attr_get(obj, SYM2ID(attr));
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_INSTANCE_VARIABLES
+static VALUE object_spec_rb_obj_instance_variables(VALUE self, VALUE obj) {
+ return rb_obj_instance_variables(obj);
+}
+#endif
+
+#ifdef HAVE_RB_CHECK_ARRAY_TYPE
+static VALUE so_check_array_type(VALUE self, VALUE ary) {
+ return rb_check_array_type(ary);
+}
+#endif
+
+#ifdef HAVE_RB_CHECK_CONVERT_TYPE
+static VALUE so_check_convert_type(VALUE self, VALUE obj, VALUE klass, VALUE method) {
+ return rb_check_convert_type(obj, T_ARRAY, RSTRING_PTR(klass), RSTRING_PTR(method));
+}
+#endif
+
+#ifdef HAVE_RB_CHECK_TO_INTEGER
+static VALUE so_check_to_integer(VALUE self, VALUE obj, VALUE method) {
+ return rb_check_to_integer(obj, RSTRING_PTR(method));
+}
+#endif
+
+#ifdef HAVE_RB_CHECK_FROZEN
+static VALUE object_spec_rb_check_frozen(VALUE self, VALUE obj) {
+ rb_check_frozen(obj);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_CHECK_STRING_TYPE
+static VALUE so_check_string_type(VALUE self, VALUE str) {
+ return rb_check_string_type(str);
+}
+#endif
+
+#ifdef HAVE_RB_CLASS_OF
+static VALUE so_rbclassof(VALUE self, VALUE obj) {
+ return rb_class_of(obj);
+}
+#endif
+
+#ifdef HAVE_RB_CONVERT_TYPE
+static VALUE so_convert_type(VALUE self, VALUE obj, VALUE klass, VALUE method) {
+ return rb_convert_type(obj, T_ARRAY, RSTRING_PTR(klass), RSTRING_PTR(method));
+}
+#endif
+
+#ifdef HAVE_RB_EXTEND_OBJECT
+static VALUE object_spec_rb_extend_object(VALUE self, VALUE obj, VALUE mod) {
+ rb_extend_object(obj, mod);
+ return obj;
+}
+#endif
+
+#ifdef HAVE_RB_INSPECT
+static VALUE so_inspect(VALUE self, VALUE obj) {
+ return rb_inspect(obj);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_ALLOC
+static VALUE so_rb_obj_alloc(VALUE self, VALUE klass) {
+ return rb_obj_alloc(klass);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_DUP
+static VALUE so_rb_obj_dup(VALUE self, VALUE klass) {
+ return rb_obj_dup(klass);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_CALL_INIT
+static VALUE so_rb_obj_call_init(VALUE self, VALUE object,
+ VALUE nargs, VALUE args) {
+ int c_nargs = FIX2INT(nargs);
+ VALUE *c_args = alloca(sizeof(VALUE) * c_nargs);
+ int i;
+
+ for (i = 0; i < c_nargs; i++)
+ c_args[i] = rb_ary_entry(args, i);
+
+ rb_obj_call_init(object, c_nargs, c_args);
+
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_CLASSNAME
+static VALUE so_rbobjclassname(VALUE self, VALUE obj) {
+ return rb_str_new2(rb_obj_classname(obj));
+}
+
+#endif
+
+#ifdef HAVE_RB_OBJ_FREEZE
+static VALUE object_spec_rb_obj_freeze(VALUE self, VALUE obj) {
+ return rb_obj_freeze(obj);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_FROZEN_P
+static VALUE object_spec_rb_obj_frozen_p(VALUE self, VALUE obj) {
+ return rb_obj_frozen_p(obj);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_ID
+static VALUE object_spec_rb_obj_id(VALUE self, VALUE obj) {
+ return rb_obj_id(obj);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_IS_INSTANCE_OF
+static VALUE so_instance_of(VALUE self, VALUE obj, VALUE klass) {
+ return rb_obj_is_instance_of(obj, klass);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_IS_KIND_OF
+static VALUE so_kind_of(VALUE self, VALUE obj, VALUE klass) {
+ return rb_obj_is_kind_of(obj, klass);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_METHOD_ARITY
+static VALUE object_specs_rb_obj_method_arity(VALUE self, VALUE obj, VALUE mid) {
+ return INT2FIX(rb_obj_method_arity(obj, SYM2ID(mid)));
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_TAINT
+static VALUE object_spec_rb_obj_taint(VALUE self, VALUE obj) {
+ return rb_obj_taint(obj);
+}
+#endif
+
+#ifdef HAVE_RB_REQUIRE
+static VALUE so_require(VALUE self) {
+ rb_require("fixtures/foo");
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_RESPOND_TO
+static VALUE so_respond_to(VALUE self, VALUE obj, VALUE sym) {
+ return rb_respond_to(obj, SYM2ID(sym)) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_RESPOND_TO
+static VALUE so_obj_respond_to(VALUE self, VALUE obj, VALUE sym, VALUE priv) {
+ return rb_obj_respond_to(obj, SYM2ID(sym), priv == Qtrue ? 1 : 0) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_METHOD_BOUNDP
+static VALUE object_spec_rb_method_boundp(VALUE self, VALUE obj, VALUE method, VALUE exclude_private) {
+ ID id = SYM2ID(method);
+ return rb_method_boundp(obj, id, exclude_private == Qtrue ? 1 : 0) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_SPECIAL_CONST_P
+static VALUE object_spec_rb_special_const_p(VALUE self, VALUE value) {
+ return rb_special_const_p(value);
+}
+#endif
+
+#ifdef HAVE_RB_TO_ID
+static VALUE so_to_id(VALUE self, VALUE obj) {
+ return ID2SYM(rb_to_id(obj));
+}
+#endif
+
+#ifdef HAVE_RTEST
+static VALUE object_spec_RTEST(VALUE self, VALUE value) {
+ return RTEST(value) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_TYPE
+static VALUE so_is_type_nil(VALUE self, VALUE obj) {
+ if(TYPE(obj) == T_NIL) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_type_object(VALUE self, VALUE obj) {
+ if(TYPE(obj) == T_OBJECT) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_type_array(VALUE self, VALUE obj) {
+ if(TYPE(obj) == T_ARRAY) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_type_module(VALUE self, VALUE obj) {
+ if(TYPE(obj) == T_MODULE) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_type_class(VALUE self, VALUE obj) {
+ if(TYPE(obj) == T_CLASS) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_type_data(VALUE self, VALUE obj) {
+ if(TYPE(obj) == T_DATA) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_TYPE_P
+static VALUE so_is_rb_type_p_nil(VALUE self, VALUE obj) {
+ if(rb_type_p(obj, T_NIL)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_rb_type_p_object(VALUE self, VALUE obj) {
+ if(rb_type_p(obj, T_OBJECT)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_rb_type_p_array(VALUE self, VALUE obj) {
+ if(rb_type_p(obj, T_ARRAY)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_rb_type_p_module(VALUE self, VALUE obj) {
+ if(rb_type_p(obj, T_MODULE)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_rb_type_p_class(VALUE self, VALUE obj) {
+ if(rb_type_p(obj, T_CLASS)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_rb_type_p_data(VALUE self, VALUE obj) {
+ if(rb_type_p(obj, T_DATA)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+#endif
+
+#ifdef HAVE_BUILTIN_TYPE
+static VALUE so_is_builtin_type_object(VALUE self, VALUE obj) {
+ if(BUILTIN_TYPE(obj) == T_OBJECT) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_builtin_type_array(VALUE self, VALUE obj) {
+ if(BUILTIN_TYPE(obj) == T_ARRAY) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_builtin_type_module(VALUE self, VALUE obj) {
+ if(BUILTIN_TYPE(obj) == T_MODULE) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_builtin_type_class(VALUE self, VALUE obj) {
+ if(BUILTIN_TYPE(obj) == T_CLASS) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE so_is_builtin_type_data(VALUE self, VALUE obj) {
+ if(BUILTIN_TYPE(obj) == T_DATA) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_TO_INT
+static VALUE object_spec_rb_to_int(VALUE self, VALUE obj) {
+ return rb_to_int(obj);
+}
+#endif
+
+#ifdef HAVE_RB_OBJ_INSTANCE_EVAL
+static VALUE object_spec_rb_obj_instance_eval(VALUE self, VALUE obj) {
+ return rb_obj_instance_eval(0, NULL, obj);
+}
+#endif
+
+#ifdef HAVE_RB_IV_GET
+static VALUE object_spec_rb_iv_get(VALUE self, VALUE obj, VALUE name) {
+ return rb_iv_get(obj, RSTRING_PTR(name));
+}
+#endif
+
+#ifdef HAVE_RB_IV_SET
+static VALUE object_spec_rb_iv_set(VALUE self, VALUE obj, VALUE name, VALUE value) {
+ return rb_iv_set(obj, RSTRING_PTR(name), value);
+}
+#endif
+
+#ifdef HAVE_RB_IVAR_GET
+static VALUE object_spec_rb_ivar_get(VALUE self, VALUE obj, VALUE sym_name) {
+ return rb_ivar_get(obj, SYM2ID(sym_name));
+}
+#endif
+
+#ifdef HAVE_RB_IVAR_SET
+static VALUE object_spec_rb_ivar_set(VALUE self, VALUE obj, VALUE sym_name, VALUE value) {
+ return rb_ivar_set(obj, SYM2ID(sym_name), value);
+}
+#endif
+
+#ifdef HAVE_RB_IVAR_DEFINED
+static VALUE object_spec_rb_ivar_defined(VALUE self, VALUE obj, VALUE sym_name) {
+ return rb_ivar_defined(obj, SYM2ID(sym_name));
+}
+#endif
+
+#ifdef HAVE_RB_EQUAL
+static VALUE object_spec_rb_equal(VALUE self, VALUE a, VALUE b) {
+ return rb_equal(a, b);
+}
+#endif
+
+#ifdef HAVE_RB_CLASS_INHERITED_P
+static VALUE object_spec_rb_class_inherited_p(VALUE self, VALUE mod, VALUE arg) {
+ return rb_class_inherited_p(mod, arg);
+}
+#endif
+
+
+void Init_object_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiObjectSpecs", rb_cObject);
+
+#ifdef HAVE_OBJ_TAINT
+ rb_define_method(cls, "OBJ_TAINT", object_spec_OBJ_TAINT, 1);
+#endif
+
+#ifdef HAVE_OBJ_TAINTED
+ rb_define_method(cls, "OBJ_TAINTED", object_spec_OBJ_TAINTED, 1);
+#endif
+
+#ifdef HAVE_OBJ_INFECT
+ rb_define_method(cls, "OBJ_INFECT", object_spec_OBJ_INFECT, 2);
+#endif
+
+#ifdef HAVE_RB_ANY_TO_S
+ rb_define_method(cls, "rb_any_to_s", object_spec_rb_any_to_s, 1);
+#endif
+
+#ifdef HAVE_RB_ATTR_GET
+ rb_define_method(cls, "rb_attr_get", so_attr_get, 2);
+#endif
+
+#ifdef HAVE_RB_OBJ_INSTANCE_VARIABLES
+ rb_define_method(cls, "rb_obj_instance_variables", object_spec_rb_obj_instance_variables, 1);
+#endif
+
+#ifdef HAVE_RB_CHECK_ARRAY_TYPE
+ rb_define_method(cls, "rb_check_array_type", so_check_array_type, 1);
+#endif
+
+#ifdef HAVE_RB_CHECK_CONVERT_TYPE
+ rb_define_method(cls, "rb_check_convert_type", so_check_convert_type, 3);
+#endif
+
+#ifdef HAVE_RB_CHECK_TO_INTEGER
+ rb_define_method(cls, "rb_check_to_integer", so_check_to_integer, 2);
+#endif
+
+#ifdef HAVE_RB_CHECK_FROZEN
+ rb_define_method(cls, "rb_check_frozen", object_spec_rb_check_frozen, 1);
+#endif
+
+#ifdef HAVE_RB_CHECK_STRING_TYPE
+ rb_define_method(cls, "rb_check_string_type", so_check_string_type, 1);
+#endif
+
+#ifdef HAVE_RB_CLASS_OF
+ rb_define_method(cls, "rb_class_of", so_rbclassof, 1);
+#endif
+
+#ifdef HAVE_RB_CONVERT_TYPE
+ rb_define_method(cls, "rb_convert_type", so_convert_type, 3);
+#endif
+
+#ifdef HAVE_RB_EXTEND_OBJECT
+ rb_define_method(cls, "rb_extend_object", object_spec_rb_extend_object, 2);
+#endif
+
+#ifdef HAVE_RB_INSPECT
+ rb_define_method(cls, "rb_inspect", so_inspect, 1);
+#endif
+
+#ifdef HAVE_RB_OBJ_ALLOC
+ rb_define_method(cls, "rb_obj_alloc", so_rb_obj_alloc, 1);
+#endif
+
+#ifdef HAVE_RB_OBJ_ALLOC
+ rb_define_method(cls, "rb_obj_dup", so_rb_obj_dup, 1);
+#endif
+
+#ifdef HAVE_RB_OBJ_CALL_INIT
+ rb_define_method(cls, "rb_obj_call_init", so_rb_obj_call_init, 3);
+#endif
+
+#ifdef HAVE_RB_OBJ_CLASSNAME
+ rb_define_method(cls, "rb_obj_classname", so_rbobjclassname, 1);
+#endif
+
+#ifdef HAVE_RB_OBJ_FREEZE
+ rb_define_method(cls, "rb_obj_freeze", object_spec_rb_obj_freeze, 1);
+#endif
+
+#ifdef HAVE_RB_OBJ_FROZEN_P
+ rb_define_method(cls, "rb_obj_frozen_p", object_spec_rb_obj_frozen_p, 1);
+#endif
+
+#ifdef HAVE_RB_OBJ_ID
+ rb_define_method(cls, "rb_obj_id", object_spec_rb_obj_id, 1);
+#endif
+
+#ifdef HAVE_RB_OBJ_IS_INSTANCE_OF
+ rb_define_method(cls, "rb_obj_is_instance_of", so_instance_of, 2);
+#endif
+
+#ifdef HAVE_RB_OBJ_IS_KIND_OF
+ rb_define_method(cls, "rb_obj_is_kind_of", so_kind_of, 2);
+#endif
+
+#ifdef HAVE_RB_OBJ_METHOD_ARITY
+ rb_define_method(cls, "rb_obj_method_arity", object_specs_rb_obj_method_arity, 2);
+#endif
+
+#ifdef HAVE_RB_OBJ_TAINT
+ rb_define_method(cls, "rb_obj_taint", object_spec_rb_obj_taint, 1);
+#endif
+
+#ifdef HAVE_RB_REQUIRE
+ rb_define_method(cls, "rb_require", so_require, 0);
+#endif
+
+#ifdef HAVE_RB_RESPOND_TO
+ rb_define_method(cls, "rb_respond_to", so_respond_to, 2);
+#endif
+
+#ifdef HAVE_RB_METHOD_BOUNDP
+ rb_define_method(cls, "rb_method_boundp", object_spec_rb_method_boundp, 3);
+#endif
+
+#ifdef HAVE_RB_OBJ_RESPOND_TO
+ rb_define_method(cls, "rb_obj_respond_to", so_obj_respond_to, 3);
+#endif
+
+#ifdef HAVE_RB_SPECIAL_CONST_P
+ rb_define_method(cls, "rb_special_const_p", object_spec_rb_special_const_p, 1);
+#endif
+
+#ifdef HAVE_RB_STR_NEW2
+#endif
+
+#ifdef HAVE_RB_TO_ID
+ rb_define_method(cls, "rb_to_id", so_to_id, 1);
+#endif
+
+#ifdef HAVE_RTEST
+ rb_define_method(cls, "RTEST", object_spec_RTEST, 1);
+#endif
+
+#ifdef HAVE_TYPE
+ rb_define_method(cls, "rb_is_type_nil", so_is_type_nil, 1);
+ rb_define_method(cls, "rb_is_type_object", so_is_type_object, 1);
+ rb_define_method(cls, "rb_is_type_array", so_is_type_array, 1);
+ rb_define_method(cls, "rb_is_type_module", so_is_type_module, 1);
+ rb_define_method(cls, "rb_is_type_class", so_is_type_class, 1);
+ rb_define_method(cls, "rb_is_type_data", so_is_type_data, 1);
+#endif
+
+#ifdef HAVE_RB_TYPE_P
+ rb_define_method(cls, "rb_is_rb_type_p_nil", so_is_rb_type_p_nil, 1);
+ rb_define_method(cls, "rb_is_rb_type_p_object", so_is_rb_type_p_object, 1);
+ rb_define_method(cls, "rb_is_rb_type_p_array", so_is_rb_type_p_array, 1);
+ rb_define_method(cls, "rb_is_rb_type_p_module", so_is_rb_type_p_module, 1);
+ rb_define_method(cls, "rb_is_rb_type_p_class", so_is_rb_type_p_class, 1);
+ rb_define_method(cls, "rb_is_rb_type_p_data", so_is_rb_type_p_data, 1);
+#endif
+
+#ifdef HAVE_BUILTIN_TYPE
+ rb_define_method(cls, "rb_is_builtin_type_object", so_is_builtin_type_object, 1);
+ rb_define_method(cls, "rb_is_builtin_type_array", so_is_builtin_type_array, 1);
+ rb_define_method(cls, "rb_is_builtin_type_module", so_is_builtin_type_module, 1);
+ rb_define_method(cls, "rb_is_builtin_type_class", so_is_builtin_type_class, 1);
+ rb_define_method(cls, "rb_is_builtin_type_data", so_is_builtin_type_data, 1);
+#endif
+
+#ifdef HAVE_RB_TO_INT
+ rb_define_method(cls, "rb_to_int", object_spec_rb_to_int, 1);
+#endif
+
+#ifdef HAVE_RB_EQUAL
+ rb_define_method(cls, "rb_equal", object_spec_rb_equal, 2);
+#endif
+
+#ifdef HAVE_RB_CLASS_INHERITED_P
+ rb_define_method(cls, "rb_class_inherited_p", object_spec_rb_class_inherited_p, 2);
+#endif
+
+#ifdef HAVE_RB_OBJ_INSTANCE_EVAL
+ rb_define_method(cls, "rb_obj_instance_eval", object_spec_rb_obj_instance_eval, 1);
+#endif
+
+#ifdef HAVE_RB_IV_GET
+ rb_define_method(cls, "rb_iv_get", object_spec_rb_iv_get, 2);
+#endif
+
+#ifdef HAVE_RB_IV_SET
+ rb_define_method(cls, "rb_iv_set", object_spec_rb_iv_set, 3);
+#endif
+
+#ifdef HAVE_RB_IVAR_GET
+ rb_define_method(cls, "rb_ivar_get", object_spec_rb_ivar_get, 2);
+#endif
+
+#ifdef HAVE_RB_IVAR_SET
+ rb_define_method(cls, "rb_ivar_set", object_spec_rb_ivar_set, 3);
+#endif
+
+#ifdef HAVE_RB_IVAR_DEFINED
+ rb_define_method(cls, "rb_ivar_defined", object_spec_rb_ivar_defined, 2);
+#endif
+
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/proc_spec.c b/spec/rubyspec/optional/capi/ext/proc_spec.c
new file mode 100644
index 0000000000..b7a47536d9
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/proc_spec.c
@@ -0,0 +1,65 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_PROC_NEW
+VALUE proc_spec_rb_proc_new_function(VALUE args) {
+ return rb_funcall(args, rb_intern("inspect"), 0);
+}
+
+VALUE proc_spec_rb_proc_new(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function, Qnil);
+}
+#endif
+
+/* This helper is not strictly necessary but reflects the code in wxRuby that
+ * originally exposed issues with this Proc.new behavior.
+ */
+VALUE proc_spec_rb_Proc_new_helper(void) {
+ return rb_funcall(rb_cProc, rb_intern("new"), 0);
+}
+
+VALUE proc_spec_rb_Proc_new(VALUE self, VALUE scenario) {
+ switch(FIX2INT(scenario)) {
+ case 0:
+ return proc_spec_rb_Proc_new_helper();
+ case 1:
+ rb_funcall(self, rb_intern("call_nothing"), 0);
+ return proc_spec_rb_Proc_new_helper();
+ case 2:
+ return rb_funcall(self, rb_intern("call_Proc_new"), 0);
+ case 3:
+ return rb_funcall(self, rb_intern("call_rb_Proc_new"), 0);
+ case 4:
+ return rb_funcall(self, rb_intern("call_rb_Proc_new_with_block"), 0);
+ case 5:
+ rb_funcall(self, rb_intern("call_rb_Proc_new_with_block"), 0);
+ return proc_spec_rb_Proc_new_helper();
+ case 6:
+ return rb_funcall(self, rb_intern("call_block_given?"), 0);
+ default:
+ rb_raise(rb_eException, "invalid scenario");
+ }
+
+ return Qnil;
+}
+
+void Init_proc_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiProcSpecs", rb_cObject);
+
+#ifdef HAVE_RB_PROC_NEW
+ rb_define_method(cls, "rb_proc_new", proc_spec_rb_proc_new, 0);
+#endif
+
+ rb_define_method(cls, "rb_Proc_new", proc_spec_rb_Proc_new, 1);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/range_spec.c b/spec/rubyspec/optional/capi/ext/range_spec.c
new file mode 100644
index 0000000000..02aff5a5c2
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/range_spec.c
@@ -0,0 +1,47 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_RANGE_NEW
+VALUE range_spec_rb_range_new(int argc, VALUE* argv, VALUE self) {
+ int exclude_end = 0;
+ if(argc == 3) {
+ exclude_end = RTEST(argv[2]);
+ }
+ return rb_range_new(argv[0], argv[1], exclude_end);
+}
+#endif
+
+#ifdef HAVE_RB_RANGE_VALUES
+VALUE range_spec_rb_range_values(VALUE self, VALUE range) {
+ VALUE beg;
+ VALUE end;
+ int excl;
+ VALUE ary = rb_ary_new();
+ rb_range_values(range, &beg, &end, &excl);
+ rb_ary_store(ary, 0, beg);
+ rb_ary_store(ary, 1, end);
+ rb_ary_store(ary, 2, excl ? Qtrue : Qfalse);
+ return ary;
+}
+#endif
+
+void Init_range_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiRangeSpecs", rb_cObject);
+
+#ifdef HAVE_RB_RANGE_NEW
+ rb_define_method(cls, "rb_range_new", range_spec_rb_range_new, -1);
+#endif
+
+#ifdef HAVE_RB_RANGE_VALUES
+ rb_define_method(cls, "rb_range_values", range_spec_rb_range_values, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/rational_spec.c b/spec/rubyspec/optional/capi/ext/rational_spec.c
new file mode 100644
index 0000000000..9f349261a0
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/rational_spec.c
@@ -0,0 +1,95 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_RATIONAL
+static VALUE rational_spec_rb_Rational(VALUE self, VALUE num, VALUE den) {
+ return rb_Rational(num, den);
+}
+#endif
+
+#ifdef HAVE_RB_RATIONAL1
+static VALUE rational_spec_rb_Rational1(VALUE self, VALUE num) {
+ return rb_Rational1(num);
+}
+#endif
+
+#ifdef HAVE_RB_RATIONAL2
+static VALUE rational_spec_rb_Rational2(VALUE self, VALUE num, VALUE den) {
+ return rb_Rational2(num, den);
+}
+#endif
+
+#ifdef HAVE_RB_RATIONAL_NEW
+static VALUE rational_spec_rb_rational_new(VALUE self, VALUE num, VALUE den) {
+ return rb_rational_new(num, den);
+}
+#endif
+
+#ifdef HAVE_RB_RATIONAL_NEW1
+static VALUE rational_spec_rb_rational_new1(VALUE self, VALUE num) {
+ return rb_rational_new1(num);
+}
+#endif
+
+#ifdef HAVE_RB_RATIONAL_NEW2
+static VALUE rational_spec_rb_rational_new2(VALUE self, VALUE num, VALUE den) {
+ return rb_rational_new2(num, den);
+}
+#endif
+
+#ifdef HAVE_RB_RATIONAL_NUM
+static VALUE rational_spec_rb_rational_num(VALUE self, VALUE rational) {
+ return rb_rational_num(rational);
+}
+#endif
+
+#ifdef HAVE_RB_RATIONAL_DEN
+static VALUE rational_spec_rb_rational_den(VALUE self, VALUE rational) {
+ return rb_rational_den(rational);
+}
+#endif
+
+void Init_rational_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiRationalSpecs", rb_cObject);
+
+#ifdef HAVE_RB_RATIONAL
+ rb_define_method(cls, "rb_Rational", rational_spec_rb_Rational, 2);
+#endif
+
+#ifdef HAVE_RB_RATIONAL1
+ rb_define_method(cls, "rb_Rational1", rational_spec_rb_Rational1, 1);
+#endif
+
+#ifdef HAVE_RB_RATIONAL2
+ rb_define_method(cls, "rb_Rational2", rational_spec_rb_Rational2, 2);
+#endif
+
+#ifdef HAVE_RB_RATIONAL_NEW
+ rb_define_method(cls, "rb_rational_new", rational_spec_rb_rational_new, 2);
+#endif
+
+#ifdef HAVE_RB_RATIONAL_NEW1
+ rb_define_method(cls, "rb_rational_new1", rational_spec_rb_rational_new1, 1);
+#endif
+
+#ifdef HAVE_RB_RATIONAL_NEW2
+ rb_define_method(cls, "rb_rational_new2", rational_spec_rb_rational_new2, 2);
+#endif
+
+#ifdef HAVE_RB_RATIONAL_NUM
+ rb_define_method(cls, "rb_rational_num", rational_spec_rb_rational_num, 1);
+#endif
+
+#ifdef HAVE_RB_RATIONAL_DEN
+ rb_define_method(cls, "rb_rational_den", rational_spec_rb_rational_den, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/regexp_spec.c b/spec/rubyspec/optional/capi/ext/regexp_spec.c
new file mode 100644
index 0000000000..1058293444
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/regexp_spec.c
@@ -0,0 +1,84 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include "ruby/re.h"
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_REG_NEW
+VALUE regexp_spec_re(VALUE self) {
+ return rb_reg_new("a", 1, 0);
+}
+#endif
+
+#ifdef HAVE_RB_REG_NTH_MATCH
+VALUE regexp_spec_reg_1st_match(VALUE self, VALUE md) {
+ return rb_reg_nth_match(1, md);
+}
+#endif
+
+#ifdef HAVE_RB_REG_OPTIONS
+VALUE regexp_spec_rb_reg_options(VALUE self, VALUE regexp) {
+ return INT2FIX(rb_reg_options(regexp));
+}
+#endif
+
+#ifdef HAVE_RB_REG_REGCOMP
+VALUE regexp_spec_rb_reg_regcomp(VALUE self, VALUE str) {
+ return rb_reg_regcomp(str);
+}
+#endif
+
+#ifdef HAVE_RB_REG_MATCH
+VALUE regexp_spec_reg_match(VALUE self, VALUE re, VALUE str) {
+ return rb_reg_match(re, str);
+}
+#endif
+
+#ifdef HAVE_RB_BACKREF_GET
+VALUE regexp_spec_backref_get(VALUE self) {
+ return rb_backref_get();
+}
+#endif
+
+VALUE regexp_spec_match(VALUE self, VALUE regexp, VALUE str) {
+ return rb_funcall(regexp, rb_intern("match"), 1, str);
+}
+
+void Init_regexp_spec(void) {
+ VALUE cls = rb_define_class("CApiRegexpSpecs", rb_cObject);
+
+ rb_define_method(cls, "match", regexp_spec_match, 2);
+
+#ifdef HAVE_RB_REG_NEW
+ rb_define_method(cls, "a_re", regexp_spec_re, 0);
+#endif
+
+#ifdef HAVE_RB_REG_NTH_MATCH
+ rb_define_method(cls, "a_re_1st_match", regexp_spec_reg_1st_match, 1);
+#endif
+
+#ifdef HAVE_RB_REG_MATCH
+ rb_define_method(cls, "rb_reg_match", regexp_spec_reg_match, 2);
+#endif
+
+#ifdef HAVE_RB_BACKREF_GET
+ rb_define_method(cls, "rb_backref_get", regexp_spec_backref_get, 0);
+#endif
+
+#ifdef HAVE_RB_REG_OPTIONS
+ rb_define_method(cls, "rb_reg_options", regexp_spec_rb_reg_options, 1);
+#endif
+
+#ifdef HAVE_RB_REG_REGCOMP
+ rb_define_method(cls, "rb_reg_regcomp", regexp_spec_rb_reg_regcomp, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/rubinius.h b/spec/rubyspec/optional/capi/ext/rubinius.h
new file mode 100644
index 0000000000..7ddf73790d
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/rubinius.h
@@ -0,0 +1,8 @@
+#ifndef RUBYSPEC_CAPI_RUBINIUS_H
+#define RUBYSPEC_CAPI_RUBINIUS_H
+
+/* #undef any HAVE_ defines that Rubinius does not have. */
+#undef HAVE_RB_DEFINE_HOOKED_VARIABLE
+#undef HAVE_RB_DEFINE_VARIABLE
+
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/rubyspec.h b/spec/rubyspec/optional/capi/ext/rubyspec.h
new file mode 100644
index 0000000000..f20bdde37c
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/rubyspec.h
@@ -0,0 +1,612 @@
+#ifndef RUBYSPEC_H
+#define RUBYSPEC_H
+
+/* Define convenience macros similar to the mspec guards to assist
+ * with version incompatibilities.
+ */
+
+#include <ruby.h>
+#ifdef HAVE_RUBY_VERSION_H
+# include <ruby/version.h>
+#else
+# include <version.h>
+#endif
+
+#ifndef RUBY_VERSION_MAJOR
+#define RUBY_VERSION_MAJOR RUBY_API_VERSION_MAJOR
+#define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
+#define RUBY_VERSION_TEENY RUBY_API_VERSION_TEENY
+#endif
+
+#define RUBY_VERSION_BEFORE(major,minor,teeny) \
+ ((RUBY_VERSION_MAJOR < (major)) || \
+ (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR < (minor)) || \
+ (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR == (minor) && RUBY_VERSION_TEENY < (teeny)))
+
+#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 4)
+#define RUBY_VERSION_IS_2_4
+#endif
+
+#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 3)
+#define RUBY_VERSION_IS_2_3
+#endif
+
+/* Define all function flags */
+
+/* Array */
+#define HAVE_RB_ARRAY 1
+#define HAVE_RARRAY_AREF 1
+#define HAVE_RARRAY_LEN 1
+#define HAVE_RARRAY_PTR 1
+#define HAVE_RB_ARY_AREF 1
+#define HAVE_RB_ARY_CLEAR 1
+#define HAVE_RB_ARY_DELETE 1
+#define HAVE_RB_ARY_DELETE_AT 1
+#define HAVE_RB_ARY_DUP 1
+#define HAVE_RB_ARY_ENTRY 1
+#define HAVE_RB_ARY_FREEZE 1
+#define HAVE_RB_ARY_INCLUDES 1
+#define HAVE_RB_ARY_JOIN 1
+#define HAVE_RB_ARY_NEW 1
+#define HAVE_RB_ARY_NEW2 1
+#define HAVE_RB_ARY_NEW_CAPA 1
+#define HAVE_RB_ARY_NEW3 1
+#define HAVE_RB_ARY_NEW_FROM_ARGS 1
+#define HAVE_RB_ARY_NEW4 1
+#define HAVE_RB_ARY_NEW_FROM_VALUES 1
+#define HAVE_RB_ARY_POP 1
+#define HAVE_RB_ARY_PUSH 1
+#define HAVE_RB_ARY_CAT 1
+#define HAVE_RB_ARY_REVERSE 1
+#define HAVE_RB_ARY_ROTATE 1
+#define HAVE_RB_ARY_SHIFT 1
+#define HAVE_RB_ARY_STORE 1
+#define HAVE_RB_ARY_CONCAT 1
+#define HAVE_RB_ARY_PLUS 1
+#define HAVE_RB_ARY_TO_ARY 1
+#define HAVE_RB_ARY_SUBSEQ 1
+#define HAVE_RB_ARY_TO_S 1
+#define HAVE_RB_ARY_UNSHIFT 1
+#define HAVE_RB_ASSOC_NEW 1
+
+#define HAVE_RB_EACH 1
+#define HAVE_RB_ITERATE 1
+#define HAVE_RB_MEM_CLEAR 1
+
+/* Bignum */
+#define HAVE_ABSINT_SIZE 1
+#define HAVE_RB_BIG2DBL 1
+#define HAVE_RB_DBL2BIG 1
+#define HAVE_RB_BIG2LL 1
+#define HAVE_RB_BIG2LONG 1
+#define HAVE_RB_BIG2STR 1
+#define HAVE_RB_BIG2ULONG 1
+#define HAVE_RB_BIG_CMP 1
+#define HAVE_RB_BIG_PACK 1
+
+/* Class */
+#define HAVE_RB_CALL_SUPER 1
+#define HAVE_RB_CLASS2NAME 1
+#define HAVE_RB_CLASS_NAME 1
+#define HAVE_RB_CLASS_NEW 1
+#define HAVE_RB_CLASS_NEW_INSTANCE 1
+#define HAVE_RB_CLASS_PATH 1
+#define HAVE_RB_CLASS_REAL 1
+#define HAVE_RB_CVAR_DEFINED 1
+#define HAVE_RB_CVAR_GET 1
+#define HAVE_RB_CVAR_SET 1
+#define HAVE_RB_CV_GET 1
+#define HAVE_RB_CV_SET 1
+#define HAVE_RB_DEFINE_ATTR 1
+#define HAVE_RB_DEFINE_CLASS_VARIABLE 1
+#define HAVE_RB_INCLUDE_MODULE 1
+#define HAVE_RB_PATH2CLASS 1
+#define HAVE_RB_PATH_TO_CLASS 1
+#define HAVE_RB_CLASS_SUPERCLASS 1
+
+/* Complex */
+#define HAVE_RB_COMPLEX 1
+#define HAVE_RB_COMPLEX1 1
+#define HAVE_RB_COMPLEX2 1
+#define HAVE_RB_COMPLEX_NEW 1
+#define HAVE_RB_COMPLEX_NEW1 1
+#define HAVE_RB_COMPLEX_NEW2 1
+
+/* Constants */
+#define HAVE_RB_CARRAY 1
+#ifndef RUBY_INTEGER_UNIFICATION
+#define HAVE_RB_CBIGNUM 1
+#endif
+#define HAVE_RB_CCLASS 1
+#define HAVE_RB_CDATA 1
+#define HAVE_RB_CFALSECLASS 1
+#define HAVE_RB_CFILE 1
+#ifndef RUBY_INTEGER_UNIFICATION
+#define HAVE_RB_CFIXNUM 1
+#endif
+#define HAVE_RB_CFLOAT 1
+#define HAVE_RB_CHASH 1
+#define HAVE_RB_CINTEGER 1
+#define HAVE_RB_CIO 1
+#define HAVE_RB_CMATCH 1
+#define HAVE_RB_CMODULE 1
+#define HAVE_RB_CNILCLASS 1
+#define HAVE_RB_CNUMERIC 1
+#define HAVE_RB_COBJECT 1
+#define HAVE_RB_CPROC 1
+#define HAVE_RB_CMETHOD 1
+#define HAVE_RB_CRANGE 1
+#define HAVE_RB_CREGEXP 1
+#define HAVE_RB_CSTRING 1
+#define HAVE_RB_CSTRUCT 1
+#define HAVE_RB_CSYMBOL 1
+#define HAVE_RB_CTIME 1
+#define HAVE_RB_CTHREAD 1
+#define HAVE_RB_CTRUECLASS 1
+#define HAVE_RB_CNUMERATOR 1
+#define HAVE_RB_EARGERROR 1
+#define HAVE_RB_EEOFERROR 1
+#define HAVE_RB_EEXCEPTION 1
+#define HAVE_RB_EFLOATDOMAINERROR 1
+#define HAVE_RB_EINDEXERROR 1
+#define HAVE_RB_EINTERRUPT 1
+#define HAVE_RB_EIOERROR 1
+#define HAVE_RB_ELOADERROR 1
+#define HAVE_RB_ELOCALJUMPERROR 1
+#define HAVE_RB_EMATHDOMAINERROR 1
+#define HAVE_RB_ENAMEERROR 1
+#define HAVE_RB_ENOMEMERROR 1
+#define HAVE_RB_ENOMETHODERROR 1
+#define HAVE_RB_ENOTIMPERROR 1
+#define HAVE_RB_ERANGEERROR 1
+#define HAVE_RB_EREGEXPERROR 1
+#define HAVE_RB_ERUNTIMEERROR 1
+#define HAVE_RB_ESCRIPTERROR 1
+#define HAVE_RB_ESECURITYERROR 1
+#define HAVE_RB_ESIGNAL 1
+#define HAVE_RB_ESTANDARDERROR 1
+#define HAVE_RB_ESYNTAXERROR 1
+#define HAVE_RB_ESYSSTACKERROR 1
+#define HAVE_RB_ESYSTEMCALLERROR 1
+#define HAVE_RB_ESYSTEMEXIT 1
+#define HAVE_RB_ETHREADERROR 1
+#define HAVE_RB_ETYPEERROR 1
+#define HAVE_RB_EZERODIVERROR 1
+#define HAVE_RB_MCOMPARABLE 1
+#define HAVE_RB_MENUMERABLE 1
+#define HAVE_RB_MERRNO 1
+#define HAVE_RB_MKERNEL 1
+#define HAVE_RB_CDIR 1
+
+/* Data */
+#define HAVE_DATA_WRAP_STRUCT 1
+#define HAVE_RDATA 1
+
+#define HAVE_TYPEDDATA_WRAP_STRUCT 1
+#define HAVE_RTYPEDDATA
+
+/* Encoding */
+#define HAVE_ENCODING_GET 1
+#define HAVE_ENCODING_SET 1
+#define HAVE_ENC_CODERANGE_ASCIIONLY 1
+
+#define HAVE_RB_ASCII8BIT_ENCODING 1
+#define HAVE_RB_ASCII8BIT_ENCINDEX 1
+#define HAVE_RB_USASCII_ENCODING 1
+#define HAVE_RB_USASCII_ENCINDEX 1
+#define HAVE_RB_UTF8_ENCODING 1
+#define HAVE_RB_UTF8_ENCINDEX 1
+#define HAVE_RB_LOCALE_ENCODING 1
+#define HAVE_RB_LOCALE_ENCINDEX 1
+#define HAVE_RB_FILESYSTEM_ENCODING 1
+#define HAVE_RB_FILESYSTEM_ENCINDEX 1
+
+#define HAVE_RB_DEFAULT_INTERNAL_ENCODING 1
+#define HAVE_RB_DEFAULT_EXTERNAL_ENCODING 1
+
+#define HAVE_RB_ENCDB_ALIAS 1
+#define HAVE_RB_ENC_ASSOCIATE 1
+#define HAVE_RB_ENC_ASSOCIATE_INDEX 1
+#define HAVE_RB_ENC_CODEPOINT_LEN 1
+#define HAVE_RB_ENC_COMPATIBLE 1
+#define HAVE_RB_ENC_COPY 1
+#define HAVE_RB_ENC_FIND 1
+#define HAVE_RB_ENC_FIND_INDEX 1
+#define HAVE_RB_ENC_FROM_ENCODING 1
+#define HAVE_RB_ENC_FROM_INDEX 1
+#define HAVE_RB_ENC_GET 1
+#define HAVE_RB_ENC_GET_INDEX 1
+#define HAVE_RB_ENC_SET_INDEX 1
+#define HAVE_RB_ENC_STR_CODERANGE 1
+#define HAVE_RB_ENC_STR_NEW 1
+#define HAVE_RB_ENC_TO_INDEX 1
+#define HAVE_RB_OBJ_ENCODING 1
+
+#define HAVE_RB_STR_ENCODE 1
+#define HAVE_RB_STR_NEW_CSTR 1
+#define HAVE_RB_USASCII_STR_NEW 1
+#define HAVE_RB_USASCII_STR_NEW_CSTR 1
+#define HAVE_RB_EXTERNAL_STR_NEW 1
+#define HAVE_RB_EXTERNAL_STR_NEW_CSTR 1
+#define HAVE_RB_EXTERNAL_STR_NEW_WITH_ENC 1
+
+#define HAVE_RB_TO_ENCODING 1
+#define HAVE_RB_TO_ENCODING_INDEX 1
+#define HAVE_RB_ENC_NTH 1
+
+#define HAVE_RB_EENCCOMPATERROR 1
+
+#define HAVE_RB_MWAITREADABLE 1
+#define HAVE_RB_MWAITWRITABLE 1
+
+#define HAVE_RSTRING_LENINT 1
+#define HAVE_TIMET2NUM 1
+
+#define HAVE_RB_LONG2INT 1
+#define HAVE_RB_INTERN3 1
+
+#define HAVE_RB_ITER_BREAK 1
+#define HAVE_RB_SOURCEFILE 1
+#define HAVE_RB_SOURCELINE 1
+#define HAVE_RB_METHOD_BOUNDP 1
+
+/* Enumerable */
+#define HAVE_RB_ENUMERATORIZE 1
+
+/* Exception */
+#define HAVE_RB_EXC_NEW 1
+#define HAVE_RB_EXC_NEW2 1
+#define HAVE_RB_EXC_NEW3 1
+#define HAVE_RB_EXC_RAISE 1
+#define HAVE_RB_SET_ERRINFO 1
+
+/* File */
+#define HAVE_RB_FILE_OPEN 1
+#define HAVE_RB_FILE_OPEN_STR 1
+#define HAVE_FILEPATHVALUE 1
+
+/* Float */
+#define HAVE_RB_FLOAT_NEW 1
+#define HAVE_RB_RFLOAT 1
+#define HAVE_RFLOAT_VALUE 1
+
+/* Globals */
+#define HAVE_RB_DEFAULT_RS 1
+#define HAVE_RB_DEFINE_HOOKED_VARIABLE 1
+#define HAVE_RB_DEFINE_READONLY_VARIABLE 1
+#define HAVE_RB_DEFINE_VARIABLE 1
+#define HAVE_RB_F_GLOBAL_VARIABLES 1
+#define HAVE_RB_GV_GET 1
+#define HAVE_RB_GV_SET 1
+#define HAVE_RB_RS 1
+#define HAVE_RB_OUTPUT_RS 1
+#define HAVE_RB_OUTPUT_FS 1
+#define HAVE_RB_STDERR 1
+#define HAVE_RB_STDIN 1
+#define HAVE_RB_STDOUT 1
+#define HAVE_RB_DEFOUT 1
+
+#define HAVE_RB_LASTLINE_SET 1
+#define HAVE_RB_LASTLINE_GET 1
+
+/* Hash */
+#define HAVE_RB_HASH 1
+#define HAVE_RB_HASH2 1
+#define HAVE_RB_HASH_DUP 1
+#define HAVE_RB_HASH_FREEZE 1
+#define HAVE_RB_HASH_AREF 1
+#define HAVE_RB_HASH_ASET 1
+#define HAVE_RB_HASH_CLEAR 1
+#define HAVE_RB_HASH_DELETE 1
+#define HAVE_RB_HASH_DELETE_IF 1
+#define HAVE_RB_HASH_FOREACH 1
+#define HAVE_RB_HASH_LOOKUP 1
+#define HAVE_RB_HASH_LOOKUP2 1
+#define HAVE_RB_HASH_NEW 1
+#define HAVE_RB_HASH_SET_IFNONE 1
+#define HAVE_RB_HASH_SIZE 1
+
+/* Integer */
+#define HAVE_RB_INTEGER_PACK 1
+
+/* IO */
+#define HAVE_GET_OPEN_FILE 1
+#define HAVE_RB_IO_ADDSTR 1
+#define HAVE_RB_IO_CHECK_IO 1
+#define HAVE_RB_IO_CHECK_CLOSED 1
+#define HAVE_RB_IO_TAINT_CHECK 1
+#define HAVE_RB_IO_CHECK_READABLE 1
+#define HAVE_RB_IO_CHECK_WRITABLE 1
+#define HAVE_RB_IO_CLOSE 1
+#define HAVE_RB_IO_PRINT 1
+#define HAVE_RB_IO_PRINTF 1
+#define HAVE_RB_IO_PUTS 1
+#define HAVE_RB_IO_WAIT_READABLE 1
+#define HAVE_RB_IO_WAIT_WRITABLE 1
+#define HAVE_RB_IO_WRITE 1
+#define HAVE_RB_IO_BINMODE 1
+
+#define HAVE_RB_THREAD_FD_WRITABLE 1
+#define HAVE_RB_THREAD_WAIT_FD 1
+
+#define HAVE_RB_MUTEX_NEW 1
+#define HAVE_RB_MUTEX_LOCKED_P 1
+#define HAVE_RB_MUTEX_TRYLOCK 1
+#define HAVE_RB_MUTEX_LOCK 1
+#define HAVE_RB_MUTEX_UNLOCK 1
+#define HAVE_RB_MUTEX_SLEEP 1
+#define HAVE_RB_MUTEX_SYNCHRONIZE 1
+
+#define HAVE_RB_FD_FIX_CLOEXEC 1
+#define HAVE_RB_CLOEXEC_OPEN 1
+
+/* Kernel */
+#define HAVE_RB_BLOCK_GIVEN_P 1
+#define HAVE_RB_BLOCK_PROC 1
+#define HAVE_RB_BLOCK_CALL 1
+#define HAVE_RB_ENSURE 1
+#define HAVE_RB_EVAL_STRING 1
+#define HAVE_RB_EXEC_RECURSIVE 1
+#define HAVE_RB_F_SPRINTF 1
+#define HAVE_RB_NEED_BLOCK 1
+#define HAVE_RB_RAISE 1
+#define HAVE_RB_RESCUE 1
+#define HAVE_RB_RESCUE2 1
+#define HAVE_RB_SET_END_PROC 1
+#define HAVE_RB_SYS_FAIL 1
+#define HAVE_RB_SYSERR_FAIL 1
+#define HAVE_RB_MAKE_BACKTRACE 1
+#define HAVE_RB_THROW 1
+#define HAVE_RB_CATCH 1
+#define HAVE_RB_THROW_OBJ 1
+#define HAVE_RB_CATCH_OBJ 1
+#define HAVE_RB_WARN 1
+#define HAVE_RB_YIELD 1
+#define HAVE_RB_YIELD_SPLAT 1
+#define HAVE_RB_YIELD_VALUES 1
+#define HAVE_RB_FUNCALL3 1
+#define HAVE_RB_FUNCALL_WITH_BLOCK 1
+
+/* GC */
+#define HAVE_RB_GC_REGISTER_ADDRESS 1
+#define HAVE_RB_GC_ENABLE 1
+#define HAVE_RB_GC_DISABLE 1
+
+/* Marshal */
+#define HAVE_RB_MARSHAL_DUMP 1
+#define HAVE_RB_MARSHAL_LOAD 1
+
+/* Module */
+#define HAVE_RB_ALIAS 1
+#define HAVE_RB_CONST_DEFINED 1
+#define HAVE_RB_CONST_DEFINED_AT 1
+#define HAVE_RB_CONST_GET 1
+#define HAVE_RB_CONST_GET_AT 1
+#define HAVE_RB_CONST_GET_FROM 1
+#define HAVE_RB_CONST_SET 1
+#define HAVE_RB_DEFINE_ALIAS 1
+#define HAVE_RB_DEFINE_CLASS 1
+#define HAVE_RB_DEFINE_CLASS_UNDER 1
+#define HAVE_RB_DEFINE_CLASS_ID_UNDER 1
+#define HAVE_RB_DEFINE_CONST 1
+#define HAVE_RB_DEFINE_GLOBAL_CONST 1
+#define HAVE_RB_DEFINE_GLOBAL_FUNCTION 1
+#define HAVE_RB_DEFINE_METHOD 1
+#define HAVE_RB_DEFINE_MODULE_FUNCTION 1
+#define HAVE_RB_DEFINE_MODULE 1
+#define HAVE_RB_DEFINE_MODULE_UNDER 1
+#define HAVE_RB_DEFINE_PRIVATE_METHOD 1
+#define HAVE_RB_DEFINE_PROTECTED_METHOD 1
+#define HAVE_RB_DEFINE_SINGLETON_METHOD 1
+#define HAVE_RB_UNDEF 1
+#define HAVE_RB_UNDEF_METHOD 1
+
+/* Numeric */
+#define HAVE_NUM2CHR 1
+#define HAVE_RB_CMPINT 1
+#define HAVE_RB_INT2INUM 1
+#define HAVE_RB_INTEGER 1
+#define HAVE_RB_LL2INUM 1
+#define HAVE_RB_NUM2DBL 1
+#if SIZEOF_INT < SIZEOF_LONG
+#define HAVE_RB_NUM2INT 1
+#define HAVE_RB_NUM2UINT 1
+#endif
+#define HAVE_RB_NUM2LONG 1
+#define HAVE_RB_INT2NUM 1
+#define HAVE_RB_NUM2ULONG 1
+#define HAVE_RB_NUM_COERCE_BIN 1
+#define HAVE_RB_NUM_COERCE_CMP 1
+#define HAVE_RB_NUM_COERCE_RELOP 1
+#define HAVE_RB_NUM_ZERODIV 1
+
+/* Fixnum */
+#if SIZEOF_INT < SIZEOF_LONG
+#define HAVE_RB_FIX2UINT 1
+#define HAVE_RB_FIX2INT 1
+#endif
+
+/* Object */
+#define HAVE_OBJ_TAINT 1
+#define HAVE_OBJ_TAINTED 1
+#define HAVE_OBJ_INFECT 1
+#define HAVE_RB_ANY_TO_S 1
+#define HAVE_RB_ATTR_GET 1
+#define HAVE_RB_OBJ_INSTANCE_VARIABLES 1
+#define HAVE_RB_CHECK_ARRAY_TYPE 1
+#define HAVE_RB_CHECK_CONVERT_TYPE 1
+#define HAVE_RB_CHECK_TO_INTEGER 1
+#define HAVE_RB_CHECK_FROZEN 1
+#define HAVE_RB_CHECK_STRING_TYPE 1
+#define HAVE_RB_CLASS_OF 1
+#define HAVE_RB_CONVERT_TYPE 1
+#define HAVE_RB_EQUAL 1
+#define HAVE_RB_CLASS_INHERITED_P 1
+#define HAVE_RB_EXTEND_OBJECT 1
+#define HAVE_RB_INSPECT 1
+#define HAVE_RB_IVAR_DEFINED 1
+#define HAVE_RB_IVAR_GET 1
+#define HAVE_RB_IVAR_SET 1
+#define HAVE_RB_IV_GET 1
+#define HAVE_RB_IV_SET 1
+#define HAVE_RB_OBJ_ALLOC 1
+#define HAVE_RB_OBJ_CALL_INIT 1
+#define HAVE_RB_OBJ_CLASSNAME 1
+#define HAVE_RB_OBJ_DUP 1
+#define HAVE_RB_OBJ_FREEZE 1
+#define HAVE_RB_OBJ_FROZEN_P 1
+#define HAVE_RB_OBJ_ID 1
+#define HAVE_RB_OBJ_INSTANCE_EVAL 1
+#define HAVE_RB_OBJ_IS_INSTANCE_OF 1
+#define HAVE_RB_OBJ_IS_KIND_OF 1
+#define HAVE_RB_OBJ_TAINT 1
+#define HAVE_RB_OBJ_METHOD 1
+#define HAVE_RB_OBJ_METHOD_ARITY 1
+#define HAVE_RB_REQUIRE 1
+#define HAVE_RB_RESPOND_TO 1
+#define HAVE_RB_OBJ_RESPOND_TO 1
+#define HAVE_RB_SPECIAL_CONST_P 1
+#define HAVE_RB_TO_ID 1
+#define HAVE_RB_TO_INT 1
+#define HAVE_RTEST 1
+#define HAVE_TYPE 1
+#define HAVE_RB_TYPE_P 1
+#define HAVE_BUILTIN_TYPE 1
+
+/* Proc */
+#define HAVE_RB_PROC_NEW 1
+
+/* Range */
+#define HAVE_RB_RANGE_NEW 1
+#define HAVE_RB_RANGE_VALUES 1
+
+/* Rational */
+#define HAVE_RB_RATIONAL 1
+#define HAVE_RB_RATIONAL1 1
+#define HAVE_RB_RATIONAL2 1
+#define HAVE_RB_RATIONAL_NEW 1
+#define HAVE_RB_RATIONAL_NEW1 1
+#define HAVE_RB_RATIONAL_NEW2 1
+#define HAVE_RB_RATIONAL_NUM 1
+#define HAVE_RB_RATIONAL_DEN 1
+
+/* Regexp */
+#define HAVE_RB_BACKREF_GET 1
+#define HAVE_RB_REG_MATCH 1
+#define HAVE_RB_REG_NEW 1
+#define HAVE_RB_REG_NTH_MATCH 1
+#define HAVE_RB_REG_OPTIONS 1
+#define HAVE_RB_REG_REGCOMP 1
+
+/* String */
+#define HAVE_RB_CSTR2INUM 1
+#define HAVE_RB_CSTR_TO_INUM 1
+#define HAVE_RB_STR2INUM 1
+#define HAVE_RB_STR_APPEND 1
+#define HAVE_RB_STR_BUF_CAT 1
+#define HAVE_RB_STR_BUF_NEW 1
+#define HAVE_RB_STR_BUF_NEW2 1
+#define HAVE_RB_STR_CAT 1
+#define HAVE_RB_STR_CAT2 1
+#define HAVE_RB_STR_CMP 1
+#define HAVE_RB_STR_DUP 1
+#define HAVE_RB_STR_FLUSH 1
+#define HAVE_RB_STR_FREEZE 1
+#define HAVE_RB_STR_HASH 1
+#define HAVE_RB_STR_UPDATE 1
+#define HAVE_RB_STR_INSPECT 1
+#define HAVE_RB_STR_INTERN 1
+#define HAVE_RB_STR_NEW 1
+#define HAVE_RB_STR_NEW2 1
+#define HAVE_RB_STR_NEW3 1
+#define HAVE_RB_STR_NEW4 1
+#define HAVE_RB_STR_NEW5 1
+#define HAVE_RB_STR_PLUS 1
+#define HAVE_RB_STR_TIMES 1
+#define HAVE_RB_STR_RESIZE 1
+#define HAVE_RB_STR_SET_LEN 1
+#define HAVE_RB_STR_SPLIT 1
+#define HAVE_RB_STR_SUBSTR 1
+#define HAVE_RB_STR_TO_STR 1
+#define HAVE_RSTRING_LEN 1
+#define HAVE_RSTRING_PTR 1
+#define HAVE_STRINGVALUE 1
+
+#define HAVE_RB_STR_FREE 1
+#define HAVE_RB_SPRINTF 1
+#define HAVE_RB_LOCALE_STR_NEW 1
+#define HAVE_RB_LOCALE_STR_NEW_CSTR 1
+#define HAVE_RB_STR_CONV_ENC 1
+#define HAVE_RB_STR_CONV_ENC_OPTS 1
+#define HAVE_RB_STR_EXPORT 1
+#define HAVE_RB_STR_EXPORT_LOCALE 1
+#define HAVE_RB_STR_LENGTH 1
+#define HAVE_RB_STR_EQUAL 1
+#define HAVE_RB_STR_SUBSEQ 1
+#define HAVE_RB_VSPRINTF 1
+#define HAVE_RB_STRING 1
+
+/* Struct */
+#define HAVE_RB_STRUCT_AREF 1
+#define HAVE_RB_STRUCT_ASET 1
+#define HAVE_RB_STRUCT_DEFINE 1
+#define HAVE_RB_STRUCT_DEFINE_UNDER 1
+#define HAVE_RB_STRUCT_NEW 1
+#define HAVE_RB_STRUCT_GETMEMBER 1
+#define HAVE_RB_STRUCT_S_MEMBERS 1
+#define HAVE_RB_STRUCT_MEMBERS 1
+#ifdef RUBY_VERSION_IS_2_4
+#define HAVE_RB_STRUCT_SIZE 1
+#endif
+
+/* Symbol */
+#define HAVE_RB_ID2NAME 1
+#define HAVE_RB_ID2STR 1
+#define HAVE_RB_INTERN_STR 1
+#define HAVE_RB_INTERN 1
+#define HAVE_RB_IS_CLASS_ID 1
+#define HAVE_RB_IS_CONST_ID 1
+#define HAVE_RB_IS_INSTANCE_ID 1
+#define HAVE_RB_SYM2STR 1
+
+/* Thread */
+#define HAVE_RB_THREAD_ALONE 1
+#define HAVE_RB_THREAD_CALL_WITHOUT_GVL 1
+#define HAVE_RB_THREAD_CURRENT 1
+#define HAVE_RB_THREAD_LOCAL_AREF 1
+#define HAVE_RB_THREAD_LOCAL_ASET 1
+#define HAVE_RB_THREAD_WAIT_FOR 1
+#define HAVE_RB_THREAD_WAKEUP 1
+#define HAVE_RB_THREAD_CREATE 1
+
+/* Time */
+#define HAVE_RB_TIME_NEW 1
+#define HAVE_RB_TIME_NANO_NEW 1
+#define HAVE_RB_TIME_NUM_NEW 1
+#define HAVE_RB_TIME_INTERVAL 1
+#define HAVE_RB_TIME_TIMEVAL 1
+#define HAVE_RB_TIME_TIMESPEC 1
+#ifdef RUBY_VERSION_IS_2_3
+#define HAVE_RB_TIMESPEC_NOW 1
+#define HAVE_RB_TIME_TIMESPEC_NEW 1
+#endif
+
+/* Util */
+#define HAVE_RB_SCAN_ARGS 1
+
+/* Now, create the differential set. The format of the preprocessor directives
+ * is significant. The alternative implementations should define RUBY because
+ * some extensions depend on that. But only one alternative implementation
+ * macro should be defined at a time. The conditional is structured so that if
+ * no alternative implementation is defined then MRI is assumed.
+ */
+
+#if defined(RUBINIUS)
+#include "rubinius.h"
+#elif defined(JRUBY)
+#include "jruby.h"
+#elif defined(TRUFFLERUBY)
+#include "truffleruby.h"
+#endif
+
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/string_spec.c b/spec/rubyspec/optional/capi/ext/string_spec.c
new file mode 100644
index 0000000000..8d579f918f
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/string_spec.c
@@ -0,0 +1,664 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef HAVE_RUBY_ENCODING_H
+#include "ruby/encoding.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_CSTR2INUM
+VALUE string_spec_rb_cstr2inum(VALUE self, VALUE str, VALUE inum) {
+ int num = FIX2INT(inum);
+ return rb_cstr2inum(RSTRING_PTR(str), num);
+}
+#endif
+
+#ifdef HAVE_RB_CSTR_TO_INUM
+static VALUE string_spec_rb_cstr_to_inum(VALUE self, VALUE str, VALUE inum, VALUE badcheck) {
+ int num = FIX2INT(inum);
+ return rb_cstr_to_inum(RSTRING_PTR(str), num, RTEST(badcheck));
+}
+#endif
+
+#ifdef HAVE_RB_STR2INUM
+VALUE string_spec_rb_str2inum(VALUE self, VALUE str, VALUE inum) {
+ int num = FIX2INT(inum);
+ return rb_str2inum(str, num);
+}
+#endif
+
+#ifdef HAVE_RB_STR_APPEND
+VALUE string_spec_rb_str_append(VALUE self, VALUE str, VALUE str2) {
+ return rb_str_append(str, str2);
+}
+#endif
+
+#ifdef HAVE_RB_STR_SET_LEN
+VALUE string_spec_rb_str_set_len(VALUE self, VALUE str, VALUE len) {
+ rb_str_set_len(str, NUM2LONG(len));
+
+ return str;
+}
+
+VALUE string_spec_rb_str_set_len_RSTRING_LEN(VALUE self, VALUE str, VALUE len) {
+ rb_str_set_len(str, NUM2LONG(len));
+
+ return INT2FIX(RSTRING_LEN(str));
+}
+#endif
+
+#ifdef HAVE_RB_STR_BUF_NEW
+VALUE string_spec_rb_str_buf_new(VALUE self, VALUE len, VALUE str) {
+ VALUE buf;
+
+ buf = rb_str_buf_new(NUM2LONG(len));
+
+ if(RTEST(str)) {
+ snprintf(RSTRING_PTR(buf), NUM2LONG(len), "%s", RSTRING_PTR(str));
+ }
+
+ return buf;
+}
+#endif
+
+#ifdef HAVE_RB_STR_BUF_NEW2
+VALUE string_spec_rb_str_buf_new2(VALUE self) {
+ return rb_str_buf_new2("hello\0invisible");
+}
+#endif
+
+#ifdef HAVE_RB_STR_BUF_CAT
+VALUE string_spec_rb_str_buf_cat(VALUE self, VALUE str) {
+ const char *question_mark = "?";
+ rb_str_buf_cat(str, question_mark, strlen(question_mark));
+ return str;
+}
+#endif
+
+#ifdef HAVE_RB_STR_CAT
+VALUE string_spec_rb_str_cat(VALUE self, VALUE str) {
+ return rb_str_cat(str, "?", 1);
+}
+#endif
+
+#ifdef HAVE_RB_STR_CAT2
+VALUE string_spec_rb_str_cat2(VALUE self, VALUE str) {
+ return rb_str_cat2(str, "?");
+}
+#endif
+
+#ifdef HAVE_RB_STR_CMP
+VALUE string_spec_rb_str_cmp(VALUE self, VALUE str1, VALUE str2) {
+ return INT2NUM(rb_str_cmp(str1, str2));
+}
+#endif
+
+#ifdef HAVE_RB_STR_CONV_ENC
+VALUE string_spec_rb_str_conv_enc(VALUE self, VALUE str, VALUE from, VALUE to) {
+ rb_encoding* from_enc;
+ rb_encoding* to_enc;
+
+ from_enc = rb_to_encoding(from);
+
+ if(NIL_P(to)) {
+ to_enc = 0;
+ } else {
+ to_enc = rb_to_encoding(to);
+ }
+
+ return rb_str_conv_enc(str, from_enc, to_enc);
+}
+#endif
+
+#ifdef HAVE_RB_STR_CONV_ENC_OPTS
+VALUE string_spec_rb_str_conv_enc_opts(VALUE self, VALUE str, VALUE from, VALUE to,
+ VALUE ecflags, VALUE ecopts)
+{
+ rb_encoding* from_enc;
+ rb_encoding* to_enc;
+
+ from_enc = rb_to_encoding(from);
+
+ if(NIL_P(to)) {
+ to_enc = 0;
+ } else {
+ to_enc = rb_to_encoding(to);
+ }
+
+ return rb_str_conv_enc_opts(str, from_enc, to_enc, FIX2INT(ecflags), ecopts);
+}
+#endif
+
+#ifdef HAVE_RB_STR_EXPORT
+VALUE string_spec_rb_str_export(VALUE self, VALUE str) {
+ return rb_str_export(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_EXPORT_LOCALE
+VALUE string_spec_rb_str_export_locale(VALUE self, VALUE str) {
+ return rb_str_export_locale(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_DUP
+VALUE string_spec_rb_str_dup(VALUE self, VALUE str) {
+ return rb_str_dup(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_FREEZE
+VALUE string_spec_rb_str_freeze(VALUE self, VALUE str) {
+ return rb_str_freeze(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_INSPECT
+VALUE string_spec_rb_str_inspect(VALUE self, VALUE str) {
+ return rb_str_inspect(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_INTERN
+VALUE string_spec_rb_str_intern(VALUE self, VALUE str) {
+ return rb_str_intern(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_LENGTH
+VALUE string_spec_rb_str_length(VALUE self, VALUE str) {
+ return rb_str_length(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_NEW
+VALUE string_spec_rb_str_new(VALUE self, VALUE str, VALUE len) {
+ return rb_str_new(RSTRING_PTR(str), FIX2INT(len));
+}
+#endif
+
+#ifdef HAVE_RB_STR_NEW2
+VALUE string_spec_rb_str_new2(VALUE self, VALUE str) {
+ if(NIL_P(str)) {
+ return rb_str_new2("");
+ } else {
+ return rb_str_new2(RSTRING_PTR(str));
+ }
+}
+#endif
+
+#ifdef HAVE_RB_STR_ENCODE
+VALUE string_spec_rb_str_encode(VALUE self, VALUE str, VALUE enc, VALUE flags, VALUE opts) {
+ return rb_str_encode(str, enc, FIX2INT(flags), opts);
+}
+#endif
+
+#ifdef HAVE_RB_STR_NEW_CSTR
+VALUE string_spec_rb_str_new_cstr(VALUE self, VALUE str) {
+ if(NIL_P(str)) {
+ return rb_str_new_cstr("");
+ } else {
+ return rb_str_new_cstr(RSTRING_PTR(str));
+ }
+}
+#endif
+
+#ifdef HAVE_RB_EXTERNAL_STR_NEW
+VALUE string_spec_rb_external_str_new(VALUE self, VALUE str) {
+ return rb_external_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
+}
+#endif
+
+#ifdef HAVE_RB_EXTERNAL_STR_NEW_CSTR
+VALUE string_spec_rb_external_str_new_cstr(VALUE self, VALUE str) {
+ return rb_external_str_new_cstr(RSTRING_PTR(str));
+}
+#endif
+
+#ifdef HAVE_RB_EXTERNAL_STR_NEW_WITH_ENC
+VALUE string_spec_rb_external_str_new_with_enc(VALUE self, VALUE str, VALUE len, VALUE encoding) {
+ return rb_external_str_new_with_enc(RSTRING_PTR(str), FIX2LONG(len), rb_to_encoding(encoding));
+}
+#endif
+
+#ifdef HAVE_RB_LOCALE_STR_NEW
+VALUE string_spec_rb_locale_str_new(VALUE self, VALUE str, VALUE len) {
+ return rb_locale_str_new(RSTRING_PTR(str), FIX2INT(len));
+}
+#endif
+
+#ifdef HAVE_RB_LOCALE_STR_NEW_CSTR
+VALUE string_spec_rb_locale_str_new_cstr(VALUE self, VALUE str) {
+ return rb_locale_str_new_cstr(RSTRING_PTR(str));
+}
+#endif
+
+#ifdef HAVE_RB_STR_NEW3
+VALUE string_spec_rb_str_new3(VALUE self, VALUE str) {
+ return rb_str_new3(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_NEW4
+VALUE string_spec_rb_str_new4(VALUE self, VALUE str) {
+ return rb_str_new4(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_NEW5
+VALUE string_spec_rb_str_new5(VALUE self, VALUE str, VALUE ptr, VALUE len) {
+ return rb_str_new5(str, RSTRING_PTR(ptr), FIX2INT(len));
+}
+#endif
+
+#ifdef HAVE_RB_STR_PLUS
+VALUE string_spec_rb_str_plus(VALUE self, VALUE str1, VALUE str2) {
+ return rb_str_plus(str1, str2);
+}
+#endif
+
+#ifdef HAVE_RB_STR_TIMES
+VALUE string_spec_rb_str_times(VALUE self, VALUE str, VALUE times) {
+ return rb_str_times(str, times);
+}
+#endif
+
+#ifdef HAVE_RB_STR_RESIZE
+VALUE string_spec_rb_str_resize(VALUE self, VALUE str, VALUE size) {
+ return rb_str_resize(str, FIX2INT(size));
+}
+
+VALUE string_spec_rb_str_resize_RSTRING_LEN(VALUE self, VALUE str, VALUE size) {
+ VALUE modified = rb_str_resize(str, FIX2INT(size));
+ return INT2FIX(RSTRING_LEN(modified));
+}
+#endif
+
+#ifdef HAVE_RB_STR_SPLIT
+VALUE string_spec_rb_str_split(VALUE self, VALUE str) {
+ return rb_str_split(str, ",");
+}
+#endif
+
+#ifdef HAVE_RB_STR_SUBSEQ
+VALUE string_spec_rb_str_subseq(VALUE self, VALUE str, VALUE beg, VALUE len) {
+ return rb_str_subseq(str, FIX2INT(beg), FIX2INT(len));
+}
+#endif
+
+#ifdef HAVE_RB_STR_SUBSTR
+VALUE string_spec_rb_str_substr(VALUE self, VALUE str, VALUE beg, VALUE len) {
+ return rb_str_substr(str, FIX2INT(beg), FIX2INT(len));
+}
+#endif
+
+#ifdef HAVE_RB_STR_TO_STR
+VALUE string_spec_rb_str_to_str(VALUE self, VALUE arg) {
+ return rb_str_to_str(arg);
+}
+#endif
+
+#ifdef HAVE_RSTRING_LEN
+VALUE string_spec_RSTRING_LEN(VALUE self, VALUE str) {
+ return INT2FIX(RSTRING_LEN(str));
+}
+#endif
+
+#ifdef HAVE_RSTRING_LENINT
+VALUE string_spec_RSTRING_LENINT(VALUE self, VALUE str) {
+ return INT2FIX(RSTRING_LENINT(str));
+}
+#endif
+
+#ifdef HAVE_RSTRING_PTR
+VALUE string_spec_RSTRING_PTR_iterate(VALUE self, VALUE str) {
+ int i;
+ char* ptr;
+
+ ptr = RSTRING_PTR(str);
+ for(i = 0; i < RSTRING_LEN(str); i++) {
+ rb_yield(CHR2FIX(ptr[i]));
+ }
+ return Qnil;
+}
+
+VALUE string_spec_RSTRING_PTR_assign(VALUE self, VALUE str, VALUE chr) {
+ int i;
+ char c;
+ char* ptr;
+
+ ptr = RSTRING_PTR(str);
+ c = FIX2INT(chr);
+
+ for(i = 0; i < RSTRING_LEN(str); i++) {
+ ptr[i] = c;
+ }
+ return Qnil;
+}
+
+VALUE string_spec_RSTRING_PTR_after_funcall(VALUE self, VALUE str, VALUE cb) {
+ /* Silence gcc 4.3.2 warning about computed value not used */
+ if(RSTRING_PTR(str)) { /* force it out */
+ rb_funcall(cb, rb_intern("call"), 1, str);
+ }
+
+ return rb_str_new2(RSTRING_PTR(str));
+}
+#endif
+
+#ifdef HAVE_STRINGVALUE
+VALUE string_spec_StringValue(VALUE self, VALUE str) {
+ return StringValue(str);
+}
+#endif
+
+#ifdef HAVE_RB_STR_HASH
+static VALUE string_spec_rb_str_hash(VALUE self, VALUE str) {
+ st_index_t val = rb_str_hash(str);
+
+#if SIZEOF_LONG == SIZEOF_VOIDP
+ return LONG2FIX((long)val);
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+ return LL2NUM((LONG_LONG)val);
+#else
+# error unsupported platform
+#endif
+}
+#endif
+
+#ifdef HAVE_RB_STR_UPDATE
+static VALUE string_spec_rb_str_update(VALUE self, VALUE str, VALUE beg, VALUE end, VALUE replacement) {
+ rb_str_update(str, FIX2LONG(beg), FIX2LONG(end), replacement);
+ return str;
+}
+#endif
+
+#ifdef HAVE_RB_STR_FREE
+static VALUE string_spec_rb_str_free(VALUE self, VALUE str) {
+ rb_str_free(str);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_SPRINTF
+static VALUE string_spec_rb_sprintf1(VALUE self, VALUE str, VALUE repl) {
+ return rb_sprintf(RSTRING_PTR(str), RSTRING_PTR(repl));
+}
+static VALUE string_spec_rb_sprintf2(VALUE self, VALUE str, VALUE repl1, VALUE repl2) {
+ return rb_sprintf(RSTRING_PTR(str), RSTRING_PTR(repl1), RSTRING_PTR(repl2));
+}
+#endif
+
+#ifdef HAVE_RB_VSPRINTF
+static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...) {
+ va_list varargs;
+ VALUE str;
+
+ va_start(varargs, fmt);
+ str = rb_vsprintf(fmt, varargs);
+ va_end(varargs);
+
+ return str;
+}
+
+static VALUE string_spec_rb_vsprintf(VALUE self, VALUE fmt, VALUE str, VALUE i, VALUE f) {
+ return string_spec_rb_vsprintf_worker(RSTRING_PTR(fmt), RSTRING_PTR(str),
+ FIX2INT(i), RFLOAT_VALUE(f));
+}
+#endif
+
+#ifdef HAVE_RB_STR_EQUAL
+VALUE string_spec_rb_str_equal(VALUE self, VALUE str1, VALUE str2) {
+ return rb_str_equal(str1, str2);
+}
+#endif
+
+#ifdef HAVE_RB_USASCII_STR_NEW
+static VALUE string_spec_rb_usascii_str_new(VALUE self, VALUE str, VALUE len) {
+ return rb_usascii_str_new(RSTRING_PTR(str), NUM2INT(len));
+}
+#endif
+
+#ifdef HAVE_RB_USASCII_STR_NEW_CSTR
+static VALUE string_spec_rb_usascii_str_new_cstr(VALUE self, VALUE str) {
+ return rb_usascii_str_new_cstr(RSTRING_PTR(str));
+}
+#endif
+
+#ifdef HAVE_RB_STRING
+static VALUE string_spec_rb_String(VALUE self, VALUE val) {
+ return rb_String(val);
+}
+#endif
+
+void Init_string_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiStringSpecs", rb_cObject);
+
+#ifdef HAVE_RB_CSTR2INUM
+ rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2);
+#endif
+
+#ifdef HAVE_RB_CSTR_TO_INUM
+ rb_define_method(cls, "rb_cstr_to_inum", string_spec_rb_cstr_to_inum, 3);
+#endif
+
+#ifdef HAVE_RB_STR2INUM
+ rb_define_method(cls, "rb_str2inum", string_spec_rb_str2inum, 2);
+#endif
+
+#ifdef HAVE_RB_STR_APPEND
+ rb_define_method(cls, "rb_str_append", string_spec_rb_str_append, 2);
+#endif
+
+#ifdef HAVE_RB_STR_BUF_NEW
+ rb_define_method(cls, "rb_str_buf_new", string_spec_rb_str_buf_new, 2);
+#endif
+
+#ifdef HAVE_RB_STR_BUF_NEW2
+ rb_define_method(cls, "rb_str_buf_new2", string_spec_rb_str_buf_new2, 0);
+#endif
+
+#ifdef HAVE_RB_STR_BUF_CAT
+ rb_define_method(cls, "rb_str_buf_cat", string_spec_rb_str_buf_cat, 1);
+#endif
+
+#ifdef HAVE_RB_STR_CAT
+ rb_define_method(cls, "rb_str_cat", string_spec_rb_str_cat, 1);
+#endif
+
+#ifdef HAVE_RB_STR_CAT2
+ rb_define_method(cls, "rb_str_cat2", string_spec_rb_str_cat2, 1);
+#endif
+
+#ifdef HAVE_RB_STR_CMP
+ rb_define_method(cls, "rb_str_cmp", string_spec_rb_str_cmp, 2);
+#endif
+
+#ifdef HAVE_RB_STR_CONV_ENC
+ rb_define_method(cls, "rb_str_conv_enc", string_spec_rb_str_conv_enc, 3);
+#endif
+
+#ifdef HAVE_RB_STR_CONV_ENC_OPTS
+ rb_define_method(cls, "rb_str_conv_enc_opts", string_spec_rb_str_conv_enc_opts, 5);
+#endif
+
+#ifdef HAVE_RB_STR_EXPORT
+ rb_define_method(cls, "rb_str_export", string_spec_rb_str_export, 1);
+#endif
+
+#ifdef HAVE_RB_STR_EXPORT_LOCALE
+ rb_define_method(cls, "rb_str_export_locale", string_spec_rb_str_export_locale, 1);
+#endif
+
+#ifdef HAVE_RB_STR_DUP
+ rb_define_method(cls, "rb_str_dup", string_spec_rb_str_dup, 1);
+#endif
+
+#ifdef HAVE_RB_STR_FREEZE
+ rb_define_method(cls, "rb_str_freeze", string_spec_rb_str_freeze, 1);
+#endif
+
+#ifdef HAVE_RB_STR_INSPECT
+ rb_define_method(cls, "rb_str_inspect", string_spec_rb_str_inspect, 1);
+#endif
+
+#ifdef HAVE_RB_STR_INTERN
+ rb_define_method(cls, "rb_str_intern", string_spec_rb_str_intern, 1);
+#endif
+
+#ifdef HAVE_RB_STR_LENGTH
+ rb_define_method(cls, "rb_str_length", string_spec_rb_str_length, 1);
+#endif
+
+#ifdef HAVE_RB_STR_NEW
+ rb_define_method(cls, "rb_str_new", string_spec_rb_str_new, 2);
+#endif
+
+#ifdef HAVE_RB_STR_NEW2
+ rb_define_method(cls, "rb_str_new2", string_spec_rb_str_new2, 1);
+#endif
+
+#ifdef HAVE_RB_STR_ENCODE
+ rb_define_method(cls, "rb_str_encode", string_spec_rb_str_encode, 4);
+#endif
+
+#ifdef HAVE_RB_STR_NEW_CSTR
+ rb_define_method(cls, "rb_str_new_cstr", string_spec_rb_str_new_cstr, 1);
+#endif
+
+#ifdef HAVE_RB_EXTERNAL_STR_NEW
+ rb_define_method(cls, "rb_external_str_new", string_spec_rb_external_str_new, 1);
+#endif
+
+#ifdef HAVE_RB_EXTERNAL_STR_NEW_CSTR
+ rb_define_method(cls, "rb_external_str_new_cstr",
+ string_spec_rb_external_str_new_cstr, 1);
+#endif
+
+#ifdef HAVE_RB_EXTERNAL_STR_NEW_WITH_ENC
+ rb_define_method(cls, "rb_external_str_new_with_enc", string_spec_rb_external_str_new_with_enc, 3);
+#endif
+
+#ifdef HAVE_RB_LOCALE_STR_NEW
+ rb_define_method(cls, "rb_locale_str_new", string_spec_rb_locale_str_new, 2);
+#endif
+
+#ifdef HAVE_RB_LOCALE_STR_NEW_CSTR
+ rb_define_method(cls, "rb_locale_str_new_cstr", string_spec_rb_locale_str_new_cstr, 1);
+#endif
+
+#ifdef HAVE_RB_STR_NEW3
+ rb_define_method(cls, "rb_str_new3", string_spec_rb_str_new3, 1);
+#endif
+
+#ifdef HAVE_RB_STR_NEW4
+ rb_define_method(cls, "rb_str_new4", string_spec_rb_str_new4, 1);
+#endif
+
+#ifdef HAVE_RB_STR_NEW5
+ rb_define_method(cls, "rb_str_new5", string_spec_rb_str_new5, 3);
+#endif
+
+#ifdef HAVE_RB_STR_PLUS
+ rb_define_method(cls, "rb_str_plus", string_spec_rb_str_plus, 2);
+#endif
+
+#ifdef HAVE_RB_STR_TIMES
+ rb_define_method(cls, "rb_str_times", string_spec_rb_str_times, 2);
+#endif
+
+#ifdef HAVE_RB_STR_RESIZE
+ rb_define_method(cls, "rb_str_resize", string_spec_rb_str_resize, 2);
+ rb_define_method(cls, "rb_str_resize_RSTRING_LEN",
+ string_spec_rb_str_resize_RSTRING_LEN, 2);
+#endif
+
+#ifdef HAVE_RB_STR_SET_LEN
+ rb_define_method(cls, "rb_str_set_len", string_spec_rb_str_set_len, 2);
+ rb_define_method(cls, "rb_str_set_len_RSTRING_LEN",
+ string_spec_rb_str_set_len_RSTRING_LEN, 2);
+#endif
+
+#ifdef HAVE_RB_STR_SPLIT
+ rb_define_method(cls, "rb_str_split", string_spec_rb_str_split, 1);
+#endif
+
+#ifdef HAVE_RB_STR_SUBSEQ
+ rb_define_method(cls, "rb_str_subseq", string_spec_rb_str_subseq, 3);
+#endif
+
+#ifdef HAVE_RB_STR_SUBSTR
+ rb_define_method(cls, "rb_str_substr", string_spec_rb_str_substr, 3);
+#endif
+
+#ifdef HAVE_RB_STR_TO_STR
+ rb_define_method(cls, "rb_str_to_str", string_spec_rb_str_to_str, 1);
+#endif
+
+#ifdef HAVE_RSTRING_LEN
+ rb_define_method(cls, "RSTRING_LEN", string_spec_RSTRING_LEN, 1);
+#endif
+
+#ifdef HAVE_RSTRING_LENINT
+ rb_define_method(cls, "RSTRING_LENINT", string_spec_RSTRING_LENINT, 1);
+#endif
+
+#ifdef HAVE_RSTRING_PTR
+ rb_define_method(cls, "RSTRING_PTR_iterate", string_spec_RSTRING_PTR_iterate, 1);
+ rb_define_method(cls, "RSTRING_PTR_assign", string_spec_RSTRING_PTR_assign, 2);
+ rb_define_method(cls, "RSTRING_PTR_after_funcall",
+ string_spec_RSTRING_PTR_after_funcall, 2);
+#endif
+
+#ifdef HAVE_STRINGVALUE
+ rb_define_method(cls, "StringValue", string_spec_StringValue, 1);
+#endif
+
+#ifdef HAVE_RB_STR_HASH
+ rb_define_method(cls, "rb_str_hash", string_spec_rb_str_hash, 1);
+#endif
+
+#ifdef HAVE_RB_STR_UPDATE
+ rb_define_method(cls, "rb_str_update", string_spec_rb_str_update, 4);
+#endif
+
+#ifdef HAVE_RB_STR_FREE
+ rb_define_method(cls, "rb_str_free", string_spec_rb_str_free, 1);
+#endif
+
+#ifdef HAVE_RB_SPRINTF
+ rb_define_method(cls, "rb_sprintf1", string_spec_rb_sprintf1, 2);
+ rb_define_method(cls, "rb_sprintf2", string_spec_rb_sprintf2, 3);
+#endif
+
+#ifdef HAVE_RB_VSPRINTF
+ rb_define_method(cls, "rb_vsprintf", string_spec_rb_vsprintf, 4);
+#endif
+
+#ifdef HAVE_RB_STR_EQUAL
+ rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2);
+#endif
+
+#ifdef HAVE_RB_USASCII_STR_NEW
+ rb_define_method(cls, "rb_usascii_str_new", string_spec_rb_usascii_str_new, 2);
+#endif
+
+#ifdef HAVE_RB_USASCII_STR_NEW_CSTR
+ rb_define_method(cls, "rb_usascii_str_new_cstr", string_spec_rb_usascii_str_new_cstr, 1);
+#endif
+
+#ifdef HAVE_RB_STRING
+ rb_define_method(cls, "rb_String", string_spec_rb_String, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/struct_spec.c b/spec/rubyspec/optional/capi/ext/struct_spec.c
new file mode 100644
index 0000000000..8f373d9f48
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/struct_spec.c
@@ -0,0 +1,131 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include "ruby/intern.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_STRUCT_AREF
+static VALUE struct_spec_rb_struct_aref(VALUE self, VALUE st, VALUE key) {
+ return rb_struct_aref(st, key);
+}
+#endif
+
+#ifdef HAVE_RB_STRUCT_GETMEMBER
+static VALUE struct_spec_rb_struct_getmember(VALUE self, VALUE st, VALUE key) {
+ return rb_struct_getmember(st, SYM2ID(key));
+}
+#endif
+
+#ifdef HAVE_RB_STRUCT_S_MEMBERS
+static VALUE struct_spec_rb_struct_s_members(VALUE self, VALUE klass)
+{
+ return rb_ary_dup(rb_struct_s_members(klass));
+}
+#endif
+
+#ifdef HAVE_RB_STRUCT_MEMBERS
+static VALUE struct_spec_rb_struct_members(VALUE self, VALUE st)
+{
+ return rb_ary_dup(rb_struct_members(st));
+}
+#endif
+
+#ifdef HAVE_RB_STRUCT_ASET
+static VALUE struct_spec_rb_struct_aset(VALUE self, VALUE st, VALUE key, VALUE value) {
+ return rb_struct_aset(st, key, value);
+}
+#endif
+
+#ifdef HAVE_RB_STRUCT_DEFINE
+/* Only allow setting three attributes, should be sufficient for testing. */
+static VALUE struct_spec_struct_define(VALUE self, VALUE name,
+ VALUE attr1, VALUE attr2, VALUE attr3) {
+
+ const char *a1 = StringValuePtr(attr1);
+ const char *a2 = StringValuePtr(attr2);
+ const char *a3 = StringValuePtr(attr3);
+ char *nm = NULL;
+
+ if (name != Qnil) nm = StringValuePtr(name);
+
+ return rb_struct_define(nm, a1, a2, a3, NULL);
+}
+#endif
+
+#ifdef HAVE_RB_STRUCT_DEFINE_UNDER
+/* Only allow setting three attributes, should be sufficient for testing. */
+static VALUE struct_spec_struct_define_under(VALUE self, VALUE outer,
+ VALUE name, VALUE attr1, VALUE attr2, VALUE attr3) {
+
+ const char *nm = StringValuePtr(name);
+ const char *a1 = StringValuePtr(attr1);
+ const char *a2 = StringValuePtr(attr2);
+ const char *a3 = StringValuePtr(attr3);
+
+ return rb_struct_define_under(outer, nm, a1, a2, a3, NULL);
+}
+#endif
+
+#ifdef HAVE_RB_STRUCT_NEW
+static VALUE struct_spec_rb_struct_new(VALUE self, VALUE klass,
+ VALUE a, VALUE b, VALUE c)
+{
+
+ return rb_struct_new(klass, a, b, c);
+}
+#endif
+
+#ifdef HAVE_RB_STRUCT_SIZE
+static VALUE struct_spec_rb_struct_size(VALUE self, VALUE st)
+{
+ return rb_struct_size(st);
+}
+#endif
+
+void Init_struct_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiStructSpecs", rb_cObject);
+
+#ifdef HAVE_RB_STRUCT_AREF
+ rb_define_method(cls, "rb_struct_aref", struct_spec_rb_struct_aref, 2);
+#endif
+
+#ifdef HAVE_RB_STRUCT_GETMEMBER
+ rb_define_method(cls, "rb_struct_getmember", struct_spec_rb_struct_getmember, 2);
+#endif
+
+#ifdef HAVE_RB_STRUCT_S_MEMBERS
+ rb_define_method(cls, "rb_struct_s_members", struct_spec_rb_struct_s_members, 1);
+#endif
+
+#ifdef HAVE_RB_STRUCT_MEMBERS
+ rb_define_method(cls, "rb_struct_members", struct_spec_rb_struct_members, 1);
+#endif
+
+#ifdef HAVE_RB_STRUCT_ASET
+ rb_define_method(cls, "rb_struct_aset", struct_spec_rb_struct_aset, 3);
+#endif
+
+#ifdef HAVE_RB_STRUCT_DEFINE
+ rb_define_method(cls, "rb_struct_define", struct_spec_struct_define, 4);
+#endif
+
+#ifdef HAVE_RB_STRUCT_DEFINE_UNDER
+ rb_define_method(cls, "rb_struct_define_under", struct_spec_struct_define_under, 5);
+#endif
+
+#ifdef HAVE_RB_STRUCT_NEW
+ rb_define_method(cls, "rb_struct_new", struct_spec_rb_struct_new, 4);
+#endif
+
+#ifdef HAVE_RB_STRUCT_SIZE
+ rb_define_method(cls, "rb_struct_size", struct_spec_rb_struct_size, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/symbol_spec.c b/spec/rubyspec/optional/capi/ext/symbol_spec.c
new file mode 100644
index 0000000000..7ffa7cf9b1
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/symbol_spec.c
@@ -0,0 +1,138 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef HAVE_RUBY_ENCODING_H
+#include "ruby/encoding.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_INTERN
+VALUE symbol_spec_rb_intern(VALUE self, VALUE string) {
+ return ID2SYM(rb_intern(RSTRING_PTR(string)));
+}
+
+VALUE symbol_spec_rb_intern2(VALUE self, VALUE string, VALUE len) {
+ return ID2SYM(rb_intern2(RSTRING_PTR(string), FIX2LONG(len)));
+}
+
+VALUE symbol_spec_rb_intern_const(VALUE self, VALUE string) {
+ return ID2SYM(rb_intern_const(RSTRING_PTR(string)));
+}
+
+VALUE symbol_spec_rb_intern_c_compare(VALUE self, VALUE string, VALUE sym) {
+ ID symbol = rb_intern(RSTRING_PTR(string));
+ return (SYM2ID(sym) == symbol) ? Qtrue : Qfalse;
+}
+
+VALUE symbol_spec_rb_intern2_c_compare(VALUE self, VALUE string, VALUE len, VALUE sym) {
+ ID symbol = rb_intern2(RSTRING_PTR(string), FIX2LONG(len));
+ return (SYM2ID(sym) == symbol) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_INTERN3
+VALUE symbol_spec_rb_intern3(VALUE self, VALUE string, VALUE len, VALUE enc) {
+ return ID2SYM(rb_intern3(RSTRING_PTR(string), FIX2LONG(len), rb_enc_get(enc)));
+}
+
+VALUE symbol_spec_rb_intern3_c_compare(VALUE self, VALUE string, VALUE len, VALUE enc, VALUE sym) {
+ ID symbol = rb_intern3(RSTRING_PTR(string), FIX2LONG(len), rb_enc_get(enc));
+ return (SYM2ID(sym) == symbol) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_ID2NAME
+VALUE symbol_spec_rb_id2name(VALUE self, VALUE symbol) {
+ const char* c_str = rb_id2name(SYM2ID(symbol));
+ return rb_str_new(c_str, strlen(c_str));
+}
+#endif
+
+#ifdef HAVE_RB_ID2STR
+VALUE symbol_spec_rb_id2str(VALUE self, VALUE symbol) {
+ return rb_id2str(SYM2ID(symbol));
+}
+#endif
+
+#ifdef HAVE_RB_INTERN_STR
+VALUE symbol_spec_rb_intern_str(VALUE self, VALUE str) {
+ return ID2SYM(rb_intern_str(str));
+}
+#endif
+
+#ifdef HAVE_RB_IS_CLASS_ID
+VALUE symbol_spec_rb_is_class_id(VALUE self, VALUE sym) {
+ return rb_is_class_id(SYM2ID(sym)) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_IS_CONST_ID
+VALUE symbol_spec_rb_is_const_id(VALUE self, VALUE sym) {
+ return rb_is_const_id(SYM2ID(sym)) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_IS_INSTANCE_ID
+VALUE symbol_spec_rb_is_instance_id(VALUE self, VALUE sym) {
+ return rb_is_instance_id(SYM2ID(sym)) ? Qtrue : Qfalse;
+}
+#endif
+
+#ifdef HAVE_RB_SYM2STR
+VALUE symbol_spec_rb_sym2str(VALUE self, VALUE sym) {
+ return rb_sym2str(sym);
+}
+#endif
+
+void Init_symbol_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiSymbolSpecs", rb_cObject);
+
+#ifdef HAVE_RB_INTERN
+ rb_define_method(cls, "rb_intern", symbol_spec_rb_intern, 1);
+ rb_define_method(cls, "rb_intern2", symbol_spec_rb_intern2, 2);
+ rb_define_method(cls, "rb_intern_const", symbol_spec_rb_intern_const, 1);
+ rb_define_method(cls, "rb_intern_c_compare", symbol_spec_rb_intern_c_compare, 2);
+ rb_define_method(cls, "rb_intern2_c_compare", symbol_spec_rb_intern2_c_compare, 3);
+#endif
+
+#ifdef HAVE_RB_INTERN3
+ rb_define_method(cls, "rb_intern3", symbol_spec_rb_intern3, 3);
+ rb_define_method(cls, "rb_intern3_c_compare", symbol_spec_rb_intern3_c_compare, 4);
+#endif
+
+#ifdef HAVE_RB_ID2NAME
+ rb_define_method(cls, "rb_id2name", symbol_spec_rb_id2name, 1);
+#endif
+
+#ifdef HAVE_RB_ID2STR
+ rb_define_method(cls, "rb_id2str", symbol_spec_rb_id2str, 1);
+#endif
+
+#ifdef HAVE_RB_INTERN_STR
+ rb_define_method(cls, "rb_intern_str", symbol_spec_rb_intern_str, 1);
+#endif
+
+#ifdef HAVE_RB_IS_CLASS_ID
+ rb_define_method(cls, "rb_is_class_id", symbol_spec_rb_is_class_id, 1);
+#endif
+
+#ifdef HAVE_RB_IS_CONST_ID
+ rb_define_method(cls, "rb_is_const_id", symbol_spec_rb_is_const_id, 1);
+#endif
+
+#ifdef HAVE_RB_IS_INSTANCE_ID
+ rb_define_method(cls, "rb_is_instance_id", symbol_spec_rb_is_instance_id, 1);
+#endif
+
+#ifdef HAVE_RB_SYM2STR
+ rb_define_method(cls, "rb_sym2str", symbol_spec_rb_sym2str, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/thread_spec.c b/spec/rubyspec/optional/capi/ext/thread_spec.c
new file mode 100644
index 0000000000..5ea96fe3d6
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/thread_spec.c
@@ -0,0 +1,181 @@
+#include "ruby.h"
+#include "ruby/thread.h"
+#include "rubyspec.h"
+
+#include <math.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_THREAD_ALONE
+static VALUE thread_spec_rb_thread_alone() {
+ return rb_thread_alone() ? Qtrue : Qfalse;
+}
+#endif
+
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
+/* This is unblocked by unblock_func(). */
+static void* blocking_gvl_func(void* data) {
+ int rfd = *(int *)data;
+ char dummy;
+ ssize_t rv;
+
+ do {
+ rv = read(rfd, &dummy, 1);
+ } while (rv == -1 && errno == EINTR);
+
+ return (void*)((rv == 1) ? Qtrue : Qfalse);
+}
+
+static void unblock_gvl_func(void *data) {
+ int wfd = *(int *)data;
+ char dummy = 0;
+ ssize_t rv;
+
+ do {
+ rv = write(wfd, &dummy, 1);
+ } while (rv == -1 && errno == EINTR);
+}
+
+/* Returns true if the thread is interrupted. */
+static VALUE thread_spec_rb_thread_call_without_gvl(VALUE self) {
+ int fds[2];
+ void* ret;
+
+ if (pipe(fds) == -1) {
+ return Qfalse;
+ }
+ ret = rb_thread_call_without_gvl(blocking_gvl_func, &fds[0],
+ unblock_gvl_func, &fds[1]);
+ close(fds[0]);
+ close(fds[1]);
+ return (VALUE)ret;
+}
+
+/* This is unblocked by a signal. */
+static void* blocking_gvl_func_for_udf_io(void *data) {
+ int rfd = (int)(size_t)data;
+ char dummy;
+
+ if (read(rfd, &dummy, 1) == -1 && errno == EINTR) {
+ return (void*)Qtrue;
+ } else {
+ return (void*)Qfalse;
+ }
+}
+
+/* Returns true if the thread is interrupted. */
+static VALUE thread_spec_rb_thread_call_without_gvl_with_ubf_io(VALUE self) {
+ int fds[2];
+ void* ret;
+
+ if (pipe(fds) == -1) {
+ return Qfalse;
+ }
+
+ ret = rb_thread_call_without_gvl(blocking_gvl_func_for_udf_io,
+ (void*)(size_t)fds[0], RUBY_UBF_IO, 0);
+ close(fds[0]);
+ close(fds[1]);
+ return (VALUE)ret;
+}
+#endif
+
+#ifdef HAVE_RB_THREAD_CURRENT
+static VALUE thread_spec_rb_thread_current() {
+ return rb_thread_current();
+}
+#endif
+
+#ifdef HAVE_RB_THREAD_LOCAL_AREF
+static VALUE thread_spec_rb_thread_local_aref(VALUE self, VALUE thr, VALUE sym) {
+ return rb_thread_local_aref(thr, SYM2ID(sym));
+}
+#endif
+
+#ifdef HAVE_RB_THREAD_LOCAL_ASET
+static VALUE thread_spec_rb_thread_local_aset(VALUE self, VALUE thr, VALUE sym, VALUE value) {
+ return rb_thread_local_aset(thr, SYM2ID(sym), value);
+}
+#endif
+
+#ifdef HAVE_RB_THREAD_WAKEUP
+static VALUE thread_spec_rb_thread_wakeup(VALUE self, VALUE thr) {
+ return rb_thread_wakeup(thr);
+}
+#endif
+
+#ifdef HAVE_RB_THREAD_WAIT_FOR
+static VALUE thread_spec_rb_thread_wait_for(VALUE self, VALUE s, VALUE ms) {
+ struct timeval tv;
+ tv.tv_sec = NUM2INT(s);
+ tv.tv_usec = NUM2INT(ms);
+ rb_thread_wait_for(tv);
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_THREAD_CREATE
+
+VALUE thread_spec_call_proc(VALUE arg_array) {
+ VALUE arg = rb_ary_pop(arg_array);
+ VALUE proc = rb_ary_pop(arg_array);
+ return rb_funcall(proc, rb_intern("call"), 1, arg);
+}
+
+static VALUE thread_spec_rb_thread_create(VALUE self, VALUE proc, VALUE arg) {
+ VALUE args = rb_ary_new();
+ rb_ary_push(args, proc);
+ rb_ary_push(args, arg);
+
+ return rb_thread_create(thread_spec_call_proc, (void*)args);
+}
+#endif
+
+
+void Init_thread_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiThreadSpecs", rb_cObject);
+
+#ifdef HAVE_RB_THREAD_ALONE
+ rb_define_method(cls, "rb_thread_alone", thread_spec_rb_thread_alone, 0);
+#endif
+
+#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
+ rb_define_method(cls, "rb_thread_call_without_gvl", thread_spec_rb_thread_call_without_gvl, 0);
+ rb_define_method(cls, "rb_thread_call_without_gvl_with_ubf_io", thread_spec_rb_thread_call_without_gvl_with_ubf_io, 0);
+#endif
+
+#ifdef HAVE_RB_THREAD_CURRENT
+ rb_define_method(cls, "rb_thread_current", thread_spec_rb_thread_current, 0);
+#endif
+
+#ifdef HAVE_RB_THREAD_LOCAL_AREF
+ rb_define_method(cls, "rb_thread_local_aref", thread_spec_rb_thread_local_aref, 2);
+#endif
+
+#ifdef HAVE_RB_THREAD_LOCAL_ASET
+ rb_define_method(cls, "rb_thread_local_aset", thread_spec_rb_thread_local_aset, 3);
+#endif
+
+#ifdef HAVE_RB_THREAD_WAKEUP
+ rb_define_method(cls, "rb_thread_wakeup", thread_spec_rb_thread_wakeup, 1);
+#endif
+
+#ifdef HAVE_RB_THREAD_WAIT_FOR
+ rb_define_method(cls, "rb_thread_wait_for", thread_spec_rb_thread_wait_for, 2);
+#endif
+
+#ifdef HAVE_RB_THREAD_CREATE
+ rb_define_method(cls, "rb_thread_create", thread_spec_rb_thread_create, 2);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/time_spec.c b/spec/rubyspec/optional/capi/ext/time_spec.c
new file mode 100644
index 0000000000..6b51120f1b
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/time_spec.c
@@ -0,0 +1,127 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_TIME_NEW
+static VALUE time_spec_rb_time_new(VALUE self, VALUE sec, VALUE usec) {
+ return rb_time_new(NUM2TIMET(sec), NUM2LONG(usec));
+}
+#endif
+
+#ifdef HAVE_RB_TIME_NANO_NEW
+static VALUE time_spec_rb_time_nano_new(VALUE self, VALUE sec, VALUE nsec) {
+ return rb_time_nano_new(NUM2TIMET(sec), NUM2LONG(nsec));
+}
+#endif
+
+#ifdef HAVE_RB_TIME_NUM_NEW
+static VALUE time_spec_rb_time_num_new(VALUE self, VALUE ts, VALUE offset) {
+ return rb_time_num_new(ts, offset);
+}
+#endif
+
+#ifdef HAVE_RB_TIME_INTERVAL
+static VALUE time_spec_rb_time_interval(VALUE self, VALUE ts) {
+ struct timeval interval = rb_time_interval(ts);
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, TIMET2NUM(interval.tv_sec));
+ rb_ary_push(ary, TIMET2NUM(interval.tv_usec));
+ return ary;
+}
+#endif
+
+#ifdef HAVE_RB_TIME_TIMEVAL
+static VALUE time_spec_rb_time_timeval(VALUE self, VALUE ts) {
+ struct timeval tv = rb_time_timeval(ts);
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, TIMET2NUM(tv.tv_sec));
+ rb_ary_push(ary, TIMET2NUM(tv.tv_usec));
+ return ary;
+}
+#endif
+
+#ifdef HAVE_RB_TIME_TIMESPEC
+static VALUE time_spec_rb_time_timespec(VALUE self, VALUE time) {
+ struct timespec ts = rb_time_timespec(time);
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, TIMET2NUM(ts.tv_sec));
+ rb_ary_push(ary, TIMET2NUM(ts.tv_nsec));
+ return ary;
+}
+#endif
+
+#ifdef HAVE_RB_TIME_TIMESPEC_NEW
+static VALUE time_spec_rb_time_timespec_new(VALUE self, VALUE sec, VALUE nsec, VALUE offset) {
+ struct timespec ts;
+ ts.tv_sec = NUM2TIMET(sec);
+ ts.tv_nsec = NUM2LONG(nsec);
+
+ return rb_time_timespec_new(&ts, NUM2INT(offset));
+}
+#endif
+
+#ifdef HAVE_RB_TIMESPEC_NOW
+static VALUE time_spec_rb_time_from_timspec_now(VALUE self, VALUE offset) {
+ struct timespec ts;
+ rb_timespec_now(&ts);
+
+ return rb_time_timespec_new(&ts, NUM2INT(offset));
+}
+#endif
+
+#ifdef HAVE_TIMET2NUM
+static VALUE time_spec_TIMET2NUM(VALUE self) {
+ time_t t = 10;
+ return TIMET2NUM(t);
+}
+#endif
+
+void Init_time_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiTimeSpecs", rb_cObject);
+
+#ifdef HAVE_RB_TIME_NEW
+ rb_define_method(cls, "rb_time_new", time_spec_rb_time_new, 2);
+#endif
+
+#ifdef HAVE_TIMET2NUM
+ rb_define_method(cls, "TIMET2NUM", time_spec_TIMET2NUM, 0);
+#endif
+
+#ifdef HAVE_RB_TIME_NANO_NEW
+ rb_define_method(cls, "rb_time_nano_new", time_spec_rb_time_nano_new, 2);
+#endif
+
+#ifdef HAVE_RB_TIME_NUM_NEW
+ rb_define_method(cls, "rb_time_num_new", time_spec_rb_time_num_new, 2);
+#endif
+
+#ifdef HAVE_RB_TIME_INTERVAL
+ rb_define_method(cls, "rb_time_interval", time_spec_rb_time_interval, 1);
+#endif
+
+#ifdef HAVE_RB_TIME_TIMEVAL
+ rb_define_method(cls, "rb_time_timeval", time_spec_rb_time_timeval, 1);
+#endif
+
+#ifdef HAVE_RB_TIME_TIMESPEC
+ rb_define_method(cls, "rb_time_timespec", time_spec_rb_time_timespec, 1);
+#endif
+
+#ifdef HAVE_RB_TIME_TIMESPEC_NEW
+ rb_define_method(cls, "rb_time_timespec_new", time_spec_rb_time_timespec_new, 3);
+#endif
+
+#ifdef HAVE_RB_TIMESPEC_NOW
+ rb_define_method(cls, "rb_time_from_timespec", time_spec_rb_time_from_timspec_now, 1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/truffleruby.h b/spec/rubyspec/optional/capi/ext/truffleruby.h
new file mode 100644
index 0000000000..99976a18a4
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/truffleruby.h
@@ -0,0 +1,6 @@
+#ifndef RUBYSPEC_CAPI_TRUFFLERUBY_H
+#undef RUBYSPEC_CAPI_TRUFFLERUBY_H
+
+// All features are available
+
+#endif
diff --git a/spec/rubyspec/optional/capi/ext/typed_data_spec.c b/spec/rubyspec/optional/capi/ext/typed_data_spec.c
new file mode 100644
index 0000000000..8436c527be
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/typed_data_spec.c
@@ -0,0 +1,177 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(HAVE_RTYPEDDATA) && defined(HAVE_TYPEDDATA_WRAP_STRUCT)
+struct sample_typed_wrapped_struct_parent {
+ int foo;
+};
+
+void sample_typed_wrapped_struct_parent_free(void* st) {
+ free(st);
+}
+
+void sample_typed_wrapped_struct_parent_mark(void* st) {
+}
+
+size_t sample_typed_wrapped_struct_parent_memsize(const void* st) {
+ return sizeof(struct sample_typed_wrapped_struct_parent);
+}
+
+static const rb_data_type_t sample_typed_wrapped_struct_parent_data_type = {
+ "sample_typed_wrapped_struct_parent",
+ {
+ sample_typed_wrapped_struct_parent_mark,
+ sample_typed_wrapped_struct_parent_free,
+ sample_typed_wrapped_struct_parent_memsize,
+ },
+};
+
+struct sample_typed_wrapped_struct {
+ int foo;
+};
+
+void sample_typed_wrapped_struct_free(void* st) {
+ free(st);
+}
+
+void sample_typed_wrapped_struct_mark(void* st) {
+}
+
+size_t sample_typed_wrapped_struct_memsize(const void* st) {
+ return sizeof(struct sample_typed_wrapped_struct);
+}
+
+static const rb_data_type_t sample_typed_wrapped_struct_data_type = {
+ "sample_typed_wrapped_struct",
+ {
+ sample_typed_wrapped_struct_mark,
+ sample_typed_wrapped_struct_free,
+ sample_typed_wrapped_struct_memsize,
+ },
+ &sample_typed_wrapped_struct_parent_data_type,
+};
+
+struct sample_typed_wrapped_struct_other {
+ int foo;
+};
+
+void sample_typed_wrapped_struct_other_free(void* st) {
+ free(st);
+}
+
+void sample_typed_wrapped_struct_other_mark(void* st) {
+}
+
+size_t sample_typed_wrapped_struct_other_memsize(const void* st) {
+ return sizeof(struct sample_typed_wrapped_struct_other);
+}
+
+static const rb_data_type_t sample_typed_wrapped_struct_other_data_type = {
+ "sample_typed_wrapped_struct_other",
+ {
+ sample_typed_wrapped_struct_other_mark,
+ sample_typed_wrapped_struct_other_free,
+ sample_typed_wrapped_struct_other_memsize,
+ },
+};
+
+
+VALUE sdaf_alloc_typed_func(VALUE klass) {
+ struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
+ bar->foo = 42;
+ return TypedData_Wrap_Struct(klass, &sample_typed_wrapped_struct_data_type, bar);
+}
+
+VALUE sdaf_typed_get_struct(VALUE self) {
+ struct sample_typed_wrapped_struct* bar;
+ TypedData_Get_Struct(self, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
+
+ return INT2FIX((*bar).foo);
+}
+
+VALUE sws_typed_wrap_struct(VALUE self, VALUE val) {
+ struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
+ bar->foo = FIX2INT(val);
+ return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar);
+}
+
+VALUE sws_typed_wrap_struct_null(VALUE self, VALUE val) {
+ struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
+ bar->foo = FIX2INT(val);
+ return TypedData_Wrap_Struct(0, &sample_typed_wrapped_struct_data_type, bar);
+}
+
+VALUE sws_typed_get_struct(VALUE self, VALUE obj) {
+ struct sample_typed_wrapped_struct* bar;
+ TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
+
+ return INT2FIX((*bar).foo);
+}
+
+VALUE sws_typed_get_struct_different_type(VALUE self, VALUE obj) {
+ struct sample_typed_wrapped_struct_other* bar;
+ TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_other, &sample_typed_wrapped_struct_other_data_type, bar);
+
+ return INT2FIX((*bar).foo);
+}
+
+VALUE sws_typed_get_struct_parent_type(VALUE self, VALUE obj) {
+ struct sample_typed_wrapped_struct_parent* bar;
+ TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_parent, &sample_typed_wrapped_struct_parent_data_type, bar);
+
+ return INT2FIX((*bar).foo);
+}
+
+VALUE sws_typed_get_struct_rdata(VALUE self, VALUE obj) {
+ struct sample_typed_wrapped_struct* bar;
+ bar = (struct sample_typed_wrapped_struct*) RTYPEDDATA(obj)->data;
+ return INT2FIX(bar->foo);
+}
+
+VALUE sws_typed_get_struct_data_ptr(VALUE self, VALUE obj) {
+ struct sample_typed_wrapped_struct* bar;
+ bar = (struct sample_typed_wrapped_struct*) DATA_PTR(obj);
+ return INT2FIX(bar->foo);
+}
+
+VALUE sws_typed_change_struct(VALUE self, VALUE obj, VALUE new_val) {
+ struct sample_typed_wrapped_struct *old_struct, *new_struct;
+ new_struct = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
+ new_struct->foo = FIX2INT(new_val);
+ old_struct = RTYPEDDATA(obj)->data;
+ free(old_struct);
+ RTYPEDDATA(obj)->data = new_struct;
+ return Qnil;
+}
+#endif
+
+void Init_typed_data_spec(void) {
+ VALUE cls;
+ cls = rb_define_class("CApiAllocTypedSpecs", rb_cObject);
+
+#if defined(HAVE_RTYPEDDATA) && defined(HAVE_TYPEDDATA_WRAP_STRUCT)
+ rb_define_alloc_func(cls, sdaf_alloc_typed_func);
+ rb_define_method(cls, "typed_wrapped_data", sdaf_typed_get_struct, 0);
+
+ cls = rb_define_class("CApiWrappedTypedStructSpecs", rb_cObject);
+ rb_define_method(cls, "typed_wrap_struct", sws_typed_wrap_struct, 1);
+ rb_define_method(cls, "typed_wrap_struct_null", sws_typed_wrap_struct_null, 1);
+ rb_define_method(cls, "typed_get_struct", sws_typed_get_struct, 1);
+ rb_define_method(cls, "typed_get_struct_other", sws_typed_get_struct_different_type, 1);
+ rb_define_method(cls, "typed_get_struct_parent", sws_typed_get_struct_parent_type, 1);
+ rb_define_method(cls, "typed_get_struct_rdata", sws_typed_get_struct_rdata, 1);
+ rb_define_method(cls, "typed_get_struct_data_ptr", sws_typed_get_struct_data_ptr, 1);
+ rb_define_method(cls, "typed_change_struct", sws_typed_change_struct, 2);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/spec/rubyspec/optional/capi/ext/util_spec.c b/spec/rubyspec/optional/capi/ext/util_spec.c
new file mode 100644
index 0000000000..50795b51af
--- /dev/null
+++ b/spec/rubyspec/optional/capi/ext/util_spec.c
@@ -0,0 +1,95 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_SCAN_ARGS
+VALUE util_spec_rb_scan_args(VALUE self, VALUE argv, VALUE fmt, VALUE expected, VALUE acc) {
+ int i, result, argc = (int)RARRAY_LEN(argv);
+ VALUE args[6], failed, a1, a2, a3, a4, a5, a6;
+
+ failed = rb_intern("failed");
+ a1 = a2 = a3 = a4 = a5 = a6 = failed;
+
+ for(i = 0; i < argc; i++) {
+ args[i] = rb_ary_entry(argv, i);
+ }
+
+ result = rb_scan_args(argc, args, RSTRING_PTR(fmt), &a1, &a2, &a3, &a4, &a5, &a6);
+
+ switch(NUM2INT(expected)) {
+ case 6:
+ rb_ary_unshift(acc, a6);
+ case 5:
+ rb_ary_unshift(acc, a5);
+ case 4:
+ rb_ary_unshift(acc, a4);
+ case 3:
+ rb_ary_unshift(acc, a3);
+ case 2:
+ rb_ary_unshift(acc, a2);
+ case 1:
+ rb_ary_unshift(acc, a1);
+ break;
+ default:
+ rb_raise(rb_eException, "unexpected number of arguments returned by rb_scan_args");
+ }
+
+ return INT2NUM(result);
+}
+#endif
+
+#ifdef HAVE_RB_LONG2INT
+static VALUE util_spec_rb_long2int(VALUE self, VALUE n) {
+ return INT2NUM(rb_long2int(NUM2LONG(n)));
+}
+#endif
+
+#ifdef HAVE_RB_ITER_BREAK
+static VALUE util_spec_rb_iter_break(VALUE self) {
+ rb_iter_break();
+ return Qnil;
+}
+#endif
+
+#ifdef HAVE_RB_SOURCEFILE
+static VALUE util_spec_rb_sourcefile(VALUE self) {
+ return rb_str_new2(rb_sourcefile());
+}
+#endif
+
+#ifdef HAVE_RB_SOURCELINE
+static VALUE util_spec_rb_sourceline(VALUE self) {
+ return INT2NUM(rb_sourceline());
+}
+#endif
+
+void Init_util_spec(void) {
+ VALUE cls = rb_define_class("CApiUtilSpecs", rb_cObject);
+
+#ifdef HAVE_RB_SCAN_ARGS
+ rb_define_method(cls, "rb_scan_args", util_spec_rb_scan_args, 4);
+#endif
+
+#ifdef HAVE_RB_LONG2INT
+ rb_define_method(cls, "rb_long2int", util_spec_rb_long2int, 1);
+#endif
+
+#ifdef HAVE_RB_ITER_BREAK
+ rb_define_method(cls, "rb_iter_break", util_spec_rb_iter_break, 0);
+#endif
+
+#ifdef HAVE_RB_SOURCEFILE
+ rb_define_method(cls, "rb_sourcefile", util_spec_rb_sourcefile, 0);
+#endif
+
+#ifdef HAVE_RB_SOURCELINE
+ rb_define_method(cls, "rb_sourceline", util_spec_rb_sourceline, 0);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif